/* header to be able to add this function to a menu */ void open_helpfile(void *data, int nr __attribute__((unused))) { Char *c = (Char*) data; int i=0,hpos=0; Char *f; Char *name; Char *fullname; EDITINFO *edata; if (!c || !(f = (Char*) malloc(sizeof(Char)*(Ustrlen(c)+1)))) return; for (i=0; (f[i]=c[i]) ; i++) if (c[i]=='#') if (!i) hpos=-1; else if (hpos) hpos=0; else hpos=i; if (hpos>0) { name = c+hpos+1; f[hpos]='\0'; } else name = c+i; f = standard_dir(f); fullname = search_through_dirs(help_dirs, nr_help_dirs, f); if (!fullname && f[0]=='/') fullname=f; else free(f); if (!fullname) { message(MP_ERROR, translate("Help document not found.")); return; } i=0; while (aig(edata = (EDITINFO*) next_data_with_type(MAINEDITWINDOW, &i)) && Ustrcmp(edata->pathname,fullname)) i++; if (!edata) { as_icon=1; edit_open(); as_icon=0; if (state_window) { edata = state_window; handle_view_filename((void *) state_window, concat(fullname,NULL)); word_wrap_window(edata->info); } } if (!edata) { message2(MP_CLICKREMARK, translate("Unable to open an edit window for document "), name); return; } if (name[0]) { int j=Ustrlen(name)+1; Char *cname = (Char*) malloc(j*sizeof(Char)); if (cname) { for (i=j-1;i>=0; i--) cname[i]=name[i]; editwindow_topto(edata->info, cname); free(cname); } } if (edata->iconized) { XMapWindow(display, edata->win_id); } XRaiseWindow(display, edata->win_id); }
uschar * read_paragraph(uschar *p, int *nest_info) { uschar *q = parabuffer; int length = Ustrlen(p); memcpy(q, p, length); q += length; *nest_info = NEST_NO; /* Not hit .nest */ for (;;) { uschar *s; if ((p = read_nextline()) == NULL) break; if (Ustrncmp(p, ".literal ", 9) == 0) { next_line = p; break; } if (Ustrncmp(p, ".nest ", 6) == 0) { p += 6; while (isspace(*p)) p++; s = p + Ustrlen(p); while (s > p && isspace(s[-1])) s--; *s = 0; if (Ustrcmp(p, "begin") == 0) *nest_info = NEST_BEGIN; else if (Ustrcmp(p, "end") == 0) *nest_info = NEST_END; else error(26, p); break; } else if (*p == '.') { dot_process(p); continue; } /* End paragraph on encountering a completely blank line */ for (s = p; *s == ' ' || *s == '\t'; s++); if (*s == '\n') break; length = Ustrlen(p); memcpy(q, p, length); q += length; } *q = 0; return parabuffer; }
uschar * string_unprinting(uschar *s) { uschar *p, *q, *r, *ss; int len, off; p = Ustrchr(s, '\\'); if (!p) return s; len = Ustrlen(s) + 1; ss = store_get(len); q = ss; off = p - s; if (off) { memcpy(q, s, off); q += off; } while (*p) { if (*p == '\\') { *q++ = string_interpret_escape((const uschar **)&p); p++; } else { r = Ustrchr(p, '\\'); if (!r) { off = Ustrlen(p); memcpy(q, p, off); p += off; q += off; break; } else { off = r - p; memcpy(q, p, off); q += off; p = r; } } } *q = '\0'; return ss; }
static uschar * rfc2231_to_2047(const uschar * fname, const uschar * charset, int * len) { int size = 0, ptr = 0; uschar * val = string_cat(NULL, &size, &ptr, US"=?", 2); uschar c; if (charset) val = string_cat(val, &size, &ptr, charset, Ustrlen(charset)); val = string_cat(val, &size, &ptr, US"?Q?", 3); while ((c = *fname)) if (c == '%' && isxdigit(fname[1]) && isxdigit(fname[2])) { val = string_cat(val, &size, &ptr, US"=", 1); val = string_cat(val, &size, &ptr, ++fname, 2); fname += 2; } else val = string_cat(val, &size, &ptr, fname++, 1); val = string_cat(val, &size, &ptr, US"?=", 2); val[*len = ptr] = '\0'; return val; }
static uschar * pdkim_decode_qp(uschar * str) { int nchar = 0; uschar * q; uschar * p = str; uschar * n = store_get(Ustrlen(str)+1); *n = '\0'; q = n; while (*p) { if (*p == '=') { p = pdkim_decode_qp_char(p, &nchar); if (nchar >= 0) { *q++ = nchar; continue; } } else *q++ = *p; p++; } *q = '\0'; return n; }
static int rfc2047_qpdecode(uschar *string, uschar **ptrptr) { int len = 0; uschar *ptr; ptr = *ptrptr = store_get(Ustrlen(string) + 1); /* No longer than this */ while (*string != 0) { int ch = *string++; if (ch == '_') *ptr++ = ' '; else if (ch == '=') { int a = *string; int b = (a == 0)? 0 : string[1]; if (!isxdigit(a) || !isxdigit(b)) return -1; /* Bad QP string */ *ptr++ = ((Ustrchr(hex_digits, tolower(a)) - hex_digits) << 4) + Ustrchr(hex_digits, tolower(b)) - hex_digits; string += 2; } else if (ch == ' ' || ch == '\t') return -1; /* Whitespace is illegal */ else *ptr++ = ch; len++; } *ptr = 0; return len; }
void create_dialog(uschar *label, uschar *value) { Arg warg[4]; Dimension x, y, xx, yy; XtTranslations pop_trans; Widget text; /* Get the position of a reference widget so the dialog box can be put near to it. */ get_pos_args[0].value = (XtArgVal)(&x); get_pos_args[1].value = (XtArgVal)(&y); XtGetValues(dialog_ref_widget, get_pos_args, 2); /* When this is not a message_specific thing, the position of the reference widget is relative to the window. Get the position of the top level widget and add to the position. */ if (dialog_ref_widget != menushell) { get_pos_args[0].value = (XtArgVal)(&xx); get_pos_args[1].value = (XtArgVal)(&yy); XtGetValues(toplevel_widget, get_pos_args, 2); x += xx; y += yy; } /* Create a transient shell for the dialog box. */ XtSetArg(warg[0], XtNtransientFor, queue_widget); XtSetArg(warg[1], XtNx, x + 50); XtSetArg(warg[2], XtNy, y + 50); XtSetArg(warg[3], XtNallowShellResize, True); dialog_shell = XtCreatePopupShell("forDialog", transientShellWidgetClass, toplevel_widget, warg, 4); /* Create the dialog box. */ dialog_arg[0].value = (XtArgVal)label; dialog_arg[1].value = (XtArgVal)value; dialog_widget = XtCreateManagedWidget("dialog", dialogWidgetClass, dialog_shell, dialog_arg, XtNumber(dialog_arg)); /* Get the text widget from within the dialog box, give it the keyboard focus, make it wider than the default, and override its translations to make Return call the dialog action function. */ text = XtNameToWidget(dialog_widget, "value"); XawTextSetInsertionPoint(text, Ustrlen(value)); XtSetKeyboardFocus(dialog_widget, text); xs_SetValues(text, 1, "width", 200); pop_trans = XtParseTranslationTable( "<Key>Return: dialogAction()\n"); XtOverrideTranslations(text, pop_trans); /* Pop the thing up. */ XtPopup(dialog_shell, XtGrabExclusive); XFlush(X_display); }
static int sqlite_callback(void *arg, int argc, char **argv, char **azColName) { struct strbuf *res = arg; int i; /* For second and subsequent results, insert \n */ if (res->string != NULL) res->string = string_cat(res->string, &res->size, &res->len, US"\n", 1); if (argc > 1) { /* For multiple fields, include the field name too */ for (i = 0; i < argc; i++) { uschar *value = US((argv[i] != NULL)? argv[i]:"<NULL>"); res->string = lf_quote(US azColName[i], value, Ustrlen(value), res->string, &res->size, &res->len); } } else { res->string = string_append(res->string, &res->size, &res->len, 1, (argv[0] != NULL)? argv[0]:"<NULL>"); } res->string[res->len] = 0; return 0; }
uschar * tls_field_from_dn(uschar * dn, const uschar * mod) { int insep = ','; uschar outsep = '\n'; uschar * ele; uschar * match = NULL; int len; uschar * list = NULL; while ((ele = string_nextinlist(&mod, &insep, NULL, 0))) if (ele[0] != '>') match = ele; /* field tag to match */ else if (ele[1]) outsep = ele[1]; /* nondefault output separator */ dn_to_list(dn); insep = ','; len = match ? Ustrlen(match) : -1; while ((ele = string_nextinlist(CUSS &dn, &insep, NULL, 0))) if ( !match || Ustrncmp(ele, match, len) == 0 && ele[len] == '=' ) list = string_append_listele(list, outsep, ele+len+1); return list; }
uschar * string_copy_dnsdomain(uschar *s) { uschar *yield; uschar *ss = yield = store_get(Ustrlen(s) + 1); while (*s != 0) { if (*s != '\\') { *ss++ = *s++; } else if (isdigit(s[1])) { *ss++ = (s[1] - '0')*100 + (s[2] - '0')*10 + s[3] - '0'; s += 4; } else if (*(++s) != 0) { *ss++ = *s++; } } *ss = 0; return yield; }
int search_findtype(const uschar *name, int len) { int bot = 0; int top = lookup_list_count; while (top > bot) { int mid = (top + bot)/2; int c = Ustrncmp(name, lookup_list[mid]->name, len); /* If c == 0 we have matched the incoming name with the start of the search type name. However, some search types are substrings of others (e.g. nis and nisplus) so we need to check that the lengths are the same. The length of the type name cannot be shorter (else c would not be 0); if it is not equal it must be longer, and in that case, the incoming name comes before the name we are testing. By leaving c == 0 when the lengths are different, and doing a > 0 test below, this all falls out correctly. */ if (c == 0 && Ustrlen(lookup_list[mid]->name) == len) { if (lookup_list[mid]->find != NULL) return mid; search_error_message = string_sprintf("lookup type \"%.*s\" is not " "available (not in the binary - check buildtime LOOKUP configuration)", len, name); return -1; } if (c > 0) bot = mid + 1; else top = mid; } search_error_message = string_sprintf("unknown lookup type \"%.*s\"",len,name); return -1; }
static BOOL read_nonrecipients_tree(tree_node **connect, FILE *f, uschar *buffer, int buffer_size) { tree_node *node; int n = Ustrlen(buffer); BOOL right = buffer[1] == 'Y'; if (n < 5) return FALSE; /* malformed line */ buffer[n-1] = 0; /* Remove \n */ node = store_get(sizeof(tree_node) + n - 3); *connect = node; Ustrcpy(node->name, buffer + 3); node->data.ptr = NULL; if (buffer[0] == 'Y') { if (Ufgets(buffer, buffer_size, f) == NULL || !read_nonrecipients_tree(&node->left, f, buffer, buffer_size)) return FALSE; } else node->left = NULL; if (right) { if (Ufgets(buffer, buffer_size, f) == NULL || !read_nonrecipients_tree(&node->right, f, buffer, buffer_size)) return FALSE; } else node->right = NULL; (void) count_below(*connect); return TRUE; }
int tls_import_cert(const uschar * buf, void ** cert) { void * reset_point = store_get(0); gnutls_datum_t datum; gnutls_x509_crt_t crt = *(gnutls_x509_crt_t *)cert; int fail = 0; if (crt) gnutls_x509_crt_deinit(crt); else gnutls_global_init(); gnutls_x509_crt_init(&crt); datum.data = string_unprinting(US buf); datum.size = Ustrlen(datum.data); if ((fail = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM))) { log_write(0, LOG_MAIN, "TLS error in certificate import: %s", gnutls_strerror(fail)); fail = 1; } else *cert = (void *)crt; store_reset(reset_point); return fail; }
static void rda_write_string(int fd, uschar *s) { int len = (s == NULL)? 0 : Ustrlen(s) + 1; (void)write(fd, &len, sizeof(int)); if (s != NULL) (void)write(fd, s, len); }
uschar * string_localpart_alabel_to_utf8(const uschar * alabel, uschar ** err) { size_t p_len = Ustrlen(alabel); punycode_uint * p; uschar * s; uschar * res; int rc; if (alabel[0] != 'x' || alabel[1] != 'n' || alabel[2] != '-' || alabel[3] != '-') { if (err) *err = US"bad alabel prefix"; return NULL; } p_len -= 4; p = (punycode_uint *) store_get((p_len+1) * sizeof(*p)); if ((rc = punycode_decode(p_len, CCS alabel+4, &p_len, p, NULL)) != PUNYCODE_SUCCESS) { if (err) *err = US punycode_strerror(rc); return NULL; } s = US stringprep_ucs4_to_utf8(p, p_len, NULL, &p_len); res = string_copyn(s, p_len); free(s); return res; }
/* decode quoted-printable MIME part */ static ssize_t mime_decode_qp(FILE* in, FILE* out, uschar* boundary) { uschar ibuf[MIME_MAX_LINE_LENGTH], obuf[MIME_MAX_LINE_LENGTH]; uschar *ipos, *opos; ssize_t len, size = 0; while (fgets(CS ibuf, MIME_MAX_LINE_LENGTH, in) != NULL) { if (boundary != NULL && Ustrncmp(ibuf, "--", 2) == 0 && Ustrncmp((ibuf+2), boundary, Ustrlen(boundary)) == 0 ) break; /* todo: check for missing boundary */ ipos = ibuf; opos = obuf; while (*ipos != 0) { if (*ipos == '=') { int decode_qp_result; ipos = mime_decode_qp_char(ipos, &decode_qp_result); if (decode_qp_result == -2) { /* Error from decoder. ipos is unchanged. */ mime_set_anomaly(MIME_ANOMALY_BROKEN_QP); *opos = '='; ++opos; ++ipos; } else if (decode_qp_result == -1) break; else if (decode_qp_result >= 0) { *opos = decode_qp_result; ++opos; } } else { *opos = *ipos; ++opos; ++ipos; } } /* something to write? */ len = opos - obuf; if (len > 0) { if (fwrite(obuf, 1, len, out) != len) return -1; /* error */ size += len; } } return size; }
uschar * string_copy_malloc(const uschar *s) { int len = Ustrlen(s) + 1; uschar *ss = store_malloc(len); memcpy(ss, s, len); return ss; }
static void compute_cram_md5(uschar *secret, uschar *challenge, uschar *digestptr) { md5 base; int i; int len = Ustrlen(secret); uschar isecret[64]; uschar osecret[64]; uschar md5secret[16]; /* If the secret is longer than 64 characters, we compute its MD5 digest and use that. */ if (len > 64) { md5_start(&base); md5_end(&base, (uschar *)secret, len, md5secret); secret = (uschar *)md5secret; len = 16; } /* The key length is now known to be <= 64. Set up the padded and xor'ed versions. */ memcpy(isecret, secret, len); memset(isecret+len, 0, 64-len); memcpy(osecret, isecret, 64); for (i = 0; i < 64; i++) { isecret[i] ^= 0x36; osecret[i] ^= 0x5c; } /* Compute the inner MD5 digest */ md5_start(&base); md5_mid(&base, isecret); md5_end(&base, (uschar *)challenge, Ustrlen(challenge), md5secret); /* Compute the outer MD5 digest */ md5_start(&base); md5_mid(&base, osecret); md5_end(&base, md5secret, 16, digestptr); }
void tree_add_duplicate(uschar *s, address_item *addr) { tree_node *node = store_get(sizeof(tree_node) + Ustrlen(s)); Ustrcpy(node->name, s); node->data.ptr = addr; if (!tree_insertnode(&tree_duplicates, node)) store_reset(node); }
void tree_add_nonrecipient(uschar *s) { tree_node *node = store_get(sizeof(tree_node) + Ustrlen(s)); Ustrcpy(node->name, s); node->data.ptr = NULL; if (!tree_insertnode(&tree_nonrecipients, node)) store_reset(node); }
uschar * string_copylc(const uschar *s) { uschar *ss = store_get(Ustrlen(s) + 1); uschar *p = ss; while (*s != 0) *p++ = tolower(*s++); *p = 0; return ss; }
int dbfn_delete(open_db *dbblock, uschar *key) { EXIM_DATUM key_datum; EXIM_DATUM_INIT(key_datum); /* Some DBM libraries require clearing */ EXIM_DATUM_DATA(key_datum) = CS key; EXIM_DATUM_SIZE(key_datum) = Ustrlen(key) + 1; return EXIM_DBDEL(dbblock->dbptr, key_datum); }
static int rda_write_string(int fd, const uschar *s) { int len = (s == NULL)? 0 : Ustrlen(s) + 1; return ( write(fd, &len, sizeof(int)) != sizeof(int) || (s != NULL && write(fd, s, len) != len) ) ? -1 : 0; }
void pvs_add_keyword(Char *keyword, Char *step, int induct) { KeywordItem *kwi; kwi=malloc(sizeof(KeywordItem)); kwi->str=keyword; kwi->len=Ustrlen(keyword); kwi->step=strdup((char*)UstrtoLocale(step)); kwi->induct=induct; kwi->next=kwlist; kwlist=kwi; }
void text_show(Widget w, uschar *s) { XawTextBlock b; b.firstPos = 0; b.ptr = CS s; b.format = FMT8BIT; b.length = Ustrlen(s); XawTextReplace(w, text_count, text_count, &b); text_count += b.length; XawTextSetInsertionPoint(w, text_count); }
void string_to_window(Char *messagegroup, Char *mess) { EDITINFO *edata; edata=message_window(messagegroup); if (!edata) { fprintf(stderr, (char*)UstrtoLocale(translate("No window named '%s'.\n%s\n")), UstrtoLocale(messagegroup), UstrtoLocale(mess)); return; } append_editwindow(edata->info, mess, Ustrlen(mess)); }
static void set_output_name(EDITINFO *einf) { int i=0,l; if (einf->outputname) free(einf->outputname); i= Ustrlen(latexdir); l = i+Ustrlen(einf->filename)+15; einf->outputname = (Char*) malloc(sizeof(Char)*l); if (latexdir[i-1]=='/') concat_in(einf->outputname,latexdir,einf->filename); else { Ustrcpy(einf->outputname,latexdir); einf->outputname[i]='/'; einf->outputname[i+1]=0; Ustrcat(einf->outputname, einf->filename); } if (output_mode==ASCII) Ustrncat(einf->outputname, translate(".asc"),l); else Ustrncat(einf->outputname, translate(".tex"),l); }
uschar * string_split_message(uschar *msg) { uschar *s, *ss; if (msg == NULL || Ustrlen(msg) <= 75) return msg; s = ss = msg = string_copy(msg); for (;;) { int i = 0; while (i < 75 && *ss != 0 && *ss != '\n') ss++, i++; if (*ss == 0) break; if (*ss == '\n') s = ++ss; else { uschar *t = ss + 1; uschar *tt = NULL; while (--t > s + 35) { if (*t == ' ') { if (t[-1] == ':') { tt = t; break; } if (tt == NULL) tt = t; } } if (tt == NULL) /* Can't split behind - try ahead */ { t = ss + 1; while (*t != 0) { if (*t == ' ' || *t == '\n') { tt = t; break; } t++; } } if (tt == NULL) break; /* Can't find anywhere to split */ *tt = '\n'; s = ss = tt+1; } } return msg; }
void tree_add_unusable(host_item *h) { tree_node *node; uschar s[256]; sprintf(CS s, "T:%.200s:%s", h->name, h->address); node = store_get(sizeof(tree_node) + Ustrlen(s)); Ustrcpy(node->name, s); node->data.val = h->why; if (h->status == hstatus_unusable_expired) node->data.val += 256; if (!tree_insertnode(&tree_unusable, node)) store_reset(node); }
/* just dump MIME part without any decoding */ static ssize_t mime_decode_asis(FILE* in, FILE* out, uschar* boundary) { ssize_t len, size = 0; uschar buffer[MIME_MAX_LINE_LENGTH]; while(fgets(CS buffer, MIME_MAX_LINE_LENGTH, mime_stream) != NULL) { if (boundary != NULL && Ustrncmp(buffer, "--", 2) == 0 && Ustrncmp((buffer+2), boundary, Ustrlen(boundary)) == 0 ) break; len = Ustrlen(buffer); if (fwrite(buffer, 1, (size_t)len, out) < len) return -1; size += len; } /* while */ return size; }