Mercurial > libpst
comparison src/pst2ldif.cpp @ 151:cda7c812ec01
track character set individually for each mapi element
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sun, 08 Mar 2009 14:35:26 -0700 |
parents | fdc58ad2c758 |
children | 252ad66d3d6e |
comparison
equal
deleted
inserted
replaced
150:06aa84023b48 | 151:cda7c812ec01 |
---|---|
22 | 22 |
23 void usage(void); | 23 void usage(void); |
24 void version(void); | 24 void version(void); |
25 char *check_filename(char *fname); | 25 char *check_filename(char *fname); |
26 void print_ldif_single(const char *attr, const char *value); | 26 void print_ldif_single(const char *attr, const char *value); |
27 void print_ldif_address(const char *attr, int nvalues, char *value, ...); | 27 void print_ldif_single(const char *attr, pst_string value); |
28 void print_ldif_dn(const char *attr, const char *value, const char *base); | 28 void print_ldif_address(const char *attr, int nvalues, pst_string value, ...); |
29 void print_ldif_multi(const char *dn, const char *value); | 29 void print_ldif_dn(const char *attr, pst_string value, const char *base); |
30 void print_ldif_two(const char *attr, const char *value1, const char *value2); | 30 void print_ldif_multi(const char *dn, pst_string value); |
31 void print_ldif_two(const char *attr, pst_string value1, pst_string value2); | |
31 void print_escaped_dn(const char *value); | 32 void print_escaped_dn(const char *value); |
32 void build_cn(char *cn, size_t len, int nvalues, char *value, ...); | 33 void build_cn(char *cn, size_t len, int nvalues, pst_string value, ...); |
33 | 34 |
34 char *prog_name; | 35 char *prog_name; |
35 pst_file pstfile; | 36 pst_file pstfile; |
36 bool old_schema = false; | 37 bool old_schema = false; |
37 char *ldap_base = NULL; // 'o=some.domain.tld,c=US' | 38 char *ldap_base = NULL; // 'o=some.domain.tld,c=US' |
38 int ldif_extra_line_count = 0; | 39 int ldif_extra_line_count = 0; |
39 iconv_t cd = 0; // Character set conversion descriptor | |
40 vector<string> ldap_class; // 'newPerson' or 'inetOrgPerson' | 40 vector<string> ldap_class; // 'newPerson' or 'inetOrgPerson' |
41 vector<string> ldif_extra_line; // 'o: myorg' | 41 vector<string> ldif_extra_line; // 'o: myorg' |
42 | 42 |
43 | 43 |
44 //////////////////////////////////////////////// | 44 //////////////////////////////////////////////// |
106 } | 106 } |
107 | 107 |
108 | 108 |
109 static void process(pst_desc_ll *d_ptr); | 109 static void process(pst_desc_ll *d_ptr); |
110 static void process(pst_desc_ll *d_ptr) { | 110 static void process(pst_desc_ll *d_ptr) { |
111 DEBUG_ENT("process"); | |
111 pst_item *item = NULL; | 112 pst_item *item = NULL; |
112 while (d_ptr) { | 113 while (d_ptr) { |
113 if (d_ptr->desc) { | 114 if (d_ptr->desc) { |
114 item = pst_parse_item(&pstfile, d_ptr, NULL); | 115 item = pst_parse_item(&pstfile, d_ptr, NULL); |
115 DEBUG_INFO(("item pointer is %p\n", item)); | 116 DEBUG_INFO(("item pointer is %p\n", item)); |
116 if (item) { | 117 if (item) { |
117 if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) { | 118 if (item->folder && d_ptr->child && item->file_as.str && strcasecmp(item->file_as.str, "Deleted Items")) { |
118 //if this is a non-empty folder other than deleted items, we want to recurse into it | 119 //if this is a non-empty folder other than deleted items, we want to recurse into it |
119 fprintf(stderr, "entering folder %s\n", item->file_as); | 120 fprintf(stderr, "entering folder %s\n", item->file_as.str); |
120 process(d_ptr->child); | 121 process(d_ptr->child); |
121 | 122 |
122 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { | 123 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { |
123 // deal with a contact | 124 // deal with a contact |
124 char cn[1000]; | 125 char cn[1000]; |
126 | |
127 // convert everything to utf8 | |
128 pst_convert_utf8_null(item, &item->contact->display_name_prefix); | |
129 pst_convert_utf8_null(item, &item->contact->first_name); | |
130 pst_convert_utf8_null(item, &item->contact->surname); | |
131 pst_convert_utf8_null(item, &item->contact->suffix); | |
132 pst_convert_utf8_null(item, &item->contact->company_name); | |
133 pst_convert_utf8_null(item, &item->contact->job_title); | |
134 pst_convert_utf8_null(item, &item->contact->address1); | |
135 pst_convert_utf8_null(item, &item->contact->address2); | |
136 pst_convert_utf8_null(item, &item->contact->address3); | |
137 pst_convert_utf8_null(item, &item->contact->address1a); | |
138 pst_convert_utf8_null(item, &item->contact->address2a); | |
139 pst_convert_utf8_null(item, &item->contact->address3a); | |
140 pst_convert_utf8_null(item, &item->contact->business_address); | |
141 pst_convert_utf8_null(item, &item->contact->business_po_box); | |
142 pst_convert_utf8_null(item, &item->contact->business_street); | |
143 pst_convert_utf8_null(item, &item->contact->business_city); | |
144 pst_convert_utf8_null(item, &item->contact->business_state); | |
145 pst_convert_utf8_null(item, &item->contact->business_postal_code); | |
146 pst_convert_utf8_null(item, &item->contact->home_address); | |
147 pst_convert_utf8_null(item, &item->contact->home_po_box); | |
148 pst_convert_utf8_null(item, &item->contact->home_street); | |
149 pst_convert_utf8_null(item, &item->contact->home_city); | |
150 pst_convert_utf8_null(item, &item->contact->home_state); | |
151 pst_convert_utf8_null(item, &item->contact->home_postal_code); | |
152 pst_convert_utf8_null(item, &item->contact->other_address); | |
153 pst_convert_utf8_null(item, &item->contact->other_po_box); | |
154 pst_convert_utf8_null(item, &item->contact->other_street); | |
155 pst_convert_utf8_null(item, &item->contact->other_city); | |
156 pst_convert_utf8_null(item, &item->contact->other_state); | |
157 pst_convert_utf8_null(item, &item->contact->other_postal_code); | |
158 pst_convert_utf8_null(item, &item->contact->business_fax); | |
159 pst_convert_utf8_null(item, &item->contact->home_fax); | |
160 pst_convert_utf8_null(item, &item->contact->business_phone); | |
161 pst_convert_utf8_null(item, &item->contact->home_phone); | |
162 pst_convert_utf8_null(item, &item->contact->car_phone); | |
163 pst_convert_utf8_null(item, &item->contact->mobile_phone); | |
164 pst_convert_utf8_null(item, &item->contact->other_phone); | |
165 pst_convert_utf8_null(item, &item->contact->business_homepage); | |
166 pst_convert_utf8_null(item, &item->contact->personal_homepage); | |
167 pst_convert_utf8_null(item, &item->comment); | |
125 | 168 |
126 build_cn(cn, sizeof(cn), 4, | 169 build_cn(cn, sizeof(cn), 4, |
127 item->contact->display_name_prefix, | 170 item->contact->display_name_prefix, |
128 item->contact->first_name, | 171 item->contact->first_name, |
129 item->contact->surname, | 172 item->contact->surname, |
130 item->contact->suffix); | 173 item->contact->suffix); |
131 if (cn[0] != 0) { | 174 if (cn[0] != 0) { |
132 // have a valid cn | 175 // have a valid cn |
133 const char *ucn = unique_string(cn); | 176 pst_string ucn; |
177 ucn.str = (char*)unique_string(cn); | |
134 | 178 |
135 print_ldif_dn("dn", ucn, ldap_base); | 179 print_ldif_dn("dn", ucn, ldap_base); |
136 print_ldif_single("cn", ucn); | 180 print_ldif_single("cn", ucn); |
137 if (item->contact->first_name) { | 181 if (item->contact->first_name.str) { |
138 print_ldif_two("givenName", | 182 print_ldif_two("givenName", |
139 item->contact->display_name_prefix, | 183 item->contact->display_name_prefix, |
140 item->contact->first_name); | 184 item->contact->first_name); |
141 } | 185 } |
142 if (item->contact->surname) { | 186 if (item->contact->surname.str) { |
143 print_ldif_two("sn", | 187 print_ldif_two("sn", |
144 item->contact->surname, | 188 item->contact->surname, |
145 item->contact->suffix); | 189 item->contact->suffix); |
146 } | 190 } |
147 else if (item->contact->company_name) { | 191 else if (item->contact->company_name.str) { |
148 print_ldif_single("sn", item->contact->company_name); | 192 print_ldif_single("sn", item->contact->company_name); |
149 } | 193 } |
150 else | 194 else |
151 print_ldif_single("sn", ucn); // use cn as sn if we cannot find something better | 195 print_ldif_single("sn", ucn); // use cn as sn if we cannot find something better |
152 | 196 |
153 if (old_schema) { | 197 if (old_schema) { |
154 if (item->contact->job_title) | 198 if (item->contact->job_title.str) |
155 print_ldif_single("personalTitle", item->contact->job_title); | 199 print_ldif_single("personalTitle", item->contact->job_title); |
156 if (item->contact->company_name) | 200 if (item->contact->company_name.str) |
157 print_ldif_single("company", item->contact->company_name); | 201 print_ldif_single("company", item->contact->company_name); |
158 } | 202 } |
159 else { | 203 else { |
160 // new schema | 204 // new schema |
161 if (item->contact->job_title) | 205 if (item->contact->job_title.str) |
162 print_ldif_single("title", item->contact->job_title); | 206 print_ldif_single("title", item->contact->job_title); |
163 if (item->contact->company_name) | 207 if (item->contact->company_name.str) |
164 print_ldif_single("o", item->contact->company_name); | 208 print_ldif_single("o", item->contact->company_name); |
165 } | 209 } |
166 if (item->contact->address1 && *item->contact->address1) | 210 if (item->contact->address1.str && *item->contact->address1.str) |
167 print_ldif_single("mail", item->contact->address1); | 211 print_ldif_single("mail", item->contact->address1); |
168 if (item->contact->address2 && *item->contact->address2) | 212 if (item->contact->address2.str && *item->contact->address2.str) |
169 print_ldif_single("mail", item->contact->address2); | 213 print_ldif_single("mail", item->contact->address2); |
170 if (item->contact->address3 && *item->contact->address3) | 214 if (item->contact->address3.str && *item->contact->address3.str) |
171 print_ldif_single("mail", item->contact->address3); | 215 print_ldif_single("mail", item->contact->address3); |
172 if (item->contact->address1a && *item->contact->address1a) | 216 if (item->contact->address1a.str && *item->contact->address1a.str) |
173 print_ldif_single("mail", item->contact->address1a); | 217 print_ldif_single("mail", item->contact->address1a); |
174 if (item->contact->address2a && *item->contact->address2a) | 218 if (item->contact->address2a.str && *item->contact->address2a.str) |
175 print_ldif_single("mail", item->contact->address2a); | 219 print_ldif_single("mail", item->contact->address2a); |
176 if (item->contact->address3a && *item->contact->address3a) | 220 if (item->contact->address3a.str && *item->contact->address3a.str) |
177 print_ldif_single("mail", item->contact->address3a); | 221 print_ldif_single("mail", item->contact->address3a); |
178 | 222 |
179 if (old_schema) { | 223 if (old_schema) { |
180 if (item->contact->business_address) { | 224 if (item->contact->business_address.str) { |
181 if (item->contact->business_po_box) | 225 if (item->contact->business_po_box.str) |
182 print_ldif_single("postalAddress", item->contact->business_po_box); | 226 print_ldif_single("postalAddress", item->contact->business_po_box); |
183 if (item->contact->business_street) | 227 if (item->contact->business_street.str) |
184 print_ldif_multi("postalAddress", item->contact->business_street); | 228 print_ldif_multi("postalAddress", item->contact->business_street); |
185 if (item->contact->business_city) | 229 if (item->contact->business_city.str) |
186 print_ldif_single("l", item->contact->business_city); | 230 print_ldif_single("l", item->contact->business_city); |
187 if (item->contact->business_state) | 231 if (item->contact->business_state.str) |
188 print_ldif_single("st", item->contact->business_state); | 232 print_ldif_single("st", item->contact->business_state); |
189 if (item->contact->business_postal_code) | 233 if (item->contact->business_postal_code.str) |
190 print_ldif_single("postalCode", item->contact->business_postal_code); | 234 print_ldif_single("postalCode", item->contact->business_postal_code); |
191 } | 235 } |
192 else if (item->contact->home_address) { | 236 else if (item->contact->home_address.str) { |
193 if (item->contact->home_po_box) | 237 if (item->contact->home_po_box.str) |
194 print_ldif_single("postalAddress", item->contact->home_po_box); | 238 print_ldif_single("postalAddress", item->contact->home_po_box); |
195 if (item->contact->home_street) | 239 if (item->contact->home_street.str) |
196 print_ldif_multi("postalAddress", item->contact->home_street); | 240 print_ldif_multi("postalAddress", item->contact->home_street); |
197 if (item->contact->home_city) | 241 if (item->contact->home_city.str) |
198 print_ldif_single("l", item->contact->home_city); | 242 print_ldif_single("l", item->contact->home_city); |
199 if (item->contact->home_state) | 243 if (item->contact->home_state.str) |
200 print_ldif_single("st", item->contact->home_state); | 244 print_ldif_single("st", item->contact->home_state); |
201 if (item->contact->home_postal_code) | 245 if (item->contact->home_postal_code.str) |
202 print_ldif_single("postalCode", item->contact->home_postal_code); | 246 print_ldif_single("postalCode", item->contact->home_postal_code); |
203 } | 247 } |
204 else if (item->contact->other_address) { | 248 else if (item->contact->other_address.str) { |
205 if (item->contact->other_po_box) | 249 if (item->contact->other_po_box.str) |
206 print_ldif_single("postalAddress", item->contact->other_po_box); | 250 print_ldif_single("postalAddress", item->contact->other_po_box); |
207 if (item->contact->other_street) | 251 if (item->contact->other_street.str) |
208 print_ldif_multi("postalAddress", item->contact->other_street); | 252 print_ldif_multi("postalAddress", item->contact->other_street); |
209 if (item->contact->other_city) | 253 if (item->contact->other_city.str) |
210 print_ldif_single("l", item->contact->other_city); | 254 print_ldif_single("l", item->contact->other_city); |
211 if (item->contact->other_state) | 255 if (item->contact->other_state.str) |
212 print_ldif_single("st", item->contact->other_state); | 256 print_ldif_single("st", item->contact->other_state); |
213 if (item->contact->other_postal_code) | 257 if (item->contact->other_postal_code.str) |
214 print_ldif_single("postalCode", item->contact->other_postal_code); | 258 print_ldif_single("postalCode", item->contact->other_postal_code); |
215 } | 259 } |
216 } | 260 } |
217 else { | 261 else { |
218 // new schema, with proper RFC4517 postal addresses | 262 // new schema, with proper RFC4517 postal addresses |
219 if (item->contact->business_address) { | 263 if (item->contact->business_address.str) { |
220 print_ldif_address("postalAddress", 6, | 264 print_ldif_address("postalAddress", 6, |
221 item->contact->business_po_box, | 265 item->contact->business_po_box, |
222 item->contact->business_street, | 266 item->contact->business_street, |
223 item->contact->business_city, | 267 item->contact->business_city, |
224 item->contact->business_state, | 268 item->contact->business_state, |
225 item->contact->business_postal_code, | 269 item->contact->business_postal_code, |
226 item->contact->business_country); | 270 item->contact->business_country); |
227 if (item->contact->business_city) | 271 if (item->contact->business_city.str) |
228 print_ldif_single("l", item->contact->business_city); | 272 print_ldif_single("l", item->contact->business_city); |
229 if (item->contact->business_state) | 273 if (item->contact->business_state.str) |
230 print_ldif_single("st", item->contact->business_state); | 274 print_ldif_single("st", item->contact->business_state); |
231 if (item->contact->business_postal_code) | 275 if (item->contact->business_postal_code.str) |
232 print_ldif_single("postalCode", item->contact->business_postal_code); | 276 print_ldif_single("postalCode", item->contact->business_postal_code); |
233 } | 277 } |
234 else if (item->contact->home_address) { | 278 else if (item->contact->home_address.str) { |
235 if (item->contact->home_city) | 279 if (item->contact->home_city.str) |
236 print_ldif_single("l", item->contact->home_city); | 280 print_ldif_single("l", item->contact->home_city); |
237 if (item->contact->home_state) | 281 if (item->contact->home_state.str) |
238 print_ldif_single("st", item->contact->home_state); | 282 print_ldif_single("st", item->contact->home_state); |
239 if (item->contact->home_postal_code) | 283 if (item->contact->home_postal_code.str) |
240 print_ldif_single("postalCode", item->contact->home_postal_code); | 284 print_ldif_single("postalCode", item->contact->home_postal_code); |
241 } | 285 } |
242 else if (item->contact->other_address) { | 286 else if (item->contact->other_address.str) { |
243 print_ldif_address("postalAddress", 6, | 287 print_ldif_address("postalAddress", 6, |
244 item->contact->other_po_box, | 288 item->contact->other_po_box, |
245 item->contact->other_street, | 289 item->contact->other_street, |
246 item->contact->other_city, | 290 item->contact->other_city, |
247 item->contact->other_state, | 291 item->contact->other_state, |
248 item->contact->other_postal_code, | 292 item->contact->other_postal_code, |
249 item->contact->other_country); | 293 item->contact->other_country); |
250 if (item->contact->other_city) | 294 if (item->contact->other_city.str) |
251 print_ldif_single("l", item->contact->other_city); | 295 print_ldif_single("l", item->contact->other_city); |
252 if (item->contact->other_state) | 296 if (item->contact->other_state.str) |
253 print_ldif_single("st", item->contact->other_state); | 297 print_ldif_single("st", item->contact->other_state); |
254 if (item->contact->other_postal_code) | 298 if (item->contact->other_postal_code.str) |
255 print_ldif_single("postalCode", item->contact->other_postal_code); | 299 print_ldif_single("postalCode", item->contact->other_postal_code); |
256 } | 300 } |
257 if (item->contact->home_address) { | 301 if (item->contact->home_address.str) { |
258 print_ldif_address("homePostalAddress", 6, | 302 print_ldif_address("homePostalAddress", 6, |
259 item->contact->home_po_box, | 303 item->contact->home_po_box, |
260 item->contact->home_street, | 304 item->contact->home_street, |
261 item->contact->home_city, | 305 item->contact->home_city, |
262 item->contact->home_state, | 306 item->contact->home_state, |
263 item->contact->home_postal_code, | 307 item->contact->home_postal_code, |
264 item->contact->home_country); | 308 item->contact->home_country); |
265 } | 309 } |
266 } | 310 } |
267 | 311 |
268 if (item->contact->business_fax) | 312 if (item->contact->business_fax.str) |
269 print_ldif_single("facsimileTelephoneNumber", item->contact->business_fax); | 313 print_ldif_single("facsimileTelephoneNumber", item->contact->business_fax); |
270 else if (item->contact->home_fax) | 314 else if (item->contact->home_fax.str) |
271 print_ldif_single("facsimileTelephoneNumber", item->contact->home_fax); | 315 print_ldif_single("facsimileTelephoneNumber", item->contact->home_fax); |
272 | 316 |
273 if (item->contact->business_phone) | 317 if (item->contact->business_phone.str) |
274 print_ldif_single("telephoneNumber", item->contact->business_phone); | 318 print_ldif_single("telephoneNumber", item->contact->business_phone); |
275 if (item->contact->home_phone) | 319 if (item->contact->home_phone.str) |
276 print_ldif_single("homePhone", item->contact->home_phone); | 320 print_ldif_single("homePhone", item->contact->home_phone); |
277 | 321 |
278 if (item->contact->car_phone) | 322 if (item->contact->car_phone.str) |
279 print_ldif_single("mobile", item->contact->car_phone); | 323 print_ldif_single("mobile", item->contact->car_phone); |
280 else if (item->contact->mobile_phone) | 324 else if (item->contact->mobile_phone.str) |
281 print_ldif_single("mobile", item->contact->mobile_phone); | 325 print_ldif_single("mobile", item->contact->mobile_phone); |
282 else if (item->contact->other_phone) | 326 else if (item->contact->other_phone.str) |
283 print_ldif_single("mobile", item->contact->other_phone); | 327 print_ldif_single("mobile", item->contact->other_phone); |
284 | 328 |
285 if (!old_schema) { | 329 if (!old_schema) { |
286 if (item->contact->business_homepage) | 330 if (item->contact->business_homepage.str) |
287 print_ldif_single("labeledURI", item->contact->business_homepage); | 331 print_ldif_single("labeledURI", item->contact->business_homepage); |
288 if (item->contact->personal_homepage) | 332 if (item->contact->personal_homepage.str) |
289 print_ldif_single("labeledURI", item->contact->personal_homepage); | 333 print_ldif_single("labeledURI", item->contact->personal_homepage); |
290 } | 334 } |
291 | 335 |
292 if (item->comment) | 336 if (item->comment.str) |
293 print_ldif_single("description", item->comment); | 337 print_ldif_single("description", item->comment); |
294 | 338 |
295 for (vector<string>::size_type i=0; i<ldap_class.size(); i++) | 339 for (vector<string>::size_type i=0; i<ldap_class.size(); i++) |
296 print_ldif_single("objectClass", ldap_class[i].c_str()); | 340 print_ldif_single("objectClass", ldap_class[i].c_str()); |
297 printf("\n"); | 341 printf("\n"); |
303 } | 347 } |
304 pst_freeItem(item); | 348 pst_freeItem(item); |
305 } | 349 } |
306 d_ptr = d_ptr->next; | 350 d_ptr = d_ptr->next; |
307 } | 351 } |
352 DEBUG_RET(); | |
353 } | |
354 | |
355 | |
356 void print_ldif_single(const char *attr, pst_string value) | |
357 { | |
358 print_ldif_single(attr, value.str); | |
308 } | 359 } |
309 | 360 |
310 | 361 |
311 // Prints an attribute together with its value. | 362 // Prints an attribute together with its value. |
312 // If the value isn't a "SAFE STRING" (as defined in RFC2849), | 363 // If the value isn't a "SAFE STRING" (as defined in RFC2849), |
313 // then it is output as a BASE-64 encoded value | 364 // then it is output as a BASE-64 encoded value |
314 void print_ldif_single(const char *attr, const char *value) | 365 void print_ldif_single(const char *attr, const char *value) |
315 { | 366 { |
316 size_t len; | 367 size_t len; |
317 bool is_safe_string = true; | 368 bool is_safe_string = true; |
318 bool needs_code_conversion = false; | |
319 bool space_flag = false; | 369 bool space_flag = false; |
320 | 370 |
321 // Strip leading spaces | 371 // Strip leading spaces |
322 while (*value == ' ') value++; | 372 while (*value == ' ') value++; |
323 len = strlen(value) + 1; | 373 len = strlen(value) + 1; |
339 space_flag = true; | 389 space_flag = true; |
340 continue; | 390 continue; |
341 } | 391 } |
342 else { | 392 else { |
343 if ((ch & 0x80) == 0x80) { | 393 if ((ch & 0x80) == 0x80) { |
344 needs_code_conversion = true; | |
345 is_safe_string = false; | 394 is_safe_string = false; |
346 } | 395 } |
347 if (space_flag) { | 396 if (space_flag) { |
348 *p++ = ' '; | 397 *p++ = ' '; |
349 space_flag = false; | 398 space_flag = false; |
352 } | 401 } |
353 } | 402 } |
354 *p = 0; | 403 *p = 0; |
355 if (is_safe_string) { | 404 if (is_safe_string) { |
356 printf("%s: %s\n", attr, &buffer[0]); | 405 printf("%s: %s\n", attr, &buffer[0]); |
357 return; | 406 } |
358 } | 407 else { |
359 | |
360 if (needs_code_conversion && cd != 0) { | |
361 size_t inlen = p - &buffer[0]; | |
362 size_t utf8_len = 2 * inlen + 1; | |
363 vector<char> utf8_buffer(utf8_len); | |
364 char *utf8_p = &utf8_buffer[0]; | |
365 | |
366 iconv(cd, NULL, NULL, NULL, NULL); | |
367 p = &buffer[0]; | |
368 int ret = iconv(cd, (ICONV_CONST char**)&p, &inlen, &utf8_p, &utf8_len); | |
369 | |
370 if (ret >= 0) { | |
371 *utf8_p = 0; | |
372 p = base64_encode(&utf8_buffer[0], utf8_p - &utf8_buffer[0]); | |
373 } | |
374 else | |
375 p = base64_encode(&buffer[0], buffer.size()); | |
376 } | |
377 else | |
378 p = base64_encode(&buffer[0], buffer.size()); | 408 p = base64_encode(&buffer[0], buffer.size()); |
379 printf("%s:: %s\n", attr, p); | 409 printf("%s:: %s\n", attr, p); |
380 free(p); | 410 free(p); |
411 } | |
381 } | 412 } |
382 | 413 |
383 | 414 |
384 // Combines values representing address lines into an address,i | 415 // Combines values representing address lines into an address,i |
385 // lines separated with "$" as per PostalAddress syntax in RFC4517 | 416 // lines separated with "$" as per PostalAddress syntax in RFC4517 |
386 void print_ldif_address(const char *attr, int nvalues, char *value, ...) | 417 void print_ldif_address(const char *attr, int nvalues, pst_string value, ...) |
387 { | 418 { |
419 DEBUG_ENT("print_ldif_address"); | |
388 bool space_flag = false; | 420 bool space_flag = false; |
389 bool newline_flag = false; | 421 bool newline_flag = false; |
390 char *address = NULL; // Buffer where address is built up | 422 char *address = NULL; // Buffer where address is built up |
391 int len = 0; // Length of buffer | 423 int len = 0; // Length of buffer |
392 int i = 0; // Index of next character position in buffer | 424 int i = 0; // Index of next character position in buffer |
393 va_list ap; | 425 va_list ap; |
394 | 426 |
395 va_start(ap, value); | 427 va_start(ap, value); |
396 | 428 while (!value.str) { |
397 while (!value) { | 429 nvalues--; |
398 nvalues--; | 430 if (nvalues == 0) { // Nothing at all to do! |
399 if (nvalues == 0) { // Nothing at all to do! | 431 va_end(ap); |
400 va_end(ap); | 432 DEBUG_RET(); |
401 return; | 433 return; |
402 } | 434 } |
403 value = va_arg(ap, char *); | 435 value = va_arg(ap, pst_string); |
404 } | 436 } |
437 | |
405 for (;;) { | 438 for (;;) { |
406 char ch = *value++; | 439 char ch = *(value.str)++; |
407 | 440 |
408 if (ch == 0 || ch == '\n') { | 441 if (ch == 0) { |
409 do { | 442 do { |
410 value = NULL; | |
411 nvalues--; | 443 nvalues--; |
412 if (nvalues == 0) break; | 444 if (nvalues == 0) break; |
413 value = va_arg(ap, char *); | 445 value = va_arg(ap, pst_string); |
414 } while (!value); | 446 } while (!value.str); |
415 if (!value) break; | 447 if (!nvalues || !value.str) break; |
416 space_flag = true; | 448 space_flag = true; |
417 newline_flag = true; | 449 newline_flag = true; |
418 } | 450 } |
419 else if (ch == '\r') | 451 else if (ch == '\r') |
420 continue; | 452 continue; |
447 va_end(ap); | 479 va_end(ap); |
448 if (i == 0) return; // Nothing to do | 480 if (i == 0) return; // Nothing to do |
449 address[i] = 0; | 481 address[i] = 0; |
450 print_ldif_single(attr, address); | 482 print_ldif_single(attr, address); |
451 free(address); | 483 free(address); |
452 } | 484 DEBUG_RET(); |
453 | 485 } |
454 | 486 |
455 void print_ldif_multi(const char *dn, const char *value) | 487 |
456 { | 488 void print_ldif_multi(const char *dn, pst_string value) |
457 const char *n; | 489 { |
458 while ((n = strchr(value, '\n'))) { | 490 char *n; |
459 print_ldif_single(dn, value); | 491 char *valuestr = value.str; |
460 value = n + 1; | 492 while ((n = strchr(valuestr, '\n'))) { |
461 } | 493 print_ldif_single(dn, valuestr); |
462 print_ldif_single(dn, value); | 494 valuestr = n + 1; |
463 } | 495 } |
464 | 496 print_ldif_single(dn, valuestr); |
465 | 497 } |
466 void print_ldif_two(const char *attr, const char *value1, const char *value2) | 498 |
499 | |
500 void print_ldif_two(const char *attr, pst_string value1, pst_string value2) | |
467 { | 501 { |
468 size_t len1, len2; | 502 size_t len1, len2; |
469 if (value1 && *value1) | 503 if (value1.str && *value1.str) |
470 len1 = strlen(value1); | 504 len1 = strlen(value1.str); |
471 else { | 505 else { |
472 print_ldif_single(attr, value2); | 506 print_ldif_single(attr, value2); |
473 return; | 507 return; |
474 } | 508 } |
475 | 509 |
476 if (value2 && *value2) | 510 if (value2.str && *value2.str) |
477 len2 = strlen(value2); | 511 len2 = strlen(value2.str); |
478 else { | 512 else { |
479 print_ldif_single(attr, value1); | 513 print_ldif_single(attr, value1); |
480 return; | 514 return; |
481 } | 515 } |
482 | 516 |
483 vector<char> value(len1 + len2 + 2); | 517 vector<char> value(len1 + len2 + 2); |
484 memcpy(&value[0], value1, len1); | 518 memcpy(&value[0], value1.str, len1); |
485 value[len1] = ' '; | 519 value[len1] = ' '; |
486 memcpy(&value[0] + len1 + 1, value2, len2 + 1); | 520 memcpy(&value[0] + len1 + 1, value2.str, len2 + 1); |
487 print_ldif_single(attr, &value[0]); | 521 print_ldif_single(attr, &value[0]); |
488 } | 522 } |
489 | 523 |
490 | 524 |
491 void build_cn(char *cn, size_t len, int nvalues, char *value, ...) | 525 void build_cn(char *cn, size_t len, int nvalues, pst_string value, ...) |
492 { | 526 { |
493 bool space_flag = false; | 527 bool space_flag = false; |
494 size_t i = 0; | 528 size_t i = 0; |
495 va_list ap; | 529 va_list ap; |
496 | 530 |
497 va_start(ap, value); | 531 va_start(ap, value); |
498 | 532 |
499 while (!value) { | 533 while (!value.str) { |
500 nvalues--; | 534 nvalues--; |
501 if (nvalues == 0) { | 535 if (nvalues == 0) { |
502 cn[0] = 0; // Just a terminating NUL | 536 cn[0] = 0; // Just a terminating NUL |
503 va_end(ap); | 537 va_end(ap); |
504 return; | 538 return; |
505 } | 539 } |
506 value = va_arg(ap, char *); | 540 value = va_arg(ap, pst_string); |
507 } | 541 } |
508 for (;;) { | 542 for (;;) { |
509 char ch = *value++; | 543 char ch = *(value.str)++; |
510 | 544 |
511 if (ch == 0 || ch == '\n') { | 545 if (ch == 0 || ch == '\n') { |
512 do { | 546 do { |
513 value = NULL; | |
514 nvalues--; | 547 nvalues--; |
515 if (nvalues == 0) break; | 548 if (nvalues == 0) break; |
516 value = va_arg(ap, char *); | 549 value = va_arg(ap, pst_string); |
517 } while (!value); | 550 } while (!value.str); |
518 if (!value) break; | 551 if (!nvalues || !value.str) break; |
519 space_flag = true; | 552 space_flag = true; |
520 } | 553 } |
521 else if (ch == '\r') | 554 else if (ch == '\r') |
522 continue; | 555 continue; |
523 else if (ch == ' ') { | 556 else if (ch == ' ') { |
547 int c; | 580 int c; |
548 char *d_log = NULL; | 581 char *d_log = NULL; |
549 prog_name = argv[0]; | 582 prog_name = argv[0]; |
550 pst_item *item = NULL; | 583 pst_item *item = NULL; |
551 | 584 |
552 while ((c = getopt(argc, argv, "b:c:C:d:l:oVh"))!= -1) { | 585 while ((c = getopt(argc, argv, "b:c:d:l:oVh"))!= -1) { |
553 switch (c) { | 586 switch (c) { |
554 case 'b': | 587 case 'b': |
555 ldap_base = optarg; | 588 ldap_base = optarg; |
556 break; | 589 break; |
557 case 'c': | 590 case 'c': |
558 ldap_class.push_back(string(optarg)); | 591 ldap_class.push_back(string(optarg)); |
559 break; | |
560 case 'C': | |
561 cd = iconv_open("UTF-8", optarg); | |
562 if (cd == (iconv_t)(-1)) { | |
563 fprintf(stderr, "I don't know character set \"%s\"!\n\n", optarg); | |
564 fprintf(stderr, "Type: \"iconv --list\" to get list of known character sets\n"); | |
565 return 1; | |
566 } | |
567 break; | 592 break; |
568 case 'd': | 593 case 'd': |
569 d_log = optarg; | 594 d_log = optarg; |
570 break; | 595 break; |
571 case 'h': | 596 case 'h': |
643 | 668 |
644 process(d_ptr->child); // do the children of TOPF | 669 process(d_ptr->child); // do the children of TOPF |
645 pst_close(&pstfile); | 670 pst_close(&pstfile); |
646 DEBUG_RET(); | 671 DEBUG_RET(); |
647 free_strings(all_strings); | 672 free_strings(all_strings); |
648 if (cd) iconv_close(cd); | |
649 | |
650 return 0; | 673 return 0; |
651 } | 674 } |
652 | 675 |
653 | 676 |
654 void usage(void) { | 677 void usage(void) { |
655 version(); | 678 version(); |
656 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); | 679 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); |
657 printf("OPTIONS:\n"); | 680 printf("OPTIONS:\n"); |
658 printf("\t-V\t- Version. Display program version\n"); | 681 printf("\t-V\t- Version. Display program version\n"); |
659 printf("\t-C charset\t- assumed character set of non-ASCII characters\n"); | |
660 printf("\t-b ldapbase\t- set the LDAP base value\n"); | 682 printf("\t-b ldapbase\t- set the LDAP base value\n"); |
661 printf("\t-c class\t- set the class of the LDAP objects (may contain more than one)\n"); | 683 printf("\t-c class\t- set the class of the LDAP objects (may contain more than one)\n"); |
662 printf("\t-d <filename>\t- Debug to file. This is a binary log. Use readpstlog to print it\n"); | 684 printf("\t-d <filename>\t- Debug to file. This is a binary log. Use readpstlog to print it\n"); |
663 printf("\t-h\t- Help. This screen\n"); | 685 printf("\t-h\t- Help. This screen\n"); |
664 printf("\t-l line\t- extra line to insert in the LDIF file for each contact\n"); | 686 printf("\t-l line\t- extra line to insert in the LDIF file for each contact\n"); |
693 return fname; | 715 return fname; |
694 } | 716 } |
695 | 717 |
696 | 718 |
697 // This function escapes Distinguished Names (as per RFC4514) | 719 // This function escapes Distinguished Names (as per RFC4514) |
698 void print_ldif_dn(const char *attr, const char *value, const char *base) | 720 void print_ldif_dn(const char *attr, pst_string value, const char *base) |
699 { | 721 { |
700 printf("dn: cn="); | 722 printf("dn: cn="); |
723 const char *valuestr = value.str; | |
701 // remove leading spaces (RFC says escape them) | 724 // remove leading spaces (RFC says escape them) |
702 while (*value == ' ') | 725 while (*valuestr == ' ') |
703 value++; | 726 valuestr++; |
704 | 727 |
705 print_escaped_dn(value); | 728 print_escaped_dn(valuestr); |
706 if (base && base[0]) { | 729 if (base && base[0]) { |
707 printf(", %s", base); | 730 printf(", %s", base); |
708 } | 731 } |
709 printf("\n"); | 732 printf("\n"); |
710 return; | 733 return; |
712 | 735 |
713 | 736 |
714 void print_escaped_dn(const char *value) | 737 void print_escaped_dn(const char *value) |
715 { | 738 { |
716 char ch; | 739 char ch; |
717 bool needs_code_conversion = false; | |
718 char *utf8_buffer = NULL; | |
719 | |
720 // First do a quick scan to see if any code conversion is required | |
721 if (cd) { | |
722 const char *p = value; | |
723 while (*p) { | |
724 if (*p++ & 0x80) { | |
725 needs_code_conversion = true; | |
726 break; | |
727 } | |
728 } | |
729 } | |
730 | |
731 if (needs_code_conversion) { | |
732 size_t inlen = strlen(value); | |
733 size_t utf8_len = 2 * inlen + 1; | |
734 char *p = (char *)value; | |
735 char *utf8_p = utf8_buffer; | |
736 | |
737 utf8_buffer = (char *)malloc(utf8_len); | |
738 utf8_p = utf8_buffer; | |
739 iconv(cd, NULL, NULL, NULL, NULL); | |
740 if (iconv(cd, (ICONV_CONST char**)&p, &inlen, &utf8_p, &utf8_len) >= 0) { | |
741 *utf8_p = 0; | |
742 value = utf8_buffer; | |
743 } | |
744 } | |
745 | 740 |
746 // escape initial '#' and space | 741 // escape initial '#' and space |
747 if (*value == '#' || *value == ' ') | 742 if (*value == '#' || *value == ' ') |
748 putchar('\\'); | 743 putchar('\\'); |
749 | 744 |
763 // Fall through | 758 // Fall through |
764 default: | 759 default: |
765 putchar(ch); | 760 putchar(ch); |
766 } | 761 } |
767 } | 762 } |
768 if (utf8_buffer) free((void *)utf8_buffer); | |
769 return; | 763 return; |
770 } | 764 } |