00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tool_setup.h"
00023
00024 #if defined(MSDOS) || defined(WIN32)
00025
00026 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
00027 # include <libgen.h>
00028 #endif
00029
00030 #ifdef WIN32
00031 # include "tool_cfgable.h"
00032 # include "tool_libinfo.h"
00033 #endif
00034
00035 #include "tool_bname.h"
00036 #include "tool_doswin.h"
00037
00038 #include "memdebug.h"
00039
00040
00041
00042
00043
00044 #define ALWAYS_TRUE (1)
00045 #define ALWAYS_FALSE (0)
00046
00047 #if defined(_MSC_VER) && !defined(__POCC__)
00048 # undef ALWAYS_TRUE
00049 # undef ALWAYS_FALSE
00050 # if (_MSC_VER < 1500)
00051 # define ALWAYS_TRUE (0, 1)
00052 # define ALWAYS_FALSE (1, 0)
00053 # else
00054 # define ALWAYS_TRUE \
00055 __pragma(warning(push)) \
00056 __pragma(warning(disable:4127)) \
00057 (1) \
00058 __pragma(warning(pop))
00059 # define ALWAYS_FALSE \
00060 __pragma(warning(push)) \
00061 __pragma(warning(disable:4127)) \
00062 (0) \
00063 __pragma(warning(pop))
00064 # endif
00065 #endif
00066
00067 #ifdef WIN32
00068 # undef PATH_MAX
00069 # define PATH_MAX MAX_PATH
00070 #endif
00071
00072 #ifndef S_ISCHR
00073 # ifdef S_IFCHR
00074 # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
00075 # else
00076 # define S_ISCHR(m) (0)
00077 # endif
00078 #endif
00079
00080 #ifdef WIN32
00081 # define _use_lfn(f) ALWAYS_TRUE
00082 #elif !defined(__DJGPP__) || (__DJGPP__ < 2)
00083 # define _use_lfn(f) ALWAYS_FALSE
00084 #elif defined(__DJGPP__)
00085 # include <fcntl.h>
00086 #endif
00087
00088 #ifndef UNITTESTS
00089 static SANITIZEcode truncate_dryrun(const char *path,
00090 const size_t truncate_pos);
00091 #ifdef MSDOS
00092 static SANITIZEcode msdosify(char **const sanitized, const char *file_name,
00093 int flags);
00094 #endif
00095 static SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
00096 const char *file_name,
00097 int flags);
00098 #endif
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 SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name,
00136 int flags)
00137 {
00138 char *p, *target;
00139 size_t len;
00140 SANITIZEcode sc;
00141 size_t max_sanitized_len;
00142
00143 if(!sanitized)
00144 return SANITIZE_ERR_BAD_ARGUMENT;
00145
00146 *sanitized = NULL;
00147
00148 if(!file_name)
00149 return SANITIZE_ERR_BAD_ARGUMENT;
00150
00151 if((flags & SANITIZE_ALLOW_PATH)) {
00152 #ifndef MSDOS
00153 if(file_name[0] == '\\' && file_name[1] == '\\')
00154
00155 max_sanitized_len = 32767-1;
00156 else
00157 #endif
00158 max_sanitized_len = PATH_MAX-1;
00159 }
00160 else
00161
00162
00163
00164 max_sanitized_len = (PATH_MAX-1 > 255) ? 255 : PATH_MAX-1;
00165
00166 len = strlen(file_name);
00167 if(len > max_sanitized_len) {
00168 if(!(flags & SANITIZE_ALLOW_TRUNCATE) ||
00169 truncate_dryrun(file_name, max_sanitized_len))
00170 return SANITIZE_ERR_INVALID_PATH;
00171
00172 len = max_sanitized_len;
00173 }
00174
00175 target = malloc(len + 1);
00176 if(!target)
00177 return SANITIZE_ERR_OUT_OF_MEMORY;
00178
00179 strncpy(target, file_name, len);
00180 target[len] = '\0';
00181
00182 #ifndef MSDOS
00183 if((flags & SANITIZE_ALLOW_PATH) && !strncmp(target, "\\\\?\\", 4))
00184
00185 p = target + 4;
00186 else
00187 #endif
00188 p = target;
00189
00190
00191 for(; *p; ++p) {
00192 const char *banned;
00193
00194 if((1 <= *p && *p <= 31) ||
00195 (!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *p == ':') ||
00196 (!(flags & SANITIZE_ALLOW_PATH) && (*p == '/' || *p == '\\'))) {
00197 *p = '_';
00198 continue;
00199 }
00200
00201 for(banned = "|<>\"?*"; *banned; ++banned) {
00202 if(*p == *banned) {
00203 *p = '_';
00204 break;
00205 }
00206 }
00207 }
00208
00209
00210 if(!(flags & SANITIZE_ALLOW_PATH) && len) {
00211 char *clip = NULL;
00212
00213 p = &target[len];
00214 do {
00215 --p;
00216 if(*p != ' ' && *p != '.')
00217 break;
00218 clip = p;
00219 } while(p != target);
00220
00221 if(clip) {
00222 *clip = '\0';
00223 len = clip - target;
00224 }
00225 }
00226
00227 #ifdef MSDOS
00228 sc = msdosify(&p, target, flags);
00229 free(target);
00230 if(sc)
00231 return sc;
00232 target = p;
00233 len = strlen(target);
00234
00235 if(len > max_sanitized_len) {
00236 free(target);
00237 return SANITIZE_ERR_INVALID_PATH;
00238 }
00239 #endif
00240
00241 if(!(flags & SANITIZE_ALLOW_RESERVED)) {
00242 sc = rename_if_reserved_dos_device_name(&p, target, flags);
00243 free(target);
00244 if(sc)
00245 return sc;
00246 target = p;
00247 len = strlen(target);
00248
00249 if(len > max_sanitized_len) {
00250 free(target);
00251 return SANITIZE_ERR_INVALID_PATH;
00252 }
00253 }
00254
00255 *sanitized = target;
00256 return SANITIZE_ERR_OK;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 SANITIZEcode truncate_dryrun(const char *path, const size_t truncate_pos)
00286 {
00287 size_t len;
00288
00289 if(!path)
00290 return SANITIZE_ERR_BAD_ARGUMENT;
00291
00292 len = strlen(path);
00293
00294 if(truncate_pos > len)
00295 return SANITIZE_ERR_BAD_ARGUMENT;
00296
00297 if(!len || !truncate_pos)
00298 return SANITIZE_ERR_INVALID_PATH;
00299
00300 if(strpbrk(&path[truncate_pos - 1], "\\/:"))
00301 return SANITIZE_ERR_INVALID_PATH;
00302
00303
00304 if(truncate_pos > 1) {
00305 const char *p = &path[truncate_pos - 1];
00306 do {
00307 --p;
00308 if(*p == ':')
00309 return SANITIZE_ERR_INVALID_PATH;
00310 } while(p != path && *p != '\\' && *p != '/');
00311 }
00312
00313 return SANITIZE_ERR_OK;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 #if defined(MSDOS) || defined(UNITTESTS)
00335 SANITIZEcode msdosify(char **const sanitized, const char *file_name,
00336 int flags)
00337 {
00338 char dos_name[PATH_MAX];
00339 static const char illegal_chars_dos[] = ".+, ;=[]"
00340 "|<>/\\\":?*";
00341 static const char *illegal_chars_w95 = &illegal_chars_dos[8];
00342 int idx, dot_idx;
00343 const char *s = file_name;
00344 char *d = dos_name;
00345 const char *const dlimit = dos_name + sizeof(dos_name) - 1;
00346 const char *illegal_aliens = illegal_chars_dos;
00347 size_t len = sizeof(illegal_chars_dos) - 1;
00348
00349 if(!sanitized)
00350 return SANITIZE_ERR_BAD_ARGUMENT;
00351
00352 *sanitized = NULL;
00353
00354 if(!file_name)
00355 return SANITIZE_ERR_BAD_ARGUMENT;
00356
00357 if(strlen(file_name) > PATH_MAX-1 &&
00358 (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
00359 truncate_dryrun(file_name, PATH_MAX-1)))
00360 return SANITIZE_ERR_INVALID_PATH;
00361
00362
00363 if(_use_lfn(file_name)) {
00364 illegal_aliens = illegal_chars_w95;
00365 len -= (illegal_chars_w95 - illegal_chars_dos);
00366 }
00367
00368
00369 if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') {
00370 *d++ = *s++;
00371 *d = ((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) ? ':' : '_';
00372 ++d, ++s;
00373 }
00374
00375 for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
00376 if(memchr(illegal_aliens, *s, len)) {
00377
00378 if((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *s == ':')
00379 *d = ':';
00380 else if((flags & SANITIZE_ALLOW_PATH) && (*s == '/' || *s == '\\'))
00381 *d = *s;
00382
00383
00384
00385
00386
00387 else if(*s == '.') {
00388 if((flags & SANITIZE_ALLOW_PATH) && idx == 0 &&
00389 (s[1] == '/' || s[1] == '\\' ||
00390 (s[1] == '.' && (s[2] == '/' || s[2] == '\\')))) {
00391
00392 *d++ = *s++;
00393 if(d == dlimit)
00394 break;
00395 if(*s == '.') {
00396 *d++ = *s++;
00397 if(d == dlimit)
00398 break;
00399 }
00400 *d = *s;
00401 }
00402 else if(idx == 0)
00403 *d = '_';
00404 else if(dot_idx >= 0) {
00405 if(dot_idx < 5) {
00406 d[dot_idx - idx] = '_';
00407 *d = '.';
00408 }
00409 else
00410 *d = '-';
00411 }
00412 else
00413 *d = '.';
00414
00415 if(*s == '.')
00416 dot_idx = idx;
00417 }
00418 else if(*s == '+' && s[1] == '+') {
00419 if(idx - 2 == dot_idx) {
00420 *d++ = 'x';
00421 if(d == dlimit)
00422 break;
00423 *d = 'x';
00424 }
00425 else {
00426
00427 if(dlimit - d < 4) {
00428 *d++ = 'x';
00429 if(d == dlimit)
00430 break;
00431 *d = 'x';
00432 }
00433 else {
00434 memcpy(d, "plus", 4);
00435 d += 3;
00436 }
00437 }
00438 s++;
00439 idx++;
00440 }
00441 else
00442 *d = '_';
00443 }
00444 else
00445 *d = *s;
00446 if(*s == '/' || *s == '\\') {
00447 idx = 0;
00448 dot_idx = -1;
00449 }
00450 else
00451 idx++;
00452 }
00453 *d = '\0';
00454
00455 if(*s) {
00456
00457
00458
00459 if(!(flags & SANITIZE_ALLOW_TRUNCATE) || strpbrk(s, "\\/:") ||
00460 truncate_dryrun(dos_name, d - dos_name))
00461 return SANITIZE_ERR_INVALID_PATH;
00462 }
00463
00464 *sanitized = strdup(dos_name);
00465 return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
00466 }
00467 #endif
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
00483 const char *file_name,
00484 int flags)
00485 {
00486
00487
00488
00489 char *p, *base;
00490 char fname[PATH_MAX];
00491 #ifdef MSDOS
00492 struct_stat st_buf;
00493 #endif
00494
00495 if(!sanitized)
00496 return SANITIZE_ERR_BAD_ARGUMENT;
00497
00498 *sanitized = NULL;
00499
00500 if(!file_name)
00501 return SANITIZE_ERR_BAD_ARGUMENT;
00502
00503
00504 #ifndef MSDOS
00505 if((flags & SANITIZE_ALLOW_PATH) &&
00506 file_name[0] == '\\' && file_name[1] == '\\') {
00507 size_t len = strlen(file_name);
00508 *sanitized = malloc(len + 1);
00509 if(!*sanitized)
00510 return SANITIZE_ERR_OUT_OF_MEMORY;
00511 strncpy(*sanitized, file_name, len + 1);
00512 return SANITIZE_ERR_OK;
00513 }
00514 #endif
00515
00516 if(strlen(file_name) > PATH_MAX-1 &&
00517 (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
00518 truncate_dryrun(file_name, PATH_MAX-1)))
00519 return SANITIZE_ERR_INVALID_PATH;
00520
00521 strncpy(fname, file_name, PATH_MAX-1);
00522 fname[PATH_MAX-1] = '\0';
00523 base = basename(fname);
00524
00525
00526
00527
00528
00529
00530 for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) {
00531 size_t p_len;
00532 int x = (curl_strnequal(p, "CON", 3) ||
00533 curl_strnequal(p, "PRN", 3) ||
00534 curl_strnequal(p, "AUX", 3) ||
00535 curl_strnequal(p, "NUL", 3)) ? 3 :
00536 (curl_strnequal(p, "CLOCK$", 6)) ? 6 :
00537 (curl_strnequal(p, "COM", 3) || curl_strnequal(p, "LPT", 3)) ?
00538 (('1' <= p[3] && p[3] <= '9') ? 4 : 3) : 0;
00539
00540 if(!x)
00541 continue;
00542
00543
00544
00545
00546 for(; p[x] == ' '; ++x)
00547 ;
00548
00549 if(p[x] == '.') {
00550 p[x] = '_';
00551 continue;
00552 }
00553 else if(p[x] == ':') {
00554 if(!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) {
00555 p[x] = '_';
00556 continue;
00557 }
00558 ++x;
00559 }
00560 else if(p[x])
00561 continue;
00562
00563
00564 p_len = strlen(p);
00565
00566
00567 if(strlen(fname) == PATH_MAX-1) {
00568 --p_len;
00569 if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(p, p_len))
00570 return SANITIZE_ERR_INVALID_PATH;
00571 p[p_len] = '\0';
00572 }
00573 memmove(p + 1, p, p_len + 1);
00574 p[0] = '_';
00575 ++p_len;
00576
00577
00578 if(p == fname)
00579 base = basename(fname);
00580 }
00581
00582
00583
00584
00585
00586
00587
00588 #ifdef MSDOS
00589 if(base && ((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
00590
00591 size_t blen = strlen(base);
00592 if(blen) {
00593 if(strlen(fname) == PATH_MAX-1) {
00594 --blen;
00595 if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(base, blen))
00596 return SANITIZE_ERR_INVALID_PATH;
00597 base[blen] = '\0';
00598 }
00599 memmove(base + 1, base, blen + 1);
00600 base[0] = '_';
00601 ++blen;
00602 }
00603 }
00604 #endif
00605
00606 *sanitized = strdup(fname);
00607 return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
00608 }
00609
00610 #if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
00611
00612
00613
00614
00615 char **__crt0_glob_function(char *arg)
00616 {
00617 (void)arg;
00618 return (char **)0;
00619 }
00620
00621 #endif
00622
00623 #ifdef WIN32
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 CURLcode FindWin32CACert(struct OperationConfig *config,
00641 const char *bundle_file)
00642 {
00643 CURLcode result = CURLE_OK;
00644
00645
00646 if(curlinfo->features & CURL_VERSION_SSL) {
00647
00648 DWORD res_len;
00649 DWORD buf_tchar_size = PATH_MAX + 1;
00650 DWORD buf_bytes_size = sizeof(TCHAR) * buf_tchar_size;
00651 char *ptr = NULL;
00652
00653 char *buf = malloc(buf_bytes_size);
00654 if(!buf)
00655 return CURLE_OUT_OF_MEMORY;
00656 buf[0] = '\0';
00657
00658 res_len = SearchPathA(NULL, bundle_file, NULL, buf_tchar_size, buf, &ptr);
00659 if(res_len > 0) {
00660 Curl_safefree(config->cacert);
00661 config->cacert = strdup(buf);
00662 if(!config->cacert)
00663 result = CURLE_OUT_OF_MEMORY;
00664 }
00665
00666 Curl_safefree(buf);
00667 }
00668
00669 return result;
00670 }
00671
00672 #endif
00673
00674 #endif