Exemplo n.º 1
0
int
camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex)
{
	CamelService *service = CAMEL_SERVICE (store);
	CamelSession *session = camel_service_get_session (service);
	int resp;

	if (!service->url->authmech && !service->url->passwd) {
		gchar *prompt;

		prompt = camel_session_build_password_prompt (
			"NNTP", service->url->user, service->url->host);

		service->url->passwd = camel_session_get_password (
			session, prompt, TRUE, service, "password", ex);

		g_free (prompt);

		if (!service->url->passwd) {
			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
					     "You didn\'t enter a password.");
			resp = 666;
			goto done;
		}
	}

	/* first send username */
	resp = camel_nntp_command (store, ex, NULL, "AUTHINFO USER %s", service->url->user);

	if (resp == NNTP_AUTH_REJECTED) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
				      _("Server rejected username"));
		goto done;

	}
	else if (resp != NNTP_AUTH_CONTINUE) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
				      _("Failed to send username to server"));
		goto done;
	}

	/* then send the username if the server asks for it */
	resp = camel_nntp_command (store, ex, NULL, "AUTHINFO PASS %s", service->url->passwd);

	if (resp == NNTP_AUTH_REJECTED) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
				      _("Server rejected username/password"));
		goto done;
	}

 done:

	if (service->url->passwd) {
		/* let's be paranoid */
		memset (service->url->passwd, 0, strlen (service->url->passwd));
		g_free (service->url->passwd);
		service->url->passwd = NULL;
	}
	return resp;
}
Exemplo n.º 2
0
static CamelNNTPGroupList*
camel_nntp_get_grouplist_from_file (CamelNNTPStore *store, CamelException *ex)
{
	gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(store));
	gchar *grouplist_file = g_strdup_printf ("%s/grouplist", root_dir);
	CamelNNTPGroupList *list;
	FILE *fp;
	char buf[300];
	unsigned long time;

	g_free (root_dir);
	fp = g_fopen (grouplist_file, "r");
	g_free (grouplist_file);

	if (fp == NULL) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
				      _("Unable to load grouplist file for %s: %s"),
				      CAMEL_SERVICE(store)->url->host,
				      strerror(errno));
		return NULL;
	}

	/* read the time */
	if (!fgets (buf, sizeof (buf), fp)) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
				      _("Unable to load grouplist file for %s: %s"),
				      CAMEL_SERVICE(store)->url->host,
				      strerror(errno));
		fclose (fp);
		return NULL;
	}


	list = g_new0 (CamelNNTPGroupList, 1);
	list->store = store;
	sscanf (buf, "%lu", &time);
	list->time = time;

	while (fgets (buf, sizeof (buf), fp)) {
		CamelNNTPGroupListEntry *entry = g_new (CamelNNTPGroupListEntry, 1);
		char **split_line = g_strsplit (buf, " ", 4);

		entry->group_name = g_strdup (split_line[0]);
		entry->high = atoi (split_line[1]);
		entry->low = atoi (split_line[2]);

		g_strfreev (split_line);

		list->group_list = g_list_prepend (list->group_list, entry);
	}

	fclose (fp);

	list->group_list = g_list_reverse(list->group_list);
	return list;
}
Exemplo n.º 3
0
static GByteArray *
anon_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
{
	CamelSaslAnonymous *sasl_anon = CAMEL_SASL_ANONYMOUS (sasl);
	CamelInternetAddress *cia;
	GByteArray *ret = NULL;

	if (token) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
				     _("Authentication failed."));
		return NULL;
	}

	switch (sasl_anon->type) {
	case CAMEL_SASL_ANON_TRACE_EMAIL:
		cia = camel_internet_address_new ();
		if (camel_internet_address_add (cia, NULL, sasl_anon->trace_info) != 1) {
			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
					      _("Invalid email address trace information:\n%s"),
					      sasl_anon->trace_info);
			camel_object_unref (cia);
			return NULL;
		}
		camel_object_unref (cia);
		ret = g_byte_array_new ();
		g_byte_array_append (ret, (guint8 *) sasl_anon->trace_info, strlen (sasl_anon->trace_info));
		break;
	case CAMEL_SASL_ANON_TRACE_OPAQUE:
		if (strchr (sasl_anon->trace_info, '@')) {
			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
					      _("Invalid opaque trace information:\n%s"),
					      sasl_anon->trace_info);
			return NULL;
		}
		ret = g_byte_array_new ();
		g_byte_array_append (ret, (guint8 *) sasl_anon->trace_info, strlen (sasl_anon->trace_info));
		break;
	case CAMEL_SASL_ANON_TRACE_EMPTY:
		ret = g_byte_array_new ();
		break;
	default:
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
				      _("Invalid trace information:\n%s"),
				      sasl_anon->trace_info);
		return NULL;
	}

	sasl->authenticated = TRUE;
	return ret;
}
static CamelStream *
insert_setup (CamelImapMessageCache *cache, const char *uid, const char *part_spec,
	      char **path, char **key, CamelException *ex)
{
	CamelStream *stream;
	int fd;

#ifdef G_OS_WIN32
	/* Trailing periods in file names are silently dropped on
	 * Win32, argh. The code in this file requires the period to
	 * be there. So in case part_spec is empty, use a tilde (just
	 * a random choice) instead.
	 */
	if (!*part_spec)
		part_spec = "~";
#endif
	*path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec);
	*key = strrchr (*path, '/') + 1;
	stream = g_hash_table_lookup (cache->parts, *key);
	if (stream)
		camel_object_unref (CAMEL_OBJECT (stream));

	fd = g_open (*path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);
	if (fd == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Failed to cache message %s: %s"),
				      uid, g_strerror (errno));
		g_free (*path);
		return NULL;
	}

	return camel_stream_fs_new_with_fd (fd);
}
Exemplo n.º 5
0
static char *
get_storage_path (CamelSession *session, CamelService *service, CamelException *ex)
{
	char *path, *p;

	p = camel_service_get_path (service);
	path = g_strdup_printf ("%s/%s", session->storage_path, p);
	g_free (p);

#ifdef G_OS_WIN32
	if (g_access (path, F_OK) == 0)
#else
	if (access (path, F_OK) == 0)
#endif
		return path;

	if (g_mkdir_with_parents (path, S_IRWXU) == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Could not create directory %s:\n%s"),
				      path, g_strerror (errno));
		g_free (path);
		return NULL;
	}

	return path;
}
/* I do not know what to do this exactly. Looking at the IMAP implementation for this, it
   seems to assume the message is copied to a folder on the same store. In that case, an
   NNTP implementation doesn't seem to make any sense. */
static void
nntp_folder_transfer_message (CamelFolder *source, GPtrArray *uids, CamelFolder *dest,
			      GPtrArray **transferred_uids, gboolean delete_orig, CamelException *ex)
{
	camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
	                      _("You cannot copy messages from a NNTP folder!"));
}
Exemplo n.º 7
0
void
camel_nntp_grouplist_save (CamelNNTPGroupList *group_list, CamelException *ex)
{
	FILE *fp;
	gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(group_list->store));
	gchar *grouplist_file = g_strdup_printf ("%s/grouplist", root_dir);

	g_free (root_dir);
	fp = g_fopen (grouplist_file, "w");
	g_free (grouplist_file);

	if (fp == NULL) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
				      _("Unable to save grouplist file for %s: %s"),
				      CAMEL_SERVICE(group_list->store)->url->host,
				      strerror(errno));
		return;
	}

	fprintf (fp, "%lu\n", (long)group_list->time);

	g_list_foreach (group_list->group_list, (GFunc)save_entry, fp);

	fclose (fp);
}
static void
nntp_folder_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex)
{
	CamelNNTPStore *nntp_store = (CamelNNTPStore *)((CamelFolder *) disco_folder)->parent_store;
	CamelStream *stream;
	char *article, *msgid;

	article = alloca(strlen(uid)+1);
	strcpy(article, uid);
	msgid = strchr(article, ',');
	if (!msgid) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Internal error: UID in invalid format: %s"), uid);
		return;
	}
	*msgid++ = 0;

	CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);

	stream = nntp_folder_download_message ((CamelNNTPFolder *) disco_folder, article, msgid, ex);
	if (stream)
		camel_object_unref (stream);

	CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
}
/**
 * camel_imap_response_extract:
 * @store: the store the response came from
 * @response: the response data returned from camel_imap_command
 * @type: the response type to extract
 * @ex: a CamelException
 *
 * This checks that @response contains a single untagged response of
 * type @type and returns just that response data. If @response
 * doesn't contain the right information, the function will set @ex
 * and return %NULL. Either way, @response will be freed and the
 * store's connect_lock released.
 *
 * Return value: the desired response string, which the caller must free.
 **/
char *
camel_imap_response_extract (CamelImapStore *store,
			     CamelImapResponse *response,
			     const char *type,
			     CamelException *ex)
{
	int len = strlen (type), i;
	char *resp;

	len = strlen (type);

	for (i = 0; i < response->untagged->len; i++) {
		resp = response->untagged->pdata[i];
		/* Skip "* ", and initial sequence number, if present */
		strtoul (resp + 2, &resp, 10);
		if (*resp == ' ')
			resp = (char *) imap_next_word (resp);

		if (!g_ascii_strncasecmp (resp, type, len))
			break;
	}

	if (i < response->untagged->len) {
		resp = response->untagged->pdata[i];
		g_ptr_array_remove_index (response->untagged, i);
	} else {
		resp = NULL;
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
				      _("IMAP server response did not contain "
					"%s information"), type);
	}

	camel_imap_response_free (store, response);
	return resp;
}
Exemplo n.º 10
0
static char *
mail_tool_get_local_movemail_path (const unsigned char *uri, CamelException *ex)
{
	unsigned char *safe_uri, *c;
	char *path, *full;
	struct stat st;

	safe_uri = (unsigned char *)g_strdup ((const gchar *)uri);
	for (c = safe_uri; *c; c++)
		if (strchr("/:;=|%&#!*^()\\, ", *c) || !isprint((int) *c))
			*c = '_';

	path = g_strdup_printf("%s/spool", mail_component_peek_base_directory(NULL));
	if (g_stat(path, &st) == -1 && g_mkdir_with_parents(path, 0777) == -1) {
		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not create spool directory `%s': %s"),
				     path, g_strerror(errno));
		g_free(path);
		return NULL;
	}

	full = g_strdup_printf("%s/movemail.%s", path, safe_uri);
	g_free(path);
	g_free(safe_uri);

	return full;
}
static void
nntp_folder_append_message_offline (CamelFolder *folder, CamelMimeMessage *mime_message,
				    const CamelMessageInfo *info, char **appended_uid,
				    CamelException *ex)
{
	camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
	                      _("You cannot post NNTP messages while working offline!"));
}
static int
groupwise_entry_play_transfer (CamelOfflineJournal *journal, CamelGroupwiseJournalEntry *entry, CamelException *ex)
{
	CamelGroupwiseFolder *gw_folder = (CamelGroupwiseFolder *) journal->folder;
	CamelFolder *folder = journal->folder;
	CamelGroupwiseMessageInfo *real;
	CamelMessageInfoBase *info;
	GPtrArray *xuids, *uids;
	CamelException lex;
	CamelFolder *src;
	const char *name;

	if (!(info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, entry->uid))) {
		/* Note: this should never happen, but rather than crash lets make a new info */
		info = camel_message_info_new (NULL);
	}

	name = camel_groupwise_store_folder_lookup ((CamelGroupwiseStore *) folder->parent_store, entry->source_container);
	if (name && (src = camel_store_get_folder (folder->parent_store, name, 0, ex))) {
		uids = g_ptr_array_sized_new (1);
		g_ptr_array_add (uids, entry->original_uid);

		camel_exception_init (&lex);
		camel_folder_transfer_messages_to (src, uids, folder, &xuids, FALSE, &lex);
		if (!camel_exception_is_set (&lex)) {
			real = (CamelGroupwiseMessageInfo *) camel_folder_summary_uid (folder->summary, xuids->pdata[0]);

			/* transfer all the system flags, user flags/tags, etc */
			gw_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info);
			camel_message_info_free (real);
		} else {
			camel_exception_xfer (ex, &lex);
			goto exception;
		}

		g_ptr_array_free (xuids, TRUE);
		g_ptr_array_free (uids, TRUE);
		camel_object_unref (src);
	} else if (!name) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get folder container %s"),
				      entry->source_container);
		goto exception;
	}

	/* message was successfully transferred, remove the fake item from the cache/summary */
	camel_folder_summary_remove_uid (folder->summary, entry->uid);
	camel_data_cache_remove (gw_folder->cache, "cache", entry->uid, NULL);
	camel_message_info_free (info);

	return 0;

 exception:

	camel_message_info_free (info);

	return -1;
}
static gboolean
update_cache (CamelGroupwiseJournal *groupwise_journal, CamelMimeMessage *message,
	      const CamelMessageInfo *mi, char **updated_uid, CamelException *ex)
{
	CamelOfflineJournal *journal = (CamelOfflineJournal *) groupwise_journal;
	CamelGroupwiseFolder *groupwise_folder = (CamelGroupwiseFolder *) journal->folder;
	CamelFolder *folder = (CamelFolder *) journal->folder;
	CamelMessageInfo *info;
	CamelStream *cache;
	guint32 nextuid;
	char *uid;

	if (groupwise_folder->cache == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
				     _("Cannot append message in offline mode: cache unavailable"));
		return FALSE;
	}

	nextuid = camel_folder_summary_next_uid (folder->summary);
	uid = g_strdup_printf ("-%u", nextuid);

	if (!(cache = camel_data_cache_add (groupwise_folder->cache, "cache", uid, ex))) {
		folder->summary->nextuid--;
		g_free (uid);
		return FALSE;
	}

	if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, cache) == -1
	    || camel_stream_flush (cache) == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Cannot append message in offline mode: %s"),
				      g_strerror (errno));
		camel_data_cache_remove (groupwise_folder->cache, "cache", uid, NULL);
		folder->summary->nextuid--;
		camel_object_unref (cache);
		g_free (uid);
		return FALSE;
	}

	camel_object_unref (cache);

	info = camel_folder_summary_info_new_from_message (folder->summary, message);
	g_free(info->uid);
	info->uid = g_strdup (uid);

	gw_message_info_dup_to ((CamelMessageInfoBase *) info, (CamelMessageInfoBase *) mi);

	camel_folder_summary_add (folder->summary, info);

	if (updated_uid)
		*updated_uid = g_strdup (uid);

	g_free (uid);

	return TRUE;
}
/**
 * camel_imap_message_cache_new:
 * @path: directory to use for storage
 * @summary: CamelFolderSummary for the folder we are caching
 * @ex: a CamelException
 *
 * Return value: a new CamelImapMessageCache object using @path for
 * storage. If cache files already exist in @path, then any that do not
 * correspond to messages in @summary will be deleted.
 **/
CamelImapMessageCache *
camel_imap_message_cache_new (const char *path, CamelFolderSummary *summary,
			      CamelException *ex)
{
	CamelImapMessageCache *cache;
	GDir *dir;
	const char *dname;
	char *uid, *p;
	GPtrArray *deletes;
	CamelMessageInfo *info;
	GError *error = NULL;

	dir = g_dir_open (path, 0, &error);
	if (!dir) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Could not open cache directory: %s"),
				      error->message);
		g_error_free (error);
		return NULL;
	}

	cache = (CamelImapMessageCache *)camel_object_new (CAMEL_IMAP_MESSAGE_CACHE_TYPE);
	cache->path = g_strdup (path);

	cache->parts = g_hash_table_new (g_str_hash, g_str_equal);
	cache->cached = g_hash_table_new (NULL, NULL);
	deletes = g_ptr_array_new ();
	while ((dname = g_dir_read_name (dir))) {
		if (!isdigit (dname[0]))
			continue;
		p = strchr (dname, '.');
		if (p)
			uid = g_strndup (dname, p - dname);
		else
			uid = g_strdup (dname);

		info = camel_folder_summary_uid (summary, uid);
		if (info) {
			camel_message_info_free(info);
			cache_put (cache, uid, dname, NULL);
		} else
			g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, dname));
		g_free (uid);
	}
	g_dir_close (dir);

	while (deletes->len) {
		g_unlink (deletes->pdata[0]);
		g_free (deletes->pdata[0]);
		g_ptr_array_remove_index_fast (deletes, 0);
	}
	g_ptr_array_free (deletes, TRUE);

	return cache;
}
Exemplo n.º 15
0
static CamelService *
get_service (CamelSession *session, const char *url_string,
	     CamelProviderType type, CamelException *ex)
{
	CamelURL *url;
	CamelProvider *provider;
	CamelService *service;
	CamelException internal_ex;

	url = camel_url_new (url_string, ex);
	if (!url)
		return NULL;

	/* We need to look up the provider so we can then lookup
	   the service in the provider's cache */
	provider = camel_provider_get(url->protocol, ex);
	if (provider && !provider->object_types[type]) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID,
				      _("No provider available for protocol `%s'"),
				      url->protocol);
		provider = NULL;
	}

	if (!provider) {
		camel_url_free (url);
		return NULL;
	}

	/* If the provider doesn't use paths but the URL contains one,
	 * ignore it.
	 */
	if (url->path && !CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_PATH))
		camel_url_set_path (url, NULL);

	/* Now look up the service in the provider's cache */
//	service = camel_object_bag_reserve(provider->service_cache[type], url);
//	if (service == NULL) {
		service = (CamelService *)camel_object_new (provider->object_types[type]);
		camel_exception_init (&internal_ex);
		camel_service_construct (service, session, provider, url, &internal_ex);
		if (camel_exception_is_set (&internal_ex)) {
			camel_exception_xfer (ex, &internal_ex);
			camel_object_unref (service);
			service = NULL;
//			camel_object_bag_abort(provider->service_cache[type], url);
		} else {
//			camel_object_bag_add(provider->service_cache[type], url, service);
		}
//	}

	camel_url_free (url);

	return service;
}
Exemplo n.º 16
0
/**
 * camel_offline_journal_write:
 * @journal: a #CamelOfflineJournal object
 * @ex: a #CamelException
 *
 * Save the journal to disk.
 *
 * Returns %0 on success or %-1 on fail
 **/
int
camel_offline_journal_write (CamelOfflineJournal *journal, CamelException *ex)
{
	EDListNode *entry;
	FILE *fp;
	int fd;

	if ((fd = g_open (journal->filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Cannot write offline journal for folder `%s': %s"),
				      journal->folder->full_name, g_strerror (errno));
		return -1;
	}

	fp = fdopen (fd, "w");
	entry = journal->queue.head;
	while (entry->next) {
		if (CAMEL_OFFLINE_JOURNAL_GET_CLASS (journal)->entry_write (journal, entry, fp) == -1)
			goto exception;
		entry = entry->next;
	}

	if (fsync (fd) == -1)
		goto exception;

	fclose (fp);

	return 0;

 exception:

	camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
			      _("Cannot write offline journal for folder `%s': %s"),
			      journal->folder->full_name, g_strerror (errno));

	fclose (fp);

	return -1;
}
struct addrinfo *
camel_getaddrinfo(const char *name, const char *service, const struct addrinfo *hints, CamelException *ex)
{
	struct _addrinfo_msg *msg;
	struct addrinfo *res = NULL;
#ifndef ENABLE_IPv6
	struct addrinfo myhints;
#endif
	g_return_val_if_fail(name != NULL, NULL);

	if (camel_operation_cancel_check(NULL)) {
		camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled"));
		return NULL;
	}

	camel_operation_start_transient(NULL, _("Resolving: %s"), name);

	/* force ipv4 addresses only */
#ifndef ENABLE_IPv6
	if (hints == NULL)
		memset(&myhints, 0, sizeof(myhints));
	else
		memcpy (&myhints, hints, sizeof (myhints));

	myhints.ai_family = AF_INET;
	hints = &myhints;
#endif

	msg = g_malloc0(sizeof(*msg));
	msg->name = name;
	msg->service = service;
	msg->hints = hints;
	msg->res = &res;
#ifdef NEED_ADDRINFO
	msg->hostbuflen = 1024;
	msg->hostbufmem = g_malloc(msg->hostbuflen);
#endif
	if (cs_waitinfo(cs_getaddrinfo, msg, _("Host lookup failed"), ex) == 0) {
		if (msg->result != 0) {
			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: %s: %s"),
					      name, gai_strerror (msg->result));
		}

		cs_freeinfo(msg);
	} else
		res = NULL;

	camel_operation_end(NULL);

	return res;
}
int
camel_getnameinfo(const struct sockaddr *sa, socklen_t salen, char **host, char **serv, int flags, CamelException *ex)
{
	struct _addrinfo_msg *msg;
	int result;

	if (camel_operation_cancel_check(NULL)) {
		camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled"));
		return -1;
	}

	camel_operation_start_transient(NULL, _("Resolving address"));

	msg = g_malloc0(sizeof(*msg));
	msg->addr = sa;
	msg->addrlen = salen;
	if (host) {
		msg->hostlen = NI_MAXHOST;
		msg->host = g_malloc(msg->hostlen);
		msg->host[0] = 0;
	}
	if (serv) {
		msg->servlen = NI_MAXSERV;
		msg->serv = g_malloc(msg->servlen);
		msg->serv[0] = 0;
	}
	msg->flags = flags;
#ifdef NEED_ADDRINFO
	msg->hostbuflen = 1024;
	msg->hostbufmem = g_malloc(msg->hostbuflen);
#endif
	cs_waitinfo(cs_getnameinfo, msg, _("Name lookup failed"), ex);

	if ((result = msg->result) != 0)
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Name lookup failed: %s"),
				      gai_strerror (result));
	else {
		if (host)
			*host = g_strdup(msg->host);
		if (serv)
			*serv = g_strdup(msg->serv);
	}

	g_free(msg->host);
	g_free(msg->serv);
	g_free(msg);

	camel_operation_end(NULL);

	return result;
}
Exemplo n.º 19
0
char *
mail_tool_do_movemail (const char *source_url, CamelException *ex)
{
#ifndef G_OS_WIN32
	char *dest_path;
	struct stat sb;
	CamelURL *uri;

	uri = camel_url_new(source_url, ex);
	if (uri == NULL)
		return NULL;

	if (strcmp(uri->protocol, "mbox") != 0) {
		/* This is really only an internal error anyway */
		camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID,
				      _("Trying to movemail a non-mbox source `%s'"),
				      source_url);
		camel_url_free(uri);
		return NULL;
	}

	/* Set up our destination. */
	dest_path = mail_tool_get_local_movemail_path ((unsigned char *)source_url, ex);
	if (dest_path == NULL)
		return NULL;

	/* Movemail from source (source_url) to dest_path */
	camel_movemail (uri->path, dest_path, ex);
	camel_url_free(uri);

	if (g_stat (dest_path, &sb) < 0 || sb.st_size == 0) {
		g_unlink (dest_path); /* Clean up the movemail.foo file. */
		g_free (dest_path);
		return NULL;
	}

	if (camel_exception_is_set (ex)) {
		g_free (dest_path);
		return NULL;
	}

	return dest_path;
#else
	/* Unclear yet whether camel-movemail etc makes any sense on
	 * Win32, at least it is not ported yet.
	 */
	g_warning("%s: Not implemented", __FUNCTION__);
	return NULL;
#endif
}
static CamelStream *
nntp_folder_download_message (CamelNNTPFolder *nntp_folder, const char *id, const char *msgid, CamelException *ex)
{
	CamelNNTPStore *nntp_store = (CamelNNTPStore *) ((CamelFolder *) nntp_folder)->parent_store;
	CamelStream *stream = NULL;
	int ret;
	char *line;

	ret = camel_nntp_command (nntp_store, ex, nntp_folder, &line, "article %s", id);
	if (ret == 220) {
		stream = camel_data_cache_add (nntp_store->cache, "cache", msgid, NULL);
		if (stream) {
			if (camel_stream_write_to_stream ((CamelStream *) nntp_store->stream, stream) == -1)
				goto fail;
			if (camel_stream_reset (stream) == -1)
				goto fail;
		} else {
			stream = (CamelStream *) nntp_store->stream;
			camel_object_ref (stream);
		}
	} else if (ret == 423 || ret == 430) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message %s: %s"), msgid, line);
	} else if (ret != -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), msgid, line);
	}

	return stream;

 fail:
	if (errno == EINTR)
		camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled"));
	else
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), msgid, g_strerror (errno));

	return NULL;
}
Exemplo n.º 21
0
static CamelNNTPGroupList *
camel_nntp_get_grouplist_from_server (CamelNNTPStore *store, CamelException *ex)
{
	int status;
	gboolean done = FALSE;
	CamelNNTPGroupList *list;

	CAMEL_NNTP_STORE_LOCK(store);
	status = camel_nntp_command (store, ex, NULL, &line, "LIST");

	if (status != NNTP_LIST_FOLLOWS) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Could not get group list from server."));
		return NULL;
	}

	list = g_new0 (CamelNNTPGroupList, 1);
	list->time = time (NULL);

	while (!done) {
		char *line;

		if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0) {
			list->group_list = g_list_reverse(list->group_list);
			return list;
		}

		if (*line == '.') {
			done = TRUE;
		}
		else {
			CamelNNTPGroupListEntry *entry = g_new (CamelNNTPGroupListEntry, 1);
			char **split_line = g_strsplit (line, " ", 4);

			entry->group_name = g_strdup (split_line[0]);
			entry->high = atoi (split_line[1]);
			entry->low = atoi (split_line[2]);

			g_strfreev (split_line);

			list->group_list = g_list_prepend (list->group_list, entry);
		}
	}
	CAMEL_NNTP_STORE_UNLOCK(store);

	list->group_list = g_list_reverse(list->group_list);
	return list;
}
/**
 * camel_imap_response_extract_continuation:
 * @store: the store the response came from
 * @response: the response data returned from camel_imap_command
 * @ex: a CamelException
 *
 * This checks that @response contains a continuation response, and
 * returns just that data. If @response doesn't contain a continuation
 * response, the function will set @ex, release @store's connect_lock,
 * and return %NULL. Either way, @response will be freed.
 *
 * Return value: the desired response string, which the caller must free.
 **/
char *
camel_imap_response_extract_continuation (CamelImapStore *store,
					  CamelImapResponse *response,
					  CamelException *ex)
{
	char *status;

	if (response->status && *response->status == '+') {
		status = response->status;
		response->status = NULL;
		camel_imap_response_free (store, response);
		return status;
	}

	camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
			      _("Unexpected OK response from IMAP server: %s"),
			      response->status);
	camel_imap_response_free (store, response);
	return NULL;
}
/**
 * camel_imap_message_cache_insert:
 * @cache: the cache
 * @uid: UID of the message data to cache
 * @part_spec: the IMAP part_spec of the data
 * @data: the data
 * @len: length of @data
 *
 * Caches the provided data into @cache.
 *
 * Return value: a CamelStream containing the cached data, which the
 * caller must unref.
 **/
CamelStream *
camel_imap_message_cache_insert (CamelImapMessageCache *cache, const char *uid,
				 const char *part_spec, const char *data,
				 int len, CamelException *ex)
{
	char *path, *key;
	CamelStream *stream;

	stream = insert_setup (cache, uid, part_spec, &path, &key, ex);
	if (!stream)
		return NULL;

	if (camel_stream_write (stream, data, len) == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Failed to cache message %s: %s"),
				      uid, g_strerror (errno));
		return insert_abort (path, stream);
	}

	return insert_finish (cache, uid, path, key, stream);
}
CamelDiscoDiary *
camel_disco_diary_new (CamelDiscoStore *store, const char *filename, CamelException *ex)
{
	CamelDiscoDiary *diary;

	g_return_val_if_fail (CAMEL_IS_DISCO_STORE (store), NULL);
	g_return_val_if_fail (filename != NULL, NULL);

	diary = CAMEL_DISCO_DIARY (camel_object_new (CAMEL_DISCO_DIARY_TYPE));
	diary->store = store;

	d(printf("diary log file '%s'\n", filename));

	/* Note that the linux man page says:

	   a+     Open for reading and appending (writing at end  of  file).   The
	          file  is created if it does not exist.  The stream is positioned
		  at the end of the file.
	   However, c99 (which glibc uses?) says:
	   a+     append; open or create text file for update, writing at
	           end-of-file

	   So we must seek ourselves.
	*/

	diary->file = g_fopen (filename, "a+b");
	if (!diary->file) {
		camel_object_unref (diary);
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      "Could not open journal file: %s",
				      g_strerror (errno));
		return NULL;
	}

	fseek(diary->file, 0, SEEK_END);

	d(printf(" is at %ld\n", ftell(diary->file)));

	return diary;
}
/**
 * camel_imap_message_cache_get:
 * @cache: the cache
 * @uid: the UID of the data to get
 * @part_spec: the part_spec of the data to get
 * @ex: exception
 *
 * Return value: a CamelStream containing the cached data (which the
 * caller must unref), or %NULL if that data is not cached.
 **/
CamelStream *
camel_imap_message_cache_get (CamelImapMessageCache *cache, const char *uid,
			      const char *part_spec, CamelException *ex)
{
	CamelStream *stream;
	char *path, *key;

	if (uid[0] == 0)
		return NULL;

#ifdef G_OS_WIN32
	/* See comment in insert_setup() */
	if (!*part_spec)
		part_spec = "~";
#endif
	path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec);
	key = strrchr (path, '/') + 1;

	stream = g_hash_table_lookup (cache->parts, key);
	if (stream) {
		camel_stream_reset (CAMEL_STREAM (stream));
		camel_object_ref (CAMEL_OBJECT (stream));
		g_free (path);
		return stream;
	}

	stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0);
	if (stream) {
		cache_put (cache, uid, key, stream);
	} else {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Failed to cache %s: %s"),
				      part_spec, g_strerror (errno));
	}

	g_free (path);

	return stream;
}
/**
 * camel_imap_message_cache_insert_wrapper:
 * @cache: the cache
 * @uid: UID of the message data to cache
 * @part_spec: the IMAP part_spec of the data
 * @wrapper: the wrapper to cache
 *
 * Caches the provided data into @cache.
 **/
void
camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache,
					 const char *uid, const char *part_spec,
					 CamelDataWrapper *wrapper, CamelException *ex)
{
	char *path, *key;
	CamelStream *stream;

	stream = insert_setup (cache, uid, part_spec, &path, &key, ex);
	if (!stream)
		return;

	if (camel_data_wrapper_write_to_stream (wrapper, stream) == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Failed to cache message %s: %s"),
				      uid, g_strerror (errno));
		insert_abort (path, stream);
	} else {
		insert_finish (cache, uid, path, key, stream);
		camel_object_unref (CAMEL_OBJECT (stream));
	}
}
static CamelFolder *
groupwise_get_folder_from_disk (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex)
{
	CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (store);
	CamelGroupwiseStorePrivate *priv = gw_store->priv;
	CamelFolder *folder;
	char *folder_dir, *storage_path;

	storage_path = g_strdup_printf("%s/folders", priv->storage_path);
	folder_dir = e_path_to_physical (storage_path, folder_name);
	g_free(storage_path);
	if (!folder_dir || g_access (folder_dir, F_OK) != 0) {
		g_free (folder_dir);
		camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
				_("No such folder %s"), folder_name);
		return NULL;
	}

	folder = camel_gw_folder_new (store, folder_name, folder_dir, ex);
	g_free (folder_dir);

	return folder;
}
Exemplo n.º 28
0
static int
spool_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex)
{
	int retry = 0;
	CamelMboxFolder *mf = (CamelMboxFolder *)lf;
	CamelSpoolFolder *sf = (CamelSpoolFolder *)lf;

	mf->lockfd = open(lf->folder_path, O_RDWR, 0);
	if (mf->lockfd == -1) {
		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
				      _("Cannot create folder lock on %s: %s"),
				      lf->folder_path, g_strerror (errno));
		return -1;
	}

	while (retry < CAMEL_LOCK_RETRY) {
		if (retry > 0)
			sleep(CAMEL_LOCK_DELAY);

		camel_exception_clear(ex);

		if (camel_lock_fcntl(mf->lockfd, type, ex) == 0) {
			if (camel_lock_flock(mf->lockfd, type, ex) == 0) {
				if ((sf->lockid = camel_lock_helper_lock(lf->folder_path, ex)) != -1)
					return 0;
				camel_unlock_flock(mf->lockfd);
			}
			camel_unlock_fcntl(mf->lockfd);
		}
		retry++;
	}

	close (mf->lockfd);
	mf->lockfd = -1;

	return -1;
}
Exemplo n.º 29
0
static CamelCipherValidity *
sm_decrypt(CamelCipherContext *context, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex)
{
	NSSCMSDecoderContext *dec;
	NSSCMSMessage *cmsg;
	CamelStreamMem *istream;
	CamelStream *ostream;
	CamelCipherValidity *valid = NULL;

	/* FIXME: This assumes the content is only encrypted.  Perhaps its ok for
	   this api to do this ... */

	ostream = camel_stream_mem_new();
	camel_stream_mem_set_secure((CamelStreamMem *)ostream);

	/* FIXME: stream this to the decoder incrementally */
	istream = (CamelStreamMem *)camel_stream_mem_new();
	camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)ipart), (CamelStream *)istream);
	camel_stream_reset((CamelStream *)istream);

	dec = NSS_CMSDecoder_Start(NULL,
				   sm_write_stream, ostream, /* content callback     */
				   NULL, NULL,
				   NULL, NULL); /* decrypt key callback */

	if (NSS_CMSDecoder_Update(dec, (char *) istream->buffer->data, istream->buffer->len) != SECSuccess) {
		printf("decoder update failed\n");
	}
	camel_object_unref(istream);

	cmsg = NSS_CMSDecoder_Finish(dec);
	if (cmsg == NULL) {
		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Decoder failed, error %d"), PORT_GetError());
		goto fail;
	}

#if 0
	/* not sure if we really care about this? */
	if (!NSS_CMSMessage_IsEncrypted(cmsg)) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("S/MIME Decrypt: No encrypted content found"));
		NSS_CMSMessage_Destroy(cmsg);
		goto fail;
	}
#endif

	camel_stream_reset(ostream);
	camel_data_wrapper_construct_from_stream((CamelDataWrapper *)opart, ostream);

	if (NSS_CMSMessage_IsSigned(cmsg)) {
		valid = sm_verify_cmsg(context, cmsg, NULL, ex);
	} else {
		valid = camel_cipher_validity_new();
		valid->encrypt.description = g_strdup(_("Encrypted content"));
		valid->encrypt.status = CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED;
	}

	NSS_CMSMessage_Destroy(cmsg);
fail:
	camel_object_unref(ostream);

	return valid;
}
Exemplo n.º 30
0
static int
sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipients, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex)
{
	struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv;
	/*NSSCMSRecipientInfo **recipient_infos;*/
	CERTCertificate **recipient_certs = NULL;
	NSSCMSContentInfo *cinfo;
	PK11SymKey *bulkkey = NULL;
	SECOidTag bulkalgtag;
	int bulkkeysize, i;
	CK_MECHANISM_TYPE type;
	PK11SlotInfo *slot;
	PLArenaPool *poolp;
	NSSCMSMessage *cmsg = NULL;
	NSSCMSEnvelopedData *envd;
 	NSSCMSEncoderContext *enc = NULL;
	CamelStreamMem *mem;
	CamelStream *ostream = NULL;
	CamelDataWrapper *dw;
	CamelContentType *ct;

	poolp = PORT_NewArena(1024);
	if (poolp == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
		return -1;
	}

	/* Lookup all recipients certs, for later working */
	recipient_certs = (CERTCertificate **)PORT_ArenaZAlloc(poolp, sizeof(*recipient_certs[0])*(recipients->len + 1));
	if (recipient_certs == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
		goto fail;
	}

	for (i=0;i<recipients->len;i++) {
		recipient_certs[i] = CERT_FindCertByNicknameOrEmailAddr(p->certdb, recipients->pdata[i]);
		if (recipient_certs[i] == NULL) {
			camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find certificate for `%s'"), recipients->pdata[i]);
			goto fail;
		}
	}

	/* Find a common algorithm, probably 3DES anyway ... */
	if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipient_certs, &bulkalgtag, &bulkkeysize) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find common bulk encryption algorithm"));
		goto fail;
	}

	/* Generate a new bulk key based on the common algorithm - expensive */
	type = PK11_AlgtagToMechanism(bulkalgtag);
	slot = PK11_GetBestSlot(type, context);
	if (slot == NULL) {
		/* PORT_GetError(); ?? */
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot allocate slot for encryption bulk key"));
		goto fail;
	}

	bulkkey = PK11_KeyGen(slot, type, NULL, bulkkeysize/8, context);
	PK11_FreeSlot(slot);

	/* Now we can start building the message */
	/* msg->envelopedData->data */
	cmsg = NSS_CMSMessage_Create(NULL);
	if (cmsg == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Message"));
		goto fail;
	}

	envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, bulkkeysize);
	if (envd == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Enveloped data"));
		goto fail;
	}

	cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
	if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS Enveloped data"));
		goto fail;
	}

	cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
	if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS data object"));
		goto fail;
	}

	/* add recipient certs */
	for (i=0;recipient_certs[i];i++) {
		NSSCMSRecipientInfo *ri = NSS_CMSRecipientInfo_Create(cmsg, recipient_certs[i]);

		if (ri == NULL) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Recipient information"));
			goto fail;
		}

		if (NSS_CMSEnvelopedData_AddRecipient(envd, ri) != SECSuccess) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Recipient information"));
			goto fail;
		}
	}

	/* dump it out */
	ostream = camel_stream_mem_new();
	enc = NSS_CMSEncoder_Start(cmsg,
				   sm_write_stream, ostream,
				   NULL, NULL,
				   NULL, NULL,
				   sm_decrypt_key, bulkkey,
				   NULL, NULL);
	if (enc == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create encoder context"));
		goto fail;
	}

	/* FIXME: Stream the input */
	/* FIXME: Canonicalise the input? */
	mem = (CamelStreamMem *)camel_stream_mem_new();
	camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, (CamelStream *)mem);
	if (NSS_CMSEncoder_Update(enc, (char *) mem->buffer->data, mem->buffer->len) != SECSuccess) {
		NSS_CMSEncoder_Cancel(enc);
		camel_object_unref(mem);
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to encoder"));
		goto fail;
	}
	camel_object_unref(mem);

	if (NSS_CMSEncoder_Finish(enc) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encode data"));
		goto fail;
	}

	PK11_FreeSymKey(bulkkey);
	NSS_CMSMessage_Destroy(cmsg);
	for (i=0;recipient_certs[i];i++)
		CERT_DestroyCertificate(recipient_certs[i]);
	PORT_FreeArena(poolp, PR_FALSE);

	dw = camel_data_wrapper_new();
	camel_data_wrapper_construct_from_stream(dw, ostream);
	camel_object_unref(ostream);
	dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY;

	ct = camel_content_type_new("application", "x-pkcs7-mime");
	camel_content_type_set_param(ct, "name", "smime.p7m");
	camel_content_type_set_param(ct, "smime-type", "enveloped-data");
	camel_data_wrapper_set_mime_type_field(dw, ct);
	camel_content_type_unref(ct);

	camel_medium_set_content_object((CamelMedium *)opart, dw);
	camel_object_unref(dw);

	camel_mime_part_set_disposition(opart, "attachment");
	camel_mime_part_set_filename(opart, "smime.p7m");
	camel_mime_part_set_description(opart, "S/MIME Encrypted Message");
	camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64);

	return 0;

fail:
	if (ostream)
		camel_object_unref(ostream);
	if (cmsg)
		NSS_CMSMessage_Destroy(cmsg);
	if (bulkkey)
		PK11_FreeSymKey(bulkkey);

	if (recipient_certs) {
		for (i=0;recipient_certs[i];i++)
			CERT_DestroyCertificate(recipient_certs[i]);
	}

	PORT_FreeArena(poolp, PR_FALSE);

	return -1;
}