IdVCard.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  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: 10417: IdVCard.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:59:38 PM czhower
  13. }
  14. unit IdVCard;
  15. {*******************************************************}
  16. { }
  17. { Indy VCardObject TIdCard }
  18. { }
  19. { Copyright (C) 2000 Winshoes Working Group }
  20. { Original author J. Peter Mugaas }
  21. { 2000-May-06 }
  22. { Based on RFC 2425, 2426 }
  23. { }
  24. {*******************************************************}
  25. {
  26. 2002-Jan-20 DOn Siders
  27. - Corrected spelling errors in Categories properties, members, methods
  28. 2000-07-24 Peter Mee
  29. - Added preliminary embedded vCard checking
  30. - Added QP Check & Decode of individual properties
  31. }
  32. interface
  33. uses
  34. Classes,
  35. IdBaseComponent, IdGlobal;
  36. { TODO:
  37. Agent property does not work and the current parsing stops whenever it
  38. sees END:VCard meaning that the VCard will be truncated if AGENT is
  39. used to embed a VCard.
  40. I omitted a property for spelling out a sound. Appearently VCard 2.1
  41. permitted a charactor representation of sound in addition to an embedded
  42. sound, and a URL.
  43. I am not sure how well the KEY property works. That is used for
  44. embedding some encryption keys into a VCard such as PGP public-key or
  45. something from Versign.
  46. VCard does not have any Quoted Printable decoding or Base64 encoding
  47. and decoding. Some routines may have to be changed to accomodate
  48. this although I don't have the where-with-all.
  49. VCards can not be saved. }
  50. type
  51. {This contains the object for Sound, Logo, Photo, Key, and Agent property}
  52. TIdVCardEmbeddedObject = class (TPersistent)
  53. protected
  54. FObjectType : String;
  55. FObjectURL : String;
  56. FBase64Encoded : Boolean;
  57. FEmbeddedData : TStrings;
  58. {Embeded data property set method}
  59. procedure SetEmbeddedData(const Value: TStrings);
  60. public
  61. Constructor Create;
  62. Destructor Destroy; override;
  63. published
  64. {this indicates the type of media such as the file type or key type}
  65. property ObjectType : String read FObjectType write FObjectType;
  66. {pointer to the URL where the object is located if it is NOT in this card
  67. itself}
  68. property ObjectURL : String read FObjectURL write FObjectURL;
  69. {The object }
  70. property Base64Encoded : Boolean read FBase64Encoded write FBase64Encoded;
  71. {The data for the object if it is in the VCard. This is usually in an
  72. encoded format such as BASE64 although some keys may not require encoding}
  73. property EmbeddedData : TStrings read FEmbeddedData write SetEmbeddedData;
  74. end;
  75. {VCard business information}
  76. TIdVCardBusinessInfo = class ( TPersistent )
  77. protected
  78. FTitle : String;
  79. FRole : String;
  80. FOrganization : String;
  81. FDivisions : TStrings;
  82. procedure SetDivisions(Value : TStrings);
  83. public
  84. constructor Create;
  85. destructor Destroy; override;
  86. published
  87. {The organization name such as XYZ Corp. }
  88. property Organization : String read FOrganization write FOrganization;
  89. { The divisions in the orginization the person is in - e.g.
  90. West Virginia Office, Computing Service}
  91. property Divisions: TStrings read FDivisions write SetDivisions;
  92. {The person's formal title in the business such
  93. "Director of Computing Services"}
  94. property Title : String read FTitle write FTitle;
  95. {The person's role in an organization such as "system administrator" }
  96. property Role : String read FRole write FRole;
  97. end;
  98. {Geographical information such as Latitude/Longitude and Time Zone}
  99. TIdVCardGeog = class ( TPersistent )
  100. protected
  101. FLatitude : Real;
  102. FLongitude : Real;
  103. FTimeZoneStr : String;
  104. published
  105. {Geographical latitude the person is in}
  106. property Latitude : Real read FLatitude write FLatitude;
  107. {Geographical longitude the person is in}
  108. property Longitude : Real read FLongitude write FLongitude;
  109. {The time zone the person is in}
  110. property TimeZoneStr : String read FTimeZoneStr write FTimeZoneStr;
  111. end;
  112. TIdPhoneAttributes = set of
  113. ( tpaHome, tpaVoiceMessaging, tpaWork, tpaPreferred, tpaVoice, tpaFax,
  114. tpaCellular, tpaVideo, tpaBBS, tpaModem, tpaCar, tpaISDN, tpaPCS, tpaPager);
  115. { This encapsolates a telephone number }
  116. TIdCardPhoneNumber = class ( TCollectionItem )
  117. protected
  118. FPhoneAttributes: TIdPhoneAttributes;
  119. FNumber : String;
  120. public
  121. procedure Assign(Source: TPersistent); override;
  122. published
  123. {This is a descriptor for the phone number }
  124. property PhoneAttributes: TIdPhoneAttributes
  125. read FPhoneAttributes write FPhoneAttributes;
  126. { the telephone number itself}
  127. property Number : String read FNumber write FNumber;
  128. end;
  129. {Since a person can have more than one address, we put them into this
  130. collection}
  131. TIdVCardTelephones = class ( TOwnedCollection )
  132. protected
  133. function GetItem ( Index: Integer ) : TIdCardPhoneNumber;
  134. procedure SetItem ( Index: Integer; const Value: TIdCardPhoneNumber );
  135. public
  136. constructor Create ( AOwner : TPersistent ); reintroduce;
  137. function Add: TIdCardPhoneNumber;
  138. property Items [ Index: Integer ] : TIdCardPhoneNumber read GetItem write
  139. SetItem; default;
  140. end;
  141. {This encapsulates a person's address} {Do not Localize}
  142. TIdCardAddressAttributes = set of ( tatHome, tatDomestic, tatInternational, tatPostal,
  143. tatParcel, tatWork, tatPreferred );
  144. TIdCardAddressItem = class ( TCollectionItem )
  145. protected
  146. FAddressAttributes : TIdCardAddressAttributes;
  147. FPOBox : String;
  148. FExtendedAddress : String;
  149. FStreetAddress : String;
  150. FLocality : String;
  151. FRegion : String;
  152. FPostalCode : String;
  153. FNation : String;
  154. public
  155. procedure Assign(Source: TPersistent); override;
  156. published
  157. { attributes for this address such as Home or Work, postal, parcel, etc.}
  158. property AddressAttributes : TIdCardAddressAttributes read
  159. FAddressAttributes write FAddressAttributes;
  160. { This is the P. O. Box for an address}
  161. property POBox : String read FPOBox write FPOBox;
  162. { This could be something such as an Office identifier for a building or
  163. an appartment number }
  164. property ExtendedAddress : String read FExtendedAddress write FExtendedAddress;
  165. {This is the streat address such as "101 Sample Avenue" }
  166. property StreetAddress : String read FStreetAddress write FStreetAddress;
  167. { This is a city or town (e.g. Chicago, New York City, Montreol }
  168. property Locality : String read FLocality write FLocality;
  169. { This is the political subdivision of a nation such as a Providence in Canda - Quebec,
  170. a State in US such as "West Virginia", or a county in England such as "Kent"}
  171. property Region : String read FRegion write FRegion;
  172. { This is the postal code for the locality such as a ZIP Code in the US }
  173. property PostalCode : String read FPostalCode write FPostalCode;
  174. { This is the nation such as Canada, U.S.A., Mexico, Russia, etc }
  175. property Nation : String read FNation write FNation;
  176. end;
  177. {Since a person can have more than one address, we put them into this collection}
  178. TIdVCardAddresses = class ( TOwnedCollection )
  179. protected
  180. function GetItem ( Index: Integer ) : TIdCardAddressItem;
  181. procedure SetItem ( Index: Integer; const Value: TIdCardAddressItem );
  182. public
  183. constructor Create ( AOwner : TPersistent ); reintroduce;
  184. function Add: TIdCardAddressItem;
  185. property Items [ Index: Integer ] : TIdCardAddressItem read GetItem write
  186. SetItem; default;
  187. end;
  188. {This type holds a mailing label }
  189. TIdVCardMailingLabelItem = class ( TCollectionItem )
  190. private
  191. FAddressAttributes : TIdCardAddressAttributes;
  192. FMailingLabel : TStrings;
  193. procedure SetMailingLabel(Value : TStrings);
  194. public
  195. constructor Create(Collection: TCollection); override;
  196. destructor Destroy; override;
  197. procedure Assign(Source: TPersistent); override;
  198. published
  199. { attributes for this mailing label such as Home or Work, postal, parcel,
  200. etc.}
  201. property AddressAttributes : TIdCardAddressAttributes read
  202. FAddressAttributes write FAddressAttributes;
  203. { The mailing label itself}
  204. property MailingLabel : TStrings read FMailingLabel write SetMailingLabel;
  205. end;
  206. {This type holds the }
  207. TIdVCardMailingLabels = class ( TOwnedCollection )
  208. protected
  209. function GetItem ( Index: Integer ) : TIdVCardMailingLabelItem;
  210. procedure SetItem ( Index: Integer; const Value: TIdVCardMailingLabelItem );
  211. public
  212. constructor Create ( AOwner : TPersistent ); reintroduce;
  213. function Add : TIdVCardMailingLabelItem;
  214. property Items [ Index: Integer ] : TIdVCardMailingLabelItem read GetItem write SetItem; default;
  215. end;
  216. { This type is used to indicate the type E-Mail indicated in the VCard
  217. which can be of several types }
  218. TIdVCardEMailType = ( ematAOL, {America On-Line}
  219. ematAppleLink, {AppleLink}
  220. ematATT, { AT&T Mail }
  221. ematCIS, { CompuServe Information Service }
  222. emateWorld, { eWorld }
  223. ematInternet, {Internet SMTP (default)}
  224. ematIBMMail, { IBM Mail }
  225. ematMCIMail, { Indicates MCI Mail }
  226. ematPowerShare, { PowerShare }
  227. ematProdigy, { Prodigy information service }
  228. ematTelex, { Telex number }
  229. ematX400 ); { X.400 service }
  230. {This object encapsolates an E-Mail address in a TCollection}
  231. TIdVCardEMailItem = class (TCollectionItem)
  232. protected
  233. FEMailType : TIdVCardEMailType;
  234. FPreferred : Boolean;
  235. FAddress : String;
  236. public
  237. constructor Create(Collection: TCollection); override;
  238. { This is the type of E-Mail address which defaults to Internet }
  239. procedure Assign(Source: TPersistent); override;
  240. published
  241. property EMailType : TIdVCardEMailType read FEMailType write FEMailType;
  242. { Is this the person's prefered E-Mail address? } {Do not Localize}
  243. property Preferred : Boolean read FPreferred write FPreferred;
  244. { The user's E-Mail address itself } {Do not Localize}
  245. property Address : String read FAddress write FAddress;
  246. end;
  247. TIdVCardEMailAddresses = class ( TOwnedCollection )
  248. protected
  249. function GetItem ( Index: Integer ) : TIdVCardEMailItem;
  250. procedure SetItem ( Index: Integer; const Value: TIdVCardEMailItem );
  251. public
  252. constructor Create ( AOwner : TPersistent ); reintroduce;
  253. function Add: TIdVCardEMailItem;
  254. property Items [ Index: Integer ] : TIdVCardEMailItem read GetItem write SetItem; default;
  255. end;
  256. TIdVCardName = class (TPersistent)
  257. protected
  258. FFirstName : String;
  259. FSurName : String;
  260. FOtherNames : TStrings;
  261. FPrefix : String;
  262. FSuffix : String;
  263. FFormattedName : String;
  264. FSortName : String;
  265. FNickNames : TStrings;
  266. procedure SetOtherNames(Value : TStrings);
  267. procedure SetNickNames(Value : TStrings);
  268. public
  269. Constructor Create;
  270. destructor Destroy; override;
  271. published
  272. {This is the person's first name, in the case of "J. Peter Mugaas",
  273. this would be "J."}
  274. property FirstName : String read FFirstName write FFirstName;
  275. {This is the person's last name, in the case of "J. Peter Mugaas",
  276. this would be "Mugaas"}
  277. property SurName : String read FSurName write FSurName;
  278. {This is a place for a middle name and some other names such as a woman's
  279. maiden name. In the case of "J. Peter Mugaas", this would be "Peter".}
  280. property OtherNames : TStrings read FOtherNames write SetOtherNames;
  281. {This is a properly formatted name which was listed in the VCard}
  282. property FormattedName : String read FFormattedName write FFormattedName;
  283. {This is a prefix added to a name such as
  284. "Mr.", "Dr.", "Hon.", "Prof.", "Reverend", etc.}
  285. property Prefix : String read FPrefix write FPrefix;
  286. {This is a suffix added to a name such as
  287. "Ph.D.", "M.D.", "Esq.", "Jr.", "Sr.", "III", etc.}
  288. property Suffix : String read FSuffix write FSuffix;
  289. {The string used for sorting a name. It may not always be the person's last
  290. name}
  291. property SortName : String read FSortName write FSortName;
  292. { Nick names which a person may have such as "Bill" or "Billy" for Wiliam.}
  293. property NickNames : TStrings read FNickNames write SetNickNames;
  294. end;
  295. TIdVCard = class ( TIdBaseComponent )
  296. private
  297. protected
  298. FComments : TStrings;
  299. FCategories : TStrings;
  300. FBusinessInfo : TIdVCardBusinessInfo;
  301. FGeography : TIdVCardGeog;
  302. FFullName : TIdVCardName;
  303. FRawForm : TStrings;
  304. FURLs : TStrings;
  305. FEMailProgram : String;
  306. FEMailAddresses : TIdVCardEMailAddresses;
  307. FAddresses : TIdVCardAddresses;
  308. FMailingLabels : TIdVCardMailingLabels;
  309. FTelephones : TIdVCardTelephones;
  310. FVCardVersion : Real;
  311. FProductID : String;
  312. FUniqueID : String;
  313. FClassification : String;
  314. FLastRevised : TDateTime;
  315. FBirthDay : TDateTime;
  316. FPhoto : TIdVCardEmbeddedObject;
  317. FLogo : TIdVCardEmbeddedObject;
  318. FSound : TIdVCardEmbeddedObject;
  319. FKey : TIdVCardEmbeddedObject;
  320. procedure SetComments(Value : TStrings);
  321. procedure SetCategories(Value : TStrings);
  322. procedure SetURLs(Value : TStrings);
  323. {This processes some types of variables after reading the string}
  324. procedure SetVariablesAfterRead;
  325. public
  326. constructor Create(AOwner: TComponent ); override;
  327. destructor Destroy; override;
  328. { This reads a VCard from a TStrings object }
  329. procedure ReadFromTStrings ( s : TStrings );
  330. { This is the raw form of the VCard }
  331. property RawForm : TStrings read FRawForm;
  332. published
  333. { This is the VCard specification version used }
  334. property VCardVersion : Real read FVCardVersion;
  335. { URL's associated with the VCard such as the person's or organication's
  336. webpage. There can be more than one.}
  337. property URLs : TStrings read FURLs write SetURLs;
  338. { This is the product ID for the program which created this VCard}
  339. property ProductID : String read FProductID write FProductID;
  340. { This is a unique indentifier for the VCard }
  341. property UniqueID : String read FUniqueID write FUniqueID;
  342. { Intent of the VCard owner for general access to information described by the vCard
  343. VCard.}
  344. property Classification : String read FClassification write FClassification;
  345. { This is the person's birthday and possibly, time of birth} {Do not Localize}
  346. property BirthDay : TDateTime read FBirthDay write FBirthDay;
  347. { This is the person's name } {Do not Localize}
  348. property FullName : TIdVCardName read FFullName write FFullName;
  349. { This is the E-Mail program used by the card's owner} {Do not Localize}
  350. property EMailProgram : String read FEMailProgram write FEMailProgram;
  351. { This is a list of the person's E-Mail address } {Do not Localize}
  352. property EMailAddresses : TIdVCardEMailAddresses read FEMailAddresses;
  353. { This is a list of telephone numbers }
  354. property Telephones : TIdVCardTelephones read FTelephones;
  355. { This is busines related information on a VCard}
  356. property BusinessInfo : TIdVCardBusinessInfo read FBusinessInfo;
  357. { This is a list of Categories used for classification }
  358. property Categories : TStrings read FCategories write SetCategories;
  359. { This is a list of addresses }
  360. property Addresses : TIdVCardAddresses read FAddresses;
  361. { This is a list of mailing labels }
  362. property MailingLabels : TIdVCardMailingLabels read FMailingLabels;
  363. { This is a miscellaneous comments, additional information, or whatever the
  364. VCard wishes to say }
  365. property Comments : TStrings read FComments write SetComments;
  366. { The owner's photograph} {Do not Localize}
  367. property Photo : TIdVCardEmbeddedObject read FPhoto;
  368. { Organization's logo} {Do not Localize}
  369. property Logo : TIdVCardEmbeddedObject read FLogo;
  370. { A sound associated with the VCard such as how to pronounce a person's name
  371. or something cute }
  372. property Sound : TIdVCardEmbeddedObject read FSound;
  373. { This is for an encryption key such as S/MIME, VeriSign, or PGP }
  374. property Key : TIdVCardEmbeddedObject read FKey;
  375. end;
  376. implementation
  377. uses
  378. IdCoderQuotedPrintable,
  379. SysUtils;
  380. const VCardProperties : array [0..27] of string = (
  381. 'FN', 'N', 'NICKNAME', 'PHOTO', {Do not Localize}
  382. 'BDAY', 'ADR', 'LABEL', 'TEL', {Do not Localize}
  383. 'EMAIL', 'MAILER', 'TZ', 'GEO', {Do not Localize}
  384. 'TITLE', 'ROLE', 'LOGO', 'AGENT', {Do not Localize}
  385. 'ORG', 'CATEGORIES', 'NOTE', 'PRODID', {Do not Localize}
  386. 'REV', 'SORT-STRING', 'SOUND', 'URL', {Do not Localize}
  387. 'UID', 'VERSION', 'CLASS', 'KEY'); {Do not Localize}
  388. { These constants are for testing the VCard for E-Mail types.
  389. Don't alter these } {Do not Localize}
  390. const EMailTypePropertyParameter : array [0..11] of string =
  391. ('AOL', {America On-Line} {Do not Localize}
  392. 'APPLELINK', {AppleLink} {Do not Localize}
  393. 'ATTMAIL', { AT&T Mail } {Do not Localize}
  394. 'CIS', { CompuServe Information Service } {Do not Localize}
  395. 'EWORLD', { eWorld } {Do not Localize}
  396. 'INTERNET', {Internet SMTP (default) } {Do not Localize}
  397. 'IBMMAIL', { IBM Mail } {Do not Localize}
  398. 'MCIMAIL', { MCI Mail } {Do not Localize}
  399. 'POWERSHARE', { PowerShare } {Do not Localize}
  400. 'PRODIGY', { Prodigy information service } {Do not Localize}
  401. 'TLX', { Telex number } {Do not Localize}
  402. 'X400' ); { X.400 service } {Do not Localize}
  403. function StrToFloat(const S: string):Extended;
  404. var LOldDecimalSeparator:char;
  405. LOldThousandSeparator:char;
  406. begin
  407. LOldDecimalSeparator:=DecimalSeparator;
  408. LOldThousandSeparator:=ThousandSeparator;
  409. DecimalSeparator:='.';
  410. ThousandSeparator:=',';
  411. try
  412. result:=SysUtils.StrToFloat(S);
  413. finally
  414. DecimalSeparator:=LOldDecimalSeparator;
  415. ThousandSeparator:=LOldThousandSeparator;
  416. end;
  417. end;
  418. {This only adds Value to strs if it is not zero}
  419. procedure AddValueToStrings(strs : TStrings; Value : String);
  420. begin
  421. if ( Length ( Value )<>0) then
  422. begin
  423. strs.Add ( Value );
  424. end; // if Legnth ( Value ) then
  425. end;
  426. {This parses a delinated string into a TStrings}
  427. Procedure ParseDelinatorToTStrings ( strs : TStrings; str : String;
  428. deliniator : Char = ',' ); {Do not Localize}
  429. begin
  430. while (str <> '') do {Do not Localize}
  431. begin
  432. AddValueToStrings( strs, Fetch ( str, deliniator ) );
  433. end; // while (str <> '') do {Do not Localize}
  434. end;
  435. {This parses time stamp from DateString and returns it as TDateTime
  436. This assumes the date Time stamp will be like this:
  437. 1995-10-31T22:27:10Z
  438. 1997-11-15
  439. }
  440. Function ParseDateTimeStamp ( DateString : String ) : TDateTime;
  441. var Year, Day, Month : Integer;
  442. Hour, Minute, Second : Integer;
  443. begin
  444. Year := StrToInt ( Copy ( DateString, 1, 4 ) );
  445. Month := StrToInt ( Copy (DateString, 5, 2 ) );
  446. Day := StrToInt ( Copy ( DateString, 7, 2 ) );
  447. if ( Length ( DateString ) > 14 ) then
  448. begin
  449. Hour := StrToInt ( Copy ( DateString, 10, 2 ) );
  450. Minute := StrToInt ( Copy ( DateString, 12, 2 ) );
  451. Second := StrToInt ( Copy ( DateString, 14, 2 ) );
  452. end //if ( Length ( DateString ) > 18 ) then
  453. else { no date }
  454. begin
  455. Hour := 0;
  456. Minute := 0;
  457. Second := 0;
  458. end; // else .. if ( Length ( DateString ) > 18 ) then
  459. // DateStamp.AsISO8601Calender := DateString;
  460. Result := EncodeDate(Year, Month, Day) + EncodeTime(Hour, Minute, Second,0);
  461. end;
  462. {This function returns a stringList with an item's attributes
  463. and sets value to the value of the item - everything in the stringlist is
  464. capitalized to facilitate parsing which is Case-Insensitive}
  465. Function GetAttributesAndValue (data : String; var value : String) : TStringList;
  466. var Buff, Buff2 : String;
  467. begin
  468. Result := TStringList.Create;
  469. Result.Sorted := False;
  470. if IndyPos(':',Data) <> 0 then {Do not Localize}
  471. begin
  472. Buff := idGlobal.Fetch( Data, ':' ); {Do not Localize}
  473. {This handles a VCard property attribute deliniator ","}
  474. Buff := StringReplace(Buff,',',';', [ rfReplaceAll ] ); {Do not Localize}
  475. while ( Buff <> '' ) do {Do not Localize}
  476. begin
  477. Buff2 := IdGlobal.Fetch ( Buff, ';' ); {Do not Localize}
  478. if ( Length ( Buff2 ) > 0 ) then
  479. begin
  480. Result.Add ( UpperCase( Buff2 ) );
  481. end; // if Length ( Buff2 ) > 0) then
  482. end; // while ( Buff <> '' ) do {Do not Localize}
  483. end; // if Pos(':',Data) <> 0 then {Do not Localize}
  484. Value := Data;
  485. end;
  486. {This parses the organization line from OrgString into}
  487. procedure ParseOrg ( OrgObj : TIdVCardBusinessInfo; OrgStr : String);
  488. begin
  489. { Organization name }
  490. OrgObj.Organization := Fetch ( OrgStr, ';' );
  491. { Divisions }
  492. ParseDelinatorToTStrings ( OrgObj.Divisions, OrgStr, ';' ); {Do not Localize}
  493. end;
  494. {This parses the geography latitude and longitude from GeogStr and
  495. puts it in Geog}
  496. procedure ParseGeography ( Geog : TIdVCardGeog; GeogStr : String );
  497. begin
  498. {Latitude}
  499. Geog.Latitude := StrToFloat ( Fetch ( GeogStr, ';' ) ); {Do not Localize}
  500. {Longitude}
  501. Geog.Longitude := StrToFloat ( Fetch ( GeogStr, ';' ) ); {Do not Localize}
  502. end;
  503. {This parses PhoneStr and places the attributes in PhoneObj }
  504. Procedure ParseTelephone ( PhoneObj : TIdCardPhoneNumber; PhoneStr : String);
  505. var Value : String;
  506. idx : Integer;
  507. Attribs : TStringList;
  508. const TelephoneTypePropertyParameter : array [ 0..13 ] of string =
  509. ( 'HOME', 'MSG', 'WORK', 'PREF', 'VOICE', 'FAX', {Do not Localize}
  510. 'CELL', 'VIDEO', 'BBS', 'MODEM', 'CAR', 'ISDN', {Do not Localize}
  511. 'PCS', 'PAGER' ); {Do not Localize}
  512. begin
  513. attribs := GetAttributesAndValue ( PhoneStr, Value );
  514. try
  515. idx := 0;
  516. while idx < Attribs.Count do
  517. begin
  518. case idGlobal.PosInStrArray ( attribs [ idx ], TelephoneTypePropertyParameter ) of
  519. { home }
  520. 0 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaHome ];
  521. { voice messaging }
  522. 1 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaVoiceMessaging ];
  523. { work }
  524. 2 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaWork ];
  525. { preferred }
  526. 3 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaPreferred ];
  527. { Voice }
  528. 4 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaVoice ];
  529. { Fax }
  530. 5 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaFax ];
  531. { Cellular phone }
  532. 6 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaCellular ];
  533. { Video conferancing number }
  534. 7 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaVideo ];
  535. { Bulleton Board System (BBS) telephone number }
  536. 8 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaBBS ];
  537. { MODEM Connection number }
  538. 9 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaModem ];
  539. { Car phone number }
  540. 10 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaCar ];
  541. { ISDN Service Number }
  542. 11 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaISDN ];
  543. { personal communication services telephone number }
  544. 12 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaPCS ];
  545. { pager }
  546. 13 : PhoneObj.PhoneAttributes := PhoneObj.PhoneAttributes + [ tpaPager ];
  547. end;
  548. inc ( idx );
  549. end; //while idx < Attribs.Count do
  550. { default telephon number }
  551. if ( Attribs.Count = 0 ) then
  552. begin
  553. PhoneObj.PhoneAttributes := [ tpaVoice ];
  554. end; // if (Attribs.Count = 0) then
  555. PhoneObj.Number := Value;
  556. finally
  557. FreeAndNil ( attribs );
  558. end; //try..finally
  559. end;
  560. {This parses AddressStr and places the attributes in AddressObj }
  561. Procedure ParseAddress ( AddressObj : TIdCardAddressItem; AddressStr : String);
  562. var Value : String;
  563. Attribs : TStringList;
  564. idx : Integer;
  565. const AttribsArray : Array[0..6] of String =
  566. ( 'HOME', 'DOM', 'INTL', 'POSTAL', 'PARCEL', 'WORK', 'PREF' ); {Do not Localize}
  567. begin
  568. Attribs := GetAttributesAndValue ( AddressStr, Value );
  569. try
  570. idx := 0;
  571. while idx < Attribs.Count do
  572. begin
  573. case idGlobal.PosInStrArray ( attribs [ idx ], AttribsArray ) of
  574. { home }
  575. 0 : AddressObj.AddressAttributes :=
  576. AddressObj.AddressAttributes + [ tatHome ];
  577. { domestic }
  578. 1 : AddressObj.AddressAttributes :=
  579. AddressObj.AddressAttributes + [ tatDomestic ];
  580. { international }
  581. 2 : AddressObj.AddressAttributes :=
  582. AddressObj.AddressAttributes + [ tatInternational ];
  583. { Postal }
  584. 3 : AddressObj.AddressAttributes :=
  585. AddressObj.AddressAttributes + [ tatPostal ];
  586. { Parcel }
  587. 4 : AddressObj.AddressAttributes :=
  588. AddressObj.AddressAttributes + [ tatParcel ];
  589. { Work }
  590. 5 : AddressObj.AddressAttributes :=
  591. AddressObj.AddressAttributes + [ tatWork ];
  592. { Preferred }
  593. 6 : AddressObj.AddressAttributes :=
  594. AddressObj.AddressAttributes + [ tatPreferred ];
  595. end;
  596. inc ( idx );
  597. end; //while idx < Attribs.Count do
  598. if (Attribs.Count = 0) then
  599. begin
  600. AddressObj.AddressAttributes := [ tatInternational, tatPostal, tatParcel, tatWork ];
  601. end;
  602. AddressObj.POBox := idGlobal.Fetch ( Value, ';' ); {Do not Localize}
  603. AddressObj.ExtendedAddress := idGlobal.Fetch( Value, ';' ); {Do not Localize}
  604. AddressObj.StreetAddress := idGlobal.Fetch ( Value,';' ); {Do not Localize}
  605. AddressObj.Locality := idGlobal.Fetch ( Value, ';' ); {Do not Localize}
  606. AddressObj.Region := idGlobal.Fetch ( Value, ';' ); {Do not Localize}
  607. AddressObj.PostalCode := idGlobal.Fetch ( Value, ';' ); {Do not Localize}
  608. AddressObj.Nation:= idGlobal.Fetch ( Value, ';' ); {Do not Localize}
  609. finally
  610. FreeAndNil ( Attribs );
  611. end; //try..finally
  612. end;
  613. {This parses LabelStr and places the attributes in TIdVCardMailingLabelItem }
  614. Procedure ParseMailingLabel ( LabelObj : TIdVCardMailingLabelItem; LabelStr : String);
  615. var Value : String;
  616. Attribs : TStringList;
  617. idx : Integer;
  618. const AttribsArray : Array[0..6] of String =
  619. ( 'HOME', 'DOM', 'INTL', 'POSTAL', 'PARCEL', 'WORK', 'PREF' ); {Do not Localize}
  620. begin
  621. Attribs := GetAttributesAndValue ( LabelStr, Value );
  622. try
  623. idx := 0;
  624. while idx < Attribs.Count do
  625. begin
  626. case idGlobal.PosInStrArray ( attribs [ idx ], AttribsArray ) of
  627. { home }
  628. 0 : LabelObj.AddressAttributes :=
  629. LabelObj.AddressAttributes + [ tatHome ];
  630. { domestic }
  631. 1 : LabelObj.AddressAttributes :=
  632. LabelObj.AddressAttributes + [ tatDomestic ];
  633. { international }
  634. 2 : LabelObj.AddressAttributes :=
  635. LabelObj.AddressAttributes + [ tatInternational ];
  636. { Postal }
  637. 3 : LabelObj.AddressAttributes :=
  638. LabelObj.AddressAttributes + [ tatPostal ];
  639. { Parcel }
  640. 4 : LabelObj.AddressAttributes :=
  641. LabelObj.AddressAttributes + [ tatParcel ];
  642. { Work }
  643. 5 : LabelObj.AddressAttributes :=
  644. LabelObj.AddressAttributes + [ tatWork ];
  645. { Preferred }
  646. 6 : LabelObj.AddressAttributes :=
  647. LabelObj.AddressAttributes + [ tatPreferred ];
  648. end;
  649. inc ( idx );
  650. end; //while idx < Attribs.Count do
  651. {Default Values}
  652. if Attribs.Count = 0 then
  653. begin
  654. LabelObj.AddressAttributes := [ tatInternational, tatPostal, tatParcel, tatWork ];
  655. end; //if Attribs.Count = 0 then
  656. LabelObj.MailingLabel.Add ( Value );
  657. finally
  658. FreeAndNil ( Attribs );
  659. end; //try..finally
  660. end;
  661. {This parses the Name and places the name in the TIdVCardName}
  662. Procedure ParseName ( NameObj : TIdVCardName; NameStr : String );
  663. var OtherNames : String;
  664. begin
  665. { surname }
  666. NameObj.SurName := Fetch ( NameStr, ';' ); {Do not Localize}
  667. { first name }
  668. NameObj.FirstName := Fetch ( NameStr, ';' ); {Do not Localize}
  669. { middle and other names}
  670. OtherNames := Fetch ( NameStr, ';' ); {Do not Localize}
  671. { Prefix }
  672. NameObj.Prefix := Fetch ( NameStr, ';' ); {Do not Localize}
  673. { Suffix }
  674. NameObj.Suffix := Fetch ( NameStr, ';' ); {Do not Localize}
  675. OtherNames := StringReplace( OtherNames, ' ', ',', [ rfReplaceAll ] ); {Do not Localize}
  676. ParseDelinatorToTStrings ( NameObj.OtherNames, OtherNames);
  677. end;
  678. {This parses EMailStr and places the attributes in EMailObj }
  679. Procedure ParseEMailAddress ( EMailObj : TIdVCardEMailItem; EMailStr : String);
  680. var Value : String;
  681. Attribs : TStringList;
  682. idx : Integer;
  683. {this is for testing the type so we can break out of the loop}
  684. ps : Integer;
  685. begin
  686. Attribs := GetAttributesAndValue ( EMailStr, Value );
  687. try
  688. EMailObj.Address := Value;
  689. EMailObj.Preferred := (attribs.IndexOf( 'PREF' ) <> -1 ); {Do not Localize}
  690. idx := 0;
  691. ps := -1;
  692. while (idx < Attribs.Count ) and (ps = -1) do
  693. begin
  694. ps := PosInStrArray( Attribs [ idx ], EMailTypePropertyParameter );
  695. case ps of
  696. 0 : EMailObj.EMailType := ematAOL; {America On-Line}
  697. 1 : EMailObj.EMailType := ematAppleLink; {AppleLink}
  698. 2 : EMailObj.EMailType := ematATT; { AT&T Mail }
  699. 3 : EMailObj.EMailType := ematCIS; { CompuServe Information Service }
  700. 4 : EMailObj.EMailType := emateWorld; { eWorld }
  701. 5 : EMailObj.EMailType := ematInternet; {Internet SMTP (default)}
  702. 6 : EMailObj.EMailType := ematIBMMail; { IBM Mail }
  703. 7 : EMailObj.EMailType := ematMCIMail; { Indicates MCI Mail }
  704. 8 : EMailObj.EMailType := ematPowerShare; { PowerShare }
  705. 9 : EMailObj.EMailType := ematProdigy; { Prodigy information service }
  706. 10 : EMailObj.EMailType := ematTelex; { Telex number }
  707. 11 : EMailObj.EMailType := ematX400; { X.400 service }
  708. end; // case ps of
  709. inc ( idx );
  710. end; // while (idx < Attribs.Count ) do
  711. finally
  712. FreeAndNil ( Attribs );
  713. end; //try..finally
  714. end;
  715. { TIdVCard }
  716. constructor TIdVCard.Create(AOwner: TComponent);
  717. begin
  718. inherited;
  719. FPhoto := TIdVCardEmbeddedObject.Create;
  720. FLogo := TIdVCardEmbeddedObject.Create;
  721. FSound := TIdVCardEmbeddedObject.Create;
  722. FKey := TIdVCardEmbeddedObject.Create;
  723. FComments := TStringList.Create;
  724. FCategories := TStringList.Create;
  725. FBusinessInfo := TIdVCardBusinessInfo.Create;
  726. FGeography := TIdVCardGeog.Create;
  727. FFullName := TIdVCardName.Create;
  728. FRawForm := TStringList.Create;
  729. FEMailAddresses := TIdVCardEMailAddresses.Create ( Self );
  730. FAddresses := TIdVCardAddresses.Create ( Self );
  731. FTelephones := TIdVCardTelephones.Create ( Self );
  732. FURLs := TStringList.Create;
  733. FMailingLabels := TIdVCardMailingLabels.Create ( Self );
  734. end;
  735. destructor TIdVCard.Destroy;
  736. begin
  737. FreeAndNil ( FKey );
  738. FreeAndNil ( FPhoto );
  739. FreeAndNil ( FLogo );
  740. FreeAndNil ( FSound );
  741. FreeAndNil ( FComments );
  742. FreeAndNil ( FMailingLabels );
  743. FreeAndNil ( FCategories );
  744. FreeAndNil ( FBusinessInfo );
  745. FreeAndNil ( FGeography );
  746. FreeAndNil ( FURLs );
  747. FreeAndNil ( FTelephones );
  748. FreeAndNil ( FAddresses );
  749. FreeAndNil ( FEMailAddresses );
  750. FreeAndNil ( FFullName );
  751. FreeAndNil ( FRawForm );
  752. inherited;
  753. end;
  754. procedure TIdVCard.ReadFromTStrings(s: TStrings);
  755. var
  756. idx, embedded : Integer;
  757. begin
  758. FRawForm.Clear;
  759. {Find the begin mark and accomodate broken VCard implemntations}
  760. idx := 0;
  761. embedded := 0;
  762. while ( idx < s.Count ) and
  763. ( Trim ( UpperCase ( s [ idx ] ) ) <> 'BEGIN:VCARD' ) do {Do not Localize}
  764. begin
  765. Inc ( idx );
  766. end; //while ..
  767. {Keep adding until end VCard }
  768. while ( idx < s.Count ) do
  769. begin
  770. if Length ( s [idx] ) > 0 then
  771. begin
  772. if UpperCase ( Trim ( s [ idx ] ) ) <> 'END:VCARD' then {Do not Localize}
  773. begin
  774. // Have an END: - check if this is embedded
  775. if embedded <> 0 then
  776. begin
  777. // Yes - decrement the counter & add
  778. Dec(embedded);
  779. end;
  780. end else if UpperCase ( Trim ( s [ idx ] ) ) <> 'BEGIN:VCARD' then {Do not Localize}
  781. begin
  782. // Have a new embedded object - increment the counter & add
  783. Inc(embedded);
  784. end;
  785. // Regardless of content - add it
  786. FRawForm.Add(s[idx]);
  787. end;
  788. Inc ( idx );
  789. end; //while ( idx < s.Count ) and (s[idx] <> 'END:VCARD') do {Do not Localize}
  790. if ( idx < s.Count ) and (Length(s [idx] ) > 0 ) then
  791. FRawForm.Add ( s [ idx ] );
  792. SetVariablesAfterRead;
  793. end;
  794. procedure TIdVCard.SetCategories(Value: TStrings);
  795. begin
  796. FCategories.Assign(Value);
  797. end;
  798. procedure TIdVCard.SetComments(Value: TStrings);
  799. begin
  800. FComments.Assign(Value);
  801. end;
  802. procedure TIdVCard.SetURLs(Value: TStrings);
  803. begin
  804. FURLs.Assign(Value);
  805. end;
  806. procedure TIdVCard.SetVariablesAfterRead;
  807. var idx : Integer;
  808. OrigLine : String;
  809. Line : String;
  810. Attribs : String;
  811. Data : String;
  812. Test : String;
  813. Colon : Integer;
  814. SColon : Integer;
  815. ColonFind : Integer;
  816. QPCoder : TIdDecoderQuotedPrintable;
  817. {These subroutines increment idx to prevent unneded comparisons of folded
  818. lines}
  819. Function UnfoldLines : String;
  820. begin
  821. Result := ''; {Do not Localize}
  822. Inc ( idx );
  823. while ( idx < FRawForm.Count ) and ( ( Length ( FRawForm [ idx ] ) > 0) and
  824. ( FRawForm [ idx ] [ 1 ] = ' ' ) or ( FRawForm [ idx ] [ 1 ] = #9 ) ) do {Do not Localize}
  825. begin
  826. Result := Result + Trim ( FRawForm [ idx ] );
  827. inc ( idx );
  828. end; // while
  829. {Correct for increment in the main while loop}
  830. Dec ( idx );
  831. end;
  832. procedure ProcessAgent;
  833. begin
  834. // The current idx of FRawForm could be an embedded vCard.
  835. { TODO : Eliminate embedded vCard }
  836. end;
  837. Procedure ParseEmbeddedObject(EmObj : TIdVCardEmbeddedObject; StLn : String);
  838. var Value : String;
  839. Attribs : TStringList;
  840. idx2 : Integer;
  841. {this is for testing the type so we can break out of the loop}
  842. begin
  843. attribs := GetAttributesAndValue ( StLn, Value );
  844. try
  845. idx2 := 0;
  846. while ( idx2 < attribs.Count ) do
  847. begin
  848. if ((Attribs[ idx2 ] = 'ENCODING=BASE64') or {Do not Localize}
  849. (Attribs [ idx2 ] = 'BASE64')) then {Do not Localize}
  850. begin
  851. emObj.Base64Encoded := True;
  852. end //if
  853. else
  854. begin
  855. if not (( Attribs [ idx2 ] = 'VALUE=URI' ) or {Do not Localize}
  856. ( Attribs [ idx2 ] = 'VALUE=URL' ) or {Do not Localize}
  857. ( Attribs [ idx2 ] = 'URI' ) or {Do not Localize}
  858. ( Attribs [ idx2 ] = 'URL' ) ) then {Do not Localize}
  859. begin
  860. emObj.ObjectType := Attribs [ idx2 ];
  861. end; // if NOT ...
  862. end; // else if not ..
  863. Inc ( idx2 );
  864. end; //while ( idx2 < attribs.Count ) do
  865. if ( Attribs.IndexOf ( 'VALUE=URI' ) > -1 ) or {Do not Localize}
  866. ( Attribs.IndexOf ( 'VALUE=URL' ) > -1 ) or {Do not Localize}
  867. ( Attribs.IndexOf ( 'URI' ) > -1 ) or {Do not Localize}
  868. ( Attribs.IndexOf ( 'URL' ) > -1 ) then {Do not Localize}
  869. begin
  870. emObj.ObjectURL := Value + UnfoldLines;
  871. end //if
  872. else
  873. begin
  874. AddValueToStrings ( EmObj.EmbeddedData, Value );
  875. {Add any folded lines}
  876. Inc( idx );
  877. while ( idx < FRawForm.Count ) and ( ( Length ( FRawForm [ idx ] ) > 0) and
  878. ( FRawForm [ idx ] [ 1 ] = ' ' ) or ( FRawForm [ idx ] [ 1 ] = #9 ) ) do {Do not Localize}
  879. begin
  880. AddValueToStrings ( EmObj.EmbeddedData, Trim ( FRawForm [ idx2 ] ) );
  881. inc ( idx );
  882. end; // while
  883. {Correct for increment in the main while loop}
  884. Dec ( idx );
  885. end; // else .. if
  886. finally
  887. FreeAndNil ( Attribs );
  888. end;
  889. end;
  890. begin
  891. // At this point, FRawForm contains the entire vCard - including possible
  892. // embedded vCards.
  893. QPCoder := TIdDecoderQuotedPrintable.Create(Self);
  894. try
  895. idx := 0;
  896. while idx < FRawForm.Count do
  897. begin
  898. // Grab the line
  899. Line := FRawForm [ idx ];
  900. {We separate the property name from the parameters and values here.
  901. We have be careful because sometimes a property in a vCard is separed by a
  902. ; or : even if the RFC and standards don't permit this
  903. - broken VCard creation tools }
  904. Colon := IndyPos(':', Line); {Do not Localize}
  905. // Store the property & complete attributes
  906. Attribs := Copy(Line, 1, Colon - 1);
  907. // Must now check for Quoted-printable attribute. vCard v2.1 allows
  908. // QP to be used in any field.
  909. //**** Begin QP check & decode
  910. if IndyPos('QUOTED-PRINTABLE', UpperCase(Attribs)) > 0 then {Do not Localize}
  911. begin
  912. // First things first - make a copy of the Line.
  913. OrigLine := Line;
  914. // Set Data to be the data contained on this line of the vCard
  915. Data := Copy(Line, Colon + 1, Length(Line));
  916. // The problem with QP-embedded objects is that the Colon character is
  917. // not standard QP-encoded... however, it is the only reliable way to
  918. // discover the next property. So loop here until the next property is
  919. // found (i.e., the next line with a colon).
  920. Inc(idx);
  921. ColonFind := IndyPos(':', FRawForm[idx]); {Do not Localize}
  922. while ColonFind = 0 do
  923. begin
  924. Data := Data + TrimLeft(FRawForm[idx]);
  925. Inc(idx);
  926. if idx <> FRawForm.Count then
  927. begin
  928. ColonFind := IndyPos(':', FRawForm[idx]); {Do not Localize}
  929. end else ColonFind := 1;
  930. end;
  931. // Return idx to this property's (last) line {Do not Localize}
  932. Dec(idx);
  933. Data := QPCoder.DecodeToString(Data);
  934. // Now reorganise property so that it does not have a QP attribute.
  935. ColonFind := IndyPos(';', Attribs); {Do not Localize}
  936. Line := ''; {Do not Localize}
  937. while ColonFind <> 0 do
  938. begin
  939. Test := Copy(Attribs, 1, ColonFind);
  940. if IndyPos('QUOTED-PRINTABLE', UpperCase(Test)) = 0 then {Do not Localize}
  941. begin
  942. // Add to Line.
  943. Line := Line + Test;
  944. end;
  945. Attribs := Copy(Attribs, ColonFind + 1, Length(Attribs));
  946. ColonFind := IndyPos(';', Attribs); {Do not Localize}
  947. end;
  948. // Clean up variables
  949. if Length(Attribs) <> 0 then
  950. begin
  951. // Does Quoted-Printable occur in what's left? {Do not Localize}
  952. if IndyPos('QUOTED-PRINTABLE', UpperCase(Attribs)) = 0 then {Do not Localize}
  953. begin
  954. // Add to line
  955. Line := Line + Attribs;
  956. end;
  957. end;
  958. // Check if the last char of Line is a semi-colon. If so, remove it.
  959. ColonFind := Length(Line);
  960. If ColonFind > 0 then
  961. begin
  962. if Line[ColonFind] = ';' then {Do not Localize}
  963. begin
  964. Line := Copy(Line, 1, ColonFind - 1);
  965. end;
  966. end;
  967. Line := Line + ':' + Data; {Do not Localize}
  968. end;
  969. //**** End QP check & decode
  970. Colon := IndyPos(':', Line); {Do not Localize}
  971. SColon := IndyPos(';', Line); {Do not Localize}
  972. if ( Colon < SColon ) or ( SColon = 0 ) then
  973. begin
  974. Line := StringReplace ( Line, ':', ';', [ ] ); {Do not Localize}
  975. end;
  976. // Grab the property name
  977. Test := UpperCase ( Fetch ( Line,';') ); {Do not Localize}
  978. // Discover which property it is.
  979. case PosInStrArray( Test, VCardProperties ) of
  980. {'FN'} {Do not Localize}
  981. 0 : FFullName.FormattedName := Line + UnfoldLines;
  982. {'N'} {Do not Localize}
  983. 1 : ParseName ( FFullName, Line + UnfoldLines );
  984. {'NICKNAME'} {Do not Localize}
  985. 2 : ParseDelinatorToTStrings ( FFullName.NickNames , Line + UnfoldLines );
  986. {'PHOTO'} {Do not Localize}
  987. 3 : ParseEmbeddedObject ( FPhoto, Line );
  988. {'BDAY'} {Do not Localize}
  989. 4 : FBirthDay := ParseDateTimeStamp ( Line + UnfoldLines );
  990. {'ADR'} {Do not Localize}
  991. 5 : ParseAddress ( FAddresses.Add, Line + UnfoldLines );
  992. {'LABEL'} {Do not Localize}
  993. 6 : ParseMailingLabel (FMailingLabels.Add, Line + UnfoldLines );
  994. {'TEL'} {Do not Localize}
  995. 7 : ParseTelephone ( FTelephones.Add, Line + UnfoldLines );
  996. {'EMAIL'} {Do not Localize}
  997. 8 : ParseEMailAddress ( FEMailAddresses.Add, Line + UnfoldLines );
  998. {'MAILER'} {Do not Localize}
  999. 9 : FEMailProgram := Line + UnfoldLines;
  1000. {'TZ'} {Do not Localize}
  1001. 10 : FGeography.TimeZoneStr := Line + UnfoldLines;
  1002. {'GEO'} {Do not Localize}
  1003. 11 : ParseGeography ( FGeography, Line + UnfoldLines );
  1004. {'TITLE'} {Do not Localize}
  1005. 12 : FBusinessInfo.Title := Line + UnfoldLines;
  1006. {'ROLE'} {Do not Localize}
  1007. 13 : FBusinessInfo.Role := Line + UnfoldLines;
  1008. {'LOGO'} {Do not Localize}
  1009. 14 : ParseEmbeddedObject ( FLogo, Line );
  1010. {'AGENT'} {Do not Localize}
  1011. 15 : ProcessAgent;
  1012. {'ORG'} {Do not Localize}
  1013. 16 : ParseOrg ( FBusinessInfo, Line + UnfoldLines );
  1014. {'CATEGORIES'} {Do not Localize}
  1015. 17 : ParseDelinatorToTStrings ( FCategories, Line + UnfoldLines );
  1016. {'NOTE'} {Do not Localize}
  1017. 18 : FComments.Add ( Line +UnfoldLines );
  1018. {'PRODID' } {Do not Localize}
  1019. 19 : FProductID := Line + UnfoldLines;
  1020. {'REV'} {Do not Localize}
  1021. 20 : FLastRevised := ParseDateTimeStamp ( Line + UnfoldLines );
  1022. {'SORT-STRING'} {Do not Localize}
  1023. 21 : FFullName.SortName := Line + UnfoldLines;
  1024. {'SOUND'} {Do not Localize}
  1025. 22 : ParseEmbeddedObject ( FSound, Line );
  1026. {'URL'} {Do not Localize}
  1027. 23 : AddValueToStrings( FURLs, Line + UnfoldLines );
  1028. {'UID'} {Do not Localize}
  1029. 24 : FUniqueID := Line + UnfoldLines;
  1030. {'VERSION'} {Do not Localize}
  1031. 25 : FVCardVersion := StrToFloat ( Line + UnfoldLines );
  1032. {'CLASS'} {Do not Localize}
  1033. 26 : FClassification := Line + UnfoldLines;
  1034. {'KEY'} {Do not Localize}
  1035. 27 : ParseEmbeddedObject ( FKey, Line );
  1036. end;
  1037. inc ( idx );
  1038. end; // while idx < FRawForm.Count do
  1039. finally
  1040. QPCoder.Free;
  1041. end;
  1042. end;
  1043. { TIdVCardEMailAddresses }
  1044. function TIdVCardEMailAddresses.Add: TIdVCardEMailItem;
  1045. begin
  1046. Result := TIdVCardEMailItem(inherited Add);
  1047. end;
  1048. constructor TIdVCardEMailAddresses.Create ( AOwner : TPersistent );
  1049. begin
  1050. inherited Create ( AOwner, TIdVCardEMailItem );
  1051. end;
  1052. function TIdVCardEMailAddresses.GetItem(Index: Integer): TIdVCardEMailItem;
  1053. begin
  1054. Result := TIdVCardEMailItem ( inherited Items [ Index ] );
  1055. end;
  1056. procedure TIdVCardEMailAddresses.SetItem(Index: Integer;
  1057. const Value: TIdVCardEMailItem);
  1058. begin
  1059. inherited SetItem ( Index, Value );
  1060. end;
  1061. { TIdVCardEMailItem }
  1062. procedure TIdVCardEMailItem.Assign(Source: TPersistent);
  1063. var EMail : TIdVCardEMailItem;
  1064. begin
  1065. if ClassType <> Source.ClassType then
  1066. begin
  1067. inherited
  1068. end
  1069. else
  1070. begin
  1071. EMail := TIdVCardEMailItem(Source);
  1072. EMailType := EMail.EMailType;
  1073. Preferred := EMail.Preferred;
  1074. Address := EMail.Address;
  1075. end;
  1076. end;
  1077. constructor TIdVCardEMailItem.Create(Collection: TCollection);
  1078. begin
  1079. inherited;
  1080. FEMailType := ematInternet;
  1081. end;
  1082. { TIdVCardAddresses }
  1083. function TIdVCardAddresses.Add: TIdCardAddressItem;
  1084. begin
  1085. Result := TIdCardAddressItem ( inherited Add );
  1086. end;
  1087. constructor TIdVCardAddresses.Create ( AOwner : TPersistent );
  1088. begin
  1089. inherited Create ( AOwner, TIdCardAddressItem );
  1090. end;
  1091. function TIdVCardAddresses.GetItem(Index: Integer): TIdCardAddressItem;
  1092. begin
  1093. Result := TIdCardAddressItem ( inherited Items [ Index ] );
  1094. end;
  1095. procedure TIdVCardAddresses.SetItem(Index: Integer;
  1096. const Value: TIdCardAddressItem);
  1097. begin
  1098. inherited SetItem ( Index, Value );
  1099. end;
  1100. { TIdVCardTelephones }
  1101. function TIdVCardTelephones.Add: TIdCardPhoneNumber;
  1102. begin
  1103. Result := TIdCardPhoneNumber ( inherited Add );
  1104. end;
  1105. constructor TIdVCardTelephones.Create ( AOwner : TPersistent );
  1106. begin
  1107. inherited Create ( AOwner, TIdCardPhoneNumber );
  1108. end;
  1109. function TIdVCardTelephones.GetItem(Index: Integer): TIdCardPhoneNumber;
  1110. begin
  1111. Result := TIdCardPhoneNumber ( inherited Items [ Index ] );
  1112. end;
  1113. procedure TIdVCardTelephones.SetItem(Index: Integer;
  1114. const Value: TIdCardPhoneNumber);
  1115. begin
  1116. inherited SetItem ( Index, Value );
  1117. end;
  1118. { TIdVCardName }
  1119. constructor TIdVCardName.Create;
  1120. begin
  1121. inherited;
  1122. FOtherNames := TStringList.Create;
  1123. FNickNames := TStringList.Create;
  1124. end;
  1125. destructor TIdVCardName.Destroy;
  1126. begin
  1127. FreeAndNil ( FNickNames );
  1128. FreeAndNil ( FOtherNames );
  1129. inherited;
  1130. end;
  1131. procedure TIdVCardName.SetNickNames(Value: TStrings);
  1132. begin
  1133. FNickNames.Assign(Value);
  1134. end;
  1135. procedure TIdVCardName.SetOtherNames(Value: TStrings);
  1136. begin
  1137. FOtherNames.Assign(Value);
  1138. end;
  1139. { TIdVCardBusinessInfo }
  1140. constructor TIdVCardBusinessInfo.Create;
  1141. begin
  1142. inherited;
  1143. FDivisions := TStringList.Create;
  1144. end;
  1145. destructor TIdVCardBusinessInfo.Destroy;
  1146. begin
  1147. FreeAndNil ( FDivisions );
  1148. inherited;
  1149. end;
  1150. procedure TIdVCardBusinessInfo.SetDivisions(Value: TStrings);
  1151. begin
  1152. FDivisions.Assign(Value);
  1153. end;
  1154. { TIdVCardMailingLabelItem }
  1155. procedure TIdVCardMailingLabelItem.Assign(Source: TPersistent);
  1156. var lbl : TIdVCardMailingLabelItem;
  1157. begin
  1158. if ClassType <> Source.ClassType then
  1159. begin
  1160. inherited
  1161. end
  1162. else
  1163. begin
  1164. lbl := TIdVCardMailingLabelItem(Source);
  1165. AddressAttributes := lbl.AddressAttributes;
  1166. MailingLabel.Assign(lbl.MailingLabel);
  1167. end;
  1168. end;
  1169. constructor TIdVCardMailingLabelItem.Create(Collection: TCollection);
  1170. begin
  1171. inherited;
  1172. FMailingLabel := TStringList.Create;
  1173. end;
  1174. destructor TIdVCardMailingLabelItem.Destroy;
  1175. begin
  1176. FreeAndNil ( FMailingLabel );
  1177. inherited;
  1178. end;
  1179. procedure TIdVCardMailingLabelItem.SetMailingLabel(Value: TStrings);
  1180. begin
  1181. FMailingLabel.Assign(Value);
  1182. end;
  1183. { TIdVCardMailingLabels }
  1184. function TIdVCardMailingLabels.Add: TIdVCardMailingLabelItem;
  1185. begin
  1186. Result := TIdVCardMailingLabelItem ( inherited Add );
  1187. end;
  1188. constructor TIdVCardMailingLabels.Create(AOwner: TPersistent);
  1189. begin
  1190. inherited Create (AOwner, TIdVCardMailingLabelItem );
  1191. end;
  1192. function TIdVCardMailingLabels.GetItem(
  1193. Index: Integer): TIdVCardMailingLabelItem;
  1194. begin
  1195. Result := TIdVCardMailingLabelItem ( inherited GetItem ( Index ) );
  1196. end;
  1197. procedure TIdVCardMailingLabels.SetItem(Index: Integer;
  1198. const Value: TIdVCardMailingLabelItem);
  1199. begin
  1200. inherited SetItem ( Index, Value );
  1201. end;
  1202. { TIdEmbeddedObject }
  1203. constructor TIdVCardEmbeddedObject.Create;
  1204. begin
  1205. inherited;
  1206. FEmbeddedData := TStringList.Create;
  1207. end;
  1208. destructor TIdVCardEmbeddedObject.Destroy;
  1209. begin
  1210. FreeAndNil ( FEmbeddedData );
  1211. inherited;
  1212. end;
  1213. procedure TIdVCardEmbeddedObject.SetEmbeddedData(const Value: TStrings);
  1214. begin
  1215. FEmbeddedData.Assign(Value);
  1216. end;
  1217. { TIdCardPhoneNumber }
  1218. procedure TIdCardPhoneNumber.Assign(Source: TPersistent);
  1219. var Phone : TIdCardPhoneNumber;
  1220. begin
  1221. if ClassType <> Source.ClassType then
  1222. begin
  1223. inherited;
  1224. end
  1225. else
  1226. begin
  1227. Phone := TIdCardPhoneNumber(Source);
  1228. PhoneAttributes := Phone.PhoneAttributes;
  1229. Number := Phone.Number;
  1230. end;
  1231. end;
  1232. { TIdCardAddressItem }
  1233. procedure TIdCardAddressItem.Assign(Source: TPersistent);
  1234. var Addr : TIdCardAddressItem;
  1235. begin
  1236. if ClassType <> Source.ClassType then
  1237. begin
  1238. inherited;
  1239. end
  1240. else
  1241. begin
  1242. Addr := TIdCardAddressItem(Source);
  1243. AddressAttributes := Addr.AddressAttributes;
  1244. POBox := Addr.POBox;
  1245. ExtendedAddress := Addr.ExtendedAddress;
  1246. StreetAddress := Addr.StreetAddress;
  1247. Locality := Addr.Locality;
  1248. Region := Addr.Region;
  1249. PostalCode := Addr.PostalCode;
  1250. Nation := Addr.Nation;
  1251. end;
  1252. end;
  1253. end.