예제 #1
0
static gboolean
decode_route (const char **in)
{
	const char *start = *in;
	const char *inptr = *in;
	GString *route;
	
	route = g_string_new ("");
	
	do {
		inptr++;
		
		g_string_append_c (route, '@');
		if (!decode_domain (&inptr, route)) {
			g_string_free (route, TRUE);
			goto error;
		}
		
		decode_lwsp (&inptr);
		if (*inptr == ',') {
			g_string_append_c (route, ',');
			inptr++;
			decode_lwsp (&inptr);
			
			/* obs-domain-lists allow commas with nothing between them... */
			while (*inptr == ',') {
				inptr++;
				decode_lwsp (&inptr);
			}
		}
	} while (*inptr == '@');
	
	g_string_free (route, TRUE);
	decode_lwsp (&inptr);
	
	if (*inptr != ':') {
		w(g_warning ("Invalid route domain-list, missing ':': %.*s", inptr - start, start));
		goto error;
	}
	
	/* eat the ':' */
	*in = inptr + 1;
	
	return TRUE;
	
 error:
	
	while (*inptr && *inptr != ':' && *inptr != '>')
		inptr++;
	
	if (*inptr == ':')
		inptr++;
	
	*in = inptr;
	
	return FALSE;
}
예제 #2
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;
}
예제 #3
0
static InternetAddress *
decode_addrspec (const char **in)
{
	InternetAddress *mailbox = NULL;
	const char *start, *inptr, *word;
	gboolean got_local = FALSE;
	GString *addr;
	size_t len;
	
	addr = g_string_new ("");
	inptr = *in;
	
	decode_lwsp (&inptr);
	
	/* some spam bots set their addresses to stuff like: )[email protected] */
	while (*inptr && !(*inptr == '"' || is_atom (*inptr)))
		inptr++;
	
	start = inptr;
	
	/* extract the first word of the local-part */
	if ((word = decode_word (&inptr))) {
		g_string_append_len (addr, word, (size_t) (inptr - word));
		decode_lwsp (&inptr);
		got_local = TRUE;
	}
	
	/* extract the rest of the local-part */
	while (word && *inptr == '.') {
		/* Note: According to the spec, only a single '.' is
		 * allowed between word tokens in the local-part of an
		 * addr-spec token, but according to Evolution bug
		 * #547969, some Japanese cellphones have email
		 * addresses that look like [email protected] */
		do {
			inptr++;
			decode_lwsp (&inptr);
			g_string_append_c (addr, '.');
		} while (*inptr == '.');
		
		if ((word = decode_word (&inptr)))
			g_string_append_len (addr, word, (size_t) (inptr - word));
		
		decode_lwsp (&inptr);
	}
	
	if (*inptr == '@') {
		len = addr->len;
		
		g_string_append_c (addr, '@');
		inptr++;
		
		if (!decode_domain (&inptr, addr)) {
			/* drop the @domain and continue as if it weren't there */
			w(g_warning ("Missing domain in addr-spec: %.*s",
				     inptr - start, start));
			g_string_truncate (addr, len);
		}
	} else if (got_local) {
		w(g_warning ("Missing '@' and domain in addr-spec: %.*s",
			     inptr - start, start));
	}
	
	*in = inptr;
	
	if (!got_local) {
		w(g_warning ("Invalid addr-spec, missing local-part: %.*s",
			     inptr - start, start));
		g_string_free (addr, TRUE);
		return NULL;
	}
	
	mailbox = g_object_newv (INTERNET_ADDRESS_TYPE_MAILBOX, 0, NULL);
	((InternetAddressMailbox *) mailbox)->addr = addr->str;
	g_string_free (addr, FALSE);
	
	return mailbox;
}
예제 #4
0
static int get_command(struct command_s *command)
{
	char *next;

again:
	printf("command: ");

	if (!fgets(cbuf, COMMAND_MAX_LEN, stdin))
		return -1;

	next = strtok(cbuf, " \n");
	if (!next)
		goto again;

	if (decode_type(command, next)) {
		fprintf(stderr, "Invalid command type \"%s\"\n", next);
		goto again;
	}

	if (command->c_type == HELP)
		return 0;

	next = strtok(NULL, " ");
	if (!next) {
		fprintf(stderr, "invalid input!\n");
		goto again;
	}

	switch (command->c_type) {
	case REGISTER:
	case UNREGISTER:
		if (decode_domain(command, next)) {
			fprintf(stderr, "Invalid domain \"%s\"\n", next);
			goto again;
		}
		break;
	case LOCK:
	case TRYLOCK:
		if (decode_level(command, next)) {
			fprintf(stderr, "Invalid lock level \"%s\"\n", next);
			goto again;
		}

		next = strtok(NULL, " ");
		if (!next) {
			fprintf(stderr, "invalid input!\n");
			goto again;
		}

		/* fall through */
	case SETLVB:
	case GETLVB:
	case UNLOCK:
		if (decode_lock(command, next)) {
			fprintf(stderr, "Invalid lock \"%s\"\n", next);
			goto again;
		}

		if (command->c_type == SETLVB) {
			/* for setlvb we want to get a pointer to the
			 * start of the string to stuff */
			next = strtok(NULL, "\n");
			if (!next) {
				fprintf(stderr, "invalid input!\n");
				goto again;
			}

			kill_return(next);
			command->c_lvb = next;
		}
		break;
	default:
		fprintf(stderr, "whoa, can't parse this\n");
	}
	return 0;
}