/* compress white space */ void spaceCrunch(char *s, bool onespace, bool unprint) { int i, j; char c; bool space = true; for (i = j = 0; c = s[i]; ++i) { if (isspaceByte(c)) { if (!onespace) continue; if (!space) s[j++] = ' ', space = true; continue; } if (unprint && !isprintByte(c)) continue; s[j++] = c, space = false; } if (space && j) --j; /* drop trailing space */ s[j] = 0; } /* spaceCrunch */
/* Return 0 if there was no need to encode */ static char *isoEncode(char *start, char *end) { int nacount = 0, count = 0, len; char *s, *t; char c, code; for (s = start; s < end; ++s) { c = *s; if (c == 0) *s = ' '; if (isspaceByte(c)) *s = ' '; } for (s = start; s < end; ++s) { c = *s; ++count; if (!isprintByte(c) && c != ' ') ++nacount; } if (!nacount) return 0; if (nacount * 4 >= count && count > 8) { code = 'B'; s = base64Encode(start, end - start, false); goto package; } code = 'Q'; s = qpEncode(start); package: len = strlen(s); t = allocMem(len + 20); sprintf(t, "=?ISO-8859-1?%c?%s?=", code, s); nzFree(s); return t; } /* isoEncode */
/* read and/or refresh the address book */ bool loadAddressBook(void) { char *buf, *bufend, *v, *last, *s, *t; bool cmt = false; char state = 0, c; int j, buflen, ln = 1; time_t mtime; if (!addressFile || (mtime = fileTimeByName(addressFile)) == -1 || mtime <= adbooktime) return true; debugPrint(3, "loading address book"); nzFree(addressList); addressList = 0; nads = 0; if (!fileIntoMemory(addressFile, &buf, &buflen)) return false; bufend = buf + buflen; for (s = t = last = buf; s < bufend; ++s) { c = *s; if (cmt) { if (c != '\n') continue; cmt = false; } if (c == ':') { /* delimiter */ if (state == 0) { setError(MSG_ABNoAlias, ln); freefail: nzFree(buf); nads = 0; return false; } while (t[-1] == ' ' || t[-1] == '\t') --t; if (state == 1) { *t++ = c; state = 2; continue; } c = '#'; /* extra fields are ignored */ } /* : */ if (c == '#') { cmt = true; continue; } if (c == '\n') { ++ln; if (state == 0) continue; if (state == 1) { setError(MSG_ABNoColon, ln - 1); goto freefail; } if (state == 3) { ++nads; while (isspaceByte(t[-1])) --t; *t = 0; v = strchr(last, ':'); if (v - last >= 16) { setError(MSG_ABAliasLong, ln - 1); goto freefail; } ++v; if (t - v >= 64) { setError(MSG_ABMailLong, ln - 1); goto freefail; } if (!strchr(v, '@')) { setError(MSG_ABNoAt, ln - 1); goto freefail; } if (strpbrk(v, " \t")) { setError(MSG_ABMailSpaces, ln - 1); goto freefail; } while (last < t) { if (!isprintByte(*last)) { setError(MSG_AbMailUnprintable, ln - 1); goto freefail; } ++last; } *t++ = c; } else t = last; /* back it up */ last = t; state = 0; continue; } /* nl */ if ((c == ' ' || c == '\t') && (state == 0 || state == 2)) continue; if (state == 0) state = 1; if (state == 2) state = 3; *t++ = c; } *t = 0; if (state) { setError(MSG_ABUnterminated); goto freefail; } if (nads) { addressList = allocMem(nads * sizeof(struct ALIAS)); j = 0; for (s = buf; *s; s = t + 1, ++j) { t = strchr(s, ':'); memcpy(addressList[j].name, s, t - s); addressList[j].name[t - s] = 0; s = t + 1; t = strchr(s, '\n'); memcpy(addressList[j].email, s, t - s); addressList[j].email[t - s] = 0; } } /* aliases are present */ nzFree(buf); adbooktime = mtime; return true; } /* loadAddressBook */