added 4 changesets to branch 'refs/remotes/jessicah-github/contacts' old head: 0000000000000000000000000000000000000000 new head: afaab8c55db06c1d075655993c4127867542dd6d overview: https://github.com/jessicah/haiku/compare/afaab8c ---------------------------------------------------------------------------- 75f2c88: Imported code from the original branch. [ Barrett <b.vitruvio@xxxxxxxxx> ] 79d1245: Removed unneeded files. [ Barrett <b.vitruvio@xxxxxxxxx> ] c314ba7: Build system changes for contact kit in a packaged world. [ Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> ] afaab8c: Also add VCard translator for a package managed world. [ Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> ] ---------------------------------------------------------------------------- 76 files changed, 9863 insertions(+), 469 deletions(-) build/jam/images/definitions/regular | 2 + headers/os/translation/TranslatorFormats.h | 8 +- headers/private/contact/AddressBook.h | 38 + headers/private/contact/Contact.h | 86 ++ headers/private/contact/ContactDefs.h | 133 ++ headers/private/contact/ContactField.h | 302 +++++ headers/private/contact/ContactGroup.h | 60 + headers/private/contact/ContactRef.h | 67 + headers/private/contact/ContactRoster.h | 42 + headers/private/contact/RawContact.h | 57 + src/add-ons/translators/Jamfile | 2 + src/add-ons/translators/person/Jamfile | 26 + src/add-ons/translators/person/PersonMain.cpp | 17 + .../translators/person/PersonTranslator.cpp | 652 ++++++++++ .../translators/person/PersonTranslator.h | 87 ++ .../translators/person/PersonTranslator.rdef | 11 + src/add-ons/translators/person/PersonView.cpp | 78 ++ src/add-ons/translators/person/PersonView.h | 18 + src/add-ons/translators/vcard/Jamfile | 29 + src/add-ons/translators/vcard/VCardMain.cpp | 17 + src/add-ons/translators/vcard/VCardParser.cpp | 212 ++++ src/add-ons/translators/vcard/VCardParser.h | 58 + src/add-ons/translators/vcard/VCardParserDefs.h | 197 +++ .../translators/vcard/VCardTranslator.cpp | 313 +++++ src/add-ons/translators/vcard/VCardTranslator.h | 70 ++ .../translators/vcard/VCardTranslator.rdef | 11 + src/add-ons/translators/vcard/VCardView.cpp | 65 + src/add-ons/translators/vcard/VCardView.h | 18 + src/add-ons/translators/vcard/cardparser.c | 737 +++++++++++ src/add-ons/translators/vcard/cardparser.h | 67 + .../AttributeTextControl.cpp | 0 .../AttributeTextControl.h | 0 src/apps/people-old/Jamfile | 24 + src/apps/people-old/LICENSE | 31 + src/apps/people-old/People.rdef | 53 + src/apps/people-old/PeopleApp.cpp | 362 ++++++ src/apps/people-old/PeopleApp.h | 67 + src/apps/people-old/PersonIcons.h | 40 + src/apps/people-old/PersonView.cpp | 449 +++++++ src/apps/people-old/PersonView.h | 76 ++ src/apps/people-old/PersonWindow.cpp | 444 +++++++ src/apps/people-old/PersonWindow.h | 71 ++ src/apps/people-old/PictureView.cpp | 644 ++++++++++ src/apps/people-old/PictureView.h | 65 + src/apps/people-old/main.cpp | 19 + src/apps/people/AddressView.cpp | 363 ++++++ src/apps/people/AddressView.h | 94 ++ src/apps/people/AddressWindow.cpp | 99 ++ src/apps/people/AddressWindow.h | 38 + src/apps/people/ContactFieldTextControl.cpp | 122 ++ src/apps/people/ContactFieldTextControl.h | 40 + src/apps/people/GroupsWindow.cpp | 43 + src/apps/people/GroupsWindow.h | 29 + src/apps/people/Jamfile | 9 +- src/apps/people/LICENSE | 0 src/apps/people/People.rdef | 6 +- src/apps/people/PeopleApp.cpp | 190 +-- src/apps/people/PeopleApp.h | 18 +- src/apps/people/PersonIcons.h | 0 src/apps/people/PersonView.cpp | 410 +++--- src/apps/people/PersonView.h | 78 +- src/apps/people/PersonWindow.cpp | 289 +++-- src/apps/people/PersonWindow.h | 31 +- src/apps/people/PictureView.cpp | 47 +- src/apps/people/PictureView.h | 4 + src/apps/people/main.cpp | 0 src/kits/Jamfile | 1 + src/kits/contact/AddressBook.cpp | 117 ++ src/kits/contact/Contact.cpp | 481 +++++++ src/kits/contact/ContactField.cpp | 1178 ++++++++++++++++++ src/kits/contact/ContactGroup.cpp | 197 +++ src/kits/contact/ContactPrivate.h | 106 ++ src/kits/contact/ContactRef.cpp | 170 +++ src/kits/contact/ContactRoster.cpp | 66 + src/kits/contact/Jamfile | 25 + src/kits/contact/RawContact.cpp | 256 ++++ ############################################################################ Commit: 75f2c88f3c344dd9efe19d06db362fa387cf4fe1 Author: Barrett <b.vitruvio@xxxxxxxxx> Date: Mon Jul 29 16:17:30 2013 UTC Committer: Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> Commit-Date: Sun May 25 01:23:44 2014 UTC Imported code from the original branch. ---------------------------------------------------------------------------- diff --git a/headers/os/translation/TranslatorFormats.h b/headers/os/translation/TranslatorFormats.h index 744c0c6..20d473a 100644 --- a/headers/os/translation/TranslatorFormats.h +++ b/headers/os/translation/TranslatorFormats.h @@ -61,7 +61,12 @@ enum { B_AU_FORMAT = 'AU ', // Text formats - B_STYLED_TEXT_FORMAT = 'STXT' + B_STYLED_TEXT_FORMAT = 'STXT', + + // Contact formats + B_CONTACT_FORMAT = 'BCFM', + B_PERSON_FORMAT = 'BPFM', + B_VCARD_FORMAT = 'BVFM' }; diff --git a/headers/private/contact/AddressBook.h b/headers/private/contact/AddressBook.h new file mode 100755 index 0000000..77b3294 --- /dev/null +++ b/headers/private/contact/AddressBook.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef ADDRESS_BOOK_H +#define ADDRESS_BOOK_H + +#include <ContactDefs.h> +#include <Contact.h> +#include <ContactGroup.h> +#include <Path.h> +#include <SupportDefs.h> + +class BAddressBook : public BContactGroup { +public: + BAddressBook(); + ~BAddressBook(); + status_t InitCheck(); + + status_t AddContact(BContactRef contact); + status_t RemoveContact(BContactRef contact); + + BPath GetPath(); + +// BContactList ContactsByGroup(BContactGroup* group); +// BContactList ContactsByQuery(BContactQuery* query); + +// status_t Commit(); +// status_t Reload(); + + //static BAddressBook* Default(); +private: + status_t _FindDir(); + status_t fInitCheck; + BPath fAddrBook; +}; + +#endif // ADDRESS_BOOK_H diff --git a/headers/private/contact/Contact.h b/headers/private/contact/Contact.h new file mode 100755 index 0000000..704e45d --- /dev/null +++ b/headers/private/contact/Contact.h @@ -0,0 +1,86 @@ +/* + * Copyright 2011 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef B_CONTACT_H +#define B_CONTACT_H + +#include <Archivable.h> +#include <ContactDefs.h> +#include <ContactField.h> +#include <ContactRef.h> +#include <Message.h> +#include <ObjectList.h> +#include <RawContact.h> + + +class BContact : public virtual BArchivable { +public: + BContact(BRawContact* contact = NULL); + BContact(BContactRef& ref); + BContact(BMessage* archive); + virtual ~BContact(); + + status_t Archive(BMessage* archive, bool deep) const; + static BArchivable* Instantiate(BMessage* data); + + status_t InitCheck() const; + + int32 ID(); + uint32 GroupID(); + + BContactRef ContactRef(); + + status_t AddField(BContactField* field); + status_t RemoveEquivalentFields(BContactField* field); + status_t RemoveField(BContactField* field); + status_t ReplaceField(BContactField* field); + bool HasField(BContactField* field); + + BContactField* FieldAt(int index); + BContactField* FieldByType(field_type type, int32 index = 0); + + int32 CountFields() const; + int32 CountFields(field_type code) const; + + const BContactFieldList& FieldList() const; + + bool IsEqual(BContact* contact); + status_t CopyFieldsFrom(BContact* contact); + status_t CreateDefaultFields(); + + // for the moment it supports only a BRawContact, in future + // the following methods will help to merge many BRawContacts + // into a BContact. + // delete the actual BRawContact objects + status_t Append(BRawContact* contact); + const BRawContact& RawContact() const; + + status_t Commit(); + status_t Reload(); + + static BObjectList<field_type>& SupportedFields(); + static BObjectList<field_usage>& SupportedUsages(); + +protected: + // status_t SetInternalID(uint32 id); + // status_t AppendGroup(uint32 id); + // status_t AppendGroup(BContactGroup group); + +private: + status_t _FlattenFields(BMessage* msg) const; + status_t _UnflattenFields(BMessage* msg); + + BRawContact* fRawContact; + status_t fInitCheck; + int32 fID; + uint32 fGroupID; + + BContactFieldList fList; + + //friend class BContactRoster; +}; + +typedef BObjectList<BContact> BContactList; + +#endif // B_CONTACT_H diff --git a/headers/private/contact/ContactDefs.h b/headers/private/contact/ContactDefs.h new file mode 100755 index 0000000..49262ef --- /dev/null +++ b/headers/private/contact/ContactDefs.h @@ -0,0 +1,133 @@ +/* + * Copyright 2011 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef B_CONTACT_DEFS_H +#define B_CONTACT_DEFS_H + +#include <Errors.h> + + +enum DefaultDefs { + B_CONTACT_ANY = 'BCAN' +}; + +enum ContactGroupDefs { + B_CONTACT_GROUP_NONE = 1, + B_CONTACT_GROUP_DEFAULT = 'BCGD', + B_CONTACT_GROUP_ADDRESS_BOOK = 'BCSG' +}; + +// TODO update code +// for missing fields +enum ContactFieldType { + B_CONTACT_ADDRESS = 'CFNA', + B_CONTACT_ASSISTANT = 'BCAS', + B_CONTACT_BIRTHDAY = 'BCBR', + B_CONTACT_CUSTOM = 'CCUS', + B_CONTACT_DELIVERY_LABEL = 'BCDL', + B_CONTACT_EMAIL = 'CFNE', + B_CONTACT_FORMATTED_NAME = 'CFFN', + B_CONTACT_GENDER = 'CFGN', + B_CONTACT_GEO = 'CFNG', + B_CONTACT_GROUP = 'CFNR', + B_CONTACT_IM = 'CFNI', + B_CONTACT_MANAGER = 'BCMN', + B_CONTACT_NAME = 'CFNN', + B_CONTACT_NICKNAME = 'CFNK', + B_CONTACT_NOTE = 'CFNO', + B_CONTACT_ORGANIZATION = 'CFNJ', + B_CONTACT_PHONE = 'CFNP', + B_CONTACT_PHOTO = 'CFNH', + B_CONTACT_PROTOCOLS = 'CFNL', + B_CONTACT_SIMPLE_GROUP = 'CFSG', + B_CONTACT_SOUND = 'BCDS', + B_CONTACT_SPOUSE = 'BCSP', + B_CONTACT_TIME_ZONE = 'CNTM', + B_CONTACT_TITLE = 'CNTL', + B_CONTACT_UID = 'CFND', + B_CONTACT_URL = 'CFNU', + B_CONTACT_REV = 'CFRV' +}; + +enum CommonFieldUsageTypes { + CONTACT_DATA_CUSTOM = 'CDTC', + CONTACT_DATA_OTHER = 'CDOT', + CONTACT_DATA_HOME = 'CDHM', + CONTACT_DATA_WORK = 'CDWK', + CONTACT_DATA_PREFERRED = 'CDPF' +}; + +enum SpecificFieldUsageTypes { + CONTACT_NAME_FAMILY = 'CNFM', + CONTACT_NAME_GIVEN = 'CNGV', + CONTACT_NAME_MIDDLE = 'CNMD', + CONTACT_NAME_SUFFIX = 'CNSF', + + CONTACT_NICKNAME_DEFAULT = 'CNDF', + CONTACT_NICKNAME_MAIDEN = 'CNMN', + CONTACT_NICKNAME_SHORT_NAME = 'CNSN', + CONTACT_NICKNAME_INITIALS = 'CNIN', + + CONTACT_EMAIL_INTERNET = 'CEIN', + CONTACT_EMAIL_MOBILE = 'CEMB', + + CONTACT_PHONE_ASSISTANT = 'CPAS', + CONTACT_PHONE_CALLBACK = 'CPXK', + CONTACT_PHONE_CAR = 'CPCR', + CONTACT_PHONE_BBS = 'CPBS', + CONTACT_PHONE_FAX = 'CPFW', + CONTACT_PHONE_ISDN = 'CPIN', + CONTACT_PHONE_MMS = 'CPMS', + CONTACT_PHONE_MODEM = 'CPMD', + CONTACT_PHONE_MOBILE = 'CPMB', + CONTACT_PHONE_MSG = 'CPMG', + CONTACT_PHONE_PAGER = 'CPPG', + CONTACT_PHONE_RADIO = 'CPRA', + CONTACT_PHONE_TELEX = 'CPTE', + CONTACT_PHONE_TTY_TDD = 'CPTY', + CONTACT_PHONE_VIDEO = 'CPVD', + CONTACT_PHONE_VOICE = 'CPVC', + + CONTACT_PHOTO_BITMAP = 'CPBT', + CONTACT_PHOTO_URL = 'CPUL', +/* CONTACT_PHOTO_AVI = 'CPAV', + CONTACT_PHOTO_BMP = 'CPBM', + CONTACT_PHOTO_GIF = 'CPGF', + CONTACT_PHOTO_MPEG = 'CPMP', + CONTACT_PHOTO_MPEG2 = 'CPM2', + CONTACT_PHOTO_PS = 'CPPS', + CONTACT_PHOTO_PDF = 'CPPD', + CONTACT_PHOTO_QTIME = 'CPBT', + CONTACT_PHOTO_TIFF = 'CPTF', + CONTACT_PHOTO_JPEG = 'CPJP', + CONTACT_PHOTO_CGM = 'CPCG', + CONTACT_PHOTO_WMF = 'CPWM', + CONTACT_PHOTO_MET = 'CPME', + CONTACT_PHOTO_PBM = 'CPPB', + CONTACT_PHOTO_DIB = 'CPDI', + CONTACT_PHOTO_PICT = 'CPPI',*/ + + CONTACT_ADDRESS_DOM = 'CADM', + CONTACT_ADDRESS_INTL = 'CAIN', + CONTACT_ADDRESS_POSTAL = 'CAPO', + CONTACT_ADDRESS_PARCEL = 'CAPA', + + CONTACT_SOUND_WAVE = 'CSWV', + CONTACT_SOUND_PCM = 'CSPC', + CONTACT_SOUND_AIFF = 'CSAI', + CONTACT_SOUND_MP3 = 'CSM3', + CONTACT_SOUND_OGG = 'CSOG', + + CONTACT_IM_AIM = 'CIMA', + CONTACT_IM_ICQ = 'CIMI', + CONTACT_IM_MSN = 'CIMM', + CONTACT_IM_JABBER = 'CIMJ', + CONTACT_IM_YAHOO = 'CIMY', + CONTACT_IM_TWITTER = 'CIMT', + CONTACT_IM_SKYPE = 'CIMS', + CONTACT_IM_GADUGADU = 'CIMG', + CONTACT_IM_GROUPWISE = 'CIMW' +}; + +#endif // B_CONTACT_DEFS_H diff --git a/headers/private/contact/ContactField.h b/headers/private/contact/ContactField.h new file mode 100755 index 0000000..94731c2 --- /dev/null +++ b/headers/private/contact/ContactField.h @@ -0,0 +1,302 @@ +/* + * Copyright 2011 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _CONTACTFIELD_H_ +#define _CONTACTFIELD_H_ + +#include <Bitmap.h> +#include <ContactDefs.h> +#include <Flattenable.h> +#include <Message.h> +#include <ObjectList.h> +#include <String.h> + +#define CONTACT_FIELD_IDENT "contactfield" + +typedef type_code field_type; +typedef type_code field_usage; + +enum { + B_CONTACT_FIELD_TYPE = 'CNFT' +}; + +class BContactFieldVisitor; + + +class BContactField : public virtual BFlattenable { +public: + BContactField(field_type type, + bool autoLabel = false); + virtual ~BContactField(); + + virtual void SetValue(const BString& value) = 0; + virtual const BString& Value() const = 0; + + field_usage GetUsage(int32 i) const; + void AddUsage(field_usage usage); + int32 CountUsages() const; + + virtual void Accept(BContactFieldVisitor* visitor) = 0; + virtual bool IsEqual(BContactField* field); + type_code FieldType() const; + + virtual bool IsHidden() const; + + // those provide a human-friendly + // description of the field + const BString& Label() const; + void SetLabel(const BString& label); + + static const char* SimpleLabel(field_type code); + static const char* ExtendedLabel(BContactField* field); + + virtual bool IsFixedSize() const; + virtual type_code TypeCode() const; + virtual bool AllowsTypeCode(type_code code) const; + virtual ssize_t FlattenedSize() const; + + status_t Flatten(BPositionIO* flatData) const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + status_t Unflatten(type_code code, BPositionIO* flatData); + + static BContactField* Duplicate(BContactField* from); + static BContactField* UnflattenChildClass(const void* data, + ssize_t size); + static BContactField* InstantiateChildClass(type_code type); + virtual status_t CopyDataFrom(BContactField* field); + +// static BObjectList<field_usage>& SupportedUsages(field_type code); +private: +// virtual void* GetUntranslatedData(); +// virtual void SetUntranslatedData(void* data); + +protected: + ssize_t _AddStringToBuffer(BPositionIO* buffer, + const BString& str) const; + BString _ReadStringFromBuffer(BPositionIO* buffer, + ssize_t len = -1); + static void _UpdateLabel(field_usage usage, BString& str); + + BString fLabel; + field_type fType; + //int32 fUsage; + BObjectList<field_usage> fUsages; + + friend class EqualityVisitorBase; + friend class CopyVisitorBase; +}; + + +/*** Contact Fields implementations ***/ + +class BStringContactField : public BContactField { +public: + BStringContactField(field_type type, + const BString& str); + + BStringContactField(field_type type, + const char* str = ""); + + virtual ~BStringContactField(); + + virtual void Accept(BContactFieldVisitor* v); + + virtual bool IsEqual(BContactField* field); + virtual void SetValue(const BString& value); + virtual const BString& Value() const; + + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + + virtual status_t CopyDataFrom(BContactField* field); +private: + struct EqualityVisitor; + struct CopyVisitor; + + BString fValue; +}; + + +// TODO move code into a BAddress object +class BAddressContactField : public BContactField { +public: + BAddressContactField( + field_type type = B_CONTACT_ADDRESS, + BString address = ""); + + virtual ~BAddressContactField(); + + void Accept(BContactFieldVisitor* v); + bool IsEqual(BContactField* field); + + bool IsDeliveryLabel() const; + //void SetDeliveryLabel(bool isLabel); + + // these accept/return a formatted address (see vcard) + virtual void SetValue(const BString& value) ; + virtual const BString& Value() const; + + const BString& Street() const; + const BString& PostalBox() const; + const BString& Neighborhood() const; + const BString& City() const; + const BString& Region() const; + const BString& PostalCode() const; + const BString& Country() const; + + void SetStreet(const BString& street); + void SetPostalBox(const BString& postBox); + void SetNeighborhood(const BString& neighbor); + void SetCity(const BString& city); + void SetRegion(const BString& region); + void SetPostalCode(const BString& postalCode); + void SetCountry(const BString& country); + + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(field_type code, const void* buffer, + ssize_t size); + + virtual status_t CopyDataFrom(BContactField* field); +private: + bool _SplitValue(const BString& str); + void _PopValue(BString& str, BString& value); + + struct EqualityVisitor; + struct CopyVisitor; + + BString fStreet; + BString fPostalBox; + BString fNeighbor; + BString fCity; + BString fRegion; + BString fPostalCode; + BString fCountry; + + mutable BString fValue; + const char* fDivider; +}; + + +class BPhotoContactField : public virtual BContactField { +public: + BPhotoContactField(BBitmap* bitmap = NULL); + virtual ~BPhotoContactField(); + + virtual void Accept(BContactFieldVisitor* v); + virtual bool IsEqual(BContactField* field); + + BBitmap* Photo() const; + void SetPhoto(BBitmap* photo); + + // dunno if the value is useful + virtual void SetValue(const BString& value) ; + virtual const BString& Value() const; + + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + + virtual status_t CopyDataFrom(BContactField* field); + + uint32 PictureType() const; + void SetPictureType(uint32 type); + const BString& PictureMIME() const; + void SetPictureMIME(const BString& mime); +private: + void _CleanUp(); + + struct EqualityVisitor; + struct CopyVisitor; + + BBitmap* fBitmap; +// entry_ref* fEntry; + BString fUrl; + + int32 fPhotoType; + uint32 fPictureType; + BString fPictureMIME; +}; + +/* +// This is a field used to provide raw unknown data +class BRawDataContactField : public virtual BContactField { +public: + BPhotoContactField(BBitmap* bitmap = NULL); + virtual ~BPhotoContactField(); + + virtual void Accept(BContactFieldVisitor* v); + virtual bool IsEqual(BContactField* field); + + const BString& Identifier() const; + + virtual void SetValue(const BString& value); + virtual const BString& Value() const; + + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + + virtual status_t CopyDataFrom(BContactField* field); +private: + void _CleanUp(); + + struct EqualityVisitor; + struct CopyVisitor; + + BString fValue; +}; + + +This will be a special type of field +that will provide a method to define +custom contact fields presumably +using a BMessage or any other type of +internal representation, as preferred. + +This is not intended to be used directly. + +class BCustomContactField : public virtual BContactField { +public: + BCustomContactField(BMessage* message, + const char* type); + virtual ~BCustomContactField(); + + void Accept(BContactFieldVisitor* v); + bool IsEqual(BContactField* field); + + BMessage* AsTemplate(); + + virtual void SetValue(const BString& value) ; + virtual const BString& Value() const; + + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + + virtual BString& CustomLabel() = 0; + +private: + struct EqualityVisitor; +}; + +*/ + +class BContactFieldVisitor { +public: + virtual void Visit(BStringContactField* field) = 0; + virtual void Visit(BAddressContactField* field) = 0; + virtual void Visit(BPhotoContactField* field) = 0; +}; + +typedef BObjectList<BContactField> BContactFieldList; + +#endif // _CONTACTFIELD_H_ diff --git a/headers/private/contact/ContactGroup.h b/headers/private/contact/ContactGroup.h new file mode 100755 index 0000000..172cfbf --- /dev/null +++ b/headers/private/contact/ContactGroup.h @@ -0,0 +1,60 @@ +/* + * Copyright 2011-2012 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _CONTACT_GROUP_H +#define _CONTACT_GROUP_H + +#include <ContactDefs.h> +#include <ContactRef.h> +#include <Flattenable.h> +#include <Message.h> +#include <SupportDefs.h> + +enum { + B_CONTACT_GROUP_TYPE = 'CNGT' +}; + + +class BContactGroup : public BFlattenable { +public: + BContactGroup( + uint32 groupID = B_CONTACT_GROUP_NONE, + bool custom = false); + + ~BContactGroup(); + + virtual bool IsFixedSize() const; + virtual type_code TypeCode() const; + virtual bool AllowsTypeCode(type_code code) const; + virtual ssize_t FlattenedSize() const; + + status_t Flatten(BPositionIO* flatData) const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + status_t Unflatten(type_code code, BPositionIO* flatData); + + status_t InitCheck() const; + + virtual status_t AddContact(BContactRef contact); + virtual status_t RemoveContact(BContactRef contact); + virtual int32 CountContacts() const; + virtual BContactRef ContactAt(int32 index) const; + + const BContactRefList AllContacts() const; + + /*BContactList* ContactsByQuery(BContactQuery* query); + const BContactRefList* ContactsByField(ContactFieldType type, + const char* value = NULL) const;*/ +protected: + BContactRefList fList; +private: + status_t fInitCheck; + uint32 fGroupID; + bool fCustom; +}; + +typedef BObjectList<BContactGroup> BContactGroupList; + +#endif // _CONTACT_GROUP_H diff --git a/headers/private/contact/ContactRef.h b/headers/private/contact/ContactRef.h new file mode 100755 index 0000000..b637628 --- /dev/null +++ b/headers/private/contact/ContactRef.h @@ -0,0 +1,67 @@ +/* + * Copyright 2011 - 2012 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _CONTACT_REF_H +#define _CONTACT_REF_H + +#include <ContactDefs.h> +#include <DataIO.h> +#include <Flattenable.h> +#include <ObjectList.h> +#include <String.h> + +enum { + B_CONTACT_REF_TYPE = 'CRft' +}; + +class BContactRef : public virtual BFlattenable { +public: + BContactRef(int32 id = -1, + uint32 groupID = B_CONTACT_GROUP_NONE, + bool autoFill = false); + + BContactRef(const BContactRef& ref); + + ~BContactRef(); + + virtual bool IsFixedSize() const; + virtual type_code TypeCode() const; + virtual bool AllowsTypeCode(type_code code) const; + virtual ssize_t FlattenedSize() const; + + status_t Flatten(BPositionIO* flatData) const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); + status_t Unflatten(type_code code, BPositionIO* flatData); + + void SetName(const char* name); + void SetNickname(const char* nickname); + void SetEmail(const char* email); + + const char* GetName(); + const char* GetNickname(); + const char* GetEmail(); + int32 GetID(); + uint32 GetGroupID(); + + bool IsEqual(const BContactRef& ref) const; +private: + ssize_t _AddStringToBuffer(BPositionIO* buffer, + const char* str) const; + const char* _ReadStringFromBuffer(BPositionIO* buffer, + ssize_t len = -1); + + BString fName; + BString fNickname; + BString fEmail; + int32 fContactID; + uint32 fGroupID; +}; + +// TODO compositing instead of inheriting + +typedef BObjectList<BContactRef> BContactRefList; + +#endif diff --git a/headers/private/contact/ContactRoster.h b/headers/private/contact/ContactRoster.h new file mode 100755 index 0000000..9d35e7e --- /dev/null +++ b/headers/private/contact/ContactRoster.h @@ -0,0 +1,42 @@ +/* + * Copyright 2011 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef CONTACT_ROSTER_H +#define CONTACT_ROSTER_H + +#include <AddressBook.h> +#include <Contact.h> +#include <ContactGroup.h> + +// Basically, i think this will supply support functions +// and support to register BContacts over the system. + +// The AddressBook will be a special group, that have their objects +// automatically published in /boot/home/peole. I don't think any other +// group should be allowed here (you can add a contact to multiple groups anyway) + +class BContactRoster { +public: + BContactRoster(); + + status_t RegisterContact(BContactRef& contact); + status_t UnregisterContact(BContactRef& contact); + + // if a contact isn't registered the following will return NULL. + BContact* InstantiateContact(BContactRef& ref); + BContactGroup* InstantiateGroup(uint32 id); + + BContactGroupList* GroupsForRef(BContactRef& ref); + + BContactGroupList* RegisteredGroups(); + +// BContactRefList* ContactsByQuery(BContactQuery* query); + + BAddressBook* AddressBook(); + +private: + +}; + +#endif // CONTACT_ROSTER_H diff --git a/headers/private/contact/RawContact.h b/headers/private/contact/RawContact.h new file mode 100755 index 0000000..87702c3 --- /dev/null +++ b/headers/private/contact/RawContact.h @@ -0,0 +1,57 @@ +/* + * Copyright 2011-2012 Haiku Inc. + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef B_RAW_CONTACT_H +#define B_RAW_CONTACT_H + +#include <Archivable.h> +#include <ContactDefs.h> +#include <Message.h> +#include <TranslatorFormats.h> +#include <TranslatorRoster.h> + +class BRawContact : public virtual BArchivable { +public: + // Initialize the RawContact from + // a BMessage if it's valid. + BRawContact(BMessage* data); + + BRawContact(uint32 finalFormat = B_CONTACT_FORMAT, + BPositionIO* destination = NULL); + + // TODO add a entry_ref constructor + + ~BRawContact(); + + status_t Archive(BMessage* data, bool deep) const; + + static BArchivable* Instantiate(BMessage* data); + + status_t InitCheck() const; + + status_t Commit(BMessage* data); + status_t Read(BMessage* data); + int32 FinalFormat() const; + + BPositionIO* Destination() const; + status_t SetDestination(BPositionIO* destination, + bool autoDelete = true); +private: + void _Init(); + void _InitTranslator(); + bool _CheckDestination(BPositionIO* destination); + status_t _FindFormat(); + + BPositionIO* fDest; + + status_t fInitCheck; + // translation stuff + uint32 fFormat; + // the id of the suitable translator + translator_id fTranslatorID; + + BTranslatorRoster* fRoster; +}; + +#endif // B_RAW_CONTACT_H diff --git a/src/add-ons/translators/Jamfile b/src/add-ons/translators/Jamfile index 782bae1..54dddde 100644 --- a/src/add-ons/translators/Jamfile +++ b/src/add-ons/translators/Jamfile @@ -9,6 +9,7 @@ SubInclude HAIKU_TOP src add-ons translators ico ; SubInclude HAIKU_TOP src add-ons translators jpeg ; SubInclude HAIKU_TOP src add-ons translators jpeg2000 ; SubInclude HAIKU_TOP src add-ons translators pcx ; +SubInclude HAIKU_TOP src add-ons translators person ; SubInclude HAIKU_TOP src add-ons translators png ; SubInclude HAIKU_TOP src add-ons translators ppm ; SubInclude HAIKU_TOP src add-ons translators raw ; @@ -18,6 +19,7 @@ SubInclude HAIKU_TOP src add-ons translators shared ; SubInclude HAIKU_TOP src add-ons translators stxt ; SubInclude HAIKU_TOP src add-ons translators tga ; SubInclude HAIKU_TOP src add-ons translators tiff ; +SubInclude HAIKU_TOP src add-ons translators vcard ; SubInclude HAIKU_TOP src add-ons translators webp ; SubInclude HAIKU_TOP src add-ons translators wonderbrush ; SubInclude HAIKU_TOP src add-ons translators icns ; diff --git a/src/add-ons/translators/person/Jamfile b/src/add-ons/translators/person/Jamfile new file mode 100755 index 0000000..56a7d4e --- /dev/null +++ b/src/add-ons/translators/person/Jamfile @@ -0,0 +1,19 @@ +SubDir HAIKU_TOP src add-ons translators person ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders contact ; +UsePrivateHeaders shared ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) shared ] ; + +AddResources PersonTranslator : PersonTranslator.rdef ; + +Translator PersonTranslator : + PersonMain.cpp + PersonTranslator.cpp + PersonView.cpp + : be translation libcontact.so libtranslatorsutils.a libshared.a + $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) + : true +; diff --git a/src/add-ons/translators/person/PersonMain.cpp b/src/add-ons/translators/person/PersonMain.cpp new file mode 100755 index 0000000..d0a85a7 --- /dev/null +++ b/src/add-ons/translators/person/PersonMain.cpp @@ -0,0 +1,17 @@ +#include <Application.h> + +#include "PersonTranslator.h" + +int main() +{ + BApplication app("application/x-vnd.Haiku-PersonTranslator"); + status_t result; + result = LaunchTranslatorWindow(new PersonTranslator, + "VCard Settings", BRect(0, 0, 225, 175)); + if (result == B_OK) { + app.Run(); + return 0; + } else + return 1; +} + diff --git a/src/add-ons/translators/person/PersonTranslator.cpp b/src/add-ons/translators/person/PersonTranslator.cpp new file mode 100755 index 0000000..c6d15c7 --- /dev/null +++ b/src/add-ons/translators/person/PersonTranslator.cpp @@ -0,0 +1,652 @@ +#include "PersonTranslator.h" + +#include <shared/AutoDeleter.h> +#include <BitmapStream.h> +#include <ContactDefs.h> +#include <ContactField.h> +#include <fs_attr.h> +#include <MimeType.h> +#include <Node.h> +#include <NodeInfo.h> +#include <File.h> +#include <ObjectList.h> +#include <Volume.h> +#include <VolumeRoster.h> + +#include <new> +#include <stdio.h> +#include <syslog.h> + +#include "PersonView.h" + +const char* kTranslatorName = "Person Contacts Files"; +const char* kTranslatorInfo = "Translator for Person files"; + +// TODO URGENT clean node attributes before to save + +#define PEOPLE_MIME_TYPE "application/x-person" +#define CONTACT_MIME_TYPE "application/x-hcontact" + +static const translation_format sInputFormats[] = { + { + B_CONTACT_FORMAT, + B_TRANSLATOR_CONTACT, + IN_QUALITY, + IN_CAPABILITY, + CONTACT_MIME_TYPE, + "Haiku binary contact" + }, + { + B_PERSON_FORMAT, + B_TRANSLATOR_CONTACT, + IN_QUALITY, + IN_CAPABILITY, + PEOPLE_MIME_TYPE, + "Person Contact file" + } +}; + +// The output formats that this translator supports. +static const translation_format sOutputFormats[] = { + { + B_CONTACT_FORMAT, + B_TRANSLATOR_CONTACT, + OUT_QUALITY, + OUT_CAPABILITY, + CONTACT_MIME_TYPE, + "Haiku binary contact" + }, + { + B_PERSON_FORMAT, + B_TRANSLATOR_CONTACT, + OUT_QUALITY, + OUT_CAPABILITY, + PEOPLE_MIME_TYPE, + "Person Contact file" + } +}; + +// Default settings for the Translator +static const TranSetting sDefaultSettings[] = { +}; + +const uint32 kNumInputFormats = sizeof(sInputFormats) + / sizeof(translation_format); + +const uint32 kNumOutputFormats = sizeof(sOutputFormats) + / sizeof(translation_format); + +const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) + / sizeof(TranSetting); + +/* +struct Attribute { + const char* attribute; + int32 width; + const char* name; +}; + +// TODO: Add flags in attribute info message to find these. +//static const char* kNameAttribute = "META:name"; +//static const char* kCategoryAttribute = "META:group"; + +struct Attribute sDefaultAttributes[] = { + { B_PEOPLE_NAME, B_TRANSLATE("Contact name") }, + { B_PEOPLE_NICKNAME, B_TRANSLATE("Nickname") }, + { B_PEOPLE_COMPANY, B_TRANSLATE("Company") }, + { B_PEOPLE_ADDRESS, B_TRANSLATE("Address") }, + { B_PEOPLE_CITY, B_TRANSLATE("City") }, + { B_PEOPLE_STATE, B_TRANSLATE("State") }, + { B_PEOPLE_ZIP, B_TRANSLATE("Zip") }, + { B_PEOPLE_COUNTRY, B_TRANSLATE("Country") }, + { B_PEOPLE_HPHONE, B_TRANSLATE("Home phone") }, + { B_PEOPLE_WPHONE, B_TRANSLATE("Work phone") }, + { B_PEOPLE_FAX, B_TRANSLATE("Fax") }, + { B_PEOPLE_EMAIL, B_TRANSLATE("E-mail") }, + { B_PEOPLE_URL, B_TRANSLATE("URL") }, + { B_PEOPLE_GROUP, B_TRANSLATE("Group") }, + { NULL, 0, NULL } +}; +*/ + +struct PersonVisitor : public BContactFieldVisitor { +public: + PersonVisitor(BFile* destination) + : + fDest(destination) + { + } + virtual ~PersonVisitor() + { + } + + virtual void Visit(BStringContactField* field) + { + BString str; + switch (field->FieldType()) { + case B_CONTACT_FORMATTED_NAME: + str << B_PEOPLE_NAME; + break; + case B_CONTACT_NICKNAME: + str << B_PEOPLE_NICKNAME; + break; +// the Person format is not supporting notes +// maybe it's the case to extend the attributes +// case B_CONTACT_NOTE: +// break; + case B_CONTACT_ORGANIZATION: + str << B_PEOPLE_COMPANY; + break; + case B_CONTACT_EMAIL: + str << B_PEOPLE_EMAIL; + break; + case B_CONTACT_URL: + str << B_PEOPLE_URL; + break; + case B_CONTACT_PHONE: + str = _TranslatePhone(field); + break; + +// case B_CONTACT_GROUP: + +// break; + + } + _WriteAttribute(str.String(), field->Value()); + } + + virtual void Visit(BAddressContactField* field) + { + _WriteAttribute(B_PEOPLE_ADDRESS, field->Street()); + _WriteAttribute(B_PEOPLE_CITY, field->City()); + _WriteAttribute(B_PEOPLE_STATE, field->Region()); + _WriteAttribute(B_PEOPLE_ZIP, field->PostalCode()); + _WriteAttribute(B_PEOPLE_COUNTRY, field->Country()); + } + + virtual void Visit(BPhotoContactField* field) + { + BBitmap* picture = field->Photo(); + if (picture) { + fDest->Seek(SEEK_SET, 0); + BBitmapStream stream(picture); + // Detach *our* bitmap from stream to avoid its deletion + // at stream object destruction + stream.DetachBitmap(&picture); + + BTranslatorRoster* roster = BTranslatorRoster::Default(); + roster->Translate(&stream, NULL, NULL, fDest, + field->PictureType(), B_TRANSLATOR_BITMAP, + NULL); + } + } + + void WriteType() + { + BNodeInfo(fDest).SetType(PEOPLE_MIME_TYPE); + } + +private: + + BString _TranslatePhone(BStringContactField* field) + { + // TODO use a map here + if (field == NULL) + return ""; + + BString str; + + if (field->CountUsages() < 1) + return str.Append(B_PEOPLE_HPHONE); + + for (int i = 0; i < field->CountUsages(); i++) { + field_usage usage = field->GetUsage(i); + switch (usage) { + case CONTACT_DATA_OTHER: + case CONTACT_DATA_HOME: + case CONTACT_PHONE_MOBILE: + str.Append(B_PEOPLE_HPHONE); + break; + case CONTACT_DATA_WORK: + str.Append(B_PEOPLE_WPHONE); + break; + case CONTACT_PHONE_FAX: + str.SetTo(B_PEOPLE_FAX); + break; + + case CONTACT_PHONE_VOICE: + break; + + default: + str.SetTo(B_PEOPLE_HPHONE); + } + } + return str; + } + + void _WriteAttribute(const char* attrName, const BString& value) + { + if (strlen(attrName) < 1 || value.Length() < 0) + return; + fDest->WriteAttr(attrName, B_STRING_TYPE, 0, + value.String(), value.Length() + 1); + } + + BFile* fDest; +}; + + +// required by the BaseTranslator class +BTranslator * +make_nth_translator(int32 n, image_id you, uint32 flags, ...) +{ + if (!n) + return new (std::nothrow) PersonTranslator(); + + return NULL; +} + + +PersonTranslator::PersonTranslator() + : + BaseTranslator(kTranslatorName, kTranslatorInfo, PERSON_TRANSLATOR_VERSION, + sInputFormats, kNumInputFormats, sOutputFormats, kNumOutputFormats, + "PersonTranslatorSettings", sDefaultSettings, kNumDefaultSettings, + B_TRANSLATOR_CONTACT, B_PERSON_FORMAT) +{ +} + + +PersonTranslator::~PersonTranslator() +{ +} + + +status_t +PersonTranslator::Identify(BPositionIO* inSource, + const translation_format* inFormat, BMessage* ioExtension, + translator_info* outInfo, uint32 outType) +{ + if (!outType) + outType = B_CONTACT_FORMAT; + + if (outType != B_CONTACT_FORMAT && outType != B_PERSON_FORMAT) + return B_NO_TRANSLATOR; + + BMessage msg; + if (outType == B_PERSON_FORMAT && msg.Unflatten(inSource) == B_OK) { + outInfo->type = B_CONTACT_FORMAT; + outInfo->group = B_TRANSLATOR_CONTACT; + outInfo->quality = IN_QUALITY; + outInfo->capability = IN_CAPABILITY; + snprintf(outInfo->name, sizeof(outInfo->name), kTranslatorName); + strcpy(outInfo->MIME, CONTACT_MIME_TYPE); + return B_OK; + } else if (outType == B_CONTACT_FORMAT) + return _IdentifyPerson(inSource, outInfo); + + return B_NO_TRANSLATOR; +} + + +status_t +PersonTranslator::Translate(BPositionIO* inSource, const translator_info* info, + BMessage* ioExtension, uint32 outType, BPositionIO* outDestination) +{ + if (!outType) + outType = B_CONTACT_FORMAT; + + if (outType != B_CONTACT_FORMAT && outType != B_PERSON_FORMAT) + return B_NO_TRANSLATOR; + + // TODO add no translation + BMessage msg; + if (outType == B_PERSON_FORMAT && msg.Unflatten(inSource) == B_OK) { + if (outDestination == NULL) + return false; + + BFile* file = _PositionToFile(outDestination); + if (file != NULL) + return TranslateContact(&msg, ioExtension, file); + else + return B_ERROR; + } else if (outType == B_CONTACT_FORMAT) + return TranslatePerson(inSource, ioExtension, outDestination); + + return B_NO_TRANSLATOR; +} + + +status_t +PersonTranslator::TranslateContact(BMessage* inSource, + BMessage* ioExtension, BFile* outDestination) +{ + int32 count; + type_code code = B_CONTACT_FIELD_TYPE; + PersonVisitor visitor(outDestination); + + visitor.WriteType(); + + status_t ret = inSource->GetInfo(CONTACT_FIELD_IDENT, &code, &count); + if (ret != B_OK) + return ret; + + for (int i = 0; i < count; i++) { + const void* data; + ssize_t size; + + ret = inSource->FindData(CONTACT_FIELD_IDENT, code, + i, &data, &size); + + BContactField* field = BContactField::UnflattenChildClass(data, size); + if (field == NULL) + return B_ERROR; + + field->Accept(&visitor); + + delete field; + } + return B_OK; +} + + +status_t +PersonTranslator::TranslatePerson(BPositionIO* inSource, + BMessage* ioExtension, BPositionIO* outDestination) +{ + BFile* file = _PositionToFile(inSource); + if (file != NULL) { + ObjectDeleter<BAddressContactField> deleter; + BAddressContactField* addressField + = new BAddressContactField(); + deleter.SetTo(addressField); + + BMessage msg; + char buf[B_ATTR_NAME_LENGTH]; + while (file->GetNextAttrName(buf) == B_OK) { + char* value; + attr_info info; + if (file->GetAttrInfo(buf, &info) != B_OK) + continue; + + value = (char*)calloc(info.size, 1); + if (value == NULL) + return B_NO_MEMORY; + + file->ReadAttr(buf, 0, 0, value, info.size); + + BContactField* field = NULL; + if (strcmp(buf, B_PEOPLE_NAME) == 0) { + field = new BStringContactField( + B_CONTACT_FORMATTED_NAME, value); + } else if (strcmp(buf, B_PEOPLE_NICKNAME) == 0) { + field = new BStringContactField(B_CONTACT_NICKNAME, value); + } else if (strcmp(buf, B_PEOPLE_COMPANY) == 0) { + field = new BStringContactField(B_CONTACT_ORGANIZATION, value); + } else if (strcmp(buf, B_PEOPLE_ADDRESS) == 0) { + addressField->SetStreet(value); + } else if (strcmp(buf, B_PEOPLE_CITY) == 0) { + addressField->SetCity(value); + } else if (strcmp(buf, B_PEOPLE_STATE) == 0) { + addressField->SetRegion(value); + } else if (strcmp(buf, B_PEOPLE_ZIP) == 0) { + addressField->SetPostalCode(value); + } else if (strcmp(buf, B_PEOPLE_COUNTRY) == 0) { + addressField->SetCountry(value); + } else if (strcmp(buf, B_PEOPLE_HPHONE) == 0) { + field = new BStringContactField(B_CONTACT_PHONE, value); + field->AddUsage(CONTACT_DATA_HOME); + } else if (strcmp(buf, B_PEOPLE_WPHONE) == 0) { + field = new BStringContactField(B_CONTACT_PHONE, value); + field->AddUsage(CONTACT_DATA_WORK); + } else if (strcmp(buf, B_PEOPLE_FAX) == 0) { + field = new BStringContactField(B_CONTACT_PHONE, value);; + field->AddUsage(CONTACT_PHONE_FAX); + } else if (strcmp(buf, B_PEOPLE_EMAIL) == 0) { + field = new BStringContactField(B_CONTACT_EMAIL, value); + } else if (strcmp(buf, B_PEOPLE_URL) == 0) { + field = new BStringContactField(B_CONTACT_URL, value); + } else if (strcmp(buf, B_PEOPLE_GROUP) == 0) { + // + } + + if (field != NULL) + _AddField(field, &msg); + + delete field; + free(value); + } + + if (addressField->Value().Length() > 0) + _AddField(addressField, &msg); + else + delete addressField; + + _AddPicture(file, &msg); + + msg.PrintToStream(); + outDestination->Seek(0, SEEK_SET); + msg.Flatten(outDestination); + return B_OK; + } + return B_NO_TRANSLATOR; +} + + +status_t +PersonTranslator::_IdentifyPerson(BPositionIO* inSource, + translator_info* outInfo) +{ + BFile* file = _PositionToFile(inSource); + if (file != NULL) { + char type[B_MIME_TYPE_LENGTH]; + BNodeInfo info(file); + if (info.InitCheck() == B_OK) { + info.GetType(type); + if (strcmp(type, PEOPLE_MIME_TYPE) == 0) { + outInfo->type = B_PERSON_FORMAT; + outInfo->group = B_TRANSLATOR_CONTACT; + outInfo->quality = IN_QUALITY; + outInfo->capability = IN_CAPABILITY; + snprintf(outInfo->name, + sizeof(outInfo->name), kTranslatorName); + + strcpy(outInfo->MIME, PEOPLE_MIME_TYPE); + return B_OK; + } + } + return B_OK; + } + return B_NO_TRANSLATOR; +} + + +BView* +PersonTranslator::NewConfigView(TranslatorSettings *settings) +{ + return new PersonView(BRect(0, 0, 225, 175), + "PersonTranslator Settings", B_FOLLOW_ALL, + B_WILL_DRAW, settings); +} + + +BFile* +PersonTranslator::_PositionToFile(BPositionIO* destination) +{ + BFile* file = dynamic_cast<BFile*>(destination); + if (file != NULL && file->InitCheck() == B_OK) + return file; + else + return NULL; +} + + +status_t +PersonTranslator::_AddField(BContactField* field, BMessage* msg) +{ + if (field != NULL) { + ssize_t size = field->FlattenedSize(); + + void* buffer = new char [size]; + if (buffer == NULL) + return B_NO_MEMORY; + MemoryDeleter deleter(buffer); + + status_t ret = field->Flatten(buffer, size); + if (ret != B_OK) + return ret; + + ret = msg->AddData(CONTACT_FIELD_IDENT, field->TypeCode(), + buffer, size, false); + if (ret != B_OK) + return ret; + + return B_OK; + } + return B_ERROR; +} + + +status_t +PersonTranslator::_AddPicture(BFile* file, BMessage* msg) +{ + off_t fileSize; + status_t status = file->GetSize(&fileSize); + if (status != B_OK) + return B_ERROR; + + if (fileSize < 1) + return B_ERROR; + + translator_info info; + memset(&info, 0, sizeof(translator_info)); + BMessage ioExtension; + + BTranslatorRoster* roster = BTranslatorRoster::Default(); + + if (roster == NULL) + return B_NO_MEMORY; + + status = roster->Identify(file, &ioExtension, &info, 0, NULL, + B_TRANSLATOR_BITMAP); + + BBitmapStream stream; + + if (status == B_OK) { + status = roster->Translate(file, &info, &ioExtension, &stream, + B_TRANSLATOR_BITMAP); + } + if (status != B_OK) + return status; + + BBitmap* picture = NULL; + if (stream.DetachBitmap(&picture) != B_OK + || picture == NULL) + return B_ERROR; + + BPhotoContactField* field = new BPhotoContactField(picture); + + // Remember image format so we could store using the same + //field->SetMIMEType(info.MIME); + field->SetPictureType(info.type); + + return _AddField(field, msg); +} + + +// Read attributes from person mime type. If it does not exist, +// or if it contains no attribute definitions, install a "clean" +// person mime type from the hard-coded default attributes. +/* +status_t +PersonTranslator::_InitAttr() +{ + bool valid = false; + BMimeType mime(PEOPLE_MIMETYPE); + if (mime.IsInstalled()) { + BMessage info; + if (mime.GetAttrInfo(&info) == B_NO_ERROR) { + int32 index = 0; + while (true) { + int32 type; + if (info.FindInt32("attr:type", index, &type) != B_OK) + break; + bool editable; + if (info.FindBool("attr:editable", index, &editable) != B_OK) + break; + + // TODO: Support other types besides string attributes. + if (type != B_STRING_TYPE || !editable) + break; + + Attribute* attribute = new Attribute(); + ObjectDeleter<Attribute> deleter(attribute); + if (info.FindString("attr:public_name", index, + &attribute->name) != B_OK) { + break; + } + if (info.FindString("attr:name", index, + &attribute->attribute) != B_OK) { + break; + } + + if (!fAttributes.AddItem(attribute)) + break; + + deleter.Detach(); + index++; + } + } + if (fAttributes.CountItems() == 0) { + valid = false; + mime.Delete(); + } else + valid = true; + } + if (!valid) { + mime.Install(); + mime.SetShortDescription(B_TRANSLATE_WITH_CONTEXT("Person", + "Short mimetype description")); + mime.SetLongDescription(B_TRANSLATE_WITH_CONTEXT( + "Contact information for a person.", + "Long mimetype description")); + mime.SetIcon(kPersonIcon, sizeof(kPersonIcon)); + mime.SetPreferredApp(APP_SIG); + + // add default person fields to meta-mime type + BMessage fields; + for (int32 i = 0; sDefaultAttributes[i].attribute; i++) { + fields.AddString("attr:public_name", sDefaultAttributes[i].name); + fields.AddString("attr:name", sDefaultAttributes[i].attribute); + fields.AddInt32("attr:type", B_STRING_TYPE); + fields.AddBool("attr:viewable", true); + fields.AddBool("attr:editable", true); + fields.AddInt32("attr:width", sDefaultAttributes[i].width); + fields.AddInt32("attr:alignment", B_ALIGN_LEFT); + fields.AddBool("attr:extra", false); + + // Add the default attribute to the attribute list, too. + Attribute* attribute = new Attribute(); + attribute->name = sDefaultAttributes[i].name; + attribute->attribute = sDefaultAttributes[i].attribute; + if (!fAttributes.AddItem(attribute)) + delete attribute; + } + + mime.SetAttrInfo(&fields); + } + + // create indices on all volumes for the found attributes. + + int32 count = fAttributes.CountItems(); + BVolumeRoster volumeRoster; + BVolume volume; + while (volumeRoster.GetNextVolume(&volume) == B_OK) { + for (int32 i = 0; i < count; i++) { + Attribute* attribute = fAttributes.ItemAt(i); + fs_create_index(volume.Device(), attribute->attribute, + B_STRING_TYPE, 0); + } + } +} +*/ diff --git a/src/add-ons/translators/person/PersonTranslator.h b/src/add-ons/translators/person/PersonTranslator.h new file mode 100755 index 0000000..fcc908b --- /dev/null +++ b/src/add-ons/translators/person/PersonTranslator.h @@ -0,0 +1,87 @@ +/* + * Copyright 2010 Dario Casalinuovo <your@email.address> + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _PERSON_TRANSLATOR_H +#define _PERSON_TRANSLATOR_H + +#include <ContactDefs.h> +#include <Translator.h> +#include <TranslatorFormats.h> +#include <TranslationDefs.h> + +#include "BaseTranslator.h" +#include "PersonView.h" +#include "TranslatorSettings.h" +#include "TranslatorWindow.h" + +#define PERSON_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(0,1,0) +#define IN_QUALITY 1 +#define IN_CAPABILITY 1 +#define OUT_QUALITY 1 +#define OUT_CAPABILITY 1 + +#define B_PEOPLE_NAME "META:name" +#define B_PEOPLE_NICKNAME "META:nickname" +#define B_PEOPLE_COMPANY "META:company" +#define B_PEOPLE_ADDRESS "META:address" +#define B_PEOPLE_CITY "META:city" +#define B_PEOPLE_STATE "META:state" +#define B_PEOPLE_ZIP "META:zip" +#define B_PEOPLE_COUNTRY "META:country" +#define B_PEOPLE_HPHONE "META:hphone" +#define B_PEOPLE_WPHONE "META:wphone" +#define B_PEOPLE_FAX "META:fax" +#define B_PEOPLE_EMAIL "META:email" +#define B_PEOPLE_URL "META:url" +#define B_PEOPLE_GROUP "META:group" + +class BFile; +class BContactField; + +class PersonTranslator : public BaseTranslator { +public: + PersonTranslator(); + + virtual status_t Identify(BPositionIO* inSource, + const translation_format* inFormat, BMessage* ioExtension, + translator_info* outInfo, uint32 outType); + // determines whether or not this translator can convert the + // data in inSource to the type outType + + virtual status_t Translate(BPositionIO* inSource, + const translator_info* inInfo, BMessage* ioExtension, + uint32 outType, BPositionIO* outDestination); + // this function is the whole point of the Translation Kit, + // it translates the data in inSource to outDestination + // using the format outType + + status_t TranslateContact(BMessage* inSource, + BMessage* ioExtension, BFile* outDestination); + + status_t TranslatePerson(BPositionIO* inSource, + BMessage* ioExtension, BPositionIO* outDestination); + + virtual BView* NewConfigView(TranslatorSettings* settings); + +protected: + virtual ~PersonTranslator(); + // this is protected because the object is deleted by the + // Release() function instead of being deleted directly by + // the user + +private: + status_t _IdentifyPerson(BPositionIO* inSource, + translator_info* outInfo); + + BFile* _PositionToFile(BPositionIO* destination); + status_t _AddField(BContactField* field, BMessage* msg); + + status_t _InitializeAttributes(BFile* file); + status_t _CheckPerson(BPositionIO* people); + status_t _AddPicture(BFile* file, BMessage* msg); + + // status_t _InitAttr(); +}; + +#endif // #ifndef _Person_TRANSLATOR_H diff --git a/src/add-ons/translators/person/PersonTranslator.rdef b/src/add-ons/translators/person/PersonTranslator.rdef new file mode 100755 index 0000000..b425cfc --- /dev/null +++ b/src/add-ons/translators/person/PersonTranslator.rdef @@ -0,0 +1,11 @@ +resource app_signature "application/x-vnd.Haiku-PersonTranslator"; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + variety = 0, + internal = 0, + short_info = "1.0.0", + long_info = "Haiku Person format Translator." +}; diff --git a/src/add-ons/translators/person/PersonView.cpp b/src/add-ons/translators/person/PersonView.cpp new file mode 100755 index 0000000..2199664 --- /dev/null +++ b/src/add-ons/translators/person/PersonView.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2011, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * Michael Wilber + * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + */ + +/*! A view with information about the PersonTranslator. */ + + +#include "PersonView.h" +#include "PersonTranslator.h" + +#include <StringView.h> + +#include <stdio.h> + + +PersonView::PersonView(const BRect &frame, const char *name, uint32 resizeMode, + uint32 flags, TranslatorSettings *settings) + : + BView(frame, name, resizeMode, flags) +{ + // TODO use layouts + fSettings = settings; + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + font_height fontHeight; + be_bold_font->GetHeight(&fontHeight); + float height = fontHeight.descent + fontHeight.ascent + fontHeight.leading; + + BRect rect(10, 10, 200, 10 + height); + BStringView *stringView = new BStringView(rect, "title", + "Person files translator"); + + stringView->SetFont(be_bold_font); + stringView->ResizeToPreferred(); + AddChild(stringView); + + float maxWidth = stringView->Bounds().Width(); + + rect.OffsetBy(0, height + 10); + char version[256]; + + snprintf(version, sizeof(version), "Version %d.%d.%d, %s", + int(PERSON_TRANSLATOR_VERSION), + int(PERSON_TRANSLATOR_VERSION), + int(PERSON_TRANSLATOR_VERSION), + __DATE__); + + stringView = new BStringView(rect, "version", version); + stringView->ResizeToPreferred(); + AddChild(stringView); + + if (stringView->Bounds().Width() > maxWidth) + maxWidth = stringView->Bounds().Width(); + + GetFontHeight(&fontHeight); + height = fontHeight.descent + fontHeight.ascent + fontHeight.leading; + + rect.OffsetBy(0, height + 5); + stringView = new BStringView(rect, "Copyright", + B_UTF8_COPYRIGHT "2011 Haiku Inc."); + + stringView->ResizeToPreferred(); + AddChild(stringView); + + if (maxWidth + 20 > Bounds().Width()) + ResizeTo(maxWidth + 20, Bounds().Height()); +} + + +PersonView::~PersonView() +{ + fSettings->Release(); +} diff --git a/src/add-ons/translators/person/PersonView.h b/src/add-ons/translators/person/PersonView.h new file mode 100755 index 0000000..2c5d0b1 --- /dev/null +++ b/src/add-ons/translators/person/PersonView.h @@ -0,0 +1,18 @@ +#ifndef PERSON_VIEW_H +#define PERSON_VIEW_H + +#include <View.h> + +#include "TranslatorSettings.h" + +class PersonView : public BView { + public: + PersonView(const BRect& frame, const char* name, uint32 resizeMode, + uint32 flags, TranslatorSettings* settings); + virtual ~PersonView(); + + private: + TranslatorSettings *fSettings; +}; + +#endif // #ifndef Person_VIEW_H diff --git a/src/add-ons/translators/vcard/Jamfile b/src/add-ons/translators/vcard/Jamfile new file mode 100755 index 0000000..ce27dc5 --- /dev/null +++ b/src/add-ons/translators/vcard/Jamfile @@ -0,0 +1,21 @@ +SubDir HAIKU_TOP src add-ons translators vcard ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders contact ; +UsePrivateHeaders shared ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) shared ] ; + +AddResources VCardTranslator : VCardTranslator.rdef ; + +Translator VCardTranslator : + VCardMain.cpp + VCardParser.cpp + VCardTranslator.cpp + VCardView.cpp + cardparser.c + : be translation libcontact.so libtranslatorsutils.a libshared.a + $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) + : true +; diff --git a/src/add-ons/translators/vcard/VCardMain.cpp b/src/add-ons/translators/vcard/VCardMain.cpp new file mode 100755 index 0000000..21508f0 --- /dev/null +++ b/src/add-ons/translators/vcard/VCardMain.cpp @@ -0,0 +1,17 @@ +#include <Application.h> + +#include "VCardTranslator.h" + +int main() +{ + BApplication app("application/x-vnd.Haiku-VCardTranslator"); + status_t result; + result = LaunchTranslatorWindow(new VCardTranslator, + "VCard Settings", BRect(0, 0, 225, 175)); + if (result == B_OK) { + app.Run(); + return 0; + } else + return 1; +} + diff --git a/src/add-ons/translators/vcard/VCardParser.cpp b/src/add-ons/translators/vcard/VCardParser.cpp new file mode 100755 index 0000000..e1f49ba --- /dev/null +++ b/src/add-ons/translators/vcard/VCardParser.cpp @@ -0,0 +1,212 @@ +/* + * Copyright 2011-2012 Dario Casalinuovo + * All rights reserved. Distributed under the terms of the MIT license. + */ +#include "VCardParser.h" + +#include <stdio.h> + + +// c++ bindings to the c API +void HandleProp(void* userData, + const CARD_Char* propName, const CARD_Char** params) +{ + VCardParser* owner = (VCardParser*) userData; + owner->PropHandler(propName, params); +} + + +void +HandleData(void* userData, const CARD_Char* data, int len) +{ + VCardParser* owner = (VCardParser*) userData; + owner->DataHandler(data, len); +} + + +VCardParser::VCardParser(BPositionIO* from, bool onlyCheck) + : + fFrom(from), + fOnlyCheck(onlyCheck), + fCheck(false), + fBegin(false), + fEnd(false), + fLatestParams(true), + fList(true), + fFieldsMap(), + fUsagesMap() +{ + // intialize the parser + fParser = CARD_ParserCreate(NULL); + CARD_SetUserData(fParser, this); + CARD_SetPropHandler(fParser, HandleProp); + CARD_SetDataHandler(fParser, HandleData); + + // fill the map with the values to translate from VCard to BContact + for (int i = 0; gFieldsMap[i].key != NULL; i++) + fFieldsMap.Put(HashString(gFieldsMap[i].key), gFieldsMap[i].type); + + for (int i = 0; gUsagesMap[i].key != NULL; i++) + fUsagesMap.Put(HashString(gUsagesMap[i].key), gUsagesMap[i].usage); +} + + +VCardParser::~VCardParser() +{ + // free the object + CARD_ParserFree(fParser); +} + + +status_t +VCardParser::Parse() +{ + if (fFrom == NULL) + return B_ERROR; + + char buf[512]; + ssize_t read; + read = fFrom->Read(buf, sizeof(buf)); + + while (read > 0) { + int err = CARD_Parse(fParser, buf, read, false); + if (err == 0) + return B_ERROR; + read = fFrom->Read(buf, sizeof(buf)); + } + // end of the parse + CARD_Parse(fParser, NULL, 0, true); + return B_OK; +} + + +bool +VCardParser::HasBegin() +{ + return fBegin && fCheck; +} + + +bool +VCardParser::HasEnd() +{ + return fEnd && fCheck; +} + + +int32 +VCardParser::CountProperties() +{ + return fList.CountItems(); +} + + +BContactField* +VCardParser::PropertyAt(int32 i) +{ + return fList.ItemAt(i); +} + + +BContactFieldList* +VCardParser::Properties() +{ + return &fList; +} + + +void +VCardParser::PropHandler(const CARD_Char* propName, const CARD_Char** params) +{ + if (!fBegin && strcasecmp(propName, "BEGIN") == 0) { + fBegin = true; + return; + } + + // if we don't have a BEGIN:VCARD field + // we just don't accept the following data. + if (!fBegin) + return; + + if (strcasecmp(propName, "END") == 0) { + fEnd = true; + return; + } + + if (!fCheck) + return; + + if (fOnlyCheck) + return; + + printf("-----%s\n", propName); + + fLatestProp.SetTo(propName); + + fLatestParams.MakeEmpty(); + for (int i = 0; params[i] != NULL; i++) { + fLatestParams.AddItem(new BString(params[i])); + if (params[i+1] == NULL) + i++; + } +} + + +void +VCardParser::DataHandler(const CARD_Char* data, int len) +{ + BString str(data, len); + + if (fBegin && !fCheck) { + if (len > 0) { + if (str.ICompare("VCARD") == 0) + fCheck = true; + return; + } + } else if (fEnd) { + if (len > 0) { + if (str.ICompare("VCARD") == 0) + fCheck = true; + else + fCheck = false; + } + return; + } + + if (fOnlyCheck) + return; + + if (len == 0) + return; + + str = ""; + for (int i = 0; i < len; i++) { + CARD_Char c = data[i]; + if (c == '\r' || c == '\n') + continue; + else if (c >= ' ' && c <= '~') + str.Append((char)c, 1); + } + + field_type type = fFieldsMap.Get(HashString(fLatestProp)); + BContactField* field = BContactField::InstantiateChildClass(type); + + if (field != NULL) { + _TranslateUsage(field); + fList.AddItem(field); + field->SetValue(str); + //printf("data %s\n", field->Value().String()); + } +} + + +void +VCardParser::_TranslateUsage(BContactField* field) { + int count = fLatestParams.CountItems(); + for (int i = 0; i < count; i++) { + BString param = fLatestParams.ItemAt(i)->String(); + field_usage usage = fUsagesMap.Get(HashString(param)); + field->AddUsage(usage); + //printf("----Param : %s\n", fLatestParams.ItemAt(i)->String()); + } +} diff --git a/src/add-ons/translators/vcard/VCardParser.h b/src/add-ons/translators/vcard/VCardParser.h new file mode 100755 index 0000000..501c231 --- /dev/null +++ b/src/add-ons/translators/vcard/VCardParser.h @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2012 Dario Casalinuovo + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _VCARD_PARSER_H +#define _VCARD_PARSER_H + +#include <ContactDefs.h> +#include <ContactField.h> + +#include <ObjectList.h> +#include <SupportDefs.h> + +#include "cardparser.h" +#include "VCardParserDefs.h" + +typedef BObjectList<BString> StringList; + +class VCardParser { +public: + VCardParser(BPositionIO* from, bool check = false); + virtual ~VCardParser(); + + status_t Parse(); + + bool HasBegin(); + bool HasEnd(); + + const char* Version(); + + void PropHandler(const CARD_Char* propName, + const CARD_Char** params); + void DataHandler(const CARD_Char* data, int len); + + int32 CountProperties(); + BContactField* PropertyAt(int32 i); + // rename Fields + BContactFieldList* Properties(); +private: + void _TranslateUsage(BContactField* field); + + CARD_Parser fParser; + BPositionIO* fFrom; + + bool fOnlyCheck; + bool fCheck; + bool fBegin; + bool fEnd; + BString fLatestProp; + StringList fLatestParams; + + BContactFieldList fList; + + InFieldsMap fFieldsMap; + InUsagesMap fUsagesMap; +}; + +#endif // _H diff --git a/src/add-ons/translators/vcard/VCardParserDefs.h b/src/add-ons/translators/vcard/VCardParserDefs.h new file mode 100755 index 0000000..0f96d41 --- /dev/null +++ b/src/add-ons/translators/vcard/VCardParserDefs.h @@ -0,0 +1,197 @@ +/* + * Copyright 2010-2012 Casalinuovo Dario + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _VCARD_PARSER_DEFS_H +#define _VCARD_PARSER_DEFS_H + +#include <ContactDefs.h> +#include <ContactField.h> +#include <HashMap.h> +#include <HashString.h> + +using BPrivate::HashMap; +using BPrivate::HashString; + +// VCard 2.1 standard fields + +#define VCARD_ADDRESS "ADR" +#define VCARD_BIRTHDAY "BDAY" +#define VCARD_DELIVERY_LABEL "LABEL" +#define VCARD_EMAIL "EMAIL" +#define VCARD_FORMATTED_NAME "FN" +#define VCARD_REVISION "REV" +#define VCARD_SOUND "SOUND" +#define VCARD_TELEPHONE "TEL" +#define VCARD_TIME_ZONE "TZ" +#define VCARD_TITLE "TITLE" +#define VCARD_URL "URL" +#define VCARD_GEOGRAPHIC_POSITION "GEO" +#define VCARD_NAME "N" +#define VCARD_NICKNAME "NICKNAME" +#define VCARD_NOTE "NOTE" +#define VCARD_ORGANIZATION "ORG" +#define VCARD_PHOTO "PHOTO" +#define VCARD_VERSION "VERSION" + +// Currently unsupported standard fields + +#define VCARD_AGENT "AGENT" +#define VCARD_CATEGORIES "CATEGORIES" +#define VCARD_CLASS "CLASS" +#define VCARD_ROLE "ROLE" +#define VCARD_SORT_STRING "SORT-STRING" +#define VCARD_KEY "KEY" +#define VCARD_LOGO "LOGO" +#define VCARD_MAILER "MAILER" +#define VCARD_PRODUCT_IDENTIFIER "PRODID" + +// Custom Haiku OS extensions + +#define X_VCARD_IM "X-HAIKU-IM" +#define X_VCARD_PROTOCOLS "X-HAIKU-PROTOCOLS" +#define X_VCARD_SIMPLE_GROUP "X-HAIKU-SIMPLEGROUP" +#define X_VCARD_GROUP "X-HAIKU-GROUP" +#define X_VCARD_UID "X-HAIKU-UID" + +// Non-Haiku custom fields supported + +#define X_VCARD_GENDER "X-GENDER" +#define X_VCARD_ASSISTANT "X-ASSISTANT" +#define X_VCARD_MANAGER "X-MANAGER" +#define X_VCARD_SPOUSE "X-SPOUSE" + +#define X_VCARD_AIM "X-AIM" +#define X_VCARD_ICQ "X-ICQ" +#define X_VCARD_MSN "X-MSN" +#define X_VCARD_JABBER "X-JABBER" +#define X_VCARD_YAHOO "X-YAHOO" +#define X_VCARD_TWITTER "X-TWITTER" +#define X_VCARD_SKYPE "X-SKYPE" +#define X_VCARD_GADUGADU "X-GADUGADU" +#define X_VCARD_GROUPWISE "X-GROUPWISE" + +// Unsupported non-Haiku custom fields + +#define X_VCARD_SKYPE_USERNAME "X-SKYPE-USERNAME" + +#define X_VCARD_PHONETIC_LAST_NAME "X-PHONETIC-LAST-NAME" +#define X_VCARD_PHONETIC_FIRST_NAME "X-PHONETIC-FIRST-NAME" + +// VCard <-> BContact defs +struct fieldMap { + const char* key; + field_type type; + int op; +}; + +struct usageMap { + const char* key; + field_usage usage; +}; +// This is a translation table +// that will be used to fill a map with the purpose to convert +// fields from BContact to VCard. +static fieldMap gFieldsMap[] = { + // Standard VCard 2.0 fields + { VCARD_ADDRESS, B_CONTACT_ADDRESS }, + { X_VCARD_ASSISTANT, B_CONTACT_ASSISTANT }, + { VCARD_BIRTHDAY, B_CONTACT_BIRTHDAY }, + { VCARD_DELIVERY_LABEL, B_CONTACT_DELIVERY_LABEL }, + { VCARD_EMAIL, B_CONTACT_EMAIL }, + { VCARD_FORMATTED_NAME, B_CONTACT_FORMATTED_NAME }, + { X_VCARD_GENDER, B_CONTACT_GENDER }, + { VCARD_GEOGRAPHIC_POSITION, B_CONTACT_GEO }, + { X_VCARD_MANAGER, B_CONTACT_MANAGER }, + { VCARD_NAME, B_CONTACT_NAME }, + { VCARD_NICKNAME, B_CONTACT_NICKNAME }, + { VCARD_NOTE, B_CONTACT_NOTE }, + { VCARD_ORGANIZATION, B_CONTACT_ORGANIZATION }, + { VCARD_TELEPHONE, B_CONTACT_PHONE }, + { VCARD_PHOTO, B_CONTACT_PHOTO }, + { X_VCARD_SPOUSE, B_CONTACT_SPOUSE }, + { VCARD_SOUND, B_CONTACT_SOUND }, + { VCARD_TIME_ZONE, B_CONTACT_TIME_ZONE }, + { VCARD_TITLE, B_CONTACT_TITLE }, + { VCARD_URL, B_CONTACT_URL }, + { VCARD_REVISION, B_CONTACT_REV }, + + // Custom VCard Haiku fields + { X_VCARD_IM, B_CONTACT_IM }, + { X_VCARD_PROTOCOLS, B_CONTACT_PROTOCOLS }, + { X_VCARD_SIMPLE_GROUP, B_CONTACT_SIMPLE_GROUP }, + { X_VCARD_GROUP, B_CONTACT_GROUP }, + { X_VCARD_UID, B_CONTACT_UID }, + + { NULL, 0 } +}; + +static usageMap gUsagesMap[] = { + // Standard vcard 2.0 usages + //{ "", CONTACT_DATA_CUSTOM }, + //{ "" , CONTACT_DATA_OTHER }, + { "HOME", CONTACT_DATA_HOME }, + { "WORK", CONTACT_DATA_WORK }, + { "PREF", CONTACT_DATA_PREFERRED }, + + { "" , CONTACT_NAME_FAMILY }, + { "" , CONTACT_NAME_GIVEN }, + { "" , CONTACT_NAME_MIDDLE }, + { "" , CONTACT_NAME_SUFFIX }, + + { "" , CONTACT_NICKNAME_DEFAULT }, + { "" , CONTACT_NICKNAME_MAIDEN }, + { "" , CONTACT_NICKNAME_SHORT_NAME }, + { "" , CONTACT_NICKNAME_INITIALS }, + + { "" , CONTACT_EMAIL_MOBILE }, + { "INTERNET" , CONTACT_EMAIL_INTERNET }, + + { "CELL", CONTACT_PHONE_MOBILE }, + { "FAX", CONTACT_PHONE_FAX }, + { "PAGER" , CONTACT_PHONE_PAGER }, + { "" , CONTACT_PHONE_CALLBACK }, + { "CAR" , CONTACT_PHONE_CAR }, + { "ISDN" , CONTACT_PHONE_ISDN }, + { "" , CONTACT_PHONE_RADIO }, + { "" , CONTACT_PHONE_TELEX }, + { "" , CONTACT_PHONE_TTY_TDD }, + { "MODEM" , CONTACT_PHONE_MODEM }, + { "" , CONTACT_PHONE_ASSISTANT }, + { "VIDEO" , CONTACT_PHONE_VIDEO }, + { "VOICE" , CONTACT_PHONE_VOICE }, + { "MSG", CONTACT_PHONE_MSG }, + + { "" , CONTACT_PHOTO_BITMAP }, + + { "DOM" , CONTACT_ADDRESS_DOM }, + { "INTL" , CONTACT_ADDRESS_INTL }, + { "POSTAL" , CONTACT_ADDRESS_POSTAL }, + { "PARCEL" , CONTACT_ADDRESS_PARCEL }, + + { "WAVE" , CONTACT_SOUND_WAVE }, + { "PCM" , CONTACT_SOUND_PCM }, + { "AIFF" , CONTACT_SOUND_AIFF }, + { "" , CONTACT_SOUND_MP3 }, + { "" , CONTACT_SOUND_OGG }, + + { "X-VCARD-AIM" , CONTACT_IM_AIM }, + { "X-VCARD-ICQ" , CONTACT_IM_ICQ }, + { "X-VCARD-MSN" , CONTACT_IM_MSN }, + { "X-VCARD-JABBER" , CONTACT_IM_JABBER }, + { "X-VCARD-YAHOO" , CONTACT_IM_YAHOO }, + { "X-VCARD-TWITTER" , CONTACT_IM_TWITTER }, + { "X-VCARD-SKYPE" , CONTACT_IM_SKYPE }, + { "X-VCARD-GADUGADU" , CONTACT_IM_GADUGADU }, + { "X-VCARD-GROUPWISE" , CONTACT_IM_GROUPWISE }, + { NULL, 0 } + }; + +// Translation map typedefs +typedef HashMap<HashKey32<field_type>, BString> OutFieldsMap; +typedef HashMap<HashKey32<field_usage>, BString> OutUsagesMap; + +typedef HashMap<HashString, field_type> InFieldsMap; +typedef HashMap<HashString, field_usage> InUsagesMap; + +#endif diff --git a/src/add-ons/translators/vcard/VCardTranslator.cpp b/src/add-ons/translators/vcard/VCardTranslator.cpp new file mode 100755 index 0000000..eb741b1 --- /dev/null +++ b/src/add-ons/translators/vcard/VCardTranslator.cpp @@ -0,0 +1,313 @@ +#include "VCardTranslator.h" + +#include <shared/AutoDeleter.h> +#include <ObjectList.h> + +#include <new> +#include <stdio.h> +#include <syslog.h> + +#include "VCardParser.h" + + +const char* kTranslatorName = "VCardTranslator"; +const char* kTranslatorInfo = "Translator for VCard files"; + +#define VCARD_MIME_TYPE "text/x-vCard" +#define CONTACT_MIME_TYPE "application/x-hcontact" + +static const translation_format sInputFormats[] = { + { + B_CONTACT_FORMAT, + B_TRANSLATOR_CONTACT, + IN_QUALITY, + IN_CAPABILITY, + CONTACT_MIME_TYPE, + "Haiku binary contact" + }, + { + B_VCARD_FORMAT , + B_TRANSLATOR_CONTACT, + IN_QUALITY, + IN_CAPABILITY, + VCARD_MIME_TYPE, + "vCard Contact file" + } +}; + +// The output formats that this translator supports. +static const translation_format sOutputFormats[] = { + { + B_CONTACT_FORMAT, + B_TRANSLATOR_CONTACT, + OUT_QUALITY, + OUT_CAPABILITY, + CONTACT_MIME_TYPE, + "Haiku binary contact" + }, + { + B_VCARD_FORMAT , + B_TRANSLATOR_CONTACT, + OUT_QUALITY, + OUT_CAPABILITY, + VCARD_MIME_TYPE, + "vCard Contact file" + } +}; + +// Default settings for the Translator +static const TranSetting sDefaultSettings[] = { +}; + +const uint32 kNumInputFormats = sizeof(sInputFormats) + / sizeof(translation_format); +const uint32 kNumOutputFormats = sizeof(sOutputFormats) + / sizeof(translation_format); +const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) + / sizeof(TranSetting); + +// required by the BaseTranslator class +BTranslator * +make_nth_translator(int32 n, image_id you, uint32 flags, ...) +{ + if (!n) + return new (std::nothrow) VCardTranslator(); + + return NULL; +} + + +VCardTranslator::VCardTranslator() + : + BaseTranslator(kTranslatorName, kTranslatorInfo, VCARD_TRANSLATOR_VERSION, + sInputFormats, kNumInputFormats, sOutputFormats, kNumOutputFormats, + "VCardTranslatorSettings", sDefaultSettings, kNumDefaultSettings, + B_TRANSLATOR_CONTACT, B_VCARD_FORMAT) +{ + for (int i = 0; gFieldsMap[i].key != NULL; i++) + fFieldsMap.Put(HashKey32<field_type>(gFieldsMap[i].type), + BString(gFieldsMap[i].key)); + + for (int i = 0; gUsagesMap[i].key != NULL; i++) + fFieldsMap.Put(HashKey32<field_usage>(gUsagesMap[i].usage), + BString(gUsagesMap[i].key)); +} + + +VCardTranslator::~VCardTranslator() +{ +} + + +status_t +VCardTranslator::Identify(BPositionIO* inSource, + const translation_format* inFormat, BMessage* ioExtension, + translator_info* outInfo, uint32 outType) +{ + if (!outType) + outType = B_CONTACT_FORMAT; + + if (outType != B_CONTACT_FORMAT && outType != B_VCARD_FORMAT) + return B_NO_TRANSLATOR; + + BMessage msg; + if (outType == B_VCARD_FORMAT && msg.Unflatten(inSource) == B_OK) { + msg.PrintToStream(); + outInfo->type = B_CONTACT_FORMAT; + outInfo->group = B_TRANSLATOR_CONTACT; + outInfo->quality = IN_QUALITY; + outInfo->capability = IN_CAPABILITY; + snprintf(outInfo->name, sizeof(outInfo->name), kTranslatorName); + strcpy(outInfo->MIME, CONTACT_MIME_TYPE); + return B_OK; + } else if (outType == B_CONTACT_FORMAT) + return _IdentifyVCard(inSource, outInfo); + + return B_NO_TRANSLATOR; +} + + +status_t +VCardTranslator::Translate(BPositionIO* inSource, const translator_info* info, + BMessage* ioExtension, uint32 outType, BPositionIO* outDestination) +{ + if (!outType) + outType = B_CONTACT_FORMAT; + + if (outType != B_CONTACT_FORMAT && outType != B_VCARD_FORMAT) + return B_NO_TRANSLATOR; + + // add no translation + BMessage msg; + if (outType == B_VCARD_FORMAT && msg.Unflatten(inSource) == B_OK) + return TranslateContact(&msg, ioExtension, outDestination); + else if (outType == B_CONTACT_FORMAT) + return TranslateVCard(inSource, ioExtension, outDestination); + + return B_ERROR; +} + + +status_t +VCardTranslator::TranslateContact(BMessage* inSource, + BMessage* ioExtension, BPositionIO* outDestination) +{ + int32 count = 0; + type_code code = B_CONTACT_FIELD_TYPE; + + _WriteBegin(outDestination); + + status_t ret = inSource->GetInfo(CONTACT_FIELD_IDENT, &code, &count); + if (ret != B_OK) + return ret; + + for (int i = 0; i < count; i++) { [ *** diff truncated: 8985 lines dropped *** ] ############################################################################ Commit: 79d124525e7536819aa456eb39b53a4f87f01f8b Author: Barrett <b.vitruvio@xxxxxxxxx> Date: Mon Jul 29 16:18:13 2013 UTC Committer: Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> Commit-Date: Sun May 25 01:24:10 2014 UTC Removed unneeded files. ---------------------------------------------------------------------------- ############################################################################ Commit: c314ba74692fe895a94fdd1519bcb07c63654bcd Author: Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> Date: Sun May 25 10:55:40 2014 UTC Build system changes for contact kit in a packaged world. ---------------------------------------------------------------------------- ############################################################################ Commit: afaab8c55db06c1d075655993c4127867542dd6d Author: Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> Date: Sun May 25 15:04:11 2014 UTC Also add VCard translator for a package managed world. ----------------------------------------------------------------------------