static void append_folded_name (GString *string, size_t *linelen, const char *name) { const char *word, *lwsp; size_t len; word = name; while (*word) { lwsp = word; if (*word == '"') { /* quoted string, don't break these up */ lwsp++; while (*lwsp && *lwsp != '"') { if (*lwsp == '\\') lwsp++; if (*lwsp) lwsp++; } if (*lwsp == '"') lwsp++; } else { /* normal word */ while (*lwsp && !is_lwsp (*lwsp)) lwsp++; } len = lwsp - word; if (*linelen > 1 && (*linelen + len) > GMIME_FOLD_LEN) { linewrap (string); *linelen = 1; } g_string_append_len (string, word, len); *linelen += len; word = lwsp; while (*word && is_lwsp (*word)) word++; if (*word && is_lwsp (*lwsp)) { g_string_append_c (string, ' '); (*linelen)++; } } }
static void skip_lwsp (const char **in) { register const char *inptr = *in; while (*inptr && is_lwsp (*inptr)) inptr++; *in = inptr; }
/** * g_mime_strdup_trim: * @str: The string to duplicate and trim * * Duplicates the given input string while also trimming leading and * trailing whitespace. * * Returns a duplicate string, minus any leading and trailing * whitespace that the original string may have contained. **/ char * g_mime_strdup_trim (const char *str) { register const char *inptr = str; register const char *end; const char *start; while (is_lwsp (*inptr)) inptr++; start = inptr; end = inptr; while (*inptr) { if (!is_lwsp (*inptr++)) end = inptr; } return g_strndup (start, (size_t) (end - start)); }
static void copy_atom (const char *src, char *dest, size_t n) { register const char *inptr = src; register char *outptr = dest; char *outend = dest + n; while (is_lwsp (*inptr)) inptr++; while (is_atom (*inptr) && outptr < outend) *outptr++ = *inptr++; *outptr = '\0'; }
static InternetAddress * decode_address (const char **in) { const char *inptr, *start, *word, *comment = NULL; InternetAddress *addr = NULL; gboolean has_lwsp = FALSE; gboolean is_word; GString *name; decode_lwsp (in); start = inptr = *in; name = g_string_new (""); /* Both groups and mailboxes can begin with a phrase (denoting * the display name for the address). Collect all of the * tokens that make up this name phrase. */ while (*inptr) { if ((word = decode_word (&inptr))) { g_string_append_len (name, word, (size_t) (inptr - word)); check_lwsp: word = inptr; skip_lwsp (&inptr); /* is the next token a word token? */ is_word = *inptr == '"' || is_atom (*inptr); if (inptr > word && is_word) { g_string_append_c (name, ' '); has_lwsp = TRUE; } if (is_word) continue; } /* specials = "(" / ")" / "<" / ">" / "@" ; Must be in quoted- * / "," / ";" / ":" / "\" / <"> ; string, to use * / "." / "[" / "]" ; within a word. */ if (*inptr == ':') { /* rfc2822 group */ inptr++; addr = decode_group (&inptr); decode_lwsp (&inptr); if (*inptr != ';') w(g_warning ("Invalid group spec, missing closing ';': %.*s", inptr - start, start)); else inptr++; break; } else if (*inptr == '<') { /* rfc2822 angle-addr */ inptr++; /* check for obsolete routing... */ if (*inptr != '@' || decode_route (&inptr)) { /* rfc2822 addr-spec */ addr = decode_addrspec (&inptr); } decode_lwsp (&inptr); if (*inptr != '>') { w(g_warning ("Invalid rfc2822 angle-addr, missing closing '>': %.*s", inptr - start, start)); while (*inptr && *inptr != '>' && *inptr != ',') inptr++; if (*inptr == '>') inptr++; } else { inptr++; } /* if comment is non-NULL, we can check for a comment containing a name */ comment = inptr; break; } else if (*inptr == '(') { /* beginning of a comment, use decode_lwsp() to skip past it */ decode_lwsp (&inptr); } else if (*inptr && strchr ("@,;", *inptr)) { if (name->len == 0) { if (*inptr == '@') { GString *domain; w(g_warning ("Unexpected address: %s: skipping.", start)); /* skip over @domain? */ inptr++; domain = g_string_new (""); decode_domain (&inptr, domain); g_string_free (domain, TRUE); } else { /* empty address */ } break; } else if (has_lwsp) { /* assume this is just an unquoted special that we should treat as part of the name */ w(g_warning ("Unquoted '%c' in address name: %s: ignoring.", *inptr, start)); g_string_append_c (name, *inptr); inptr++; goto check_lwsp; } addrspec: /* what we thought was a name was actually an addrspec? */ g_string_truncate (name, 0); inptr = start; addr = decode_addrspec (&inptr); /* if comment is non-NULL, we can check for a comment containing a name */ comment = inptr; break; } else if (*inptr == '.') { /* This would normally signify that we are * decoding the local-part of an addr-spec, * but sadly, it is common for broken mailers * to forget to quote/encode .'s in the name * phrase. */ g_string_append_c (name, *inptr); inptr++; goto check_lwsp; } else if (*inptr) { /* Technically, these are all invalid tokens * but in the interest of being liberal in * what we accept, we'll ignore them. */ w(g_warning ("Unexpected char '%c' in address: %s: ignoring.", *inptr, start)); g_string_append_c (name, *inptr); inptr++; goto check_lwsp; } else { goto addrspec; } } /* Note: will also skip over any comments */ decode_lwsp (&inptr); if (name->len == 0 && comment && inptr > comment) { /* missing a name, look for a trailing comment */ if ((comment = memchr (comment, '(', inptr - comment))) { const char *cend; /* find the end of the comment */ cend = inptr - 1; while (cend > comment && is_lwsp (*cend)) cend--; if (*cend == ')') cend--; g_string_append_len (name, comment + 1, (size_t) (cend - comment)); } } if (addr && name->len > 0) _internet_address_decode_name (addr, name); g_string_free (name, TRUE); *in = inptr; return addr; }
/** * camel_scalix_stream_next_token: * @stream: scalix stream * @token: scalix token * * Reads the next token from the scalix stream and saves it in @token. * * Returns 0 on success or -1 on fail. **/ int camel_scalix_stream_next_token (CamelSCALIXStream *stream, camel_scalix_token_t *token) { register unsigned char *inptr; unsigned char *inend, *start, *p; gboolean escaped = FALSE; size_t literal = 0; guint32 nz_number; int ret; g_return_val_if_fail (CAMEL_IS_SCALIX_STREAM (stream), -1); g_return_val_if_fail (stream->mode != CAMEL_SCALIX_STREAM_MODE_LITERAL, -1); g_return_val_if_fail (token != NULL, -1); if (stream->have_unget) { memcpy (token, &stream->unget, sizeof (camel_scalix_token_t)); stream->have_unget = FALSE; return 0; } token_clear (stream); inptr = stream->inptr; inend = stream->inend; *inend = '\0'; do { if (inptr == inend) { if ((ret = scalix_fill (stream)) < 0) { token->token = CAMEL_SCALIX_TOKEN_ERROR; return -1; } else if (ret == 0) { token->token = CAMEL_SCALIX_TOKEN_NO_DATA; return 0; } inptr = stream->inptr; inend = stream->inend; *inend = '\0'; } while (*inptr == ' ' || *inptr == '\r') inptr++; } while (inptr == inend); do { if (inptr < inend) { if (*inptr == '"') { /* qstring token */ escaped = FALSE; start = inptr; /* eat the beginning " */ inptr++; p = inptr; while (inptr < inend) { if (*inptr == '"' && !escaped) break; if (*inptr == '\\' && !escaped) { token_save (stream, p, inptr - p); escaped = TRUE; inptr++; p = inptr; } else { inptr++; escaped = FALSE; } } token_save (stream, p, inptr - p); if (inptr == inend) { stream->inptr = start; goto refill; } /* eat the ending " */ inptr++; /* nul-terminate the atom token */ token_save (stream, "", 1); token->token = CAMEL_SCALIX_TOKEN_QSTRING; token->v.qstring = stream->tokenbuf; d(fprintf (stderr, "token: \"%s\"\n", token->v.qstring)); break; } else if (strchr ("+*()[]\n", *inptr)) { /* special character token */ token->token = *inptr++; if (camel_debug ("scalix:stream")) { if (token->token != '\n') fprintf (stderr, "token: %c\n", token->token); else fprintf (stderr, "token: \\n\n"); } break; } else if (*inptr == '{') { /* literal identifier token */ if ((p = strchr (inptr, '}')) && strchr (p, '\n')) { inptr++; while (isdigit ((int) *inptr) && literal < UINT_MAX / 10) literal = (literal * 10) + (*inptr++ - '0'); if (*inptr != '}') { if (isdigit ((int) *inptr)) g_warning ("illegal literal identifier: literal too large"); else if (*inptr != '+') g_warning ("illegal literal identifier: garbage following size"); while (*inptr != '}') inptr++; } /* skip over '}' */ inptr++; /* skip over any trailing whitespace */ while (*inptr == ' ' || *inptr == '\r') inptr++; if (*inptr != '\n') { g_warning ("illegal token following literal identifier: %s", inptr); /* skip ahead to the eoln */ inptr = strchr (inptr, '\n'); } /* skip over '\n' */ inptr++; token->token = CAMEL_SCALIX_TOKEN_LITERAL; token->v.literal = literal; d(fprintf (stderr, "token: {%zu}\n", literal)); stream->mode = CAMEL_SCALIX_STREAM_MODE_LITERAL; stream->literal = literal; stream->eol = FALSE; break; } else { stream->inptr = inptr; goto refill; } } else if (*inptr >= '0' && *inptr <= '9') { /* number token */ *inend = '\0'; nz_number = strtoul ((char *) inptr, (char **) &start, 10); if (start == inend) goto refill; if (*start == ':' || *start == ',') { /* workaround for 'set' tokens (APPENDUID / COPYUID) */ goto atom_token; } inptr = start; token->token = CAMEL_SCALIX_TOKEN_NUMBER; token->v.number = nz_number; d(fprintf (stderr, "token: %u\n", nz_number)); break; } else if (is_atom (*inptr)) { atom_token: /* simple atom token */ start = inptr; while (inptr < inend && is_atom (*inptr)) inptr++; if (inptr == inend) { stream->inptr = start; goto refill; } token_save (stream, start, inptr - start); /* nul-terminate the atom token */ token_save (stream, "", 1); if (!strcmp (stream->tokenbuf, "NIL")) { /* special atom token */ token->token = CAMEL_SCALIX_TOKEN_NIL; d(fprintf (stderr, "token: NIL\n")); } else { token->token = CAMEL_SCALIX_TOKEN_ATOM; token->v.atom = stream->tokenbuf; d(fprintf (stderr, "token: %s\n", token->v.atom)); } break; } else if (*inptr == '\\') { /* possible flag token ("\" atom) */ start = inptr++; while (inptr < inend && is_atom (*inptr)) inptr++; if (inptr == inend) { stream->inptr = start; goto refill; } /* handle the \* case */ if ((inptr - start) == 1 && *inptr == '*') inptr++; if ((inptr - start) > 1) { token_save (stream, start, inptr - start); /* nul-terminate the flag token */ token_save (stream, "", 1); token->token = CAMEL_SCALIX_TOKEN_FLAG; token->v.atom = stream->tokenbuf; d(fprintf (stderr, "token: %s\n", token->v.atom)); } else { token->token = '\\'; d(fprintf (stderr, "token: %c\n", token->token)); } break; } else if (is_lwsp (*inptr)) { inptr++; } else { /* unknown character token? */ token->token = *inptr++; d(fprintf (stderr, "token: %c\n", token->token)); break; } } else { refill: token_clear (stream); if (scalix_fill (stream) <= 0) { token->token = CAMEL_SCALIX_TOKEN_ERROR; return -1; } inptr = stream->inptr; inend = stream->inend; *inend = '\0'; } } while (inptr < inend); stream->inptr = inptr; return 0; }