Mercurial > libpst
annotate src/pst2ldif.cpp @ 60:97b7706bdda2
Work around bogus 7c.b5 blocks in some messages that have been read.
They appear to have attachments, but of some unknown format.
Before the message was read, it did not have any attachments.
Use autoscan to cleanup our autoconf system.
Use autoconf to detect when we need to use our XGetopt files
and other header files.
More fields, including BCC.
Fix missing LE32_CPU byte swapping for FILETIME types.
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sat, 16 Feb 2008 12:26:35 -0800 |
parents | 7d5c637aaafb |
children | 3cb02cb1e6cd |
rev | line source |
---|---|
16 | 1 /* |
2 | |
3 Copyright (c) 2004 Carl Byington - 510 Software Group, released under | |
4 the GPL version 2 or any later version at your choice available at | |
5 http://www.fsf.org/licenses/gpl.txt | |
6 | |
7 Based on readpst.c by David Smith | |
8 | |
9 */ | |
10 | |
11 using namespace std; | |
12 | |
13 // needed for std c++ collections | |
14 #include <set> | |
15 | |
16 extern "C" { | |
17 #include "define.h" | |
59
7d5c637aaafb
General cleanup and code fixes.
Carl Byington <carl@five-ten-sg.com>
parents:
52
diff
changeset
|
18 #include "libstrfunc.h" |
16 | 19 #include "libpst.h" |
20 #include "common.h" | |
21 #include "timeconv.h" | |
22 #include "lzfu.h" | |
23 } | |
24 | |
25 int32_t usage(); | |
26 int32_t version(); | |
27 char *my_stristr(char *haystack, char *needle); | |
28 char *check_filename(char *fname); | |
29 char *single(char *str); | |
30 char *folded(char *str); | |
31 void multi(char *fmt, char *str); | |
32 char *rfc2426_escape(char *str); | |
33 int32_t chr_count(char *str, char x); | |
34 | |
35 char *prog_name; | |
36 pst_file pstfile; | |
37 char *ldap_base = NULL; // 'o=some.domain.tld, c=US' | |
38 char *ldap_class = NULL; // 'newPerson' | |
39 char *ldap_org = NULL; // 'o=some.domain.tld', computed from ldap_base | |
40 | |
41 | |
42 //////////////////////////////////////////////// | |
43 // define our ordering | |
44 struct ltstr { | |
45 bool operator()(char* s1, char* s2) const { | |
46 return strcasecmp(s1, s2) < 0; | |
47 } | |
48 }; | |
49 // define our set | |
50 typedef set<char *, ltstr> string_set; | |
51 // make a static set to hold the cn values | |
52 static string_set all_strings; | |
53 | |
54 | |
55 //////////////////////////////////////////////// | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
56 // helper to free all the strings in a set |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
57 // |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
58 static void free_strings(string_set &s); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
59 static void free_strings(string_set &s) |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
60 { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
61 for (string_set::iterator i=s.begin(); i!=s.end(); i++) { |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
62 free(*i); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
63 } |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
64 s.clear(); |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
65 } |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
66 |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
67 |
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
68 //////////////////////////////////////////////// |
16 | 69 // helper to register a string in a string set |
70 // | |
71 static char* register_string(string_set &s, char *name); | |
72 static char* register_string(string_set &s, char *name) { | |
73 string_set::iterator i = s.find(name); | |
74 if (i != s.end()) return *i; | |
75 char *x = strdup(name); | |
76 s.insert(x); | |
77 return x; | |
78 } | |
79 | |
80 //////////////////////////////////////////////// | |
81 // register a global string | |
82 // | |
83 static char* register_string(char *name); | |
84 static char* register_string(char *name) { | |
85 return register_string(all_strings, name); | |
86 } | |
87 | |
88 | |
89 //////////////////////////////////////////////// | |
90 // make a unique string | |
91 // | |
92 static char* unique_string(char *name); | |
93 static char* unique_string(char *name) { | |
94 int unique = 2; | |
95 string_set::iterator i = all_strings.find(name); | |
96 if (i == all_strings.end()) return register_string(name); | |
97 while (true) { | |
98 char n[strlen(name)+10]; | |
99 snprintf(n, sizeof(n), "%s %d", name, unique++); | |
100 string_set::iterator i = all_strings.find(n); | |
101 if (i == all_strings.end()) return register_string(n); | |
102 } | |
103 } | |
104 | |
105 | |
106 //////////////////////////////////////////////// | |
107 // remove leading and trailing blanks | |
108 // | |
109 static char *trim(char *name); | |
110 static char *trim(char *name) { | |
111 char *p; | |
112 while (*name == ' ') name++; | |
113 p = name + strlen(name) - 1; | |
114 while ((p >= name) && (*p == ' ')) *p-- = '\0'; | |
115 return name; | |
116 } | |
117 | |
118 | |
119 static void process(pst_desc_ll *d_ptr); | |
120 static void process(pst_desc_ll *d_ptr) { | |
121 pst_item *item = NULL; | |
122 while (d_ptr) { | |
123 if (d_ptr->desc) { | |
52 | 124 item = pst_parse_item(&pstfile, d_ptr); |
16 | 125 DEBUG_INFO(("item pointer is %p\n", item)); |
126 if (item) { | |
127 if (item->message_store) { | |
128 // there should only be one message_store, and we have already done it | |
129 DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); | |
130 } | |
131 | |
132 if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) { | |
133 //if this is a non-empty folder other than deleted items, we want to recurse into it | |
134 fprintf(stderr, "entering folder %s\n", item->file_as); | |
135 process(d_ptr->child); | |
136 } else if (item->contact) { | |
137 // deal with a contact | |
138 if (item->type != PST_TYPE_CONTACT) { | |
139 DIE(("type should be contact\n")); | |
140 } | |
141 else if (item->contact == NULL) { // this is an incorrect situation. Inform user | |
142 DIE(("null item contact\n")); | |
143 } else { | |
144 char cn[1000]; | |
145 snprintf(cn, sizeof(cn), "%s %s %s %s", | |
146 single(item->contact->display_name_prefix), | |
147 single(item->contact->first_name), | |
148 single(item->contact->surname), | |
149 single(item->contact->suffix)); | |
150 if (strcmp(cn, " ")) { | |
151 // fprintf(stderr, "\n\n\n"); | |
152 // fprintf(stderr, "access_method %s\n", item->contact->access_method); | |
153 // fprintf(stderr, "account_name %s\n", item->contact->account_name); | |
154 // fprintf(stderr, "address1 %s\n", item->contact->address1); | |
155 // fprintf(stderr, "address1_desc %s\n", item->contact->address1_desc); | |
156 // fprintf(stderr, "address1_transport %s\n", item->contact->address1_transport); | |
157 // fprintf(stderr, "address2 %s\n", item->contact->address2); | |
158 // fprintf(stderr, "address2_desc %s\n", item->contact->address2_desc); | |
159 // fprintf(stderr, "address2_transport %s\n", item->contact->address2_transport); | |
160 // fprintf(stderr, "address3 %s\n", item->contact->address3); | |
161 // fprintf(stderr, "address3_desc %s\n", item->contact->address3_desc); | |
162 // fprintf(stderr, "address3_transport %s\n", item->contact->address3_transport); | |
163 // fprintf(stderr, "assistant_name %s\n", item->contact->assistant_name); | |
164 // fprintf(stderr, "assistant_phone %s\n", item->contact->assistant_phone); | |
165 // fprintf(stderr, "billing_information %s\n", item->contact->billing_information); | |
166 // fprintf(stderr, "business_address %s\n", item->contact->business_address); | |
167 // fprintf(stderr, "business_city %s\n", item->contact->business_city); | |
168 // fprintf(stderr, "business_country %s\n", item->contact->business_country); | |
169 // fprintf(stderr, "business_fax %s\n", item->contact->business_fax); | |
170 // fprintf(stderr, "business_homepage %s\n", item->contact->business_homepage); | |
171 // fprintf(stderr, "business_phone %s\n", item->contact->business_phone); | |
172 // fprintf(stderr, "business_phone2 %s\n", item->contact->business_phone2); | |
173 // fprintf(stderr, "business_po_box %s\n", item->contact->business_po_box); | |
174 // fprintf(stderr, "business_postal_code %s\n", item->contact->business_postal_code); | |
175 // fprintf(stderr, "business_state %s\n", item->contact->business_state); | |
176 // fprintf(stderr, "business_street %s\n", item->contact->business_street); | |
177 // fprintf(stderr, "callback_phone %s\n", item->contact->callback_phone); | |
178 // fprintf(stderr, "car_phone %s\n", item->contact->car_phone); | |
179 // fprintf(stderr, "company_main_phone %s\n", item->contact->company_main_phone); | |
180 // fprintf(stderr, "company_name %s\n", item->contact->company_name); | |
181 // fprintf(stderr, "computer_name %s\n", item->contact->computer_name); | |
182 // fprintf(stderr, "customer_id %s\n", item->contact->customer_id); | |
183 // fprintf(stderr, "def_postal_address %s\n", item->contact->def_postal_address); | |
184 // fprintf(stderr, "department %s\n", item->contact->department); | |
185 // fprintf(stderr, "display_name_prefix %s\n", item->contact->display_name_prefix); | |
186 // fprintf(stderr, "first_name %s\n", item->contact->first_name); | |
187 // fprintf(stderr, "followup %s\n", item->contact->followup); | |
188 // fprintf(stderr, "free_busy_address %s\n", item->contact->free_busy_address); | |
189 // fprintf(stderr, "ftp_site %s\n", item->contact->ftp_site); | |
190 // fprintf(stderr, "fullname %s\n", item->contact->fullname); | |
191 // fprintf(stderr, "gov_id %s\n", item->contact->gov_id); | |
192 // fprintf(stderr, "hobbies %s\n", item->contact->hobbies); | |
193 // fprintf(stderr, "home_address %s\n", item->contact->home_address); | |
194 // fprintf(stderr, "home_city %s\n", item->contact->home_city); | |
195 // fprintf(stderr, "home_country %s\n", item->contact->home_country); | |
196 // fprintf(stderr, "home_fax %s\n", item->contact->home_fax); | |
197 // fprintf(stderr, "home_phone %s\n", item->contact->home_phone); | |
198 // fprintf(stderr, "home_phone2 %s\n", item->contact->home_phone2); | |
199 // fprintf(stderr, "home_po_box %s\n", item->contact->home_po_box); | |
200 // fprintf(stderr, "home_postal_code %s\n", item->contact->home_postal_code); | |
201 // fprintf(stderr, "home_state %s\n", item->contact->home_state); | |
202 // fprintf(stderr, "home_street %s\n", item->contact->home_street); | |
203 // fprintf(stderr, "initials %s\n", item->contact->initials); | |
204 // fprintf(stderr, "isdn_phone %s\n", item->contact->isdn_phone); | |
205 // fprintf(stderr, "job_title %s\n", item->contact->job_title); | |
206 // fprintf(stderr, "keyword %s\n", item->contact->keyword); | |
207 // fprintf(stderr, "language %s\n", item->contact->language); | |
208 // fprintf(stderr, "location %s\n", item->contact->location); | |
209 // fprintf(stderr, "manager_name %s\n", item->contact->manager_name); | |
210 // fprintf(stderr, "middle_name %s\n", item->contact->middle_name); | |
211 // fprintf(stderr, "mileage %s\n", item->contact->mileage); | |
212 // fprintf(stderr, "mobile_phone %s\n", item->contact->mobile_phone); | |
213 // fprintf(stderr, "nickname %s\n", item->contact->nickname); | |
214 // fprintf(stderr, "office_loc %s\n", item->contact->office_loc); | |
215 // fprintf(stderr, "org_id %s\n", item->contact->org_id); | |
216 // fprintf(stderr, "other_address %s\n", item->contact->other_address); | |
217 // fprintf(stderr, "other_city %s\n", item->contact->other_city); | |
218 // fprintf(stderr, "other_country %s\n", item->contact->other_country); | |
219 // fprintf(stderr, "other_phone %s\n", item->contact->other_phone); | |
220 // fprintf(stderr, "other_po_box %s\n", item->contact->other_po_box); | |
221 // fprintf(stderr, "other_postal_code %s\n", item->contact->other_postal_code); | |
222 // fprintf(stderr, "other_state %s\n", item->contact->other_state); | |
223 // fprintf(stderr, "other_street %s\n", item->contact->other_street); | |
224 // fprintf(stderr, "pager_phone %s\n", item->contact->pager_phone); | |
225 // fprintf(stderr, "personal_homepage %s\n", item->contact->personal_homepage); | |
226 // fprintf(stderr, "pref_name %s\n", item->contact->pref_name); | |
227 // fprintf(stderr, "primary_fax %s\n", item->contact->primary_fax); | |
228 // fprintf(stderr, "primary_phone %s\n", item->contact->primary_phone); | |
229 // fprintf(stderr, "profession %s\n", item->contact->profession); | |
230 // fprintf(stderr, "radio_phone %s\n", item->contact->radio_phone); | |
231 // fprintf(stderr, "spouse_name %s\n", item->contact->spouse_name); | |
232 // fprintf(stderr, "suffix %s\n", item->contact->suffix); | |
233 // fprintf(stderr, "surname %s\n", item->contact->surname); | |
234 // fprintf(stderr, "telex %s\n", item->contact->telex); | |
235 // fprintf(stderr, "transmittable_display_name %s\n", item->contact->transmittable_display_name); | |
236 // fprintf(stderr, "ttytdd_phone %s\n", item->contact->ttytdd_phone); | |
237 // have a valid cn | |
238 char *ucn = unique_string(folded(trim(cn))); | |
239 printf("dn: cn=%s, %s\n", ucn, ldap_base); | |
240 printf("cn: %s\n", ucn); | |
241 if (item->contact->first_name) { | |
242 snprintf(cn, sizeof(cn), "%s %s", | |
243 single(item->contact->display_name_prefix), | |
244 single(item->contact->first_name)); | |
245 printf("givenName: %s\n", trim(cn)); | |
246 } | |
247 if (item->contact->surname) { | |
248 snprintf(cn, sizeof(cn), "%s %s", | |
249 single(item->contact->surname), | |
250 single(item->contact->suffix)); | |
251 printf("sn: %s\n", trim(cn)); | |
252 } | |
253 else if (item->contact->company_name) { | |
254 printf("sn: %s\n", single(item->contact->company_name)); | |
255 } | |
256 else | |
257 printf("sn: %s\n", ucn); // use cn as sn if we cannot find something better | |
258 | |
259 if (item->contact->job_title) | |
260 printf("personalTitle: %s\n", single(item->contact->job_title)); | |
261 if (item->contact->company_name) | |
262 printf("company: %s\n", single(item->contact->company_name)); | |
263 if (item->contact->address1 && *item->contact->address1) | |
264 printf("mail: %s\n", single(item->contact->address1)); | |
265 if (item->contact->address2 && *item->contact->address2) | |
266 printf("mail: %s\n", single(item->contact->address2)); | |
267 if (item->contact->address3 && *item->contact->address3) | |
268 printf("mail: %s\n", single(item->contact->address3)); | |
269 if (item->contact->address1a && *item->contact->address1a) | |
270 printf("mail: %s\n", single(item->contact->address1a)); | |
271 if (item->contact->address2a && *item->contact->address2a) | |
272 printf("mail: %s\n", single(item->contact->address2a)); | |
273 if (item->contact->address3a && *item->contact->address3a) | |
274 printf("mail: %s\n", single(item->contact->address3a)); | |
275 if (item->contact->business_address) { | |
276 if (item->contact->business_po_box) | |
277 printf("postalAddress: %s\n", single(item->contact->business_po_box)); | |
278 if (item->contact->business_street) | |
279 multi("postalAddress: %s\n", item->contact->business_street); | |
280 if (item->contact->business_city) | |
281 printf("l: %s\n", single(item->contact->business_city)); | |
282 if (item->contact->business_state) | |
283 printf("st: %s\n", single(item->contact->business_state)); | |
284 if (item->contact->business_postal_code) | |
285 printf("postalCode: %s\n", single(item->contact->business_postal_code)); | |
286 } | |
287 else if (item->contact->home_address) { | |
288 if (item->contact->home_po_box) | |
289 printf("postalAddress: %s\n", single(item->contact->home_po_box)); | |
290 if (item->contact->home_street) | |
291 multi("postalAddress: %s\n", item->contact->home_street); | |
292 if (item->contact->home_city) | |
293 printf("l: %s\n", single(item->contact->home_city)); | |
294 if (item->contact->home_state) | |
295 printf("st: %s\n", single(item->contact->home_state)); | |
296 if (item->contact->home_postal_code) | |
297 printf("postalCode: %s\n", single(item->contact->home_postal_code)); | |
298 } | |
299 else if (item->contact->other_address) { | |
300 if (item->contact->other_po_box) | |
301 printf("postalAddress: %s\n", single(item->contact->other_po_box)); | |
302 if (item->contact->other_street) | |
303 multi("postalAddress: %s\n", item->contact->other_street); | |
304 if (item->contact->other_city) | |
305 printf("l: %s\n", single(item->contact->other_city)); | |
306 if (item->contact->other_state) | |
307 printf("st: %s\n", single(item->contact->other_state)); | |
308 if (item->contact->other_postal_code) | |
309 printf("postalCode: %s\n", single(item->contact->other_postal_code)); | |
310 } | |
311 if (item->contact->business_fax) | |
312 printf("facsimileTelephoneNumber: %s\n", single(item->contact->business_fax)); | |
313 else if (item->contact->home_fax) | |
314 printf("facsimileTelephoneNumber: %s\n", single(item->contact->home_fax)); | |
315 | |
316 if (item->contact->business_phone) | |
317 printf("telephoneNumber: %s\n", single(item->contact->business_phone)); | |
318 if (item->contact->home_phone) | |
319 printf("homePhone: %s\n", single(item->contact->home_phone)); | |
320 | |
321 if (item->contact->car_phone) | |
322 printf("mobile: %s\n", single(item->contact->car_phone)); | |
323 else if (item->contact->mobile_phone) | |
324 printf("mobile: %s\n", single(item->contact->mobile_phone)); | |
325 else if (item->contact->other_phone) | |
326 printf("mobile: %s\n", single(item->contact->other_phone)); | |
327 | |
328 | |
329 if (item->comment) | |
330 printf("description: %s\n", single(item->comment)); | |
331 | |
332 printf("objectClass: %s\n\n", ldap_class); | |
333 } | |
334 } | |
335 } | |
336 else { | |
337 DEBUG_INFO(("item is not a contact\n")); | |
338 } | |
339 } | |
46 | 340 pst_freeItem(item); |
16 | 341 } |
342 d_ptr = d_ptr->next; | |
343 } | |
344 } | |
345 | |
346 | |
347 int main(int argc, char** argv) { | |
348 pst_desc_ll *d_ptr; | |
349 char *fname = NULL; | |
350 char *temp = NULL; //temporary char pointer | |
351 char c; | |
33
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
352 char *d_log = NULL; |
16 | 353 prog_name = argv[0]; |
354 pst_item *item = NULL; | |
355 | |
33
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
356 while ((c = getopt(argc, argv, "b:c:d:Vh"))!= -1) { |
16 | 357 switch (c) { |
358 case 'b': | |
359 ldap_base = optarg; | |
360 temp = strchr(ldap_base, ','); | |
361 if (temp) { | |
362 *temp = '\0'; | |
363 ldap_org = strdup(ldap_base+2); // assume first 2 chars are o= | |
364 *temp = ','; | |
365 } | |
366 break; | |
367 case 'c': | |
368 ldap_class = optarg; | |
369 break; | |
33
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
370 case 'd': |
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
371 d_log = optarg; |
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
372 break; |
16 | 373 case 'h': |
374 usage(); | |
375 exit(0); | |
376 break; | |
377 case 'V': | |
378 version(); | |
379 exit(0); | |
380 break; | |
381 default: | |
382 usage(); | |
383 exit(1); | |
384 break; | |
385 } | |
386 } | |
387 | |
388 if ((argc > optind) && (ldap_base) && (ldap_class) && (ldap_org)) { | |
389 fname = argv[optind]; | |
390 } else { | |
391 usage(); | |
392 exit(2); | |
393 } | |
394 | |
395 #ifdef DEBUG_ALL | |
33
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
396 // force a log file |
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
397 if (!d_log) d_log = "pst2ldif.log"; |
16 | 398 #endif |
33
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
399 DEBUG_INIT(d_log); |
12cac756bc05
enable -d option, but if not specified, don't generate a debug file
carl
parents:
22
diff
changeset
|
400 DEBUG_REGISTER_CLOSE(); |
16 | 401 DEBUG_ENT("main"); |
59
7d5c637aaafb
General cleanup and code fixes.
Carl Byington <carl@five-ten-sg.com>
parents:
52
diff
changeset
|
402 RET_DERROR(pst_open(&pstfile, fname), 1, ("Error opening File\n")); |
16 | 403 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n")); |
404 | |
405 pst_load_extended_attributes(&pstfile); | |
406 | |
407 d_ptr = pstfile.d_head; // first record is main record | |
46 | 408 item = (pst_item*)pst_parse_item(&pstfile, d_ptr); |
16 | 409 if (!item || !item->message_store) { |
410 DEBUG_RET(); | |
411 DIE(("main: Could not get root record\n")); | |
412 } | |
413 | |
414 d_ptr = pst_getTopOfFolders(&pstfile, item); | |
415 if (!d_ptr) { | |
416 DEBUG_RET(); | |
417 DIE(("Top of folders record not found. Cannot continue\n")); | |
418 } | |
419 | |
46 | 420 pst_freeItem(item); |
16 | 421 |
422 // write the ldap header | |
423 printf("dn: %s\n", ldap_base); | |
424 printf("o: %s\n", ldap_org); | |
425 printf("objectClass: organization\n\n"); | |
426 printf("dn: cn=root, %s\n", ldap_base); | |
427 printf("cn: root\n"); | |
428 printf("objectClass: %s\n\n", ldap_class); | |
429 | |
430 process(d_ptr->child); // do the children of TOPF | |
431 pst_close(&pstfile); | |
432 DEBUG_RET(); | |
41
183ae993b9ad
security fix for potential buffer overrun in lz decompress
carl
parents:
38
diff
changeset
|
433 free_strings(all_strings); |
16 | 434 return 0; |
435 } | |
436 | |
437 | |
438 int usage() { | |
439 version(); | |
440 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); | |
441 printf("OPTIONS:\n"); | |
442 printf("\t-h\t- Help. This screen\n"); | |
443 printf("\t-V\t- Version. Display program version\n"); | |
444 printf("\t-b ldapbase\t- set the ldap base value\n"); | |
445 printf("\t-c class \t- set the class of the ldap objects\n"); | |
446 return 0; | |
447 } | |
448 | |
449 | |
450 int version() { | |
451 printf("pst2ldif v%s\n", VERSION); | |
452 #if BYTE_ORDER == BIG_ENDIAN | |
453 printf("Big Endian implementation being used.\n"); | |
454 #elif BYTE_ORDER == LITTLE_ENDIAN | |
455 printf("Little Endian implementation being used.\n"); | |
456 #else | |
457 # error "Byte order not supported by this library" | |
458 #endif | |
459 #ifdef __GNUC__ | |
460 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__); | |
461 #endif | |
462 return 0; | |
463 } | |
464 | |
465 | |
466 // my_stristr varies from strstr in that its searches are case-insensitive | |
467 char * my_stristr(char *haystack, char *needle) { | |
468 char *x=haystack, *y=needle, *z = NULL; | |
469 if (haystack == NULL || needle == NULL) | |
470 return NULL; | |
471 while (*y != '\0' && *x != '\0') { | |
472 if (tolower(*y) == tolower(*x)) { | |
473 // move y on one | |
474 y++; | |
475 if (z == NULL) { | |
476 z = x; // store first position in haystack where a match is made | |
477 } | |
478 } else { | |
479 y = needle; // reset y to the beginning of the needle | |
480 z = NULL; // reset the haystack storage point | |
481 } | |
482 x++; // advance the search in the haystack | |
483 } | |
484 return z; | |
485 } | |
486 | |
487 | |
488 char *check_filename(char *fname) { | |
489 char *t = fname; | |
490 if (t == NULL) { | |
491 return fname; | |
492 } | |
493 while ((t = strpbrk(t, "/\\:"))) { | |
494 // while there are characters in the second string that we don't want | |
495 *t = '_'; //replace them with an underscore | |
496 } | |
497 return fname; | |
498 } | |
499 | |
500 | |
501 char *single(char *str) { | |
502 if (!str) return ""; | |
503 char *ret = rfc2426_escape(str); | |
504 char *n = strchr(ret, '\n'); | |
505 if (n) *n = '\0'; | |
506 return ret; | |
507 } | |
508 | |
509 | |
510 char *folded(char *str) { | |
511 if (!str) return ""; | |
512 char *ret = rfc2426_escape(str); | |
513 char *n = ret; | |
514 while (n = strchr(n, '\n')) { | |
515 *n = ' '; | |
516 } | |
517 n = ret; | |
518 while (n = strchr(n, ',')) { | |
519 *n = ' '; | |
520 } | |
521 return ret; | |
522 } | |
523 | |
524 | |
525 void multi(char *fmt, char *str) { | |
526 if (!str) return; | |
527 char *ret = rfc2426_escape(str); | |
528 char *n = ret; | |
529 while (n = strchr(ret, '\n')) { | |
530 *n = '\0'; | |
531 printf(fmt, ret); | |
532 ret = n+1; | |
533 } | |
534 if (*ret) printf(fmt, ret); | |
535 } | |
536 | |
537 | |
538 char *rfc2426_escape(char *str) { | |
539 static char* buf = NULL; | |
540 char *ret, *a, *b; | |
541 int x = 0, y, z; | |
542 if (str == NULL) | |
543 ret = str; | |
544 else { | |
545 | |
546 // calculate space required to escape all the following characters | |
38 | 547 y = chr_count(str, '\\') |
548 + chr_count(str, ';'); | |
16 | 549 z = chr_count(str, '\r'); |
550 if (y == 0 && z == 0) | |
551 // there isn't any extra space required | |
552 ret = str; | |
553 else { | |
38 | 554 x = strlen(str) + y - z + 1; // don't forget room for the NUL |
555 buf = (char*) realloc(buf, x); | |
16 | 556 a = str; |
557 b = buf; | |
558 while (*a != '\0') { | |
559 switch(*a) { | |
560 case '\\': | |
561 case ';' : | |
562 *(b++)='\\'; | |
563 *b=*a; | |
564 break; | |
38 | 565 case '\r': // skip cr |
566 b--; | |
16 | 567 break; |
568 default: | |
569 *b=*a; | |
570 } | |
571 b++; | |
572 a++; | |
573 } | |
38 | 574 *b = '\0'; // NUL-terminate the string (buf) |
16 | 575 ret = buf; |
576 } | |
577 } | |
578 return ret; | |
579 } | |
580 | |
581 | |
582 int chr_count(char *str, char x) { | |
583 int r = 0; | |
584 while (*str != '\0') { | |
585 if (*str == x) | |
586 r++; | |
587 str++; | |
588 } | |
589 return r; | |
590 } | |
591 |