Mercurial > libpst
comparison src/pst2ldif.cpp @ 104:39ba19372732
many fixes in pst2ldif by Robert Harris
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 09 Oct 2008 12:04:40 -0700 |
parents | b7f456946c5b |
children | 4703d622e95b |
comparison
equal
deleted
inserted
replaced
103:0af0bbe166e1 | 104:39ba19372732 |
---|---|
10 | 10 |
11 using namespace std; | 11 using namespace std; |
12 | 12 |
13 // needed for std c++ collections | 13 // needed for std c++ collections |
14 #include <set> | 14 #include <set> |
15 #include <vector> | |
16 #include <string> | |
15 | 17 |
16 extern "C" { | 18 extern "C" { |
17 #include "define.h" | 19 #include "define.h" |
18 #include "libstrfunc.h" | 20 #include "libstrfunc.h" |
19 #include "libpst.h" | 21 #include "libpst.h" |
25 } | 27 } |
26 | 28 |
27 int32_t usage(); | 29 int32_t usage(); |
28 int32_t version(); | 30 int32_t version(); |
29 char *check_filename(char *fname); | 31 char *check_filename(char *fname); |
30 char *dn_escape(const char *str); | 32 void print_ldif_single(const char *attr, const char *value); |
31 void print_ldif(const char *dn, const char *value); | 33 void print_ldif_address(const char *attr, int nvalues, char *value, ...); |
32 void print_ldif_single(const char *dn, const char *value); | 34 void print_ldif_dn(const char *attr, const char *value, const char *base); |
33 void print_ldif_multi(const char *dn, const char *value); | 35 void print_ldif_multi(const char *dn, const char *value); |
34 void print_ldif_two(const char *dn, const char *value1, const char *value2); | 36 void print_ldif_two(const char *attr, const char *value1, const char *value2); |
37 void print_escaped_dn(const char *value); | |
35 void build_cn(char *cn, size_t len, int nvalues, char *value, ...); | 38 void build_cn(char *cn, size_t len, int nvalues, char *value, ...); |
36 | 39 |
37 char *prog_name; | 40 char *prog_name; |
38 pst_file pstfile; | 41 pst_file pstfile; |
39 char *ldap_base = NULL; // 'o=some.domain.tld, c=US' | 42 bool old_schema = false; |
40 char *ldap_class = NULL; // 'newPerson' | 43 char *ldap_base = NULL; // 'o=some.domain.tld,c=US' |
41 char *ldap_org = NULL; // 'some.domain.tld', computed from ldap_base | 44 int ldif_extra_line_count = 0; |
42 iconv_t cd = 0; // Character set conversion descriptor | 45 iconv_t cd = 0; // Character set conversion descriptor |
46 vector<string> ldap_class; // 'newPerson' or 'inetOrgPerson' | |
47 vector<string> ldif_extra_line; // 'o: myorg' | |
43 | 48 |
44 | 49 |
45 //////////////////////////////////////////////// | 50 //////////////////////////////////////////////// |
46 // define our ordering | 51 // define our ordering |
47 struct ltstr { | 52 struct ltstr { |
121 process(d_ptr->child); | 126 process(d_ptr->child); |
122 | 127 |
123 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { | 128 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { |
124 // deal with a contact | 129 // deal with a contact |
125 char cn[1000]; | 130 char cn[1000]; |
131 | |
126 build_cn(cn, sizeof(cn), 4, | 132 build_cn(cn, sizeof(cn), 4, |
127 item->contact->display_name_prefix, | 133 item->contact->display_name_prefix, |
128 item->contact->first_name, | 134 item->contact->first_name, |
129 item->contact->surname, | 135 item->contact->surname, |
130 item->contact->suffix); | 136 item->contact->suffix); |
131 if (cn[0] != 0) { | 137 if (cn[0] != 0) { |
132 // have a valid cn | 138 // have a valid cn |
133 const char *ucn = unique_string(cn); | 139 const char *ucn = unique_string(cn); |
134 char dn[strlen(ucn) + strlen(ldap_base) + 6]; | 140 |
135 | 141 print_ldif_dn("dn", ucn, ldap_base); |
136 sprintf(dn, "cn=%s, %s", ucn, ldap_base); | |
137 print_ldif_single("dn", dn); | |
138 print_ldif_single("cn", ucn); | 142 print_ldif_single("cn", ucn); |
139 if (item->contact->first_name) { | 143 if (item->contact->first_name) { |
140 print_ldif_two("givenName", | 144 print_ldif_two("givenName", |
141 item->contact->display_name_prefix, | 145 item->contact->display_name_prefix, |
142 item->contact->first_name); | 146 item->contact->first_name); |
150 print_ldif_single("sn", item->contact->company_name); | 154 print_ldif_single("sn", item->contact->company_name); |
151 } | 155 } |
152 else | 156 else |
153 print_ldif_single("sn", ucn); // use cn as sn if we cannot find something better | 157 print_ldif_single("sn", ucn); // use cn as sn if we cannot find something better |
154 | 158 |
155 if (item->contact->job_title) | 159 if (old_schema) { |
156 print_ldif_single("personalTitle", item->contact->job_title); | 160 if (item->contact->job_title) |
157 if (item->contact->company_name) | 161 print_ldif_single("personalTitle", item->contact->job_title); |
158 print_ldif_single("company", item->contact->company_name); | 162 if (item->contact->company_name) |
163 print_ldif_single("company", item->contact->company_name); | |
164 else { | |
165 // new schema | |
166 if (item->contact->job_title) | |
167 print_ldif_single("title", item->contact->job_title); | |
168 if (item->contact->company_name) | |
169 print_ldif_single("o", item->contact->company_name); | |
170 } | |
171 } | |
159 if (item->contact->address1 && *item->contact->address1) | 172 if (item->contact->address1 && *item->contact->address1) |
160 print_ldif_single("mail", item->contact->address1); | 173 print_ldif_single("mail", item->contact->address1); |
161 if (item->contact->address2 && *item->contact->address2) | 174 if (item->contact->address2 && *item->contact->address2) |
162 print_ldif_single("mail", item->contact->address2); | 175 print_ldif_single("mail", item->contact->address2); |
163 if (item->contact->address3 && *item->contact->address3) | 176 if (item->contact->address3 && *item->contact->address3) |
166 print_ldif_single("mail", item->contact->address1a); | 179 print_ldif_single("mail", item->contact->address1a); |
167 if (item->contact->address2a && *item->contact->address2a) | 180 if (item->contact->address2a && *item->contact->address2a) |
168 print_ldif_single("mail", item->contact->address2a); | 181 print_ldif_single("mail", item->contact->address2a); |
169 if (item->contact->address3a && *item->contact->address3a) | 182 if (item->contact->address3a && *item->contact->address3a) |
170 print_ldif_single("mail", item->contact->address3a); | 183 print_ldif_single("mail", item->contact->address3a); |
171 if (item->contact->business_address) { | 184 |
172 if (item->contact->business_po_box) | 185 if (old_schema) { |
173 print_ldif_single("postalAddress", item->contact->business_po_box); | 186 if (item->contact->business_address) { |
174 if (item->contact->business_street) | 187 if (item->contact->business_po_box) |
175 print_ldif_multi("postalAddress", item->contact->business_street); | 188 print_ldif_single("postalAddress", item->contact->business_po_box); |
176 if (item->contact->business_city) | 189 if (item->contact->business_street) |
177 print_ldif_single("l", item->contact->business_city); | 190 print_ldif_multi("postalAddress", item->contact->business_street); |
178 if (item->contact->business_state) | 191 if (item->contact->business_city) |
179 print_ldif_single("st", item->contact->business_state); | 192 print_ldif_single("l", item->contact->business_city); |
180 if (item->contact->business_postal_code) | 193 if (item->contact->business_state) |
181 print_ldif_single("postalCode", item->contact->business_postal_code); | 194 print_ldif_single("st", item->contact->business_state); |
195 if (item->contact->business_postal_code) | |
196 print_ldif_single("postalCode", item->contact->business_postal_code); | |
197 } | |
198 else if (item->contact->home_address) { | |
199 if (item->contact->home_po_box) | |
200 print_ldif_single("postalAddress", item->contact->home_po_box); | |
201 if (item->contact->home_street) | |
202 print_ldif_multi("postalAddress", item->contact->home_street); | |
203 if (item->contact->home_city) | |
204 print_ldif_single("l", item->contact->home_city); | |
205 if (item->contact->home_state) | |
206 print_ldif_single("st", item->contact->home_state); | |
207 if (item->contact->home_postal_code) | |
208 print_ldif_single("postalCode", item->contact->home_postal_code); | |
209 } | |
210 else if (item->contact->other_address) { | |
211 if (item->contact->other_po_box) | |
212 print_ldif_single("postalAddress", item->contact->other_po_box); | |
213 if (item->contact->other_street) | |
214 print_ldif_multi("postalAddress", item->contact->other_street); | |
215 if (item->contact->other_city) | |
216 print_ldif_single("l", item->contact->other_city); | |
217 if (item->contact->other_state) | |
218 print_ldif_single("st", item->contact->other_state); | |
219 if (item->contact->other_postal_code) | |
220 print_ldif_single("postalCode", item->contact->other_postal_code); | |
221 } | |
182 } | 222 } |
183 else if (item->contact->home_address) { | 223 else { |
184 if (item->contact->home_po_box) | 224 // new schema, with proper RFC4517 postal addresses |
185 print_ldif_single("postalAddress", item->contact->home_po_box); | 225 if (item->contact->business_address) { |
186 if (item->contact->home_street) | 226 print_ldif_address("postalAddress", 6, |
187 print_ldif_multi("postalAddress", item->contact->home_street); | 227 item->contact->business_po_box, |
188 if (item->contact->home_city) | 228 item->contact->business_street, |
189 print_ldif_single("l", item->contact->home_city); | 229 item->contact->business_city, |
190 if (item->contact->home_state) | 230 item->contact->business_state, |
191 print_ldif_single("st", item->contact->home_state); | 231 item->contact->business_postal_code, |
192 if (item->contact->home_postal_code) | 232 item->contact->business_country); |
193 print_ldif_single("postalCode", item->contact->home_postal_code); | 233 if (item->contact->business_city) |
234 print_ldif_single("l", item->contact->business_city); | |
235 if (item->contact->business_state) | |
236 print_ldif_single("st", item->contact->business_state); | |
237 if (item->contact->business_postal_code) | |
238 print_ldif_single("postalCode", item->contact->business_postal_code); | |
239 } | |
240 else if (item->contact->home_address) { | |
241 if (item->contact->home_city) | |
242 print_ldif_single("l", item->contact->home_city); | |
243 if (item->contact->home_state) | |
244 print_ldif_single("st", item->contact->home_state); | |
245 if (item->contact->home_postal_code) | |
246 print_ldif_single("postalCode", item->contact->home_postal_code); | |
247 } | |
248 else if (item->contact->other_address) { | |
249 print_ldif_address("postalAddress", 6, | |
250 item->contact->other_po_box, | |
251 item->contact->other_street, | |
252 item->contact->other_city, | |
253 item->contact->other_state, | |
254 item->contact->other_postal_code, | |
255 item->contact->other_country); | |
256 if (item->contact->other_city) | |
257 print_ldif_single("l", item->contact->other_city); | |
258 if (item->contact->other_state) | |
259 print_ldif_single("st", item->contact->other_state); | |
260 if (item->contact->other_postal_code) | |
261 print_ldif_single("postalCode", item->contact->other_postal_code); | |
262 } | |
263 if (item->contact->home_address) { | |
264 print_ldif_address("homePostalAddress", 6, | |
265 item->contact->home_po_box, | |
266 item->contact->home_street, | |
267 item->contact->home_city, | |
268 item->contact->home_state, | |
269 item->contact->home_postal_code, | |
270 item->contact->home_country); | |
271 } | |
194 } | 272 } |
195 else if (item->contact->other_address) { | 273 |
196 if (item->contact->other_po_box) | |
197 print_ldif_single("postalAddress", item->contact->other_po_box); | |
198 if (item->contact->other_street) | |
199 print_ldif_multi("postalAddress", item->contact->other_street); | |
200 if (item->contact->other_city) | |
201 print_ldif_single("l", item->contact->other_city); | |
202 if (item->contact->other_state) | |
203 print_ldif_single("st", item->contact->other_state); | |
204 if (item->contact->other_postal_code) | |
205 print_ldif_single("postalCode", item->contact->other_postal_code); | |
206 } | |
207 if (item->contact->business_fax) | 274 if (item->contact->business_fax) |
208 print_ldif_single("facsimileTelephoneNumber", item->contact->business_fax); | 275 print_ldif_single("facsimileTelephoneNumber", item->contact->business_fax); |
209 else if (item->contact->home_fax) | 276 else if (item->contact->home_fax) |
210 print_ldif_single("facsimileTelephoneNumber", item->contact->home_fax); | 277 print_ldif_single("facsimileTelephoneNumber", item->contact->home_fax); |
211 | 278 |
219 else if (item->contact->mobile_phone) | 286 else if (item->contact->mobile_phone) |
220 print_ldif_single("mobile", item->contact->mobile_phone); | 287 print_ldif_single("mobile", item->contact->mobile_phone); |
221 else if (item->contact->other_phone) | 288 else if (item->contact->other_phone) |
222 print_ldif_single("mobile", item->contact->other_phone); | 289 print_ldif_single("mobile", item->contact->other_phone); |
223 | 290 |
291 if (!old_schema) { | |
292 if (item->contact->business_homepage) | |
293 print_ldif_single("labeledURI", item->contact->business_homepage); | |
294 if (item->contact->personal_homepage) | |
295 print_ldif_single("labeledURI", item->contact->personal_homepage); | |
296 } | |
224 | 297 |
225 if (item->comment) | 298 if (item->comment) |
226 print_ldif_single("description", item->comment); | 299 print_ldif_single("description", item->comment); |
227 | 300 |
228 print_ldif("objectClass", ldap_class); | 301 for (int i=0; i<ldap_class.size(); i++) |
229 putchar('\n'); | 302 print_ldif_single("objectClass", ldap_class[i].c_str()); |
303 printf("\n"); | |
230 } | 304 } |
231 } | 305 } |
232 else { | 306 else { |
233 DEBUG_INFO(("item is not a contact\n")); | 307 DEBUG_INFO(("item is not a contact\n")); |
234 } | 308 } |
238 d_ptr = d_ptr->next; | 312 d_ptr = d_ptr->next; |
239 } | 313 } |
240 } | 314 } |
241 | 315 |
242 | 316 |
243 void print_ldif(const char *dn, const char *value) | 317 // Prints an attribute together with its value. |
244 { | |
245 printf("%s: %s\n", dn, value); | |
246 } | |
247 | |
248 | |
249 // Prints a Distinguished Name together with its value. | |
250 // If the value isn't a "SAFE STRING" (as defined in RFC2849), | 318 // If the value isn't a "SAFE STRING" (as defined in RFC2849), |
251 // then it is output as a BASE-64 encoded value | 319 // then it is output as a BASE-64 encoded value |
252 void print_ldif_single(const char *dn, const char *value) | 320 void print_ldif_single(const char *attr, const char *value) |
253 { | 321 { |
254 size_t len; | 322 size_t len; |
255 bool is_safe_string = true; | 323 bool is_safe_string = true; |
256 bool needs_code_conversion = false; | 324 bool needs_code_conversion = false; |
257 bool space_flag = false; | 325 bool space_flag = false; |
259 // Strip leading spaces | 327 // Strip leading spaces |
260 while (*value == ' ') value++; | 328 while (*value == ' ') value++; |
261 len = strlen(value) + 1; | 329 len = strlen(value) + 1; |
262 char buffer[len]; | 330 char buffer[len]; |
263 char *p = buffer; | 331 char *p = buffer; |
332 | |
264 // See if "value" is a "SAFE STRING" | 333 // See if "value" is a "SAFE STRING" |
265 | |
266 // First check characters that are safe but not safe as initial characters | 334 // First check characters that are safe but not safe as initial characters |
267 if (*value == ':' || *value == '<') | 335 if (*value == ':' || *value == '<') |
268 is_safe_string = false; | 336 is_safe_string = false; |
269 for (;;) { | 337 for (;;) { |
270 char ch = *value++; | 338 char ch = *value++; |
289 *p++ = ch; | 357 *p++ = ch; |
290 } | 358 } |
291 } | 359 } |
292 *p = 0; | 360 *p = 0; |
293 if (is_safe_string) { | 361 if (is_safe_string) { |
294 printf("%s: %s\n", dn, buffer); | 362 printf("%s: %s\n", attr, buffer); |
295 return; | 363 return; |
296 } | 364 } |
297 | 365 |
298 if (needs_code_conversion && cd != 0) { | 366 if (needs_code_conversion && cd != 0) { |
299 size_t inlen = p - buffer; | 367 size_t inlen = p - buffer; |
312 else | 380 else |
313 p = base64_encode(buffer, strlen(buffer)); | 381 p = base64_encode(buffer, strlen(buffer)); |
314 } | 382 } |
315 else | 383 else |
316 p = base64_encode(buffer, strlen(buffer)); | 384 p = base64_encode(buffer, strlen(buffer)); |
317 printf("%s:: %s\n", dn, p); | 385 printf("%s:: %s\n", attr, p); |
318 free(p); | 386 free(p); |
319 } | 387 } |
320 | 388 |
321 | 389 |
322 void print_ldif_multi(const char *dn, const char *value) | 390 // Combines values representing address lines into an address,i |
323 { | 391 // lines separated with "$" as per PostalAddress syntax in RFC4517 |
324 const char *n; | 392 void print_ldif_address(const char *attr, int nvalues, char *value, ...) |
325 while ((n = strchr(value, '\n'))) { | |
326 print_ldif_single(dn, value); | |
327 value = n + 1; | |
328 } | |
329 print_ldif_single(dn, value); | |
330 } | |
331 | |
332 | |
333 void print_ldif_two(const char *dn, const char *value1, const char *value2) | |
334 { | |
335 size_t len1, len2; | |
336 if (value1 && *value1) | |
337 len1 = strlen(value1); | |
338 else { | |
339 print_ldif_single(dn, value2); | |
340 return; | |
341 } | |
342 | |
343 if (value2 && *value2) | |
344 len2 = strlen(value2); | |
345 else { | |
346 print_ldif_single(dn, value1); | |
347 return; | |
348 } | |
349 | |
350 char value[len1 + len2 + 2]; | |
351 memcpy(value, value1, len1); | |
352 value[len1] = ' '; | |
353 memcpy(value + len1 + 1, value2, len2 + 1); | |
354 print_ldif_single(dn, value); | |
355 } | |
356 | |
357 | |
358 void build_cn(char *cn, size_t len, int nvalues, char *value, ...) | |
359 { | 393 { |
360 bool space_flag = false; | 394 bool space_flag = false; |
361 int i = 0; | 395 bool newline_flag = false; |
396 char *address = NULL; // Buffer where address is built up | |
397 int len = 0; // Length of buffer | |
398 int i = 0; // Index of next character position in buffer | |
362 va_list ap; | 399 va_list ap; |
363 | 400 |
364 va_start(ap, value); | 401 va_start(ap, value); |
365 | 402 |
366 while (!value) { | 403 while (!value) { |
367 nvalues--; | 404 nvalues--; |
368 if (nvalues == 0) { | 405 if (nvalues == 0) { // Nothing at all to do! |
369 va_end(ap); | 406 va_end(ap); |
370 return; | 407 return; |
371 } | 408 } |
372 value = va_arg(ap, char *); | 409 value = va_arg(ap, char *); |
373 } | 410 } |
381 if (nvalues == 0) break; | 418 if (nvalues == 0) break; |
382 value = va_arg(ap, char *); | 419 value = va_arg(ap, char *); |
383 } while (!value); | 420 } while (!value); |
384 if (!value) break; | 421 if (!value) break; |
385 space_flag = true; | 422 space_flag = true; |
423 newline_flag = true; | |
424 } | |
425 else if (ch == '\r') | |
426 continue; | |
427 else if (ch == '\n') { | |
428 newline_flag = true; | |
429 continue; | |
430 } | |
431 else if (ch == ' ') { | |
432 space_flag = true; | |
433 continue; | |
434 } | |
435 else { | |
436 if (i > (len-5)) { | |
437 len += 256; | |
438 address = (char *)realloc(address, len); | |
439 } | |
440 if (newline_flag) { | |
441 address[i++] = '$'; | |
442 newline_flag = false; | |
443 space_flag = false; | |
444 } | |
445 else if (space_flag) { | |
446 address[i++] = ' '; | |
447 space_flag = false; | |
448 } | |
449 if (ch == '$' || ch == '\\') address[i++] = '\\'; | |
450 address[i++] = ch; | |
451 } | |
452 } | |
453 va_end(ap); | |
454 if (i == 0) return; // Nothing to do | |
455 address[i] = 0; | |
456 print_ldif_single(attr, address); | |
457 free(address); | |
458 } | |
459 | |
460 | |
461 void print_ldif_multi(const char *dn, const char *value) | |
462 { | |
463 const char *n; | |
464 while ((n = strchr(value, '\n'))) { | |
465 print_ldif_single(dn, value); | |
466 value = n + 1; | |
467 } | |
468 print_ldif_single(dn, value); | |
469 } | |
470 | |
471 | |
472 void print_ldif_two(const char *attr, const char *value1, const char *value2) | |
473 { | |
474 size_t len1, len2; | |
475 if (value1 && *value1) | |
476 len1 = strlen(value1); | |
477 else { | |
478 print_ldif_single(attr, value2); | |
479 return; | |
480 } | |
481 | |
482 if (value2 && *value2) | |
483 len2 = strlen(value2); | |
484 else { | |
485 print_ldif_single(attr, value1); | |
486 return; | |
487 } | |
488 | |
489 char value[len1 + len2 + 2]; | |
490 memcpy(value, value1, len1); | |
491 value[len1] = ' '; | |
492 memcpy(value + len1 + 1, value2, len2 + 1); | |
493 print_ldif_single(attr, value); | |
494 } | |
495 | |
496 | |
497 void build_cn(char *cn, size_t len, int nvalues, char *value, ...) | |
498 { | |
499 bool space_flag = false; | |
500 int i = 0; | |
501 va_list ap; | |
502 | |
503 va_start(ap, value); | |
504 | |
505 while (!value) { | |
506 nvalues--; | |
507 if (nvalues == 0) { | |
508 cn[0] = 0; // Just a terminating NUL | |
509 va_end(ap); | |
510 return; | |
511 } | |
512 value = va_arg(ap, char *); | |
513 } | |
514 for (;;) { | |
515 char ch = *value++; | |
516 | |
517 if (ch == 0 || ch == '\n') { | |
518 do { | |
519 value = NULL; | |
520 nvalues--; | |
521 if (nvalues == 0) break; | |
522 value = va_arg(ap, char *); | |
523 } while (!value); | |
524 if (!value) break; | |
525 space_flag = true; | |
386 } | 526 } |
387 else if (ch == '\r') | 527 else if (ch == '\r') |
388 continue; | 528 continue; |
389 else if (ch == ' ') { | 529 else if (ch == ' ') { |
390 space_flag = true; | 530 space_flag = true; |
408 | 548 |
409 | 549 |
410 int main(int argc, char** argv) { | 550 int main(int argc, char** argv) { |
411 pst_desc_ll *d_ptr; | 551 pst_desc_ll *d_ptr; |
412 char *fname = NULL; | 552 char *fname = NULL; |
413 char *temp = NULL; //temporary char pointer | |
414 int c; | 553 int c; |
415 char *d_log = NULL; | 554 char *d_log = NULL; |
416 prog_name = argv[0]; | 555 prog_name = argv[0]; |
417 pst_item *item = NULL; | 556 pst_item *item = NULL; |
418 | 557 |
419 while ((c = getopt(argc, argv, "b:c:C:d:Vh"))!= -1) { | 558 while ((c = getopt(argc, argv, "b:c:C:d:l:oVh"))!= -1) { |
420 switch (c) { | 559 switch (c) { |
421 case 'b': | 560 case 'b': |
422 ldap_base = optarg; | 561 ldap_base = optarg; |
423 temp = strchr(ldap_base, ','); | |
424 if (temp) { | |
425 *temp = '\0'; | |
426 ldap_org = strdup(ldap_base+2); // assume first 2 chars are o= | |
427 *temp = ','; | |
428 } | |
429 break; | 562 break; |
430 case 'c': | 563 case 'c': |
431 ldap_class = optarg; | 564 ldap_class.push_back(string(optarg)); |
432 break; | 565 break; |
433 case 'C': | 566 case 'C': |
434 cd = iconv_open("UTF-8", optarg); | 567 cd = iconv_open("UTF-8", optarg); |
435 if (cd == (iconv_t)(-1)) { | 568 if (cd == (iconv_t)(-1)) { |
436 fprintf(stderr, "I don't know character set \"%s\"!\n\n", optarg); | 569 fprintf(stderr, "I don't know character set \"%s\"!\n\n", optarg); |
443 break; | 576 break; |
444 case 'h': | 577 case 'h': |
445 usage(); | 578 usage(); |
446 exit(0); | 579 exit(0); |
447 break; | 580 break; |
581 case 'l': | |
582 ldif_extra_line.push_back(string(optarg)); | |
583 break; | |
584 case 'o': | |
585 old_schema = true; | |
586 break; | |
448 case 'V': | 587 case 'V': |
449 version(); | 588 version(); |
450 exit(0); | 589 exit(0); |
451 break; | 590 break; |
452 default: | 591 default: |
454 exit(1); | 593 exit(1); |
455 break; | 594 break; |
456 } | 595 } |
457 } | 596 } |
458 | 597 |
459 if ((argc > optind) && (ldap_base) && (ldap_class) && (ldap_org)) { | 598 if ((argc > optind) && (ldap_base)) { |
460 fname = argv[optind]; | 599 fname = argv[optind]; |
461 } else { | 600 } else { |
462 usage(); | 601 usage(); |
463 exit(2); | 602 exit(2); |
464 } | 603 } |
488 DIE(("Top of folders record not found. Cannot continue\n")); | 627 DIE(("Top of folders record not found. Cannot continue\n")); |
489 } | 628 } |
490 | 629 |
491 pst_freeItem(item); | 630 pst_freeItem(item); |
492 | 631 |
493 // write the ldap header | 632 if (old_schema && (strlen(ldap_base) > 2)) { |
494 printf("dn: %s\n", ldap_base); | 633 char *ldap_org = strdup(ldap_base+2); // assume first 2 chars are o= |
495 printf("o: %s\n", ldap_org); | 634 char *temp = strchr(ldap_org, ','); |
496 printf("objectClass: organization\n\n"); | 635 if (temp) { |
497 printf("dn: cn=root, %s\n", ldap_base); | 636 *temp = '\0'; |
498 printf("cn: root\n"); | 637 // write the ldap header |
499 printf("objectClass: %s\n\n", ldap_class); | 638 printf("dn: %s\n", ldap_base); |
639 printf("o: %s\n", ldap_org); | |
640 printf("objectClass: organization\n\n"); | |
641 printf("dn: cn=root, %s\n", ldap_base); | |
642 printf("cn: root\n"); | |
643 for (int i=0; i<ldap_class.size(); i++) | |
644 print_ldif_single("objectClass", ldap_class[i].c_str()); | |
645 printf("\n"); | |
646 } | |
647 } | |
500 | 648 |
501 process(d_ptr->child); // do the children of TOPF | 649 process(d_ptr->child); // do the children of TOPF |
502 pst_close(&pstfile); | 650 pst_close(&pstfile); |
503 DEBUG_RET(); | 651 DEBUG_RET(); |
504 free_strings(all_strings); | 652 free_strings(all_strings); |
653 if (cd) iconv_close(cd); | |
654 | |
505 return 0; | 655 return 0; |
506 } | 656 } |
507 | 657 |
508 | 658 |
509 int usage() { | 659 int usage() { |
510 version(); | 660 version(); |
511 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); | 661 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); |
512 printf("OPTIONS:\n"); | 662 printf("OPTIONS:\n"); |
663 printf("\t-V\t- Version. Display program version\n"); | |
664 printf("\t-C charset\t- assumed character set of non-ASCII characters\n"); | |
665 printf("\t-b ldapbase\t- set the LDAP base value\n"); | |
666 printf("\t-c class\t- set the class of the LDAP objects (may contain more than one)\n"); | |
667 printf("\t-d <filename>\t- Debug to file. This is a binary log. Use readpstlog to print it\n"); | |
513 printf("\t-h\t- Help. This screen\n"); | 668 printf("\t-h\t- Help. This screen\n"); |
514 printf("\t-V\t- Version. Display program version\n"); | 669 printf("\t-l line\t- extra line to insert in the LDIF file for each contact\n"); |
515 printf("\t-b ldapbase\t- set the LDAP base value\n"); | 670 printf("\t-o\t- use old schema, default is new schema\n"); |
516 printf("\t-c class \t- set the class of the LDAP objects\n"); | |
517 printf("\t-C charset \t- assumed character set of non-ASCII characters\n"); | |
518 return 0; | 671 return 0; |
519 } | 672 } |
520 | 673 |
521 | 674 |
522 int version() { | 675 int version() { |
545 *t = '_'; //replace them with an underscore | 698 *t = '_'; //replace them with an underscore |
546 } | 699 } |
547 return fname; | 700 return fname; |
548 } | 701 } |
549 | 702 |
550 #if 0 | 703 |
551 // This function escapes Distinguished Names (as per RFC4514) | 704 // This function escapes Distinguished Names (as per RFC4514) |
552 char *dn_escape(const char *str) { | 705 void print_ldif_dn(const char *attr, const char *value, const char *base) |
553 static char* buf = NULL; | 706 { |
554 const char *a; | 707 printf("dn: cn="); |
555 char *ret, *b; | 708 // remove leading spaces (RFC says escape them) |
556 if (str == NULL) | 709 while (*value == ' ') |
557 ret = NULL; | 710 value++; |
558 else { | 711 |
559 // Calculate maximum space needed (if every character must be escaped) | 712 print_escaped_dn(value); |
560 int x = 2 * strlen(str) + 1; // don't forget room for the NUL | 713 if (base && base[0]) { |
561 buf = (char*) realloc(buf, x); | 714 printf(","); |
562 a = str; | 715 print_escaped_dn(base); |
563 b = buf; | 716 } |
564 | 717 printf("\n"); |
565 // remove leading spaces (RFC says escape them) | 718 return; |
566 while (*a == ' ') | 719 } |
567 a++; | 720 |
568 | 721 |
569 // escape initial '#' | 722 void print_escaped_dn(const char *value) |
570 if (*a == '#') | 723 { |
571 *b++ = '\\'; | 724 char ch; |
572 | 725 bool needs_code_conversion = false; |
573 while (*a != '\0') { | 726 char *utf8_buffer = NULL; |
574 switch(*a) { | 727 |
575 case '\\': | 728 // First do a quick scan to see if any code conversion is required |
576 case '"' : | 729 if (cd) { |
577 case '+' : | 730 const char *p = value; |
578 case ';' : | 731 while (*p) { |
579 case '<' : | 732 if (*p++ & 0x80) { |
580 case '>' : | 733 needs_code_conversion = true; |
581 *(b++)='\\'; | |
582 *b=*a; | |
583 break; | 734 break; |
584 case '\r': // skip cr | 735 } |
585 b--; | 736 } |
586 break; | 737 } |
587 default: | 738 |
588 *b=*a; | 739 if (needs_code_conversion) { |
589 } | 740 size_t inlen = strlen(value); |
590 b++; | 741 size_t utf8_len = 2 * inlen + 1; |
591 a++; | 742 char *p = (char *)value; |
592 } | 743 char *utf8_p = utf8_buffer; |
593 *b = '\0'; // NUL-terminate the string (buf) | 744 |
594 ret = buf; | 745 utf8_buffer = (char *)malloc(utf8_len); |
595 } | 746 utf8_p = utf8_buffer; |
596 return ret; | 747 iconv(cd, NULL, NULL, NULL, NULL); |
597 } | 748 if (iconv(cd, &p, &inlen, &utf8_p, &utf8_len) >= 0) { |
598 #endif | 749 *utf8_p = 0; |
750 value = utf8_buffer; | |
751 } | |
752 } | |
753 | |
754 // escape initial '#' and space | |
755 if (*value == '#' || *value == ' ') | |
756 putchar('\\'); | |
757 | |
758 while ((ch = *value++) != 0) { | |
759 if (((ch & 0x80) != 0) || (ch <= 0x1F)) | |
760 // Print as escaped hex digits | |
761 printf("\\%2.2X", ch & 0xFF); | |
762 else switch (ch) { | |
763 case '\\': | |
764 case '"' : | |
765 case '+' : | |
766 case ';' : | |
767 case '<' : | |
768 case '>' : | |
769 putchar('\\'); | |
770 // Fall through | |
771 default: | |
772 putchar(ch); | |
773 } | |
774 } | |
775 if (utf8_buffer) free((void *)utf8_buffer); | |
776 return; | |
777 } |