1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 2000, Sun Microsystems, Inc. All rights reserved. */ 22 23 #pragma ident "@(#)lcl_parse_header.c 1.3 00/01/07 SMI" 24 25 /* 26 * Determine velues by parsing mime header, then update the 27 * attribute values. It override the default values in DB. 28 */ 29 #include <string.h> 30 #include <stdlib.h> 31 32 #include "lcl.h" 33 #include "lcl_internal.h" 34 35 #define ENCODE_BEGIN "=?" 36 #define CHARSET_DONE '?' 37 #define ENCODING_DONE '?' 38 #define ENCODE_DONE "?=" 39 40 #define ENCODE_BASE64 "?B?" 41 #define ENCODE_QP "?Q?" 42 #define ENCODE_NONE 0 43 44 #define MIME_VERSION "Mime-Version" 45 #define CONTENT_TYPE "Content-Type" 46 #define TYPE_TEXTPLAIN "Text/Plain" 47 #define CHARSET "charset" 48 49 #define X_SUN_ATTACHEMENT "X-sun-attachment" 50 #define X_SUN "X-Sun" 51 #define X_SUN_CHARSET "X-Sun-Charset" 52 53 typedef enum {False=0, True = 1} Bool; 54 #define Private static; 55 56 /* 57 * Public functions. 58 * ---------------- 59 * 1. 60 * char* _lcl_parse_body(char* h, // unparsed header:in 61 * char* b // unparsed body:in 62 * LclMailType type // Mail type:in 63 * ) 64 * returns the parsed(converted) Body 65 * 66 * 2. 67 * char* _lcl_parse_header(char* h, // unparsed header:in 68 * char* b, // unparsed body:in 69 * LclMailType *type // Mail type:inout 70 * char** charset // charset of parsed header:out 71 * ) 72 * returns the parsed(converted) header 73 * 74 * 3 75 * returns Mail type. 76 * LclMailType _lcl_get_body_charset(char* h, // unparsed header:in 77 * char* b, // unparsed body:in 78 * LclMailType type // Mail type:in 79 * char** charset // charset of parsed header:out 80 * charset CAN BE NULL if it is UNKNOWN.(or NOT IMPLEMENTED YET ;-) 81 * 82 */ 83 84 /*/// Need lcld for all functions for MT */ 85 86 static Bool 87 _is_mime_header(char* h){ 88 Bool is_mime = False ; 89 if(!h) return False ; 90 if(strcasestr(h, MIME_VERSION) || 91 strcasestr(h, CONTENT_TYPE) || 92 (strstr(h, ENCODE_BEGIN) && strstr(h, ENCODE_DONE) && 93 (strcasestr(h, ENCODE_BASE64) || strcasestr(h, ENCODE_QP))) 94 ) { 95 is_mime = True ; 96 } 97 return is_mime ; 98 } 99 100 static Bool 101 _is_V3_header(char* h){ 102 /* 103 * case 1: X-Sun-Attachment is found. 104 * case 2: Header looks like 822, but other X-Sun- header is found. 105 * case 3: Header looks like 822, but X-Sun-Charset is found in Body. 106 * otherwise it should be 822. 107 */ 108 if(h && strcasestr(h, X_SUN)){ 109 return True ; 110 } 111 /* case 3 is missing */ 112 return False ; /* should be 822 */ 113 } 114 115 static char* 116 _lcl_V3_header(char* h){ 117 int len = strlen(h); 118 char* orig = malloc(len +1); 119 memcpy(orig, h, len+1); 120 return orig ; /* Waiting for full implementation */ 121 } 122 123 static char* 124 _lcl_822_header(char* h){ 125 int len = strlen(h); 126 char* orig = malloc(len +1); 127 memcpy(orig, h, len+1); 128 return orig ; /* Waiting for full implementation */ 129 } 130 131 static char * 132 copy_next_line(char** cur_p, char* copy_p, int *len_p){ 133 char *p = *cur_p ; 134 char* next_line = strchr(p, '\n') ; 135 if(next_line){ 136 int len = next_line - p ; 137 strncpy(copy_p, p, len); 138 *cur_p = next_line ; 139 *len_p = len ; 140 return copy_p; 141 } 142 return 0 ; 143 } 144 145 static char * 146 dup_next_line(char** cur_p, int *len_p){ 147 char *p = *cur_p ; 148 char* next_line = strchr(p, '\n') ; 149 if(next_line){ 150 int len = next_line - p ; 151 char *buf = (char*)malloc(len + 1); 152 strncpy(buf, p, len); 153 buf[len] = (char)0; 154 *cur_p = next_line ; 155 *len_p = len ; 156 return buf; 157 } 158 return 0 ; 159 } 160 161 162 static char* 163 _lcl_mime_header(char* h, char **charset){ 164 int len = strlen(h) ; 165 char* orig = malloc(len +1); 166 char* buf = malloc(len*10/8); /* XXX guestimation to be safer side. */ 167 memcpy(orig, h, len+1); 168 MIME_strHeaderDecode(orig, buf, len, charset); 169 free(orig); 170 return buf ; 171 } 172 /* 173 * returns Mail type. 174 * LclMailType _lcl_get_body_charset(char* t, // unparsed taggedtext:in 175 * LclMailType *type // Mail type:out 176 * char** charset // charset of parsed header:out 177 * ) 178 */ 179 LclMailType 180 _lcl_get_taggedtext_charset(char* t, LclMailType type, char** charset){ 181 if( type == LclV3Type || 182 (type == LclUnKnownType && _is_V3_header(t) == True)){ 183 184 } else { /* Must be MIME - No 822type for tagged text*/ 185 /* 186 * Body charset information is in header. 187 */ 188 char *p = strcasestr(t, "\nContent-Type:"); 189 if(!p){ 190 char *x = strcasestr(t, "Content-Type:"); 191 if(x == t) 192 p = t ; 193 } 194 if(p){ 195 char* eoline = strchr(p+1, '\n'); 196 if(eoline){ 197 p = strcasestr(p+14, "charset=") ; 198 if(p && (p < eoline)){ 199 int len = eoline - (p+=8) ; /* skip "charset=" */ 200 *charset = malloc(len +1); 201 strncpy(*charset, p, len); 202 (*charset)[len] = NULL ; 203 } else *charset = NULL ; 204 } else *charset = NULL ; 205 } else *charset = NULL ; 206 return LclMIMEType ; 207 } 208 } 209 /* 210 * returns Mail type. 211 * LclMailType _lcl_get_body_charset(char* h, // unparsed header:in 212 * char* b, // unparsed body:in 213 * LclMailType *type // Mail type:out 214 * char** charset // charset of parsed header:out 215 * ) 216 */ 217 LclMailType 218 _lcl_get_body_charset(char* h, char* b, LclMailType type, char** charset){ 219 if( type == LclMIMEType || 220 (type == LclUnKnownType && _is_mime_header(h) == True)){ 221 /* 222 * Body charset information is in header. 223 */ 224 char *p = strcasestr(h, "\nContent-Type:"); 225 if(!p){ 226 char *x = strcasestr(h, "Content-Type:"); 227 if(x == h) 228 p = h ; 229 } 230 if(p){ 231 char* eoline = strchr(p+1, '\n'); 232 if(eoline){ 233 p = strcasestr(p+14, "charset=") ; 234 if(p && (p < eoline)){ 235 int len = eoline - (p+=8) ; /* skip "charset=" */ 236 *charset = malloc(len +1); 237 strncpy(*charset, p, len); 238 (*charset)[len] = NULL ; 239 } else *charset = NULL ; 240 } else *charset = NULL ; 241 } else *charset = NULL ; 242 return LclMIMEType ; 243 } else if( type == LclV3Type || 244 (type == LclUnKnownType && _is_V3_header(h) == True)){ 245 /* 246 * Body charset information is in header when there is no 247 * attachment. 248 */ 249 char *p = strcasestr(h, "\nX-Sun-Charset:"); 250 if(!p) p = strcasestr(b, "\nX-Sun-Charset:"); 251 if(p){ 252 char* eoline = strchr(p+1, '\n'); 253 if(eoline){ 254 p+=15 ; /* skipping "\nX-Sun-Charset:" */ 255 while(isspace(*++p)); /* skipping space */ 256 if(p < eoline){ 257 int len = eoline - p ; /* skip "charset=" */ 258 *charset = malloc(len +1); 259 strncpy(*charset, p, len); 260 (*charset)[len] = NULL ; 261 } else *charset = NULL ; 262 } else *charset = NULL ; 263 } else *charset = NULL ; 264 /* 265 * Body charset information is in body 266 */ 267 return LclV3Type ; 268 } else { 269 *charset = NULL ; /* Unknown */ 270 return Lcl822Type ; 271 } 272 } 273 /* 274 * returns the parsed(converted) header 275 * char* _lcl_parse_header(char* h, // unparsed header:in 276 * char* b, // unparsed body:in 277 * LclMailType *type // Mail type:out 278 * char** charset // charset of parsed header:out 279 * ) 280 */ 281 char* 282 _lcl_parse_header(char* h, char* b, LclMailType *type ,char** charset){ 283 LclMailType mail_type = _lcl_get_body_charset(h, b, *type, charset); 284 if(*charset) 285 free(*charset); 286 *charset = (char *)NULL; 287 288 switch(mail_type){ 289 case LclMIMEType: 290 return _lcl_mime_decode_header(h, strlen(h), charset); 291 case LclV3Type: 292 return _lcl_V3_header(h); 293 case Lcl822Type: 294 return _lcl_mime_decode_header(h, strlen(h), charset); 295 default: 296 break ; 297 } 298 } 299 300 static Bool 301 _is_mime_body(char* h){ 302 return strcasestr(h, MIME_VERSION)?True:False ; /* Too easy? */ 303 } 304 305 static Bool 306 _is_V3_body(char* h){ 307 /* 308 * case 1: X-Sun-Attachment is found. 309 * case 2: Header looks like 822, but other X-Sun- header is found. 310 * case 3: Header looks like 822, but X-Sun-Charset is found in Body. 311 * otherwise it should be 822. 312 */ 313 if(strcasestr(h, X_SUN)){ 314 return True ; 315 } 316 /* case 3 is missing */ 317 return False ; /* should be 822 */ 318 } 319 320 static char* 321 _lcl_mime_body(char* b){ 322 return b ; /* Waiting for full implementation */ 323 } 324 325 326 static char* 327 _lcl_V3_body(char* b){ 328 return b ; /* Waiting for full implementation */ 329 } 330 331 static char* 332 _lcl_822_body(char* b){ 333 return b ; /* Waiting for full implementation */ 334 } 335 336 /* 337 * returns the parsed(converted) Body 338 * char* _lcl_parse_body(char* h, // unparsed header:in 339 * char* b // unparsed body:in 340 * ) 341 */ 342 char* 343 _lcl_parse_body(char* h, /* unparsed header:in */ 344 char* b, /* unparsed body:in */ 345 LclMailType type /* Mail type:in */){ 346 if( type == LclMIMEType || 347 (type == LclUnKnownType && h &&_is_mime_header(h) == True)){ 348 char *p ; 349 if(h){ 350 p = strcasestr(h, "\nContent-Transfer-Encoding:"); 351 } 352 if(!p){ 353 char *x = strcasestr(h, "Content-Transfer-Encoding:"); 354 if(x == h) 355 p = h ; 356 } 357 if(p){ 358 char* eoline = strchr(p+1, '\n'); 359 if(eoline){ 360 char *save_p=p; 361 int b_len = strlen(b) ; 362 p = strcasestr(p+27, "quoted-printable"); 363 if(p && (p < eoline)){ 364 char *eb = malloc(b_len + 1); 365 char *db = malloc(b_len + 1); 366 memcpy(eb, b, b_len + 1); 367 str_fromqp(eb, b_len, db, b_len); 368 free(eb); 369 return db ; 370 } else { 371 p = strcasestr(save_p+27, "base64"); 372 if(p && (p < eoline)){ 373 char *eb = malloc(b_len + 1); 374 char *db = malloc(b_len + 1); 375 memcpy(eb, b, b_len + 1); 376 str_from64(eb, b_len, db, b_len); 377 free(eb); 378 return db ; 379 } 380 } 381 } 382 } 383 return NULL ; 384 } else { 385 /* No decoding for V3 and 822 */ 386 return NULL ; 387 } 388 } 389 390 char* 391 _lcl_encode_body(char* b, /* unparsed body:in */ 392 LclMailType type, /* Mail type:in */ 393 char* charset, /* to charset:in */ 394 LclMailEncoding e /* base64/QP */ 395 ){ 396 int b_len = strlen(b); 397 char* orig = malloc(b_len+1); 398 char* eb ; 399 memcpy(orig, b, b_len + 1); 400 switch(e){ 401 case LclBase64Encoding: 402 eb = malloc(b_len*3+1); 403 str_to64(orig, b_len, eb, b_len*3, 0);/* no portable newline */ 404 free(orig); 405 break ; 406 case LclQPEncoding: 407 eb = malloc(b_len*2+1); 408 str_toqp(orig, b_len, eb, b_len*2, 0);/* no portable newline */ 409 free(orig); 410 break ; 411 case Lcl822Encoding: 412 case LclUnKnownEncoding: 413 default: 414 eb = orig ; 415 break ; 416 } 417 return eb ; 418 } 419 420 char* 421 _lcl_encode_header(char* h, /* unparsed header:in */ 422 LclMailType type, /* Mail type:in */ 423 char* charset, /* to charset:in */ 424 LclMailEncoding he, /* header B/Q:in */ 425 LclMailEncoding be, /* body base64/QP:in */ 426 boolean_t add_header/* add if true:in */ 427 ){ 428 char *eh; 429 switch(he){ 430 case LclBase64Encoding: 431 eh = _lcl_mime_encode_header(h, strlen(h), he, charset); 432 if(add_header == B_TRUE){ 433 434 } 435 break ; 436 case LclQPEncoding: 437 eh = _lcl_mime_encode_header(h, strlen(h), he, charset); 438 if(add_header == B_TRUE){ 439 440 } 441 break ; 442 case Lcl822Encoding: 443 case LclUnKnownEncoding: 444 default: 445 eh = (char *)NULL; 446 break ; 447 } 448 return eh ; 449 } 450 451 char* 452 _lcl_encode_taggedtext(char* t, /* unparsed taggedtext:in */ 453 LclMailType type, /* Mail type:in */ 454 char* charset, /* to charset:in */ 455 LclMailEncoding e, /* base64/QP */ 456 boolean_t add_header/* add if true:in */ 457 ){ 458 char* et = _lcl_encode_body(t, type, charset, e); 459 if(add_header == B_TRUE){ 460 461 } 462 } 463 464 char* 465 _lcl_parse_taggedtext(char* t, /* unparsed taggedtext:in */ 466 LclMailType *type, /* Mail type:in */ 467 char** charset /* charset of parsed text:out */ 468 ){ 469 if(*type == LclUnKnownType){ 470 if(_is_V3_header(t)){ 471 *type = LclV3Type ; 472 } else { 473 *type = LclMIMEType ; 474 } 475 } 476 return _lcl_parse_header(t, t, type , charset); 477 } 478 479 /*//////////////////////////////////////////////////*/ 480 char* 481 _lcl_encode_taggedtext_body(char* b, /* unparsed body:in */ 482 LclMailType type, /* Mail type:in */ 483 char* charset, /* to charset:in */ 484 LclMailEncoding e /* base64/QP */ 485 ){ 486 if(type == LclUnKnownType){ 487 type = LclMIMEType ; /* Brute force */ 488 } 489 return _lcl_encode_body(b, type, charset, e); 490 } 491 492 char* 493 _lcl_encode_taggedtext_header(char* h, /* unparsed header:in */ 494 LclMailType type, /* Mail type:in */ 495 char* charset, /* to charset:in */ 496 LclMailEncoding he, /* header B/Q:in */ 497 LclMailEncoding be, /* body base64/QP:in */ 498 boolean_t add_header /* add if true:in */ 499 ){ 500 if(type == LclUnKnownType){ 501 if(_is_V3_header(h)){ 502 type = LclV3Type ; 503 } else { 504 type = LclMIMEType ; 505 } 506 } 507 return _lcl_encode_header(h, type, charset, he, be, add_header); 508 } 509 510 char* 511 _lcl_parse_taggedtext_body(char* h, /* unparsed header:in */ 512 char* b, /* unparsed body:in */ 513 LclMailType type /* Mail type:in */ 514 ){ 515 if(type == LclUnKnownType){ 516 if(_is_V3_header(h)){ 517 type = LclV3Type ; 518 } else { 519 type = LclMIMEType ; 520 } 521 } 522 return _lcl_parse_body(h, b, type); 523 } 524 525 char* 526 _lcl_parse_taggedtext_header(char* h, /* unparsed header:in */ 527 char* b, /* unparsed body:in */ 528 LclMailType *type, /* Mail type:inout */ 529 char** charset /* charset of parsed header:out */ 530 ){ 531 if(*type == LclUnKnownType){ 532 if(_is_V3_header(h)){ 533 *type = LclV3Type ; 534 } else { 535 *type = LclMIMEType ; 536 } 537 } 538 return _lcl_parse_header(h, b, type , charset); 539 } 540