00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 #ifdef __cplusplus
00148
00149 extern "C" {
00150
00151 #endif
00152
00153 #include "cbf.h"
00154 #include "cbf_file.h"
00155 #include "cbf_context.h"
00156 #include "cbf_binary.h"
00157 #include "cbf_codes.h"
00158 #include "cbf_read_mime.h"
00159 #include "cbf_string.h"
00160
00161 #include <ctype.h>
00162 #include <string.h>
00163
00164
00165
00166
00167 int cbf_mime_temp (cbf_node *column, unsigned int row)
00168 {
00169 cbf_file *file;
00170
00171 cbf_file *temp_file;
00172
00173 long start, temp_start;
00174
00175 size_t size;
00176
00177 int id, bits, sign, type, checked_digest;
00178
00179 unsigned int compression;
00180
00181 char old_digest [25], *new_digest, digest [25];
00182
00183
00184
00185
00186 if (!cbf_is_mimebinary (column, row))
00187
00188 return CBF_ASCII;
00189
00190
00191
00192
00193 size = 0;
00194
00195 cbf_failnez (cbf_get_bintext (column, row, &type,
00196 &id, &file, &start, &size, &checked_digest,
00197 old_digest, &bits, &sign, &compression))
00198
00199
00200
00201
00202 cbf_failnez (cbf_set_fileposition (file, start, SEEK_SET))
00203
00204
00205
00206
00207 cbf_failnez (cbf_open_temporary (column->context, &temp_file))
00208
00209
00210
00211
00212 cbf_onfailnez (cbf_set_fileposition (temp_file, 0, SEEK_END),
00213 cbf_delete_fileconnection (&temp_file))
00214
00215
00216
00217
00218 cbf_onfailnez (cbf_get_fileposition (temp_file, &temp_start),
00219 cbf_delete_fileconnection (&temp_file))
00220
00221
00222
00223
00224 if (cbf_is_base64digest (old_digest) && (file->read_headers & MSG_DIGEST)
00225 && !checked_digest)
00226
00227 new_digest = digest;
00228
00229 else
00230
00231 new_digest = NULL;
00232
00233
00234
00235
00236 cbf_onfailnez (cbf_read_mime (file, temp_file,
00237 NULL, NULL, old_digest, new_digest),
00238 cbf_delete_fileconnection (&temp_file))
00239
00240
00241
00242
00243 if (new_digest)
00244
00245 if (strcmp (old_digest, new_digest) == 0)
00246
00247 checked_digest = 1;
00248
00249 else
00250
00251 return CBF_FORMAT | cbf_delete_fileconnection (&temp_file);
00252
00253
00254
00255
00256 cbf_onfailnez (cbf_set_bintext (column, row, CBF_TOKEN_TMP_BIN,
00257 id, temp_file, temp_start, size,
00258 checked_digest, old_digest, bits,
00259 sign,
00260 compression),
00261 cbf_delete_fileconnection (&temp_file))
00262
00263
00264
00265
00266 return 0;
00267 }
00268
00269
00270
00271
00272 int cbf_read_mime (cbf_file *infile, cbf_file *outfile,
00273 size_t *size,
00274 long *id,
00275 char *old_digest,
00276 char *new_digest)
00277 {
00278 int encoding;
00279
00280 size_t file_size;
00281
00282 unsigned int compression;
00283
00284
00285
00286
00287 encoding = 0;
00288
00289 file_size = 0;
00290
00291 cbf_failnez (cbf_parse_mimeheader (infile, &encoding,
00292 &file_size, id,
00293 old_digest,
00294 &compression,
00295 NULL, NULL))
00296
00297 if (file_size <= 0)
00298
00299 return CBF_FORMAT;
00300
00301
00302
00303
00304 cbf_failnez (cbf_reset_bits (outfile))
00305
00306
00307
00308
00309 switch (encoding)
00310 {
00311 case ENC_QP:
00312
00313 cbf_failnez (cbf_fromqp (infile, outfile, file_size, NULL,
00314 new_digest))
00315
00316 break;
00317
00318 case ENC_BASE64:
00319
00320 cbf_failnez (cbf_frombase64 (infile, outfile, file_size, NULL,
00321 new_digest))
00322
00323 break;
00324
00325 case ENC_BASE8:
00326 case ENC_BASE10:
00327 case ENC_BASE16:
00328
00329 cbf_failnez (cbf_frombasex (infile, outfile, file_size, NULL,
00330 new_digest))
00331
00332 break;
00333
00334 default:
00335
00336 return CBF_FORMAT;
00337 }
00338
00339
00340
00341
00342 cbf_failnez (cbf_flush_bits (outfile))
00343
00344
00345
00346
00347 if (size)
00348
00349 *size = file_size;
00350
00351
00352
00353
00354 return 0;
00355 }
00356
00357
00358
00359
00360 int cbf_is_blank (const char *line)
00361 {
00362 if (line)
00363
00364 for (; *line; line++)
00365
00366 if (!isspace (*line))
00367
00368 return 0;
00369
00370 return 1;
00371 }
00372
00373
00374
00375 int cbf_nblen (const char *line, int *nblen)
00376 {
00377 register char *myline;
00378
00379 register int mylen;
00380
00381 *nblen = mylen = 0;
00382
00383
00384
00385 if (!(myline = (char *)line)) return 1;
00386
00387 for (; *myline; myline++)
00388
00389 if (!isspace (*myline)) mylen = myline-(char *)line+1;
00390
00391 *nblen = mylen;
00392
00393 return 0;
00394
00395 }
00396
00397
00398
00399
00400 int cbf_skip_whitespace (cbf_file *file, const char **line,
00401 const char **curpoint,
00402 int *freshline)
00403 {
00404 static const char end = '\0';
00405
00406 const char *c;
00407
00408 int comment_level;
00409
00410
00411
00412
00413 if (*freshline)
00414 {
00415 *curpoint = &end;
00416
00417 return 0;
00418 }
00419
00420 c = *curpoint;
00421
00422 comment_level = 0;
00423
00424 while (isspace (*c) || *c == '(' || *c == '\0')
00425
00426 if (*c == '\0')
00427 {
00428 cbf_failnez (cbf_read_line (file, line))
00429
00430 c = *line;
00431
00432 if (cbf_is_blank (c) || (*c != ' ' && *c != '\t'))
00433 {
00434 *freshline = 1;
00435
00436 *curpoint = &end;
00437
00438 return 0;
00439 }
00440 }
00441 else
00442
00443 if (*c == '(')
00444 {
00445 c++;
00446
00447 comment_level++;
00448
00449 while (comment_level)
00450 {
00451 switch (*c)
00452 {
00453 case '\0':
00454
00455 cbf_failnez (cbf_read_line (file, line))
00456
00457 c = *line;
00458
00459 if (cbf_is_blank (c) || (*c != ' ' && *c != '\t'))
00460 {
00461 *freshline = 1;
00462
00463 *curpoint = &end;
00464
00465 return 0;
00466 }
00467
00468 break;
00469
00470 case '\\':
00471
00472 c++;
00473
00474 break;
00475
00476 case '(':
00477
00478 comment_level++;
00479
00480 break;
00481
00482 case ')':
00483
00484 comment_level--;
00485
00486 break;
00487 }
00488
00489 c++;
00490 }
00491 }
00492 else
00493
00494 c++;
00495
00496 *freshline = 0;
00497
00498 *curpoint = c;
00499
00500
00501
00502
00503 return 0;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 int cbf_parse_mimeheader (cbf_file *file, int *encoding,
00517 size_t *size,
00518 long *id,
00519 char *digest,
00520 unsigned int *compression,
00521 int *bits,
00522 int *sign)
00523 {
00524 static const char *value [] = {
00525
00526 "Content-Type:",
00527 "Content-Transfer-Encoding:",
00528 "X-Binary-Size:",
00529 "X-Binary-ID:",
00530 "X-Binary-Element-Type:",
00531 "Content-MD5:"
00532
00533 };
00534
00535 const char *line, *c;
00536
00537 int state, continuation, item, line_count, fresh_line, quote, text_bits,
00538 count, failure, nblen;
00539
00540
00541
00542
00543 if (encoding)
00544
00545 *encoding = 0;
00546
00547 if (size)
00548
00549 *size = 0;
00550
00551 if (id)
00552
00553 *id = 0;
00554
00555 if (digest)
00556
00557 *digest = '\0';
00558
00559 if (compression)
00560
00561 *compression = CBF_NONE;
00562
00563 if (bits)
00564
00565 *bits = 0;
00566
00567 if (sign)
00568
00569 *sign = -1;
00570
00571
00572
00573
00574 state = -1;
00575
00576 line_count = 0;
00577
00578 fresh_line = 0;
00579
00580 nblen = 1;
00581
00582 while (nblen)
00583 {
00584 if (!fresh_line)
00585
00586 cbf_failnez (cbf_read_line (file, &line))
00587
00588 cbf_nblen(line, &nblen);
00589
00590 fresh_line = 0;
00591
00592 line_count++;
00593
00594
00595
00596 if ( (line[0] == ';') ||
00597 ( cbf_cistrncmp(line,"--CIF-BINARY-FORMAT-SECTION--",29) == 0 ) )
00598
00599 return CBF_FORMAT;
00600
00601
00602
00603
00604 continuation = line [0] == ' ' || line [0] == '\t';
00605
00606
00607
00608
00609 if (continuation)
00610
00611 item = 0;
00612
00613 else
00614 {
00615 for (c = line; *c != ':' && *c > 32 && *c < 127; c++);
00616
00617 item = c != line && *c == ':';
00618 }
00619
00620
00621
00622
00623 if (line_count > 1 && cbf_is_blank (line))
00624
00625 return 0;
00626
00627
00628
00629
00630 if (!item && (line_count == 1 || !continuation))
00631
00632 return CBF_FORMAT;
00633
00634
00635
00636
00637 c = line;
00638
00639 if (item)
00640
00641 for (state = 5; state > -1; state--)
00642
00643 if (cbf_cistrncmp (line, value [state], strlen (value [state]))
00644 == 0)
00645
00646 {
00647 c = line + strlen (value [state]);
00648
00649 break;
00650 }
00651
00652
00653
00654
00655 cbf_failnez (cbf_skip_whitespace (file, &line, &c, &fresh_line))
00656
00657
00658
00659
00660 switch (state)
00661 {
00662 case 0:
00663
00664
00665
00666 if (cbf_cistrncmp (c, "application/", 12) != 0 &&
00667 cbf_cistrncmp (c, "image/", 6) != 0 &&
00668 cbf_cistrncmp (c, "text/", 5) != 0 &&
00669 cbf_cistrncmp (c, "audio/", 6) != 0 &&
00670 cbf_cistrncmp (c, "video/", 6) != 0)
00671
00672 return CBF_FORMAT;
00673
00674
00675 while (*c)
00676 {
00677
00678
00679 while (*c)
00680
00681 if (*c == '\"')
00682 {
00683 c++;
00684
00685 while (*c)
00686
00687 if (*c == '\"')
00688 {
00689 c++;
00690
00691 break;
00692 }
00693 else
00694 {
00695 if (*c == '\\')
00696
00697 c++;
00698
00699 if (*c)
00700
00701 c++;
00702 }
00703 }
00704 else
00705
00706 if (*c == '(')
00707
00708 cbf_failnez (cbf_skip_whitespace (file, &line, &c,
00709 &fresh_line))
00710
00711 else
00712
00713 if (*c == ';')
00714 {
00715 c++;
00716
00717 break;
00718 }
00719 else
00720
00721 c++;
00722
00723
00724
00725
00726 cbf_failnez (cbf_skip_whitespace (file, &line, &c,
00727 &fresh_line))
00728
00729 if (cbf_cistrncmp (c, "conversions", 11) == 0)
00730 {
00731 c += 11;
00732
00733 cbf_failnez (cbf_skip_whitespace (file, &line, &c,
00734 &fresh_line))
00735
00736 if (*c == '=')
00737 {
00738 c++;
00739
00740 cbf_failnez (cbf_skip_whitespace (file, &line, &c,
00741 &fresh_line))
00742
00743 if (compression)
00744 {
00745 quote = 0;
00746
00747 if (*c == '\"')
00748
00749 quote = 1;
00750
00751 *compression = CBF_NONE;
00752
00753 if (cbf_cistrncmp (c + quote, "x-cbf_packed", 12) == 0)
00754
00755 *compression = CBF_PACKED;
00756
00757 if (cbf_cistrncmp (c + quote, "x-cbf_canonical", 15) == 0)
00758
00759 *compression = CBF_CANONICAL;
00760
00761 if (cbf_cistrncmp (c + quote, "x-cbf_byte_offset", 17) == 0)
00762
00763 *compression = CBF_BYTE_OFFSET;
00764
00765 if (cbf_cistrncmp (c + quote, "x-cbf_predictor", 15) == 0)
00766
00767 *compression = CBF_PREDICTOR;
00768 }
00769 }
00770 }
00771 }
00772
00773 state = -1;
00774
00775 break;
00776
00777 case 1:
00778
00779
00780
00781 if (encoding)
00782 {
00783 failure = 1;
00784
00785 quote = 0;
00786
00787 if (*c == '\"')
00788
00789 quote = 1;
00790
00791 if (cbf_cistrncmp (c+quote, "Quoted-Printable", 16) == 0)
00792
00793 if (isspace (c [16]) || c [16] == '('
00794 || (quote && c [16] == '\"')) {
00795
00796 failure = 0;
00797
00798 *encoding = ENC_QP;
00799 }
00800
00801 if (cbf_cistrncmp (c+quote, "Base64", 6) == 0)
00802
00803 if (isspace (c [6]) || c [6] == '(' || (quote && c [16] == '\"')) {
00804
00805 failure = 0;
00806
00807 *encoding = ENC_BASE64;
00808 }
00809
00810 if (cbf_cistrncmp (c+quote, "X-Base8", 7) == 0)
00811
00812 if (isspace (c [7]) || c [7] == '(' || (quote && c [16] == '\"')) {
00813
00814 failure = 0;
00815
00816 *encoding = ENC_BASE8;
00817 }
00818
00819 if (cbf_cistrncmp (c+quote, "X-Base10", 8) == 0)
00820
00821 if (isspace (c [8]) || c [8] == '(' || (quote && c [16] == '\"')) {
00822
00823 failure = 0;
00824
00825 *encoding = ENC_BASE10;
00826 }
00827
00828 if (cbf_cistrncmp (c+quote, "X-Base16", 8) == 0)
00829
00830 if (isspace (c [8]) || c [8] == '(' || (quote && c [16] == '\"')) {
00831
00832 failure = 0;
00833
00834 *encoding = ENC_BASE16;
00835 }
00836
00837 if (cbf_cistrncmp (c+quote, "7bit", 4) == 0 ||
00838 cbf_cistrncmp (c+quote, "8bit", 4) == 0)
00839
00840 if (isspace (c [4]) || c [4] == '(' || (quote && c [16] == '\"')) {
00841
00842 failure = 0;
00843
00844 *encoding = ENC_NONE;
00845 }
00846
00847 if (cbf_cistrncmp (c+quote, "Binary", 6) == 0)
00848
00849 if (isspace (c [6]) || c [6] == '(' || (quote && c [16] == '\"')) {
00850
00851 failure = 0;
00852
00853 *encoding = ENC_NONE;
00854 }
00855 }
00856
00857 if (failure) return CBF_FORMAT;
00858
00859 break;
00860
00861 case 2:
00862
00863
00864
00865 if (size)
00866
00867 *size = atol (c);
00868
00869 break;
00870
00871 case 3:
00872
00873
00874
00875 if (id)
00876
00877 *id = atol (c);
00878
00879 break;
00880
00881 case 4:
00882
00883
00884
00885 failure = 3;
00886
00887 while (*c)
00888 {
00889 quote = 0;
00890
00891 cbf_failnez (cbf_skip_whitespace (file, &line, &c,
00892 &fresh_line))
00893 if (*c == '\"') {
00894
00895 if (quote) break;
00896
00897 c++;
00898
00899 quote++;
00900 }
00901
00902 if (failure == 3) {
00903
00904 if (cbf_cistrncmp (c, "signed", 6) == 0)
00905 {
00906 c += 6;
00907
00908 if (sign) *sign = 1;
00909
00910 failure --;
00911 }
00912
00913 if (cbf_cistrncmp (c, "unsigned", 8) == 0)
00914 {
00915 c += 8;
00916
00917 if (sign) *sign = 0;
00918
00919 failure --;
00920 }
00921 }
00922
00923 if (failure == 2) {
00924
00925 count = 0;
00926
00927 sscanf (c, "%d-%n", &text_bits, &count);
00928
00929 if (cbf_cistrncmp (c+count, "bit", 3 ) == 0)
00930
00931 if (count && text_bits > 0 && text_bits <= 64)
00932 {
00933 c += count;
00934
00935 if (bits) *bits = text_bits;
00936
00937 failure --;
00938 }
00939 }
00940
00941 if (failure == 1) {
00942
00943 if (cbf_cistrncmp (c, "integer", 7 ) == 0) failure--;
00944
00945 }
00946
00947 if (*c)
00948
00949 c++;
00950 }
00951
00952 if (failure) return CBF_FORMAT;
00953
00954 break;
00955
00956 case 5:
00957
00958
00959
00960 if (digest)
00961 {
00962 strncpy (digest, c, 24);
00963
00964 digest [24] = '\0';
00965 }
00966
00967 break;
00968 }
00969 }
00970
00971
00972
00973
00974 return 0;
00975 }
00976
00977
00978 #ifdef __cplusplus
00979
00980 }
00981
00982 #endif