acquire-method.cc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: acquire-method.cc,v 1.1 1998/10/30 07:53:35 jgg Exp $
  4. /* ######################################################################
  5. Acquire Method
  6. ##################################################################### */
  7. /*}}}*/
  8. // Include Files /*{{{*/
  9. #ifdef __GNUG__
  10. #pragma implementation "apt-pkg/acquire-method.h"
  11. #endif
  12. #include <apt-pkg/acquire-method.h>
  13. #include <apt-pkg/error.h>
  14. #include <apt-pkg/configuration.h>
  15. #include <strutl.h>
  16. #include <apt-pkg/fileutl.h>
  17. #include <stdio.h>
  18. /*}}}*/
  19. // AcqMethod::pkgAcqMethod - Constructor /*{{{*/
  20. // ---------------------------------------------------------------------
  21. /* This constructs the initialization text */
  22. pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
  23. {
  24. char S[300] = "";
  25. char *End = S;
  26. strcat(End,"100 Capabilities\n");
  27. sprintf(End+strlen(End),"Version: %s\n",Ver);
  28. if ((Flags & SingleInstance) == SingleInstance)
  29. strcat(End,"Single-Instance: true\n");
  30. if ((Flags & PreScan) == PreScan)
  31. strcat(End,"Pre-Scan: true\n");
  32. if ((Flags & Pipeline) == Pipeline)
  33. strcat(End,"Pipeline: true\n");
  34. if ((Flags & SendConfig) == SendConfig)
  35. strcat(End,"Send-Config: true\n");
  36. strcat(End,"\n");
  37. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  38. exit(100);
  39. }
  40. /*}}}*/
  41. // AcqMethod::Fail - A fetch has failed /*{{{*/
  42. // ---------------------------------------------------------------------
  43. /* */
  44. void pkgAcqMethod::Fail()
  45. {
  46. string Err = "Undetermined Error";
  47. if (_error->empty() == false)
  48. _error->PopMessage(Err);
  49. _error->Discard();
  50. Fail(Err);
  51. }
  52. /*}}}*/
  53. // AcqMethod::Fail - A fetch has failed /*{{{*/
  54. // ---------------------------------------------------------------------
  55. /* */
  56. void pkgAcqMethod::Fail(string Err)
  57. {
  58. char S[1024];
  59. snprintf(S,sizeof(S),"400 URI Failure\nURI: %s\n"
  60. "Message %s\n\n",CurrentURI.c_str(),Err.c_str());
  61. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  62. exit(100);
  63. }
  64. /*}}}*/
  65. // AcqMethod::URIStart - Indicate a download is starting /*{{{*/
  66. // ---------------------------------------------------------------------
  67. /* */
  68. void pkgAcqMethod::URIStart(FetchResult &Res,unsigned long Resume = 0)
  69. {
  70. char S[1024] = "";
  71. char *End = S;
  72. End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",CurrentURI.c_str());
  73. if (Res.Size != 0)
  74. End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
  75. if (Res.LastModified != 0)
  76. End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
  77. TimeRFC1123(Res.LastModified).c_str());
  78. if (Resume != 0)
  79. End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
  80. Resume);
  81. strcat(End,"\n");
  82. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  83. exit(100);
  84. }
  85. /*}}}*/
  86. // AcqMethod::URIDone - A URI is finished /*{{{*/
  87. // ---------------------------------------------------------------------
  88. /* */
  89. void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
  90. {
  91. char S[1024] = "";
  92. char *End = S;
  93. End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",CurrentURI.c_str());
  94. if (Res.Filename.empty() == false)
  95. End += snprintf(End,sizeof(S) - (End - S),"Filename: %s\n",Res.Filename.c_str());
  96. if (Res.Size != 0)
  97. End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
  98. if (Res.LastModified != 0)
  99. End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
  100. TimeRFC1123(Res.LastModified).c_str());
  101. if (Res.MD5Sum.empty() == false)
  102. End += snprintf(End,sizeof(S) - (End - S),"MD5Sum: %s\n",Res.MD5Sum.c_str());
  103. if (Res.IMSHit == true)
  104. strcat(End,"IMS-Hit: true\n");
  105. End = S + strlen(S);
  106. if (Alt != 0)
  107. {
  108. if (Alt->Filename.empty() == false)
  109. End += snprintf(End,sizeof(S) - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
  110. if (Alt->Size != 0)
  111. End += snprintf(End,sizeof(S) - (End - S),"Alt-Size: %u\n",Alt->Size);
  112. if (Alt->LastModified != 0)
  113. End += snprintf(End,sizeof(S) - (End - S),"Alt-Last-Modified: %s\n",
  114. TimeRFC1123(Alt->LastModified).c_str());
  115. if (Alt->MD5Sum.empty() == false)
  116. End += snprintf(End,sizeof(S) - (End - S),"Alt-MD5Sum: %s\n",
  117. Alt->MD5Sum.c_str());
  118. if (Alt->IMSHit == true)
  119. strcat(End,"Alt-IMS-Hit: true\n");
  120. }
  121. strcat(End,"\n");
  122. if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
  123. exit(100);
  124. }
  125. /*}}}*/
  126. // AcqMethod::Configuration - Handle the configuration message /*{{{*/
  127. // ---------------------------------------------------------------------
  128. /* This parses each configuration entry and puts it into the _config
  129. Configuration class. */
  130. bool pkgAcqMethod::Configuration(string Message)
  131. {
  132. ::Configuration &Cnf = *_config;
  133. const char *I = Message.begin();
  134. unsigned int Length = strlen("Config-Item");
  135. for (; I + Length < Message.end(); I++)
  136. {
  137. // Not a config item
  138. if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
  139. continue;
  140. I += Length + 1;
  141. for (; I < Message.end() && *I == ' '; I++);
  142. const char *Equals = I;
  143. for (; Equals < Message.end() && *Equals != '='; Equals++);
  144. const char *End = Equals;
  145. for (; End < Message.end() && *End != '\n'; End++);
  146. if (End == Equals)
  147. return false;
  148. Cnf.Set(string(I,Equals-I),string(Equals+1,End-Equals-1));
  149. I = End;
  150. }
  151. return true;
  152. }
  153. /*}}}*/
  154. // AcqMethod::Run - Run the message engine /*{{{*/
  155. // ---------------------------------------------------------------------
  156. /* */
  157. int pkgAcqMethod::Run()
  158. {
  159. SetNonBlock(STDIN_FILENO,true);
  160. while (1)
  161. {
  162. if (Messages.empty() == true)
  163. if (WaitFd(STDIN_FILENO) == false)
  164. return 0;
  165. if (ReadMessages(STDIN_FILENO,Messages) == false)
  166. return 0;
  167. string Message = Messages.front();
  168. Messages.erase(Messages.begin());
  169. // Fetch the message number
  170. char *End;
  171. int Number = strtol(Message.c_str(),&End,10);
  172. if (End == Message.c_str())
  173. {
  174. cerr << "Malformed message!" << endl;
  175. return 100;
  176. }
  177. switch (Number)
  178. {
  179. case 601:
  180. if (Configuration(Message) == false)
  181. return 100;
  182. break;
  183. case 600:
  184. {
  185. CurrentURI = LookupTag(Message,"URI");
  186. DestFile = LookupTag(Message,"FileName");
  187. StrToTime(LookupTag(Message,"Last-Modified"),LastModified);
  188. if (Fetch(Message,CurrentURI) == false)
  189. Fail();
  190. break;
  191. }
  192. }
  193. }
  194. return 0;
  195. }
  196. /*}}}*/
  197. // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
  198. // ---------------------------------------------------------------------
  199. /* */
  200. pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
  201. IMSHit(false), Size(0)
  202. {
  203. }
  204. /*}}}*/