IdRFCReply.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10311: IdRFCReply.pas
  11. {
  12. { Rev 1.3 8/8/04 12:26:16 AM RLebeau
  13. { Bug fix for ParseResponse() to better support RFC 959
  14. }
  15. {
  16. { Rev 1.2 11/05/2003 23:21:56 CCostelloe
  17. { IMAP-specific code moved from here to TIdIMAP4.pas
  18. }
  19. {
  20. { Rev 1.1 3/23/2003 05:29:34 PM JPMugaas
  21. { Updated TIdRFCReply so it can display things in the TCollection editor
  22. { better. This is a backport from Indy 10.
  23. }
  24. {
  25. { Rev 1.0 2002.11.12 10:50:40 PM czhower
  26. }
  27. unit IdRFCReply;
  28. interface
  29. uses
  30. Classes;
  31. type
  32. TIdRFCReply = class(TCollectionItem)
  33. protected
  34. FNumericCode: integer;
  35. FText: TStrings;
  36. FTextCode: string;
  37. //
  38. procedure AssignTo(ADest: TPersistent); override;
  39. function GetDisplayName: string; override;
  40. procedure SetNumericCode(const AValue: Integer);
  41. procedure SetText(const AValue: TStrings);
  42. procedure SetTextCode(const AValue: string);
  43. public
  44. procedure Clear;
  45. constructor Create(Collection: TCollection); override;
  46. destructor Destroy; override;
  47. function GenerateReply: string;
  48. procedure ParseResponse(const AStrings: TStrings); overload;
  49. function ReplyExists: Boolean;
  50. procedure SetReply(const ANumericCode: Integer; const AText: string);
  51. published
  52. property NumericCode: Integer read FNumericCode write SetNumericCode;
  53. property Text: TStrings read FText write SetText;
  54. property TextCode: string read FTextCode write SetTextCode;
  55. end;
  56. TIdRFCReplies = class(TOwnedCollection)
  57. protected
  58. function GetItem(Index: Integer): TIdRFCReply;
  59. procedure SetItem(Index: Integer; const Value: TIdRFCReply);
  60. public
  61. function Add: TIdRFCReply; overload;
  62. function Add(const ANumericCode: Integer; const AText: string): TIdRFCReply; overload;
  63. constructor Create(AOwner: TPersistent); reintroduce;
  64. function FindByNumber(const ANo: Integer): TIdRFCReply; virtual;
  65. function UpdateReply(const ANumericCode: Integer; const AText: string): TIdRFCReply;
  66. procedure UpdateText(AReply: TIdRFCReply);
  67. //
  68. property Items[Index: Integer]: TIdRFCReply read GetItem write SetItem; default;
  69. end;
  70. implementation
  71. uses
  72. IdGlobal,
  73. SysUtils;
  74. { TIdRFCReply }
  75. procedure TIdRFCReply.AssignTo(ADest: TPersistent);
  76. begin
  77. if ADest is TIdRFCReply then begin
  78. with TIdRFCReply(ADest) do begin
  79. Clear;
  80. // Bypass as this and TextCode mutually exclude each other
  81. FNumericCode := Self.NumericCode;
  82. Text.Assign(Self.Text);
  83. // Bypass as this and NumericCode mutually exclude each other
  84. FTextCode := Self.TextCode;
  85. end;
  86. end else begin
  87. inherited;
  88. end;
  89. end;
  90. procedure TIdRFCReply.Clear;
  91. begin
  92. FNumericCode := 0;
  93. FText.Clear;
  94. FTextCode := '';
  95. end;
  96. constructor TIdRFCReply.Create(Collection: TCollection);
  97. begin
  98. inherited;
  99. FText := TStringList.Create;
  100. Clear;
  101. end;
  102. destructor TIdRFCReply.Destroy;
  103. begin
  104. FreeAndNil(FText);
  105. inherited;
  106. end;
  107. function TIdRFCReply.GenerateReply: string;
  108. var
  109. i: Integer;
  110. begin
  111. // TODO: Account for TextCode <> '' when integrated into POP3
  112. Result := '';
  113. if NumericCode > 0 then begin
  114. Result := '';
  115. if FText.Count > 0 then begin
  116. for i := 0 to FText.Count - 1 do begin
  117. if i < FText.Count - 1 then begin
  118. Result := Result + IntToStr(NumericCode) + '-' + FText[i] + EOL;
  119. end else begin
  120. Result := Result + IntToStr(NumericCode) + ' ' + FText[i] + EOL;
  121. end;
  122. end;
  123. end else begin
  124. Result := Result + IntToStr(NumericCode) + ' ' + EOL;
  125. end;
  126. end else if FText.Count > 0 then begin
  127. Result := FText.Text;
  128. end;
  129. end;
  130. procedure TIdRFCReply.ParseResponse(const AStrings: TStrings);
  131. var
  132. i: Integer;
  133. LCode, LTemp: string;
  134. begin
  135. Clear;
  136. if AStrings.Count > 0 then begin
  137. // Get 4 chars - for POP3
  138. LCode := Trim(Copy(AStrings[0], 1, 4));
  139. if Length(LCode) = 4 then begin
  140. if LCode[4] = '-' then begin
  141. SetLength(LCode, 3);
  142. end;
  143. end;
  144. TextCode := LCode;
  145. Text.Add(Copy(AStrings[0], 5, MaxInt));
  146. if AStrings.Count > 1 then begin
  147. for i := 1 to AStrings.Count - 1 do begin
  148. // RLebeau - RFC 959 for the FTP protocol does not require the
  149. // response code to be prepended to every line like with other
  150. // protocols. Most FTP servers do this, but not all of them do,
  151. // so check here for that possibility ...
  152. if AnsiSameText(Copy(AStrings[i], 1, 3), LCode) then begin
  153. LTemp := Copy(AStrings[i], 5, MaxInt);
  154. end else begin
  155. LTemp := TrimLeft(AStrings[i]);
  156. end;
  157. Text.Add(LTemp);
  158. end;
  159. end;
  160. end;
  161. end;
  162. function TIdRFCReply.ReplyExists: Boolean;
  163. begin
  164. Result := (NumericCode > 0) or (FText.Count > 0);
  165. end;
  166. procedure TIdRFCReply.SetNumericCode(const AValue: Integer);
  167. begin
  168. FNumericCode := AValue;
  169. // Dont reset the text if 0 otherwise there are streaming and assign problems
  170. if AValue > 0 then begin
  171. FTextCode := IntToStr(AValue);
  172. end;
  173. end;
  174. procedure TIdRFCReply.SetReply(const ANumericCode: Integer; const AText: string);
  175. begin
  176. FNumericCode := ANumericCode;
  177. FText.Text := AText;
  178. end;
  179. procedure TIdRFCReply.SetText(const AValue: TStrings);
  180. begin
  181. FText.Assign(AValue);
  182. end;
  183. procedure TIdRFCReply.SetTextCode(const AValue: string);
  184. begin
  185. FTextCode := AValue;
  186. // Dont reset the numeric if '' otherwise there are streaming and assign problems
  187. if Length(AValue) > 0 then begin
  188. // StrToIntDef is necessary for POP3
  189. FNumericCode := StrToIntDef(AValue, 0);
  190. end;
  191. end;
  192. function TIdRFCReply.GetDisplayName: string;
  193. begin
  194. if Text.Count > 0 then begin
  195. Result := TextCode + ' ' + Text[0];
  196. end else begin
  197. Result := TextCode;
  198. end;
  199. end;
  200. { TIdRFCReplies }
  201. function TIdRFCReplies.Add: TIdRFCReply;
  202. begin
  203. Result := TIdRFCReply(inherited Add);
  204. end;
  205. function TIdRFCReplies.Add(const ANumericCode: Integer; const AText: string): TIdRFCReply;
  206. begin
  207. Result := nil;
  208. if FindByNumber(ANumericCode) = nil then begin
  209. Result := Add;
  210. Result.SetReply(ANumericCode, AText);
  211. end;
  212. end;
  213. constructor TIdRFCReplies.Create(AOwner: TPersistent);
  214. begin
  215. inherited Create(AOwner, TIdRFCReply);
  216. end;
  217. function TIdRFCReplies.FindByNumber(const ANo: Integer): TIdRFCReply;
  218. var
  219. i: Integer;
  220. begin
  221. Result := nil;
  222. for i := 0 to Count - 1 do begin
  223. if Items[i].FNumericCode = ANo then begin
  224. Result := Items[i];
  225. Break;
  226. end;
  227. end;
  228. end;
  229. function TIdRFCReplies.GetItem(Index: Integer): TIdRFCReply;
  230. begin
  231. Result := TIdRFCReply(inherited Items[Index]);
  232. end;
  233. procedure TIdRFCReplies.SetItem(Index: Integer; const Value: TIdRFCReply);
  234. begin
  235. inherited SetItem(Index, Value);
  236. end;
  237. function TIdRFCReplies.UpdateReply(const ANumericCode: Integer; const AText: string): TIdRFCReply;
  238. begin
  239. Result := FindByNumber(ANumericCode);
  240. if Result = nil then begin
  241. Result := Add;
  242. end;
  243. Result.SetReply(ANumericCode, AText);
  244. end;
  245. procedure TIdRFCReplies.UpdateText(AReply: TIdRFCReply);
  246. var
  247. LReply: TIdRFCReply;
  248. begin
  249. // Reply text is blank, get it from the ReplyTexts
  250. if AReply.Text.Count = 0 then begin
  251. LReply := FindByNumber(AReply.NumericCode);
  252. if LReply <> nil then begin
  253. AReply.Text.Assign(LReply.Text);
  254. end;
  255. end;
  256. end;
  257. end.