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 }