/* Domain must be the trailing substring of server. */ bool domainSecurityCheck(const char *server, const char *domain) { int i, dl, nd; dl = strlen(domain); /* x.com or x.y.z */ if (dl < 5) return false; if (dl > strlen(server)) return false; i = strlen(server) - dl; if (!stringEqualCI(server + i, domain)) return false; if (i && server[i - 1] != '.') return false; nd = 2; /* number of dots */ if (dl > 4 && domain[dl - 4] == '.') { static const char *const tld[] = { "com", "edu", "net", "org", "gov", "mil", "int", "biz", NULL }; if (stringInListCI(tld, domain + dl - 3) >= 0) nd = 1; } for (i = 0; domain[i]; i++) if (domain[i] == '.') if (!--nd) return true; return false; } /* domainSecurityCheck */
static void acceptCookie(struct cookie *c) { struct cookie *d; displacedCookie = false; foreach(d, cookies) { if (stringEqualCI(d->name, c->name) && stringEqualCI(d->domain, c->domain)) { displacedCookie = true; delFromList(d); freeCookie(d); nzFree(d); break; } } addToListBack(&cookies, c); } /* acceptCookie */
/* set document.cookie to the cookies relevant to this url */ static void docCookie(jsobjtype d) { int cook_l; char *cook = initString(&cook_l); const char *url = cw->fileName; bool secure = false; const char *proto; char *s; if (url) { proto = getProtURL(url); if (proto && stringEqualCI(proto, "https")) secure = true; sendCookies(&cook, &cook_l, url, secure); if (memEqualCI(cook, "cookie: ", 8)) { /* should often happen */ strmove(cook, cook + 8); } if (s = strstr(cook, "\r\n")) *s = 0; } set_property_string(d, "cookie", cook); nzFree(cook); } /* docCookie */
/* Read a file into memory, mime encode it, * and return the type of encoding and the encoded data. * Last three parameters are result parameters. * If ismail is nonzero, the file is the mail, not an attachment. * In fact ismail indicates the line that holds the subject. * If ismail is negative, then -ismail indicates the subject line, * and the string file is not the filename, but rather, the mail to send. */ bool encodeAttachment(const char *file, int ismail, bool webform, const char **type_p, const char **enc_p, char **data_p) { char *buf; char c; bool longline; char *s, *t, *v; char *ct, *ce; /* content type, content encoding */ int buflen, i, cx; int nacount, nullcount, nlcount; if (ismail < 0) { buf = cloneString(file); buflen = strlen(buf); ismail = -ismail; file = EMPTYSTRING; } else { if (!ismc && (cx = stringIsNum(file)) >= 0) { static char newfilename[16]; if (!unfoldBuffer(cx, false, &buf, &buflen)) return false; if (!buflen) { if (webform) { empty: buf = EMPTYSTRING; ct = "text/plain"; ce = "7bit"; goto success; } setError(MSG_BufferXEmpty, cx); goto freefail; } sprintf(newfilename, "<buffer %d>", cx); file = newfilename; if (sessionList[cx].lw->fileName) file = sessionList[cx].lw->fileName; } else { if (!fileIntoMemory(file, &buf, &buflen)) return false; if (!buflen) { if (webform) goto empty; setError(MSG_FileXEmpty, file); goto freefail; } } } /* ismail negative or normal */ if (ismail) { /* Put newline at the end. Yes, the buffer is allocated * with space for newline and null. */ if (buf[buflen - 1] != '\n') buf[buflen++] = '\n'; /* check for subject: line */ s = buf; i = ismail; while (--i) { while (*s != '\n') ++s; ++s; } while (*s == ' ' || *s == '\t') ++s; if (!memEqualCI(s, "subject:", 8)) { setError(MSG_SubjectStart); goto freefail; } s += 8; while (*s == ' ' || *s == '\t') ++s; t = s; while (*s != '\n') ++s; v = s; while (s > t && isspaceByte(s[-1])) --s; if (s - t >= sizeof(subjectLine)) { setError(MSG_SubjectLong, sizeof(subjectLine) - 1); goto freefail; } if (s > t) memcpy(subjectLine, t, s - t); subjectLine[s - t] = 0; if (subjectLine[0]) { char *subjiso = isoEncode(subjectLine, subjectLine + strlen(subjectLine)); if (subjiso) { if (strlen(subjiso) >= sizeof(subjectLine)) { nzFree(subjiso); setError(MSG_SubjectLong, sizeof(subjectLine) - 1); goto freefail; } strcpy(subjectLine, subjiso); nzFree(subjiso); } } debugPrint(6, "subject = %s", subjectLine); /* Blank lines after subject are optional, and ignored. */ for (t = buf + buflen; v < t; ++v) if (*v != '\r' && *v != '\n') break; buflen -= (v - buf); if (buflen) memmove(buf, v, buflen); buf[buflen] = 0; if (doSignature) { /* Append .signature file. */ /* Try account specific .signature file, then fall back to .signature */ sprintf(sigFileEnd, "%d", mailAccount); c = fileTypeByName(sigFile, false); if (!c) { *sigFileEnd = 0; c = fileTypeByName(sigFile, false); } if (c != 0) { int fd, n; if (c != 'f') { setError(MSG_SigRegular); goto freefail; } n = fileSizeByName(sigFile); if (n > 0) { buf = reallocMem(buf, buflen + n + 1); fd = open(sigFile, O_RDONLY); if (fd < 0) { setError(MSG_SigAccess); goto freefail; } read(fd, buf + buflen, n); close(fd); buflen += n; buf[buflen] = 0; } } } /* .signature */ } /* Infer content type from the filename */ ct = 0; s = strrchr(file, '.'); if (s && s[1]) { ++s; if (stringEqualCI(s, "ps")) ct = "application/PostScript"; if (stringEqualCI(s, "jpeg")) ct = "image/jpeg"; if (stringEqualCI(s, "gif")) ct = "image/gif"; if (stringEqualCI(s, "wav")) ct = "audio/basic"; if (stringEqualCI(s, "mpeg")) ct = "video/mpeg"; if (stringEqualCI(s, "rtf")) ct = "text/richtext"; if (stringEqualCI(s, "htm") || stringEqualCI(s, "html") || stringEqualCI(s, "shtm") || stringEqualCI(s, "shtml") || stringEqualCI(s, "asp")) ct = "text/html"; } /* Count the nonascii characters */ nacount = nullcount = nlcount = 0; longline = false; s = 0; for (i = 0; i < buflen; ++i) { c = buf[i]; if (c == '\0') ++nullcount; if (c < 0) ++nacount; if (c != '\n') continue; ++nlcount; t = buf + i; if (s && t - s > 120) longline = true; if (!s && i > 120) longline = true; s = t; } t = buf + i; if (s && t - s > 120) longline = true; if (!s && i > 120) longline = true; debugPrint(6, "attaching %s length %d nonascii %d nulls %d longline %d", file, buflen, nacount, nullcount, longline); nacount += nullcount; /* Set the type of attachment */ if (buflen > 20 && nacount * 5 > buflen) { if (!ct) ct = "application/octet-stream"; /* default type for binary */ } if (!ct) ct = "text/plain"; /* Criteria for base64 encode. * files uploaded from a web form need not be encoded, unless they contain * nulls, which is a quirk of my slapped together software. */ if (!webform && (buflen > 20 && nacount * 5 > buflen) || webform && nullcount) { if (ismail) { setError(MSG_MailBinary, file); goto freefail; } s = base64Encode(buf, buflen, true); nzFree(buf); buf = s; ce = "base64"; goto success; } if (!webform) { /* Switch to unix newlines - we'll switch back to dos later. */ v = buf + buflen; for (s = t = buf; s < v; ++s) { c = *s; if (c == '\r' && s < v - 1 && s[1] == '\n') continue; *t++ = c; } buflen = t - buf; /* Do we need to use quoted-printable? */ /* Perhaps this hshould read (nacount > 0) */ if (nacount * 20 > buflen || nullcount || longline) { char *newbuf; int l, colno = 0, space = 0; newbuf = initString(&l); v = buf + buflen; for (s = buf; s < v; ++s) { c = *s; /* do we have to =expand this character? */ if (c < '\n' && c != '\t' || c == '=' || c == '\xff' || (c == ' ' || c == '\t') && s < v - 1 && s[1] == '\n') { char expand[4]; sprintf(expand, "=%02X", (uchar) c); stringAndString(&newbuf, &l, expand); colno += 3; } else { stringAndChar(&newbuf, &l, c); ++colno; } if (c == '\n') { colno = space = 0; continue; } if (c == ' ' || c == '\t') space = l; if (colno < 72) continue; if (s == v - 1) continue; /* If newline's coming up anyways, don't force another one. */ if (s[1] == '\n') continue; i = l; if (!space || space == i) { stringAndString(&newbuf, &l, "=\n"); colno = space = 0; continue; } colno = i - space; stringAndString(&newbuf, &l, "**"); /* make room */ while (i > space) { newbuf[i + 1] = newbuf[i - 1]; --i; } newbuf[space] = '='; newbuf[space + 1] = '\n'; space = 0; } /* loop over characters */ nzFree(buf); buf = newbuf; ce = "quoted-printable"; goto success; } } buf[buflen] = 0; ce = (nacount ? "8bit" : "7bit"); success: debugPrint(6, "encoded %s %s length %d", ct, ce, strlen(buf)); *enc_p = ce; *type_p = ct; *data_p = buf; return true; freefail: nzFree(buf); return false; } /* encodeAttachment */