1 /* 2 * Copyright 2015-2016, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "People.h" 8 9 #include <stdio.h> 10 11 #include <Autolock.h> 12 #include <Node.h> 13 14 15 static BString 16 PersonName(BNode& node) 17 { 18 BString fullName; 19 node.ReadAttrString("META:name", &fullName); 20 21 return fullName; 22 } 23 24 25 static void 26 AddPersonAddresses(BNode& node, BStringList& addresses) 27 { 28 BString email; 29 if (node.ReadAttrString("META:email", &email) != B_OK || email.IsEmpty()) 30 return; 31 32 addresses.Add(email); 33 34 // Support for 3rd-party People apps 35 for (int i = 2; i < 99; i++) { 36 char attr[32]; 37 snprintf(attr, sizeof(attr), "META:email%d", i); 38 39 if (node.ReadAttrString(attr, &email) != B_OK) 40 break; 41 42 addresses.Add(email); 43 } 44 } 45 46 47 static void 48 AddPersonGroups(BNode& node, BStringList& groups) 49 { 50 BString groupString; 51 if (node.ReadAttrString("META:group", &groupString) != B_OK 52 || groupString.IsEmpty()) { 53 return; 54 } 55 56 int first = 0; 57 while (first < groupString.Length()) { 58 int end = groupString.FindFirst(',', first); 59 if (end < 0) 60 end = groupString.Length(); 61 62 BString group; 63 groupString.CopyInto(group, first, end - first); 64 group.Trim(); 65 groups.Add(group); 66 67 first = end + 1; 68 } 69 } 70 71 72 // #pragma mark - Person 73 74 75 Person::Person(const entry_ref& ref) 76 { 77 BNode node(&ref); 78 if (node.InitCheck() != B_OK) 79 return; 80 81 fName = PersonName(node); 82 AddPersonAddresses(node, fAddresses); 83 AddPersonGroups(node, fGroups); 84 } 85 86 87 Person::~Person() 88 { 89 } 90 91 92 bool 93 Person::IsInGroup(const char* group) const 94 { 95 for (int32 index = 0; index < CountGroups(); index++) { 96 if (GroupAt(index) == group) 97 return true; 98 } 99 return false; 100 } 101 102 103 // #pragma mark - PersonList 104 105 106 PersonList::PersonList(QueryList& query) 107 : 108 fQueryList(query), 109 fPersons(10, true) 110 { 111 fQueryList.AddListener(this); 112 } 113 114 115 PersonList::~PersonList() 116 { 117 fQueryList.RemoveListener(this); 118 } 119 120 121 void 122 PersonList::EntryCreated(QueryList& source, const entry_ref& ref, ino_t node) 123 { 124 BAutolock locker(this); 125 126 Person* person = new Person(ref); 127 fPersons.AddItem(person); 128 fPersonMap.insert(std::make_pair(node_ref(ref.device, node), person)); 129 } 130 131 132 void 133 PersonList::EntryRemoved(QueryList& source, const node_ref& nodeRef) 134 { 135 BAutolock locker(this); 136 137 PersonMap::iterator found = fPersonMap.find(nodeRef); 138 if (found != fPersonMap.end()) { 139 Person* person = found->second; 140 fPersonMap.erase(found); 141 fPersons.RemoveItem(person); 142 } 143 } 144 145 146 // #pragma mark - GroupList 147 148 149 GroupList::GroupList(QueryList& query) 150 : 151 fQueryList(query) 152 { 153 fQueryList.AddListener(this); 154 } 155 156 157 GroupList::~GroupList() 158 { 159 fQueryList.RemoveListener(this); 160 } 161 162 163 void 164 GroupList::EntryCreated(QueryList& source, const entry_ref& ref, ino_t _node) 165 { 166 BNode node(&ref); 167 if (node.InitCheck() != B_OK) 168 return; 169 170 BAutolock locker(this); 171 172 BStringList groups; 173 AddPersonGroups(node, groups); 174 175 for (int32 index = 0; index < groups.CountStrings(); index++) { 176 BString group = groups.StringAt(index); 177 178 StringCountMap::iterator found = fGroupMap.find(group); 179 if (found != fGroupMap.end()) 180 found->second++; 181 else { 182 fGroupMap[group] = 1; 183 fGroups.Add(group); 184 } 185 } 186 187 // TODO: sort groups 188 } 189 190 191 void 192 GroupList::EntryRemoved(QueryList& source, const node_ref& nodeRef) 193 { 194 // TODO! 195 } 196