/* * Read an LDIF line. * * 0: ok if name->len != 0 * 0: end of file or empty line if name->len == 0 * -1: parse error * -2: line is just "-" */ static int ldif_read_line1(FILE *s, GString *name, GString *value) { int c; char encoding; unsigned char *ustr; int len; g_string_truncate(name, 0); g_string_truncate(value, 0); /* skip comment lines */ do { c = fgetc(s); switch (c) { case EOF: if (ferror(s)) syserr(); return 0; case '\n': return 0; case '\r': if (fgetc(s) != '\n') return -1; return 0; case '#': if (ldif_skip_comment(s) == -1) return -1; break; default: ungetc(c, s); c = -1; } } while (c != -1); if ( c = ldif_read_ad(s, name)) return c; if ( (encoding = ldif_read_encoding(s)) == -1) return -1; switch (encoding) { case 0: if (ldif_read_safe(s, value) == -1) return -1; break; case '\n': break; case ':': if (ldif_read_safe(s, value) == -1) return -1; ustr = (unsigned char *) value->str;; if ( (len = read_base64(value->str, ustr, value->len)) == -1) { fputs("Error: Invalid Base64 string.\n", stderr); return -1; } value->len = len; break; case '<': if (ldif_read_safe(s, value) == -1) return -1; if (strncmp(value->str, "file://", 7)) { fputs("Error: Unknown URL scheme.\n", stderr); return -1; } if (ldif_read_from_file(value, value->str + 7) == -1) return -1; break; default: abort(); } return 0; }
static int parse(const char *boundary, char **argv) { char *line, *s, *p; const char *type; int boundary_len = strlen(boundary); const char *delims = " ;\"\t\r\n"; const char *uniq; int ntokens; const char *tokens[32]; // 32 is enough // prepare unique string pattern uniq = xasprintf("%%llu.%u.%s", (unsigned)getpid(), safe_gethostname()); //bb_info_msg("PARSE[%s]", uniq); while ((line = xmalloc_fgets_str(stdin, "\r\n\r\n")) != NULL) { // seek to start of MIME section // N.B. to avoid false positives let us seek to the _last_ occurance p = NULL; s = line; while ((s = strcasestr(s, "Content-Type:")) != NULL) p = s++; if (!p) goto next; //bb_info_msg("L[%s]", p); // split to tokens // TODO: strip of comments which are of form: (comment-text) ntokens = 0; tokens[ntokens] = NULL; for (s = strtok(p, delims); s; s = strtok(NULL, delims)) { tokens[ntokens] = s; if (ntokens < ARRAY_SIZE(tokens) - 1) ntokens++; //bb_info_msg("L[%d][%s]", ntokens, s); } tokens[ntokens] = NULL; //bb_info_msg("N[%d]", ntokens); // analyse tokens type = find_token(tokens, "Content-Type:", "text/plain"); //bb_info_msg("T[%s]", type); if (0 == strncasecmp(type, "multipart/", 10)) { if (0 == strcasecmp(type+10, "mixed")) { parse(xfind_token(tokens, "boundary="), argv); } else bb_error_msg_and_die("no support of content type '%s'", type); } else { pid_t pid = pid; int rc; FILE *fp; // fetch charset const char *charset = find_token(tokens, "charset=", CONFIG_FEATURE_MIME_CHARSET); // fetch encoding const char *encoding = find_token(tokens, "Content-Transfer-Encoding:", "7bit"); // compose target filename char *filename = (char *)find_token(tokens, "filename=", NULL); if (!filename) filename = xasprintf(uniq, monotonic_us()); else filename = bb_get_last_path_component_strip(xstrdup(filename)); // start external helper, if any if (opts & OPT_X) { int fd[2]; xpipe(fd); pid = vfork(); if (0 == pid) { // child reads from fd[0] close(fd[1]); xmove_fd(fd[0], STDIN_FILENO); xsetenv("CONTENT_TYPE", type); xsetenv("CHARSET", charset); xsetenv("ENCODING", encoding); xsetenv("FILENAME", filename); BB_EXECVP_or_die(argv); } // parent dumps to fd[1] close(fd[0]); fp = xfdopen_for_write(fd[1]); signal(SIGPIPE, SIG_IGN); // ignore EPIPE // or create a file for dump } else { char *fname = xasprintf("%s%s", *argv, filename); fp = xfopen_for_write(fname); free(fname); } // housekeeping free(filename); // dump to fp if (0 == strcasecmp(encoding, "base64")) { read_base64(stdin, fp, '-'); } else if (0 != strcasecmp(encoding, "7bit") && 0 != strcasecmp(encoding, "8bit") ) { // quoted-printable, binary, user-defined are unsupported so far bb_error_msg_and_die("no support of encoding '%s'", encoding); } else { // N.B. we have written redundant \n. so truncate the file // The following weird 2-tacts reading technique is due to // we have to not write extra \n at the end of the file // In case of -x option we could truncate the resulting file as // fseek(fp, -1, SEEK_END); // if (ftruncate(fileno(fp), ftell(fp))) // bb_perror_msg("ftruncate"); // But in case of -X we have to be much more careful. There is // no means to truncate what we already have sent to the helper. p = xmalloc_fgets_str(stdin, "\r\n"); while (p) { s = xmalloc_fgets_str(stdin, "\r\n"); if (s == NULL) break; if ('-' == s[0] && '-' == s[1] && 0 == strncmp(s+2, boundary, boundary_len) ) { break; } fputs(p, fp); p = s; } /* while ((s = xmalloc_fgetline_str(stdin, "\r\n")) != NULL) { if ('-' == s[0] && '-' == s[1] && 0 == strncmp(s+2, boundary, boundary_len)) break; fprintf(fp, "%s\n", s); } // N.B. we have written redundant \n. so truncate the file fseek(fp, -1, SEEK_END); if (ftruncate(fileno(fp), ftell(fp))) bb_perror_msg("ftruncate"); */ } fclose(fp); // finalize helper if (opts & OPT_X) { signal(SIGPIPE, SIG_DFL); // exit if helper exited >0 rc = (wait4pid(pid) & 0xff); if (rc) return rc+20; } // check multipart finalized if (s && '-' == s[2+boundary_len] && '-' == s[2+boundary_len+1]) { free(line); break; } } next: free(line); } //bb_info_msg("ENDPARSE[%s]", boundary); return EXIT_SUCCESS; }