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