register const unsigned char *inptr;
const unsigned char *inend;
int sign = 1, val = 0;
-
+
inptr = in;
inend = in + inlen;
-
+
if (*inptr == '-') {
sign = -1;
inptr++;
} else if (*inptr == '+')
inptr++;
-
+
for ( ; inptr < inend; inptr++) {
if (!isdigit ((int) *inptr))
return -1;
else
val = (val * 10) + (*inptr - '0');
}
-
+
val *= sign;
-
+
return val;
}
get_mday (const unsigned char *in, unsigned int inlen)
{
int mday;
-
+
mday = decode_int (in, inlen);
-
+
if (mday < 0 || mday > 31)
mday = -1;
-
+
return mday;
}
get_year (const unsigned char *in, unsigned int inlen)
{
int year;
-
+
year = decode_int (in, inlen);
if (year == -1)
return -1;
-
+
if (year < 100)
year += (year < 70) ? 2000 : 1900;
-
+
if (year < 1969)
return -1;
-
+
return year;
}
register const unsigned char *inptr;
const unsigned char *inend;
int *val, colons = 0;
-
+
*hour = *min = *sec = 0;
-
+
inend = in + inlen;
val = hour;
for (inptr = in; inptr < inend; inptr++) {
else
*val = (*val * 10) + (*inptr - '0');
}
-
+
return TRUE;
}
const unsigned char *inptr, *inend;
unsigned int inlen;
int i, t;
-
+
for (i = 0; *token && i < 2; *token = (*token)->next, i++) {
inptr = (*token)->start;
inlen = (*token)->len;
inend = inptr + inlen;
-
+
if (*inptr == '+' || *inptr == '-') {
t = decode_int (inptr, inlen);
if (t < -1200 || t > 1400)
return -1;
-
+
return t;
} else {
if (*inptr == '(') {
struct _date_token *token;
struct tm tm;
time_t time;
-
+
memset ((void *) &tm, 0, sizeof (struct tm));
got_wday = got_month = got_tzone = FALSE;
offset = 0;
-
+
token = tokens;
while (token) {
if (is_weekday (token) && !got_wday) {
goto next_token;
}
}
-
+
if (is_month (token) && !got_month) {
if ((n = get_month (token->start, token->len)) != -1) {
d(printf ("month; "));
goto next_token;
}
}
-
+
if (is_time (token) && !tm.tm_hour && !tm.tm_min && !tm.tm_sec) {
if (get_time (token->start, token->len, &hour, &min, &sec)) {
d(printf ("time; "));
goto next_token;
}
}
-
+
if (is_tzone (token) && !got_tzone) {
struct _date_token *t = token;
-
+
if ((n = get_tzone (&t)) != -1) {
d(printf ("tzone; "));
got_tzone = TRUE;
goto next_token;
}
}
-
+
if (is_numeric (token)) {
if (token->len == 4 && !tm.tm_year) {
if ((n = get_year (token->start, token->len)) != -1) {
}
}
}
-
+
d(printf ("???; "));
-
+
next_token:
-
+
token = token->next;
}
-
+
d(printf ("\n"));
-
+
time = e_mktime_utc (&tm);
-
+
/* time is now GMT of the time we want, but not offset by the timezone ... */
-
+
/* this should convert the time to the GMT equiv time */
time -= ((offset / 100) * 60 * 60) + (offset % 100) * 60;
-
+
if (tzone)
*tzone = offset;
-
+
return time;
}
{
struct _date_token *token, *tokens;
time_t date;
-
+
tokens = datetok (datestr);
-
+
date = decode_broken_date (tokens, saveoffset);
-
+
/* cleanup */
while (tokens) {
token = tokens;
tokens = tokens->next;
g_free (token);
}
-
+
return date;
}
table_init ()
{
int i;
-
+
memset (datetok_table, 0, sizeof (datetok_table));
-
+
for (i = 0; i < 256; i++) {
if (!strchr (NUMERIC_CHARS, i))
datetok_table[i] |= DATE_TOKEN_NON_NUMERIC;
-
+
if (!strchr (WEEKDAY_CHARS, i))
datetok_table[i] |= DATE_TOKEN_NON_WEEKDAY;
-
+
if (!strchr (MONTH_CHARS, i))
datetok_table[i] |= DATE_TOKEN_NON_MONTH;
-
+
if (!strchr (TIME_CHARS, i))
datetok_table[i] |= DATE_TOKEN_NON_TIME;
-
+
if (!strchr (TIMEZONE_ALPHA_CHARS, i))
datetok_table[i] |= DATE_TOKEN_NON_TIMEZONE_ALPHA;
-
+
if (!strchr (TIMEZONE_NUMERIC_CHARS, i))
datetok_table[i] |= DATE_TOKEN_NON_TIMEZONE_NUMERIC;
-
+
if (((char) i) == ':')
datetok_table[i] |= DATE_TOKEN_HAS_COLON;
-
+
if (strchr ("+-", i))
datetok_table[i] |= DATE_TOKEN_HAS_SIGN;
}
-
+
printf ("static const unsigned int datetok_table[256] = {");
for (i = 0; i < 256; i++) {
if (i % 16 == 0)
{
time_t date;
int offset;
-
+
/*table_init ();*/
-
+
date = parse_broken_date (argv[1], &offset);
printf ("%d; %d\n", date, offset);
-
+
return 0;
}
camel_address_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (), "CamelAddress",
sizeof (CamelAddress),
(CamelObjectInitFunc) camel_address_init,
(CamelObjectFinalizeFunc) camel_address_finalize);
}
-
+
return type;
}
* camel_address_new:
*
* Create a new #CamelAddress object.
- *
+ *
* Returns a new #CamelAddress object
**/
CamelAddress *
/**
* camel_address_new_clone:
* @addr: a #CamelAddress object
- *
+ *
* Clone an existing address type.
- *
+ *
* Returns the cloned address
**/
CamelAddress *
/**
* camel_address_length:
* @addr: a #CamelAddress object
- *
+ *
* Get the number of addresses stored in the address @addr.
- *
+ *
* Returns the number of addresses contained in @addr
**/
int
/**
* camel_address_encode:
* @addr: a #CamelAddress object
- *
+ *
* Encode an address in a format suitable for a raw header.
- *
+ *
* Returns the encoded address
**/
char *
* camel_address_unformat:
* @addr: a #CamelAddress object
* @raw: raw address description
- *
+ *
* Attempt to convert a previously formatted and/or edited
* address back into internal form.
- *
+ *
* Returns the number of addresses parsed or %-1 on fail
**/
int
/**
* camel_address_format:
* @addr: a #CamelAddress object
- *
+ *
* Format an address in a format suitable for display.
- *
+ *
* Returns a newly allocated string containing the formatted addresses
**/
char *
* camel_address_cat:
* @dest: destination #CamelAddress object
* @source: source #CamelAddress object
- *
+ *
* Concatenate one address onto another. The addresses must
* be of the same type.
- *
+ *
* Returns the number of addresses concatenated
**/
int
* camel_address_copy:
* @dest: destination #CamelAddress object
* @source: source #CamelAddress object
- *
+ *
* Copy the contents of one address into another.
- *
+ *
* Returns the number of addresses copied
**/
int
* camel_address_remove:
* @addr: a #CamelAddress object
* @index: The address to remove, use %-1 to remove all address.
- *
+ *
* Remove an address by index, or all addresses.
**/
void
struct _CamelBlockFilePrivate *prev;
struct _CamelBlockFile *base;
-
+
pthread_mutex_t root_lock; /* for modifying the root block */
pthread_mutex_t cache_lock; /* for refcounting, flag manip, cache manip */
pthread_mutex_t io_lock; /* for all io ops */
-
+
unsigned int deleted:1;
};
CamelBlockRoot *br;
struct stat st;
int retval;
-
+
br = bs->root;
-
+
retval = fstat (bs->fd, &st);
-
+
d(printf("Validate root: '%s'\n", bs->path));
d(printf("version: %.8s (%.8s)\n", bs->root->version, bs->version));
d(printf("block size: %d (%d)%s\n", br->block_size, bs->block_size,
p = bs->priv = g_malloc0(sizeof(*bs->priv));
p->base = bs;
-
+
pthread_mutex_init(&p->root_lock, NULL);
pthread_mutex_init(&p->cache_lock, NULL);
pthread_mutex_init(&p->io_lock, NULL);
-
+
/* link into lru list */
LOCK(block_file_lock);
e_dlist_addhead(&block_file_list, (EDListNode *)p);
bl = bn;
bn = bn->next;
}
-
+
g_hash_table_destroy (bs->blocks);
-
+
if (bs->root_block)
camel_block_file_unref_block(bs, bs->root_block);
g_free(bs->path);
if (bs->fd != -1)
close(bs->fd);
-
+
pthread_mutex_destroy(&p->io_lock);
pthread_mutex_destroy(&p->cache_lock);
pthread_mutex_destroy(&p->root_lock);
-
+
g_free(p);
}
camel_block_file_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelBlockFile",
sizeof (CamelBlockFile),
(CamelObjectInitFunc) camel_block_file_init,
(CamelObjectFinalizeFunc) camel_block_file_finalise);
}
-
+
return type;
}
/**
* camel_block_file_new:
- * @path:
- * @:
- * @block_size:
- *
+ * @path:
+ * @:
+ * @block_size:
+ *
* Allocate a new block file, stored at @path. @version contains an 8 character
* version string which must match the head of the file, or the file will be
* intitialised.
- *
+ *
* @block_size is currently ignored and is set to CAMEL_BLOCK_SIZE.
*
* Return value: The new block file, or NULL if it could not be created.
CAMEL_BLOCK_FILE_UNLOCK(bs, io_lock);
return ret;
-
+
}
/**
* camel_block_file_new_block:
- * @bs:
- *
+ * @bs:
+ *
* Allocate a new block, return a pointer to it. Old blocks
* may be flushed to disk during this call.
- *
+ *
* Return value: The block, or NULL if an error occured.
**/
CamelBlock *camel_block_file_new_block(CamelBlockFile *bs)
/**
* camel_block_file_free_block:
- * @bs:
- * @id:
- *
- *
+ * @bs:
+ * @id:
+ *
+ *
**/
int camel_block_file_free_block(CamelBlockFile *bs, camel_block_t id)
{
/**
* camel_block_file_get_block:
- * @bs:
- * @id:
- *
+ * @bs:
+ * @id:
+ *
* Retreive a block @id.
- *
+ *
* Return value: The block, or NULL if blockid is invalid or a file error
* occured.
**/
/**
* camel_block_file_detach_block:
- * @bs:
- * @bl:
- *
+ * @bs:
+ * @bl:
+ *
* Detatch a block from the block file's cache. The block should
* be unref'd or attached when finished with. The block file will
* perform no writes of this block or flushing of it if the cache
/**
* camel_block_file_attach_block:
- * @bs:
- * @bl:
- *
+ * @bs:
+ * @bl:
+ *
* Reattach a block that has been detached.
**/
void camel_block_file_attach_block(CamelBlockFile *bs, CamelBlock *bl)
/**
* camel_block_file_touch_block:
- * @bs:
- * @bl:
- *
+ * @bs:
+ * @bl:
+ *
* Mark a block as dirty. The block will be written to disk if
* it ever expires from the cache.
**/
/**
* camel_block_file_unref_block:
- * @bs:
- * @bl:
- *
+ * @bs:
+ * @bl:
+ *
* Mark a block as unused. If a block is used it will not be
* written to disk, or flushed from memory.
*
/**
* camel_block_file_sync_block:
- * @bs:
- * @bl:
- *
+ * @bs:
+ * @bl:
+ *
* Flush a block to disk immediately. The block will only
* be flushed to disk if it is marked as dirty (touched).
- *
+ *
* Return value: -1 on io error.
**/
int camel_block_file_sync_block(CamelBlockFile *bs, CamelBlock *bl)
/**
* camel_block_file_sync:
- * @bs:
- *
+ * @bs:
+ *
* Sync all dirty blocks to disk, including the root block.
- *
+ *
* Return value: -1 on io error.
**/
int camel_block_file_sync(CamelBlockFile *bs)
p = bs->priv = g_malloc0(sizeof(*bs->priv));
p->base = bs;
-
+
pthread_mutex_init(&p->lock, NULL);
-
+
LOCK(key_file_lock);
e_dlist_addhead(&key_file_list, (EDListNode *)p);
UNLOCK(key_file_lock);
UNLOCK(key_file_lock);
g_free(bs->path);
-
+
pthread_mutex_destroy(&p->lock);
-
+
g_free(p);
}
camel_key_file_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelKeyFile",
sizeof (CamelKeyFile),
(CamelObjectInitFunc) camel_key_file_init,
(CamelObjectFinalizeFunc) camel_key_file_finalise);
}
-
+
return type;
}
/**
* camel_key_file_new:
- * @path:
+ * @path:
* @flags: open flags
* @version: Version string (header) of file. Currently
* written but not checked.
- *
+ *
* Create a new key file. A linked list of record blocks.
- *
+ *
* Return value: A new key file, or NULL if the file could not
* be opened/created/initialised.
**/
CAMEL_KEY_FILE_UNLOCK(kf, lock);
return ret;
-
+
}
/**
* camel_key_file_write:
- * @kf:
- * @parent:
- * @len:
- * @records:
- *
+ * @kf:
+ * @parent:
+ * @len:
+ * @records:
+ *
* Write a new list of records to the key file.
- *
+ *
* Return value: -1 on io error. The key file will remain unchanged.
**/
int
/**
* camel_key_file_read:
- * @kf:
+ * @kf:
* @start: The record pointer. This will be set to the next record pointer on success.
* @len: Number of records read, if != NULL.
* @records: Records, allocated, must be freed with g_free, if != NULL.
- *
+ *
* Read the next block of data from the key file. Returns the number of
* records.
- *
+ *
* Return value: -1 on io error.
**/
int
camel_certdb_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (),
"CamelCertDB",
(CamelObjectInitFunc) camel_certdb_init,
(CamelObjectFinalizeFunc) camel_certdb_finalize);
}
-
+
return type;
}
camel_certdb_class_init (CamelCertDBClass *klass)
{
parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
-
+
klass->header_load = certdb_header_load;
klass->header_save = certdb_header_save;
-
+
klass->cert_new = certdb_cert_new;
klass->cert_load = certdb_cert_load;
klass->cert_save = certdb_cert_save;
camel_certdb_init (CamelCertDB *certdb)
{
certdb->priv = g_malloc (sizeof (struct _CamelCertDBPrivate));
-
+
certdb->filename = NULL;
certdb->version = CAMEL_CERTDB_VERSION;
certdb->saved_certs = 0;
-
+
certdb->cert_size = sizeof (CamelCert);
-
+
certdb->cert_chunks = NULL;
-
+
certdb->certs = g_ptr_array_new ();
certdb->cert_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
+
certdb->priv->db_lock = g_mutex_new ();
certdb->priv->io_lock = g_mutex_new ();
certdb->priv->alloc_lock = g_mutex_new ();
{
CamelCertDB *certdb = (CamelCertDB *) obj;
struct _CamelCertDBPrivate *p;
-
+
p = certdb->priv;
-
+
if (certdb->flags & CAMEL_CERTDB_DIRTY)
camel_certdb_save (certdb);
-
+
camel_certdb_clear (certdb);
g_ptr_array_free (certdb->certs, TRUE);
g_hash_table_destroy (certdb->cert_hash);
-
+
g_free (certdb->filename);
-
+
if (certdb->cert_chunks)
e_memchunk_destroy (certdb->cert_chunks);
-
+
g_mutex_free (p->db_lock);
g_mutex_free (p->io_lock);
g_mutex_free (p->alloc_lock);
g_mutex_free (p->ref_lock);
-
+
g_free (p);
}
camel_certdb_set_default (CamelCertDB *certdb)
{
pthread_mutex_lock (&default_certdb_lock);
-
+
if (default_certdb)
camel_object_unref (default_certdb);
-
+
if (certdb)
camel_object_ref (certdb);
-
+
default_certdb = certdb;
-
+
pthread_mutex_unlock (&default_certdb_lock);
}
camel_certdb_get_default (void)
{
CamelCertDB *certdb;
-
+
pthread_mutex_lock (&default_certdb_lock);
-
+
if (default_certdb)
camel_object_ref (default_certdb);
-
+
certdb = default_certdb;
-
+
pthread_mutex_unlock (&default_certdb_lock);
-
+
return certdb;
}
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
g_return_if_fail (filename != NULL);
-
+
CAMEL_CERTDB_LOCK (certdb, db_lock);
-
+
g_free (certdb->filename);
certdb->filename = g_strdup (filename);
-
+
CAMEL_CERTDB_UNLOCK (certdb, db_lock);
}
return -1;
if (camel_file_util_decode_uint32 (istream, &certdb->saved_certs) == -1)
return -1;
-
+
return 0;
}
certdb_cert_load (CamelCertDB *certdb, FILE *istream)
{
CamelCert *cert;
-
+
cert = camel_certdb_cert_new (certdb);
if (camel_file_util_decode_string (istream, &cert->issuer) == -1)
goto error;
if (camel_file_util_decode_uint32 (istream, &cert->trust) == -1)
goto error;
-
+
return cert;
-
+
error:
-
+
camel_certdb_cert_unref (certdb, cert);
-
+
return NULL;
}
CamelCert *cert;
FILE *in;
int i;
-
+
g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), -1);
g_return_val_if_fail (certdb->filename, -1);
in = g_fopen (certdb->filename, "rb");
if (in == NULL)
return -1;
-
+
CAMEL_CERTDB_LOCK (certdb, io_lock);
if (CAMEL_CERTDB_GET_CLASS (certdb)->header_load (certdb, in) == -1)
goto error;
-
+
for (i = 0; i < certdb->saved_certs; i++) {
cert = CAMEL_CERTDB_GET_CLASS (certdb)->cert_load (certdb, in);
-
+
if (cert == NULL)
goto error;
-
+
camel_certdb_add (certdb, cert);
}
-
+
CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-
+
if (fclose (in) != 0)
return -1;
-
+
certdb->flags &= ~CAMEL_CERTDB_DIRTY;
-
+
return 0;
-
+
error:
-
+
g_warning ("Cannot load certificate database: %s", strerror (ferror (in)));
-
+
CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-
+
fclose (in);
-
+
return -1;
}
return -1;
if (camel_file_util_encode_uint32 (ostream, certdb->saved_certs) == -1)
return -1;
-
+
return 0;
}
return -1;
if (camel_file_util_encode_uint32 (ostream, cert->trust) == -1)
return -1;
-
+
return 0;
}
char *filename;
int fd, i;
FILE *out;
-
+
g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), -1);
g_return_val_if_fail (certdb->filename, -1);
-
+
filename = alloca (strlen (certdb->filename) + 4);
sprintf (filename, "%s~", certdb->filename);
-
+
fd = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
if (fd == -1)
return -1;
-
+
out = fdopen (fd, "wb");
if (out == NULL) {
i = errno;
errno = i;
return -1;
}
-
+
CAMEL_CERTDB_LOCK (certdb, io_lock);
-
+
certdb->saved_certs = certdb->certs->len;
if (CAMEL_CERTDB_GET_CLASS (certdb)->header_save (certdb, out) == -1)
goto error;
-
+
for (i = 0; i < certdb->saved_certs; i++) {
cert = (CamelCert *) certdb->certs->pdata[i];
-
+
if (CAMEL_CERTDB_GET_CLASS (certdb)->cert_save (certdb, cert, out) == -1)
goto error;
}
-
+
CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-
+
if (fflush (out) != 0 || fsync (fileno (out)) == -1) {
i = errno;
fclose (out);
errno = i;
return -1;
}
-
+
if (fclose (out) != 0) {
i = errno;
g_unlink (filename);
errno = i;
return -1;
}
-
+
if (g_rename (filename, certdb->filename) == -1) {
i = errno;
g_unlink (filename);
errno = i;
return -1;
}
-
+
certdb->flags &= ~CAMEL_CERTDB_DIRTY;
-
+
return 0;
-
+
error:
-
+
g_warning ("Cannot save certificate database: %s", strerror (ferror (out)));
-
+
CAMEL_CERTDB_UNLOCK (certdb, io_lock);
-
+
i = errno;
fclose (out);
g_unlink (filename);
errno = i;
-
+
return -1;
}
camel_certdb_touch (CamelCertDB *certdb)
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-
+
certdb->flags |= CAMEL_CERTDB_DIRTY;
}
camel_certdb_get_cert (CamelCertDB *certdb, const char *fingerprint)
{
CamelCert *cert;
-
+
g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
-
+
CAMEL_CERTDB_LOCK (certdb, db_lock);
-
+
cert = g_hash_table_lookup (certdb->cert_hash, fingerprint);
if (cert)
camel_certdb_cert_ref (certdb, cert);
-
+
CAMEL_CERTDB_UNLOCK (certdb, db_lock);
-
+
return cert;
}
camel_certdb_add (CamelCertDB *certdb, CamelCert *cert)
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-
+
CAMEL_CERTDB_LOCK (certdb, db_lock);
-
+
if (g_hash_table_lookup (certdb->cert_hash, cert->fingerprint)) {
CAMEL_CERTDB_UNLOCK (certdb, db_lock);
return;
}
-
+
camel_certdb_cert_ref (certdb, cert);
g_ptr_array_add (certdb->certs, cert);
g_hash_table_insert (certdb->cert_hash, cert->fingerprint, cert);
-
+
certdb->flags |= CAMEL_CERTDB_DIRTY;
-
+
CAMEL_CERTDB_UNLOCK (certdb, db_lock);
}
camel_certdb_remove (CamelCertDB *certdb, CamelCert *cert)
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-
+
CAMEL_CERTDB_LOCK (certdb, db_lock);
-
+
if (g_hash_table_lookup (certdb->cert_hash, cert->fingerprint)) {
g_hash_table_remove (certdb->cert_hash, cert->fingerprint);
g_ptr_array_remove (certdb->certs, cert);
camel_certdb_cert_unref (certdb, cert);
-
+
certdb->flags |= CAMEL_CERTDB_DIRTY;
}
-
+
CAMEL_CERTDB_UNLOCK (certdb, db_lock);
}
certdb_cert_new (CamelCertDB *certdb)
{
CamelCert *cert;
-
+
if (certdb->cert_chunks)
cert = e_memchunk_alloc0 (certdb->cert_chunks);
else
cert = g_malloc0 (certdb->cert_size);
-
+
cert->refcount = 1;
-
+
return cert;
}
camel_certdb_cert_new (CamelCertDB *certdb)
{
CamelCert *cert;
-
+
g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
-
+
CAMEL_CERTDB_LOCK (certdb, alloc_lock);
-
+
cert = CAMEL_CERTDB_GET_CLASS (certdb)->cert_new (certdb);
-
+
CAMEL_CERTDB_UNLOCK (certdb, alloc_lock);
-
+
return cert;
}
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
g_return_if_fail (cert != NULL);
-
+
CAMEL_CERTDB_LOCK (certdb, ref_lock);
cert->refcount++;
CAMEL_CERTDB_UNLOCK (certdb, ref_lock);
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
g_return_if_fail (cert != NULL);
-
+
CAMEL_CERTDB_LOCK (certdb, ref_lock);
-
+
if (cert->refcount <= 1) {
CAMEL_CERTDB_GET_CLASS (certdb)->cert_free (certdb, cert);
if (certdb->cert_chunks)
} else {
cert->refcount--;
}
-
+
CAMEL_CERTDB_UNLOCK (certdb, ref_lock);
}
{
CamelCert *cert;
int i;
-
+
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
-
+
CAMEL_CERTDB_LOCK (certdb, db_lock);
-
+
g_hash_table_foreach_remove (certdb->cert_hash, cert_remove, NULL);
for (i = 0; i < certdb->certs->len; i++) {
cert = (CamelCert *) certdb->certs->pdata[i];
camel_certdb_cert_unref (certdb, cert);
}
-
+
certdb->saved_certs = 0;
g_ptr_array_set_size (certdb->certs, 0);
certdb->flags |= CAMEL_CERTDB_DIRTY;
-
+
CAMEL_CERTDB_UNLOCK (certdb, db_lock);
}
{
g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
g_return_val_if_fail (cert != NULL, NULL);
-
+
/* FIXME: do locking? */
-
+
return CAMEL_CERTDB_GET_CLASS (certdb)->cert_get_string (certdb, cert, string);
}
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
g_return_if_fail (cert != NULL);
-
+
/* FIXME: do locking? */
-
+
CAMEL_CERTDB_GET_CLASS (certdb)->cert_set_string (certdb, cert, string, value);
}
{
g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), CAMEL_CERT_TRUST_UNKNOWN);
g_return_val_if_fail (cert != NULL, CAMEL_CERT_TRUST_UNKNOWN);
-
+
return cert->trust;
}
{
g_return_if_fail (CAMEL_IS_CERTDB (certdb));
g_return_if_fail (cert != NULL);
-
+
cert->trust = trust;
}
typedef struct {
guint32 refcount;
-
+
char *issuer;
char *subject;
char *hostname;
char *fingerprint;
-
+
CamelCertTrust trust;
GByteArray *rawcert;
} CamelCert;
struct _CamelCertDB {
CamelObject parent_object;
struct _CamelCertDBPrivate *priv;
-
+
char *filename;
guint32 version;
guint32 saved_certs;
guint32 flags;
-
+
guint32 cert_size;
-
+
struct _EMemChunk *cert_chunks;
-
+
GPtrArray *certs;
GHashTable *cert_hash;
};
struct _CamelCertDBClass {
CamelObjectClass parent_class;
-
+
int (*header_load) (CamelCertDB *certdb, FILE *istream);
int (*header_save) (CamelCertDB *certdb, FILE *ostream);
-
+
CamelCert * (*cert_load) (CamelCertDB *certdb, FILE *istream);
int (*cert_save) (CamelCertDB *certdb, CamelCert *cert, FILE *ostream);
-
+
CamelCert * (*cert_new) (CamelCertDB *certdb);
void (*cert_free) (CamelCertDB *certdb, CamelCert *cert);
-
+
const char * (*cert_get_string) (CamelCertDB *certdb, CamelCert *cert, int string);
void (*cert_set_string) (CamelCertDB *certdb, CamelCert *cert, int string, const char *value);
};
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */
-/*
+/*
* Authors:
* Michael Zucchi <notzed@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 2000-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
register unsigned int mask;
register int level;
register guint32 c;
-
+
mask = cc->mask;
level = cc->level;
-
+
/* check what charset a given string will fit in */
while ((c = camel_utf8_getc_limit(&inptr, inend)) != 0xffff) {
if (c < 0xffff) {
mask &= charset_mask(c);
-
+
if (c>=128 && c<256)
level = MAX(level, 1);
else if (c>=256)
break;
}
}
-
+
cc->mask = mask;
cc->level = level;
}
{
const char *locale_lang, *lang;
int i;
-
+
locale_lang = e_iconv_locale_language ();
for (i = 0; i < G_N_ELEMENTS (camel_charinfo); i++) {
if (camel_charinfo[i].bit & mask) {
lang = e_iconv_charset_language (camel_charinfo[i].name);
-
+
if (!locale_lang || (lang && !strncmp (locale_lang, lang, 2)))
return camel_charinfo[i].name;
}
}
-
+
return "UTF-8";
}
* iso-8859-13 are Baltic that it also maps to
* windows-cp1257.
*/
-
+
if (!g_ascii_strcasecmp (isocharset, "iso-8859-1") || !g_ascii_strcasecmp (isocharset, "us-ascii"))
return "windows-cp1252";
else if (!g_ascii_strcasecmp (isocharset, "iso-8859-2"))
return "windows-cp1254";
else if (!g_ascii_strcasecmp (isocharset, "iso-8859-13"))
return "windows-cp1257";
-
+
return isocharset;
}
camel_cipher_context_new (CamelSession *session)
{
CamelCipherContext *context;
-
+
g_return_val_if_fail (session != NULL, NULL);
-
+
context = CAMEL_CIPHER_CONTEXT (camel_object_new (CAMEL_CIPHER_CONTEXT_TYPE));
-
+
camel_object_ref (session);
context->session = session;
-
+
return context;
}
{
g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
g_return_if_fail (CAMEL_IS_SESSION (session));
-
+
camel_object_ref (session);
context->session = session;
}
struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
{
int retval;
-
+
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
camel_operation_start(NULL, _("Signing message"));
CIPHER_LOCK(context);
-
+
retval = CCC_CLASS (context)->sign (context, userid, hash, ipart, opart, ex);
-
+
CIPHER_UNLOCK(context);
camel_operation_end(NULL);
camel_cipher_verify (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex)
{
CamelCipherValidity *valid;
-
+
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
-
+
camel_operation_start(NULL, _("Verifying message"));
CIPHER_LOCK(context);
-
+
valid = CCC_CLASS (context)->verify (context, ipart, ex);
-
+
CIPHER_UNLOCK(context);
camel_operation_end(NULL);
-
+
return valid;
}
struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex)
{
int retval;
-
+
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
camel_operation_start(NULL, _("Encrypting message"));
-
+
CIPHER_LOCK(context);
-
+
retval = CCC_CLASS (context)->encrypt (context, userid, recipients, ipart, opart, ex);
-
+
CIPHER_UNLOCK(context);
camel_operation_end(NULL);
-
+
return retval;
}
/**
* camel_cipher_decrypt:
- * @context:
- * @ipart:
- * @opart:
- * @ex:
- *
+ * @context:
+ * @ipart:
+ * @opart:
+ * @ex:
+ *
* Decrypts @ipart into @opart.
- *
+ *
* Return value: A validity/encryption status.
**/
CamelCipherValidity *
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
camel_operation_start(NULL, _("Decrypting message"));
-
+
CIPHER_LOCK(context);
-
+
valid = CCC_CLASS (context)->decrypt (context, ipart, opart, ex);
-
+
CIPHER_UNLOCK(context);
camel_operation_end(NULL);
-
+
return valid;
}
{
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("You may not import keys with this cipher"));
-
+
return -1;
}
{
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
g_return_val_if_fail (CAMEL_IS_STREAM (istream), -1);
-
+
return CCC_CLASS (context)->import_keys (context, istream, ex);
}
{
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("You may not export keys with this cipher"));
-
+
return -1;
}
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
g_return_val_if_fail (CAMEL_IS_STREAM (ostream), -1);
g_return_val_if_fail (keys != NULL, -1);
-
+
return CCC_CLASS (context)->export_keys (context, keys, ostream, ex);
}
camel_cipher_id_to_hash(CamelCipherContext *context, const char *id)
{
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), CAMEL_CIPHER_HASH_DEFAULT);
-
+
return CCC_CLASS (context)->id_to_hash (context, id);
}
camel_cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash)
{
g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
-
+
return CCC_CLASS (context)->hash_to_id (context, hash);
}
camel_cipher_validity_new (void)
{
CamelCipherValidity *validity;
-
+
validity = g_malloc(sizeof(*validity));
camel_cipher_validity_init(validity);
camel_cipher_validity_set_valid (CamelCipherValidity *validity, gboolean valid)
{
g_assert (validity != NULL);
-
+
validity->sign.status = valid?CAMEL_CIPHER_VALIDITY_SIGN_GOOD:CAMEL_CIPHER_VALIDITY_SIGN_BAD;
}
{
if (validity == NULL)
return NULL;
-
+
return validity->sign.description;
}
camel_cipher_validity_set_description (CamelCipherValidity *validity, const gchar *description)
{
g_assert (validity != NULL);
-
+
g_free(validity->sign.description);
validity->sign.description = g_strdup(description);
}
/**
* camel_cipher_validity_add_certinfo:
- * @vin:
- * @mode:
- * @name:
- * @email:
- *
+ * @vin:
+ * @mode:
+ * @name:
+ * @email:
+ *
* Add a cert info to the signer or encrypter info.
**/
void
* camel_cipher_validity_envelope:
* @parent:
* @valid:
- *
+ *
* Calculate a conglomerate validity based on wrapping one secure part inside
* another one.
**/
camel_cipher_context_finalise (CamelObject *o)
{
CamelCipherContext *context = (CamelCipherContext *)o;
-
+
camel_object_unref (CAMEL_OBJECT (context->session));
-
+
g_mutex_free (context->priv->lock);
-
+
g_free (context->priv);
}
camel_cipher_context_class_init (CamelCipherContextClass *camel_cipher_context_class)
{
parent_class = camel_type_get_global_classfuncs (camel_object_get_type ());
-
+
camel_cipher_context_class->hash_to_id = cipher_hash_to_id;
camel_cipher_context_class->id_to_hash = cipher_id_to_hash;
camel_cipher_context_class->sign = cipher_sign;
camel_cipher_context_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (),
"CamelCipherContext",
(CamelObjectInitFunc) camel_cipher_context_init,
(CamelObjectFinalizeFunc) camel_cipher_context_finalise);
}
-
+
return type;
}
CamelDataWrapper *dw;
CamelTransferEncoding encoding;
int parts, i;
-
+
dw = camel_medium_get_content_object((CamelMedium *)part);
if (!dw)
return;
-
+
if (CAMEL_IS_MULTIPART (dw)) {
parts = camel_multipart_get_number((CamelMultipart *)dw);
for (i = 0; i < parts; i++)
* @part: Part to write.
* @flags: flags for the canonicalisation filter (CamelMimeFilterCanon)
* @ostream: stream to write canonicalised output to.
- *
+ *
* Writes a part to a stream in a canonicalised format, suitable for signing/encrypting.
*
* The transfer encoding paramaters for the part may be changed by this function.
- *
+ *
* Return value: -1 on error;
**/
int
typedef struct _CamelCipherContext {
CamelObject parent_object;
-
+
struct _CamelCipherContextPrivate *priv;
-
+
CamelSession *session;
-
+
/* these MUST be set by implementors */
const char *sign_protocol;
const char *encrypt_protocol;
typedef struct _CamelCipherContextClass {
CamelObjectClass parent_class;
-
+
CamelCipherHash (*id_to_hash)(CamelCipherContext *context, const char *id);
const char * (*hash_to_id)(CamelCipherContext *context, CamelCipherHash hash);
-
+
int (*sign) (CamelCipherContext *context, const char *userid, CamelCipherHash hash,
struct _CamelMimePart *ipart, struct _CamelMimePart *opart, CamelException *ex);
-
+
CamelCipherValidity * (*verify) (CamelCipherContext *context, struct _CamelMimePart *ipart, CamelException *ex);
-
+
int (*encrypt) (CamelCipherContext *context, const char *userid,
GPtrArray *recipients, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
CamelException *ex);
-
+
CamelCipherValidity *(*decrypt) (CamelCipherContext *context, struct _CamelMimePart *ipart, struct _CamelMimePart *opart,
CamelException *ex);
-
+
int (*import_keys) (CamelCipherContext *context, struct _CamelStream *istream,
CamelException *ex);
-
+
int (*export_keys) (CamelCipherContext *context, GPtrArray *keys,
struct _CamelStream *ostream, CamelException *ex);
} CamelCipherContextClass;
*
* Copyright (C) 2001 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
p = cdc->priv;
camel_object_bag_destroy(p->busy_bag);
g_free(p);
-
+
g_free (cdc->path);
}
camel_data_cache_get_type(void)
{
static CamelType camel_data_cache_type = CAMEL_INVALID_TYPE;
-
+
if (camel_data_cache_type == CAMEL_INVALID_TYPE) {
camel_data_cache_type = camel_type_register(
CAMEL_OBJECT_TYPE, "CamelDataCache",
* camel_data_cache_new:
* @path: Base path of cache, subdirectories will be created here.
* @flags: Open flags, none defined.
- * @ex:
- *
+ * @ex:
+ *
* Create a new data cache.
- *
+ *
* Return value: A new cache object, or NULL if the base path cannot
* be written to.
**/
* camel_data_cache_set_expire_age:
* @cdc: A #CamelDataCache
* @when: Timeout for age expiry, or -1 to disable.
- *
+ *
* Set the cache expiration policy for aged entries.
- *
+ *
* Items in the cache older than @when seconds may be
* flushed at any time. Items are expired in a lazy
* manner, so it is indeterminate when the items will
* camel_data_cache_set_expire_access:
* @cdc: A #CamelDataCache
* @when: Timeout for access, or -1 to disable access expiry.
- *
+ *
* Set the cache expiration policy for access times.
*
* Items in the cache which haven't been accessed for @when
while ( (dname = g_dir_read_name(dir)) ) {
if (strcmp(dname, keep) == 0)
continue;
-
+
g_string_printf (s, "%s/%s", path, dname);
dd(printf("Checking '%s' for expiry\n", s->str));
if (g_stat(s->str, &st) == 0
hash = (hash>>5)&CAMEL_DATA_CACHE_MASK;
dir = alloca(strlen(cdc->path) + strlen(path) + 8);
sprintf(dir, "%s/%s/%02x", cdc->path, path, hash);
-
-#ifdef G_OS_WIN32
+
+#ifdef G_OS_WIN32
if (g_access(dir, F_OK) == -1) {
#else
if (access (dir, F_OK) == -1) {
* @cdc: A #CamelDataCache
* @path: Relative path of item to add.
* @key: Key of item to add.
- * @ex:
- *
+ * @ex:
+ *
* Add a new item to the cache.
*
* The key and the path combine to form a unique key used to store
* the item.
- *
+ *
* Potentially, expiry processing will be performed while this call
* is executing.
*
* @cdc: A #CamelDataCache
* @path: Path to the (sub) cache the item exists in.
* @key: Key for the cache item.
- * @ex:
- *
+ * @ex:
+ *
* Lookup an item in the cache. If the item exists, a stream
* is returned for the item. The stream may be shared by
* multiple callers, so ensure the stream is in a valid state
* through external locking.
- *
+ *
* Return value: A cache item, or NULL if the cache item does not exist.
**/
CamelStream *
/**
* camel_data_cache_remove:
* @cdc: A #CamelDataCache
- * @path:
- * @key:
- * @ex:
- *
+ * @path:
+ * @key:
+ * @ex:
+ *
* Remove/expire a cache item.
- *
- * Return value:
+ *
+ * Return value:
**/
int
camel_data_cache_remove(CamelDataCache *cdc, const char *path, const char *key, CamelException *ex)
/**
* camel_data_cache_rename:
- * @cache:
- * @old:
- * @new:
- * @ex:
- *
+ * @cache:
+ * @old:
+ * @new:
+ * @ex:
+ *
* Rename a cache path. All cache items accessed from the old path
* are accessible using the new path.
*
* CURRENTLY UNIMPLEMENTED
- *
+ *
* Return value: -1 on error.
**/
int camel_data_cache_rename(CamelDataCache *cache,
/**
* camel_data_cache_clear:
- * @cache:
+ * @cache:
* @path: Path to clear, or NULL to clear all items in
* all paths.
- * @ex:
- *
+ * @ex:
+ *
* Clear all items in a given cache path or all items in the cache.
- *
+ *
* CURRENTLY_UNIMPLEMENTED
*
* Return value: -1 on error.
*
* Copyright (C) 2001 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_data_wrapper_init (gpointer object, gpointer klass)
{
CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
-
+
camel_data_wrapper->priv = g_malloc (sizeof (struct _CamelDataWrapperPrivate));
pthread_mutex_init (&camel_data_wrapper->priv->stream_lock, NULL);
-
+
camel_data_wrapper->mime_type = camel_content_type_new ("application", "octet-stream");
camel_data_wrapper->encoding = CAMEL_TRANSFER_ENCODING_DEFAULT;
camel_data_wrapper->offline = FALSE;
camel_data_wrapper_finalize (CamelObject *object)
{
CamelDataWrapper *camel_data_wrapper = CAMEL_DATA_WRAPPER (object);
-
+
pthread_mutex_destroy (&camel_data_wrapper->priv->stream_lock);
-
+
g_free (camel_data_wrapper->priv);
-
+
if (camel_data_wrapper->mime_type)
camel_content_type_unref (camel_data_wrapper->mime_type);
-
+
if (camel_data_wrapper->stream)
camel_object_unref (camel_data_wrapper->stream);
}
camel_data_wrapper_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_OBJECT_TYPE,
"CamelDataWrapper",
(CamelObjectInitFunc) camel_data_wrapper_init,
(CamelObjectFinalizeFunc) camel_data_wrapper_finalize);
}
-
+
return type;
}
write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
{
ssize_t ret;
-
+
if (data_wrapper->stream == NULL) {
return -1;
}
-
+
CAMEL_DATA_WRAPPER_LOCK (data_wrapper, stream_lock);
if (camel_stream_reset (data_wrapper->stream) == -1) {
CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
return -1;
}
-
+
ret = camel_stream_write_to_stream (data_wrapper->stream, stream);
-
+
CAMEL_DATA_WRAPPER_UNLOCK (data_wrapper, stream_lock);
-
+
return ret;
}
CamelMimeFilter *filter;
CamelStream *fstream;
ssize_t ret;
-
+
fstream = (CamelStream *) camel_stream_filter_new_with_stream (stream);
-
+
switch (data_wrapper->encoding) {
case CAMEL_TRANSFER_ENCODING_BASE64:
filter = (CamelMimeFilter *) camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
default:
break;
}
-
+
if (camel_content_type_is (data_wrapper->mime_type, "text", "*")) {
filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter);
camel_object_unref (filter);
}
-
+
ret = camel_data_wrapper_write_to_stream (data_wrapper, fstream);
camel_stream_flush (fstream);
camel_object_unref (fstream);
-
+
return ret;
}
{
g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-
+
return CDW_CLASS (data_wrapper)->decode_to_stream (data_wrapper, stream);
}
{
if (data_wrapper->stream)
camel_object_unref (data_wrapper->stream);
-
+
data_wrapper->stream = stream;
camel_object_ref (stream);
return 0;
{
g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-
+
return CDW_CLASS (data_wrapper)->construct_from_stream (data_wrapper, stream);
}
struct _CamelDataWrapper {
CamelObject parent_object;
struct _CamelDataWrapperPrivate *priv;
-
+
CamelTransferEncoding encoding;
-
+
CamelContentType *mime_type;
CamelStream *stream;
-
+
unsigned int offline:1;
};
typedef struct {
CamelObjectClass parent_class;
-
+
/* Virtual methods */
void (*set_mime_type) (CamelDataWrapper *data_wrapper,
const char *mime_type);
CamelContentType * (*get_mime_type_field) (CamelDataWrapper *data_wrapper);
void (*set_mime_type_field) (CamelDataWrapper *data_wrapper,
CamelContentType *mime_type_field);
-
+
ssize_t (*write_to_stream) (CamelDataWrapper *data_wrapper,
CamelStream *stream);
-
+
ssize_t (*decode_to_stream) (CamelDataWrapper *data_wrapper,
CamelStream *stream);
-
+
int (*construct_from_stream) (CamelDataWrapper *data_wrapper,
CamelStream *);
-
+
gboolean (*is_offline) (CamelDataWrapper *data_wrapper);
} CamelDataWrapperClass;
*
* Copyright 2004 Novell Inc. (www.novell.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/**
* camel_debug_init:
- * @void:
- *
+ * @void:
+ *
* Init camel debug. Maintain legacy CAMEL_VERBOSE_DEBUG as well as the
* new CAMEL_DEBUG based environment variable interfaces.
*
/**
* camel_debug:
- * @mode:
- *
+ * @mode:
+ *
* Check to see if a debug mode is activated. @mode takes one of two forms,
* a fully qualified 'module:target', or a wildcard 'module' name. It
* returns a boolean to indicate if the module or module and target is
* currently activated for debug output.
- *
- * Return value:
+ *
+ * Return value:
**/
gboolean camel_debug(const char *mode)
{
/* Now check ':subsystem' */
*colon = ':';
if (g_hash_table_lookup(debug_table, colon))
- return TRUE;
+ return TRUE;
}
}
/**
* camel_debug_start:
* @mode:
- *
+ *
* Start debug output for a given mode, used to make sure debug output
* is output atomically and not interspersed with unrelated stuff.
*
/**
* camel_debug_end:
- *
+ *
* Call this when you're done with your debug output. If and only if
* you called camel_debug_start, and if it returns TRUE.
**/
*
* Copyright 2004 Novell Inc. (www.novell.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_digest_folder_class_init (CamelDigestFolderClass *camel_digest_folder_class)
{
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_digest_folder_class);
-
+
parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
-
+
/* virtual method definition */
-
+
/* virtual method overload */
camel_folder_class->refresh_info = digest_refresh_info;
camel_folder_class->sync = digest_sync;
camel_folder_class->expunge = digest_expunge;
camel_folder_class->get_full_name = digest_get_full_name;
-
+
camel_folder_class->get_message = digest_get_message;
camel_folder_class->append_message = digest_append_message;
camel_folder_class->transfer_messages_to = digest_transfer_messages_to;
-
+
camel_folder_class->search_by_expression = digest_search_by_expression;
camel_folder_class->search_by_uids = digest_search_by_uids;
camel_folder_class->search_free = digest_search_free;
{
CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (object);
CamelFolder *folder = CAMEL_FOLDER (object);
-
+
folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
-
+
folder->summary = camel_digest_summary_new ();
-
+
digest_folder->priv = g_new (struct _CamelDigestFolderPrivate, 1);
digest_folder->priv->message = NULL;
digest_folder->priv->search = NULL;
{
CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (object);
CamelFolder *folder = CAMEL_FOLDER (object);
-
+
if (folder->summary) {
camel_object_unref (folder->summary);
folder->summary = NULL;
}
-
+
camel_object_unref (digest_folder->priv->message);
-
+
if (digest_folder->priv->search)
camel_object_unref (digest_folder->priv->search);
-
+
g_mutex_free (digest_folder->priv->search_lock);
-
+
g_free (digest_folder->priv);
}
camel_digest_folder_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_FOLDER_TYPE,
"CamelDigestFolder",
(CamelObjectInitFunc) camel_digest_folder_init,
(CamelObjectFinalizeFunc) digest_finalize);
}
-
+
return type;
}
CamelDataWrapper *wrapper;
CamelMimePart *part;
int i, parts;
-
+
parts = camel_multipart_get_number (multipart);
for (i = 0; i < parts && !has_message_parts; i++) {
part = camel_multipart_get_part (multipart, i);
has_message_parts = TRUE;
}
}
-
+
return has_message_parts;
}
CamelMimePart *part;
int parts, i;
char *uid;
-
+
parts = camel_multipart_get_number (multipart);
for (i = 0; i < parts; i++) {
part = camel_multipart_get_part (multipart, i);
-
+
wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-
+
if (CAMEL_IS_MULTIPART (wrapper)) {
uid = g_strdup_printf ("%s%d.", preuid, i);
digest_add_multipart (folder, CAMEL_MULTIPART (wrapper), uid);
} else if (!CAMEL_IS_MIME_MESSAGE (wrapper)) {
continue;
}
-
+
info = camel_folder_summary_info_new_from_message (folder->summary, CAMEL_MIME_MESSAGE (wrapper));
g_free(info->uid);
info->uid = g_strdup_printf ("%s%d", preuid, i);
CamelDigestFolder *digest_folder;
CamelDataWrapper *wrapper;
CamelFolder *folder;
-
+
wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (message));
if (!wrapper || !CAMEL_IS_MULTIPART (wrapper))
return NULL;
-
+
/* Make sure we have a multipart/digest subpart or at least some message/rfc822 attachments... */
if (!camel_content_type_is (CAMEL_DATA_WRAPPER (message)->mime_type, "multipart", "digest")) {
if (!multipart_contains_message_parts (CAMEL_MULTIPART (wrapper)))
return NULL;
}
-
+
folder = CAMEL_FOLDER (camel_object_new (camel_digest_folder_get_type ()));
digest_folder = CAMEL_DIGEST_FOLDER (folder);
-
+
camel_folder_construct (folder, parent_store, "folder_name", "short_name");
-
+
camel_object_ref (message);
digest_folder->priv->message = message;
-
+
construct_summary (folder, CAMEL_MULTIPART (wrapper));
-
+
return folder;
}
static void
digest_refresh_info (CamelFolder *folder, CamelException *ex)
{
-
+
}
static void
CamelMimePart *part;
char *subuid;
int id;
-
+
part = CAMEL_MIME_PART (digest->priv->message);
wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-
+
do {
id = strtoul (uid, &subuid, 10);
if (!CAMEL_IS_MULTIPART (wrapper))
return NULL;
-
+
part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), id);
wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
uid = subuid + 1;
} while (*subuid == '.');
-
+
if (!CAMEL_IS_MIME_MESSAGE (wrapper))
return NULL;
-
+
message = CAMEL_MIME_MESSAGE (wrapper);
camel_object_ref (message);
-
+
return message;
}
{
CamelDigestFolder *df = (CamelDigestFolder *) folder;
GPtrArray *matches;
-
+
CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
-
+
if (!df->priv->search)
df->priv->search = camel_folder_search_new ();
-
+
camel_folder_search_set_folder (df->priv->search, folder);
matches = camel_folder_search_search(df->priv->search, expression, NULL, ex);
-
+
CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
-
+
return matches;
}
return g_ptr_array_new();
CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
-
+
if (!df->priv->search)
df->priv->search = camel_folder_search_new ();
-
+
camel_folder_search_set_folder (df->priv->search, folder);
matches = camel_folder_search_search(df->priv->search, expression, NULL, ex);
-
+
CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
-
+
return matches;
}
digest_search_free (CamelFolder *folder, GPtrArray *result)
{
CamelDigestFolder *digest_folder = CAMEL_DIGEST_FOLDER (folder);
-
+
CAMEL_DIGEST_FOLDER_LOCK (folder, search_lock);
-
+
camel_folder_search_free_result (digest_folder->priv->search, result);
-
+
CAMEL_DIGEST_FOLDER_UNLOCK (folder, search_lock);
}
struct _CamelDigestFolder {
CamelFolder parent;
-
+
struct _CamelDigestFolderPrivate *priv;
};
struct _CamelDigestFolderClass {
CamelFolderClass parent_class;
-
+
};
CamelType camel_digest_folder_get_type (void);
camel_digest_store_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_store_get_type (),
"CamelDigestStore",
(CamelObjectInitFunc) camel_digest_store_init,
(CamelObjectFinalizeFunc) camel_digest_store_finalise);
}
-
+
return type;
}
{
CamelObjectClass *object_class = (CamelObjectClass *) klass;
CamelStoreClass *store_class = (CamelStoreClass *) klass;
-
+
parent_class = CAMEL_STORE_CLASS(camel_type_get_global_classfuncs (camel_store_get_type ()));
-
+
/* virtual method overload */
object_class->setv = digest_setv;
object_class->getv = digest_getv;
-
+
store_class->get_folder = digest_get_folder;
store_class->rename_folder = digest_rename_folder;
store_class->delete_folder = digest_delete_folder;
store_class->get_folder_info = digest_get_folder_info;
store_class->free_folder_info = camel_store_free_folder_info_full;
-
+
store_class->get_trash = digest_get_trash;
store_class->get_junk = digest_get_junk;
}
camel_digest_store_init (CamelDigestStore *obj)
{
CamelStore *store = (CamelStore *) obj;
-
+
/* we dont want a vtrash and vjunk on this one */
- store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK);
+ store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK);
}
static void
camel_digest_store_finalise (CamelObject *obj)
{
-
+
}
static int
* @url:
*
* Create a new CamelDigestStore object.
- *
+ *
* Return value: A new CamelDigestStore widget.
**/
CamelStore *
{
CamelStore *store;
CamelURL *uri;
-
+
uri = camel_url_new (url, NULL);
if (!uri)
return NULL;
-
+
store = CAMEL_STORE (camel_object_new (camel_digest_store_get_type ()));
CAMEL_SERVICE (store)->url = uri;
-
+
return store;
}
static void
digest_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
{
-
+
}
static void
digest_rename_folder (CamelStore *store, const char *old, const char *new, CamelException *ex)
{
-
+
}
struct _CamelDigestStore {
CamelStore parent;
-
+
};
struct _CamelDigestStoreClass {
CamelStoreClass parent_class;
-
+
};
CamelType camel_digest_store_get_type (void);
camel_digest_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (
camel_folder_summary_get_type (),
(CamelObjectInitFunc) camel_digest_summary_init,
(CamelObjectFinalizeFunc) camel_digest_summary_finalise);
}
-
+
return type;
}
camel_digest_summary_init (CamelDigestSummary *summary)
{
CamelFolderSummary *s = (CamelFolderSummary *) summary;
-
+
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof (CamelMessageInfo);
s->content_info_size = sizeof (CamelMessageContentInfo);
-
+
/* and a unique file version */
s->version += CAMEL_DIGEST_SUMMARY_VERSION;
}
static void
camel_digest_summary_finalise (CamelObject *object)
{
-
+
}
struct _CamelDigestSummary {
CamelFolderSummary parent_object;
-
+
};
struct _CamelDigestSummaryClass {
CamelFolderSummaryClass parent_class;
-
+
};
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-disco-diary.c: class for a disconnected operation log */
-/*
+/*
* Authors: Dan Winship <danw@ximian.com>
*
* Copyright (C) 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#include "camel-session.h"
#include "camel-store.h"
-#define d(x)
+#define d(x)
static void
camel_disco_diary_class_init (CamelDiscoDiaryClass *camel_disco_diary_class)
*
* Copyright 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-disco-folder.c: abstract class for a disconnectable folder */
-/*
+/*
* Authors: Dan Winship <danw@ximian.com>
*
* Copyright (C) 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* the bodies of all messages described by @expression (using the
* same syntax as camel_folder_search_by_expression() ).
**/
-void
+void
camel_disco_folder_prepare_for_offline (CamelDiscoFolder *disco_folder,
const char *expression,
CamelException *ex)
*
* Copyright 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#include "camel-exception.h"
#include "camel-session.h"
-#define d(x)
+#define d(x)
#define CDS_CLASS(o) (CAMEL_DISCO_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
CAMEL_SERVICE_CLASS (camel_disco_store_class);
CamelStoreClass *camel_store_class =
CAMEL_STORE_CLASS (camel_disco_store_class);
-
+
parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ()));
-
+
/* virtual method definition */
camel_disco_store_class->set_status = set_status;
camel_disco_store_class->can_work_offline = can_work_offline;
-
+
/* virtual method overload */
camel_object_class->setv = disco_setv;
camel_object_class->getv = disco_getv;
-
+
camel_service_class->construct = disco_construct;
camel_service_class->connect = disco_connect;
camel_service_class->disconnect = disco_disconnect;
camel_service_class->cancel_connect = disco_cancel_connect;
-
+
camel_store_class->get_folder = disco_get_folder;
camel_store_class->get_folder_info = disco_get_folder_info;
}
camel_disco_store_get_type (void)
{
static CamelType camel_disco_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_disco_store_type == CAMEL_INVALID_TYPE) {
camel_disco_store_type = camel_type_register (
CAMEL_STORE_TYPE,
NULL,
NULL);
}
-
+
return camel_disco_store_type;
}
guint32 flags, CamelException *ex)
{
CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (store);
-
+
switch (camel_disco_store_status (disco_store)) {
case CAMEL_DISCO_STORE_ONLINE:
return CDS_CLASS (store)->get_folder_online (store, name, flags, ex);
-
+
case CAMEL_DISCO_STORE_OFFLINE:
return CDS_CLASS (store)->get_folder_offline (store, name, flags, ex);
-
+
case CAMEL_DISCO_STORE_RESYNCING:
- return CDS_CLASS (store)->get_folder_resyncing (store, name, flags, ex);
+ return CDS_CLASS (store)->get_folder_resyncing (store, name, flags, ex);
}
-
+
g_assert_not_reached ();
return NULL;
}
switch (camel_disco_store_status (disco_store)) {
case CAMEL_DISCO_STORE_ONLINE:
return CDS_CLASS (store)->get_folder_info_online (store, top, flags, ex);
-
+
case CAMEL_DISCO_STORE_OFFLINE:
/* Can't edit subscriptions while offline */
if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) &&
camel_disco_store_check_online (disco_store, ex);
return NULL;
}
-
+
return CDS_CLASS (store)->get_folder_info_offline (store, top, flags, ex);
-
+
case CAMEL_DISCO_STORE_RESYNCING:
return CDS_CLASS (store)->get_folder_info_resyncing (store, top, flags, ex);
}
-
+
g_assert_not_reached ();
return NULL;
}
GPtrArray *folders;
CamelFolder *folder;
int i, sync;
-
+
sync = camel_url_get_param(((CamelService *)disco_store)->url, "offline_sync") != NULL;
-
+
folders = camel_object_bag_list(((CamelStore *)disco_store)->folders);
for (i=0;i<folders->len;i++) {
folder = folders->pdata[i];
g_ptr_array_free(folders, TRUE);
}
}
-
+
camel_store_sync(CAMEL_STORE (disco_store), FALSE, &x);
camel_exception_clear(&x);
}
-
+
if (!camel_service_disconnect (CAMEL_SERVICE (disco_store), network_state, ex))
return;
GPtrArray *folders;
CamelFolder *folder;
int i, sync;
-
+
sync = camel_url_get_param(((CamelService *)disco_store)->url, "offline_sync") != NULL;
-
+
folders = camel_object_bag_list(((CamelStore *)disco_store)->folders);
for (i=0;i<folders->len;i++) {
folder = folders->pdata[i];
g_ptr_array_free(folders, TRUE);
}
}
-
+
camel_store_sync(CAMEL_STORE (disco_store), FALSE, &x);
camel_exception_clear(&x);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-disco-store.h: abstruct class for a disconnectable store */
-/*
+/*
* Authors: Dan Winship <danw@ximian.com>
*
* Copyright (C) 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
} CamelDiscoStoreStatus;
struct _CamelDiscoStore {
- CamelStore parent_object;
+ CamelStore parent_object;
CamelDiscoStoreStatus status;
CamelDiscoDiary *diary;
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
+/*
*
- * Author :
+ * Author :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/**
- * camel_exception_new: allocate a new exception object.
- *
+ * camel_exception_new: allocate a new exception object.
+ *
* Create and returns a new exception object.
- *
+ *
* Returns the newly allocated exception object
**/
CamelException *
/**
* camel_exception_init:
* @ex: a #CamelException
- *
+ *
* Init an exception. This routine is mainly useful when using a
* statically allocated exception.
**/
/**
* camel_exception_clear:
* @ex: a #CamelException
- *
+ *
* Clear an exception, that is, set the exception ID to
* #CAMEL_EXCEPTION_NONE and free the description text. If the
* exception is %NULL, this funtion just returns.
**/
-void
+void
camel_exception_clear (CamelException *exception)
{
if (!exception)
/**
* camel_exception_free:
* @ex: a #CamelException
- *
+ *
* Free an exception object. If the exception is %NULL, nothing is
* done, the routine simply returns.
**/
-void
+void
camel_exception_free (CamelException *exception)
{
if (!exception)
return;
-
+
if (exception->desc)
g_free (exception->desc);
}
/**
- * camel_exception_set: set an exception
+ * camel_exception_set: set an exception
* @ex: a #CamelException
- * @id: exception id
+ * @id: exception id
* @desc: textual description of the exception
- *
- * Set the value of an exception. The exception id is
- * a unique number representing the exception. The
- * textual description is a small text explaining
+ *
+ * Set the value of an exception. The exception id is
+ * a unique number representing the exception. The
+ * textual description is a small text explaining
* what happened and provoked the exception.
*
* When @ex is %NULL, nothing is done, this routine
}
/**
- * camel_exception_setv: set an exception
+ * camel_exception_setv: set an exception
* @ex: a #CamelException
- * @id: exception id
+ * @id: exception id
* @format: format of the description string. The format string is
* used as in printf().
- *
- * Set the value of an exception. The exception id is
- * a unique number representing the exception. The
- * textual description is a small text explaining
- * what happened and provoked the exception.
- * In this version, the string is created from the format
+ *
+ * Set the value of an exception. The exception id is
+ * a unique number representing the exception. The
+ * textual description is a small text explaining
+ * what happened and provoked the exception.
+ * In this version, the string is created from the format
* string and the variable argument list.
*
* It is safe to say:
/**
* camel_exception_xfer:
- * @ex_dst: Destination exception object
+ * @ex_dst: Destination exception object
* @ex_src: Source exception object
- *
+ *
* Transfer the content of an exception from an exception object to
* another. The destination exception receives the id and the
* description text of the source exception.
**/
-void
+void
camel_exception_xfer (CamelException *ex_dst,
CamelException *ex_src)
{
/**
* camel_exception_get_id:
* @ex: a #CamelException
- *
+ *
* Get the id of an exception.
- *
+ *
* Returns the exception id (#CAMEL_EXCEPTION_NONE will be returned if
* @ex is %NULL or unset)
**/
{
if (ex)
return ex->id;
-
+
w(g_warning ("camel_exception_get_id called with NULL parameter."));
-
+
return CAMEL_EXCEPTION_NONE;
}
/**
* camel_exception_get_description:
* @ex: a #CamelException
- *
+ *
* Get the exception description text.
- *
+ *
* Returns the exception description text (%NULL will be returned if
* @ex is %NULL or unset)
**/
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-execpetion.h : exception utils */
-/*
+/*
*
- * Author :
+ * Author :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
const char *desc);
void camel_exception_setv (CamelException *ex,
ExceptionId id,
- const char *format,
+ const char *format,
...);
/* exception content transfer */
*
* Copyright (C) 2000, 2003 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* camel_file_util_encode_uint32:
* @out: file to output to
* @value: value to output
- *
+ *
* Utility function to save an uint32 to a file.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
* camel_file_util_decode_uint32:
* @in: file to read from
* @dest: pointer to a variable to store the value in
- *
+ *
* Retrieve an encoded uint32 from a file.
- *
+ *
* Return value: 0 on success, -1 on error. @*dest will contain the
* decoded value.
**/
* camel_file_util_encode_fixed_int32:
* @out: file to output to
* @value: value to output
- *
+ *
* Encode a gint32, performing no compression, but converting
* to network order.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
* camel_file_util_decode_fixed_int32:
* @in: file to read from
* @dest: pointer to a variable to store the value in
- *
+ *
* Retrieve a gint32.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
* camel_file_util_encode_time_t:
* @out: file to output to
* @value: value to output
- *
+ *
* Encode a time_t value to the file.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
CFU_ENCODE_T(time_t)
* camel_file_util_decode_time_t:
* @in: file to read from
* @dest: pointer to a variable to store the value in
- *
+ *
* Decode a time_t value.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
CFU_DECODE_T(time_t)
* camel_file_util_encode_off_t:
* @out: file to output to
* @value: value to output
- *
+ *
* Encode an off_t type.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
CFU_ENCODE_T(off_t)
* camel_file_util_decode_off_t:
* @in: file to read from
* @dest: pointer to a variable to put the value in
- *
+ *
* Decode an off_t type.
- *
+ *
* Return value: 0 on success, -1 on failure.
**/
CFU_DECODE_T(off_t)
* camel_file_util_encode_size_t:
* @out: file to output to
* @value: value to output
- *
+ *
* Encode an size_t type.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
CFU_ENCODE_T(size_t)
* camel_file_util_decode_size_t:
* @in: file to read from
* @dest: pointer to a variable to put the value in
- *
+ *
* Decode an size_t type.
- *
+ *
* Return value: 0 on success, -1 on failure.
**/
CFU_DECODE_T(size_t)
* camel_file_util_encode_string:
* @out: file to output to
* @str: value to output
- *
+ *
* Encode a normal string and save it in the output file.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
if (str == NULL)
return camel_file_util_encode_uint32 (out, 1);
-
+
if ((len = strlen (str)) > 65536)
len = 65536;
-
+
if (camel_file_util_encode_uint32 (out, len+1) == -1)
return -1;
if (len == 0 || fwrite (str, len, 1, out) == 1)
* camel_file_util_decode_string:
* @in: file to read from
* @str: pointer to a variable to store the value in
- *
+ *
* Decode a normal string from the input file.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
* @out: file to output to
* @str: value to output
* @len: total-len of str to store
- *
+ *
* Encode a normal string and save it in the output file.
* Unlike @camel_file_util_encode_string, it pads the
* @str with "NULL" bytes, if @len is > strlen(str)
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
/* Max size is 64K */
if (len > 65536)
len = 65536;
-
+
memset(buf, 0x00, len);
g_strlcpy(buf, str, len);
* camel_file_util_decode_fixed_string:
* @in: file to read from
* @str: pointer to a variable to store the value in
- * @len: total-len to decode.
- *
+ * @len: total-len to decode.
+ *
* Decode a normal string from the input file.
- *
+ *
* Return value: 0 on success, -1 on error.
**/
int
if (name == NULL)
return NULL;
-
+
return camel_url_encode(name, unsafe_chars);
}
{
ssize_t nread;
int cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
#ifndef G_OS_WIN32
int errnosav, flags, fdmax;
fd_set rdset;
-
+
flags = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-
+
do {
struct timeval tv;
int res;
else if (FD_ISSET (cancel_fd, &rdset)) {
errno = EINTR;
goto failed;
- } else {
+ } else {
do {
nread = read (fd, buf, n);
} while (nread == -1 && errno == EINTR);
errno = errnosav;
#endif
}
-
+
return nread;
}
{
ssize_t w, written = 0;
int cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
#ifndef G_OS_WIN32
int errnosav, flags, fdmax;
fd_set rdset, wrset;
-
+
flags = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-
+
fdmax = MAX (fd, cancel_fd) + 1;
do {
struct timeval tv;
FD_SET (fd, &wrset);
FD_SET (cancel_fd, &rdset);
tv.tv_sec = IO_TIMEOUT;
- tv.tv_usec = 0;
+ tv.tv_usec = 0;
w = -1;
res = select (fdmax, &rdset, &wrset, 0, &tv);
do {
w = write (fd, buf + written, n - written);
} while (w == -1 && errno == EINTR);
-
+
if (w == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
w = 0;
written += w;
}
} while (w != -1 && written < n);
-
+
errnosav = errno;
fcntl (fd, F_SETFL, flags);
errno = errnosav;
#endif
}
-
+
if (w == -1)
return -1;
-
+
return written;
}
#else
ssize_t nread;
int cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
else if (FD_ISSET (cancel_fd, &rdset)) {
errno = EINTR;
goto failed;
- } else {
+ } else {
nread = recv (fd, buf, n, 0);
}
} while (nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK);
failed:
;
}
-
+
return nread;
#endif
}
#else
ssize_t w, written = 0;
int cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
FD_SET (fd, &wrset);
FD_SET (cancel_fd, &rdset);
tv.tv_sec = IO_TIMEOUT;
- tv.tv_usec = 0;
+ tv.tv_usec = 0;
w = -1;
res = select (fdmax, &rdset, &wrset, 0, &tv);
arg = 0;
ioctlsocket (fd, FIONBIO, &arg);
}
-
+
if (w == -1)
return -1;
-
+
return written;
#endif
}
/**
* camel_file_util_savename:
* @filename: a pathname
- *
+ *
* Builds a pathname where the basename is of the form ".#" + the
* basename of @filename, for instance used in a two-stage commit file
* write.
- *
+ *
* Return value: The new pathname. It must be free'd with g_free().
**/
char *
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
+/*
* Authors:
* Michael Zucchi <notzed@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2000, 2003 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
CamelSession *session;
CamelFolder *defaultfolder; /* defualt folder */
-
+
CamelFilterStatusFunc *statusfunc; /* status callback */
void *statusdata; /* status callback data */
-
+
CamelFilterShellFunc *shellfunc; /* execute shell command callback */
void *shelldata; /* execute shell command callback data */
-
+
CamelFilterPlaySoundFunc *playfunc; /* play-sound command callback */
void *playdata; /* play-sound command callback data */
-
+
CamelFilterSystemBeepFunc *beep; /* system beep callback */
void *beepdata; /* system beep callback data */
-
+
/* for callback */
CamelFilterGetFolderFunc get_folder;
void *data;
-
+
/* run-time data */
GHashTable *folders; /* folders that message has been copied to */
int closed; /* close count */
GHashTable *forwards; /* addresses that have been forwarded the message */
GHashTable *only_once; /* actions to run only-once */
-
+
gboolean terminated; /* message processing was terminated */
gboolean deleted; /* message was marked for deletion */
gboolean copied; /* message was copied to some folder or another */
gboolean moved; /* message was moved to some folder or another */
-
+
CamelMimeMessage *message; /* input message */
CamelMessageInfo *info; /* message summary info */
const char *uid; /* message uid */
CamelFolder *source; /* message source folder */
gboolean modified; /* has the input message been modified? */
-
+
FILE *logfile; /* log file */
-
+
EDList rules; /* list of _filter_rule structs */
-
+
CamelException *ex;
-
+
/* evaluator */
ESExp *eval;
};
(CamelObjectInitFunc) camel_filter_driver_init,
(CamelObjectFinalizeFunc) camel_filter_driver_finalise);
}
-
+
return type;
}
{
struct _CamelFilterDriverPrivate *p;
int i;
-
+
p = _PRIVATE (obj) = g_malloc0 (sizeof (*p));
e_dlist_init(&p->rules);
e_sexp_add_function (p->eval, 0, symbols[i].name, symbols[i].func, obj);
}
}
-
+
p->globals = g_hash_table_new (g_str_hash, g_str_equal);
-
+
p->folders = g_hash_table_new (g_str_hash, g_str_equal);
-
+
p->only_once = g_hash_table_new (g_str_hash, g_str_equal);
}
camel_filter_driver_finalise (CamelObject *obj)
{
CamelFilterDriver *driver = (CamelFilterDriver *) obj;
- struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
+ struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
struct _filter_rule *node;
/* close all folders that were opened for appending */
close_folders (driver);
g_hash_table_destroy (p->folders);
-
+
g_hash_table_foreach (p->globals, free_hash_strings, driver);
g_hash_table_destroy (p->globals);
-
+
g_hash_table_foreach (p->only_once, free_hash_strings, driver);
g_hash_table_destroy (p->only_once);
-
+
e_sexp_unref(p->eval);
-
+
if (p->defaultfolder) {
camel_folder_thaw (p->defaultfolder);
camel_object_unref (p->defaultfolder);
camel_filter_driver_set_logfile (CamelFilterDriver *d, FILE *logfile)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
+
p->logfile = logfile;
}
camel_filter_driver_set_status_func (CamelFilterDriver *d, CamelFilterStatusFunc *func, void *data)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
+
p->statusfunc = func;
p->statusdata = data;
}
camel_filter_driver_set_shell_func (CamelFilterDriver *d, CamelFilterShellFunc *func, void *data)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
+
p->shellfunc = func;
p->shelldata = data;
}
camel_filter_driver_set_play_sound_func (CamelFilterDriver *d, CamelFilterPlaySoundFunc *func, void *data)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
+
p->playfunc = func;
p->playdata = data;
}
camel_filter_driver_set_system_beep_func (CamelFilterDriver *d, CamelFilterSystemBeepFunc *func, void *data)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
+
p->beep = func;
p->beepdata = data;
}
camel_filter_driver_set_default_folder (CamelFilterDriver *d, CamelFolder *def)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
-
+
if (p->defaultfolder) {
camel_folder_thaw (p->defaultfolder);
camel_object_unref (p->defaultfolder);
}
-
+
p->defaultfolder = def;
-
+
if (p->defaultfolder) {
camel_folder_freeze (p->defaultfolder);
camel_object_ref (p->defaultfolder);
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
struct _filter_rule *node;
-
+
node = (struct _filter_rule *) p->rules.head;
while (node->next) {
if (!strcmp (node->name, name)) {
g_free (node->action);
g_free (node->name);
g_free (node);
-
+
return 0;
}
-
+
node = node->next;
}
-
+
return -1;
}
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
va_list ap;
char *str;
-
+
if (p->statusfunc) {
va_start (ap, desc);
str = g_strdup_vprintf (desc, ap);
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (d);
char *oldkey, *oldvalue;
-
+
if (g_hash_table_lookup_extended (p->globals, name, (void *)&oldkey, (void *)&oldvalue)) {
g_free (oldvalue);
g_hash_table_insert (p->globals, oldkey, g_strdup (value));
do_delete (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "doing delete\n"));
p->deleted = TRUE;
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Delete");
-
+
return NULL;
}
mark_forward (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
/*struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);*/
-
+
d(fprintf (stderr, "marking message for forwarding\n"));
/* FIXME: do stuff here */
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Forward");
-
+
return NULL;
}
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
int i;
-
+
d(fprintf (stderr, "copying message...\n"));
-
+
for (i = 0; i < argc; i++) {
if (argv[i]->type == ESEXP_RES_STRING) {
/* open folders we intent to copy to */
char *folder = argv[i]->value.string;
CamelFolder *outbox;
-
+
outbox = open_folder (driver, folder);
if (!outbox)
break;
-
+
if (outbox == p->source)
break;
-
+
if (!p->modified && p->uid && p->source && camel_folder_has_summary_capability (p->source)) {
GPtrArray *uids;
-
+
uids = g_ptr_array_new ();
g_ptr_array_add (uids, (char *) p->uid);
camel_folder_transfer_messages_to (p->source, uids, outbox, NULL, FALSE, p->ex);
} else {
if (p->message == NULL)
p->message = camel_folder_get_message (p->source, p->uid, p->ex);
-
+
if (!p->message)
continue;
-
+
camel_folder_append_message (outbox, p->message, p->info, NULL, p->ex);
}
-
+
if (!camel_exception_is_set (p->ex))
p->copied = TRUE;
-
+
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Copy to folder %s",
folder);
}
}
-
+
return NULL;
}
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
int i;
-
+
d(fprintf (stderr, "moving message...\n"));
-
+
for (i = 0; i < argc; i++) {
if (argv[i]->type == ESEXP_RES_STRING) {
/* open folders we intent to move to */
char *folder = argv[i]->value.string;
CamelFolder *outbox;
int last;
-
+
outbox = open_folder (driver, folder);
if (!outbox)
break;
-
+
if (outbox == p->source)
break;
} else {
if (p->message == NULL)
p->message = camel_folder_get_message (p->source, p->uid, p->ex);
-
+
if (!p->message)
continue;
-
+
camel_folder_append_message (outbox, p->message, p->info, NULL, p->ex);
if (!camel_exception_is_set(p->ex) && last) {
camel_message_info_set_flags(p->info, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FOLDER_FLAGGED, ~0);
}
}
-
+
if (!camel_exception_is_set (p->ex)) {
p->moved = TRUE;
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Move to folder %s", folder);
do_stop (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Stopped processing");
d(fprintf (stderr, "terminating message processing\n"));
p->terminated = TRUE;
-
+
return NULL;
}
do_label (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "setting label tag\n"));
if (argc > 0 && argv[0]->type == ESEXP_RES_STRING) {
/* This is a list of new labels, we should used these in case of passing in old names.
camel_message_info_set_user_flag (p->info, label, TRUE);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set label to %s", label);
}
-
+
return NULL;
}
do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "setting colour tag\n"));
if (argc > 0 && argv[0]->type == ESEXP_RES_STRING) {
if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
camel_message_info_set_user_tag(p->info, "colour", argv[0]->value.string);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set colour to %s", argv[0]->value.string);
}
-
+
return NULL;
}
do_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "setting score tag\n"));
if (argc > 0 && argv[0]->type == ESEXP_RES_INT) {
char *value;
-
+
value = g_strdup_printf ("%d", argv[0]->value.number);
camel_message_info_set_user_tag(p->info, "score", value);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set score to %d", argv[0]->value.number);
g_free (value);
}
-
+
return NULL;
}
do_adjust_score(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE(driver);
-
+
d(fprintf (stderr, "adjusting score tag\n"));
if (argc > 0 && argv[0]->type == ESEXP_RES_INT) {
char *value;
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Adjust score (%d) to %s", argv[0]->value.number, value);
g_free (value);
}
-
+
return NULL;
}
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
guint32 flags;
-
+
d(fprintf (stderr, "setting flag\n"));
if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
flags = camel_system_flag (argv[0]->value.string);
camel_message_info_set_flags(p->info, flags | CAMEL_MESSAGE_FOLDER_FLAGGED, ~0);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set %s flag", argv[0]->value.string);
}
-
+
return NULL;
}
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
guint32 flags;
-
+
d(fprintf (stderr, "unsetting flag\n"));
if (argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
flags = camel_system_flag (argv[0]->value.string);
camel_message_info_set_flags(p->info, flags | CAMEL_MESSAGE_FOLDER_FLAGGED, 0);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Unset %s flag", argv[0]->value.string);
}
-
+
return NULL;
}
child_watch_data_t child_watch_data;
GSource *source;
GMainContext *context;
-
+
if (argc < 1 || argv[0]->value.string[0] == '\0')
return 0;
-
+
/* make sure we have the message... */
if (p->message == NULL) {
if (!(p->message = camel_folder_get_message (p->source, p->uid, p->ex)))
return -1;
}
-
+
args = g_ptr_array_new ();
for (i = 0; i < argc; i++)
g_ptr_array_add (args, argv[i]->value.string);
g_error_free (error);
return -1;
}
-
+
g_ptr_array_free (args, TRUE);
-
+
stream = camel_stream_fs_new_with_fd (pipe_to_child);
if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (p->message), stream) == -1) {
camel_object_unref (stream);
close (pipe_from_child);
goto wait;
}
-
+
if (camel_stream_flush (stream) == -1) {
camel_object_unref (stream);
close (pipe_from_child);
goto wait;
}
-
+
camel_object_unref (stream);
-
+
stream = camel_stream_fs_new_with_fd (pipe_from_child);
mem = camel_stream_mem_new ();
if (camel_stream_write_to_stream (stream, mem) == -1) {
camel_object_unref (mem);
goto wait;
}
-
+
camel_object_unref (stream);
camel_stream_reset (mem);
-
+
parser = camel_mime_parser_new ();
camel_mime_parser_init_with_stream (parser, mem);
camel_mime_parser_scan_from (parser, FALSE);
camel_object_unref (mem);
-
+
message = camel_mime_message_new ();
if (camel_mime_part_construct_from_parser ((CamelMimePart *) message, parser) == -1) {
camel_exception_setv (p->ex, CAMEL_EXCEPTION_SYSTEM,
p->message = message;
p->modified = TRUE;
}
-
+
camel_object_unref (parser);
-
+
wait:
context = g_main_context_new ();
child_watch_data.loop = g_main_loop_new (context, FALSE);
pipe_message (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
int i;
-
+
/* make sure all args are strings */
for (i = 0; i < argc; i++) {
if (argv[i]->type != ESEXP_RES_STRING)
return NULL;
}
-
+
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Piping message to %s", argv[0]->value.string);
pipe_to_system (f, argc, argv, driver);
-
+
return NULL;
}
GString *command;
GPtrArray *args;
int i;
-
+
d(fprintf (stderr, "executing shell command\n"));
-
+
command = g_string_new ("");
-
+
args = g_ptr_array_new ();
-
+
/* make sure all args are strings */
for (i = 0; i < argc; i++) {
if (argv[i]->type != ESEXP_RES_STRING)
goto done;
-
+
g_ptr_array_add (args, argv[i]->value.string);
-
+
g_string_append (command, argv[i]->value.string);
g_string_append_c (command, ' ');
}
-
+
g_string_truncate (command, command->len - 1);
-
+
if (p->shellfunc && argc >= 1) {
p->shellfunc (driver, argc, (char **) args->pdata, p->shelldata);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Executing shell command: [%s]",
command->str);
}
-
+
done:
-
+
g_ptr_array_free (args, TRUE);
g_string_free (command, TRUE);
-
+
return NULL;
}
do_beep (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "beep\n"));
-
+
if (p->beep) {
p->beep (driver, p->beepdata);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Beep");
}
-
+
return NULL;
}
play_sound (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "play sound\n"));
-
+
if (p->playfunc && argc == 1 && argv[0]->type == ESEXP_RES_STRING) {
p->playfunc (driver, argv[0]->value.string, p->playdata);
camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Play sound");
}
-
+
return NULL;
}
do_only_once (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDriver *driver)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
d(fprintf (stderr, "only once\n"));
-
+
if (argc == 2 && !g_hash_table_lookup (p->only_once, argv[0]->value.string))
g_hash_table_insert (p->only_once, g_strdup (argv[0]->value.string),
g_strdup (argv[1]->value.string));
-
+
return NULL;
}
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
CamelFolder *camelfolder;
-
+
/* we have a lookup table of currently open folders */
camelfolder = g_hash_table_lookup (p->folders, folder_url);
if (camelfolder)
} else {
camelfolder = p->get_folder (driver, folder_url, p->data, p->ex);
}
-
+
if (camelfolder) {
g_hash_table_insert (p->folders, g_strdup (folder_url), camelfolder);
camel_folder_freeze (camelfolder);
} else {
g_hash_table_insert (p->folders, g_strdup (folder_url), FOLDER_INVALID);
}
-
+
return camelfolder;
}
static void
close_folder (void *key, void *value, void *data)
-{
+{
CamelFolder *folder = value;
CamelFilterDriver *driver = data;
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
g_hash_table_foreach (p->folders, close_folder, driver);
g_hash_table_destroy (p->folders);
p->folders = g_hash_table_new (g_str_hash, g_str_equal);
-
+
/* FIXME: status from driver */
return 0;
}
camel_filter_driver_log (CamelFilterDriver *driver, enum filter_log_t status, const char *desc, ...)
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
-
+
if (p->logfile) {
char *str = NULL;
-
+
if (desc) {
va_list ap;
-
+
va_start (ap, desc);
str = g_strdup_vprintf (desc, ap);
}
-
+
switch (status) {
case FILTER_LOG_START: {
/* write log header */
const char *from = NULL;
char date[50];
time_t t;
-
+
/* FIXME: does this need locking? Probably */
-
+
from = camel_message_info_from (p->info);
subject = camel_message_info_subject (p->info);
-
+
time (&t);
strftime (date, 49, "%a, %d %b %Y %H:%M:%S", localtime (&t));
fprintf (p->logfile, "Applied filter \"%s\" to message from %s - \"%s\" at %s\n",
str, from ? from : "unknown", subject ? subject : "", date);
-
+
break;
}
case FILTER_LOG_ACTION:
/* nothing else is loggable */
break;
}
-
+
g_free (str);
}
}
struct _CamelFilterDriverPrivate *p = _PRIVATE (data->driver);
CamelException *ex = data->ex;
ESExpResult *r;
-
+
d(printf ("evaluating: %s\n\n", action));
-
+
e_sexp_input_text (p->eval, action, strlen (action));
if (e_sexp_parse (p->eval) == -1) {
if (!camel_exception_is_set (ex))
e_sexp_error (p->eval), action);
goto done;
}
-
+
r = e_sexp_eval (p->eval);
if (r == NULL) {
if (!camel_exception_is_set (ex))
e_sexp_error (p->eval), action);
goto done;
}
-
+
e_sexp_result_free (p->eval, r);
-
+
done:
-
+
g_free (key);
g_free (action);
-
+
return TRUE;
}
{
struct _CamelFilterDriverPrivate *p = _PRIVATE (driver);
struct _run_only_once data;
-
+
if (!p->only_once)
return;
-
+
data.driver = driver;
data.ex = ex;
-
+
g_hash_table_foreach_remove (p->only_once, (GHRFunc) run_only_once, &data);
}
int status;
off_t last = 0;
int ret = -1;
-
+
fd = g_open (mbox, O_RDONLY|O_BINARY, 0);
if (fd == -1) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Unable to open spool folder"));
}
/* to get the filesize */
fstat (fd, &st);
-
+
mp = camel_mime_parser_new ();
camel_mime_parser_scan_from (mp, TRUE);
if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
goto fail;
}
fd = -1;
-
+
source_url = g_filename_to_uri (mbox, NULL, NULL);
-
+
while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) {
CamelMessageInfo *info;
CamelMimeMessage *msg;
int pc = 0;
-
+
if (st.st_size > 0)
pc = (int)(100.0 * ((double)camel_mime_parser_tell (mp) / (double)st.st_size));
-
+
report_status (driver, CAMEL_FILTER_STATUS_START, pc, _("Getting message %d (%d%%)"), i, pc);
-
+
msg = camel_mime_message_new ();
if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) {
camel_exception_set (ex, (errno==EINTR)?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_SYSTEM, _("Cannot open message"));
camel_message_info_free (info);
goto fail;
}
-
+
i++;
-
+
/* skip over the FROM_END state */
camel_mime_parser_step (mp, 0, 0);
camel_message_info_free (info);
}
-
+
if (p->defaultfolder) {
report_status(driver, CAMEL_FILTER_STATUS_PROGRESS, 100, _("Syncing folder"));
camel_folder_sync(p->defaultfolder, FALSE, camel_exception_is_set (ex) ? NULL : ex);
}
-
+
report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Complete"));
-
+
ret = 0;
fail:
g_free (source_url);
close (fd);
if (mp)
camel_object_unref (mp);
-
+
return ret;
}
int status = 0;
CamelURL *url;
int i;
-
+
service_url = camel_service_get_url (CAMEL_SERVICE (camel_folder_get_parent_store (folder)));
url = camel_url_new (service_url, NULL);
g_free (service_url);
-
+
source_url = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
camel_url_free (url);
-
+
if (uids == NULL) {
uids = camel_folder_get_uids (folder);
freeuids = TRUE;
}
-
+
for (i = 0; i < uids->len; i++) {
int pc = (100 * i)/uids->len;
-
+
report_status (driver, CAMEL_FILTER_STATUS_START, pc, _("Getting message %d of %d"), i+1,
uids->len);
-
+
if (camel_folder_has_summary_capability (folder))
info = camel_folder_get_message_info (folder, uids->pdata[i]);
else
info = NULL;
-
+
status = camel_filter_driver_filter_message (driver, NULL, info, uids->pdata[i],
folder, source_url, source_url, ex);
-
+
if (camel_folder_has_summary_capability (folder))
camel_folder_free_message_info (folder, info);
-
+
if (camel_exception_is_set (ex) || status == -1) {
report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed at message %d of %d"),
i+1, uids->len);
status = -1;
break;
}
-
+
if (remove)
camel_folder_set_message_flags (folder, uids->pdata[i],
CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN, ~0);
-
+
if (cache)
camel_uid_cache_save_uid (cache, uids->pdata[i]);
}
-
+
if (p->defaultfolder) {
report_status (driver, CAMEL_FILTER_STATUS_PROGRESS, 100, _("Syncing folder"));
camel_folder_sync (p->defaultfolder, FALSE, camel_exception_is_set (ex) ? NULL : ex);
}
-
+
if (i == uids->len)
report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Complete"));
-
+
if (freeuids)
camel_folder_free_uids (folder, uids);
-
+
g_free (source_url);
-
+
return status;
}
struct _CamelFilterDriverPrivate *p = msgdata->p;
const char *source_url = msgdata->source_url;
CamelMimeMessage *message;
-
+
if (p->message) {
message = p->message;
camel_object_ref (message);
} else {
const char *uid;
-
+
if (p->uid)
uid = p->uid;
else
uid = camel_message_info_uid (p->info);
-
+
message = camel_folder_get_message (p->source, uid, ex);
}
-
+
if (source_url && message && camel_mime_message_get_source (message) == NULL)
camel_mime_message_set_source (message, source_url);
-
+
return message;
}
gboolean filtered = FALSE;
ESExpResult *r;
int result;
-
+
/* FIXME: make me into a g_return_if_fail/g_assert or whatever... */
if (message == NULL && (source == NULL || uid == NULL)) {
g_warning ("there is no way to fetch the message using the information provided...");
return -1;
}
-
+
if (info == NULL) {
struct _camel_header_raw *h;
-
+
if (message) {
camel_object_ref (message);
} else {
if (!message)
return -1;
}
-
+
h = CAMEL_MIME_PART (message)->headers;
info = camel_message_info_new_from_header (NULL, h);
freeinfo = TRUE;
} else {
if (camel_message_info_flags(info) & CAMEL_MESSAGE_DELETED)
return 0;
-
+
uid = camel_message_info_uid (info);
-
+
if (message)
camel_object_ref (message);
}
-
+
p->ex = ex;
p->terminated = FALSE;
p->deleted = FALSE;
p->info = info;
p->uid = uid;
p->source = source;
-
+
if (message && original_source_url && camel_mime_message_get_source (message) == NULL)
camel_mime_message_set_source (message, original_source_url);
-
+
node = (struct _filter_rule *) p->rules.head;
result = CAMEL_SEARCH_NOMATCH;
while (node->next && !p->terminated) {
struct _get_message data;
-
+
d(printf("applying rule %s\naction %s\n", node->match, node->action));
-
+
data.p = p;
data.source_url = original_source_url;
-
- result = camel_filter_search_match (p->session, get_message_cb, &data, p->info,
+
+ result = camel_filter_search_match (p->session, get_message_cb, &data, p->info,
original_source_url ? original_source_url : source_url,
node->match, p->ex);
-
+
switch (result) {
case CAMEL_SEARCH_ERROR:
goto error;
default:
break;
}
-
+
node = node->next;
}
-
+
/* *Now* we can set the DELETED flag... */
if (p->deleted) {
if (p->source && p->uid && camel_folder_has_summary_capability (p->source))
else
camel_message_info_set_flags(info, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FOLDER_FLAGGED, ~0);
}
-
+
/* Logic: if !Moved and there exists a default folder... */
if (!(p->copied && p->deleted) && !p->moved && p->defaultfolder) {
/* copy it to the default inbox */
if (!p->modified && p->uid && p->source && camel_folder_has_summary_capability (p->source)) {
GPtrArray *uids;
-
+
uids = g_ptr_array_new ();
g_ptr_array_add (uids, (char *) p->uid);
camel_folder_transfer_messages_to (p->source, uids, p->defaultfolder, NULL, FALSE, p->ex);
camel_folder_append_message (p->defaultfolder, p->message, p->info, NULL, p->ex);
}
}
-
+
if (p->message)
camel_object_unref (p->message);
-
+
if (freeinfo)
camel_message_info_free (info);
-
+
return 0;
-
+
error:
if (filtered)
camel_filter_driver_log (driver, FILTER_LOG_END, NULL);
-
+
if (p->message)
camel_object_unref (p->message);
-
+
if (freeinfo)
camel_message_info_free (info);
-
+
return -1;
}
struct _CamelFilterDriver {
CamelObject parent;
-
+
struct _CamelFilterDriverPrivate *priv;
};
{
if (fms->message)
return fms->message;
-
+
fms->message = fms->get_message (fms->get_message_data, fms->ex);
-
+
if (fms->message == NULL)
e_sexp_fatal_error (sexp, _("Failed to retrieve message"));
-
+
return fms->message;
}
gboolean matched = FALSE;
ESExpResult *r;
int i;
-
+
if (argc > 1 && argv[0]->type == ESEXP_RES_STRING) {
char *name = argv[0]->value.string;
}
}
}
-
+
r = e_sexp_result_new (f, ESEXP_RES_BOOL);
r->value.bool = matched;
-
+
return r;
}
gboolean matched = FALSE;
ESExpResult *r;
int i;
-
+
message = camel_filter_search_get_message (fms, f);
-
+
for (i = 0; i < argc && !matched; i++) {
if (argv[i]->type == ESEXP_RES_STRING)
matched = camel_medium_get_header (CAMEL_MEDIUM (message), argv[i]->value.string) != NULL;
}
-
+
r = e_sexp_result_new (f, ESEXP_RES_BOOL);
r->value.bool = matched;
-
+
return r;
}
CamelMimeMessage *message;
regex_t pattern;
const char *contents;
-
+
message = camel_filter_search_get_message (fms, f);
-
+
if (argc > 1 && argv[0]->type == ESEXP_RES_STRING
&& (contents = camel_medium_get_header (CAMEL_MEDIUM (message), argv[0]->value.string))
&& camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE, argc-1, argv+1, fms->ex) == 0) {
regfree (&pattern);
} else
r->value.bool = FALSE;
-
+
return r;
}
GString *str = g_string_new ("");
char *ret;
struct _camel_header_raw *h;
-
+
for (h = mp->headers; h; h = h->next) {
if (h->value != NULL) {
g_string_append (str, h->name);
g_string_append_c(str, '\n');
}
}
-
+
ret = str->str;
g_string_free (str, FALSE);
-
+
return ret;
}
CamelMimeMessage *message;
regex_t pattern;
char *contents;
-
+
if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_NEWLINE,
argc, argv, fms->ex) == 0) {
message = camel_filter_search_get_message (fms, f);
regfree (&pattern);
} else
r->value.bool = FALSE;
-
+
return r;
}
{
/* match-all: when dealing with single messages is a no-op */
ESExpResult *r;
-
+
if (argc > 0)
return e_sexp_term_eval (f, argv[0]);
-
+
r = e_sexp_result_new (f, ESEXP_RES_BOOL);
r->value.bool = TRUE;
-
+
return r;
}
ESExpResult *r = e_sexp_result_new (f, ESEXP_RES_BOOL);
CamelMimeMessage *message;
regex_t pattern;
-
+
if (camel_search_build_match_regex (&pattern, CAMEL_SEARCH_MATCH_ICASE, argc, argv, fms->ex) == 0) {
message = camel_filter_search_get_message (fms, f);
r->value.bool = camel_search_message_body_contains ((CamelDataWrapper *) message, &pattern);
regfree (&pattern);
} else
r->value.bool = FALSE;
-
+
return r;
}
ESExpResult *r = e_sexp_result_new(f, ESEXP_RES_BOOL);
CamelMimeMessage *message;
regex_t pattern;
-
+
if (camel_search_build_match_regex(&pattern, CAMEL_SEARCH_MATCH_ICASE|CAMEL_SEARCH_MATCH_REGEX|CAMEL_SEARCH_MATCH_NEWLINE,
argc, argv, fms->ex) == 0) {
message = camel_filter_search_get_message (fms, f);
regfree (&pattern);
} else
r->value.bool = FALSE;
-
+
return r;
}
ESExpResult *r;
gboolean truth = FALSE;
int i;
-
+
/* performs an OR of all words */
for (i = 0; i < argc && !truth; i++) {
if (argv[i]->type == ESEXP_RES_STRING
break;
}
}
-
+
r = e_sexp_result_new (f, ESEXP_RES_BOOL);
r->value.bool = truth;
-
+
return r;
}
system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r;
-
+
if (argc != 1 || argv[0]->type != ESEXP_RES_STRING)
e_sexp_fatal_error(f, _("Invalid arguments to (system-flag)"));
-
+
r = e_sexp_result_new (f, ESEXP_RES_BOOL);
r->value.bool = camel_system_flag_get (camel_message_info_flags(fms->info), argv[0]->value.string);
-
+
return r;
}
if (argc != 1 || argv[0]->type != ESEXP_RES_STRING)
e_sexp_fatal_error(f, _("Invalid arguments to (user-tag)"));
-
+
tag = camel_message_info_user_tag(fms->info, argv[0]->value.string);
-
+
r = e_sexp_result_new (f, ESEXP_RES_STRING);
r->value.string = g_strdup (tag ? tag : "");
-
+
return r;
}
{
CamelMimeMessage *message;
ESExpResult *r;
-
+
message = camel_filter_search_get_message (fms, f);
r = e_sexp_result_new (f, ESEXP_RES_INT);
r->value.number = camel_mime_message_get_date (message, NULL);
-
+
return r;
}
{
CamelMimeMessage *message;
ESExpResult *r;
-
+
message = camel_filter_search_get_message (fms, f);
r = e_sexp_result_new (f, ESEXP_RES_INT);
r->value.number = camel_mime_message_get_date_received (message, NULL);
-
+
return r;
}
get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r;
-
+
r = e_sexp_result_new (f, ESEXP_RES_INT);
r->value.number = time (NULL);
-
+
return r;
}
r = e_sexp_result_new(f, ESEXP_RES_BOOL);
r->value.bool = truth;
-
+
return r;
}
get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
{
ESExpResult *r;
-
+
r = e_sexp_result_new(f, ESEXP_RES_INT);
r->value.number = camel_message_info_size(fms->info) / 1024;
child_watch_data_t child_watch_data;
GSource *source;
GMainContext *context;
-
+
if (argc < 1 || argv[0]->value.string[0] == '\0')
return 0;
-
+
args = g_ptr_array_new ();
for (i = 0; i < argc; i++)
g_ptr_array_add (args, argv[i]->value.string);
g_ptr_array_add (args, NULL);
-
+
if (!g_spawn_async_with_pipes (NULL,
(gchar **) args->pdata,
NULL,
g_error_free (error);
return -1;
}
-
+
g_ptr_array_free (args, TRUE);
-
+
message = camel_filter_search_get_message (fms, f);
-
+
stream = camel_stream_fs_new_with_fd (pipe_to_child);
camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream);
camel_stream_flush (stream);
camel_object_unref (stream);
-
+
context = g_main_context_new ();
child_watch_data.loop = g_main_loop_new (context, FALSE);
g_main_context_unref (context);
{
ESExpResult *r;
int retval, i;
-
+
/* make sure all args are strings */
for (i = 0; i < argc; i++) {
if (argv[i]->type != ESEXP_RES_STRING) {
goto done;
}
}
-
+
retval = run_command (f, argc, argv, fms);
-
+
done:
r = e_sexp_result_new (f, ESEXP_RES_INT);
r->value.number = retval;
-
+
return r;
}
fms.info = info;
fms.source = source;
fms.ex = ex;
-
+
sexp = e_sexp_new ();
-
+
for (i = 0; i < sizeof (symbols) / sizeof (symbols[0]); i++) {
if (symbols[i].type == 1)
e_sexp_add_ifunction (sexp, 0, symbols[i].name, (ESExpIFunc *)symbols[i].func, &fms);
else
e_sexp_add_function (sexp, 0, symbols[i].name, symbols[i].func, &fms);
}
-
+
e_sexp_input_text (sexp, expression, strlen (expression));
if (e_sexp_parse (sexp) == -1) {
if (!camel_exception_is_set (ex))
e_sexp_error (sexp), expression);
goto error;
}
-
+
result = e_sexp_eval (sexp);
if (result == NULL) {
if (!camel_exception_is_set (ex))
e_sexp_error (sexp), expression);
goto error;
}
-
+
if (result->type == ESEXP_RES_BOOL)
retval = result->value.bool ? CAMEL_SEARCH_MATCHED : CAMEL_SEARCH_NOMATCH;
else
retval = CAMEL_SEARCH_NOMATCH;
-
+
e_sexp_result_free (sexp, result);
e_sexp_unref (sexp);
-
+
if (fms.message)
camel_object_unref (fms.message);
-
+
return retval;
-
+
error:
if (fms.message)
camel_object_unref (fms.message);
-
+
e_sexp_unref (sexp);
-
+
return CAMEL_SEARCH_ERROR;
}
#include "camel-search-private.h"
#include "camel-stream-mem.h"
-#define d(x)
-#define r(x)
+#define d(x)
+#define r(x)
struct _CamelFolderSearchPrivate {
GHashTable *mempool_hash;
camel_folder_search_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (), "CamelFolderSearch",
sizeof (CamelFolderSearch),
(CamelObjectInitFunc) camel_folder_search_init,
(CamelObjectFinalizeFunc) camel_folder_search_finalize);
}
-
+
return type;
}
* camel_folder_search_new:
*
* Create a new CamelFolderSearch object.
- *
+ *
* A CamelFolderSearch is a subclassable, extensible s-exp
* evaluator which enforces a particular set of s-expressions.
* Particular methods may be overriden by an implementation to
* camel_folder_search_set_folder:
* @search:
* @folder: A folder.
- *
+ *
* Set the folder attribute of the search. This is currently unused, but
* could be used to perform a slow-search when indexes and so forth are not
* available. Or for use by subclasses.
/**
* camel_folder_search_set_summary:
- * @search:
+ * @search:
* @summary: An array of CamelMessageInfo pointers.
- *
+ *
* Set the array of summary objects representing the span of the search.
*
* If this is not set, then a subclass must provide the functions
/**
* camel_folder_search_set_body_index:
- * @search:
- * @index:
- *
+ * @search:
+ * @index:
+ *
* Set the index representing the contents of all messages
* in this folder. If this is not set, then the folder implementation
* should sub-class the CamelFolderSearch and provide its own
/**
* camel_folder_search_execute_expression:
- * @search:
- * @expr:
- * @ex:
- *
+ * @search:
+ * @expr:
+ * @ex:
+ *
* Execute the search expression @expr, returning an array of
* all matches as a GPtrArray of uid's of matching messages.
*
*
* TODO: The interface should probably return summary items instead
* (since they are much more useful to any client).
- *
+ *
* Return value: A GPtrArray of strings of all matching messages.
* This must only be freed by camel_folder_search_free_result.
**/
/**
* camel_folder_search_search:
- * @search:
- * @expr:
+ * @search:
+ * @expr:
* @uids: to search against, NULL for all uid's.
- * @ex:
- *
+ * @ex:
+ *
* Run a search. Search must have had Folder already set on it, and
* it must implement summaries.
- *
- * Return value:
+ *
+ * Return value:
**/
GPtrArray *
camel_folder_search_search(CamelFolderSearch *search, const char *expr, GPtrArray *uids, CamelException *ex)
search_header_exists (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
{
ESExpResult *r;
-
+
r(printf ("executing header-exists\n"));
-
+
if (search->current) {
r = e_sexp_result_new(f, ESEXP_RES_BOOL);
if (argc == 1 && argv[0]->type == ESEXP_RES_STRING)
r->value.bool = camel_medium_get_header(CAMEL_MEDIUM(search->current), argv[0]->value.string) != NULL;
-
+
} else {
r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
r->value.ptrarray = g_ptr_array_new();
}
-
+
return r;
}
int i;
/* we can have a maximum of 32 words, as we use it as the AND mask */
-
+
wc = camel_index_words(search->body_index);
if (wc) {
while ((word = camel_index_cursor_next(wc))) {
CamelDataWrapper *containee;
int truth = FALSE;
int parts, i;
-
+
containee = camel_medium_get_content_object (CAMEL_MEDIUM (object));
-
+
if (containee == NULL)
return FALSE;
-
+
/* using the object types is more accurate than using the mime/types */
if (CAMEL_IS_MULTIPART (containee)) {
parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
return TRUE;
}
}
-
+
camel_object_unref (mem);
}
-
+
return truth;
}
for (i=0;i<indexed->len;i++) {
const char *uid = g_ptr_array_index(indexed, i);
-
+
if (match_words_message(search->folder, uid, words, ex))
g_ptr_array_add(matches, (char *)uid);
}
-
+
g_ptr_array_free(indexed, TRUE);
} else {
GPtrArray *v = search->summary_set?search->summary_set:search->summary;
for (i=0;i<v->len;i++) {
CamelMessageInfo *info = g_ptr_array_index(v, i);
const char *uid = camel_message_info_uid(info);
-
+
if (match_words_message(search->folder, uid, words, ex))
g_ptr_array_add(matches, (char *)uid);
}
ESExpResult *r;
struct _glib_sux_donkeys lambdafoo;
- if (search->current) {
+ if (search->current) {
int truth = FALSE;
if (argc == 1 && argv[0]->value.string[0] == 0) {
search_system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search)
{
ESExpResult *r;
-
+
r(printf ("executing system-flag\n"));
-
+
if (search->current) {
gboolean truth = FALSE;
-
+
if (argc == 1)
truth = camel_system_flag_get (camel_message_info_flags(search->current), argv[0]->value.string);
-
+
r = e_sexp_result_new(f, ESEXP_RES_BOOL);
r->value.bool = truth;
} else {
r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
r->value.ptrarray = g_ptr_array_new ();
}
-
+
return r;
}
{
const char *value = NULL;
ESExpResult *r;
-
+
r(printf("executing user-tag\n"));
-
+
if (argc == 1)
value = camel_message_info_user_tag(search->current, argv[0]->value.string);
-
+
r = e_sexp_result_new(f, ESEXP_RES_STRING);
r->value.string = g_strdup (value ? value : "");
-
+
return r;
}
search_get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s)
{
ESExpResult *r;
-
+
r(printf("executing get-size\n"));
-
+
/* are we inside a match-all? */
if (s->current) {
r = e_sexp_result_new (f, ESEXP_RES_INT);
r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR);
r->value.ptrarray = g_ptr_array_new ();
}
-
+
return r;
}
/* (header-contains "headername" "string1" ...) List of matches, or true if in single-message mode */
ESExpResult * (*header_contains)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (header-matches "headername" "string") */
ESExpResult * (*header_matches)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (header-starts-with "headername" "string") */
ESExpResult * (*header_starts_with)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (header-ends-with "headername" "string") */
ESExpResult * (*header_ends_with)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (header-exists "headername") */
ESExpResult * (*header_exists)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (user-flag "flagname" "flagname" ...) If one of user-flag set */
ESExpResult * (*user_flag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
/* (user-tag "flagname") Returns the value of a user tag. Can only be used in match-all */
ESExpResult * (*user_tag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (system-flag "flagname") Returns the value of a system flag. Can only be used in match-all */
ESExpResult * (*system_flag)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
+
/* (get-sent-date) Retrieve the date that the message was sent on as a time_t */
ESExpResult * (*get_sent_date)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
s->messages = g_ptr_array_new();
s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
-
+
p->summary_lock = g_mutex_new();
p->io_lock = g_mutex_new();
p->filter_lock = g_mutex_new();
s->meta_summary = g_malloc0(sizeof(CamelFolderMetaSummary));
/* Default is 20, any implementor having UIDs that has length
- exceeding 20, has to override this value
+ exceeding 20, has to override this value
*/
s->meta_summary->uid_len = 20;
}
/* Freeing memory occupied by meta-summary-header */
g_free(s->meta_summary->path);
g_free(s->meta_summary);
-
+
g_mutex_free(p->summary_lock);
g_mutex_free(p->io_lock);
g_mutex_free(p->filter_lock);
g_mutex_free(p->alloc_lock);
g_mutex_free(p->ref_lock);
-
+
g_free(p);
}
camel_folder_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (), "CamelFolderSummary",
sizeof (CamelFolderSummary),
(CamelObjectInitFunc) camel_folder_summary_init,
(CamelObjectFinalizeFunc) camel_folder_summary_finalize);
}
-
+
return type;
}
* @folder: parent #CamelFolder object
*
* Create a new #CamelFolderSummary object.
- *
+ *
* Returns a new #CamelFolderSummary object
**/
CamelFolderSummary *
* camel_folder_summary_set_filename:
* @summary: a #CamelFolderSummary object
* @filename: a filename
- *
+ *
* Set the filename where the summary will be loaded to/saved from.
**/
void
* camel_folder_summary_set_index:
* @summary: a #CamelFolderSummary object
* @index: a #CamelIndex
- *
+ *
* Set the index used to index body content. If the index is %NULL, or
* not set (the default), no indexing of body content will take place.
*
* camel_folder_summary_set_build_content:
* @summary: a #CamelFolderSummary object
* @state: to build or not to build the content
- *
+ *
* Set a flag to tell the summary to build the content info summary
* (#CamelMessageInfo.content). The default is not to build content
* info summaries.
/**
* camel_folder_summary_count:
* @summary: a #CamelFolderSummary object
- *
+ *
* Get the number of summary items stored in this summary.
- *
+ *
* Returns the number of items in the summary
**/
int
* camel_folder_summary_index:
* @summary: a #CamelFolderSummary object
* @index: item index
- *
+ *
* Retrieve a summary item by index number.
*
* A referenced to the summary item is returned, which may be
* ref'd or free'd as appropriate.
- *
+ *
* Returns the summary item, or %NULL if @index is out of range
**/
CamelMessageInfo *
/**
* camel_folder_summary_array:
* @summary: a #CamelFolderSummary object
- *
+ *
* Obtain a copy of the summary array. This is done atomically,
* so cannot contain empty entries.
*
CamelMessageInfo *info;
GPtrArray *res = g_ptr_array_new();
int i;
-
+
CAMEL_SUMMARY_LOCK(s, summary_lock);
CAMEL_SUMMARY_LOCK(s, ref_lock);
* camel_folder_summary_array_free:
* @summary: a #CamelFolderSummary object
* @array: array of #CamelMessageInfo items as returned from #camel_folder_summary_array
- *
+ *
* Free the folder summary array.
**/
void
* camel_folder_summary_uid:
* @summary: a #CamelFolderSummary object
* @uid: a uid
- *
+ *
* Retrieve a summary item by uid.
*
* A referenced to the summary item is returned, which may be
* ref'd or free'd as appropriate.
- *
+ *
* Returns the summary item, or %NULL if the uid @uid is not available
**/
CamelMessageInfo *
/**
* camel_folder_summary_next_uid:
* @summary: a #CamelFolderSummary object
- *
+ *
* Generate a new unique uid value as an integer. This
* may be used to create a unique sequence of numbers.
- *
+ *
* Returns the next unique uid value
**/
guint32
* @summary: a #CamelFolderSummary object
* @uid: The next minimum uid to assign. To avoid clashing
* uid's, set this to the uid of a given messages + 1.
- *
+ *
* Set the next minimum uid available. This can be used to
* ensure new uid's do not clash with existing uid's.
**/
}
CAMEL_SUMMARY_UNLOCK(s, io_lock);
-
+
if (fclose (in) != 0)
return -1;
error:
if (errno != EINVAL)
g_warning ("Cannot load summary file: `%s': %s", s->summary_path, g_strerror (errno));
-
+
CAMEL_SUMMARY_UNLOCK(s, io_lock);
fclose (in);
s->flags |= ~CAMEL_SUMMARY_DIRTY;
if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->content_info_save (s, out, ci) == -1)
return -1;
-
+
if (camel_file_util_encode_uint32 (out, my_list_size ((struct _node **)&ci->childs)) == -1)
return -1;
-
+
part = ci->childs;
while (part) {
if (perform_content_info_save (s, out, part) == -1)
return -1;
part = part->next;
}
-
+
return 0;
}
/**
* camel_folder_summary_save:
* @summary: a #CamelFolderSummary object
- *
+ *
* Writes the summary to disk. The summary is only written if changes
* have occured.
- *
+ *
* Returns %0 on success or %-1 on fail
**/
int
g_assert(s->message_info_size >= sizeof(CamelMessageInfoBase));
- if (s->summary_path == NULL
+ if (s->summary_path == NULL
|| s->meta_summary->path == NULL
|| (s->flags & CAMEL_SUMMARY_DIRTY) == 0)
return 0;
}
/* Meta summary code */
- /* This meta summary will be used by beagle in order to
- quickly pass through the actual summary file, which
+ /* This meta summary will be used by beagle in order to
+ quickly pass through the actual summary file, which
is quite time consuming otherwise.
*/
/* FIXME: Merge meta-summary and summary */
if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_save(s, out) == -1)
goto exception;
-
+
if (summary_meta_header_save(s, out_meta) == -1)
goto exception;
mi = s->messages->pdata[i];
if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->meta_message_info_save (s, out_meta, out, mi) == -1)
goto exception;
-
+
if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->message_info_save (s, out, mi) == -1)
goto exception;
goto exception;
}
}
-
+
/* FIXME: Can't we use the above "fd" variables, instead of fileno()? */
if (fflush (out) != 0 || fsync (fileno (out)) == -1)
goto exception;
-
+
if (fflush (out_meta) != 0 || fsync (fileno (out_meta)) == -1)
goto exception;
fclose (out_meta);
CAMEL_SUMMARY_UNLOCK(s, io_lock);
-
+
#ifdef G_OS_WIN32
g_unlink(s->summary_path);
#endif
/**
* camel_folder_summary_header_load:
* @summary: a #CamelFolderSummary object
- *
+ *
* Only load the header information from the summary,
* keep the rest on disk. This should only be done on
* a fresh summary object.
- *
+ *
* Returns %0 on success or %-1 on fail
**/
int
ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in);
ret = summary_meta_header_load(s, in_meta);
CAMEL_SUMMARY_UNLOCK(s, io_lock);
-
+
fclose(in);
fclose(in_meta);
s->flags &= ~CAMEL_SUMMARY_DIRTY;
* camel_folder_summary_add:
* @summary: a #CamelFolderSummary object
* @info: a #CamelMessageInfo
- *
+ *
* Adds a new @info record to the summary. If @info->uid is %NULL,
* then a new uid is automatically re-assigned by calling
* #camel_folder_summary_next_uid_string.
* camel_folder_summary_add_from_header:
* @summary: a #CamelFolderSummary object
* @headers: rfc822 headers
- *
+ *
* Build a new info record based on a set of headers, and add it to
* the summary.
*
* Note that this function should not be used if build_content_info
* has been specified for this summary.
- *
+ *
* Returns the newly added record
**/
CamelMessageInfo *
* camel_folder_summary_add_from_parser:
* @summary: a #CamelFolderSummary object
* @parser: a #CamelMimeParser object
- *
+ *
* Build a new info record based on the current position of a #CamelMimeParser.
*
* The parser should be positioned before the start of the message to summarise.
* This function may be used if build_contnet_info or an index has been
* specified for the summary.
- *
+ *
* Returns the newly added record
**/
CamelMessageInfo *
* camel_folder_summary_add_from_message:
* @summary: a #CamelFolderSummary object
* @message: a #CamelMimeMessage object
- *
+ *
* Add a summary item from an existing message.
- *
+ *
* Returns the newly added record
**/
CamelMessageInfo *
* camel_folder_summary_info_new_from_header:
* @summary: a #CamelFolderSummary object
* @headers: rfc822 headers
- *
+ *
* Create a new info record from a header.
*
* Returns the newly allocated record which must be freed with
* camel_folder_summary_info_new_from_parser:
* @summary: a #CamelFolderSummary object
* @parser: a #CamelMimeParser object
- *
+ *
* Create a new info record from a parser. If the parser cannot
* determine a uid, then none will be assigned.
*
* camel_folder_summary_info_new_from_message:
* @summary: a #CamelFodlerSummary object
* @message: a #CamelMimeMessage object
- *
+ *
* Create a summary item from a message.
- *
+ *
* Returns the newly allocated record which must be freed using
* #camel_message_info_free
**/
* camel_folder_summary_content_info_free:
* @summary: a #CamelFolderSummary object
* @ci: a #CamelMessageContentInfo
- *
+ *
* Free the content info @ci, and all associated memory.
**/
void
/**
* camel_folder_summary_touch:
* @summary: a #CamelFolderSummary object
- *
+ *
* Mark the summary as changed, so that a save will force it to be
* written back to disk.
**/
/**
* camel_folder_summary_clear:
* @summary: a #CamelFolderSummary object
- *
+ *
* Empty the summary contents.
**/
void
* camel_folder_summary_remove:
* @summary: a #CamelFolderSummary object
* @info: a #CamelMessageInfo
- *
+ *
* Remove a specific @info record from the summary.
**/
void
s->flags |= CAMEL_SUMMARY_DIRTY;
s->meta_summary->msg_expunged = TRUE;
CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
+
camel_message_info_free(info);
}
* camel_folder_summary_remove_uid:
* @summary: a #CamelFolderSummary object
* @uid: a uid
- *
+ *
* Remove a specific info record from the summary, by @uid.
**/
void
* camel_folder_summary_remove_index:
* @summary: a #CamelFolderSummary object
* @index: record index
- *
+ *
* Remove a specific info record from the summary, by index.
**/
void
* @summary: a #CamelFolderSummary object
* @start: initial index
* @end: last index to remove
- *
+ *
* Removes an indexed range of info records.
**/
void
* camel_folder_summary_encode_token:
* @out: output FILE pointer
* @str: string token to encode
- *
+ *
* Encode a string value, but use tokenisation and compression
* to reduce the size taken for common mailer words. This
* can still be used to encode normal strings as well.
- *
+ *
* Returns %0 on success or %-1 on fail
**/
int
* camel_folder_summary_decode_token:
* @in: input FILE pointer
* @str: string pointer to hold the decoded result
- *
+ *
* Decode a token value.
- *
+ *
* Returns %0 on success or %-1 on fail
**/
int
guint32 len;
io(printf("Decode token ...\n"));
-
+
if (camel_file_util_decode_uint32(in, &len) == -1) {
io(printf ("Could not decode token from file"));
*str = NULL;
|| camel_file_util_decode_uint32(in, &s->meta_summary->uid_len) == -1) {
return -1;
}
-
+
return 0;
}
/**
* camel_folder_summary_content_info_new:
* @summary: a #CamelFolderSummary object
- *
+ *
* Allocate a new #CamelMessageContentInfo, suitable for adding
* to this summary.
- *
+ *
* Returns a newly allocated #CamelMessageContentInfo
**/
CamelMessageContentInfo *
&& (charset = camel_content_type_param(ct, "charset"))
&& (g_ascii_strcasecmp(charset, "us-ascii") == 0))
charset = NULL;
-
+
charset = charset ? e_iconv_charset_name (charset) : NULL;
-
+
subject = summary_format_string(h, "subject", charset);
from = summary_format_address(h, "from", charset);
to = summary_format_address(h, "to", charset);
if (ct)
camel_content_type_unref(ct);
-
+
mi->subject = camel_pstring_add (subject, TRUE);
mi->from = camel_pstring_add (from, TRUE);
mi->to = camel_pstring_add (to, TRUE);
mi->cc = camel_pstring_add (cc, TRUE);
mi->mlist = camel_pstring_add (mlist, TRUE);
-
+
mi->user_flags = NULL;
mi->user_tags = NULL;
mi->date_sent = camel_header_decode_date(camel_header_raw_find(&h, "date", NULL), NULL);
memcpy(mi->message_id.id.hash, digest, sizeof(mi->message_id.id.hash));
g_free(msgid);
}
-
+
/* decode our references and in-reply-to headers */
refs = camel_header_references_decode (camel_header_raw_find (&h, "references", NULL));
irt = camel_header_references_inreplyto_decode (camel_header_raw_find (&h, "in-reply-to", NULL));
/* The References field is populated from the ``References'' and/or ``In-Reply-To''
headers. If both headers exist, take the first thing in the In-Reply-To header
that looks like a Message-ID, and append it to the References header. */
-
+
if (refs)
irt->next = refs;
-
+
refs = irt;
}
-
+
count = camel_header_references_list_size(&refs);
mi->references = g_malloc(sizeof(*mi->references) + ((count-1) * sizeof(mi->references->references[0])));
count = 0;
camel_file_util_decode_string(in, &to);
camel_file_util_decode_string(in, &cc);
camel_file_util_decode_string(in, &mlist);
-
+
mi->uid = uid;
mi->subject = camel_pstring_add (subject, TRUE);
mi->from = camel_pstring_add (from, TRUE);
mi->to = camel_pstring_add (to, TRUE);
mi->cc = camel_pstring_add (cc, TRUE);
mi->mlist = camel_pstring_add (mlist, TRUE);
-
+
mi->content = NULL;
camel_file_util_decode_fixed_int32(in, &mi->message_id.id.part.hi);
time (×tamp);
offset = ftell (out);
/* FIXME: errno check after ftell */
-
+
camel_file_util_encode_time_t(out_meta, timestamp);
camel_file_util_encode_fixed_string(out_meta, camel_message_info_uid(mi), s->meta_summary->uid_len);
camel_file_util_encode_uint32(out_meta, mi->flags);
- camel_file_util_encode_off_t(out_meta, offset);
+ camel_file_util_encode_off_t(out_meta, offset);
return ferror(out);
}
{
CamelMessageContentInfo *ci;
const char *charset;
-
+
ci = camel_folder_summary_content_info_new (s);
-
+
charset = e_iconv_locale_charset ();
ci->id = camel_header_msgid_decode (camel_header_raw_find (&h, "content-id", NULL));
ci->description = camel_header_decode_string (camel_header_raw_find (&h, "content-description", NULL), charset);
io(printf("Loading content info\n"));
ci = camel_folder_summary_content_info_new(s);
-
+
camel_folder_summary_decode_token(in, &type);
camel_folder_summary_decode_token(in, &subtype);
ct = camel_content_type_new(type, subtype);
/* start of this part */
state = camel_mime_parser_step(mp, &buffer, &len);
-
+
if (s->build_content)
info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_parser(s, mp);
const char *charset;
d(printf("generating index:\n"));
-
+
encoding = camel_content_transfer_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL));
if (encoding) {
if (!g_ascii_strcasecmp(encoding, "base64")) {
camel_mime_filter_reset((CamelMimeFilter *)p->filter_html);
html_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_html);
}
-
+
/* and this filter actually does the indexing */
idx_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_index);
}
if (s->build_content)
info = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_message(s, object);
-
+
containee = camel_medium_get_content_object(CAMEL_MEDIUM(object));
if (containee == NULL)
* camel_flag_get:
* @list: the address of a #CamelFlag list
* @name: name of the flag to get
- *
+ *
* Find the state of the flag @name in @list.
- *
+ *
* Returns the state of the flag (%TRUE or %FALSE)
**/
gboolean
* @list: the address of a #CamelFlag list
* @name: name of the flag to set or change
* @value: the value to set on the flag
- *
+ *
* Set the state of a flag @name in the list @list to @value.
*
* Returns %TRUE if the value of the flag has been changed or %FALSE
/**
* camel_flag_list_size:
* @list: the address of a #CamelFlag list
- *
+ *
* Get the length of the flag list.
- *
+ *
* Returns the number of flags in the list
**/
int
/**
* camel_flag_list_free:
* @list: the address of a #CamelFlag list
- *
+ *
* Free the memory associated with the flag list @list.
**/
void
* camel_flag_list_copy:
* @to: the address of the #CamelFlag list to copy to
* @from: the address of the #CamelFlag list to copy from
- *
+ *
* Copy a flag list.
- *
+ *
* Returns %TRUE if @to is changed or %FALSE otherwise
**/
gboolean
* @name: name of the tag to get
*
* Find the flag @name in @list and get the value.
- *
+ *
* Returns the value of the flag or %NULL if unset
**/
const char *
* @list: the address of a #CamelTag list
* @name: name of the tag to set
* @value: value to set on the tag
- *
+ *
* Set the tag @name in the tag list @list to @value.
*
* Returns %TRUE if the value on the tag changed or %FALSE otherwise
/**
* camel_tag_list_size:
* @list: the address of a #CamelTag list
- *
+ *
* Get the number of tags present in the tag list @list.
- *
+ *
* Returns the number of tags
**/
int
* camel_tag_list_copy:
* @to: the address of the #CamelTag list to copy to
* @from: the address of the #CamelTag list to copy from
- *
+ *
* Copy a tag list.
- *
+ *
* Returns %TRUE if @to is changed or %FALSE otherwise
**/
gboolean
/**
* camel_tag_list_free:
* @list: the address of a #CamelTag list
- *
+ *
* Free the tag list @list.
**/
void
* camel_system_flag_get:
* @flags: bitwise system flags
* @name: name of the flag to check for
- *
+ *
* Find the state of the flag @name in @flags.
- *
+ *
* Returns %TRUE if the named flag is set or %FALSE otherwise
**/
gboolean
camel_system_flag_get (guint32 flags, const char *name)
{
g_return_val_if_fail (name != NULL, FALSE);
-
+
return flags & camel_system_flag (name);
}
/**
* camel_message_info_ref:
* @info: a #CamelMessageInfo
- *
+ *
* Reference an info.
**/
void
camel_content_info_dump (CamelMessageContentInfo *ci, int depth)
{
char *p;
-
+
p = alloca (depth * 4 + 1);
memset (p, ' ', depth * 4);
p[depth * 4] = 0;
-
+
if (ci == NULL) {
printf ("%s<empty>\n", p);
return;
}
-
+
if (ci->type)
printf ("%scontent-type: %s/%s\n", p, ci->type->type ? ci->type->type : "(null)",
ci->type->subtype ? ci->type->subtype : "(null)");
describe the content structure of the message (if it has any) */
struct _CamelMessageContentInfo {
struct _CamelMessageContentInfo *next;
-
+
struct _CamelMessageContentInfo *childs;
struct _CamelMessageContentInfo *parent;
-
+
CamelContentType *type;
char *id;
char *description;
CAMEL_MESSAGE_DRAFT = 1<<2,
CAMEL_MESSAGE_FLAGGED = 1<<3,
CAMEL_MESSAGE_SEEN = 1<<4,
-
+
/* these aren't really system flag bits, but are convenience flags */
CAMEL_MESSAGE_ATTACHMENTS = 1<<5,
CAMEL_MESSAGE_ANSWERED_ALL = 1<<6,
struct _camel_header_param *headers;
};
-/* probably do this as well, removing CamelFolderChangeInfo and interfaces
+/* probably do this as well, removing CamelFolderChangeInfo and interfaces
typedef struct _CamelChangeInfo CamelChangeInfo;
struct _CamelChangeInfo {
GPtrArray *added;
#include "camel-folder-thread.h"
-#define d(x)
-#define m(x)
+#define d(x)
+#define m(x)
/*#define TIMEIT*/
{
char *s, *p;
CamelFolderThreadNode *scan;
-
+
s = NULL;
c->re = FALSE;
if (c->message)
GHashTable *subject_table = g_hash_table_new(g_str_hash, g_str_equal);
CamelFolderThreadNode *c, *clast, *scan, *container;
- /* gather subject lines */
+ /* gather subject lines */
d(printf("gathering subject lines\n"));
clast = (CamelFolderThreadNode *)cp;
c = clast->next;
const CamelFolderThreadNode *a1 = ((CamelFolderThreadNode **)a)[0];
const CamelFolderThreadNode *b1 = ((CamelFolderThreadNode **)b)[0];
- /* if we have no message, it must be a dummy node, which
+ /* if we have no message, it must be a dummy node, which
also means it must have a child, just use that as the
sort data (close enough?) */
if (a1->message == NULL)
/* remove empty parent nodes */
prune_empty(thread, &head);
-
+
/* find any siblings which missed out - but only if we are allowing threading by subject */
if (thread->subject)
group_root_set (thread, &head);
/**
* camel_folder_thread_messages_new:
- * @folder:
+ * @folder:
* @uids: The subset of uid's to thread. If NULL. then thread all
* uid's in @folder.
* @thread_subject: thread based on subject also
- *
+ *
* Thread a (subset) of the messages in a folder. And sort the result
* in summary order.
*
* If @thread_subject is %TRUE, messages with
* related subjects will also be threaded. The default behaviour is to
* only thread based on message-id.
- *
+ *
* This function is probably to be removed soon.
*
* Return value: A CamelFolderThread contianing a tree of CamelFolderThreadNode's
/**
* camel_folder_thread_messages_unref:
- * @thread:
- *
+ * @thread:
+ *
* Free all memory associated with the thread descriptor @thread.
**/
void
/**
* camel_folder_thread_messages_new_summary:
* @summary: Array of CamelMessageInfo's to thread.
- *
+ *
* Thread a list of MessageInfo's. The summary must remain valid for the
* life of the CamelFolderThread created by this function, and it is upto the
* caller to ensure this.
- *
+ *
* Return value: A CamelFolderThread contianing a tree of CamelFolderThreadNode's
* which represent the threaded structure of the messages.
**/
typedef struct _CamelFolderThread {
guint32 refcount : 31;
guint32 subject : 1;
-
+
struct _CamelFolderThreadNode *tree;
struct _EMemChunk *node_chunks;
CamelFolder *folder;
camel_object_unref (camel_folder->summary);
camel_folder_change_info_free(p->changed_frozen);
-
+
g_static_rec_mutex_free(&p->lock);
g_static_mutex_free(&p->change_lock);
-
+
g_free(p);
}
g_return_if_fail (CAMEL_IS_FOLDER (folder));
CAMEL_FOLDER_REC_LOCK(folder, lock);
-
+
if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED))
CF_CLASS (folder)->sync (folder, expunge, ex);
-
+
CAMEL_FOLDER_REC_UNLOCK(folder, lock);
}
camel_folder_expunge (CamelFolder *folder, CamelException *ex)
{
g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
+
CAMEL_FOLDER_REC_LOCK(folder, lock);
-
+
if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED))
CF_CLASS (folder)->expunge (folder, ex);
-
+
CAMEL_FOLDER_REC_UNLOCK(folder, lock);
}
int count = -1;
g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1);
-
+
camel_object_get(folder, NULL, CAMEL_FOLDER_UNREAD, &count, 0);
return count;
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
_("Unsupported operation: append message: for %s"),
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)));
-
+
w(g_warning ("CamelFolder::append_message not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-
+
return;
}
* camel_folder_free_message_info:
* @folder: a #CamelFolder object
* @info: a #CamelMessageInfo
- *
+ *
* Free (unref) a #CamelMessageInfo, previously obtained with
* #camel_folder_get_message_info.
**/
* camel_folder_ref_message_info:
* @folder: a #CamelFolder object
* @info: a #CamelMessageInfo
- *
+ *
* DEPRECATED: Use #camel_message_info_ref directly.
*
* Ref a #CamelMessageInfo, previously obtained with
{
w(g_warning ("CamelFolder::get_message not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-
+
return NULL;
}
g_ptr_array_set_size(array, count);
for (i = 0, j = 0; i < count; i++) {
CamelMessageInfo *info = camel_folder_summary_index(folder->summary, i);
-
+
if (info) {
array->pdata[j++] = g_strdup (camel_message_info_uid (info));
camel_message_info_free(info);
}
}
-
+
g_ptr_array_set_size (array, j);
-
+
return array;
}
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
_("Unsupported operation: search by expression: for %s"),
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)));
-
+
w(g_warning ("CamelFolder::search_by_expression not implemented for "
"`%s'", camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-
+
return NULL;
}
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
_("Unsupported operation: search by UIDs: for %s"),
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder)));
-
+
w(g_warning ("CamelFolder::search_by_expression not implemented for "
"`%s'", camel_type_to_name (CAMEL_OBJECT_GET_TYPE (folder))));
-
+
return NULL;
}
* camel_folder_search_free:
* @folder: a #CamelFolder object
* @result: search results to free
- *
+ *
* Free the result of a search as gotten by #camel_folder_search or
* #camel_folder_search_by_uids.
**/
-void
+void
camel_folder_search_free (CamelFolder *folder, GPtrArray *result)
{
g_return_if_fail (CAMEL_IS_FOLDER (folder));
{
CamelMimeMessage *msg;
CamelMessageInfo *minfo, *info;
-
+
/* Default implementation. */
-
+
msg = camel_folder_get_message(source, uid, ex);
if (!msg)
return;
camel_folder_free_message_info(source, minfo);
} else
info = camel_message_info_new_from_header(NULL, ((CamelMimePart *)msg)->headers);
-
+
/* we don't want to retain the deleted flag */
camel_message_info_set_flags(info, CAMEL_MESSAGE_DELETED, 0);
-
+
camel_folder_append_message (dest, msg, info, transferred_uid, ex);
camel_object_unref (msg);
-
+
if (delete_original && !camel_exception_is_set (ex))
camel_folder_set_message_flags (source, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, ~0);
-
+
camel_message_info_free (info);
}
g_return_if_fail (CAMEL_IS_FOLDER (source));
g_return_if_fail (CAMEL_IS_FOLDER (dest));
g_return_if_fail (uids != NULL);
-
+
if (source == dest || uids->len == 0) {
/* source and destination folders are the same, or no work to do, do nothing. */
return;
}
-
+
if (source->parent_store == dest->parent_store) {
/* If either folder is a vtrash, we need to use the
* vtrash transfer method.
camel_folder_delete (CamelFolder *folder)
{
g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
+
CAMEL_FOLDER_REC_LOCK (folder, lock);
if (folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) {
CAMEL_FOLDER_REC_UNLOCK (folder, lock);
return;
}
-
+
folder->folder_flags |= CAMEL_FOLDER_HAS_BEEN_DELETED;
-
+
CF_CLASS (folder)->delete (folder);
CAMEL_FOLDER_REC_UNLOCK (folder, lock);
* camel_folder_rename:
* @folder: a #CamelFolder object
* @new: new name for the folder
- *
+ *
* Mark an active folder object as renamed.
*
* NOTE: This is an internal function used by camel stores, no locking
info = folder->priv->changed_frozen;
folder->priv->changed_frozen = camel_folder_change_info_new();
}
-
+
CAMEL_FOLDER_UNLOCK(folder, change_lock);
if (info) {
for (i = 0; i < m->junk->len; i ++) {
CamelMimeMessage *msg = camel_folder_get_message(m->folder, m->junk->pdata[i], NULL);
int pc = 100 * i / m->junk->len;
-
+
camel_operation_progress(NULL, pc);
if (msg) {
notjunk = g_ptr_array_new();
g_ptr_array_add (notjunk, g_strdup (changed->uid_changed->pdata [i]));
}
- /* reset junk learn flag so that we don't process it again*/
+ /* reset junk learn flag so that we don't process it again*/
camel_folder_set_message_flags (folder, changed->uid_changed->pdata [i], CAMEL_MESSAGE_JUNK_LEARN, 0);
}
}
if ((folder->folder_flags & (CAMEL_FOLDER_FILTER_RECENT|CAMEL_FOLDER_FILTER_JUNK))
&& p->uid_filter->len > 0)
driver = camel_session_get_filter_driver(session,
- (folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT)
+ (folder->folder_flags & CAMEL_FOLDER_FILTER_RECENT)
? "incoming":"junktest", NULL);
-
+
if (driver) {
recents = g_ptr_array_new();
for (i = 0; i < p->uid_filter->len; i++)
g_ptr_array_add (recents, g_strdup (p->uid_filter->pdata[i]));
-
+
g_ptr_array_set_size (p->uid_filter, 0);
}
-
+
if (driver || junk || notjunk) {
struct _folder_filter_msg *msg;
/**
* camel_folder_change_info_new:
- *
+ *
* Create a new folder change info structure.
*
* Change info structures are not MT-SAFE and must be
* camel_folder_change_info_add_source:
* @info: a #CamelFolderChangeInfo
* @uid: a uid
- *
+ *
* Add a source uid for generating a changeset.
**/
void
camel_folder_change_info_add_source(CamelFolderChangeInfo *info, const char *uid)
{
struct _CamelFolderChangeInfoPrivate *p;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (p->uid_source == NULL)
p->uid_source = g_hash_table_new(g_str_hash, g_str_equal);
* camel_folder_change_info_add_source_list:
* @info: a #CamelFolderChangeInfo
* @list: a list of uids
- *
+ *
* Add a list of source uid's for generating a changeset.
**/
void
{
struct _CamelFolderChangeInfoPrivate *p;
int i;
-
+
g_assert(info != NULL);
g_assert(list != NULL);
-
+
p = info->priv;
if (p->uid_source == NULL)
* camel_folder_change_info_add_update:
* @info: a #CamelFolderChangeInfo
* @uid: a uid
- *
+ *
* Add a uid from the updated list, used to generate a changeset diff.
**/
void
struct _CamelFolderChangeInfoPrivate *p;
char *key;
int value;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (p->uid_source == NULL) {
camel_folder_change_info_add_uid(info, uid);
return;
* camel_folder_change_info_add_update_list:
* @info: a #CamelFolderChangeInfo
* @list: a list of uids
- *
+ *
* Add a list of uid's from the updated list.
**/
void
camel_folder_change_info_add_update_list(CamelFolderChangeInfo *info, const GPtrArray *list)
{
int i;
-
+
g_assert(info != NULL);
g_assert(list != NULL);
-
+
for (i=0;i<list->len;i++)
camel_folder_change_info_add_update(info, list->pdata[i]);
}
/**
* camel_folder_change_info_build_diff:
* @info: a #CamelFolderChangeInfo
- *
+ *
* Compare the source uid set to the updated uid set and generate the
* differences into the added and removed lists.
**/
camel_folder_change_info_build_diff(CamelFolderChangeInfo *info)
{
struct _CamelFolderChangeInfoPrivate *p;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (p->uid_source) {
g_hash_table_foreach(p->uid_source, (GHFunc)change_info_remove, info);
g_hash_table_destroy(p->uid_source);
struct _CamelFolderChangeInfoPrivate *p;
GPtrArray *olduids;
char *olduid;
-
+
p = info->priv;
- /* always add to recent, but dont let anyone else know */
+ /* always add to recent, but dont let anyone else know */
if (!g_hash_table_lookup_extended(p->uid_stored, uid, (void **)&olduid, (void **)&olduids)) {
olduid = e_mempool_strdup(p->uid_pool, uid);
}
struct _CamelFolderChangeInfoPrivate *p;
GPtrArray *olduids;
char *olduid;
-
+
p = info->priv;
- /* always add to filter, but dont let anyone else know */
+ /* always add to filter, but dont let anyone else know */
if (!g_hash_table_lookup_extended(p->uid_stored, uid, (void **)&olduid, (void **)&olduids)) {
olduid = e_mempool_strdup(p->uid_pool, uid);
}
* camel_folder_change_info_cat:
* @info: a #CamelFolderChangeInfo to append to
* @src: a #CamelFolderChangeInfo to append from
- *
+ *
* Concatenate one change info onto antoher. Can be used to copy them
* too.
**/
{
g_assert(info != NULL);
g_assert(source != NULL);
-
+
change_info_cat(info, source->uid_added, camel_folder_change_info_add_uid);
change_info_cat(info, source->uid_removed, camel_folder_change_info_remove_uid);
change_info_cat(info, source->uid_changed, camel_folder_change_info_change_uid);
* camel_folder_change_info_add_uid:
* @info: a #CamelFolderChangeInfo
* @uid: a uid
- *
+ *
* Add a new uid to the changeinfo.
**/
void
struct _CamelFolderChangeInfoPrivate *p;
GPtrArray *olduids;
char *olduid;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (g_hash_table_lookup_extended(p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
/* if it was removed then added, promote it to a changed */
/* if it was changed then added, leave as changed */
* camel_folder_change_info_remove_uid:
* @info: a #CamelFolderChangeInfo
* @uid: a uid
- *
+ *
* Add a uid to the removed uid list.
**/
void
struct _CamelFolderChangeInfoPrivate *p;
GPtrArray *olduids;
char *olduid;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (g_hash_table_lookup_extended(p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
/* if it was added/changed them removed, then remove it */
if (olduids != info->uid_removed) {
* camel_folder_change_info_change_uid:
* @info: a #CamelFolderChangeInfo
* @uid: a uid
- *
+ *
* Add a uid to the changed uid list.
**/
void
struct _CamelFolderChangeInfoPrivate *p;
GPtrArray *olduids;
char *olduid;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (g_hash_table_lookup_extended(p->uid_stored, uid, (gpointer) &olduid, (gpointer) &olduids)) {
/* if we have it already, leave it as that */
return;
camel_folder_change_info_recent_uid(CamelFolderChangeInfo *info, const char *uid)
{
g_assert(info != NULL);
-
+
change_info_recent_uid(info, uid);
change_info_filter_uid(info, uid);
}
camel_folder_change_info_changed(CamelFolderChangeInfo *info)
{
g_assert(info != NULL);
-
+
return (info->uid_added->len || info->uid_removed->len || info->uid_changed->len || info->uid_recent->len);
}
/**
* camel_folder_change_info_clear:
* @info: a #CamelFolderChangeInfo
- *
+ *
* Empty out the change info; called after changes have been
* processed.
**/
camel_folder_change_info_clear(CamelFolderChangeInfo *info)
{
struct _CamelFolderChangeInfoPrivate *p;
-
+
g_assert(info != NULL);
-
+
p = info->priv;
-
+
g_ptr_array_set_size(info->uid_added, 0);
g_ptr_array_set_size(info->uid_removed, 0);
g_ptr_array_set_size(info->uid_changed, 0);
/**
* camel_folder_change_info_free:
* @info: a #CamelFolderChangeInfo
- *
+ *
* Free memory associated with the folder change info lists.
**/
void
struct _CamelFolderChangeInfoPrivate *p;
g_assert(info != NULL);
-
+
p = info->priv;
-
+
if (p->uid_source)
g_hash_table_destroy(p->uid_source);
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelObjectClass parent_class;
- /* Virtual methods */
+ /* Virtual methods */
void (*refresh_info) (CamelFolder *folder, CamelException *ex);
- void (*sync) (CamelFolder *folder, gboolean expunge,
+ void (*sync) (CamelFolder *folder, gboolean expunge,
CamelException *ex);
const char * (*get_name) (CamelFolder *folder);
CamelStore * (*get_parent_store) (CamelFolder *folder);
- void (*expunge) (CamelFolder *folder,
+ void (*expunge) (CamelFolder *folder,
CamelException *ex);
int (*get_message_count) (CamelFolder *folder);
- void (*append_message) (CamelFolder *folder,
+ void (*append_message) (CamelFolder *folder,
CamelMimeMessage *message,
const CamelMessageInfo *info,
char **appended_uid,
CamelException *ex);
-
+
guint32 (*get_permanent_flags) (CamelFolder *folder);
guint32 (*get_message_flags) (CamelFolder *folder,
const char *uid);
const char *name,
const char *value);
- CamelMimeMessage * (*get_message) (CamelFolder *folder,
- const char *uid,
+ CamelMimeMessage * (*get_message) (CamelFolder *folder,
+ const char *uid,
CamelException *ex);
GPtrArray * (*get_uids) (CamelFolder *folder);
GPtrArray **transferred_uids,
gboolean delete_originals,
CamelException *ex);
-
+
void (*delete) (CamelFolder *folder);
void (*rename) (CamelFolder *folder, const char *newname);
-
+
void (*freeze) (CamelFolder *folder);
void (*thaw) (CamelFolder *folder);
gboolean (*is_frozen) (CamelFolder *folder);
const char *full_name,
const char *name);
-void camel_folder_refresh_info (CamelFolder *folder,
+void camel_folder_refresh_info (CamelFolder *folder,
CamelException *ex);
-void camel_folder_sync (CamelFolder *folder,
- gboolean expunge,
+void camel_folder_sync (CamelFolder *folder,
+ gboolean expunge,
CamelException *ex);
CamelStore * camel_folder_get_parent_store (CamelFolder *folder);
/* delete operations */
-void camel_folder_expunge (CamelFolder *folder,
+void camel_folder_expunge (CamelFolder *folder,
CamelException *ex);
/* message manipulation */
-void camel_folder_append_message (CamelFolder *folder,
+void camel_folder_append_message (CamelFolder *folder,
CamelMimeMessage *message,
const CamelMessageInfo *info,
char **appended_uid,
GPtrArray *array);
/* uid based access operations */
-CamelMimeMessage * camel_folder_get_message (CamelFolder *folder,
- const char *uid,
+CamelMimeMessage * camel_folder_get_message (CamelFolder *folder,
+ const char *uid,
CamelException *ex);
#define camel_folder_delete_message(folder, uid) \
camel_folder_set_message_flags (folder, uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN)
#include "camel-stream-fs.h"
#include "camel-stream-mem.h"
-#define d(x)
+#define d(x)
#ifdef GPG_LOG
static int logid;
{
CamelCipherContext *cipher;
CamelGpgContext *ctx;
-
+
g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
-
+
ctx = (CamelGpgContext *) camel_object_new (camel_gpg_context_get_type ());
-
+
cipher = (CamelCipherContext *) ctx;
cipher->session = session;
camel_object_ref (session);
-
+
return cipher;
}
camel_gpg_context_set_always_trust (CamelGpgContext *ctx, gboolean always_trust)
{
g_return_if_fail (CAMEL_IS_GPG_CONTEXT (ctx));
-
+
ctx->always_trust = always_trust;
}
case CAMEL_CIPHER_HASH_HAVAL5160:
return "pgp-haval-5-160";
}
-
+
return NULL;
}
else if (!strcmp (id, "haval-5-160"))
return CAMEL_CIPHER_HASH_HAVAL5160;
}
-
+
return CAMEL_CIPHER_HASH_DEFAULT;
}
CamelSession *session;
GHashTable *userid_hint;
pid_t pid;
-
+
char *userid;
char *sigfile;
GPtrArray *recipients;
CamelCipherHash hash;
-
+
int stdin_fd;
int stdout_fd;
int stderr_fd;
int status_fd;
int passwd_fd; /* only needed for sign/decrypt */
-
+
/* status-fd buffer */
unsigned char *statusbuf;
unsigned char *statusptr;
unsigned int statusleft;
-
+
char *need_id;
char *passwd;
-
+
CamelStream *istream;
CamelStream *ostream;
-
+
GByteArray *diagbuf;
CamelStream *diagnostics;
-
+
int exit_status;
-
+
unsigned int exited:1;
unsigned int complete:1;
unsigned int seen_eof1:1;
unsigned int armor:1;
unsigned int need_passwd:1;
unsigned int send_passwd:1;
-
+
unsigned int bad_passwds:2;
-
+
unsigned int hadsig:1;
unsigned int badsig:1;
unsigned int errsig:1;
unsigned int nopubkey:1;
unsigned int nodata:1;
unsigned int trust:3;
-
+
unsigned int diagflushed:1;
-
+
unsigned int utf8:1;
-
+
unsigned int padding:10;
};
struct _GpgCtx *gpg;
const char *charset;
CamelStream *stream;
-
+
gpg = g_new (struct _GpgCtx, 1);
gpg->mode = GPG_CTX_MODE_SIGN;
gpg->session = session;
gpg->pid = (pid_t) -1;
gpg->exit_status = 0;
gpg->exited = FALSE;
-
+
gpg->userid = NULL;
gpg->sigfile = NULL;
gpg->recipients = NULL;
gpg->hash = CAMEL_CIPHER_HASH_DEFAULT;
gpg->always_trust = FALSE;
gpg->armor = FALSE;
-
+
gpg->stdin_fd = -1;
gpg->stdout_fd = -1;
gpg->stderr_fd = -1;
gpg->status_fd = -1;
gpg->passwd_fd = -1;
-
+
gpg->statusbuf = g_malloc (128);
gpg->statusptr = gpg->statusbuf;
gpg->statusleft = 128;
-
+
gpg->bad_passwds = 0;
gpg->need_passwd = FALSE;
gpg->send_passwd = FALSE;
gpg->need_id = NULL;
gpg->passwd = NULL;
-
+
gpg->nodata = FALSE;
gpg->hadsig = FALSE;
gpg->badsig = FALSE;
gpg->validsig = FALSE;
gpg->nopubkey = FALSE;
gpg->trust = GPG_TRUST_NONE;
-
+
gpg->istream = NULL;
gpg->ostream = NULL;
-
+
stream = camel_stream_mem_new ();
gpg->diagbuf = CAMEL_STREAM_MEM (stream)->buffer;
gpg->diagflushed = FALSE;
-
+
if ((charset = e_iconv_locale_charset ()) && g_ascii_strcasecmp (charset, "UTF-8") != 0) {
CamelMimeFilterCharset *filter;
CamelStreamFilter *fstream;
-
+
gpg->utf8 = FALSE;
-
+
if ((filter = camel_mime_filter_charset_new_convert (charset, "UTF-8"))) {
fstream = camel_stream_filter_new_with_stream (stream);
camel_stream_filter_add (fstream, (CamelMimeFilter *) filter);
camel_object_unref (filter);
camel_object_unref (stream);
-
+
stream = (CamelStream *) fstream;
}
} else {
gpg->utf8 = TRUE;
}
-
+
gpg->diagnostics = stream;
-
+
return gpg;
}
{
if (gpg->mode != GPG_CTX_MODE_ENCRYPT && gpg->mode != GPG_CTX_MODE_EXPORT)
return;
-
+
if (!gpg->recipients)
gpg->recipients = g_ptr_array_new ();
-
+
g_ptr_array_add (gpg->recipients, g_strdup (keyid));
}
camel_stream_flush (gpg->diagnostics);
if (gpg->diagbuf->len == 0)
return NULL;
-
+
g_byte_array_append (gpg->diagbuf, (guchar *) "", 1);
}
-
+
return (const char *) gpg->diagbuf->data;
}
if (gpg->session)
camel_object_unref (gpg->session);
-
+
g_hash_table_foreach (gpg->userid_hint, userid_hint_free, NULL);
g_hash_table_destroy (gpg->userid_hint);
-
+
g_free (gpg->userid);
-
+
g_free (gpg->sigfile);
-
+
if (gpg->recipients) {
for (i = 0; i < gpg->recipients->len; i++)
g_free (gpg->recipients->pdata[i]);
-
+
g_ptr_array_free (gpg->recipients, TRUE);
}
-
+
if (gpg->stdin_fd != -1)
close (gpg->stdin_fd);
if (gpg->stdout_fd != -1)
close (gpg->status_fd);
if (gpg->passwd_fd != -1)
close (gpg->passwd_fd);
-
+
g_free (gpg->statusbuf);
-
+
g_free (gpg->need_id);
-
+
if (gpg->passwd) {
memset (gpg->passwd, 0, strlen (gpg->passwd));
g_free (gpg->passwd);
}
-
+
if (gpg->istream)
camel_object_unref (gpg->istream);
-
+
if (gpg->ostream)
camel_object_unref (gpg->ostream);
-
+
camel_object_unref (gpg->diagnostics);
-
+
g_free (gpg);
}
GPtrArray *argv;
char *buf;
int i;
-
+
argv = g_ptr_array_new ();
g_ptr_array_add (argv, "gpg");
-
+
g_ptr_array_add (argv, "--verbose");
g_ptr_array_add (argv, "--no-secmem-warning");
g_ptr_array_add (argv, "--no-greeting");
g_ptr_array_add (argv, "--batch");
g_ptr_array_add (argv, "--yes");
}
-
+
*sfd = buf = g_strdup_printf ("--status-fd=%d", status_fd);
g_ptr_array_add (argv, buf);
-
+
if (passwd_fd != -1) {
*pfd = buf = g_strdup_printf ("--command-fd=%d", passwd_fd);
g_ptr_array_add (argv, buf);
}
-
+
switch (gpg->mode) {
case GPG_CTX_MODE_SIGN:
g_ptr_array_add (argv, "--sign");
g_ptr_array_add (argv, gpg->recipients->pdata[i]);
break;
}
-
+
g_ptr_array_add (argv, NULL);
-
+
return argv;
}
int i, maxfd, errnosave, fds[10];
GPtrArray *argv;
int flags;
-
+
for (i = 0; i < 10; i++)
fds[i] = -1;
-
+
maxfd = gpg->need_passwd ? 10 : 8;
for (i = 0; i < maxfd; i += 2) {
if (pipe (fds + i) == -1)
goto exception;
}
-
+
argv = gpg_ctx_get_argv (gpg, fds[7], &status_fd, fds[8], &passwd_fd);
-
+
if (!(gpg->pid = fork ())) {
/* child process */
-
+
if ((dup2 (fds[0], STDIN_FILENO) < 0 ) ||
(dup2 (fds[3], STDOUT_FILENO) < 0 ) ||
(dup2 (fds[5], STDERR_FILENO) < 0 )) {
_exit (255);
}
-
+
/* Dissociate from camel's controlling terminal so
* that gpg won't be able to read from it.
*/
setsid ();
-
+
maxfd = sysconf (_SC_OPEN_MAX);
/* Loop over all fds. */
for (i = 3; i < maxfd; i++) {
if (i != fds[7] && i != fds[8])
fcntl (i, F_SETFD, FD_CLOEXEC);
}
-
+
/* run gpg */
execvp ("gpg", (char **) argv->pdata);
_exit (255);
g_free (passwd_fd);
goto exception;
}
-
+
g_ptr_array_free (argv, TRUE);
g_free (status_fd);
g_free (passwd_fd);
-
+
/* Parent */
close (fds[0]);
gpg->stdin_fd = fds[1];
flags = fcntl (gpg->passwd_fd, F_GETFL);
fcntl (gpg->passwd_fd, F_SETFL, flags | O_NONBLOCK);
}
-
+
flags = fcntl (gpg->stdin_fd, F_GETFL);
fcntl (gpg->stdin_fd, F_SETFL, flags | O_NONBLOCK);
-
+
flags = fcntl (gpg->stdout_fd, F_GETFL);
fcntl (gpg->stdout_fd, F_SETFL, flags | O_NONBLOCK);
-
+
flags = fcntl (gpg->stderr_fd, F_GETFL);
fcntl (gpg->stderr_fd, F_SETFL, flags | O_NONBLOCK);
-
+
flags = fcntl (gpg->status_fd, F_GETFL);
fcntl (gpg->status_fd, F_SETFL, flags | O_NONBLOCK);
-
+
return 0;
-
+
exception:
-
+
errnosave = errno;
-
+
for (i = 0; i < 10; i++) {
if (fds[i] != -1)
close (fds[i]);
}
-
+
errno = errnosave;
#else
/* FIXME: Port me */
errno = EINVAL;
#endif
-
+
return -1;
}
next_token (const char *in, char **token)
{
const char *start, *inptr = in;
-
+
while (*inptr == ' ')
inptr++;
-
+
if (*inptr == '\0' || *inptr == '\n') {
if (token)
*token = NULL;
return inptr;
}
-
+
start = inptr;
while (*inptr && *inptr != ' ' && *inptr != '\n')
inptr++;
-
+
if (token)
*token = g_strndup (start, inptr - start);
-
+
return inptr;
}
g_free(message);
return -1;
}
-
+
status += 9;
-
+
if (!strncmp ((char *) status, "USERID_HINT ", 12)) {
char *hint, *user;
-
+
status += 12;
status = (const unsigned char *) next_token ((char *) status, &hint);
if (!hint) {
_("Failed to parse gpg userid hint."));
return -1;
}
-
+
if (g_hash_table_lookup (gpg->userid_hint, hint)) {
/* we already have this userid hint... */
g_free (hint);
goto recycle;
}
-
+
if (gpg->utf8 || !(user = g_locale_to_utf8 ((gchar *) status, -1, &nread, &nwritten, NULL)))
user = g_strdup ((gchar *) status);
-
+
g_strstrip (user);
-
+
g_hash_table_insert (gpg->userid_hint, hint, user);
} else if (!strncmp ((char *) status, "NEED_PASSPHRASE ", 16)) {
char *userid;
-
+
status += 16;
-
+
status = (const unsigned char *) next_token ((char *) status, &userid);
if (!userid) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to parse gpg passphrase request."));
return -1;
}
-
+
g_free (gpg->need_id);
gpg->need_id = userid;
} else if (!strncmp ((char *) status, "NEED_PASSPHRASE_PIN ", 20)) {
char *userid;
-
+
status += 20;
-
+
status = (const unsigned char *) next_token ((char *) status, &userid);
if (!userid) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to parse gpg passphrase request."));
return -1;
}
-
+
g_free (gpg->need_id);
gpg->need_id = userid;
} else if (!strncmp ((char *) status, "GET_HIDDEN ", 11)) {
const char *name = NULL;
char *prompt, *passwd;
guint32 flags;
-
+
status += 11;
-
+
if (gpg->need_id && !(name = g_hash_table_lookup (gpg->userid_hint, gpg->need_id)))
name = gpg->need_id;
else if (!name)
name = "";
-
+
if (!strncmp ((char *) status, "passphrase.pin.ask", 18)) {
prompt = g_markup_printf_escaped (
_("You need a PIN to unlock the key for your\n"
g_free (prompt);
return -1;
}
-
+
flags = CAMEL_SESSION_PASSWORD_SECRET | CAMEL_SESSION_PASSPHRASE;
if ((passwd = camel_session_get_password (gpg->session, NULL, NULL, prompt, gpg->need_id, flags, ex))) {
if (!gpg->utf8) {
char *opasswd = passwd;
-
+
if ((passwd = g_locale_to_utf8 (passwd, -1, &nread, &nwritten, NULL))) {
memset (opasswd, 0, strlen (opasswd));
g_free (opasswd);
passwd = opasswd;
}
}
-
+
gpg->passwd = g_strdup_printf ("%s\n", passwd);
memset (passwd, 0, strlen (passwd));
g_free (passwd);
-
+
gpg->send_passwd = TRUE;
} else {
if (!camel_exception_is_set (ex))
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled."));
return -1;
}
-
+
g_free (prompt);
} else if (!strncmp ((char *) status, "GOOD_PASSPHRASE", 15)) {
gpg->bad_passwds = 0;
} else if (!strncmp ((char *) status, "BAD_PASSPHRASE", 14)) {
gpg->bad_passwds++;
-
+
camel_session_forget_password (gpg->session, NULL, NULL, gpg->need_id, ex);
-
+
if (gpg->bad_passwds == 3) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Failed to unlock secret key: 3 bad passphrases given."));
break;
}
}
-
+
recycle:
-
+
/* recycle our statusbuf by moving inptr to the beginning of statusbuf */
len = gpg->statusptr - inptr;
memmove (gpg->statusbuf, inptr, len);
-
+
len = inptr - gpg->statusbuf;
gpg->statusleft += len;
gpg->statusptr -= len;
-
+
/* if we have more data, try parsing the next line? */
if (gpg->statusptr > gpg->statusbuf)
goto parse;
-
+
return 0;
}
{
pid_t retval;
int status;
-
+
if (gpg->exited)
return;
-
+
kill (gpg->pid, SIGTERM);
sleep (1);
retval = waitpid (gpg->pid, &status, WNOHANG);
the next file descriptor and so on until we've done what we
can to all of them. If one fails along the way, return
-1. */
-
+
if (polls[2].revents & (POLLIN|POLLHUP)) {
/* read the status message and decide what to do... */
char buffer[4096];
ssize_t nread;
-
+
d(printf ("reading from gpg's status-fd...\n"));
-
+
do {
nread = read (gpg->status_fd, buffer, sizeof (buffer));
} while (nread == -1 && (errno == EINTR || errno == EAGAIN));
if (nread == -1)
goto exception;
-
+
if (nread > 0) {
status_backup (gpg, buffer, nread);
-
+
if (gpg_ctx_parse_status (gpg, ex) == -1)
return -1;
} else {
gpg->complete = TRUE;
}
}
-
+
if ((polls[0].revents & (POLLIN|POLLHUP)) && gpg->ostream) {
char buffer[4096];
ssize_t nread;
-
+
d(printf ("reading gpg's stdout...\n"));
-
+
do {
nread = read (gpg->stdout_fd, buffer, sizeof (buffer));
} while (nread == -1 && (errno == EINTR || errno == EAGAIN));
if (nread == -1)
goto exception;
-
+
if (nread > 0) {
if (camel_stream_write (gpg->ostream, buffer, (size_t) nread) == -1)
goto exception;
gpg->seen_eof1 = TRUE;
}
}
-
+
if (polls[1].revents & (POLLIN|POLLHUP)) {
char buffer[4096];
ssize_t nread;
-
+
d(printf ("reading gpg's stderr...\n"));
-
+
do {
nread = read (gpg->stderr_fd, buffer, sizeof (buffer));
} while (nread == -1 && (errno == EINTR || errno == EAGAIN));
if (nread == -1)
goto exception;
-
+
if (nread > 0) {
camel_stream_write (gpg->diagnostics, buffer, nread);
} else {
gpg->seen_eof2 = TRUE;
}
}
-
+
if ((polls[4].revents & (POLLOUT|POLLHUP)) && gpg->need_passwd && gpg->send_passwd) {
ssize_t w, nwritten = 0;
size_t n;
-
+
d(printf ("sending gpg our passphrase...\n"));
-
+
/* send the passphrase to gpg */
n = strlen (gpg->passwd);
do {
do {
w = write (gpg->passwd_fd, gpg->passwd + nwritten, n - nwritten);
} while (w == -1 && (errno == EINTR || errno == EAGAIN));
-
+
if (w > 0)
nwritten += w;
} while (nwritten < n && w != -1);
-
+
/* zero and free our passwd buffer */
memset (gpg->passwd, 0, n);
g_free (gpg->passwd);
gpg->passwd = NULL;
-
+
if (w == -1)
goto exception;
-
+
gpg->send_passwd = FALSE;
}
-
+
if ((polls[3].revents & (POLLOUT|POLLHUP)) && gpg->istream) {
char buffer[4096];
ssize_t nread;
-
+
d(printf ("writing to gpg's stdin...\n"));
-
+
/* write our stream to gpg's stdin */
nread = camel_stream_read (gpg->istream, buffer, sizeof (buffer));
if (nread > 0) {
ssize_t w, nwritten = 0;
-
+
do {
do {
w = write (gpg->stdin_fd, buffer + nwritten, nread - nwritten);
} while (w == -1 && (errno == EINTR || errno == EAGAIN));
-
+
if (w > 0)
nwritten += w;
} while (nwritten < nread && w != -1);
-
+
if (w == -1)
goto exception;
-
+
d(printf ("wrote %d (out of %d) bytes to gpg's stdin\n", nwritten, nread));
}
-
+
if (camel_stream_eos (gpg->istream)) {
d(printf ("closing gpg's stdin\n"));
close (gpg->stdin_fd);
gpg->stdin_fd = -1;
}
}
-
+
return 0;
-
+
exception:
/* always called on an i/o error */
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to execute gpg: %s"), g_strerror(errno));
{
pid_t retval;
int status;
-
+
if (gpg->exited)
return TRUE;
-
+
retval = waitpid (gpg->pid, &status, WNOHANG);
if (retval == gpg->pid) {
gpg->exit_status = status;
gpg->exited = TRUE;
return TRUE;
}
-
+
return FALSE;
}
#endif
sigset_t mask, omask;
pid_t retval;
int status;
-
+
if (!gpg->exited) {
sigemptyset (&mask);
sigaddset (&mask, SIGALRM);
retval = waitpid (gpg->pid, &status, 0);
alarm (0);
sigprocmask (SIG_SETMASK, &omask, NULL);
-
+
if (retval == (pid_t) -1 && errno == EINTR) {
/* The child is hanging: send a friendly reminder. */
kill (gpg->pid, SIGTERM);
status = gpg->exit_status;
retval = gpg->pid;
}
-
+
if (retval != (pid_t) -1 && WIFEXITED (status))
return WEXITSTATUS (status);
else
int res = -1;
CamelMimePart *sigpart;
CamelMultipartSigned *mps;
-
+
/* Note: see rfc2015 or rfc3156, section 5 */
-
+
/* FIXME: stream this, we stream output at least */
istream = camel_stream_mem_new();
if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM,
gpg_ctx_set_userid (gpg, userid);
gpg_ctx_set_istream (gpg, istream);
gpg_ctx_set_ostream (gpg, ostream);
-
+
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg: %s"), g_strerror (errno));
goto fail;
}
-
+
while (!gpg_ctx_op_complete (gpg)) {
if (gpg_ctx_op_step (gpg, ex) == -1)
goto fail;
}
-
+
if (gpg_ctx_op_wait (gpg) != 0) {
const char *diagnostics;
-
+
diagnostics = gpg_ctx_get_diagnostics (gpg);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics :
camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps);
fail:
camel_object_unref(ostream);
-
+
if (gpg)
gpg_ctx_free (gpg);
-
+
return res;
}
CamelStream *ostream;
char *template;
int fd, ret;
-
+
template = g_build_filename (g_get_tmp_dir (), "evolution-pgp.XXXXXX", NULL);
if ((fd = g_mkstemp (template)) == -1) {
g_free (template);
return NULL;
}
-
+
/* TODO: This should probably just write the decoded message content out, not the part + headers */
-
+
ostream = camel_stream_fs_new_with_fd (fd);
ret = camel_data_wrapper_write_to_stream((CamelDataWrapper *)sigpart, ostream);
if (ret != -1) {
if (ret != -1)
ret = camel_stream_close (ostream);
}
-
+
camel_object_unref(ostream);
-
+
if (ret == -1) {
g_unlink (template);
g_free (template);
return NULL;
}
-
+
return template;
}
mps = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)ipart);
ct = ((CamelDataWrapper *)mps)->mime_type;
-
+
/* Inline signature (using our fake mime type) or PGP/Mime signature */
if (camel_content_type_is(ct, "multipart", "signed")) {
/* PGP/Mime Signature */
tmp = camel_content_type_param(ct, "protocol");
if (!CAMEL_IS_MULTIPART_SIGNED(mps)
- || tmp == NULL
+ || tmp == NULL
|| g_ascii_strcasecmp(tmp, context->sign_protocol) != 0) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot verify message signature: Incorrect message format"));
return NULL;
}
-
+
if (!(istream = camel_multipart_signed_get_content_stream ((CamelMultipartSigned *) mps, NULL))) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot verify message signature: Incorrect message format"));
return NULL;
}
-
+
if (!(sigpart = camel_multipart_get_part (mps, CAMEL_MULTIPART_SIGNED_SIGNATURE))) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot verify message signature: Incorrect message format"));
_("Cannot verify message signature: Incorrect message format"));
return NULL;
}
-
+
/* Now start the real work of verifying the message */
#ifdef GPG_LOG
if (camel_debug_start("gpg:sign")) {
goto exception;
}
}
-
+
camel_stream_reset(istream);
gpg = gpg_ctx_new (context->session);
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_VERIFY);
if (sigfile)
gpg_ctx_set_sigfile (gpg, sigfile);
gpg_ctx_set_istream (gpg, istream);
-
+
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg."));
goto exception;
}
-
+
while (!gpg_ctx_op_complete (gpg)) {
if (gpg_ctx_op_step (gpg, ex) == -1)
goto exception;
}
-
+
gpg_ctx_op_wait (gpg);
validity = camel_cipher_validity_new ();
diagnostics = gpg_ctx_get_diagnostics (gpg);
} else {
validity->sign.status = CAMEL_CIPHER_VALIDITY_SIGN_BAD;
}
-
+
gpg_ctx_free (gpg);
-
+
if (sigfile) {
g_unlink (sigfile);
g_free (sigfile);
}
camel_object_unref(istream);
-
+
return validity;
-
+
exception:
-
+
if (gpg != NULL)
gpg_ctx_free (gpg);
-
+
if (istream)
camel_object_unref(istream);
g_unlink (sigfile);
g_free (sigfile);
}
-
+
return NULL;
}
for (i = 0; i < recipients->len; i++) {
gpg_ctx_add_recipient (gpg, recipients->pdata[i]);
}
-
+
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to execute gpg."));
goto fail;
if (gpg_ctx_op_step (gpg, ex) == -1)
goto fail;
}
-
+
if (gpg_ctx_op_wait (gpg) != 0) {
const char *diagnostics;
-
+
diagnostics = gpg_ctx_get_diagnostics (gpg);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics : _("Failed to execute gpg."));
fail1:
camel_object_unref(istream);
camel_object_unref(ostream);
-
+
return res;
}
ct = camel_mime_part_get_content_type((CamelMimePart *)content);
/* Encrypted part (using our fake mime type) or PGP/Mime multipart */
- if (camel_content_type_is(ct, "multipart", "encrypted")) {
+ if (camel_content_type_is(ct, "multipart", "encrypted")) {
mp = (CamelMultipart *) camel_medium_get_content_object ((CamelMedium *) ipart);
if (!(encrypted = camel_multipart_get_part (mp, CAMEL_MULTIPART_ENCRYPTED_CONTENT))) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to decrypt MIME part: protocol error"));
_("Cannot decrypt message: Incorrect message format"));
return NULL;
}
-
+
istream = camel_stream_mem_new();
camel_data_wrapper_decode_to_stream (content, istream);
camel_stream_reset(istream);
-
+
ostream = camel_stream_mem_new();
camel_stream_mem_set_secure((CamelStreamMem *)ostream);
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_DECRYPT);
gpg_ctx_set_istream (gpg, istream);
gpg_ctx_set_ostream (gpg, ostream);
-
+
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg."));
goto fail;
}
-
+
while (!gpg_ctx_op_complete (gpg)) {
if (gpg_ctx_op_step (gpg, ex) == -1)
goto fail;
}
-
+
if (gpg_ctx_op_wait (gpg) != 0) {
const char *diagnostics;
-
+
diagnostics = gpg_ctx_get_diagnostics (gpg);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics :
/* Set mime/type of this new part to application/octet-stream to force type snooping */
camel_mime_part_set_content_type(opart, "application/octet-stream");
}
- if (rv != -1) {
+ if (rv != -1) {
valid = camel_cipher_validity_new();
valid->encrypt.description = g_strdup(_("Encrypted content"));
valid->encrypt.status = CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED;
-
+
if (gpg->hadsig) {
if (gpg->validsig) {
if (gpg->trust == GPG_TRUST_UNDEFINED || gpg->trust == GPG_TRUST_NONE)
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Unable to parse message content"));
}
-
+
fail:
camel_object_unref(ostream);
camel_object_unref(istream);
gpg = gpg_ctx_new (context->session);
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_IMPORT);
gpg_ctx_set_istream (gpg, istream);
-
+
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg: %s"),
errno ? g_strerror (errno) : _("Unknown"));
goto fail;
}
-
+
while (!gpg_ctx_op_complete (gpg)) {
if (gpg_ctx_op_step (gpg, ex) == -1)
goto fail;
}
-
+
if (gpg_ctx_op_wait (gpg) != 0) {
const char *diagnostics;
-
+
diagnostics = gpg_ctx_get_diagnostics (gpg);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics :
res = 0;
fail:
gpg_ctx_free (gpg);
-
+
return res;
}
gpg_ctx_set_mode (gpg, GPG_CTX_MODE_EXPORT);
gpg_ctx_set_armor (gpg, TRUE);
gpg_ctx_set_ostream (gpg, ostream);
-
+
for (i = 0; i < keys->len; i++) {
gpg_ctx_add_recipient (gpg, keys->pdata[i]);
}
-
+
if (gpg_ctx_op_start (gpg) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to execute gpg: %s"),
errno ? g_strerror (errno) : _("Unknown"));
goto fail;
}
-
+
while (!gpg_ctx_op_complete (gpg)) {
if (gpg_ctx_op_step (gpg, ex) == -1)
goto fail;
}
-
+
if (gpg_ctx_op_wait (gpg) != 0) {
const char *diagnostics;
-
+
diagnostics = gpg_ctx_get_diagnostics (gpg);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
diagnostics && *diagnostics ? diagnostics :
res = 0;
fail:
gpg_ctx_free (gpg);
-
+
return res;
}
camel_gpg_context_class_init (CamelGpgContextClass *klass)
{
CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS (klass);
-
+
parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ()));
-
+
cipher_class->hash_to_id = gpg_hash_to_id;
cipher_class->id_to_hash = gpg_id_to_hash;
cipher_class->sign = gpg_sign;
camel_gpg_context_init (CamelGpgContext *context)
{
CamelCipherContext *cipher = (CamelCipherContext *) context;
-
+
context->always_trust = FALSE;
-
+
cipher->sign_protocol = "application/pgp-signature";
cipher->encrypt_protocol = "application/pgp-encrypted";
cipher->key_protocol = "application/pgp-keys";
camel_gpg_context_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_cipher_context_get_type (),
"CamelGpgContext",
(CamelObjectInitFunc) camel_gpg_context_init,
(CamelObjectFinalizeFunc) camel_gpg_context_finalise);
}
-
+
return type;
}
struct _CamelGpgContext {
CamelCipherContext parent_object;
-
+
gboolean always_trust;
};
struct _CamelGpgContextClass {
CamelCipherContextClass parent_class;
-
+
};
camel_html_parser_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (), "CamelHTMLParser",
sizeof (CamelHTMLParser),
(CamelObjectInitFunc) camel_html_parser_init,
(CamelObjectFinalizeFunc) camel_html_parser_finalize);
}
-
+
return type;
}
* camel_html_parser_new:
*
* Create a new CamelHTMLParser object.
- *
+ *
* Return value: A new CamelHTMLParser widget.
**/
CamelHTMLParser *
p->tag = g_string_new("");
p->ent = g_string_new("");
p->charset = NULL;
-
+
if (entities == NULL)
tokenise_setup();
#include "camel-tcp-stream-ssl.h"
#endif
-#define d(x)
+#define d(x)
static CamelStreamClass *parent_class = NULL;
{
CamelStreamClass *camel_stream_class =
CAMEL_STREAM_CLASS (camel_http_stream_class);
-
+
parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (camel_stream_get_type ()));
-
+
/* virtual method overload */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_http_stream_init (gpointer object, gpointer klass)
{
CamelHttpStream *http = CAMEL_HTTP_STREAM (object);
-
+
http->parser = NULL;
http->content_type = NULL;
http->headers = NULL;
camel_http_stream_finalize (CamelObject *object)
{
CamelHttpStream *http = CAMEL_HTTP_STREAM (object);
-
+
if (http->parser)
camel_object_unref(http->parser);
-
+
if (http->content_type)
camel_content_type_unref (http->content_type);
-
+
if (http->headers)
camel_header_raw_clear (&http->headers);
-
+
if (http->session)
camel_object_unref(http->session);
-
+
if (http->url)
camel_url_free (http->url);
-
+
if (http->proxy)
camel_url_free (http->proxy);
-
+
g_free (http->authrealm);
g_free (http->authpass);
-
+
if (http->raw)
camel_object_unref(http->raw);
if (http->read)
camel_http_stream_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_stream_get_type (),
"CamelHttpStream",
(CamelObjectInitFunc) camel_http_stream_init,
(CamelObjectFinalizeFunc) camel_http_stream_finalize);
}
-
+
return type;
}
{
CamelHttpStream *stream;
char *str;
-
+
g_return_val_if_fail(CAMEL_IS_SESSION(session), NULL);
g_return_val_if_fail(url != NULL, NULL);
-
+
stream = CAMEL_HTTP_STREAM (camel_object_new (camel_http_stream_get_type ()));
-
+
stream->method = method;
stream->session = session;
camel_object_ref(session);
-
+
str = camel_url_to_string (url, 0);
stream->url = camel_url_new (str, NULL);
g_free (str);
-
+
return (CamelStream *)stream;
}
} else {
stream = camel_tcp_stream_raw_new ();
}
-
+
if (stream == NULL) {
errno = EINVAL;
return NULL;
camel_object_unref (stream);
return NULL;
}
-
+
if (camel_tcp_stream_connect (CAMEL_TCP_STREAM (stream), ai) == -1) {
errsave = errno;
camel_object_unref (stream);
errno = errsave;
return NULL;
}
-
+
camel_freeaddrinfo(ai);
http->raw = stream;
http->read = camel_stream_buffer_new (stream, CAMEL_STREAM_BUFFER_READ);
-
+
return stream;
}
camel_object_unref(http->raw);
http->raw = NULL;
}
-
+
if (http->read) {
camel_object_unref(http->read);
http->read = NULL;
http_next_token (const unsigned char *in)
{
const unsigned char *inptr = in;
-
+
while (*inptr && !isspace ((int) *inptr))
inptr++;
-
+
while (*inptr && isspace ((int) *inptr))
inptr++;
-
+
return (const char *) inptr;
}
{
const char *token;
char buffer[4096];
-
+
if (camel_stream_buffer_gets ((CamelStreamBuffer *)http->read, buffer, sizeof (buffer)) <= 0)
return -1;
}
http_disconnect(http);
-
+
return -1;
}
char *buf;
size_t len;
int err;
-
+
if (http->parser)
camel_object_unref (http->parser);
-
+
http->parser = camel_mime_parser_new ();
camel_mime_parser_init_with_stream (http->parser, http->read);
-
+
switch (camel_mime_parser_step (http->parser, &buf, &len)) {
case CAMEL_MIME_PARSER_STATE_MESSAGE:
case CAMEL_MIME_PARSER_STATE_HEADER:
http->content_type = camel_content_type_decode (type);
else
http->content_type = NULL;
-
+
if (http->headers)
camel_header_raw_clear (&http->headers);
-
+
http->headers = NULL;
tail = (struct _camel_header_raw *) &http->headers;
-
+
d(printf("HTTP Headers:\n"));
while (headers) {
d(printf(" %s:%s\n", headers->name, headers->value));
tail = node;
headers = headers->next;
}
-
+
break;
default:
g_warning ("Invalid state encountered???: %u", camel_mime_parser_state (http->parser));
}
-
+
err = camel_mime_parser_errno (http->parser);
-
+
if (err != 0) {
camel_object_unref (http->parser);
http->parser = NULL;
goto exception;
}
-
+
camel_mime_parser_drop_step (http->parser);
-
+
return 0;
-
+
exception:
http_disconnect(http);
-
+
return -1;
}
{
const char *method = NULL;
char *url;
-
+
switch (http->method) {
case CAMEL_HTTP_METHOD_GET:
method = "GET";
default:
g_assert_not_reached ();
}
-
+
url = camel_url_to_string (http->url, 0);
d(printf("HTTP Stream Sending: %s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n",
method,
if (http->authrealm)
d(printf("HTTP Stream Sending: WWW-Authenticate: %s\n", http->authrealm));
-
+
if (http->authrealm && camel_stream_printf (http->raw, "WWW-Authenticate: %s\r\n", http->authrealm) == -1) {
http_disconnect(http);
return -1;
if (http->authpass && http->proxy)
d(printf("HTTP Stream Sending: Proxy-Aurhorization: Basic %s\n", http->authpass));
-
+
if (http->authpass && http->proxy && camel_stream_printf (http->raw, "Proxy-Authorization: Basic %s\r\n",
http->authpass) == -1) {
http_disconnect(http);
return -1;
}
-
+
/* end the headers */
if (camel_stream_write (http->raw, "\r\n", 2) == -1 || camel_stream_flush (http->raw) == -1) {
http_disconnect(http);
return -1;
}
-
+
return 0;
}
CamelHttpStream *http = CAMEL_HTTP_STREAM (stream);
const char *parser_buf;
ssize_t nread;
-
+
if (http->method != CAMEL_HTTP_METHOD_GET && http->method != CAMEL_HTTP_METHOD_HEAD) {
errno = EIO;
return -1;
}
-
+
redirect:
-
+
if (!http->raw) {
if (http_connect (http, http->proxy ? http->proxy : http->url) == NULL)
return -1;
-
+
if (http_method_invoke (http) == -1)
return -1;
-
+
if (http_get_statuscode (http) == -1)
return -1;
-
+
if (http_get_headers (http) == -1)
return -1;
-
+
switch (http->statuscode) {
case 200:
case 206:
return -1;
}
}
-
+
nread = camel_mime_parser_read (http->parser, &parser_buf, n);
-
+
if (nread > 0)
memcpy (buffer, parser_buf, nread);
else if (nread == 0)
stream->eos = TRUE;
-
+
return nread;
}
stream_flush (CamelStream *stream)
{
CamelHttpStream *http = (CamelHttpStream *) stream;
-
+
if (http->raw)
return camel_stream_flush (http->raw);
else
stream_close (CamelStream *stream)
{
CamelHttpStream *http = (CamelHttpStream *) stream;
-
+
if (http->raw) {
if (camel_stream_close (http->raw) == -1)
return -1;
http_disconnect(http);
}
-
+
return 0;
}
stream_reset (CamelStream *stream)
{
CamelHttpStream *http = CAMEL_HTTP_STREAM (stream);
-
+
if (http->raw)
http_disconnect(http);
camel_http_stream_set_user_agent (CamelHttpStream *http_stream, const char *user_agent)
{
g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream));
-
+
g_free (http_stream->user_agent);
http_stream->user_agent = g_strdup (user_agent);
}
camel_http_stream_set_proxy (CamelHttpStream *http_stream, const char *proxy_url)
{
g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream));
-
+
if (http_stream->proxy)
camel_url_free (http_stream->proxy);
camel_http_stream_set_proxy_authrealm (CamelHttpStream *http_stream, const char *proxy_authrealm)
{
g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream));
-
+
g_free (http_stream->authrealm);
http_stream->authrealm = g_strdup (proxy_authrealm);
}
camel_http_stream_set_proxy_authpass (CamelHttpStream *http_stream, const char *proxy_authpass)
{
g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream));
-
+
g_free (http_stream->authpass);
http_stream->authpass = g_strdup (proxy_authpass);
}
struct _CamelHttpStream {
CamelStream parent_object;
-
+
CamelMimeParser *parser;
-
+
CamelContentType *content_type;
struct _camel_header_raw *headers;
-
+
CamelHttpMethod method;
struct _CamelSession *session;
CamelURL *url;
-
+
char *user_agent;
-
+
/* proxy info */
CamelURL *proxy;
char *authrealm;
char *authpass;
-
+
int statuscode;
-
+
CamelStream *raw;
CamelStream *read;
};
struct _CamelHttpStreamClass {
CamelStreamClass parent_class;
-
+
/* Virtual methods */
};
# ifdef CAMEL_EXPLICIT_TRANSLATION_DOMAIN
# undef _
# define _(String) dgettext (CAMEL_EXPLICIT_TRANSLATION_DOMAIN, String)
-# else
+# else
# define _(String) gettext (String)
# endif
# ifdef gettext_noop
camel_index_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelIndex",
sizeof (CamelIndex),
(CamelObjectInitFunc) camel_index_init,
(CamelObjectFinalizeFunc) camel_index_finalise);
}
-
+
return type;
}
camel_index_rename(CamelIndex *idx, const char *path)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), -1);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->rename(idx, path);
else {
camel_index_set_normalise(CamelIndex *idx, CamelIndexNorm func, void *data)
{
g_return_if_fail (CAMEL_IS_INDEX (idx));
-
+
idx->normalise = func;
idx->normalise_data = data;
}
camel_index_sync(CamelIndex *idx)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), -1);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->sync(idx);
else {
camel_index_compress(CamelIndex *idx)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), -1);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->compress(idx);
else {
int ret;
g_return_val_if_fail (CAMEL_IS_INDEX (idx), -1);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0) {
ret = CI_CLASS(idx)->delete(idx);
idx->state |= CAMEL_INDEX_DELETED;
camel_index_has_name(CamelIndex *idx, const char *name)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), FALSE);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->has_name(idx, name);
else
camel_index_add_name(CamelIndex *idx, const char *name)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), NULL);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->add_name(idx, name);
else
camel_index_write_name(CamelIndex *idx, CamelIndexName *idn)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), -1);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->write_name(idx, idn);
else {
camel_index_find_name(CamelIndex *idx, const char *name)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), NULL);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->find_name(idx, name);
else
camel_index_delete_name(CamelIndex *idx, const char *name)
{
g_return_if_fail (CAMEL_IS_INDEX (idx));
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
CI_CLASS(idx)->delete_name(idx, name);
}
CamelIndexCursor *ret;
g_return_val_if_fail (CAMEL_IS_INDEX (idx), NULL);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) != 0)
return NULL;
camel_index_words(CamelIndex *idx)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), NULL);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->words(idx);
else
camel_index_names(CamelIndex *idx)
{
g_return_val_if_fail (CAMEL_IS_INDEX (idx), NULL);
-
+
if ((idx->state & CAMEL_INDEX_DELETED) == 0)
return CI_CLASS(idx)->names(idx);
else
camel_index_name_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelIndexName",
sizeof (CamelIndexName),
(CamelObjectInitFunc) camel_index_name_init,
(CamelObjectFinalizeFunc) camel_index_name_finalise);
}
-
+
return type;
}
camel_index_cursor_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelIndexCursor",
sizeof (CamelIndexCursor),
(CamelObjectInitFunc) camel_index_cursor_init,
(CamelObjectFinalizeFunc) camel_index_cursor_finalise);
}
-
+
return type;
}
camel_internet_address_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_address_get_type(), "CamelInternetAddress",
sizeof (CamelInternetAddress),
(CamelObjectInitFunc) camel_internet_address_init,
NULL);
}
-
+
return type;
}
}
camel_header_address_list_clear(&ha);
}
-
+
return a->addresses->len - count;
}
if (a->addresses->len == 0)
return NULL;
-
+
out = g_string_new("");
-
+
for (i = 0;i < a->addresses->len; i++) {
struct _address *addr = g_ptr_array_index(a->addresses, i);
char *enc;
g_string_append(out, enc);
g_free(enc);
}
-
+
ret = out->str;
g_string_free(out, FALSE);
-
+
return ret;
}
int i;
GString *out;
char *ret;
-
+
if (a->addresses->len == 0)
return NULL;
-
+
out = g_string_new("");
-
+
for (i = 0;i < a->addresses->len; i++) {
struct _address *addr = g_ptr_array_index(a->addresses, i);
char *enc;
g_string_append(out, enc);
g_free(enc);
}
-
+
ret = out->str;
g_string_free(out, FALSE);
-
+
return ret;
}
internet_remove (CamelAddress *a, int index)
{
struct _address *addr;
-
+
if (index < 0 || index >= a->addresses->len)
return;
-
+
addr = g_ptr_array_index(a->addresses, index);
g_free(addr->name);
g_free(addr->address);
* camel_internet_address_new:
*
* Create a new #CamelInternetAddress object.
- *
+ *
* Returns a new #CamelInternetAddress object
**/
CamelInternetAddress *
* @addr: a #CamelInternetAddress object
* @name: name associated with the new address
* @address: routing address associated with the new address
- *
+ *
* Add a new internet address to @addr.
- *
+ *
* Returns the index of added entry
**/
int
* @index: address's array index
* @namep: holder for the returned name, or %NULL, if not required.
* @addressp: holder for the returned address, or %NULL, if not required.
- *
+ *
* Get the address at @index.
- *
+ *
* Returns %TRUE if such an address exists, or %FALSE otherwise
**/
gboolean
* @addr: a #CamelInternetAddress object
* @name: name to lookup
* @addressp: holder for address part, or %NULL, if not required.
- *
+ *
* Find address by real name.
- *
+ *
* Returns the index of the address matching the name, or %-1 if no
* match was found
**/
* @addr: a #CamelInternetAddress object
* @address: address to lookup
* @namep: holder for the matching name, or %NULL, if not required.
- *
+ *
* Find an address by address.
- *
+ *
* Returns the index of the address, or %-1 if not found
**/
int
* @len: the length of the line the address is being appended to
* @name: the unencoded real name associated with the address
* @addr: the routing address
- *
+ *
* Encode a single address ready for internet usage. Header folding
* as per rfc822 is also performed, based on the length *@len. If @len
* is %NULL, then no folding will occur.
*
* Note: The value at *@in will be updated based on any linewrapping done
- *
+ *
* Returns the encoded address
**/
char *
g_string_append_printf(out, ">");
len += out->len;
-
+
if (inlen != NULL)
*inlen = len;
g_free(name);
-
+
ret = out->str;
g_string_free(out, FALSE);
* camel_internet_address_format_address:
* @name: a name, quotes may be stripped from it
* @addr: an rfc822 routing address
- *
+ *
* Function to format a single address, suitable for display.
- *
+ *
* Returns a nicely formatted string containing the rfc822 address
**/
char *
/**
* camel_dlist_init:
- * @v:
- *
+ * @v:
+ *
* Initialise a double-linked list header. All list headers must be
* initialised before use.
**/
* camel_dlist_addhead:
* @l: An initialised list header.
* @n: A node, the next and prev pointers will be overwritten.
- *
+ *
* Add the list node @n to the head (start) of the list @l.
- *
+ *
* Return value: @n.
**/
CamelDListNode *camel_dlist_addhead(CamelDList *l, CamelDListNode *n)
* camel_dlist_addtail:
* @l: An intialised list header.
* @n: A node, the next and prev pointers will be overwritten.
- *
+ *
* Add the list onde @n to the tail (end) of the list @l.
- *
+ *
* Return value: @n.
**/
CamelDListNode *camel_dlist_addtail(CamelDList *l, CamelDListNode *n)
/**
* camel_dlist_remove:
* @n: A node which is part of a list.
- *
+ *
* Remove @n from the list it's in. @n must belong to a list.
- *
+ *
* Return value: @n.
**/
CamelDListNode *camel_dlist_remove(CamelDListNode *n)
/**
* camel_dlist_remhead:
* @l: An initialised list, maybe containing items.
- *
+ *
* Remove the head node (start) of the list.
- *
+ *
* xReturn value: The previously first-node in the list, or NULLif @l
* is an empty list.
**/
/**
* camel_dlist_remtail:
* @l: An initialised list, maybe containing items.
- *
+ *
* Remove the last node in the list.
- *
+ *
* Return value: The previously last-node in the list, or NULL if @l
* is an empty list.
**/
/**
* camel_dlist_empty:
* @l: An initialised list header.
- *
+ *
* Returns %TRUE if @l is an empty list.
- *
+ *
* Return value: %TRUE if @l is an empty list, %FALSE otherwise.
**/
int camel_dlist_empty(CamelDList *l)
/**
* camel_dlist_length:
* @l: An initialised list header.
- *
+ *
* Returns the number of nodes in the list @l.
- *
+ *
* Return value: The number of nodes.
**/
int camel_dlist_length(CamelDList *l)
/**
* struct _CamelDListNode - A double-linked list node.
- *
+ *
* @next: The next node link.
* @prev: The previous node link.
- *
+ *
* A double-linked list node header. Put this at the start of the
* list node structure. Data is stored in the list by subclassing the
* node header rather than using a pointer. Or more normally by just
/**
* struct _CamelDList - A double-linked list header.
- *
+ *
* @head: The head node's next pointer.
* @tail: The tail node's next pointer.
* @tailpred: The previous node to the tail node.
- *
+ *
* This is the merging of two separate head and tail nodes into a
* single structure. i.e. if you ahve a NULL terminated head and tail
* node such as head = { first, NULL } and tail = { NULL, last } then
/**
* struct _CamelSListNode - A single-linked list node.
- *
+ *
* @next: The next node in the list.
*
* A single-linked list node header. Put this at hte start of the
/**
* struct _CamelSList - A single-linked list header.
- *
+ *
* @head: The head of the list.
- *
+ *
* This is the header of a single-linked list.
**/
struct _CamelSList {
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
*
* Copyright (C) 2001 Ximian Inc (www.ximian.com/)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{
struct sigaction sa;
sigset_t sigset;
-
+
/* ignore sigint/sigio */
sa.sa_handler = SIG_IGN;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
-
+
sigemptyset(&sigset);
sigaddset(&sigset, SIGIO);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-
+
sigaction (SIGIO, &sa, NULL);
sigaction (SIGINT, &sa, NULL);
-
+
/* FIXME: add more sanity checks/setup here */
#ifdef SETEUID_SAVES
tv.tv_sec = delay;
tv.tv_usec = 0;
}
-
+
d(fprintf(stderr, "lock helper waiting for input\n"));
if (select(STDIN_FILENO+1, &rset, NULL, NULL, lock_info_list?&tv:NULL) == -1) {
if (errno == EINTR)
}
info = info->next;
}
-
+
continue;
}
*
* Copyright (C) 1999 Ximian (www.ximian.com/).
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
*
* Copyright (C) 1999 Ximian (www.ximian.com/).
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/**
* camel_lock_dot:
- * @path:
- * @ex:
- *
+ * @path:
+ * @ex:
+ *
* Create an exclusive lock using .lock semantics.
* All locks are equivalent to write locks (exclusive).
- *
+ *
* Return value: -1 on error, sets @ex appropriately.
**/
int
/**
* camel_unlock_dot:
- * @path:
- *
+ * @path:
+ *
* Attempt to unlock a .lock lock.
**/
void
/**
* camel_lock_fcntl:
- * @fd:
- * @type:
- * @ex:
- *
+ * @fd:
+ * @type:
+ * @ex:
+ *
* Create a lock using fcntl(2).
*
* @type is CAMEL_LOCK_WRITE or CAMEL_LOCK_READ,
* to create exclusive or shared read locks
- *
+ *
* Return value: -1 on error.
**/
int
/**
* camel_unlock_fcntl:
- * @fd:
- *
+ * @fd:
+ *
* Unlock an fcntl lock.
**/
void
/**
* camel_lock_flock:
- * @fd:
- * @type:
- * @ex:
- *
+ * @fd:
+ * @type:
+ * @ex:
+ *
* Create a lock using flock(2).
- *
+ *
* @type is CAMEL_LOCK_WRITE or CAMEL_LOCK_READ,
* to create exclusive or shared read locks
*
/**
* camel_unlock_flock:
- * @fd:
- *
+ * @fd:
+ *
* Unlock an flock lock.
**/
void
* @path: Path to the file to lock (used for .locking only).
* @fd: Open file descriptor of the right type to lock.
* @type: Type of lock, CAMEL_LOCK_READ or CAMEL_LOCK_WRITE.
- * @ex:
- *
+ * @ex:
+ *
* Attempt to lock a folder, multiple attempts will be made using all
* locking strategies available.
- *
+ *
* Return value: -1 on error, @ex will describe the locking system that failed.
**/
int
* camel_unlock_folder:
* @path: Filename of folder.
* @fd: Open descrptor on which locks were placed.
- *
+ *
* Free a lock on a folder.
**/
void
return 1;
}
fd2 = open("mylock", O_RDWR);
- if (fd2 == -1) {
+ if (fd2 == -1) {
printf("Could not open lock file (mylock): %s", g_strerror (errno));
close (fd1);
return 1;
*
* Copyright (C) 1999 Ximian (www.ximian.com/).
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#include "camel-mime-utils.h"
static void reset(CamelMimeFilter *mf);
-static void complete(CamelMimeFilter *mf, char *in, size_t len,
- size_t prespace, char **out,
+static void complete(CamelMimeFilter *mf, char *in, size_t len,
+ size_t prespace, char **out,
size_t *outlen, size_t *outprespace);
-static void filter(CamelMimeFilter *mf, char *in, size_t len,
- size_t prespace, char **out,
+static void filter(CamelMimeFilter *mf, char *in, size_t len,
+ size_t prespace, char **out,
size_t *outlen, size_t *outprespace);
static void camel_mime_filter_basic_class_init (CamelMimeFilterBasicClass *klass);
camel_mime_filter_basic_class_init (CamelMimeFilterBasicClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
camel_mime_filter_basic_parent = CAMEL_MIME_FILTER_CLASS(camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
filter_class->reset = reset;
camel_mime_filter_basic_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterBasic",
sizeof (CamelMimeFilterBasic),
(CamelObjectInitFunc) camel_mime_filter_basic_init,
NULL);
}
-
+
return type;
}
reset(CamelMimeFilter *mf)
{
CamelMimeFilterBasic *f = (CamelMimeFilterBasic *)mf;
-
+
switch(f->type) {
case CAMEL_MIME_FILTER_BASIC_QP_ENC:
f->state = -1;
{
CamelMimeFilterBasic *f = (CamelMimeFilterBasic *)mf;
size_t newlen = 0;
-
+
switch(f->type) {
case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
/* wont go to more than 2x size (overly conservative) */
{
CamelMimeFilterBasic *f = (CamelMimeFilterBasic *)mf;
size_t newlen;
-
+
switch(f->type) {
case CAMEL_MIME_FILTER_BASIC_BASE64_ENC:
/* wont go to more than 2x size (overly conservative) */
if (!(f->state & CAMEL_UUDECODE_STATE_BEGIN)) {
register char *inptr, *inend;
size_t left;
-
+
inptr = in;
inend = inptr + len;
-
+
while (inptr < inend) {
left = inend - inptr;
if (left < 6) {
}
break;
}
-
+
/* go to the next line */
for ( ; inptr < inend && *inptr != '\n'; inptr++);
-
+
if (inptr < inend)
inptr++;
}
}
-
+
if ((f->state & CAMEL_UUDECODE_STATE_BEGIN) && !(f->state & CAMEL_UUDECODE_STATE_END)) {
/* "begin <mode> <filename>\n" has been found, so we can now start decoding */
camel_mime_filter_set_size (mf, len + 3, FALSE);
* camel_mime_filter_basic_new:
*
* Create a new #CamelMimeFilterBasic object.
- *
+ *
* Returns a new #CamelMimeFilterBasic object
**/
CamelMimeFilterBasic *
* @type: a #CamelMimeFilterBasicType type
*
* Create a new #CamelMimeFilterBasic object of type @type.
- *
+ *
* Returns a new #CamelMimeFilterBasic object
**/
CamelMimeFilterBasic *
struct _CamelMimeFilterBasicPrivate *priv;
CamelMimeFilterBasicType type;
-
+
unsigned char uubuf[60];
int state;
int save;
camel_mime_filter_bestenc_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterBestenc",
sizeof (CamelMimeFilterBestenc),
(CamelObjectInitFunc) camel_mime_filter_bestenc_init,
NULL);
}
-
+
return type;
}
if (f->flags & CAMEL_BESTENC_GET_ENCODING) {
register unsigned int /* hopefully reg's are assinged in the order they appear? */
c,
- lastc=f->lastc,
+ lastc=f->lastc,
countline=f->countline,
count0=f->count0,
count8 = f->count8;
* camel_mime_filter_bestenc_new:
* @flags: a bitmask of data required.
*
- * Create a new #CamelMimeFilterBestenc object.
- *
+ * Create a new #CamelMimeFilterBestenc object.
+ *
* Returns a new #CamelMimeFilterBestenc object
**/
CamelMimeFilterBestenc *
* camel_mime_filter_bestenc_get_best_encoding:
* @filter: a #CamelMimeFilterBestenc object
* @required: maximum level of output encoding allowed.
- *
+ *
* Get the best encoding, given specific constraints, that can be used to
* encode a stream of bytes.
- *
+ *
* Returns the best encoding to use
**/
CamelTransferEncoding
{
CamelTransferEncoding bestenc;
int istext;
-
+
istext = (required & CAMEL_BESTENC_TEXT) ? 1 : 0;
required = required & ~CAMEL_BESTENC_TEXT;
-
+
#if 0
printf("count0 = %d, count8 = %d, total = %d\n", filter->count0, filter->count8, filter->total);
printf("maxline = %d, crlfnoorder = %s\n", filter->maxline, filter->crlfnoorder?"TRUE":"FALSE");
bestenc = CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE;
else
bestenc = CAMEL_TRANSFER_ENCODING_BASE64;
-
+
/* if we have nocrlf order, or long lines, we need to encode always */
if (filter->crlfnoorder || filter->maxline >= 998)
return bestenc;
/**
* camel_mime_filter_bestenc_get_best_charset:
* @filter: a #CamelMimeFilterBestenc object
- *
+ *
* Gets the best charset that can be used to contain this content.
- *
+ *
* Returns the name of the best charset to use to encode the input
* text filtered by @filter
**/
* camel_mime_filter_bestenc_set_flags:
* @filter: a #CamelMimeFilterBestenc object
* @flags: bestenc filter flags
- *
+ *
* Set the flags for subsequent operations.
**/
void
CAMEL_BESTENC_7BIT,
CAMEL_BESTENC_8BIT,
CAMEL_BESTENC_BINARY,
-
+
/* is the content stream to be treated as text? */
CAMEL_BESTENC_TEXT = 1<<8
} CamelBestencEncoding;
camel_mime_filter_canon_class_init (CamelMimeFilterCanonClass *klass)
{
CamelMimeFilterClass *mime_filter_class = (CamelMimeFilterClass *) klass;
-
+
mime_filter_class->filter = filter;
mime_filter_class->complete = complete;
mime_filter_class->reset = reset;
camel_mime_filter_canon_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterCanon",
sizeof (CamelMimeFilterCanon),
NULL,
NULL);
}
-
+
return type;
}
/* empty line */
*o++ = '\r';
}
-
+
*o++ = c;
start = inptr;
starto = o;
filter_run(f, in, len, prespace, out, outlen, outprespace, FALSE);
}
-static void
+static void
complete(CamelMimeFilter *f, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
{
filter_run(f, in, len, prespace, out, outlen, outprespace, TRUE);
camel_mime_filter_charset_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterCharset",
sizeof (CamelMimeFilterCharset),
(CamelObjectInitFunc) camel_mime_filter_charset_init,
(CamelObjectFinalizeFunc) camel_mime_filter_charset_finalize);
}
-
+
return type;
}
char buf[16];
char *buffer;
size_t outlen = 16;
-
+
/* what happens with the output bytes if this resets the state? */
if (f->ic != (iconv_t) -1) {
buffer = buf;
size_t inleft, outleft, converted = 0;
const char *inbuf;
char *outbuf;
-
+
if (charset->ic == (iconv_t) -1)
goto noop;
-
+
camel_mime_filter_set_size (mf, len * 5 + 16, FALSE);
outbuf = mf->outbuf;
outleft = mf->outsize;
-
+
inbuf = in;
inleft = len;
-
+
if (inleft > 0) {
do {
converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
*
* We just need to grow our outbuffer and try again.
*/
-
+
converted = outbuf - mf->outbuf;
camel_mime_filter_set_size (mf, inleft * 5 + mf->outsize + 16, TRUE);
outbuf = mf->outbuf + converted;
*
* What we do here is eat the invalid bytes in the sequence and continue
*/
-
+
inbuf++;
inleft--;
} else if (errno == EINVAL) {
* We assume that this can only happen if we've run out of
* bytes for a multibyte sequence, if not we're in trouble.
*/
-
+
break;
} else
goto noop;
}
} while (((int) inleft) > 0);
}
-
+
/* flush the iconv conversion */
e_iconv (charset->ic, NULL, NULL, &outbuf, &outleft);
-
+
*out = mf->outbuf;
*outlen = mf->outsize - outleft;
*outprespace = mf->outpre;
-
+
return;
-
+
noop:
-
+
*out = in;
*outlen = len;
*outprespace = prespace;
size_t inleft, outleft, converted = 0;
const char *inbuf;
char *outbuf;
-
+
if (charset->ic == (iconv_t) -1)
goto noop;
-
+
camel_mime_filter_set_size (mf, len * 5 + 16, FALSE);
outbuf = mf->outbuf + converted;
outleft = mf->outsize - converted;
-
+
inbuf = in;
inleft = len;
-
+
do {
converted = e_iconv (charset->ic, &inbuf, &inleft, &outbuf, &outleft);
if (converted == (size_t) -1) {
if (errno == E2BIG || errno == EINVAL)
break;
-
+
if (errno == EILSEQ) {
/*
* EILSEQ An invalid multibyte sequence has been encountered
*
* What we do here is eat the invalid bytes in the sequence and continue
*/
-
+
inbuf++;
inleft--;
} else {
}
}
} while (((int) inleft) > 0);
-
+
if (((int) inleft) > 0) {
/* We've either got an E2BIG or EINVAL. Save the
remainder of the buffer as we'll process this next
time through */
camel_mime_filter_backup (mf, inbuf, inleft);
}
-
+
*out = mf->outbuf;
*outlen = outbuf - mf->outbuf;
*outprespace = mf->outpre;
-
+
return;
-
+
noop:
-
+
*out = in;
*outlen = len;
*outprespace = prespace;
camel_mime_filter_charset_class_init (CamelMimeFilterCharsetClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
camel_mime_filter_charset_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
filter_class->reset = reset;
* camel_mime_filter_charset_new:
*
* Create a new #CamelMimeFilterCharset object.
- *
+ *
* Returns a new #CamelMimeFilterCharset object
**/
CamelMimeFilterCharset *
camel_mime_filter_charset_new_convert (const char *from_charset, const char *to_charset)
{
CamelMimeFilterCharset *new;
-
+
new = CAMEL_MIME_FILTER_CHARSET (camel_object_new (camel_mime_filter_charset_get_type ()));
-
+
new->ic = e_iconv_open (to_charset, from_charset);
if (new->ic == (iconv_t) -1) {
w(g_warning ("Cannot create charset conversion from %s to %s: %s",
new->from = g_strdup (from_charset);
new->to = g_strdup (to_charset);
}
-
+
return new;
}
{
CamelMimeFilterClass *mime_filter_class =
(CamelMimeFilterClass *) klass;
-
+
mime_filter_class->filter = filter;
mime_filter_class->complete = complete;
mime_filter_class->reset = reset;
camel_mime_filter_crlf_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterCRLF",
sizeof (CamelMimeFilterCRLF),
const char *inend;
gboolean do_dots;
char *outptr;
-
+
do_dots = crlf->mode == CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS;
-
+
inptr = in;
inend = in + len;
-
+
if (crlf->direction == CAMEL_MIME_FILTER_CRLF_ENCODE) {
camel_mime_filter_set_size (f, 3 * len, FALSE);
-
+
outptr = f->outbuf;
while (inptr < inend) {
if (*inptr == '\r') {
} else {
if (do_dots && *inptr == '.' && crlf->saw_lf)
*outptr++ = '.';
-
+
crlf->saw_cr = FALSE;
crlf->saw_lf = FALSE;
}
-
+
*outptr++ = *inptr++;
}
} else {
* in practice, as the input is processed in arbitrarily-sized
* blocks. */
camel_mime_filter_set_size (f, len + 1, FALSE);
-
+
outptr = f->outbuf;
while (inptr < inend) {
if (*inptr == '\r') {
} else {
if (crlf->saw_cr) {
crlf->saw_cr = FALSE;
-
+
if (*inptr == '\n') {
crlf->saw_lf = TRUE;
*outptr++ = *inptr++;
} else
*outptr++ = '\r';
}
-
+
*outptr++ = *inptr;
}
-
+
if (do_dots && *inptr == '.') {
if (crlf->saw_lf) {
crlf->saw_dot = TRUE;
crlf->saw_dot = FALSE;
}
}
-
+
crlf->saw_lf = FALSE;
-
+
inptr++;
}
}
-
+
*out = f->outbuf;
*outlen = outptr - f->outbuf;
*outprespace = f->outpre;
}
-static void
+static void
complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace,
char **out, size_t *outlen, size_t *outprespace)
{
reset (CamelMimeFilter *f)
{
CamelMimeFilterCRLF *crlf = (CamelMimeFilterCRLF *)f;
-
+
crlf->saw_cr = FALSE;
crlf->saw_lf = TRUE;
crlf->saw_dot = FALSE;
camel_mime_filter_crlf_new (CamelMimeFilterCRLFDirection direction, CamelMimeFilterCRLFMode mode)
{
CamelMimeFilterCRLF *crlf = CAMEL_MIME_FILTER_CRLF(camel_object_new (CAMEL_MIME_FILTER_CRLF_TYPE));
-
+
crlf->direction = direction;
crlf->mode = mode;
crlf->saw_cr = FALSE;
crlf->saw_lf = TRUE;
crlf->saw_dot = FALSE;
-
+
return (CamelMimeFilter *)crlf;
}
{ "/color", "</font>", FALSE, NULL },
{ "lang", "<span lang=\"%s\">", TRUE, param_parse_lang },
{ "/lang", "</span>", FALSE, NULL },
-
+
/* don't handle this tag yet... */
{ "paraindent", "<!-- ", /* TRUE */ FALSE, NULL },
{ "/paraindent", " -->", FALSE, NULL },
-
+
/* as soon as we support all the tags that can have a param
* tag argument, these should be unnecessary, but we'll keep
* them anyway just in case? */
camel_mime_filter_enriched_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (),
"CamelMimeFilterEnriched",
(CamelObjectInitFunc) camel_mime_filter_enriched_init,
(CamelObjectFinalizeFunc) camel_mime_filter_enriched_finalize);
}
-
+
return type;
}
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
int i;
-
+
parent_class = CAMEL_MIME_FILTER_CLASS (camel_mime_filter_get_type ());
-
+
filter_class->reset = filter_reset;
filter_class->filter = filter_filter;
filter_class->complete = filter_complete;
-
+
if (!enriched_hash) {
enriched_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
for (i = 0; i < NUM_ENRICHED_TAGS; i++)
enriched_tag_needs_param (const char *tag)
{
int i;
-
+
for (i = 0; i < NUM_ENRICHED_TAGS; i++)
if (!g_ascii_strcasecmp (tag, enriched_tags[i].enriched))
return enriched_tags[i].needs_param;
-
+
return FALSE;
}
#endif
guint32 rgb = 0;
guint v;
int i;
-
+
for (i = 0; i < NUM_VALID_COLOURS; i++) {
if (!g_ascii_strncasecmp (inptr, valid_colours[i], inlen))
return g_strdup (valid_colours[i]);
}
-
+
/* check for numeric r/g/b in the format: ####,####,#### */
if (inptr[4] != ',' || inptr[9] != ',') {
/* okay, mailer must have used a string name that
inend = inptr + inlen;
while (end < inend && ((*end >= 'a' && *end <= 'z') || (*end >= 'A' && *end <= 'Z')))
end++;
-
+
return g_strndup (inptr, end - inptr);
}
-
+
for (i = 0; i < 3; i++) {
v = strtoul (inptr, (char **) &end, 16);
if (end != inptr + 4)
goto invalid_format;
-
+
v >>= 8;
rgb = (rgb << 8) | (v & 0xff);
-
+
inptr += 5;
}
-
+
return g_strdup_printf ("#%.6X", rgb);
-
+
invalid_format:
-
+
/* default colour? */
return g_strdup ("black");
}
{
register const char *inptr = fontfamily;
const char *inend = inptr + inlen;
-
+
/* don't allow any of '"', '<', nor '>' */
while (inptr < inend && *inptr != '"' && *inptr != '<' && *inptr != '>')
inptr++;
-
+
return g_strndup (fontfamily, inptr - fontfamily);
}
{
register const char *inptr = lang;
const char *inend = inptr + inlen;
-
+
/* don't allow any of '"', '<', nor '>' */
while (inptr < inend && *inptr != '"' && *inptr != '<' && *inptr != '>')
inptr++;
-
+
return g_strndup (lang, inptr - lang);
}
param_parse (const char *enriched, const char *inptr, int inlen)
{
int i;
-
+
for (i = 0; i < NUM_ENRICHED_TAGS; i++) {
if (!g_ascii_strcasecmp (enriched, enriched_tags[i].enriched))
return enriched_tags[i].parse_param (inptr, inlen);
}
-
+
g_assert_not_reached ();
-
+
return NULL;
}
const char *tag, *inend, *outend;
register const char *inptr;
register char *outptr;
-
+
camel_mime_filter_set_size (filter, inlen * 2 + 6, FALSE);
-
+
inptr = in;
inend = in + inlen;
outptr = filter->outbuf;
outend = filter->outbuf + filter->outsize;
-
+
retry:
do {
while (inptr < inend && outptr < outend && !strchr (" <>&\n", *inptr))
*outptr++ = *inptr++;
-
+
if (outptr == outend)
goto backup;
-
+
if ((inptr + 1) >= inend)
break;
-
+
switch (*inptr++) {
case ' ':
while (inptr < inend && (outptr + 7) < outend && *inptr == ' ') {
outptr += 6;
inptr++;
}
-
+
if (outptr < outend)
*outptr++ = ' ';
-
+
break;
case '\n':
if (!(enriched->flags & IS_RICHTEXT)) {
inptr--;
goto backup;
}
-
+
while (inptr < inend && (outptr + 4) < outend && *inptr == '\n') {
memcpy (outptr, "<br>", 4);
outptr += 4;
goto backup;
}
}
-
+
tag = inptr;
while (inptr < inend && *inptr != '>')
inptr++;
-
+
if (inptr == inend) {
inptr = tag - 1;
goto need_input;
}
-
+
if (!g_ascii_strncasecmp (tag, "nofill>", 7)) {
if ((outptr + 5) < outend) {
enriched->nofill++;
const char *html_tag;
char *enriched_tag;
int len;
-
+
len = inptr - tag;
enriched_tag = g_alloca (len + 1);
memcpy (enriched_tag, tag, len);
enriched_tag[len] = '\0';
-
+
html_tag = g_hash_table_lookup (enriched_hash, enriched_tag);
-
+
if (html_tag) {
if (html_tag_needs_param (html_tag)) {
const char *start;
char *param;
-
+
while (inptr < inend && *inptr != '<')
inptr++;
-
+
if (inptr == inend || (inend - inptr) <= 15) {
inptr = tag - 1;
goto need_input;
}
-
+
if (g_ascii_strncasecmp (inptr, "<param>", 7) != 0) {
/* ignore the enriched command tag... */
inptr -= 1;
goto loop;
}
-
+
inptr += 7;
start = inptr;
-
+
while (inptr < inend && *inptr != '<')
inptr++;
-
+
if (inptr == inend || (inend - inptr) <= 8) {
inptr = tag - 1;
goto need_input;
}
-
+
if (g_ascii_strncasecmp (inptr, "</param>", 8) != 0) {
/* ignore the enriched command tag... */
inptr += 7;
goto loop;
}
-
+
len = inptr - start;
param = param_parse (enriched_tag, start, len);
len = strlen (param);
-
+
inptr += 7;
-
+
len += strlen (html_tag);
-
+
if ((outptr + len) < outend) {
outptr += snprintf (outptr, len, html_tag, param);
g_free (param);
}
}
}
-
+
loop:
inptr++;
break;
break;
}
} while (inptr < inend);
-
+
need_input:
-
+
/* the reason we ignore @flush here is because if there isn't
enough input to parse a tag, then there's nothing we can
do. */
-
+
if (inptr < inend)
camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr));
-
+
*out = filter->outbuf;
*outlen = outptr - filter->outbuf;
*outprespace = filter->outpre;
-
+
return;
-
+
backup:
-
+
if (flush) {
size_t offset, grow;
-
+
grow = (inend - inptr) * 2 + 20;
offset = outptr - filter->outbuf;
camel_mime_filter_set_size (filter, filter->outsize + grow, TRUE);
outend = filter->outbuf + filter->outsize;
outptr = filter->outbuf + offset;
-
+
goto retry;
} else {
camel_mime_filter_backup (filter, inptr, (unsigned) (inend - inptr));
}
-
+
*out = filter->outbuf;
*outlen = outptr - filter->outbuf;
*outprespace = filter->outpre;
enriched_to_html (filter, in, len, prespace, out, outlen, outprespace, FALSE);
}
-static void
+static void
filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
char **out, size_t *outlen, size_t *outprespace)
{
filter_reset (CamelMimeFilter *filter)
{
CamelMimeFilterEnriched *enriched = (CamelMimeFilterEnriched *) filter;
-
+
enriched->nofill = 0;
}
camel_mime_filter_enriched_new (guint32 flags)
{
CamelMimeFilterEnriched *new;
-
+
new = (CamelMimeFilterEnriched *) camel_object_new (CAMEL_TYPE_MIME_FILTER_ENRICHED);
new->flags = flags;
-
+
return CAMEL_MIME_FILTER (new);
}
if (in == NULL)
return NULL;
-
+
filter = camel_mime_filter_enriched_new(flags);
-
+
camel_mime_filter_complete(filter, (char *)in, strlen(in), 0, &outbuf, &outlen, &outpre);
outbuf = g_strndup (outbuf, outlen);
camel_object_unref (filter);
-
+
return outbuf;
}
struct _CamelMimeFilterEnriched {
CamelMimeFilter parent_object;
-
+
guint32 flags;
int nofill;
};
struct _CamelMimeFilterEnrichedClass {
CamelMimeFilterClass parent_class;
-
+
};
CamelType camel_mime_filter_enriched_get_type (void);
camel_mime_filter_from_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterFrom",
sizeof (CamelMimeFilterFrom),
(CamelObjectInitFunc) camel_mime_filter_from_init,
NULL);
}
-
+
return type;
}
*out = in;
*outlen = inend - in;
*outprespace = prespace;
-
+
d(printf("Filtered '%.*s'\n", *outlen, *out));
}
}
camel_mime_filter_from_class_init (CamelMimeFilterFromClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
camel_mime_filter_from_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
filter_class->filter = filter;
* camel_mime_filter_from_new:
*
* Create a new #CamelMimeFilterFrom object.
- *
+ *
* Returns a new #CamelMimeFilterFrom object
**/
CamelMimeFilterFrom *
prespace = 0;
camel_mime_filter_complete(f, buffer, len, prespace, &buffer, &len, &prespace);
printf("complete = '%.*s'\n", len, buffer);
-
+
return 0;
}
struct _CamelMimeFilterFrom {
CamelMimeFilter parent;
-
+
int midline; /* are we between lines? */
};
guint16 xlen;
guint16 xlen_nread;
guint16 crc16;
-
+
guint8 got_hdr:1;
guint8 is_valid:1;
guint8 got_xlen:1;
struct _CamelMimeFilterGZipPrivate {
z_stream *stream;
-
+
gzip_state_t state;
gzip_hdr_t hdr;
-
+
guint32 crc32;
guint32 isize;
};
camel_mime_filter_gzip_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (),
"CamelMimeFilterGZip",
(CamelObjectInitFunc) camel_mime_filter_gzip_init,
(CamelObjectFinalizeFunc) camel_mime_filter_gzip_finalize);
}
-
+
return type;
}
camel_mime_filter_gzip_class_init (CamelMimeFilterGZipClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
parent_class = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
-
+
filter_class->reset = filter_reset;
filter_class->filter = filter_filter;
filter_class->complete = filter_complete;
{
CamelMimeFilterGZip *gzip = (CamelMimeFilterGZip *) object;
struct _CamelMimeFilterGZipPrivate *priv = gzip->priv;
-
+
if (gzip->mode == CAMEL_MIME_FILTER_GZIP_MODE_ZIP)
deflateEnd (priv->stream);
else
inflateEnd (priv->stream);
-
+
g_free (priv->stream);
g_free (priv);
}
CamelMimeFilterGZip *gzip = (CamelMimeFilterGZip *) filter;
struct _CamelMimeFilterGZipPrivate *priv = gzip->priv;
int retval;
-
+
if (!priv->state.zip.wrote_hdr) {
priv->hdr.v.id1 = 31;
priv->hdr.v.id2 = 139;
struct _CamelMimeFilterGZipPrivate *priv = gzip->priv;
guint16 need, val;
int retval;
-
+
if (!priv->state.unzip.got_hdr) {
if (len < 10) {
camel_mime_filter_backup (filter, in, len);
return;
}
-
+
memcpy (priv->hdr.buf, in, 10);
priv->state.unzip.got_hdr = TRUE;
len -= 10;
in += 10;
-
+
priv->state.unzip.is_valid = (priv->hdr.v.id1 == 31 &&
priv->hdr.v.id2 == 139 &&
priv->hdr.v.cm == Z_DEFLATED);
}
-
+
if (!priv->state.unzip.is_valid)
return;
-
+
if (priv->hdr.v.flg & GZIP_FLAG_FEXTRA) {
if (!priv->state.unzip.got_xlen) {
if (len < 2) {
camel_mime_filter_backup (filter, in, len);
return;
}
-
+
memcpy (&val, in, 2);
priv->state.unzip.xlen = GUINT16_FROM_LE (val);
priv->state.unzip.got_xlen = TRUE;
len -= 2;
in += 2;
}
-
+
if (priv->state.unzip.xlen_nread < priv->state.unzip.xlen) {
need = priv->state.unzip.xlen - priv->state.unzip.xlen_nread;
-
+
if (need < len) {
priv->state.unzip.xlen_nread += need;
len -= need;
}
}
}
-
+
if ((priv->hdr.v.flg & GZIP_FLAG_FNAME) && !priv->state.unzip.got_fname) {
while (*in && len > 0) {
len--;
in++;
}
-
+
if (*in == '\0' && len > 0) {
priv->state.unzip.got_fname = TRUE;
len--;
return;
}
}
-
+
if ((priv->hdr.v.flg & GZIP_FLAG_FCOMMENT) && !priv->state.unzip.got_fcomment) {
while (*in && len > 0) {
len--;
in++;
}
-
+
if (*in == '\0' && len > 0) {
priv->state.unzip.got_fcomment = TRUE;
len--;
char **out, size_t *outlen, size_t *outprespace)
{
CamelMimeFilterGZip *gzip = (CamelMimeFilterGZip *) filter;
-
+
if (gzip->mode == CAMEL_MIME_FILTER_GZIP_MODE_ZIP)
gzip_filter (filter, in, len, prespace, out, outlen, outprespace, Z_SYNC_FLUSH);
else
char **out, size_t *outlen, size_t *outprespace)
{
CamelMimeFilterGZip *gzip = (CamelMimeFilterGZip *) filter;
-
+
if (gzip->mode == CAMEL_MIME_FILTER_GZIP_MODE_ZIP)
gzip_filter (filter, in, len, prespace, out, outlen, outprespace, Z_FULL_FLUSH);
else
{
CamelMimeFilterGZip *gzip = (CamelMimeFilterGZip *) filter;
struct _CamelMimeFilterGZipPrivate *priv = gzip->priv;
-
+
memset (&priv->state, 0, sizeof (priv->state));
-
+
if (gzip->mode == CAMEL_MIME_FILTER_GZIP_MODE_ZIP)
deflateReset (priv->stream);
else
inflateReset (priv->stream);
-
+
priv->crc32 = crc32 (0, Z_NULL, 0);
priv->isize = 0;
}
{
CamelMimeFilterGZip *new;
int retval;
-
+
new = (CamelMimeFilterGZip *) camel_object_new (CAMEL_TYPE_MIME_FILTER_GZIP);
new->mode = mode;
new->level = level;
-
+
if (mode == CAMEL_MIME_FILTER_GZIP_MODE_ZIP)
retval = deflateInit2 (new->priv->stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
else
retval = inflateInit2 (new->priv->stream, -MAX_WBITS);
-
+
if (retval != Z_OK) {
camel_object_unref (new);
return NULL;
}
-
+
return (CamelMimeFilter *) new;
}
struct _CamelMimeFilterGZip {
CamelMimeFilter parent_object;
-
+
struct _CamelMimeFilterGZipPrivate *priv;
-
+
CamelMimeFilterGZipMode mode;
int level;
};
struct _CamelMimeFilterGZipClass {
CamelMimeFilterClass parent_class;
-
+
};
camel_mime_filter_html_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterHTML",
sizeof (CamelMimeFilterHTML),
(CamelObjectInitFunc) camel_mime_filter_html_init,
(CamelObjectFinalizeFunc) camel_mime_filter_html_finalize);
}
-
+
return type;
}
CamelMimeFilterHTML *f = (CamelMimeFilterHTML *) mf;
camel_html_parser_t state;
char *outp;
-
+
d(printf("converting html:\n%.*s\n", (int)inlen, in));
-
+
/* We should generally shrink the data, but this'll do */
camel_mime_filter_set_size (mf, inlen * 2 + 256, FALSE);
outp = mf->outbuf;
-
+
camel_html_parser_set_data (f->priv->ctxt, in, inlen, last);
do {
const char *data;
int len;
-
+
state = camel_html_parser_step(f->priv->ctxt, &data, &len);
-
+
switch(state) {
case CAMEL_HTML_PARSER_DATA:
case CAMEL_HTML_PARSER_ENT:
camel_mime_filter_html_class_init (CamelMimeFilterHTMLClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
camel_mime_filter_html_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
filter_class->reset = reset;
* camel_mime_filter_html_new:
*
* Create a new #CamelMimeFilterHTML object.
- *
+ *
* Returns a new #CamelMimeFilterHTML object
**/
CamelMimeFilterHTML *
camel_mime_filter_index_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (), "CamelMimeFilterIndex",
sizeof (CamelMimeFilterIndex),
NULL,
(CamelObjectFinalizeFunc) camel_mime_filter_index_finalize);
}
-
+
return type;
}
camel_mime_filter_index_class_init (CamelMimeFilterIndexClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
camel_mime_filter_index_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
/*filter_class->reset = reset;*/
* camel_mime_filter_index_new:
*
* Create a new #CamelMimeFilterIndex object
- *
+ *
* Returns a new #CamelMimeFilterIndex object
**/
CamelMimeFilterIndex *
{
CamelMimeFilterClass *mime_filter_class =
(CamelMimeFilterClass *) klass;
-
+
mime_filter_class->filter = filter;
mime_filter_class->complete = complete;
mime_filter_class->reset = reset;
camel_mime_filter_linewrap_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterLinewrap",
sizeof (CamelMimeFilterLinewrap),
NULL,
NULL);
}
-
+
return type;
}
CamelMimeFilterLinewrap *linewrap = (CamelMimeFilterLinewrap *)f;
char *inend, *p, *q;
int nchars = linewrap->nchars;
-
+
/* we'll be adding chars here so we need a bigger buffer */
camel_mime_filter_set_size (f, 3 * len, FALSE);
-
+
p = in;
q = f->outbuf;
inend = in + len;
-
+
while (p < inend) {
if (*p == '\n') {
*q++ = *p++;
*q++ = *p++;
nchars++;
}
-
+
/* line is getting way too long, we must force a wrap here */
if (nchars >= (linewrap->max_len - 1) && *p != '\n') {
*q++ = '\n';
nchars = 0;
}
}
-
+
linewrap->nchars = nchars;
-
+
*out = f->outbuf;
*outlen = q - f->outbuf;
*outprespace = f->outpre;
}
-static void
+static void
complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace,
char **out, size_t *outlen, size_t *outprespace)
{
reset (CamelMimeFilter *f)
{
CamelMimeFilterLinewrap *linewrap = (CamelMimeFilterLinewrap *)f;
-
+
linewrap->nchars = 0;
}
{
CamelMimeFilterLinewrap *linewrap =
CAMEL_MIME_FILTER_LINEWRAP (camel_object_new (CAMEL_MIME_FILTER_LINEWRAP_TYPE));
-
+
linewrap->indent = indent_char;
linewrap->wrap_len = preferred_len;
linewrap->max_len = max_len;
linewrap->nchars = 0;
-
+
return (CamelMimeFilter *) linewrap;
}
struct _CamelMimeFilterLinewrap {
CamelMimeFilter parent;
-
+
guint wrap_len;
guint max_len;
char indent;
camel_mime_filter_pgp_class_init (CamelMimeFilterPgpClass *klass)
{
CamelMimeFilterClass *mime_filter_class = (CamelMimeFilterClass *) klass;
-
+
mime_filter_class->filter = filter;
mime_filter_class->complete = complete;
mime_filter_class->reset = reset;
camel_mime_filter_pgp_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (),
"CamelMimeFilterPgp",
NULL,
NULL);
}
-
+
return type;
}
filter_run (f, in, len, prespace, out, outlen, outprespace, FALSE);
}
-static void
+static void
complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace)
{
filter_run (f, in, len, prespace, out, outlen, outprespace, TRUE);
{
CamelMimeFilterClass *mime_filter_class =
(CamelMimeFilterClass *) klass;
-
+
mime_filter_class->filter = filter;
mime_filter_class->complete = complete;
mime_filter_class->reset = reset;
camel_mime_filter_save_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type(), "CamelMimeFilterSave",
sizeof (CamelMimeFilterSave),
NULL,
NULL);
}
-
+
return type;
}
char **out, size_t *outlen, size_t *outprespace)
{
CamelMimeFilterSave *save = (CamelMimeFilterSave *) f;
-
+
if (save->stream)
camel_stream_write (save->stream, in, len);
-
+
*out = in;
*outlen = len;
*outprespace = f->outpre;
}
-static void
+static void
complete (CamelMimeFilter *f, char *in, size_t len, size_t prespace,
char **out, size_t *outlen, size_t *outprespace)
{
camel_mime_filter_save_new (void)
{
CamelMimeFilterSave *save = CAMEL_MIME_FILTER_SAVE (camel_object_new (CAMEL_MIME_FILTER_SAVE_TYPE));
-
+
save->stream = camel_stream_mem_new ();
-
+
return (CamelMimeFilter *) save;
}
camel_mime_filter_save_new_with_stream (CamelStream *stream)
{
CamelMimeFilterSave *save = CAMEL_MIME_FILTER_SAVE (camel_object_new (CAMEL_MIME_FILTER_SAVE_TYPE));
-
+
save->stream = stream;
camel_object_ref (stream);
-
+
return (CamelMimeFilter *) save;
}
struct _CamelMimeFilterSave {
CamelMimeFilter parent;
-
+
CamelStream *stream;
};
camel_mime_filter_tohtml_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (),
"CamelMimeFilterToHTML",
(CamelObjectInitFunc) camel_mime_filter_tohtml_init,
(CamelObjectFinalizeFunc) camel_mime_filter_tohtml_finalize);
}
-
+
return type;
}
camel_mime_filter_tohtml_finalize (CamelObject *obj)
{
CamelMimeFilterToHTML *filter = (CamelMimeFilterToHTML *) obj;
-
+
camel_url_scanner_free (filter->scanner);
}
camel_mime_filter_tohtml_init (CamelMimeFilterToHTML *filter)
{
filter->scanner = camel_url_scanner_new ();
-
+
filter->flags = 0;
filter->colour = 0;
filter->column = 0;
check_size (CamelMimeFilter *filter, char *outptr, char **outend, size_t len)
{
size_t offset;
-
+
if (*outend - outptr >= len)
return outptr;
-
+
offset = outptr - filter->outbuf;
-
+
camel_mime_filter_set_size (filter, filter->outsize + len, TRUE);
-
+
*outend = filter->outbuf + filter->outsize;
-
+
return filter->outbuf + offset;
}
{
register const char *inptr = in;
int depth = 1;
-
+
if (*inptr++ != '>')
return 0;
-
+
#if FOOLISHLY_UNMUNGE_FROM
/* check that it isn't an escaped From line */
if (!strncmp (inptr, "From", 4))
return 0;
#endif
-
+
while (*inptr != '\n') {
if (*inptr == ' ')
inptr++;
-
+
if (*inptr++ != '>')
break;
-
+
depth++;
}
-
+
return depth;
}
{
CamelMimeFilterToHTML *html = (CamelMimeFilterToHTML *) filter;
const unsigned char *inptr = in;
-
+
while (inptr < inend) {
guint32 u;
-
+
outptr = check_size (filter, outptr, outend, 16);
u = camel_utf8_getc_limit (&inptr, inend);
break;
}
}
-
+
return outptr;
}
return;
}
-
+
camel_mime_filter_set_size (filter, inlen * 2 + 6, FALSE);
-
+
inptr = in;
inend = in + inlen;
outptr = filter->outbuf;
outend = filter->outbuf + filter->outsize;
-
+
if (html->flags & CAMEL_MIME_FILTER_TOHTML_PRE && !html->pre_open) {
outptr = g_stpcpy (outptr, "<pre>");
html->pre_open = TRUE;
html->column = 0;
depth = 0;
-
+
if (html->flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) {
if ((depth = citation_depth (start)) > 0) {
/* FIXME: we could easily support multiple colour depths here */
-
+
outptr = check_size (filter, outptr, &outend, 25);
outptr += sprintf(outptr, "<font color=\"#%06x\">", (html->colour & 0xffffff));
}
outptr = g_stpcpy (outptr, "> ");
html->column += 2;
}
-
+
#define CONVERT_URLS (CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES)
if (html->flags & CONVERT_URLS) {
size_t matchlen, buflen, len;
urlmatch_t match;
-
+
len = inptr - start;
-
+
do {
if (camel_url_scanner_scan (html->scanner, start, len, &match)) {
/* write out anything before the first regex match */
outptr = writeln (filter, (const unsigned char *)start, (const unsigned char *)start + match.um_so,
outptr, &outend);
-
+
start += match.um_so;
len -= match.um_so;
-
+
matchlen = match.um_eo - match.um_so;
-
+
buflen = 20 + strlen (match.prefix) + matchlen + matchlen;
outptr = check_size (filter, outptr, &outend, buflen);
-
+
/* write out the href tag */
outptr = g_stpcpy (outptr, "<a href=\"");
outptr = g_stpcpy (outptr, match.prefix);
memcpy (outptr, start, matchlen);
outptr += matchlen;
outptr = g_stpcpy (outptr, "\">");
-
+
/* now write the matched string */
memcpy (outptr, start, matchlen);
html->column += matchlen;
outptr += matchlen;
start += matchlen;
len -= matchlen;
-
+
/* close the href tag */
outptr = g_stpcpy (outptr, "</a>");
} else {
} else {
outptr = writeln (filter, (const unsigned char *)start, (const unsigned char *)inptr, outptr, &outend);
}
-
+
if ((html->flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) && depth > 0) {
outptr = check_size (filter, outptr, &outend, 8);
outptr = g_stpcpy (outptr, "</font>");
}
-
+
if (inptr < inend) {
if (html->flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_NL) {
outptr = check_size (filter, outptr, &outend, 5);
outptr = g_stpcpy (outptr, "<br>");
}
-
+
*outptr++ = '\n';
}
-
+
start = ++inptr;
} while (inptr < inend);
-
+
if (flush) {
/* flush the rest of our input buffer */
if (start < inend)
outptr = writeln (filter, (const unsigned char *)start, (const unsigned char *)inend, outptr, &outend);
-
+
if (html->pre_open) {
/* close the pre-tag */
outptr = check_size (filter, outptr, &outend, 10);
/* backup */
camel_mime_filter_backup (filter, start, (unsigned) (inend - start));
}
-
+
*out = filter->outbuf;
*outlen = outptr - filter->outbuf;
*outprespace = filter->outpre;
html_convert (filter, in, len, prespace, out, outlen, outprespace, FALSE);
}
-static void
+static void
filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
char **out, size_t *outlen, size_t *outprespace)
{
filter_reset (CamelMimeFilter *filter)
{
CamelMimeFilterToHTML *html = (CamelMimeFilterToHTML *) filter;
-
+
html->column = 0;
html->pre_open = FALSE;
}
camel_mime_filter_tohtml_class_init (CamelMimeFilterToHTMLClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
camel_mime_filter_tohtml_parent = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
-
+
filter_class->reset = filter_reset;
filter_class->filter = filter_filter;
filter_class->complete = filter_complete;
{
CamelMimeFilterToHTML *new;
int i;
-
+
new = CAMEL_MIME_FILTER_TOHTML (camel_object_new (camel_mime_filter_tohtml_get_type ()));
-
+
new->flags = flags;
new->colour = colour;
-
+
for (i = 0; i < NUM_URL_PATTERNS; i++) {
if (patterns[i].mask & flags)
camel_url_scanner_add (new->scanner, &patterns[i].pattern);
}
-
+
return CAMEL_MIME_FILTER (new);
}
CamelMimeFilter *filter;
size_t outlen, outpre;
char *outbuf;
-
+
g_return_val_if_fail (in != NULL, NULL);
-
+
filter = camel_mime_filter_tohtml_new (flags, colour);
-
+
camel_mime_filter_complete (filter, (char *) in, strlen (in), 0,
&outbuf, &outlen, &outpre);
-
+
outbuf = g_strndup (outbuf, outlen);
-
+
camel_object_unref (filter);
-
+
return outbuf;
}
struct _CamelMimeFilterToHTML {
CamelMimeFilter parent;
-
+
struct _CamelUrlScanner *scanner;
-
+
guint32 flags;
guint32 colour;
-
+
guint32 column : 31;
guint32 pre_open : 1;
};
camel_mime_filter_windows_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (),
"CamelMimeFilterWindows",
(CamelObjectInitFunc) camel_mime_filter_windows_init,
(CamelObjectFinalizeFunc) camel_mime_filter_windows_finalize);
}
-
+
return type;
}
camel_mime_filter_windows_finalize (CamelObject *o)
{
CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) o;
-
+
g_free (windows->claimed_charset);
}
camel_mime_filter_windows_init (CamelObject *o)
{
CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) o;
-
+
windows->is_windows = FALSE;
windows->claimed_charset = NULL;
}
CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) filter;
register unsigned char *inptr;
unsigned char *inend;
-
+
if (!windows->is_windows) {
inptr = (unsigned char *) in;
inend = inptr + len;
-
+
while (inptr < inend) {
register unsigned char c = *inptr++;
-
+
if (c >= 128 && c <= 159) {
w(g_warning ("Encountered Windows charset masquerading as %s",
windows->claimed_charset));
}
}
}
-
+
*out = in;
*outlen = len;
*outprespace = prespace;
}
-static void
+static void
filter_complete (CamelMimeFilter *filter, char *in, size_t len, size_t prespace,
char **out, size_t *outlen, size_t *outprespace)
{
filter_reset (CamelMimeFilter *filter)
{
CamelMimeFilterWindows *windows = (CamelMimeFilterWindows *) filter;
-
+
windows->is_windows = FALSE;
}
camel_mime_filter_windows_class_init (CamelMimeFilterWindowsClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
parent_class = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
-
+
filter_class->reset = filter_reset;
filter_class->filter = filter_filter;
filter_class->complete = filter_complete;
camel_mime_filter_windows_new (const char *claimed_charset)
{
CamelMimeFilterWindows *new;
-
+
g_return_val_if_fail (claimed_charset != NULL, NULL);
-
+
new = CAMEL_MIME_FILTER_WINDOWS (camel_object_new (camel_mime_filter_windows_get_type ()));
-
+
new->claimed_charset = g_strdup (claimed_charset);
-
+
return CAMEL_MIME_FILTER (new);
}
camel_mime_filter_windows_is_windows_charset (CamelMimeFilterWindows *filter)
{
g_return_val_if_fail (CAMEL_IS_MIME_FILTER_WINDOWS (filter), FALSE);
-
+
return filter->is_windows;
}
camel_mime_filter_windows_real_charset (CamelMimeFilterWindows *filter)
{
g_return_val_if_fail (CAMEL_IS_MIME_FILTER_WINDOWS (filter), NULL);
-
+
if (filter->is_windows)
return camel_charset_iso_to_windows (filter->claimed_charset);
else
struct _CamelMimeFilterWindows {
CamelMimeFilter parent;
-
+
gboolean is_windows;
char *claimed_charset;
};
struct _CamelMimeFilterWindowsClass {
CamelMimeFilterClass parent_class;
-
+
};
camel_mime_filter_yenc_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_mime_filter_get_type (),
"CamelMimeFilterYenc",
(CamelObjectInitFunc) camel_mime_filter_yenc_init,
NULL);
}
-
+
return type;
}
camel_mime_filter_yenc_class_init (CamelMimeFilterYencClass *klass)
{
CamelMimeFilterClass *filter_class = (CamelMimeFilterClass *) klass;
-
+
parent_class = CAMEL_MIME_FILTER_CLASS (camel_type_get_global_classfuncs (camel_mime_filter_get_type ()));
-
+
filter_class->reset = filter_reset;
filter_class->filter = filter_filter;
filter_class->complete = filter_complete;
{
CamelMimeFilterYenc *yenc = (CamelMimeFilterYenc *) filter;
size_t newlen = 0;
-
+
switch (yenc->direction) {
case CAMEL_MIME_FILTER_YENC_DIRECTION_ENCODE:
/* won't go to more than 2 * (x + 2) + 62 */
if (!(yenc->state & CAMEL_MIME_YDECODE_STATE_DECODE)) {
register char *inptr, *inend;
size_t left;
-
+
inptr = in;
inend = inptr + len;
-
+
/* we cannot start decoding until we have found an =ybegin line */
if (!(yenc->state & CAMEL_MIME_YDECODE_STATE_BEGIN)) {
while (inptr < inend) {
}
break;
}
-
+
/* go to the next line */
while (inptr < inend && *inptr != '\n')
inptr++;
-
+
if (inptr < inend)
inptr++;
}
}
-
+
left = inend - inptr;
if ((yenc->state & CAMEL_MIME_YDECODE_STATE_BEGIN) && left > 0) {
/* we have found an '=ybegin' line but we may yet have an "=ypart" line to
}
}
}
-
+
if ((yenc->state & CAMEL_MIME_YDECODE_STATE_DECODE) && !(yenc->state & CAMEL_MIME_YDECODE_STATE_END)) {
/* all yEnc headers have been found so we can now start decoding */
camel_mime_filter_set_size (filter, len + 3, FALSE);
}
break;
}
-
+
*out = filter->outbuf;
*outlen = newlen;
*outprespace = filter->outpre;
{
CamelMimeFilterYenc *yenc = (CamelMimeFilterYenc *) filter;
size_t newlen = 0;
-
+
switch (yenc->direction) {
case CAMEL_MIME_FILTER_YENC_DIRECTION_ENCODE:
/* won't go to more than 2 * (x + 2) + 62 */
}
break;
}
-
+
*out = filter->outbuf;
*outlen = newlen;
*outprespace = filter->outpre;
filter_reset (CamelMimeFilter *filter)
{
CamelMimeFilterYenc *yenc = (CamelMimeFilterYenc *) filter;
-
+
switch (yenc->direction) {
case CAMEL_MIME_FILTER_YENC_DIRECTION_ENCODE:
yenc->state = CAMEL_MIME_YENCODE_STATE_INIT;
camel_mime_filter_yenc_new (CamelMimeFilterYencDirection direction)
{
CamelMimeFilterYenc *new;
-
+
new = (CamelMimeFilterYenc *) camel_object_new (CAMEL_TYPE_MIME_FILTER_YENC);
new->direction = direction;
-
+
switch (direction) {
case CAMEL_MIME_FILTER_YENC_DIRECTION_ENCODE:
new->state = CAMEL_MIME_YENCODE_STATE_INIT;
default:
g_assert_not_reached ();
}
-
+
return (CamelMimeFilter *) new;
}
camel_mime_filter_yenc_set_state (CamelMimeFilterYenc *yenc, int state)
{
g_return_if_fail (CAMEL_IS_MIME_FILTER_YENC (yenc));
-
+
yenc->state = state;
}
camel_mime_filter_yenc_set_crc (CamelMimeFilterYenc *yenc, guint32 crc)
{
g_return_if_fail (CAMEL_IS_MIME_FILTER_YENC (yenc));
-
+
yenc->crc = crc;
}
camel_mime_filter_yenc_get_part (CamelMimeFilterYenc *yenc)
{
g_return_val_if_fail (CAMEL_IS_MIME_FILTER_YENC (yenc), -1);
-
+
if (yenc->state & CAMEL_MIME_YDECODE_STATE_PART)
return yenc->part;
-
+
return -1;
}
#endif
camel_mime_filter_yenc_get_pcrc (CamelMimeFilterYenc *yenc)
{
g_return_val_if_fail (CAMEL_IS_MIME_FILTER_YENC (yenc), -1);
-
+
return CAMEL_MIME_YENCODE_CRC_FINAL (yenc->pcrc);
}
camel_mime_filter_yenc_get_crc (CamelMimeFilterYenc *yenc)
{
g_return_val_if_fail (CAMEL_IS_MIME_FILTER_YENC (yenc), -1);
-
+
return CAMEL_MIME_YENCODE_CRC_FINAL (yenc->crc);
}
const unsigned char *inend;
unsigned char ch;
int ystate;
-
+
if (*state & CAMEL_MIME_YDECODE_STATE_END)
return 0;
-
+
ystate = *state;
-
+
inend = in + inlen;
outptr = out;
-
+
inptr = in;
while (inptr < inend) {
ch = *inptr++;
-
+
if ((ystate & YENC_NEWLINE_ESCAPE) == YENC_NEWLINE_ESCAPE) {
ystate &= ~CAMEL_MIME_YDECODE_STATE_EOLN;
-
+
if (ch == 'y') {
/* we probably have a =yend here */
ystate |= CAMEL_MIME_YDECODE_STATE_END;
break;
}
}
-
+
if (ch == '\n') {
ystate |= CAMEL_MIME_YDECODE_STATE_EOLN;
continue;
}
-
+
if (ystate & CAMEL_MIME_YDECODE_STATE_ESCAPE) {
ystate &= ~CAMEL_MIME_YDECODE_STATE_ESCAPE;
ch -= 64;
ystate |= CAMEL_MIME_YDECODE_STATE_ESCAPE;
continue;
}
-
+
ystate &= ~CAMEL_MIME_YDECODE_STATE_EOLN;
-
+
*outptr++ = ch -= 42;
-
+
*pcrc = yenc_crc_add (*pcrc, ch);
*crc = yenc_crc_add (*crc, ch);
}
-
+
*state = ystate;
-
+
return outptr - out;
}
const unsigned char *inend;
register int already;
unsigned char ch;
-
+
inend = in + inlen;
outptr = out;
-
+
already = *state;
-
+
inptr = in;
while (inptr < inend) {
ch = (*inptr++);
-
+
*pcrc = yenc_crc_add (*pcrc, ch);
*crc = yenc_crc_add (*crc, ch);
-
+
ch += 42;
-
+
if (ch == '\0' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '=') {
*outptr++ = '=';
*outptr++ = ch + 64;
*outptr++ = ch;
already++;
}
-
+
if (already >= 128) {
*outptr++ = '\n';
already = 0;
}
}
-
+
*state = already;
-
+
return outptr - out;
}
int *state, guint32 *pcrc, guint32 *crc)
{
register unsigned char *outptr;
-
+
outptr = out;
-
+
if (inlen)
outptr += camel_yencode_step (in, inlen, out, state, pcrc, crc);
-
+
if (*state)
*outptr++ = '\n';
-
+
*state = CAMEL_MIME_YENCODE_STATE_INIT;
-
+
return outptr - out;
}
struct _CamelMimeFilterYenc {
CamelMimeFilter parent_object;
-
+
CamelMimeFilterYencDirection direction;
-
+
int part;
-
+
int state;
guint32 pcrc;
guint32 crc;
struct _CamelMimeFilterYencClass {
CamelMimeFilterClass parent_class;
-
+
};
static CamelObjectClass *camel_mime_filter_parent;
-static void complete (CamelMimeFilter *mf, char *in, size_t len,
- size_t prespace, char **out, size_t *outlen,
+static void complete (CamelMimeFilter *mf, char *in, size_t len,
+ size_t prespace, char **out, size_t *outlen,
size_t *outprespace);
static void
camel_mime_filter_get_type (void)
{
static CamelType camel_mime_filter_type = CAMEL_INVALID_TYPE;
-
+
if (camel_mime_filter_type == CAMEL_INVALID_TYPE) {
camel_mime_filter_type = camel_type_register (CAMEL_OBJECT_TYPE, "CamelMimeFilter",
sizeof (CamelMimeFilter),
(CamelObjectInitFunc) camel_mime_filter_init,
(CamelObjectFinalizeFunc) camel_mime_filter_finalize);
}
-
+
return camel_mime_filter_type;
}
* camel_mime_filter_new:
*
* Create a new #CamelMimeFilter object.
- *
+ *
* Returns a new #CamelMimeFilter
**/
CamelMimeFilter *
prespace -= f->backlen;
f->backlen = 0;
}
-
+
filterfunc(f, in, len, prespace, out, outlen, outprespace);
#ifdef MALLOC_CHECK
filter->outptr = filter->outreal + offset;
filter->outbuf = filter->outreal + PRE_HEAD*4;
filter->outsize = size;
- /* this could be offset from the end of the structure, but
+ /* this could be offset from the end of the structure, but
this should be good enough */
filter->outpre = PRE_HEAD*4;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
/* camel-mime-message.c : class for a mime_message */
-/*
+/*
* Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
* Michael Zucchi <notzed@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
CamelMimePartClass *camel_mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_message_class);
CamelMediumClass *camel_medium_class = CAMEL_MEDIUM_CLASS (camel_mime_message_class);
int i;
-
+
parent_class = CAMEL_MIME_PART_CLASS (camel_type_get_global_classfuncs (camel_mime_part_get_type ()));
-
+
header_name_table = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
for (i = 0;header_names[i]; i++)
g_hash_table_insert (header_name_table, header_names[i], GINT_TO_POINTER(i+1));
{
CamelMimeMessage *mime_message = (CamelMimeMessage *)object;
int i;
-
+
mime_message->recipients = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
for (i=0;recipient_names[i];i++) {
g_hash_table_insert(mime_message->recipients, recipient_names[i], camel_internet_address_new());
mime_message->message_id = NULL;
}
-static void
+static void
camel_mime_message_finalize (CamelObject *object)
{
CamelMimeMessage *message = CAMEL_MIME_MESSAGE (object);
-
+
g_free (message->subject);
-
+
g_free (message->message_id);
-
+
if (message->reply_to)
camel_object_unref ((CamelObject *)message->reply_to);
-
+
if (message->from)
camel_object_unref ((CamelObject *)message->from);
-
+
g_hash_table_foreach (message->recipients, unref_recipient, NULL);
g_hash_table_destroy (message->recipients);
}
camel_mime_message_get_type (void)
{
static CamelType camel_mime_message_type = CAMEL_INVALID_TYPE;
-
+
if (camel_mime_message_type == CAMEL_INVALID_TYPE) {
camel_mime_message_type = camel_type_register (camel_mime_part_get_type(), "CamelMimeMessage",
sizeof (CamelMimeMessage),
(CamelObjectInitFunc) camel_mime_message_init,
(CamelObjectFinalizeFunc) camel_mime_message_finalize);
}
-
+
return camel_mime_message_type;
}
* Returns a new #CamelMimeMessage object
**/
CamelMimeMessage *
-camel_mime_message_new (void)
+camel_mime_message_new (void)
{
CamelMimeMessage *mime_message;
mime_message = CAMEL_MIME_MESSAGE (camel_object_new (CAMEL_MIME_MESSAGE_TYPE));
-
+
return mime_message;
}
camel_mime_message_set_date (CamelMimeMessage *message, time_t date, int offset)
{
char *datestr;
-
+
g_assert(message);
-
+
if (date == CAMEL_MESSAGE_DATE_CURRENT) {
struct tm local;
int tz;
-
+
date = time(NULL);
e_localtime_with_offset(date, &local, &tz);
offset = (((tz/60/60) * 100) + (tz/60 % 60));
}
message->date = date;
message->date_offset = offset;
-
+
datestr = camel_header_format_date (date, offset);
CAMEL_MEDIUM_CLASS (parent_class)->set_header ((CamelMedium *)message, "Date", datestr);
g_free (datestr);
{
if (offset)
*offset = msg->date_offset;
-
+
return msg->date;
}
{
if (msg->date_received == CAMEL_MESSAGE_DATE_CURRENT) {
const char *received;
-
+
received = camel_medium_get_header ((CamelMedium *)msg, "received");
if (received)
received = strrchr (received, ';');
if (received)
msg->date_received = camel_header_decode_date (received + 1, &msg->date_received_offset);
}
-
+
if (offset)
*offset = msg->date_received_offset;
-
+
return msg->date_received;
}
camel_mime_message_set_message_id (CamelMimeMessage *mime_message, const char *message_id)
{
char *id;
-
+
g_assert (mime_message);
-
+
g_free (mime_message->message_id);
-
+
if (message_id) {
id = g_strstrip (g_strdup (message_id));
} else {
id = camel_header_msgid_generate ();
}
-
+
mime_message->message_id = id;
id = g_strdup_printf ("<%s>", mime_message->message_id);
CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (mime_message), "Message-Id", id);
camel_mime_message_get_message_id (CamelMimeMessage *mime_message)
{
g_assert (mime_message);
-
+
return mime_message->message_id;
}
camel_mime_message_set_reply_to (CamelMimeMessage *msg, const CamelInternetAddress *reply_to)
{
char *addr;
-
+
g_assert(msg);
-
+
if (msg->reply_to) {
camel_object_unref ((CamelObject *)msg->reply_to);
msg->reply_to = NULL;
}
-
+
if (reply_to == NULL) {
CAMEL_MEDIUM_CLASS (parent_class)->remove_header (CAMEL_MEDIUM (msg), "Reply-To");
return;
}
-
+
msg->reply_to = (CamelInternetAddress *)camel_address_new_clone ((CamelAddress *)reply_to);
addr = camel_address_encode ((CamelAddress *)msg->reply_to);
CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (msg), "Reply-To", addr);
camel_mime_message_get_reply_to (CamelMimeMessage *mime_message)
{
g_assert (mime_message);
-
+
/* TODO: ref for threading? */
-
+
return mime_message->reply_to;
}
camel_mime_message_set_subject (CamelMimeMessage *message, const char *subject)
{
char *text;
-
+
g_assert(message);
-
+
g_free (message->subject);
-
+
if (subject) {
message->subject = g_strstrip (g_strdup (subject));
text = camel_header_encode_string ((unsigned char *) message->subject);
message->subject = NULL;
text = NULL;
}
-
+
CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (message), "Subject", text);
g_free (text);
}
camel_mime_message_get_subject (CamelMimeMessage *mime_message)
{
g_assert(mime_message);
-
+
return mime_message->subject;
}
camel_mime_message_set_from (CamelMimeMessage *msg, const CamelInternetAddress *from)
{
char *addr;
-
+
g_assert(msg);
-
+
if (msg->from) {
camel_object_unref((CamelObject *)msg->from);
msg->from = NULL;
}
-
+
if (from == NULL || camel_address_length((CamelAddress *)from) == 0) {
CAMEL_MEDIUM_CLASS(parent_class)->remove_header(CAMEL_MEDIUM(msg), "From");
return;
}
-
+
msg->from = (CamelInternetAddress *)camel_address_new_clone((CamelAddress *)from);
addr = camel_address_encode((CamelAddress *)msg->from);
CAMEL_MEDIUM_CLASS (parent_class)->set_header(CAMEL_MEDIUM(msg), "From", addr);
camel_mime_message_get_from (CamelMimeMessage *mime_message)
{
g_assert (mime_message);
-
+
/* TODO: we should really ref this for multi-threading to work */
-
+
return mime_message->from;
}
{
char *text;
CamelInternetAddress *addr;
-
+
g_assert(mime_message);
-
+
addr = g_hash_table_lookup (mime_message->recipients, type);
if (addr == NULL) {
g_warning ("trying to set a non-valid receipient type: %s", type);
return;
}
-
+
if (r == NULL || camel_address_length ((CamelAddress *)r) == 0) {
camel_address_remove ((CamelAddress *)addr, -1);
CAMEL_MEDIUM_CLASS (parent_class)->remove_header (CAMEL_MEDIUM (mime_message), type);
return;
}
-
+
/* note this does copy, and not append (cat) */
camel_address_copy ((CamelAddress *)addr, (const CamelAddress *)r);
-
+
/* and sync our headers */
text = camel_address_encode (CAMEL_ADDRESS (addr));
CAMEL_MEDIUM_CLASS (parent_class)->set_header (CAMEL_MEDIUM (mime_message), type, text);
camel_mime_message_get_recipients (CamelMimeMessage *mime_message, const char *type)
{
g_assert(mime_message);
-
+
return g_hash_table_lookup (mime_message->recipients, type);
}
{
CamelURL *url;
char *uri;
-
+
g_assert (mime_message);
-
+
url = camel_url_new (src, NULL);
if (url) {
uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
camel_mime_message_get_source (CamelMimeMessage *mime_message)
{
const char *src;
-
+
g_assert(mime_message);
-
+
src = camel_medium_get_header (CAMEL_MEDIUM (mime_message), "X-Evolution-Source");
if (src) {
while (*src && isspace ((unsigned) *src))
write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
{
CamelMimeMessage *mm = CAMEL_MIME_MESSAGE (data_wrapper);
-
+
/* force mandatory headers ... */
if (mm->from == NULL) {
/* FIXME: should we just abort? Should we make one up? */
}
if (!camel_medium_get_header ((CamelMedium *)mm, "Date"))
camel_mime_message_set_date (mm, CAMEL_MESSAGE_DATE_CURRENT, 0);
-
+
if (mm->subject == NULL)
camel_mime_message_set_subject (mm, "No Subject");
-
+
if (mm->message_id == NULL)
camel_mime_message_set_message_id (mm, NULL);
-
+
/* FIXME: "To" header needs to be set explicitly as well ... */
-
+
if (!camel_medium_get_header ((CamelMedium *)mm, "Mime-Version"))
camel_medium_set_header ((CamelMedium *)mm, "Mime-Version", "1.0");
-
+
return CAMEL_DATA_WRAPPER_CLASS (parent_class)->write_to_stream (data_wrapper, stream);
}
default:
return FALSE;
}
-
+
return TRUE;
}
CamelDataWrapper *containee;
int parts, i;
int go = TRUE;
-
+
if (callback (msg, part, data) == FALSE)
return FALSE;
-
+
containee = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-
+
if (containee == NULL)
return go;
-
+
/* using the object types is more accurate than using the mime/types */
if (CAMEL_IS_MULTIPART (containee)) {
parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
for (i = 0; go && i < parts; i++) {
CamelMimePart *mpart = camel_multipart_get_part (CAMEL_MULTIPART (containee), i);
-
+
go = message_foreach_part_rec (msg, mpart, callback, data);
}
} else if (CAMEL_IS_MIME_MESSAGE (containee)) {
go = message_foreach_part_rec (msg, (CamelMimePart *)containee, callback, data);
}
-
+
return go;
}
{
CamelTransferEncoding encoding;
int *has8bit = data;
-
+
/* check this part, and stop as soon as we are done */
encoding = camel_mime_part_get_encoding (part);
-
+
*has8bit = encoding == CAMEL_TRANSFER_ENCODING_8BIT || encoding == CAMEL_TRANSFER_ENCODING_BINARY;
-
+
return !(*has8bit);
}
camel_mime_message_has_8bit_parts (CamelMimeMessage *msg)
{
int has8bit = FALSE;
-
+
camel_mime_message_foreach_part (msg, check_8bit, &has8bit);
-
+
return has8bit;
}
CamelStream *null;
int idb, idc = -1;
gboolean istext;
-
+
/* we use all these weird stream things so we can do it with streams, and
not have to read the whole lot into memory - although i have a feeling
it would make things a fair bit simpler to do so ... */
-
+
d(printf("starting to check part\n"));
-
+
content = camel_medium_get_content_object ((CamelMedium *)part);
if (content == NULL) {
/* charset might not be right here, but it'll get the right stuff
*charsetp = NULL;
return CAMEL_TRANSFER_ENCODING_DEFAULT;
}
-
+
istext = camel_content_type_is (((CamelDataWrapper *) part)->mime_type, "text", "*");
if (istext) {
flags = CAMEL_BESTENC_GET_CHARSET | CAMEL_BESTENC_GET_ENCODING;
} else {
flags = CAMEL_BESTENC_GET_ENCODING;
}
-
+
/* when building the message, any encoded parts are translated already */
flags |= CAMEL_BESTENC_LF_IS_CRLF;
/* and get any flags the caller passed in */
callerflags = (required & CAMEL_BESTENC_NO_FROM);
flags |= callerflags;
-
+
/* first a null stream, so any filtering is thrown away; we only want the sideeffects */
null = (CamelStream *)camel_stream_null_new ();
filter = camel_stream_filter_new_with_stream (null);
-
+
/* if we're looking for the best charset, then we need to convert to UTF-8 */
if (istext && (required & CAMEL_BESTENC_GET_CHARSET) != 0
&& (charsetin = camel_content_type_param (content->mime_type, "charset"))) {
idc = camel_stream_filter_add (filter, (CamelMimeFilter *)charenc);
charsetin = NULL;
}
-
+
bestenc = camel_mime_filter_bestenc_new (flags);
idb = camel_stream_filter_add (filter, (CamelMimeFilter *)bestenc);
d(printf("writing to checking stream\n"));
camel_object_unref (charenc);
charenc = NULL;
}
-
+
if (istext && (required & CAMEL_BESTENC_GET_CHARSET) != 0) {
charsetin = camel_mime_filter_bestenc_get_best_charset (bestenc);
d(printf("best charset = %s\n", charsetin ? charsetin : "(null)"));
charset = g_strdup (charsetin);
-
+
charsetin = camel_content_type_param (content->mime_type, "charset");
} else {
charset = NULL;
}
-
+
/* if we have US-ASCII, or we're not doing text, we dont need to bother with the rest */
if (istext && charsetin && charset && (required & CAMEL_BESTENC_GET_CHARSET) != 0) {
d(printf("have charset, trying conversion/etc\n"));
-
+
/* now that 'bestenc' has told us what the best encoding is, we can use that to create
a charset conversion filter as well, and then re-add the bestenc to filter the
result to find the best encoding to use as well */
-
+
charenc = camel_mime_filter_charset_new_convert (charsetin, charset);
if (charenc != NULL) {
/* otherwise, try another pass, converting to the real charset */
-
+
camel_mime_filter_reset ((CamelMimeFilter *)bestenc);
camel_mime_filter_bestenc_set_flags (bestenc, CAMEL_BESTENC_GET_ENCODING |
CAMEL_BESTENC_LF_IS_CRLF | callerflags);
-
+
camel_stream_filter_add (filter, (CamelMimeFilter *)charenc);
camel_stream_filter_add (filter, (CamelMimeFilter *)bestenc);
-
+
/* and write it to the new stream */
camel_data_wrapper_write_to_stream (content, (CamelStream *)filter);
-
+
camel_object_unref (charenc);
}
}
-
+
encoding = camel_mime_filter_bestenc_get_best_encoding (bestenc, enctype);
-
+
camel_object_unref (filter);
camel_object_unref (bestenc);
camel_object_unref (null);
-
+
d(printf("done, best encoding = %d\n", encoding));
-
+
if (charsetp)
*charsetp = charset;
else
g_free (charset);
-
+
return encoding;
}
CamelTransferEncoding encoding;
CamelDataWrapper *wrapper;
char *charset;
-
+
wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part));
if (!wrapper)
return FALSE;
-
+
/* we only care about actual content objects */
if (!CAMEL_IS_MULTIPART (wrapper) && !CAMEL_IS_MIME_MESSAGE (wrapper)) {
encoding = find_best_encoding (part, data->required, data->enctype, &charset);
/* we always set the encoding, if we got this far. GET_CHARSET implies
also GET_ENCODING */
camel_mime_part_set_encoding (part, encoding);
-
+
if ((data->required & CAMEL_BESTENC_GET_CHARSET) != 0) {
if (camel_content_type_is (((CamelDataWrapper *) part)->mime_type, "text", "*")) {
char *newct;
-
+
/* FIXME: ick, the part content_type interface needs fixing bigtime */
camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "charset",
charset ? charset : "us-ascii");
newct = camel_content_type_format (((CamelDataWrapper *) part)->mime_type);
if (newct) {
d(printf("Setting content-type to %s\n", newct));
-
+
camel_mime_part_set_content_type (part, newct);
g_free (newct);
}
}
}
-
+
g_free (charset);
}
-
+
return TRUE;
}
camel_mime_message_set_best_encoding (CamelMimeMessage *msg, CamelBestencRequired required, CamelBestencEncoding enctype)
{
struct _enc_data data;
-
+
if ((required & (CAMEL_BESTENC_GET_ENCODING|CAMEL_BESTENC_GET_CHARSET)) == 0)
return;
-
+
data.required = required;
data.enctype = enctype;
-
+
camel_mime_message_foreach_part (msg, best_encoding, &data);
}
struct _check_content_id *check = (struct _check_content_id *) data;
const char *content_id;
gboolean found;
-
+
content_id = camel_mime_part_get_content_id (part);
-
+
found = content_id && !strcmp (content_id, check->content_id) ? TRUE : FALSE;
if (found) {
check->part = part;
camel_object_ref (part);
}
-
+
return !found;
}
camel_mime_message_get_part_by_content_id (CamelMimeMessage *message, const char *id)
{
struct _check_content_id check;
-
+
g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
-
+
if (id == NULL)
return NULL;
-
+
check.content_id = id;
check.part = NULL;
-
+
camel_mime_message_foreach_part (message, check_content_id, &check);
-
+
return check.part;
}
time_t thetime;
int offset;
struct tm tm;
-
+
tmp = camel_header_raw_find (&header, "Sender", NULL);
if (tmp == NULL)
tmp = camel_header_raw_find (&header, "From", NULL);
if (tmp != NULL) {
struct _camel_header_address *addr = camel_header_address_decode (tmp, NULL);
-
+
tmp = NULL;
if (addr) {
if (addr->type == CAMEL_HEADER_ADDRESS_NAME) {
camel_header_address_unref (addr);
}
}
-
+
if (tmp == NULL)
g_string_append (out, "unknown@nodomain.now.au");
-
+
/* try use the received header to get the date */
tmp = camel_header_raw_find (&header, "Received", NULL);
if (tmp) {
if (tmp)
tmp++;
}
-
+
/* if there isn't one, try the Date field */
if (tmp == NULL)
tmp = camel_header_raw_find (&header, "Date", NULL);
-
+
thetime = camel_header_decode_date (tmp, &offset);
thetime += ((offset / 100) * (60 * 60)) + (offset % 100) * 60;
gmtime_r (&thetime, &tm);
tz_days[tm.tm_wday], tz_months[tm.tm_mon],
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_year + 1900);
-
+
ret = out->str;
g_string_free (out, FALSE);
-
+
return ret;
}
printf("%smime-type: %s\n", s, camel_content_type_format(((CamelDataWrapper *)part)->mime_type));
containee = camel_medium_get_content_object((CamelMedium *)part);
-
+
if (containee == NULL)
return;
printf("%scontent class: %s\n", s, ((CamelObject *)containee)->klass->name);
printf("%scontent mime-type: %s\n", s, camel_content_type_format(((CamelDataWrapper *)containee)->mime_type));
-
+
/* using the object types is more accurate than using the mime/types */
if (CAMEL_IS_MULTIPART(containee)) {
parts = camel_multipart_get_number((CamelMultipart *)containee);
for (i = 0; go && i < parts; i++) {
CamelMimePart *mpart = camel_multipart_get_part((CamelMultipart *)containee, i);
-
+
cmm_dump_rec(msg, mpart, body, depth+2);
}
} else if (CAMEL_IS_MIME_MESSAGE(containee)) {
/**
* camel_mime_message_dump:
- * @msg:
- * @body:
- *
+ * @msg:
+ * @body:
+ *
* Dump information about the mime message to stdout.
*
* If body is TRUE, then dump body content of the message as well (currently unimplemented).
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelMimePartClass parent_class;
- /* Virtual methods */
+ /* Virtual methods */
} CamelMimeMessageClass;
void camel_mime_message_set_source (CamelMimeMessage *message,
const char *identity);
const char *camel_mime_message_get_source (CamelMimeMessage *message);
-
+
/* utility functions */
gboolean camel_mime_message_has_8bit_parts (CamelMimeMessage *message);
#include "camel-seekable-stream.h"
#include "camel-stream.h"
-#define r(x)
-#define h(x)
-#define c(x)
-#define d(x)
+#define r(x)
+#define h(x)
+#define c(x)
+#define d(x)
/*#define PRESERVE_HEADERS*/
camel_mime_parser_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (), "CamelMimeParser",
sizeof (CamelMimeParser),
(CamelObjectInitFunc) camel_mime_parser_init,
(CamelObjectFinalizeFunc) camel_mime_parser_finalise);
}
-
+
return type;
}
* camel_mime_parser_new:
*
* Create a new CamelMimeParser object.
- *
+ *
* Return value: A new CamelMimeParser widget.
**/
CamelMimeParser *
/**
* camel_mime_parser_filter_add:
- * @m:
- * @mf:
- *
+ * @m:
+ * @mf:
+ *
* Add a filter that will be applied to any body content before it is passed
* to the caller. Filters may be pipelined to perform multi-pass operations
* on the content, and are applied in the order they were added.
* Note that filters are only applied to the body content of messages, and once
* a filter has been set, all content returned by a filter_step() with a state
* of CAMEL_MIME_PARSER_STATE_BODY will have passed through the filter.
- *
+ *
* Return value: An id that may be passed to filter_remove() to remove
* the filter, or -1 if the operation failed.
**/
/**
* camel_mime_parser_filter_remove:
- * @m:
- * @id:
- *
+ * @m:
+ * @id:
+ *
* Remove a processing filter from the pipeline. There is no
* restriction on the order the filters can be removed.
**/
{
struct _header_scan_state *s = _PRIVATE(m);
struct _header_scan_filter *f, *old;
-
+
f = (struct _header_scan_filter *)&s->filters;
while (f && f->next) {
old = f->next;
/**
* camel_mime_parser_header:
- * @m:
+ * @m:
* @name: Name of header.
* @offset: Pointer that can receive the offset of the header in
* the stream from the start of parsing.
- *
+ *
* Lookup a header by name.
- *
+ *
* Return value: The header value, or NULL if the header is not
* defined.
**/
/**
* camel_mime_parser_headers_raw:
- * @m:
- *
+ * @m:
+ *
* Get the list of the raw headers which are defined for the
* current state of the parser. These headers are valid
* until the next call to parser_step(), or parser_drop_step().
- *
+ *
* Return value: The raw headers, or NULL if there are no headers
* defined for the current part or state. These are READ ONLY.
**/
/**
* camel_mime_parser_preface:
- * @m:
- *
+ * @m:
+ *
* Retrieve the preface text for the current multipart.
* Can only be used when the state is CAMEL_MIME_PARSER_STATE_MULTIPART_END.
- *
+ *
* Return value: The preface text, or NULL if there wasn't any.
**/
const char *
/**
* camel_mime_parser_postface:
- * @m:
- *
+ * @m:
+ *
* Retrieve the postface text for the current multipart.
* Only returns valid data when the current state if
* CAMEL_MIME_PARSER_STATE_MULTIPART_END.
- *
+ *
* Return value: The postface text, or NULL if there wasn't any.
**/
const char *
/**
* camel_mime_parser_from_line:
- * @m:
- *
+ * @m:
+ *
* Get the last scanned "From " line, from a recently scanned from.
* This should only be called in the CAMEL_MIME_PARSER_STATE_FROM state. The
* from line will include the closing \n found (if there was one).
*
* The return value will remain valid while in the CAMEL_MIME_PARSER_STATE_FROM
* state, or any deeper state.
- *
+ *
* Return value: The From line, or NULL if called out of context.
**/
const char *
/**
* camel_mime_parser_init_with_fd:
- * @m:
+ * @m:
* @fd: A valid file descriptor.
- *
+ *
* Initialise the scanner with an fd. The scanner's offsets
* will be relative to the current file position of the file
* descriptor. As a result, seekable descritors should
/**
* camel_mime_parser_init_with_stream:
- * @m:
- * @stream:
- *
+ * @m:
+ * @stream:
+ *
* Initialise the scanner with a source stream. The scanner's
* offsets will be relative to the current file position of
* the stream. As a result, seekable streams should only
* be seeked using the parser seek function.
- *
+ *
* Return value: -1 on error.
**/
int
* camel_mime_parser_scan_from:
* @parser: MIME parser object
* @scan_from: #TRUE if the scanner should scan From lines.
- *
+ *
* Tell the scanner if it should scan "^From " lines or not.
*
* If the scanner is scanning from lines, two additional
camel_mime_parser_scan_from (CamelMimeParser *parser, gboolean scan_from)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
s->scan_from = scan_from;
}
* camel_mime_parser_scan_pre_from:
* @parser: MIME parser object
* @scan_pre_from: #TRUE if we want to get pre-from data.
- *
+ *
* Tell the scanner whether we want to know abou the pre-from
* data during a scan. If we do, then we may get an additional
* state CAMEL_MIME_PARSER_STATE_PRE_FROM which returns the specified data.
camel_mime_parser_scan_pre_from (CamelMimeParser *parser, gboolean scan_pre_from)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
s->scan_pre_from = scan_pre_from;
}
/**
* camel_mime_parser_content_type:
* @parser: MIME parser object
- *
+ *
* Get the content type defined in the current part.
- *
+ *
* Return value: A content_type structure, or NULL if there
* is no content-type defined for this part of state of the
* parser.
camel_mime_parser_content_type (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
/* FIXME: should this search up until it's found the 'right'
content-type? can it? */
if (s->parts)
return s->parts->content_type;
-
+
return NULL;
}
/**
* camel_mime_parser_unstep:
* @parser: MIME parser object
- *
- * Cause the last step operation to repeat itself. If this is
+ *
+ * Cause the last step operation to repeat itself. If this is
* called repeated times, then the same step will be repeated
* that many times.
*
camel_mime_parser_unstep (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
s->unstep++;
}
/**
* camel_mime_parser_drop_step:
* @parser: MIME parser object
- *
+ *
* Drop the last step call. This should only be used
* in conjunction with seeking of the stream as the
* stream may be in an undefined state relative to the
camel_mime_parser_drop_step (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
s->unstep = 0;
folder_scan_drop_step(s);
}
/**
* camel_mime_parser_step:
- * @parser: MIME parser object
+ * @parser: MIME parser object
* @databuffer: Pointer to accept a pointer to the data
* associated with this step (if any). May be #NULL,
* in which case datalength is also ingored.
* @datalength: Pointer to accept a pointer to the data
* length associated with this step (if any).
- *
+ *
* Parse the next part of the MIME message. If _unstep()
* has been called, then continue to return the same state
* for that many calls.
databuffer = &dummy;
datalength = &dummylength;
}
-
+
folder_scan_step(s, databuffer, datalength);
} else
s->unstep--;
/**
* camel_mime_parser_read:
* @parser: MIME parser object
- * @databuffer:
- * @len:
- *
+ * @databuffer:
+ * @len:
+ *
* Read at most @len bytes from the internal mime parser buffer.
*
* Returns the address of the internal buffer in @databuffer,
/**
* camel_mime_parser_tell:
* @parser: MIME parser object
- *
+ *
* Return the current scanning offset. The meaning of this
* value will depend on the current state of the parser.
*
* CAMEL_MIME_PARSER_STATE_*_END, The position of the character starting
* the next section of the scan (the last position + 1 of
* the respective current state).
- *
+ *
* Return value: See above.
**/
off_t
/**
* camel_mime_parser_tell_start_headers:
* @parser: MIME parser object
- *
+ *
* Find out the position within the file of where the
* headers started, this is cached by the parser
* at the time.
- *
+ *
* Return value: The header start position, or -1 if
* no headers were scanned in the current state.
**/
/**
* camel_mime_parser_tell_start_from:
* @parser: MIME parser object
- *
+ *
* If the parser is scanning From lines, then this returns
* the position of the start of the From line.
- *
+ *
* Return value: The start of the from line, or -1 if there
* was no From line, or From lines are not being scanned.
**/
/**
* camel_mime_parser_tell_start_boundary:
* @parser: MIME parser object
- *
+ *
* When parsing a multipart, this returns the start of the last
* boundary.
- *
+ *
* Return value: The start of the boundary, or -1 if there
* was no boundary encountered yet.
**/
* @parser: MIME parser object
* @offset: Number of bytes to offset the seek by.
* @whence: SEEK_SET, SEEK_CUR, SEEK_END
- *
+ *
* Reset the source position to a known value.
*
* Note that if the source stream/descriptor was not
* positioned at 0 to begin with, and an absolute seek
* is specified (whence != SEEK_CUR), then the seek
* position may not match the desired seek position.
- *
+ *
* Return value: The new seek offset, or -1 on
* an error (for example, trying to seek on a non-seekable
* stream or file descriptor).
camel_mime_parser_seek(CamelMimeParser *parser, off_t offset, int whence)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
return folder_seek(s, offset, whence);
}
/**
* camel_mime_parser_state:
* @parser: MIME parser object
- *
+ *
* Get the current parser state.
- *
+ *
* Return value: The current parser state.
**/
camel_mime_parser_state_t
camel_mime_parser_state (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
return s->state;
}
* @mp: MIME parser object
* @newstate: New state
* @boundary: Boundary marker for state.
- *
+ *
* Pre-load a new parser state. Used to post-parse multipart content
* without headers.
**/
/**
* camel_mime_parser_stream:
* @parser: MIME parser object
- *
+ *
* Get the stream, if any, the parser has been initialised
* with. May be used to setup sub-streams, but should not
* be read from directly (without saving and restoring
* the seek position in between).
- *
+ *
* Return value: The stream from _init_with_stream(), or NULL
* if the parser is reading from a file descriptor or is
* uninitialised.
camel_mime_parser_stream (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
return s->stream;
}
/**
* camel_mime_parser_fd:
* @parser: MIME parser object
- *
+ *
* Return the file descriptor, if any, the parser has been
* initialised with.
*
* Should not be read from unless the parser it to terminate,
* or the seek offset can be reset before the next parse
* step.
- *
+ *
* Return value: The file descriptor or -1 if the parser
* is reading from a stream or has not been initialised.
**/
camel_mime_parser_fd (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
return s->fd;
}
camel_mime_parser_errno (CamelMimeParser *parser)
{
struct _header_scan_state *s = _PRIVATE (parser);
-
+
return s->ioerrno;
}
}
/*
- need some way to prime the parser state, so this actually works for
+ need some way to prime the parser state, so this actually works for
other than top-level messages
*/
static off_t
/* again, make sure we're in range */
if (part->boundarylenfinal <= len) {
int extra = part->boundarylenfinal - part->boundarylen;
-
+
/* check the extra stuff on an final boundary, normally -- for mime parts */
if (extra>0) {
*lastone = memcmp(&boundary[part->boundarylen],
{
struct _camel_header_raw *l, *n;
char *content;
-
+
content = strchr(header, ':');
if (content) {
register int len;
n = e_mempool_alloc(h->pool, sizeof(*n));
n->next = NULL;
-
+
len = content-header;
n->name = e_mempool_alloc(h->pool, len+1);
memcpy(n->name, header, len);
n->name[len] = 0;
-
+
content++;
-
+
len = s->outptr - content;
n->value = e_mempool_alloc(h->pool, len+1);
memcpy(n->value, content, len);
n->value[len] = 0;
-
+
n->offset = offset;
-
+
l = (struct _camel_header_raw *)&h->headers;
while (l->next) {
l = l->next;
}
l->next = n;
}
-
+
}
#define header_raw_append_parse(a, b, c) (header_append_mempool(s, h, b, c))
while ((len = folder_read(s))>0 && len >= s->atleast) { /* ensure we have at least enough room here */
inptr = s->inptr;
inend = s->inend-s->atleast+1;
-
+
while (inptr<inend) {
if (!s->midline) {
if (folder_boundary_check(s, inptr, lastone)) {
if ((s->outptr>s->outbuf))
goto header_truncated; /* may not actually be truncated */
-
+
goto header_done;
}
}
-
+
start = inptr;
/* goto next line/sentinal */
while ((*inptr++)!='\n')
;
-
+
g_assert(inptr<=s->inend+1);
-
+
/* check for sentinal or real end of line */
if (inptr > inend) {
h(printf("not at end of line yet, going further\n"));
} else {
/* otherwise, complete header, add it */
s->outptr[0] = 0;
-
+
h(printf("header '%s' at %d\n", s->outbuf, (int)s->header_start));
-
+
header_raw_append_parse(&h->headers, s->outbuf, s->header_start);
s->outptr = s->outbuf;
s->header_start = -1;
}
goto header_truncated;
}
-
+
s->atleast = atleast;
-
+
return h;
-
+
header_truncated:
header_append(s, start, inptr);
-
+
s->outptr[0] = 0;
if (s->outbuf == s->outptr)
goto header_done;
-
+
header_raw_append_parse(&h->headers, s->outbuf, s->header_start);
-
+
s->outptr = s->outbuf;
header_done:
s->inptr = inptr;
/* otherwise, jump to the state of the boundary we actually found */
goto normal_exit;
}
-
+
/* goto the next line */
while ((*inptr++)!='\n')
;
folder_push_part(s, h);
s->state = type;
return;
-
+
case CAMEL_MIME_PARSER_STATE_HEADER:
s->state = CAMEL_MIME_PARSER_STATE_BODY;
-
+
case CAMEL_MIME_PARSER_STATE_BODY:
h = s->parts;
*datalength = 0;
presize = SCAN_HEAD;
f = s->filters;
-
+
do {
hb = folder_scan_content (s, &state, databuffer, datalength);
return;
}
} while (hb == h && *datalength > 0);
-
+
/* check for any filter completion data */
while (f) {
camel_mime_filter_complete(f->filter, *databuffer, *datalength, presize,
if (*datalength > 0)
return;
-
+
s->state = CAMEL_MIME_PARSER_STATE_BODY_END;
break;
-
+
case CAMEL_MIME_PARSER_STATE_MULTIPART:
h = s->parts;
/* This mess looks for the next boundary on this
name = argv[i];
printf("opening: %s", name);
-
+
fd = g_open(name, O_RDONLY|O_BINARY, 0);
if (fd==-1) {
perror("Cannot open mailbox");
h = g_malloc0(sizeof(*h));
h->savestate = CAMEL_MIME_PARSER_STATE_EOF;
folder_push_part(s, h);
-#endif
+#endif
while (s->state != CAMEL_MIME_PARSER_STATE_EOF) {
folder_scan_step(s, &data, &len);
printf("\n -- PARSER STEP RETURN -- %d '%s'\n\n", s->state, states[s->state]);
CAMEL_MIME_PARSER_STATE_BODY, /* scanning body of message */
CAMEL_MIME_PARSER_STATE_MULTIPART, /* got multipart header */
CAMEL_MIME_PARSER_STATE_MESSAGE, /* rfc822 message */
-
+
CAMEL_MIME_PARSER_STATE_PART, /* part of a multipart */
-
+
CAMEL_MIME_PARSER_STATE_END = 8, /* bit mask for 'end' flags */
-
+
CAMEL_MIME_PARSER_STATE_EOF = 8, /* end of file */
CAMEL_MIME_PARSER_STATE_PRE_FROM_END, /* pre from end */
CAMEL_MIME_PARSER_STATE_FROM_END, /* end of whole from bracket */
*
* Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
ct = camel_mime_parser_content_type (mp);
encoding = camel_content_transfer_encoding_decode (camel_mime_parser_header (mp, "Content-Transfer-Encoding", NULL));
-
+
switch (camel_mime_parser_state (mp)) {
case CAMEL_MIME_PARSER_STATE_HEADER:
d(printf("Creating body part\n"));
content = (CamelDataWrapper *) camel_multipart_signed_new ();
else
content = (CamelDataWrapper *) camel_multipart_new ();
-
+
camel_multipart_construct_from_parser((CamelMultipart *)content, mp);
d(printf("Created multi-part\n"));
break;
default:
g_warning("Invalid state encountered???: %u", camel_mime_parser_state (mp));
}
-
+
if (content) {
if (encoding)
content->encoding = camel_transfer_encoding_from_string (encoding);
/* camel-mime-part-utils : Utility for mime parsing and so on */
-/*
+/*
*
- * Author :
+ * Author :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
/* camelMimePart.c : Abstract class for a mime_part */
-/*
+/*
* Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
* Michael Zucchi <notzed@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
static ssize_t write_to_stream (CamelDataWrapper *dw, CamelStream *stream);
static int construct_from_stream (CamelDataWrapper *dw, CamelStream *stream);
-/* from CamelMedium */
+/* from CamelMedium */
static void add_header (CamelMedium *medium, const char *name, const void *value);
static void set_header (CamelMedium *medium, const char *name, const void *value);
static void remove_header (CamelMedium *medium, const char *name);
init_header_name_table();
camel_mime_part_class->construct_from_parser = construct_from_parser;
-
- /* virtual method overload */
+
+ /* virtual method overload */
camel_medium_class->add_header = add_header;
camel_medium_class->set_header = set_header;
camel_medium_class->get_header = get_header;
camel_medium_class->get_headers = get_headers;
camel_medium_class->free_headers = free_headers;
camel_medium_class->set_content_object = set_content_object;
-
+
camel_data_wrapper_class->write_to_stream = write_to_stream;
camel_data_wrapper_class->construct_from_stream= construct_from_stream;
}
camel_mime_part_init (gpointer object, gpointer klass)
{
CamelMimePart *mime_part = CAMEL_MIME_PART (object);
-
+
if (((CamelDataWrapper *) mime_part)->mime_type)
camel_content_type_unref (((CamelDataWrapper *) mime_part)->mime_type);
((CamelDataWrapper *) mime_part)->mime_type = camel_content_type_new ("text", "plain");
-
+
mime_part->description = NULL;
mime_part->disposition = NULL;
mime_part->content_id = NULL;
}
-static void
+static void
camel_mime_part_finalize (CamelObject *object)
{
CamelMimePart *mime_part = CAMEL_MIME_PART (object);
-
+
g_free (mime_part->description);
g_free (mime_part->content_id);
g_free (mime_part->content_MD5);
g_free (mime_part->content_location);
camel_string_list_free (mime_part->content_languages);
camel_content_disposition_unref(mime_part->disposition);
-
+
camel_header_raw_clear(&mime_part->headers);
}
camel_mime_part_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_MEDIUM_TYPE,
"CamelMimePart",
(CamelObjectInitFunc) camel_mime_part_init,
(CamelObjectFinalizeFunc) camel_mime_part_finalize);
}
-
+
return type;
}
set_header (CamelMedium *medium, const char *name, const void *value)
{
CamelMimePart *part = CAMEL_MIME_PART (medium);
-
+
process_header(medium, name, value);
camel_header_raw_replace(&part->headers, name, value, -1);
}
add_header (CamelMedium *medium, const char *name, const void *value)
{
CamelMimePart *part = CAMEL_MIME_PART (medium);
-
+
/* Try to parse the header pair. If it corresponds to something */
/* known, the job is done in the parsing routine. If not, */
/* we simply add the header in a raw fashion */
remove_header (CamelMedium *medium, const char *name)
{
CamelMimePart *part = (CamelMimePart *)medium;
-
+
process_header(medium, name, NULL);
camel_header_raw_remove(&part->headers, name);
}
camel_mime_part_set_filename (CamelMimePart *mime_part, const char *filename)
{
char *str;
-
+
if (mime_part->disposition == NULL)
mime_part->disposition = camel_content_disposition_decode("attachment");
camel_medium_set_header (CAMEL_MEDIUM (mime_part),
"Content-Disposition", str);
g_free(str);
-
+
camel_content_type_set_param (((CamelDataWrapper *) mime_part)->mime_type, "name", filename);
str = camel_content_type_format (((CamelDataWrapper *) mime_part)->mime_type);
camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", str);
if (name)
return name;
}
-
+
return camel_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "name");
}
camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid)
{
char *cid, *id;
-
+
if (contentid)
id = g_strstrip (g_strdup (contentid));
else
id = camel_header_msgid_generate ();
-
+
cid = g_strdup_printf ("<%s>", id);
g_free (id);
camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-ID", cid);
{
if (mime_part->content_languages)
camel_string_list_free (mime_part->content_languages);
-
+
mime_part->content_languages = content_languages;
/* FIXME: translate to a header and set it */
{
CamelDataWrapper *mime_part = CAMEL_DATA_WRAPPER (medium);
CamelContentType *content_type;
-
+
parent_class->set_content_object (medium, content);
-
+
content_type = camel_data_wrapper_get_mime_type_field (content);
if (mime_part->mime_type != content_type) {
char *txt;
-
+
txt = camel_content_type_format (content_type);
camel_medium_set_header (CAMEL_MEDIUM (mime_part), "Content-Type", txt);
g_free (txt);
{
ssize_t len, out, total;
char *v, *ids, *ide;
-
+
/* this is only approximate, based on the next >, this way it retains any content
from the original which may not be properly formatted, etc. It also doesn't handle
the case where an individual messageid is too long, however thats a bad mail to
ssize_t total = 0;
ssize_t count;
int errnosav;
-
+
d(printf("mime_part::write_to_stream\n"));
-
+
/* FIXME: something needs to be done about this ... */
/* TODO: content-languages header? */
-
+
if (mp->headers) {
struct _camel_header_raw *h = mp->headers;
char *val;
ssize_t (*writefn)(CamelStream *stream, struct _camel_header_raw *);
-
+
/* fold/write the headers. But dont fold headers that are already formatted
(e.g. ones with parameter-lists, that we know about, and have created) */
while (h) {
h = h->next;
}
}
-
+
count = camel_stream_write(stream, "\n", 1);
if (count == -1)
return -1;
total += count;
-
+
content = camel_medium_get_content_object(medium);
if (content) {
CamelMimeFilter *filter = NULL;
const char *part_charset = NULL;
gboolean reencode = FALSE;
const char *filename;
-
+
if (camel_content_type_is (dw->mime_type, "text", "*")) {
content_charset = camel_content_type_param (content->mime_type, "charset");
part_charset = camel_content_type_param (dw->mime_type, "charset");
-
+
if (content_charset && part_charset) {
content_charset = e_iconv_charset_name (content_charset);
part_charset = e_iconv_charset_name (part_charset);
}
}
-
+
if (mp->encoding != content->encoding) {
switch (mp->encoding) {
case CAMEL_TRANSFER_ENCODING_BASE64:
break;
}
}
-
+
if (content_charset && part_charset && part_charset != content_charset)
charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (content_charset, part_charset);
-
+
if (filter || charenc) {
filter_stream = camel_stream_filter_new_with_stream(stream);
-
+
/* if we have a character encoder, add that always */
if (charenc) {
camel_stream_filter_add(filter_stream, charenc);
camel_object_unref (charenc);
}
-
+
/* we only re-do crlf on encoded blocks */
if (filter && camel_content_type_is (dw->mime_type, "text", "*")) {
CamelMimeFilter *crlf = camel_mime_filter_crlf_new(CAMEL_MIME_FILTER_CRLF_ENCODE,
CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
-
+
camel_stream_filter_add(filter_stream, crlf);
camel_object_unref (crlf);
}
-
+
if (filter) {
camel_stream_filter_add(filter_stream, filter);
camel_object_unref (filter);
}
-
+
stream = (CamelStream *)filter_stream;
-
+
reencode = TRUE;
}
-
+
if (reencode)
count = camel_data_wrapper_decode_to_stream (content, stream);
else
count = camel_data_wrapper_write_to_stream (content, stream);
-
+
if (filter_stream) {
errnosav = errno;
camel_stream_flush (stream);
camel_object_unref (filter_stream);
errno = errnosav;
}
-
+
if (count == -1)
return -1;
-
+
total += count;
-
+
if (reencode && mp->encoding == CAMEL_TRANSFER_ENCODING_UUENCODE) {
count = camel_stream_write (ostream, "end\n", 4);
if (count == -1)
} else {
g_warning("No content for medium, nothing to write");
}
-
+
return total;
}
char *buf;
size_t len;
int err;
-
+
d(printf("mime_part::construct_from_parser()\n"));
-
+
switch (camel_mime_parser_step(mp, &buf, &len)) {
case CAMEL_MIME_PARSER_STATE_MESSAGE:
/* set the default type of a message always */
* @parser: a #CamelMimeParser object
*
* Constructs a MIME part from a parser.
- *
+ *
* Returns %0 on success or %-1 on fail
**/
int
* @data: data to put into the part
* @length: length of @data
* @type: Content-Type of the data
- *
- * Utility function used to set the content of a mime part object to
+ *
+ * Utility function used to set the content of a mime part object to
* be the provided data. If @length is 0, this routine can be used as
* a way to remove old content (in which case @data and @type are
* ignored and may be %NULL).
**/
-void
+void
camel_mime_part_set_content (CamelMimePart *mime_part,
const char *data, int length,
const char *type) /* why on earth is the type last? */
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */
/* camel-mime-part.h : class for a mime part */
-/*
+/*
*
* Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* Do not change these values directly, you would regret it one day */
struct _CamelMimePart {
CamelMedium parent_object;
-
+
struct _camel_header_raw *headers; /* mime headers */
-
+
/* All fields here are -** PRIVATE **- */
/* TODO: these should be in a camelcontentinfo */
char *description;
typedef struct _CamelMimePartClass {
CamelMediumClass parent_class;
-
+
/* Virtual methods */
int (*construct_from_parser) (CamelMimePart *, CamelMimeParser *);
} CamelMimePartClass;
register unsigned char *outptr, *bufptr;
register guint32 saved;
int uulen, uufill, i;
-
+
outptr = out;
-
+
if (len > 0)
outptr += camel_uuencode_step (in, len, out, uubuf, state, save);
-
+
uufill = 0;
-
+
saved = *save;
i = *state & 0xff;
uulen = (*state >> 8) & 0xff;
-
+
bufptr = uubuf + ((uulen / 3) * 4);
-
+
if (i > 0) {
while (i < 3) {
saved <<= 8 | 0;
uufill++;
i++;
}
-
+
if (i == 3) {
/* convert 3 normal bytes into 4 uuencoded bytes */
unsigned char b0, b1, b2;
-
+
b0 = saved >> 16;
b1 = saved >> 8 & 0xff;
b2 = saved & 0xff;
-
+
*bufptr++ = CAMEL_UUENCODE_CHAR ((b0 >> 2) & 0x3f);
*bufptr++ = CAMEL_UUENCODE_CHAR (((b0 << 4) | ((b1 >> 4) & 0xf)) & 0x3f);
*bufptr++ = CAMEL_UUENCODE_CHAR (((b1 << 2) | ((b2 >> 6) & 0x3)) & 0x3f);
*bufptr++ = CAMEL_UUENCODE_CHAR (b2 & 0x3f);
-
+
i = 0;
saved = 0;
uulen += 3;
}
}
-
+
if (uulen > 0) {
int cplen = ((uulen / 3) * 4);
-
+
*outptr++ = CAMEL_UUENCODE_CHAR ((uulen - uufill) & 0xff);
memcpy (outptr, uubuf, cplen);
outptr += cplen;
*outptr++ = '\n';
uulen = 0;
}
-
+
*outptr++ = CAMEL_UUENCODE_CHAR (uulen & 0xff);
*outptr++ = '\n';
-
+
*save = 0;
*state = 0;
-
+
return outptr - out;
}
unsigned char *inend;
register guint32 saved;
int uulen, i;
-
+
saved = *save;
i = *state & 0xff;
uulen = (*state >> 8) & 0xff;
-
+
inptr = in;
inend = in + len;
-
+
outptr = out;
-
+
bufptr = uubuf + ((uulen / 3) * 4);
-
+
while (inptr < inend) {
while (uulen < 45 && inptr < inend) {
while (i < 3 && inptr < inend) {
saved = (saved << 8) | *inptr++;
i++;
}
-
+
if (i == 3) {
/* convert 3 normal bytes into 4 uuencoded bytes */
unsigned char b0, b1, b2;
-
+
b0 = saved >> 16;
b1 = saved >> 8 & 0xff;
b2 = saved & 0xff;
-
+
*bufptr++ = CAMEL_UUENCODE_CHAR ((b0 >> 2) & 0x3f);
*bufptr++ = CAMEL_UUENCODE_CHAR (((b0 << 4) | ((b1 >> 4) & 0xf)) & 0x3f);
*bufptr++ = CAMEL_UUENCODE_CHAR (((b1 << 2) | ((b2 >> 6) & 0x3)) & 0x3f);
*bufptr++ = CAMEL_UUENCODE_CHAR (b2 & 0x3f);
-
+
i = 0;
saved = 0;
uulen += 3;
}
}
-
+
if (uulen >= 45) {
*outptr++ = CAMEL_UUENCODE_CHAR (uulen & 0xff);
memcpy (outptr, uubuf, ((uulen / 3) * 4));
bufptr = uubuf;
}
}
-
+
*save = saved;
*state = ((uulen & 0xff) << 8) | (i & 0xff);
-
+
return outptr - out;
}
register guint32 saved;
gboolean last_was_eoln;
int uulen, i;
-
+
if (*state & CAMEL_UUDECODE_STATE_END)
return 0;
-
+
saved = *save;
i = *state & 0xff;
uulen = (*state >> 8) & 0xff;
last_was_eoln = TRUE;
else
last_was_eoln = FALSE;
-
+
inend = in + len;
outptr = out;
-
+
inptr = in;
while (inptr < inend) {
if (*inptr == '\n' || last_was_eoln) {
} else {
last_was_eoln = TRUE;
}
-
+
inptr++;
continue;
}
-
+
ch = *inptr++;
-
+
if (uulen > 0) {
/* save the byte */
saved = (saved << 8) | ch;
if (i == 4) {
/* convert 4 uuencoded bytes to 3 normal bytes */
unsigned char b0, b1, b2, b3;
-
+
b0 = saved >> 24;
b1 = saved >> 16 & 0xff;
b2 = saved >> 8 & 0xff;
b3 = saved & 0xff;
-
+
if (uulen >= 3) {
*outptr++ = CAMEL_UUDECODE_CHAR (b0) << 2 | CAMEL_UUDECODE_CHAR (b1) >> 4;
*outptr++ = CAMEL_UUDECODE_CHAR (b1) << 4 | CAMEL_UUDECODE_CHAR (b2) >> 2;
*outptr++ = CAMEL_UUDECODE_CHAR (b1) << 4 | CAMEL_UUDECODE_CHAR (b2) >> 2;
}
}
-
+
i = 0;
saved = 0;
uulen -= 3;
break;
}
}
-
+
*save = saved;
*state = (*state & CAMEL_UUDECODE_STATE_MASK) | ((uulen & 0xff) << 8) | (i & 0xff);
-
+
return outptr - out;
}
unsigned char c;
register int sofar = *save; /* keeps track of how many chars on a line */
register int last = *statep; /* keeps track if last char to end was a space cr etc */
-
+
inptr = in;
inend = in + len;
outptr = out;
sofar += 3;
}
}
-
+
if (camel_mime_is_qpsafe(c)) {
if (sofar > 74) {
*outptr++ = '=';
*outptr++ = '\n';
sofar = 0;
}
-
+
/* delay output of space char */
if (c==' ' || c=='\t') {
last = c;
sofar = 3;
} else
sofar += 3;
-
+
*outptr++ = '=';
*outptr++ = tohex[(c >> 4) & 0xf];
*outptr++ = tohex[c & 0xf];
}
*save = sofar;
*statep = last;
-
+
return (outptr - out);
}
Should it also canonicalise the end of line to CR LF??
Note: Trailing rubbish (at the end of input), like = or =x or =\r will be lost.
-*/
+*/
/**
* camel_quoted_decode_step:
case 0:
while (inptr<inend) {
c = *inptr++;
- if (c=='=') {
+ if (c=='=') {
state = 1;
break;
}
append_latin1 (GString *out, const char *in, size_t len)
{
unsigned int c;
-
+
while (len) {
c = (unsigned int)*in++;
len--;
char *outbase, *outbuf;
size_t outlen;
iconv_t ic;
-
+
ic = e_iconv_open ("UTF-8", charset);
if (ic == (iconv_t) -1)
return FALSE;
outlen = inlen * 6 + 16;
outbuf = outbase = g_malloc(outlen);
-
+
if (e_iconv (ic, &inbuf, &inlen, &outbuf, &outlen) == (size_t) -1) {
w(g_warning("Conversion to '%s' failed: %s", charset, strerror (errno)));
g_free(outbase);
e_iconv_close (ic);
return FALSE;
}
-
+
e_iconv (ic, NULL, NULL, &outbuf, &outlen);
-
+
*outbuf = 0;
g_string_append(out, outbase);
g_free(outbase);
e_iconv_close (ic);
return TRUE;
-
+
}
static GString *
register const char *inptr = in;
const char *inend = in + inlen;
char c;
-
+
while (inptr < inend) {
c = *inptr++;
if (c == '\\' && inptr < inend)
return header_decode_text (in, TRUE, default_charset);
}
-/* how long a sequence of pre-encoded words should be less than, to attempt to
+/* how long a sequence of pre-encoded words should be less than, to attempt to
fit into a properly folded word. Only a guide. */
#define CAMEL_FOLD_PREENCODED (24)
}
inlen -= (inptr - p);
}
-
+
enclen = out-buffer;
-
+
if (enclen) {
/* create token */
out = ascii;
out += sprintf (out, "=?%s?Q?", type);
out += quoted_encode ((unsigned char *) buffer, enclen, (unsigned char *) out, safemask);
sprintf (out, "?=");
-
+
d(printf("converted part = %s\n", ascii));
-
+
g_string_append (outstring, ascii);
}
}
-
+
if (ic != (iconv_t) -1)
e_iconv_close (ic);
}
while (inptr && *inptr) {
gunichar c;
const char *newinptr;
-
+
newinptr = g_utf8_next_char (inptr);
c = g_utf8_get_char ((gchar *) inptr);
if (newinptr == NULL || !g_unichar_validate (c)) {
inptr++;
continue;
}
-
+
if (c < 256 && camel_mime_is_lwsp (c) && !last_was_space) {
/* we've reached the end of a 'word' */
if (word && !(last_was_encoded && encoding)) {
g_string_append_len (out, (const gchar *) start, word - start);
start = word;
}
-
+
switch (encoding) {
case 0:
g_string_append_len (out, (const char *) start, inptr - start);
enum _phrase_word_t type;
int encoding, count = 0;
GList *words = NULL;
-
+
/* break the input into words */
type = WORD_ATOM;
last = inptr;
words = g_list_append (words, word);
count = 0;
}
-
+
start = inptr;
type = WORD_ATOM;
encoding = 0;
encoding = MAX (encoding, 2);
}
}
-
+
last = inptr;
}
-
+
if (count > 0) {
word = g_new0 (struct _phrase_word, 1);
word->start = start;
word->encoding = encoding;
words = g_list_append (words, word);
}
-
+
return words;
}
GList *wordl, *nextl, *words = *wordsp;
struct _phrase_word *word, *next;
gboolean merged = FALSE;
-
+
/* scan the list, checking for words of similar types that can be merged */
wordl = words;
while (wordl) {
word = wordl->data;
nextl = g_list_next (wordl);
-
+
while (nextl) {
next = nextl->data;
/* merge nodes of the same type AND we are not creating too long a string */
words = g_list_remove_link (words, nextl);
g_list_free_1 (nextl);
g_free (next);
-
+
nextl = g_list_next (wordl);
-
+
merged = TRUE;
} else {
/* if it is going to be too long, make sure we include the
break;
}
}
-
+
wordl = g_list_next (wordl);
}
-
+
*wordsp = words;
-
+
return merged;
}
}
break;
}
-
+
g_free (last_word);
wordl = g_list_next (wordl);
-
+
last_word = word;
}
-
+
/* and we no longer need the list */
g_free (word);
g_list_free (words);
-
+
outstr = out->str;
g_string_free (out, FALSE);
-
+
return outstr;
}
{
const char *inptr = *in;
const char *start;
-
+
header_decode_lwsp (&inptr);
start = inptr;
while (camel_mime_is_ttoken (*inptr))
header_decode_word (const char **in)
{
const char *inptr = *in;
-
+
header_decode_lwsp (&inptr);
if (*inptr == '"') {
*in = inptr;
} else
*outptr++ = *inptr++;
}
-
+
*outptr = '\0';
-
+
return outbuf;
}
outlen = inlen * 6 + 16;
outbuf = outbase = g_malloc(outlen);
-
+
ret = e_iconv(ic, &in, &inlen, &outbuf, &outlen);
if (ret != (size_t) -1) {
e_iconv(ic, NULL, 0, &outbuf, &outlen);
const char *inend = in + len;
const char *charset;
char *decoded, *decword, *encoding;
-
+
inptr = memchr (inptr, '\'', len);
if (!inptr)
return NULL;
memcpy(encoding, in, inptr-in);
encoding[inptr-in] = 0;
charset = e_iconv_charset_name (encoding);
-
+
inptr = memchr (inptr + 1, '\'', inend - inptr - 1);
if (!inptr)
return NULL;
camel_header_set_param (struct _camel_header_param **l, const char *name, const char *value)
{
struct _camel_header_param *p = (struct _camel_header_param *)l, *pn;
-
+
if (name == NULL)
return NULL;
-
+
while (p->next) {
pn = p->next;
if (!g_ascii_strcasecmp (pn->name, name)) {
if (pre) {
size_t l = strlen (last);
size_t p = strlen (pre);
-
+
/* dont append ' ' between sucsessive encoded words */
if ((l>6 && last[l-2] == '?' && last[l-1] == '=')
&& (p>6 && pre[0] == '=' && pre[1] == '?')) {
inptr++;
} else {
w(g_warning("invalid route address, no closing '>': %s", *in));
- }
+ }
} else if (name == NULL && comment != NULL && inptr>comment) { /* check for comment after address */
char *text, *tmp;
const char *comstart, *comend;
comend = inptr-1;
while (comend > comstart && comend[0] != ')')
comend--;
-
+
if (comend > comstart) {
d(printf(" looking at subset '%.*s'\n", comend-comstart, comstart));
tmp = g_strndup (comstart, comend-comstart);
}
}
}
-
+
*in = inptr;
-
+
if (addr->len > 0) {
if (!g_utf8_validate (addr->str, addr->len, NULL)) {
/* workaround for invalid addr-specs containing 8bit chars (see bug #42170 for details) */
const char *locale_charset;
GString *out;
-
+
locale_charset = e_iconv_locale_charset ();
-
+
out = g_string_new ("");
-
+
if ((charset == NULL || !append_8bit (out, addr->str, addr->len, charset))
&& (locale_charset == NULL || !append_8bit (out, addr->str, addr->len, locale_charset)))
append_latin1 (out, addr->str, addr->len);
-
+
g_string_free (addr, TRUE);
addr = out;
}
-
+
address = camel_header_address_new_name(name ? name->str : "", addr->str);
}
-
+
d(printf("got mailbox: %s\n", addr->str));
-
+
g_string_free(addr, TRUE);
if (name)
g_string_free(name, TRUE);
-
+
return address;
}
gboolean at = FALSE;
GString *addr;
char *buf;
-
+
d(printf("decoding Content-ID: '%s'\n", in));
-
+
header_decode_lwsp (&inptr);
-
+
/* some lame mailers quote the Content-Id */
if (*inptr == '"')
inptr++;
-
+
/* make sure the content-id is not "" which can happen if we get a
* content-id such as <.@> (which Eudora likes to use...) */
if ((buf = camel_header_msgid_decode (inptr)) != NULL && *buf)
return buf;
-
+
g_free (buf);
-
+
/* ugh, not a valid msg-id - try to get something useful out of it then? */
inptr = in;
header_decode_lwsp (&inptr);
inptr++;
header_decode_lwsp (&inptr);
}
-
+
/* Eudora has been known to use <.@> as a content-id */
if (!(buf = header_decode_word (&inptr)) && !strchr (".@", *inptr))
return NULL;
-
+
addr = g_string_new ("");
header_decode_lwsp (&inptr);
while (buf != NULL || *inptr == '.' || (*inptr == '@' && !at)) {
g_free (buf);
buf = NULL;
}
-
+
if (!at) {
if (*inptr == '.') {
g_string_append_c (addr, *inptr++);
g_string_append_c (addr, *inptr++);
buf = header_decode_atom (&inptr);
}
-
+
header_decode_lwsp (&inptr);
}
-
+
buf = addr->str;
g_string_free (addr, FALSE);
-
+
return buf;
}
struct _camel_header_references *ref;
const char *inptr = *in;
char *id, *word;
-
+
while (*inptr) {
header_decode_lwsp (&inptr);
if (*inptr == '<') {
inptr++; /* Stupid mailer tricks */
}
}
-
+
*in = inptr;
}
camel_header_references_inreplyto_decode (const char *in)
{
struct _camel_header_references *ref = NULL;
-
+
if (in == NULL || in[0] == '\0')
return NULL;
-
+
header_references_decode_single (&in, &ref);
-
+
return ref;
}
camel_header_references_decode (const char *in)
{
struct _camel_header_references *refs = NULL;
-
+
if (in == NULL || in[0] == '\0')
return NULL;
-
+
while (*in)
header_references_decode_single (&in, &refs);
-
+
return refs;
}
{
if (encoding >= sizeof (encodings) / sizeof (encodings[0]))
encoding = 0;
-
+
return encodings[encoding];
}
camel_transfer_encoding_from_string (const char *string)
{
int i;
-
+
if (string != NULL) {
for (i = 0; i < sizeof (encodings) / sizeof (encodings[0]); i++)
if (!g_ascii_strcasecmp (string, encodings[i]))
return i;
}
-
+
return CAMEL_TRANSFER_ENCODING_DEFAULT;
}
else if (a->index < b->index)
res = -1;
}
-
+
return res;
}
g_free(value);
} else if (g_ascii_strcasecmp (name, "boundary") != 0 && !g_utf8_validate(value, -1, NULL)) {
const char *charset = e_iconv_locale_charset();
-
+
if ((node->value = header_convert("UTF-8", charset?charset:"ISO-8859-1", value, strlen(value)))) {
g_free(value);
} else {
GString *out;
guint32 c;
char *str;
-
+
*encoded = FALSE;
-
+
g_return_val_if_fail (in != NULL, NULL);
/* if we have really broken utf8 passed in, we just treat it as binary data */
g_string_append_printf (out, "%%%c%c", tohex[(c >> 4) & 0xf], tohex[c & 0xf]);
}
g_free (outbuf);
-
+
str = out->str;
g_string_free (out, FALSE);
*encoded = TRUE;
-
+
return str;
}
{
GString *out;
char *ret;
-
+
if (ct == NULL)
return NULL;
-
+
out = g_string_new ("");
if (ct->type == NULL) {
g_string_append_printf (out, "text/plain");
g_string_append_printf (out, "%s/%s", ct->type, ct->subtype);
}
camel_header_param_list_format_append (out, ct->params);
-
+
ret = out->str;
g_string_free (out, FALSE);
-
+
return ret;
}
{
if (in)
return decode_token (&in);
-
+
return NULL;
}
time += ((offset / 100) * (60*60)) + (offset % 100)*60;
d(printf("converting date %s", ctime(&time)));
-
+
gmtime_r (&time, &tm);
-
+
return g_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %+05d",
tz_days[tm.tm_wday],
tm.tm_mday, tz_months[tm.tm_mon],
camel_header_to_decode(value);
} else if (!g_ascii_strcasecmp(name, "Content-type")) {
printf("- Decoding content-type\n");
- camel_content_type_dump(camel_content_type_decode(value));
+ camel_content_type_dump(camel_content_type_decode(value));
} else if (!g_ascii_strcasecmp(name, "MIME-Version")) {
printf("- Decoding mime version\n");
camel_header_mime_decode(value);
name = host;
} else
name = "localhost.localdomain";
-
+
COUNT_LOCK ();
msgid = g_strdup_printf ("%d.%d.%d.camel@%s", (int) time (NULL), getpid (), count++, name);
COUNT_UNLOCK ();
-
+
if (ai)
camel_freeaddrinfo(ai);
-
+
return msgid;
}
{ "X-Loop", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" },
/* X-List: gnome-hackers */
/* X-List: gnome-hackers@gnome.org */
- { "X-List", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" },
+ { "X-List", "[ \t]*([^@]+)@?([^ \n\t\r>]*)" },
/* Sender: owner-gnome-hackers@gnome.org */
/* Sender: owner-gnome-hacekrs */
{ "Sender", "[ \t]*owner-([^@]+)@?([^ @\n\t\r>]*)" },
if (errcode != 0) {
char *errstr;
size_t len;
-
+
len = regerror(errcode, &mail_list_magic[i].regex, NULL, 0);
errstr = g_malloc0(len + 1);
regerror(errcode, &mail_list_magic[i].regex, errstr, len);
-
+
g_warning("Internal error, compiling regex failed: %s: %s", mail_list_magic[i].pattern, errstr);
g_free(errstr);
failed++;
if (v != NULL && regexec (&mail_list_magic[i].regex, v, 3, match, 0) == 0 && match[1].rm_so != -1) {
int len1, len2;
char *mlist;
-
+
len1 = match[1].rm_eo - match[1].rm_so;
len2 = match[2].rm_eo - match[2].rm_so;
-
+
mlist = g_malloc (len1 + len2 + 2);
memcpy (mlist, v + match[1].rm_so, len1);
if (len2) {
} else {
mlist[len1] = '\0';
}
-
+
return mlist;
}
}
|| h->type == CAMEL_HEADER_ADDRESS_NONE) {
h->type = CAMEL_HEADER_ADDRESS_GROUP;
camel_header_address_list_append(&h->v.members, member);
- }
+ }
}
}
header_address_list_encode_append (GString *out, int encode, struct _camel_header_address *a)
{
char *text;
-
+
while (a) {
switch (a->type) {
case CAMEL_HEADER_ADDRESS_NAME:
{
GString *out;
char *ret;
-
+
if (a == NULL)
return NULL;
-
+
out = g_string_new ("");
header_address_list_encode_append (out, TRUE, a);
ret = out->str;
g_string_free (out, FALSE);
-
+
return ret;
}
{
GString *out;
char *ret;
-
+
if (a == NULL)
return NULL;
-
+
out = g_string_new ("");
-
+
header_address_list_encode_append (out, FALSE, a);
ret = out->str;
g_string_free (out, FALSE);
-
+
return ret;
}
GString *out;
char *ret;
int i, needunfold = FALSE;
-
+
if (in == NULL)
return NULL;
-
+
/* first, check to see if we even need to fold */
len = headerlen + 2;
p = in;
len += strlen (p);
break;
}
-
+
needunfold = TRUE;
len += n-p;
-
+
if (len >= CAMEL_FOLD_SIZE)
break;
len = 0;
}
if (len < CAMEL_FOLD_SIZE)
return g_strdup (in);
-
+
/* we need to fold, so first unfold (if we need to), then process */
if (needunfold)
inptr = in = camel_header_unfold (in);
-
+
out = g_string_new ("");
outlen = headerlen + 2;
while (*inptr) {
} else {
len = strlen (inptr);
}
-
+
d(printf("next word '%.*s'\n", len, inptr));
-
+
if (outlen + len > CAMEL_FOLD_SIZE) {
d(printf("outlen = %d wordlen = %d\n", outlen, len));
/* strip trailing space */
g_string_append (out, "\n\t");
outlen = 1;
}
-
+
outlen += len;
for (i = 0; i < len; i++) {
g_string_append_c (out, inptr[i]);
}
-
+
inptr += len;
}
ret = out->str;
g_string_free (out, FALSE);
-
+
if (needunfold)
g_free ((char *)in);
-
- return ret;
+
+ return ret;
}
/* simple header folding */
needunfold = TRUE;
len += n-p;
-
+
if (len >= CAMEL_FOLD_SIZE)
break;
len = 0;
if (needunfold)
g_free((char *)in);
- return ret;
+ return ret;
}
char *
iv[0].iov_len = strlen(header->name);
iv[2].iov_base = header->value;
iv[2].iov_len = strlen(header->value);
-
+
do {
len = writev(fd, iv, 4);
} while (len == -1 && errno == EINTR);
-
+
if (len == -1)
return -1;
outlen += len;
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-movemail.h: mbox copy function */
-/*
- * Author:
+/*
+ * Author:
* Dan Winship <danw@ximian.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
camel_multipart_encrypted_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_multipart_get_type (),
"CamelMultipartEncrypted",
(CamelObjectInitFunc) camel_multipart_encrypted_init,
(CamelObjectFinalizeFunc) camel_multipart_encrypted_finalize);
}
-
+
return type;
}
camel_multipart_encrypted_class_init (CamelMultipartEncryptedClass *klass)
{
CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (klass);
-
+
parent_class = (CamelMultipartClass *) camel_multipart_get_type ();
-
+
/* virtual method overload */
camel_data_wrapper_class->set_mime_type_field = set_mime_type_field;
}
camel_multipart_encrypted_init (gpointer object, gpointer klass)
{
CamelMultipartEncrypted *multipart = (CamelMultipartEncrypted *) object;
-
+
camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/encrypted");
-
+
multipart->decrypted = NULL;
}
camel_multipart_encrypted_finalize (CamelObject *object)
{
CamelMultipartEncrypted *mpe = (CamelMultipartEncrypted *) object;
-
+
g_free (mpe->protocol);
-
+
if (mpe->decrypted)
camel_object_unref (mpe->decrypted);
}
set_mime_type_field (CamelDataWrapper *data_wrapper, CamelContentType *mime_type)
{
CamelMultipartEncrypted *mpe = (CamelMultipartEncrypted *) data_wrapper;
-
+
if (mime_type) {
const char *protocol;
-
+
protocol = camel_content_type_param (mime_type, "protocol");
g_free (mpe->protocol);
mpe->protocol = g_strdup (protocol);
}
-
+
((CamelDataWrapperClass *) parent_class)->set_mime_type_field (data_wrapper, mime_type);
}
camel_multipart_encrypted_new (void)
{
CamelMultipartEncrypted *multipart;
-
+
multipart = (CamelMultipartEncrypted *) camel_object_new (CAMEL_MULTIPART_ENCRYPTED_TYPE);
-
+
return multipart;
}
struct _CamelMultipartEncrypted {
CamelMultipart parent_object;
-
+
CamelMimePart *version;
CamelMimePart *content;
CamelMimePart *decrypted;
-
+
char *protocol;
};
struct _CamelMultipartEncryptedClass {
CamelMultipartClass parent_class;
-
+
};
CamelType camel_multipart_encrypted_get_type (void);
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- * camel-multipart.c : Abstract class for a multipart
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * camel-multipart.c : Abstract class for a multipart
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
if (state == CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
mps->end2 = camel_mime_parser_tell_start_boundary(cmp);
-
+
camel_multipart_set_preface(mp, camel_mime_parser_preface(cmp));
camel_multipart_set_postface(mp, camel_mime_parser_postface(cmp));
}
const char *boundary;
ssize_t total = 0;
ssize_t count;
-
+
/* we have 3 basic cases:
1. constructed, we write out the data wrapper stream we got
2. signed content, we create and write out a new stream
if (count == -1)
return -1;
total += count;
-
+
/* boundary */
count = camel_stream_printf(stream, "\n--%s\n", boundary);
if (count == -1)
total += count;
}
- return total;
+ return total;
}
sub = camel_seekable_substream_new((CamelSeekableStream *)((CamelDataWrapper *)mps)->stream, mps->start1, mps->end1);
constream = (CamelStream *)camel_stream_filter_new_with_stream(sub);
camel_object_unref((CamelObject *)sub);
-
+
/* Note: see rfc2015 or rfc3156, section 5 */
canon_filter = camel_mime_filter_canon_new (CAMEL_MIME_FILTER_CANON_CRLF);
camel_stream_filter_add((CamelStreamFilter *)constream, (CamelMimeFilter *)canon_filter);
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- * camel-signed--multipart.h : class for a signed-multipart
+ * camel-signed--multipart.h : class for a signed-multipart
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
/* get the bundary text */
boundary = camel_multipart_get_boundary (multipart);
-
+
/* we cannot write a multipart without a boundary string */
g_return_val_if_fail (boundary, -1);
-
+
/*
* write the preface text (usually something like
* "This is a mime message, if you see this, then
* camel_multipart_set_preface:
* @multipart: a #CamelMultipart object
* @preface: the multipart preface
- *
+ *
* Set the preface text for this multipart. Will be written out infront
* of the multipart. This text should only include US-ASCII strings, and
* be relatively short, and will be ignored by any MIME mail client.
* camel_multipart_set_postface:
* @multipart: a #CamelMultipart object
* @postface: multipat postface
- *
+ *
* Set the postfix text for this multipart. Will be written out after
* the last boundary of the multipart, and ignored by any MIME mail
* client.
CamelMimePart *bodypart;
char *buf;
size_t len;
-
+
g_assert(camel_mime_parser_state(mp) == CAMEL_MIME_PARSER_STATE_MULTIPART);
-
+
/* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */
d(printf("Creating multi-part\n"));
-
+
content_type = camel_mime_parser_content_type(mp);
camel_multipart_set_boundary(multipart,
camel_content_type_param(content_type, "boundary"));
-
+
while (camel_mime_parser_step(mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
camel_mime_parser_unstep(mp);
bodypart = camel_mime_part_new();
camel_multipart_add_part(multipart, bodypart);
camel_object_unref((CamelObject *)bodypart);
}
-
+
/* these are only return valid data in the MULTIPART_END state */
camel_multipart_set_preface(multipart, camel_mime_parser_preface (mp));
camel_multipart_set_postface(multipart, camel_mime_parser_postface (mp));
-
+
err = camel_mime_parser_errno(mp);
if (err != 0) {
errno = err;
*
* Copyright (C) 2004 Ximian Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
struct addrinfo hints, *res;
int retval, len;
char *addr;
-
+
memset (&hints, 0, sizeof (struct addrinfo));
#ifdef HAVE_AI_ADDRCONFIG
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
-
+
if ((retval = getaddrinfo (name, NULL, &hints, &res)) != 0) {
*herr = ai_to_herr (retval);
return -1;
}
-
+
len = ALIGN (strlen (res->ai_canonname) + 1);
if (buflen < IPv6_BUFLEN_MIN + len + res->ai_addrlen + sizeof (char *))
return ERANGE;
-
+
/* h_name */
strcpy (buf, res->ai_canonname);
host->h_name = buf;
buf += len;
-
+
/* h_aliases */
((char **) buf)[0] = NULL;
host->h_aliases = (char **) buf;
buf += sizeof (char *);
-
+
/* h_addrtype and h_length */
host->h_length = res->ai_addrlen;
if (res->ai_family == PF_INET6) {
host->h_addrtype = AF_INET6;
-
+
addr = (char *) &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
} else {
host->h_addrtype = AF_INET;
-
+
addr = (char *) &((struct sockaddr_in *) res->ai_addr)->sin_addr;
}
-
+
memcpy (buf, addr, host->h_length);
addr = buf;
buf += ALIGN (host->h_length);
-
+
/* h_addr_list */
((char **) buf)[0] = addr;
((char **) buf)[1] = NULL;
host->h_addr_list = (char **) buf;
-
+
freeaddrinfo (res);
-
+
return 0;
#else /* No support for IPv6 addresses */
#ifdef HAVE_GETHOSTBYNAME_R
#else
struct hostent *hp;
int retval;
-
+
retval = gethostbyname_r (name, host, buf, buflen, &hp, herr);
if (hp != NULL) {
*herr = 0;
*/
retval = -1;
}
-
+
return retval;
#endif
#else /* No support for gethostbyname_r */
struct hostent *h;
-
+
G_LOCK (gethost_mutex);
-
+
h = gethostbyname (name);
-
+
if (!h) {
*herr = h_errno;
G_UNLOCK (gethost_mutex);
return -1;
}
-
+
GETHOST_PROCESS (h, host, buf, buflen, herr);
-
+
G_UNLOCK (gethost_mutex);
-
+
return 0;
#endif /* HAVE_GETHOSTBYNAME_R */
#endif /* ENABLE_IPv6 */
{
#ifdef ENABLE_IPv6
int retval, len;
-
+
if ((retval = getnameinfo (addr, addrlen, buf, buflen, NULL, 0, NI_NAMEREQD)) != 0) {
*herr = ai_to_herr (retval);
return -1;
}
-
+
len = ALIGN (strlen (buf) + 1);
if (buflen < IPv6_BUFLEN_MIN + len + addrlen + sizeof (char *))
return ERANGE;
-
+
/* h_name */
host->h_name = buf;
buf += len;
-
+
/* h_aliases */
((char **) buf)[0] = NULL;
host->h_aliases = (char **) buf;
buf += sizeof (char *);
-
+
/* h_addrtype and h_length */
host->h_length = addrlen;
host->h_addrtype = type;
-
+
memcpy (buf, addr, host->h_length);
addr = buf;
buf += ALIGN (host->h_length);
-
+
/* h_addr_list */
((char **) buf)[0] = addr;
((char **) buf)[1] = NULL;
host->h_addr_list = (char **) buf;
-
+
return 0;
#else /* No support for IPv6 addresses */
#ifdef HAVE_GETHOSTBYADDR_R
#else
struct hostent *hp;
int retval;
-
+
retval = gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, &hp, herr);
if (hp != NULL) {
*herr = 0;
*/
retval = -1;
}
-
+
return retval;
#endif
#else /* No support for gethostbyaddr_r */
struct hostent *h;
-
+
G_LOCK (gethost_mutex);
-
+
h = gethostbyaddr (addr, addrlen, type);
-
+
if (!h) {
*herr = h_errno;
G_UNLOCK (gethost_mutex);
return -1;
}
-
+
GETHOST_PROCESS (h, host, buf, buflen, herr);
-
+
G_UNLOCK (gethost_mutex);
-
+
return 0;
#endif /* HAVE_GETHOSTBYADDR_R */
#endif /* ENABLE_IPv6 */
worker(msg);
return 0;
}
-
+
reply_port = msg->msg.reply_port = e_msgport_new();
fd = e_msgport_fd(msg->msg.reply_port);
if ((err = pthread_create(&id, NULL, worker, msg)) == 0) {
);
else
camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled"));
-
+
/* We cancel so if the thread impl is decent it causes immediate exit.
We detach so we dont need to wait for it to exit if it isn't.
We check the reply port incase we had a reply in the mean time, which we free later */
msg->hostbuflen *= 2;
msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen);
}
-
+
/* If we got cancelled, dont reply, just free it */
if (msg->cancelled)
goto cancel;
struct _addrinfo_msg *info = data;
info->result = getaddrinfo(info->name, info->service, info->hints, info->res);
-
+
if (info->cancelled) {
cs_freeinfo(info);
} else {
e_msgport_reply((EMsg *)info);
}
-
+
return NULL;
}
#endif /* NEED_ADDRINFO */
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;
memset(&myhints, 0, sizeof(myhints));
else
memcpy (&myhints, hints, sizeof (myhints));
-
+
myhints.ai_family = AF_INET;
hints = &myhints;
#endif
msg->hostbuflen *= 2;
msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen);
}
-
+
if (msg->cancelled)
goto cancel;
msg->host = g_strdup(h.h_name);
} else {
unsigned char *in = (unsigned char *)&sin->sin_addr;
-
+
/* sin_addr is always network order which is big-endian */
msg->host = g_strdup_printf("%u.%u.%u.%u", in[0], in[1], in[2], in[3]);
}
/* there doens't appear to be a return code which says host or serv buffers are too short, lengthen them */
msg->result = getnameinfo(msg->addr, msg->addrlen, msg->host, msg->hostlen, msg->serv, msg->servlen, msg->flags);
-
+
if (msg->cancelled)
cs_freeinfo(msg);
else
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
+ *
* Authors: Michael Zucchi <notzed@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2004 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_news_address_get_type (void)
{
static guint type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_address_get_type (), "CamelNewsAddress",
sizeof (CamelNewsAddress),
NULL,
NULL);
}
-
+
return type;
}
* camel_news_address_new:
*
* Create a new CamelNewsAddress object.
- *
+ *
* Return value: A new CamelNewsAddress widget.
**/
CamelNewsAddress *
camel_nntp_address_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_address_get_type(), "CamelNNTPAddress",
sizeof (CamelNNTPAddress),
(CamelObjectInitFunc) camel_nntp_address_init,
NULL);
}
-
+
return type;
}
camel_nntp_address_add((CamelNNTPAddress *)a, n->newsgroup);
camel_header_newsgroups_free(ha);
}
-
+
return a->addresses->len - count;
}
int i;
GString *out;
char *ret;
-
+
if (a->addresses->len == 0)
return NULL;
-
+
out = g_string_new("");
-
+
for (i = 0;i < a->addresses->len; i++) {
if (i != 0)
g_string_append(out, ", ");
g_string_append(out, g_ptr_array_index(a->addresses, i));
}
-
+
ret = out->str;
g_string_free(out, FALSE);
-
+
return ret;
}
{
if (index < 0 || index >= a->addresses->len)
return;
-
+
g_free(g_ptr_array_index(a->addresses, index));
g_ptr_array_remove_index(a->addresses, index);
}
* camel_nntp_address_new:
*
* Create a new CamelNNTPAddress object.
- *
+ *
* Return value: A new CamelNNTPAddress object.
**/
CamelNNTPAddress *
/**
* camel_nntp_address_add:
* @a: nntp address object
- * @name:
- *
+ * @name:
+ *
* Add a new nntp address to the address object. Duplicates are not added twice.
- *
+ *
* Return value: Index of added entry, or existing matching entry.
**/
int
* @a: nntp address object
* @index: address's array index
* @addressp: Holder for the returned address, or NULL, if not required.
- *
+ *
* Get the address at @index.
- *
+ *
* Return value: TRUE if such an address exists, or FALSE otherwise.
**/
gboolean
}
camel_object_unget_hooks(obj);
}
-
+
return res;
}
for (i=0;i<count;i++) {
char *name = NULL, *value = NULL;
-
+
if (camel_file_util_decode_string(fp, &name) == 0
&& camel_file_util_decode_string(fp, &value) == 0) {
camel_object_meta_set(obj, name, value);
}
count = MIN(count, CAMEL_ARGV_MAX);
-
+
/* we batch up the properties and set them in one go */
argv = g_try_malloc(sizeof(CamelArgV) -
((CAMEL_ARGV_MAX - count) * sizeof(CamelArg)));
if (argv == NULL)
return -1;
-
+
argv->argc = 0;
for (i=0;i<count;i++) {
if (camel_file_util_decode_uint32(fp, &argv->argv[argv->argc].tag) == -1)
0, sizeof(CamelInterface),
cinterface_class_init, cinterface_class_finalise,
cinterface_init, NULL);
-
+
}
return camel_object_type;
CamelHookList *hooks = NULL;
g_return_if_fail(CAMEL_IS_OBJECT(o));
-
+
klass = o->klass;
if (o->hooks)
what = g_strdup_printf("finalised CLASS");
else if (o->magic == CAMEL_INTERFACE_FINALISED_MAGIC)
what = g_strdup_printf("finalised INTERFACE");
- else
+ else
what = g_strdup_printf("junk data");
return what;
what = g_strdup_printf("OBJECT '%s'", ((CamelObject *)o)->klass->name);
else
what = g_strdup_printf("OBJECT '%s'", ((CamelObjectClass *)o)->name);
- }
+ }
if (to == NULL)
to = g_strdup_printf("OBJECT '%s'", ctype->name);
g_warning("Trying to check %s is %s", what, to);
}
pthread_mutex_unlock(&lock);
}
-
+
g_static_rec_mutex_lock(&o->hooks->lock);
-
- return o->hooks;
+
+ return o->hooks;
}
unsigned int
pair = co_find_pair_ptr(obj->klass, interface_name);
if (pair) {
GPtrArray *interfaces = pair->data;
-
+
for (i=0;i<interfaces->len;i++) {
hook = co_find_pair(interfaces->pdata[i], name);
if (hook)
/* lock the object for hook emission */
camel_object_ref(obj);
hooks = camel_object_get_hooks(obj);
-
+
if (hooks->list) {
/* first, copy the items in the list, and say we're in an event */
hooks->depth++;
/**
* camel_object_meta_get:
- * @vo:
- * @name:
- *
+ * @vo:
+ * @name:
+ *
* Get a meta-data on an object.
- *
+ *
* Return value: NULL if the meta-data is not set.
**/
char *
/**
* camel_object_meta_set:
- * @vo:
+ * @vo:
* @name: Name of meta-data. Should be prefixed with class of setter.
* @value: Value to set. If NULL, then the meta-data is removed.
- *
+ *
* Set a meta-data item on an object. If the object supports persistent
* data, then the meta-data will be persistent across sessions.
*
/**
* camel_object_state_read:
- * @vo:
- *
+ * @vo:
+ *
* Read persistent object state from object_set(CAMEL_OBJECT_STATE_FILE).
- *
+ *
* Return value: -1 on error.
**/
int camel_object_state_read(void *vo)
/**
* camel_object_state_write:
- * @vo:
- *
+ * @vo:
+ *
* Write persistent state to the file as set by object_set(CAMEL_OBJECT_STATE_FILE).
- *
+ *
* Return value: -1 on error.
**/
int camel_object_state_write(void *vo)
Add a 'const' bit to the arg type field,
specifying that the object should not be freed.
-
+
And, add free handlers for any pointer objects which are
not const. The free handlers would be hookpairs off of the
class.
/**
* camel_object_bag_new:
- * @hash:
- * @equal:
- * @keycopy:
- * @keyfree:
- *
+ * @hash:
+ * @equal:
+ * @keycopy:
+ * @keyfree:
+ *
* Allocate a new object bag. Object bag's are key'd hash tables of
* camel-objects which can be updated atomically using transaction
* semantics.
- *
- * Return value:
+ *
+ * Return value:
**/
CamelObjectBag *
camel_object_bag_new(GHashFunc hash, GEqualFunc equal, CamelCopyFunc keycopy, GFreeFunc keyfree)
g_hash_table_foreach(bag->object_table, (GHFunc)save_object, objects);
for (i=0;i<objects->len;i++)
camel_object_bag_remove(bag, objects->pdata[i]);
-
+
g_ptr_array_free(objects, TRUE);
g_hash_table_destroy(bag->object_table);
g_hash_table_destroy(bag->key_table);
/**
* camel_object_bag_add:
- * @bag:
- * @key:
- * @vo:
- *
+ * @bag:
+ * @key:
+ * @vo:
+ *
* Add an object @vo to the object bag @bag. The @key MUST have
* previously been reserved using camel_object_bag_reserve().
**/
g_hash_table_insert(bag->key_table, vo, k);
co_bag_unreserve(bag, key);
-
+
REF_UNLOCK();
camel_object_unget_hooks(o);
}
/**
* camel_object_bag_get:
- * @bag:
- * @key:
- *
+ * @bag:
+ * @key:
+ *
* Lookup an object by @key. If the key is currently reserved, then
* wait until the key has been committed before continuing.
- *
+ *
* Return value: NULL if the object corresponding to @key is not
* in the bag. Otherwise a ref'd object pointer which the caller owns
* the ref to.
co_bag_unreserve(bag, key);
}
}
-
+
REF_UNLOCK();
-
+
return o;
}
/**
* camel_object_bag_peek:
- * @bag:
- * @key:
- *
+ * @bag:
+ * @key:
+ *
* Lookup the object @key in @bag, ignoring any reservations. If it
* isn't committed, then it isn't considered. This should only be
* used where reliable transactional-based state is not required.
- *
+ *
* Unlike other 'peek' operations, the object is still reffed if
* found.
*
/**
* camel_object_bag_reserve:
- * @bag:
- * @key:
- *
+ * @bag:
+ * @key:
+ *
* Reserve a key in the object bag. If the key is already reserved in
* another thread, then wait until the reservation has been committed.
*
*
* You may reserve multiple keys from the same thread, but they should
* always be reserved in the same order, to avoid deadlocks.
- *
- * Return value:
+ *
+ * Return value:
**/
void *
camel_object_bag_reserve(CamelObjectBag *bag, const void *key)
bag->reserved = res;
}
}
-
+
REF_UNLOCK();
return o;
/**
* camel_object_bag_abort:
- * @bag:
- * @key:
- *
+ * @bag:
+ * @key:
+ *
* Abort a key reservation.
**/
void
/**
* camel_object_bag_rekey:
- * @bag:
- * @o:
- * @newkey:
- *
+ * @bag:
+ * @o:
+ * @newkey:
+ *
* Re-key an object, atomically. The key for object @o is set to
* @newkey, in an atomic manner.
*
REF_LOCK();
camel_object_bag_remove_unlocked(inbag, o, hooks);
-
+
REF_UNLOCK();
camel_object_unget_hooks(o);
}
{
g_assert(it);
g_return_val_if_fail(((CamelIterator *)it)->klass->length != NULL, 0);
-
+
return ((CamelIterator *)it)->klass->length(it);
}
camel_offline_folder_get_type (void)
{
static CamelType type = NULL;
-
+
if (!type) {
type = camel_type_register (CAMEL_FOLDER_TYPE,
"CamelOfflineFolder",
(CamelObjectInitFunc) camel_offline_folder_init,
(CamelObjectFinalizeFunc) camel_offline_folder_finalize);
}
-
+
return type;
}
camel_offline_folder_class_init (CamelOfflineFolderClass *klass)
{
int i;
-
+
parent_class = (CamelFolderClass *) camel_type_get_global_classfuncs (CAMEL_FOLDER_TYPE);
-
+
if (offline_folder_props == NULL) {
for (i = 0; i < G_N_ELEMENTS (offline_prop_list); i++) {
offline_prop_list[i].description = _(offline_prop_list[i].description);
offline_folder_props = g_slist_prepend (offline_folder_props, &offline_prop_list[i]);
}
}
-
+
((CamelObjectClass *) klass)->getv = offline_folder_getv;
((CamelObjectClass *) klass)->setv = offline_folder_setv;
-
+
klass->downsync = offline_folder_downsync;
}
struct _offline_downsync_msg {
CamelSessionThreadMsg msg;
-
+
CamelFolder *folder;
CamelFolderChangeInfo *changes;
};
struct _offline_downsync_msg *m = (struct _offline_downsync_msg *) mm;
CamelMimeMessage *message;
int i;
-
+
camel_operation_start (NULL, _("Downloading new messages for offline mode"));
-
+
if (m->changes) {
for (i = 0; i < m->changes->uid_added->len; i++) {
int pc = i * 100 / m->changes->uid_added->len;
-
+
camel_operation_progress (NULL, pc);
if ((message = camel_folder_get_message (m->folder, m->changes->uid_added->pdata[i], &mm->ex)))
camel_object_unref (message);
} else {
camel_offline_folder_downsync ((CamelOfflineFolder *) m->folder, "(match-all)", &mm->ex);
}
-
+
camel_operation_end (NULL);
}
offline_downsync_free (CamelSession *session, CamelSessionThreadMsg *mm)
{
struct _offline_downsync_msg *m = (struct _offline_downsync_msg *) mm;
-
+
if (m->changes)
camel_folder_change_info_free (m->changes);
-
+
camel_object_unref (m->folder);
}
{
CamelOfflineFolder *offline = (CamelOfflineFolder *) folder;
CamelService *service = (CamelService *) folder->parent_store;
-
+
if (changes->uid_added->len > 0 && (offline->sync_offline || camel_url_get_param (service->url, "sync_offline"))) {
CamelSession *session = service->session;
struct _offline_downsync_msg *m;
-
+
m = camel_session_thread_msg_new (session, &offline_downsync_ops, sizeof (*m));
m->changes = camel_folder_change_info_new ();
camel_folder_change_info_cat (m->changes, changes);
camel_object_ref (folder);
m->folder = folder;
-
+
camel_session_thread_queue (session, &m->msg, 0);
}
}
static void
camel_offline_folder_init (CamelOfflineFolder *folder, CamelOfflineFolderClass *klass)
-{
+{
camel_object_hook_event (folder, "folder_changed", (CamelObjectEventHookFunc) offline_folder_changed, NULL);
}
CamelArgGetV props;
int i, count = 0;
guint32 tag;
-
+
for (i = 0; i < args->argc; i++) {
CamelArgGet *arg = &args->argv[i];
-
+
tag = arg->tag;
-
+
switch (tag & CAMEL_ARG_TAG) {
case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES:
case CAMEL_FOLDER_ARG_PROPERTIES:
count++;
continue;
}
-
+
arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
}
-
+
if (count)
return ((CamelObjectClass *) parent_class)->getv (object, ex, args);
-
+
return 0;
}
gboolean save = FALSE;
guint32 tag;
int i;
-
+
for (i = 0; i < args->argc; i++) {
CamelArg *arg = &args->argv[i];
-
+
tag = arg->tag;
-
+
switch (tag & CAMEL_ARG_TAG) {
case CAMEL_OFFLINE_FOLDER_ARG_SYNC_OFFLINE:
if (folder->sync_offline != arg->ca_int) {
default:
continue;
}
-
+
arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
}
-
+
if (save)
camel_object_state_write (object);
-
+
return ((CamelObjectClass *) parent_class)->setv (object, ex, args);
}
CamelMimeMessage *message;
GPtrArray *uids;
int i;
-
+
camel_operation_start (NULL, _("Syncing messages in folder '%s' to disk"), folder->full_name);
-
+
if (expression)
uids = camel_folder_search_by_expression (folder, expression, ex);
else
uids = camel_folder_get_uids (folder);
-
+
if (!uids) {
camel_operation_end (NULL);
return;
}
-
+
for (i = 0; i < uids->len; i++) {
int pc = i * 100 / uids->len;
-
+
message = camel_folder_get_message (folder, uids->pdata[i], ex);
camel_operation_progress (NULL, pc);
if (message == NULL)
break;
-
+
camel_object_unref (message);
}
-
+
if (expression)
camel_folder_search_free (folder, uids);
else
camel_folder_free_uids (folder, uids);
-
+
camel_operation_end (NULL);
}
camel_offline_folder_downsync (CamelOfflineFolder *offline, const char *expression, CamelException *ex)
{
g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline));
-
+
CAMEL_OFFLINE_FOLDER_GET_CLASS (offline)->downsync (offline, expression, ex);
}
struct _CamelOfflineFolder {
CamelFolder parent_object;
-
+
unsigned int sync_offline:1;
};
struct _CamelOfflineFolderClass {
CamelFolderClass parent_class;
-
+
void (* downsync) (CamelOfflineFolder *folder, const char *expression, CamelException *ex);
};
camel_offline_journal_get_type (void)
{
static CamelType type = NULL;
-
+
if (!type) {
type = camel_type_register (camel_object_get_type (),
"CamelOfflineJournal",
(CamelObjectInitFunc) camel_offline_journal_init,
(CamelObjectFinalizeFunc) camel_offline_journal_finalize);
}
-
+
return type;
}
{
CamelOfflineJournal *journal = (CamelOfflineJournal *) object;
EDListNode *entry;
-
+
g_free (journal->filename);
-
+
while ((entry = e_dlist_remhead (&journal->queue)))
CAMEL_OFFLINE_JOURNAL_GET_CLASS (journal)->entry_free (journal, entry);
}
{
EDListNode *entry;
FILE *fp;
-
+
journal->filename = g_strdup (filename);
journal->folder = folder;
-
+
if ((fp = g_fopen (filename, "rb"))) {
while ((entry = CAMEL_OFFLINE_JOURNAL_GET_CLASS (journal)->entry_load (journal, fp)))
e_dlist_addtail (&journal->queue, entry);
-
+
fclose (fp);
}
}
camel_offline_journal_set_filename (CamelOfflineJournal *journal, const char *filename)
{
g_return_if_fail (CAMEL_IS_OFFLINE_JOURNAL (journal));
-
+
g_free (journal->filename);
journal->filename = g_strdup (filename);
}
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) {
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;
}
EDListNode *entry, *next;
CamelException lex;
int failed = 0;
-
+
camel_exception_init (&lex);
-
+
entry = journal->queue.head;
while (entry->next) {
next = entry->next;
}
entry = next;
}
-
+
if (failed > 0)
return -1;
-
+
return 0;
}
struct _CamelOfflineJournal {
CamelObject parent_object;
-
+
struct _CamelFolder *folder;
char *filename;
EDList queue;
struct _CamelOfflineJournalClass {
CamelObjectClass parent_class;
-
+
/* entry methods */
void (* entry_free) (CamelOfflineJournal *journal, EDListNode *entry);
-
+
EDListNode * (* entry_load) (CamelOfflineJournal *journal, FILE *in);
int (* entry_write) (CamelOfflineJournal *journal, EDListNode *entry, FILE *out);
int (* entry_play) (CamelOfflineJournal *journal, EDListNode *entry, CamelException *ex);
camel_offline_store_get_type (void)
{
static CamelType type = NULL;
-
+
if (!type) {
type = camel_type_register (CAMEL_STORE_TYPE,
"CamelOfflineStore",
(CamelObjectInitFunc) camel_offline_store_init,
(CamelObjectFinalizeFunc) camel_offline_store_finalize);
}
-
+
return type;
}
camel_offline_store_class_init (CamelOfflineStoreClass *klass)
{
parent_class = (CamelStoreClass *) camel_type_get_global_classfuncs (CAMEL_STORE_TYPE);
-
+
((CamelServiceClass *) klass)->construct = offline_store_construct;
}
CamelException *ex)
{
CamelOfflineStore *store = CAMEL_OFFLINE_STORE (service);
-
+
CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
if (camel_exception_is_set (ex))
return;
-
+
store->state = camel_session_is_online (session) ?
CAMEL_OFFLINE_STORE_NETWORK_AVAIL : CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL;
}
if (store->state == state)
return;
-
+
camel_exception_init (&lex);
if (store->state == CAMEL_OFFLINE_STORE_NETWORK_AVAIL) {
/* network available -> network unavailable */
GPtrArray *folders;
CamelFolder *folder;
int i, sync;
-
+
sync = camel_url_get_param (((CamelService *) store)->url, "sync_offline") != NULL;
-
+
folders = camel_object_bag_list (((CamelStore *) store)->folders);
for (i = 0; i < folders->len; i++) {
folder = folders->pdata[i];
-
+
if (CAMEL_CHECK_TYPE (folder, CAMEL_OFFLINE_FOLDER_TYPE)
&& (sync || ((CamelOfflineFolder *) folder)->sync_offline)) {
camel_offline_folder_downsync ((CamelOfflineFolder *) folder, NULL, &lex);
camel_exception_clear (&lex);
}
-
+
camel_object_unref (folder);
}
-
+
g_ptr_array_free (folders, TRUE);
}
-
+
camel_store_sync (CAMEL_STORE (store), FALSE, &lex);
camel_exception_clear (&lex);
}
if (!camel_service_connect (CAMEL_SERVICE (store), ex))
return;
}
-
+
store->state = state;
}
struct _CamelOfflineStore {
CamelStore parent_object;
-
+
int state;
};
struct _CamelOfflineStoreClass {
CamelStoreClass parent_class;
-
+
void (* set_network_state) (CamelOfflineStore *store, int state, CamelException *ex);
};
* @status: Callback for receiving status messages. This will always
* be called with an internal lock held.
* @status_data: User data.
- *
+ *
* Create a new camel operation handle. Camel operation handles can
* be used in a multithreaded application (or a single operation
* handle can be used in a non threaded appliation) to cancel running
* operations and to obtain notification messages of the internal
* status of messages.
- *
+ *
* Return value: A new operation handle.
**/
CamelOperation *
LOCK();
e_dlist_addtail(&operation_list, (EDListNode *)cc);
UNLOCK();
-
+
return cc;
}
/**
* camel_operation_mute:
- * @cc:
- *
+ * @cc:
+ *
* mutes a camel operation permanently. from this point on you will never
* receive operation updates, even if more are sent.
**/
/**
* camel_operation_ref:
* @cc: operation context
- *
+ *
* Add a reference to the CamelOperation @cc.
**/
void
/**
* camel_operation_unref:
* @cc: operation context
- *
+ *
* Unref and potentially free @cc.
**/
void
LOCK();
if (cc->refcount == 1) {
CamelOperationMsg *msg;
-
+
e_dlist_remove((EDListNode *)cc);
while ((msg = (CamelOperationMsg *)e_msgport_get(cc->cancel_port)))
g_free(msg);
e_msgport_destroy(cc->cancel_port);
-
+
n = cc->status_stack;
while (n) {
g_warning("Camel operation status stack non empty: %s", (char *)n->data);
/**
* camel_operation_cancel_block:
* @cc: operation context
- *
+ *
* Block cancellation for this operation. If @cc is NULL, then the
* current thread is blocked.
**/
/**
* camel_operation_cancel_unblock:
* @cc: operation context
- *
+ *
* Unblock cancellation, when the unblock count reaches the block
* count, then this operation can be cancelled. If @cc is NULL, then
* the current thread is unblocked.
/**
* camel_operation_cancel:
* @cc: operation context
- *
+ *
* Cancel a given operation. If @cc is NULL then all outstanding
* operations are cancelled.
**/
camel_operation_cancel (CamelOperation *cc)
{
CamelOperationMsg *msg;
-
+
LOCK();
if (cc == NULL) {
/**
* camel_operation_uncancel:
* @cc: operation context
- *
+ *
* Uncancel a cancelled operation. If @cc is NULL then the current
* operation is uncancelled.
*
/**
* camel_operation_register:
* @cc: operation context
- *
+ *
* Register a thread or the main thread for cancellation through @cc.
* If @cc is NULL, then a new cancellation is created for this thread.
*
/**
* camel_operation_unregister:
* @cc: operation context
- *
+ *
* Unregister the current thread for all cancellations.
**/
void
/**
* camel_operation_cancel_check:
* @cc: operation context
- *
+ *
* Check if cancellation has been applied to @cc. If @cc is NULL,
* then the CamelOperation registered for the current thread is used.
- *
+ *
* Return value: TRUE if the operation has been cancelled.
**/
gboolean
/**
* camel_operation_cancel_fd:
* @cc: operation context
- *
+ *
* Retrieve a file descriptor that can be waited on (select, or poll)
* for read, to asynchronously detect cancellation.
- *
+ *
* Return value: The fd, or -1 if cancellation is not available
* (blocked, or has not been registered for this thread).
**/
/**
* camel_operation_cancel_prfd:
* @cc: operation context
- *
+ *
* Retrieve a file descriptor that can be waited on (select, or poll)
* for read, to asynchronously detect cancellation.
- *
+ *
* Return value: The fd, or NULL if cancellation is not available
* (blocked, or has not been registered for this thread).
**/
* @cc: operation context
* @what: action being performed (printf-style format string)
* @Varargs: varargs
- *
+ *
* Report the start of an operation. All start operations should have
* similar end operations.
**/
* @cc: operation context
* @what: printf-style format string describing the action being performed
* @Varargs: varargs
- *
+ *
* Start a transient event. We only update this to the display if it
* takes very long to process, and if we do, we then go back to the
* previous state when finished.
* camel_operation_progress:
* @cc: Operation to report to.
* @pc: Percent complete, 0 to 100.
- *
+ *
* Report progress on the current operation. If @cc is NULL, then the
* currently registered operation is used. @pc reports the current
* percentage of completion, which should be in the range of 0 to 100.
* camel_operation_end:
* @cc: operation context
* @what: Format string.
- * @Varargs: varargs
- *
+ * @Varargs: varargs
+ *
* Report the end of an operation. If @cc is NULL, then the currently
* registered operation is notified.
**/
camel_object_unref((CamelObject *)cpi->blocks);
}
-
+
pthread_mutex_destroy(&p->lock);
-
+
g_free(p);
}
camel_partition_table_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelPartitionTable",
sizeof (CamelPartitionTable),
(CamelObjectInitFunc) camel_partition_table_init,
(CamelObjectFinalizeFunc) camel_partition_table_finalise);
}
-
+
return type;
}
{
CamelBlock *bl, *bn;
int ret = 0;
-
+
CAMEL_PARTITION_TABLE_LOCK(cpi, lock);
-
+
if (cpi->blocks) {
bl = (CamelBlock *)cpi->partition.head;
bn = bl->next;
}
CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock);
-
+
camel_block_file_unref_block(cpi->blocks, block);
return keyid;
hashid = hash_key(key);
CAMEL_PARTITION_TABLE_LOCK(cpi, lock);
-
+
ptblock = find_partition(cpi, hashid, &index);
if (ptblock == NULL) {
CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock);
if (pkb->keys[i].hashid == hashid) {
/* !! need to: lookup and compare string value */
/* get_key() if key == key ... */
-
+
/* remove this key */
pkb->used--;
for (;i<pkb->used;i++) {
}
CAMEL_PARTITION_TABLE_UNLOCK(cpi, lock);
-
+
camel_block_file_unref_block(cpi->blocks, block);
}
camel_block_file_sync(ki->blocks);
camel_object_unref((CamelObject *)ki->blocks);
}
-
+
pthread_mutex_destroy(&p->lock);
-
+
g_free(p);
}
camel_key_table_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_object_get_type(), "CamelKeyTable",
sizeof (CamelKeyTable),
(CamelObjectInitFunc) camel_key_table_init,
(CamelObjectFinalizeFunc) camel_key_table_finalise);
}
-
+
return type;
}
do {
blockid = next & (~(CAMEL_BLOCK_SIZE-1));
index = next & (CAMEL_BLOCK_SIZE-1);
-
+
bl = camel_block_file_get_block(ki->blocks, blockid);
if (bl == NULL) {
CAMEL_KEY_TABLE_UNLOCK(ki, lock);
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
struct _CamelStreamFilter *filter_stream;
struct _CamelIndex *index;
-
+
GMutex *summary_lock; /* for the summary hashtable/array */
GMutex *io_lock; /* load/save lock, for access to saved_count, etc */
GMutex *filter_lock; /* for accessing any of the filtering/indexing stuff, since we share them */
gboolean destroyed;
GList *folders; /* lock using subfolder_lock before changing/accessing */
GList *folders_changed; /* for list of folders that have changed between updates */
-
+
GMutex *summary_lock; /* for locking vfolder summary */
GMutex *subfolder_lock; /* for locking the subfolder list */
GMutex *changed_lock; /* for locking the folders-changed list */
{
int errnosav, fd[6], i;
pid_t pid;
-
+
for (i = 0; i < 6; i++)
fds[i] = -1;
-
+
for (i = 0; i < 6; i += 2) {
if (pipe (fd + i) == -1) {
errnosav = errno;
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to create pipe to '%s': %s"),
argv[0], strerror (errno));
-
+
for (i = 0; i < 6; i++) {
if (fd[i] == -1)
break;
close (fd[i]);
}
-
+
errno = errnosav;
-
+
return -1;
}
}
-
+
if (!(pid = fork ())) {
/* child process */
int maxfd, nullfd = -1;
-
+
if (!outfd || !errfd)
nullfd = open ("/dev/null", O_WRONLY);
-
+
if (dup2 (fd[0], STDIN_FILENO) == -1)
_exit (255);
-
+
if (dup2 (outfd ? fd[3] : nullfd, STDOUT_FILENO) == -1)
_exit (255);
-
+
if (dup2 (errfd ? fd[5] : nullfd, STDERR_FILENO) == -1)
_exit (255);
-
+
setsid ();
-
+
if ((maxfd = sysconf (_SC_OPEN_MAX)) > 0) {
for (i = 3; i < maxfd; i++)
fcntl (i, F_SETFD, FD_CLOEXEC);
}
-
+
execv (path, argv);
_exit (255);
} else if (pid == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to create child process '%s': %s"),
argv[0], strerror (errno));
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++)
close (fd[i]);
return -1;
}
-
+
/* parent process */
close (fd[0]);
close (fd[3]);
close (fd[5]);
-
+
if (infd)
*infd = fd[1];
else
close (fd[1]);
-
+
if (outfd)
*outfd = fd[2];
else
close (fd[2]);
-
+
if (errfd)
*errfd = fd[4];
else
close (fd[4]);
-
+
return pid;
}
sigset_t mask, omask;
int status;
pid_t r;
-
+
sigemptyset (&mask);
sigaddset (&mask, SIGALRM);
sigprocmask (SIG_BLOCK, &mask, &omask);
alarm (1);
-
+
r = waitpid (pid, &status, 0);
-
+
alarm (0);
sigprocmask (SIG_SETMASK, &omask, NULL);
-
+
if (r == (pid_t) -1 && errno == EINTR) {
kill (pid, SIGTERM);
sleep (1);
r = waitpid (pid, &status, WNOHANG);
}
}
-
+
if (r != (pid_t) -1 && WIFEXITED (status))
return WEXITSTATUS (status);
else
static CamelProvider vee_provider = {
"vfolder",
N_("Virtual folder email provider"),
-
+
N_("For reading mail as a query of another set of folders"),
-
+
"vfolder",
-
+
CAMEL_PROVIDER_IS_STORAGE,
CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH,
-
+
/* ... */
};
CAMEL_PROVIDERDIR, g_strerror (errno));
return;
}
-
+
while ((entry = g_dir_read_name (dir))) {
FILE *fp;
-
+
p = strrchr (entry, '.');
if (!p || strcmp (p, ".urls") != 0)
continue;
-
+
name = g_strdup_printf ("%s/%s", CAMEL_PROVIDERDIR, entry);
fp = g_fopen (name, "r");
if (!fp) {
g_free (name);
continue;
}
-
+
p = strrchr (name, '.');
strcpy (p, "." G_MODULE_SUFFIX);
p = strchr (buf, '\n');
if (p)
*p = '\0';
-
+
if (*buf) {
char *protocol = g_strdup(buf);
* Loads the provider at @path, and calls its initialization function,
* passing @session as an argument. The provider should then register
* itself with @session.
- **/
+ **/
void
camel_provider_load(const char *path, CamelException *ex)
{
UNLOCK();
return;
}
-
+
for (i = 0; i < CAMEL_NUM_PROVIDER_TYPES; i++) {
if (provider->object_types[i])
provider->service_cache[i] = camel_object_bag_new (provider->url_hash, provider->url_equal,
typedef struct {
/* Provider name used in CamelURLs. */
char *protocol;
-
+
/* Provider name as used by people. (May be the same as protocol) */
char *name;
-
+
/* Description of the provider. A novice user should be able
* to read this description, and the information provided by
* an ISP, IS department, etc, and determine whether or not
* information goes with it.
*/
char *description;
-
+
/* The category of message that this provider works with.
* (evolution-mail will only list a provider in the store/transport
* config dialogs if its domain is "mail".)
*/
char *domain;
-
+
/* Flags describing the provider, flags describing its URLs */
int flags, url_flags;
/* The ConfEntry and AutoDetect functions will probably be
* DEPRECATED in a future release */
-
+
/* Extra configuration information */
CamelProviderConfEntry *extra_conf;
* uses the store type (eg, Exchange or NNTP).
*/
CamelType object_types[CAMEL_NUM_PROVIDER_TYPES];
-
+
/* GList of CamelServiceAuthTypes the provider supports */
GList *authtypes;
-
+
CamelObjectBag *service_cache[CAMEL_NUM_PROVIDER_TYPES];
-
+
GHashFunc url_hash;
GCompareFunc url_equal;
/* This string points to the provider's gconf key value
*/
const char *license;
-
+
/* This holds the license file name [ ascii text format ] containing
- * the license agreement. This should be the absolute file path. This
+ * the license agreement. This should be the absolute file path. This
* is read only when the HAS_LICENSE flag is set
*/
const char *license_file;
- /* Private to the provider */
+ /* Private to the provider */
void *priv;
} CamelProvider;
CamelServiceAuthType camel_sasl_anonymous_authtype = {
N_("Anonymous"),
-
+
N_("This option will connect to the server using an anonymous login."),
-
+
"ANONYMOUS",
FALSE
};
camel_sasl_anonymous_class_init (CamelSaslAnonymousClass *camel_sasl_anonymous_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_anonymous_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = anon_challenge;
}
camel_sasl_anonymous_finalize (CamelObject *object)
{
CamelSaslAnonymous *sasl = CAMEL_SASL_ANONYMOUS (object);
-
+
g_free (sasl->trace_info);
}
camel_sasl_anonymous_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslAnonymous",
NULL,
(CamelObjectFinalizeFunc) camel_sasl_anonymous_finalize);
}
-
+
return type;
}
camel_sasl_anonymous_new (CamelSaslAnonTraceType type, const char *trace_info)
{
CamelSaslAnonymous *sasl_anon;
-
+
if (!trace_info && type != CAMEL_SASL_ANON_TRACE_EMPTY) return NULL;
-
+
sasl_anon = CAMEL_SASL_ANONYMOUS (camel_object_new (camel_sasl_anonymous_get_type ()));
sasl_anon->trace_info = g_strdup (trace_info);
sasl_anon->type = type;
-
+
return CAMEL_SASL (sasl_anon);
}
typedef struct _CamelSaslAnonymous {
CamelSasl parent_object;
-
+
char *trace_info;
CamelSaslAnonTraceType type;
} CamelSaslAnonymous;
typedef struct _CamelSaslAnonymousClass {
CamelSaslClass parent_class;
-
+
} CamelSaslAnonymousClass;
camel_sasl_cram_md5_class_init (CamelSaslCramMd5Class *camel_sasl_cram_md5_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_cram_md5_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = cram_md5_challenge;
}
camel_sasl_cram_md5_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslCramMd5",
NULL,
NULL);
}
-
+
return type;
}
typedef struct _CamelSaslCramMd5Class {
CamelSaslClass parent_class;
-
+
} CamelSaslCramMd5Class;
camel_sasl_digest_md5_class_init (CamelSaslDigestMd5Class *camel_sasl_digest_md5_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_digest_md5_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = digest_md5_challenge;
}
camel_sasl_digest_md5_init (gpointer object, gpointer klass)
{
CamelSaslDigestMd5 *sasl_digest = CAMEL_SASL_DIGEST_MD5 (object);
-
+
sasl_digest->priv = g_new0 (struct _CamelSaslDigestMd5Private, 1);
}
struct _DigestResponse *r = sasl->priv->response;
GList *p;
int i;
-
+
if (c != NULL) {
for (i = 0; i < c->realms->len; i++)
g_free (c->realms->pdata[i]);
g_ptr_array_free (c->realms, TRUE);
-
+
g_free (c->nonce);
g_free (c->charset);
g_free (c->algorithm);
for (p = c->params; p; p = p->next) {
struct _param *param = p->data;
-
+
g_free (param->name);
g_free (param->value);
g_free (param);
g_list_free (c->params);
g_free (c);
}
-
+
if (r != NULL) {
g_free (r->username);
g_free (r->realm);
g_free (r->param);
g_free (r);
}
-
+
g_free (sasl->priv);
}
camel_sasl_digest_md5_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslDigestMd5",
(CamelObjectInitFunc) camel_sasl_digest_md5_init,
(CamelObjectFinalizeFunc) camel_sasl_digest_md5_finalize);
}
-
+
return type;
}
decode_lwsp (const char **in)
{
const char *inptr = *in;
-
+
while (isspace (*inptr))
inptr++;
-
+
*in = inptr;
}
char *out = NULL, *outptr;
int outlen;
int c;
-
+
decode_lwsp (&inptr);
if (*inptr == '"') {
const char *intmp;
int skip = 0;
-
+
/* first, calc length */
inptr++;
intmp = inptr;
skip++;
}
}
-
+
outlen = intmp - inptr - skip;
out = outptr = g_malloc (outlen + 1);
-
+
while ((c = *inptr++) && c != '"') {
if (c == '\\' && *inptr) {
c = *inptr++;
}
*outptr = '\0';
}
-
+
*in = inptr;
-
+
return out;
}
{
const char *inptr = *in;
const char *start;
-
+
decode_lwsp (&inptr);
start = inptr;
-
+
while (*inptr && *inptr != '=' && *inptr != ',')
inptr++;
-
+
if (inptr > start) {
*in = inptr;
return g_strndup (start, inptr - start);
decode_value (const char **in)
{
const char *inptr = *in;
-
+
decode_lwsp (&inptr);
if (*inptr == '"') {
d(printf ("decoding quoted string token\n"));
GList *params = NULL;
struct _param *param;
const char *ptr;
-
+
for (ptr = tokens; ptr && *ptr; ) {
param = g_new0 (struct _param, 1);
param->name = decode_token (&ptr);
ptr++;
param->value = decode_value (&ptr);
}
-
+
params = g_list_prepend (params, param);
-
+
if (*ptr == ',')
ptr++;
}
-
+
return params;
}
decode_data_type (DataType *dtype, const char *name)
{
int i;
-
+
for (i = 0; dtype[i].name; i++) {
if (!g_ascii_strcasecmp (dtype[i].name, name))
break;
}
-
+
return dtype[i].type;
}
type_to_string (DataType *dtype, guint type)
{
int i;
-
+
for (i = 0; dtype[i].name; i++) {
if (dtype[i].type == type)
break;
}
-
+
return dtype[i].name;
}
gboolean got_maxbuf = FALSE;
gboolean got_charset = FALSE;
#endif /* PARANOID */
-
+
params = parse_param_list (tokens);
if (!params) {
*abort = TRUE;
return NULL;
}
-
+
*abort = FALSE;
-
+
challenge = g_new0 (struct _DigestChallenge, 1);
challenge->realms = g_ptr_array_new ();
challenge->maxbuf = 65536;
-
+
for (p = params; p; p = p->next) {
struct _param *param = p->data;
int type;
-
+
type = get_digest_arg (param->name);
switch (type) {
case DIGEST_REALM:
for (ptr = param->value; ptr && *ptr; ) {
char *token;
-
+
token = decode_token (&ptr);
if (token)
g_ptr_array_add (challenge->realms, token);
-
+
if (*ptr == ',')
ptr++;
}
case DIGEST_QOP:
for (ptr = param->value; ptr && *ptr; ) {
char *token;
-
+
token = decode_token (&ptr);
if (token)
challenge->qop |= decode_qop (token);
-
+
if (*ptr == ',')
ptr++;
}
-
+
if (challenge->qop & QOP_INVALID)
challenge->qop = QOP_INVALID;
g_free (param->value);
case DIGEST_CIPHER:
for (ptr = param->value; ptr && *ptr; ) {
char *token;
-
+
token = decode_token (&ptr);
if (token)
challenge->cipher |= decode_cipher (token);
-
+
if (*ptr == ',')
ptr++;
}
break;
}
}
-
+
g_list_free (params);
-
+
return challenge;
}
resp->realm = g_strdup (challenge->realms->pdata[0]);
else
resp->realm = g_strdup ("");
-
+
resp->nonce = g_strdup (challenge->nonce);
-
+
/* generate the cnonce */
bgen = g_strdup_printf ("%p:%lu:%lu", (void *) resp,
(unsigned long) getpid (),
GByteArray *buffer;
const char *str;
char *buf;
-
+
buffer = g_byte_array_new ();
g_byte_array_append (buffer, (guint8 *) "username=\"", 10);
if (resp->charset) {
guchar out[33];
char *tokens;
struct addrinfo *ai, hints;
-
+
/* Need to wait for the server */
if (!token)
return NULL;
-
+
g_return_val_if_fail (sasl->service->url->passwd != NULL, NULL);
-
+
switch (priv->state) {
case STATE_AUTH:
if (token->len > 2048) {
_("Server challenge invalid\n"));
return NULL;
}
-
+
if (priv->challenge->qop == QOP_INVALID) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Server challenge contained invalid "
rspauth->value = decode_value (&ptr);
}
g_free (tokens);
-
+
if (!rspauth->value) {
g_free (rspauth->name);
g_free (rspauth);
_("Server response contained incomplete authorization data"));
return NULL;
}
-
+
compute_response (priv->response, sasl->service->url->passwd, FALSE, out);
if (memcmp (out, rspauth->value, 32) != 0) {
g_free (rspauth->name);
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Server response does not match"));
sasl->authenticated = TRUE;
-
+
return NULL;
}
-
+
g_free (rspauth->name);
g_free (rspauth->value);
g_free (rspauth);
-
+
ret = g_byte_array_new ();
-
+
sasl->authenticated = TRUE;
default:
break;
}
-
+
priv->state++;
-
+
return ret;
}
typedef struct _CamelSaslDigestMd5 {
CamelSasl parent_object;
struct _CamelSaslDigestMd5Private *priv;
-
+
} CamelSaslDigestMd5;
typedef struct _CamelSaslDigestMd5Class {
CamelSaslClass parent_class;
-
+
} CamelSaslDigestMd5Class;
#ifdef HAVE_HEIMDAL_KRB5
#include <gssapi.h>
#else
-#ifdef HAVE_SUN_KRB5
+#ifdef HAVE_SUN_KRB5
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_ext.h>
extern gss_OID gss_nt_service_name;
CamelServiceAuthType camel_sasl_gssapi_authtype = {
N_("GSSAPI"),
-
+
N_("This option will connect to the server using "
"Kerberos 5 authentication."),
-
+
"GSSAPI",
FALSE
};
camel_sasl_gssapi_class_init (CamelSaslGssapiClass *klass)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (klass);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = gssapi_challenge;
}
camel_sasl_gssapi_init (gpointer object, gpointer klass)
{
CamelSaslGssapi *gssapi = CAMEL_SASL_GSSAPI (object);
-
+
gssapi->priv = g_new (struct _CamelSaslGssapiPrivate, 1);
gssapi->priv->state = GSSAPI_STATE_INIT;
gssapi->priv->ctx = GSS_C_NO_CONTEXT;
{
CamelSaslGssapi *gssapi = CAMEL_SASL_GSSAPI (object);
guint32 status;
-
+
if (gssapi->priv->ctx != GSS_C_NO_CONTEXT)
gss_delete_sec_context (&status, &gssapi->priv->ctx, GSS_C_NO_BUFFER);
-
+
if (gssapi->priv->target != GSS_C_NO_NAME)
gss_release_name (&status, &gssapi->priv->target);
-
+
g_free (gssapi->priv);
}
camel_sasl_gssapi_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (
camel_sasl_get_type (),
(CamelObjectInitFunc) camel_sasl_gssapi_init,
(CamelObjectFinalizeFunc) camel_sasl_gssapi_finalize);
}
-
+
return type;
}
gssapi_set_exception (OM_uint32 major, OM_uint32 minor, CamelException *ex)
{
const char *str;
-
+
switch (major) {
case GSS_S_BAD_MECH:
str = _("The specified mechanism is not supported by the "
default:
str = _("Bad authentication response from server.");
}
-
+
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, str);
}
gss_OID mech;
char *str;
struct addrinfo *ai, hints;
-
+
switch (priv->state) {
case GSSAPI_STATE_INIT:
memset(&hints, 0, sizeof(hints));
ai = camel_getaddrinfo(sasl->service->url->host?sasl->service->url->host:"localhost", NULL, &hints, ex);
if (ai == NULL)
return NULL;
-
+
str = g_strdup_printf("%s@%s", sasl->service_name, ai->ai_canonname);
camel_freeaddrinfo(ai);
-
+
inbuf.value = str;
inbuf.length = strlen (str);
major = gss_import_name (&minor, &inbuf, GSS_C_NT_HOSTBASED_SERVICE, &priv->target);
g_free (str);
-
+
if (major != GSS_S_COMPLETE) {
gssapi_set_exception (major, minor, ex);
return NULL;
}
-
+
input_token = GSS_C_NO_BUFFER;
-
+
goto challenge;
break;
case GSSAPI_STATE_CONTINUE_NEEDED:
_("Bad authentication response from server."));
return NULL;
}
-
+
inbuf.value = token->data;
inbuf.length = token->len;
input_token = &inbuf;
-
+
challenge:
major = gss_init_sec_context (&minor, GSS_C_NO_CREDENTIAL, &priv->ctx, priv->target,
GSS_C_OID_KRBV5_DES, GSS_C_MUTUAL_FLAG |
GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG,
0, GSS_C_NO_CHANNEL_BINDINGS,
input_token, &mech, &outbuf, &flags, &time);
-
+
switch (major) {
case GSS_S_COMPLETE:
priv->state = GSSAPI_STATE_COMPLETE;
gssapi_set_exception (major, minor, ex);
return NULL;
}
-
+
challenge = g_byte_array_new ();
g_byte_array_append (challenge, outbuf.value, outbuf.length);
#ifndef HAVE_HEIMDAL_KRB5
_("Bad authentication response from server."));
return NULL;
}
-
+
inbuf.value = token->data;
inbuf.length = token->len;
-
+
major = gss_unwrap (&minor, priv->ctx, &inbuf, &outbuf, &conf_state, &qop);
if (major != GSS_S_COMPLETE) {
gssapi_set_exception (major, minor, ex);
return NULL;
}
-
+
if (outbuf.length < 4) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Bad authentication response from server."));
#endif
return NULL;
}
-
+
/* check that our desired security layer is supported */
if ((((unsigned char *) outbuf.value)[0] & DESIRED_SECURITY_LAYER) != DESIRED_SECURITY_LAYER) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
#endif
return NULL;
}
-
+
inbuf.length = 4 + strlen (sasl->service->url->user);
inbuf.value = str = g_malloc (inbuf.length);
memcpy (inbuf.value, outbuf.value, 4);
str[0] = DESIRED_SECURITY_LAYER;
memcpy (str + 4, sasl->service->url->user, inbuf.length - 4);
-
+
#ifndef HAVE_HEIMDAL_KRB5
gss_release_buffer (&minor, &outbuf);
#endif
-
+
major = gss_wrap (&minor, priv->ctx, FALSE, qop, &inbuf, &conf_state, &outbuf);
if (major != GSS_S_COMPLETE) {
gssapi_set_exception (major, minor, ex);
g_free (str);
return NULL;
}
-
+
g_free (str);
challenge = g_byte_array_new ();
g_byte_array_append (challenge, outbuf.value, outbuf.length);
-
+
#ifndef HAVE_HEIMDAL_KRB5
gss_release_buffer (&minor, &outbuf);
#endif
-
+
priv->state = GSSAPI_STATE_AUTHENTICATED;
-
+
sasl->authenticated = TRUE;
break;
default:
return NULL;
}
-
+
return challenge;
}
struct _CamelSaslGssapi {
CamelSasl parent_object;
-
+
struct _CamelSaslGssapiPrivate *priv;
-
+
};
struct _CamelSaslGssapiClass {
CamelSaslClass parent_class;
-
+
};
/* Standard Camel function */
struct _CamelSaslKerberos4Private {
int state;
-
+
guint32 nonce_n;
guint32 nonce_h;
-
+
des_cblock session;
des_key_schedule schedule;
};
camel_sasl_kerberos4_class_init (CamelSaslKerberos4Class *camel_sasl_kerberos4_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_kerberos4_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = krb4_challenge;
}
camel_sasl_kerberos4_init (gpointer object, gpointer klass)
{
CamelSaslKerberos4 *sasl_krb4 = CAMEL_SASL_KERBEROS4 (object);
-
+
sasl_krb4->priv = g_new0 (struct _CamelSaslKerberos4Private, 1);
}
camel_sasl_kerberos4_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslKerberos4",
(CamelObjectInitFunc) camel_sasl_kerberos4_init,
(CamelObjectFinalizeFunc) camel_sasl_kerberos4_finalize);
}
-
+
return type;
}
typedef struct _CamelSaslKerberos4Class {
CamelSaslClass parent_class;
-
+
} CamelSaslKerberos4Class;
CamelServiceAuthType camel_sasl_login_authtype = {
N_("Login"),
-
+
N_("This option will connect to the server using a "
"simple password."),
-
+
"LOGIN",
TRUE
};
camel_sasl_login_class_init (CamelSaslLoginClass *camel_sasl_login_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_login_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = login_challenge;
}
camel_sasl_login_init (gpointer object, gpointer klass)
{
CamelSaslLogin *sasl_login = CAMEL_SASL_LOGIN (object);
-
+
sasl_login->priv = g_new0 (struct _CamelSaslLoginPrivate, 1);
}
camel_sasl_login_finalize (CamelObject *object)
{
CamelSaslLogin *sasl = CAMEL_SASL_LOGIN (object);
-
+
g_free (sasl->priv);
}
camel_sasl_login_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslLogin",
(CamelObjectInitFunc) camel_sasl_login_init,
(CamelObjectFinalizeFunc) camel_sasl_login_finalize);
}
-
+
return type;
}
struct _CamelSaslLoginPrivate *priv = CAMEL_SASL_LOGIN (sasl)->priv;
GByteArray *buf = NULL;
CamelURL *url = sasl->service->url;
-
+
g_return_val_if_fail (url->passwd != NULL, NULL);
/* Need to wait for the server */
if (!token)
return NULL;
-
+
switch (priv->state) {
case LOGIN_USER:
buf = g_byte_array_new ();
_("Unknown authentication state."));
}
}
-
+
priv->state++;
-
+
return buf;
}
typedef struct _CamelSaslLogin {
CamelSasl parent_object;
-
+
struct _CamelSaslLoginPrivate *priv;
-
+
} CamelSaslLogin;
typedef struct _CamelSaslLoginClass {
CamelSaslClass parent_class;
-
+
} CamelSaslLoginClass;
camel_sasl_ntlm_class_init (CamelSaslNTLMClass *camel_sasl_ntlm_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_ntlm_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = ntlm_challenge;
}
}
/* MD4 */
-static void md4sum (const unsigned char *in,
- int nbytes,
+static void md4sum (const unsigned char *in,
+ int nbytes,
unsigned char digest[16]);
/* DES */
}
-/*
+/*
* MD4 encoder. (The one everyone else uses is not GPL-compatible;
* this is a reimplementation from spec.) This doesn't need to be
* efficient for our purposes, although it would be nice to fix
des (guint32 ks[16][2], unsigned char block[8])
{
guint32 left, right, work;
-
+
/* Read input block and place in left/right in big-endian order */
left = ((guint32)block[0] << 24)
| ((guint32)block[1] << 16)
| (guint32)block[7];
/* Hoey's clever initial permutation algorithm, from Outerbridge
- * (see Schneier p 478)
+ * (see Schneier p 478)
*
* The convention here is the same as Outerbridge: rotate each
* register left by 1 bit, i.e., so that "left" contains permuted
- * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
+ * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
* (using origin-1 numbering as in the FIPS). This allows us to avoid
* one of the two rotates that would otherwise be required in each of
* the 16 rounds.
typedef struct _CamelSaslNTLMClass {
CamelSaslClass parent_class;
-
+
} CamelSaslNTLMClass;
camel_sasl_plain_class_init (CamelSaslPlainClass *camel_sasl_plain_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_plain_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = plain_challenge;
}
camel_sasl_plain_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslPlain",
NULL,
NULL);
}
-
+
return type;
}
typedef struct _CamelSaslPlainClass {
CamelSaslClass parent_class;
-
+
} CamelSaslPlainClass;
camel_sasl_popb4smtp_class_init (CamelSaslPOPB4SMTPClass *camel_sasl_popb4smtp_class)
{
CamelSaslClass *camel_sasl_class = CAMEL_SASL_CLASS (camel_sasl_popb4smtp_class);
-
+
parent_class = CAMEL_SASL_CLASS (camel_type_get_global_classfuncs (camel_sasl_get_type ()));
-
+
/* virtual method overload */
camel_sasl_class->challenge = popb4smtp_challenge;
camel_sasl_popb4smtp_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_sasl_get_type (),
"CamelSaslPOPB4SMTP",
NULL,
NULL);
}
-
+
return type;
}
POPB4SMTP_UNLOCK(lock);
g_free(popuri);
-
+
return NULL;
}
typedef struct _CamelSaslPOPB4SMTPClass {
CamelSaslClass parent_class;
-
+
} CamelSaslPOPB4SMTPClass;
camel_sasl_class_init (CamelSaslClass *camel_sasl_class)
{
parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE);
-
+
/* virtual method definition */
camel_sasl_class->challenge = sasl_challenge;
}
camel_sasl_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_OBJECT_TYPE,
"CamelSasl",
NULL,
(CamelObjectFinalizeFunc) camel_sasl_finalize);
}
-
+
return type;
}
camel_sasl_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex)
{
g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
-
+
return CS_CLASS (sasl)->challenge (sasl, token, ex);
}
camel_sasl_new (const char *service_name, const char *mechanism, CamelService *service)
{
CamelSasl *sasl;
-
+
g_return_val_if_fail (service_name != NULL, NULL);
g_return_val_if_fail (mechanism != NULL, NULL);
g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
-
+
/* We don't do ANONYMOUS here, because it's a little bit weird. */
-
+
if (!strcmp (mechanism, "CRAM-MD5"))
sasl = (CamelSasl *) camel_object_new (CAMEL_SASL_CRAM_MD5_TYPE);
else if (!strcmp (mechanism, "DIGEST-MD5"))
sasl->service_name = g_strdup (service_name);
sasl->service = service;
camel_object_ref (service);
-
+
return sasl;
}
camel_sasl_authtype_list (gboolean include_plain)
{
GList *types = NULL;
-
+
types = g_list_prepend (types, &camel_sasl_cram_md5_authtype);
types = g_list_prepend (types, &camel_sasl_digest_md5_authtype);
#ifdef HAVE_KRB5
types = g_list_prepend (types, &camel_sasl_ntlm_authtype);
if (include_plain)
types = g_list_prepend (types, &camel_sasl_plain_authtype);
-
+
return types;
}
typedef struct _CamelSasl {
CamelObject parent_object;
-
+
char *service_name;
char *mech; /* mechanism */
CamelService *service;
typedef struct _CamelSaslClass {
CamelObjectClass parent_class;
-
+
GByteArray * (*challenge) (CamelSasl *sasl, GByteArray *token, CamelException *ex);
} CamelSaslClass;
r<<=1;
m<<=5;
} while (r & 0x40);
-
+
*ptr = p;
v &= ~m;
int c, i, count=0, err;
char *word;
int flags;
-
+
/* build a regex pattern we can use to match the words, we OR them together */
if (argc>1)
g_string_append_c (match, '(');
if (argv[i]->type == ESEXP_RES_STRING) {
if (count > 0)
g_string_append_c (match, '|');
-
+
word = argv[i]->value.string;
if (type & CAMEL_SEARCH_MATCH_REGEX) {
/* no need to escape because this should already be a valid regex */
flags |= REG_NEWLINE;
err = regcomp (pattern, match->str, flags);
if (err != 0) {
- /* regerror gets called twice to get the full error string
+ /* regerror gets called twice to get the full error string
length to do proper posix error reporting */
int len = regerror (err, pattern, 0, 0);
char *buffer = g_malloc0 (len + 1);
-
+
regerror (err, pattern, buffer, len);
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Regular expression compilation failed: %s: %s"),
match->str, buffer);
-
+
regfree (pattern);
}
d(printf("Built regex: '%s'\n", match->str));
g_string_free (match, TRUE);
-
+
return err;
}
{
guchar *c, last = '\0';
gint n;
-
+
for (c = (guchar *) sound; *c && !isalpha (*c); c++);
code[0] = toupper (*c);
memset (code + 1, '0', 3);
for (n = 1; *c && n < 5; c++) {
guchar ch = soundex_table[*c];
-
+
if (ch && ch != last) {
code[n++] = ch;
last = ch;
char c;
GString *word;
int truth = FALSE;
-
+
soundexify (match, mcode);
-
+
/* split the header into words, and soundexify and compare each one */
/* FIXME: Should this convert to utf8, and split based on that, and what not?
soundex only makes sense for us-ascii though ... */
-
+
word = g_string_new("");
p = header;
do {
g_string_append_c (word, c);
} while (c && !truth);
g_string_free (word, TRUE);
-
+
return truth;
}
gunichar *nuni, *puni;
gunichar u;
const unsigned char *p;
-
+
g_return_val_if_fail (haystack != NULL, NULL);
g_return_val_if_fail (needle != NULL, NULL);
-
+
if (strlen (needle) == 0)
return haystack;
if (strlen (haystack) == 0)
return NULL;
-
+
puni = nuni = g_alloca (sizeof (gunichar) * strlen (needle));
-
+
p = (const unsigned char *) needle;
while ((u = camel_utf8_getc(&p)))
*puni++ = g_unichar_tolower (u);
-
+
/* NULL means there was illegal utf-8 sequence */
if (!p)
return NULL;
-
+
p = (const unsigned char *)haystack;
while ((u = camel_utf8_getc(&p))) {
gunichar c;
-
+
c = g_unichar_tolower (u);
/* We have valid stripped char */
if (c == nuni[0]) {
const unsigned char *q = p;
gint npos = 1;
-
+
while (nuni + npos < puni) {
u = camel_utf8_getc(&q);
if (!q || !u)
return NULL;
-
- c = g_unichar_tolower (u);
+
+ c = g_unichar_tolower (u);
if (c != nuni[npos])
break;
-
+
npos++;
}
-
+
if (nuni + npos == puni)
return (const char *) p;
}
}
-
+
return NULL;
}
gunichar u1, u2 = 0;
const unsigned char *s1 = (const unsigned char *)ps1;
const unsigned char *s2 = (const unsigned char *)ps2;
-
+
CAMEL_SEARCH_COMPARE (s1, s2, NULL);
-
+
u1 = camel_utf8_getc(&s1);
u2 = camel_utf8_getc(&s2);
while (u1 && u2) {
return -1;
else if (u1 > u2)
return 1;
-
+
u1 = camel_utf8_getc(&s1);
u2 = camel_utf8_getc(&s2);
}
-
+
/* end of one of the strings ? */
CAMEL_SEARCH_COMPARE (u1, u2, 0);
-
+
/* if we have invalid utf8 sequence ? */
CAMEL_SEARCH_COMPARE (s1, s2, NULL);
-
+
return 0;
}
gunichar u1, u2 = 0;
const unsigned char *s1 = (const unsigned char *)ps1;
const unsigned char *s2 = (const unsigned char *)ps2;
-
+
CAMEL_SEARCH_COMPARE (s1, s2, NULL);
-
+
u1 = camel_utf8_getc(&s1);
u2 = camel_utf8_getc(&s2);
while (len > 0 && u1 && u2) {
return -1;
else if (u1 > u2)
return 1;
-
+
len--;
u1 = camel_utf8_getc(&s1);
u2 = camel_utf8_getc(&s2);
}
-
+
if (len == 0)
return 0;
-
+
/* end of one of the strings ? */
CAMEL_SEARCH_COMPARE (u1, u2, 0);
-
+
/* if we have invalid utf8 sequence ? */
CAMEL_SEARCH_COMPARE (s1, s2, NULL);
-
+
return 0;
}
const unsigned char *p;
int vlen, mlen;
gunichar c;
-
+
if (how == CAMEL_SEARCH_MATCH_SOUNDEX)
return header_soundex (value, match);
mlen = strlen(match);
if (vlen < mlen)
return FALSE;
-
+
/* from dan the man, if we have mixed case, perform a case-sensitive match,
otherwise not */
p = (const unsigned char *)match;
return FALSE;
}
}
-
+
switch (how) {
case CAMEL_SEARCH_MATCH_EXACT:
return camel_ustrcasecmp(value, match) == 0;
default:
break;
}
-
+
return FALSE;
}
for (i=0; !truth && camel_internet_address_get(cia, i, &name, &addr);i++)
truth = (name && header_match(name, match, how)) || (addr && header_match(addr, match, how));
-
+
camel_object_unref (cia);
break;
}
CamelDataWrapper *containee;
int truth = FALSE;
int parts, i;
-
+
containee = camel_medium_get_content_object (CAMEL_MEDIUM (object));
-
+
if (containee == NULL)
return FALSE;
-
+
/* using the object types is more accurate than using the mime/types */
if (CAMEL_IS_MULTIPART (containee)) {
parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
} else if (camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "text", "*")) {
/* for all other text parts, we look inside, otherwise we dont care */
CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new ();
-
+
camel_data_wrapper_write_to_stream (containee, CAMEL_STREAM (mem));
camel_stream_write (CAMEL_STREAM (mem), "", 1);
truth = regexec (pattern, (char *) mem->buffer->data, 0, NULL, 0) == 0;
camel_object_unref (mem);
}
-
+
return truth;
}
guint32 c;
int inquote = 0;
- words = g_malloc0(sizeof(*words));
+ words = g_malloc0(sizeof(*words));
w = g_string_new("");
do {
struct _camel_search_words *words;
guint32 c;
- words = g_malloc0(sizeof(*words));
+ words = g_malloc0(sizeof(*words));
for (i=0;i<wordin->len;i++) {
if ((wordin->words[i]->type & CAMEL_SEARCH_WORD_COMPLEX) == 0) {
camel_service_class_init (CamelServiceClass *camel_service_class)
{
CamelObjectClass *object_class = CAMEL_OBJECT_CLASS (camel_service_class);
-
+
parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE);
-
+
/* virtual method overloading */
object_class->setv = service_setv;
object_class->getv = service_getv;
-
+
/* virtual method definition */
camel_service_class->construct = construct;
camel_service_class->connect = service_connect;
camel_service_init (void *o, void *k)
{
CamelService *service = o;
-
+
service->priv = g_malloc0(sizeof(*service->priv));
g_static_rec_mutex_init(&service->priv->connect_lock);
g_static_mutex_init(&service->priv->connect_op_lock);
if (service->status == CAMEL_SERVICE_CONNECTED) {
CamelException ex;
-
+
camel_exception_init (&ex);
CSERV_CLASS (service)->disconnect (service, TRUE, &ex);
if (camel_exception_is_set (&ex)) {
}
camel_exception_clear (&ex);
}
-
+
if (service->url)
camel_url_free (service->url);
if (service->session)
camel_object_unref (service->session);
-
+
g_static_rec_mutex_free (&service->priv->connect_lock);
g_static_mutex_free (&service->priv->connect_op_lock);
-
+
g_free (service->priv);
}
camel_service_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type =
camel_type_register (CAMEL_OBJECT_TYPE,
(CamelObjectInitFunc) camel_service_init,
camel_service_finalize );
}
-
+
return type;
}
gboolean reconnect = FALSE;
guint32 tag;
int i;
-
+
for (i = 0; i < args->argc; i++) {
tag = args->argv[i].tag;
-
+
/* make sure this is an arg we're supposed to handle */
if ((tag & CAMEL_ARG_TAG) <= CAMEL_SERVICE_ARG_FIRST ||
(tag & CAMEL_ARG_TAG) >= CAMEL_SERVICE_ARG_FIRST + 100)
continue;
-
+
if (tag == CAMEL_SERVICE_USERNAME) {
/* set the username */
if (strcmp (url->user, args->argv[i].ca_str) != 0) {
/* error? */
continue;
}
-
+
/* let our parent know that we've handled this arg */
camel_argv_ignore (args, i);
}
-
+
/* FIXME: what if we are in the process of connecting? */
if (reconnect && service->status == CAMEL_SERVICE_CONNECTED) {
/* reconnect the service using the new URL */
if (camel_service_disconnect (service, TRUE, ex))
camel_service_connect (service, ex);
}
-
+
return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
}
CamelURL *url = service->url;
guint32 tag;
int i;
-
+
for (i = 0; i < args->argc; i++) {
tag = args->argv[i].tag;
-
+
/* make sure this is an arg we're supposed to handle */
if ((tag & CAMEL_ARG_TAG) <= CAMEL_SERVICE_ARG_FIRST ||
(tag & CAMEL_ARG_TAG) >= CAMEL_SERVICE_ARG_FIRST + 100)
continue;
-
+
switch (tag) {
case CAMEL_SERVICE_USERNAME:
/* get the username */
break;
}
}
-
+
return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
}
construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex)
{
char *err, *url_string;
-
+
if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER) &&
(url->user == NULL || url->user[0] == '\0')) {
err = _("URL '%s' needs a username component");
err = _("URL '%s' needs a path component");
goto fail;
}
-
+
service->provider = provider;
service->url = camel_url_copy(url);
service->session = session;
camel_object_ref (session);
-
+
service->status = CAMEL_SERVICE_DISCONNECTED;
return;
{
g_return_if_fail (CAMEL_IS_SERVICE (service));
g_return_if_fail (CAMEL_IS_SESSION (session));
-
+
CSERV_CLASS (service)->construct (service, session, provider, url, ex);
}
{
gboolean ret = FALSE;
gboolean unreg = FALSE;
-
+
g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
g_return_val_if_fail (service->session != NULL, FALSE);
g_return_val_if_fail (service->url != NULL, FALSE);
-
+
CAMEL_SERVICE_REC_LOCK (service, connect_lock);
-
+
if (service->status == CAMEL_SERVICE_CONNECTED) {
CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
return TRUE;
if (service->connect_op) {
if (unreg)
camel_operation_unregister (service->connect_op);
-
+
camel_operation_unref (service->connect_op);
service->connect_op = NULL;
}
CAMEL_SERVICE_UNLOCK (service, connect_op_lock);
CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
-
+
return ret;
}
/*service->connect_level--;*/
/* We let people get away with not having a disconnect
- * function -- CamelMboxStore, for example.
+ * function -- CamelMboxStore, for example.
*/
-
+
return TRUE;
}
int unreg = FALSE;
CAMEL_SERVICE_REC_LOCK (service, connect_lock);
-
+
if (service->status != CAMEL_SERVICE_DISCONNECTED
&& service->status != CAMEL_SERVICE_DISCONNECTING) {
CAMEL_SERVICE_LOCK (service, connect_op_lock);
service->connect_op = NULL;
CAMEL_SERVICE_UNLOCK (service, connect_op_lock);
}
-
+
CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
-
+
service->status = CAMEL_SERVICE_DISCONNECTED;
return res;
}
w(g_warning ("CamelService::get_name not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (service))));
return g_strdup ("???");
-}
+}
/**
{
g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
g_return_val_if_fail (service->url, NULL);
-
+
return CSERV_CLASS (service)->get_name (service, brief);
}
CamelURL *url = service->url;
GString *gpath;
char *path;
-
+
/* A sort of ad-hoc default implementation that works for our
* current set of services.
*/
-
+
gpath = g_string_new (service->provider->protocol);
if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_USER)) {
if (CAMEL_PROVIDER_ALLOWS (prov, CAMEL_URL_PART_HOST)) {
g_string_append_printf (gpath, "/%s@%s",
url->user ? url->user : "",
url->host ? url->host : "");
-
+
if (url->port)
g_string_append_printf (gpath, ":%d", url->port);
} else {
g_string_append_printf (gpath, "/%s%s",
CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_HOST) ? "" : "@",
url->host ? url->host : "");
-
+
if (url->port)
g_string_append_printf (gpath, ":%d", url->port);
}
-
+
if (CAMEL_PROVIDER_NEEDS (prov, CAMEL_URL_PART_PATH))
g_string_append_printf (gpath, "%s%s", *url->path == '/' ? "" : "/", url->path);
-
+
path = gpath->str;
g_string_free (gpath, FALSE);
-
+
return path;
-}
+}
/**
* camel_service_get_path:
{
g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
g_return_val_if_fail (service->url, NULL);
-
+
return CSERV_CLASS (service)->get_path (service);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-service.h : Abstract class for an email service */
-/*
+/*
*
* Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
CamelURL *url,
CamelException *ex);
- gboolean (*connect) (CamelService *service,
+ gboolean (*connect) (CamelService *service,
CamelException *ex);
gboolean (*disconnect) (CamelService *service,
gboolean clean,
char *name; /* user-friendly name */
char *description;
char *authproto;
-
+
gboolean need_password; /* needs a password to authenticate */
} CamelServiceAuthType;
void camel_service_construct (CamelService *service,
CamelSession *session,
CamelProvider *provider,
- CamelURL *url,
+ CamelURL *url,
CamelException *ex);
-gboolean camel_service_connect (CamelService *service,
+gboolean camel_service_connect (CamelService *service,
CamelException *ex);
gboolean camel_service_disconnect (CamelService *service,
gboolean clean,
session->online = TRUE;
session->network_state = TRUE;
session->priv = g_malloc0(sizeof(*session->priv));
-
+
session->priv->lock = g_mutex_new();
session->priv->thread_lock = g_mutex_new();
session->priv->thread_id = 1;
{
CamelSession *session = (CamelSession *)o;
GThreadPool *thread_pool = session->priv->thread_pool;
-
+
g_hash_table_destroy(session->priv->thread_active);
if (thread_pool != NULL) {
/* virtual method definition */
camel_session_class->get_service = get_service;
camel_session_class->get_storage_path = get_storage_path;
-
+
camel_session_class->thread_msg_new = session_thread_msg_new;
camel_session_class->thread_msg_free = session_thread_msg_free;
camel_session_class->thread_queue = session_thread_queue;
CamelProvider *provider;
CamelService *service;
CamelException internal_ex;
-
+
url = camel_url_new (url_string, ex);
if (!url)
return NULL;
url->protocol);
provider = NULL;
}
-
+
if (!provider) {
camel_url_free (url);
return NULL;
*/
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) {
path = g_strdup_printf ("%s/%s", session->storage_path, p);
g_free (p);
-#ifdef G_OS_WIN32
+#ifdef G_OS_WIN32
if (g_access (path, F_OK) == 0)
#else
if (access (path, F_OK) == 0)
* If #CAMEL_SESSION_PASSWORD_STATIC is set, it means the password returned
* will be stored statically by the caller automatically, for the current
* session.
- *
+ *
* The authenticator should set @ex to #CAMEL_EXCEPTION_USER_CANCEL if
* the user did not provide the information. The caller must #g_free
* the information returned when it is done with it.
g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
g_return_val_if_fail (prompt != NULL, NULL);
g_return_val_if_fail (item != NULL, NULL);
-
+
return CS_CLASS (session)->get_password (session, service, domain, prompt, item, flags, ex);
}
CAMEL_SESSION_UNLOCK(session, thread_lock);
d(printf("free msg, ops->free = %p\n", msg->ops->free));
-
+
if (msg->ops->free)
msg->ops->free(session, msg);
if (msg->op)
* @session: a #CamelSession object
* @ops: thread operations
* @size: number of bytes
- *
+ *
* Create a new thread message, using ops as the receive/reply/free
* ops, of @size bytes.
*
* camel_session_thread_msg_free:
* @session: a #CamelSession object
* @msg: a #CamelSessionThreadMsg
- *
+ *
* Free a @msg. Note that the message must have been allocated using
* msg_new, and must nto have been submitted to any queue function.
**/
* @session: a #CamelSession object
* @msg: a #CamelSessionThreadMsg
* @flags: queue type flags, currently 0.
- *
+ *
* Queue a thread message in another thread for processing.
* The operation should be (but needn't) run in a queued manner
* with other operations queued in this manner.
- *
+ *
* Returns the id of the operation queued
**/
int
/**
* camel_session_check_junk:
* @session: a #CamelSession object
- *
+ *
* Do we have to check incoming messages to be junk?
*
* Returns whether or not we are checking incoming messages for junk
* camel_session_set_check_junk:
* @session: a #CamelSession object
* @check_junk: state
- *
+ *
* Set check_junk flag, if set, incoming mail will be checked for being junk.
**/
void
CamelFilterDriver * (*get_filter_driver) (CamelSession *session,
const char *type,
CamelException *ex);
-
+
/* mechanism for creating and maintaining multiple threads of control */
void * (*thread_msg_new) (CamelSession *session,
CamelSessionThreadOps *ops,
const char *url_string,
CamelProviderType type,
CamelException *ex);
-CamelService * camel_session_get_service_connected (CamelSession *session,
+CamelService * camel_session_get_service_connected (CamelSession *session,
const char *url_string,
- CamelProviderType type,
+ CamelProviderType type,
CamelException *ex);
#define camel_session_get_store(session, url_string, ex) \
* Michael Zucchi <notzed@ximian.com>
*
* The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
+ * Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
{
CamelCipherContext *cipher;
CamelSMIMEContext *ctx;
-
+
g_return_val_if_fail(CAMEL_IS_SESSION(session), NULL);
-
+
ctx =(CamelSMIMEContext *) camel_object_new(camel_smime_context_get_type());
-
+
cipher =(CamelCipherContext *) ctx;
cipher->session = session;
camel_object_ref(session);
-
+
return cipher;
}
else if (!strcmp(id, "sha1"))
return CAMEL_CIPHER_HASH_SHA1;
}
-
+
return CAMEL_CIPHER_HASH_DEFAULT;
}
goto fail;
}
- enc = NSS_CMSEncoder_Start(cmsg,
+ enc = NSS_CMSEncoder_Start(cmsg,
sm_write_stream, ostream, /* DER output callback */
NULL, NULL, /* destination storage */
NULL, NULL, /* password callback */
mps->contentraw = istream;
camel_stream_reset(istream);
camel_object_ref(istream);
-
+
camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps);
} else {
ct = camel_content_type_new("application", "x-pkcs7-mime");
camel_content_type_set_param(ct, "smime-type", "signed-data");
camel_data_wrapper_set_mime_type_field(dw, ct);
camel_content_type_unref(ct);
-
+
camel_medium_set_content_object((CamelMedium *)opart, dw);
camel_mime_part_set_filename(opart, "smime.p7m");
camel_mime_part_set_disposition(opart, "attachment");
camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64);
}
-
+
camel_object_unref(dw);
-fail:
+fail:
camel_object_unref(ostream);
camel_object_unref(istream);
}
digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);
-
+
digcx = NSS_CMSDigestContext_StartMultiple(digestalgs);
if (digcx == NULL) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot calculate digests"));
/* check for certs-only message */
nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
if (nsigners == 0) {
-
+
/* already imported certs above, not sure what usage we should use here or if this isn't handled above */
if (NSS_CMSSignedData_VerifyCertsOnly(sigd, p->certdb, certUsageEmailSigner) != SECSuccess) {
g_string_printf(description, _("Certificate is the only message, cannot verify certificates"));
for (j = 0; j < nsigners; j++) {
NSSCMSSignerInfo *si;
char *cn, *em;
-
+
si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
NSS_CMSSignedData_VerifySignerInfo(sigd, j, p->certdb, certUsageEmailSigner);
-
+
status = NSS_CMSSignerInfo_GetVerificationStatus(si);
-
+
cn = NSS_CMSSignerInfo_GetSignerCommonName(si);
em = NSS_CMSSignerInfo_GetSignerEmailAddress(si);
-
+
g_string_append_printf(description, _("Signer: %s <%s>: %s\n"),
cn?cn:"<unknown>", em?em:"<unknown>",
sm_status_description(status));
-
+
camel_cipher_validity_add_certinfo(valid, CAMEL_CIPHER_VALIDITY_SIGN, cn, em);
if (cn)
PORT_Free(cn);
if (em)
PORT_Free(em);
-
+
if (status != NSSCMSVS_GoodSignature)
camel_cipher_validity_set_valid(valid, FALSE);
}
/* FIXME: we should stream this to the decoder */
mem = (CamelStreamMem *)camel_stream_mem_new();
-
+
if (camel_content_type_is(ct, "multipart", "signed")) {
CamelMultipart *mps = (CamelMultipart *)dw;
goto fail;
}
- dec = NSS_CMSDecoder_Start(NULL,
+ dec = NSS_CMSDecoder_Start(NULL,
NULL, NULL, /* content callback */
NULL, NULL, /* password callback */
NULL, NULL); /* decrypt key callback */
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Decoder failed"));
goto fail;
}
-
+
valid = sm_verify_cmsg(context, cmsg, constream, ex);
-
+
NSS_CMSMessage_Destroy(cmsg);
fail:
camel_object_unref(mem);
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);
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,
+ dec = NSS_CMSDecoder_Start(NULL,
sm_write_stream, ostream, /* content callback */
NULL, NULL,
NULL, NULL); /* decrypt key callback */
sm_import_keys(CamelCipherContext *context, CamelStream *istream, CamelException *ex)
{
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("import keys: unimplemented"));
-
+
return -1;
}
sm_export_keys(CamelCipherContext *context, GPtrArray *keys, CamelStream *ostream, CamelException *ex)
{
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("export keys: unimplemented"));
-
+
return -1;
}
camel_smime_context_class_init(CamelSMIMEContextClass *klass)
{
CamelCipherContextClass *cipher_class = CAMEL_CIPHER_CONTEXT_CLASS(klass);
-
+
parent_class = CAMEL_CIPHER_CONTEXT_CLASS(camel_type_get_global_classfuncs(camel_cipher_context_get_type()));
-
+
cipher_class->hash_to_id = sm_hash_to_id;
cipher_class->id_to_hash = sm_id_to_hash;
cipher_class->sign = sm_sign;
camel_smime_context_init(CamelSMIMEContext *context)
{
CamelCipherContext *cipher =(CamelCipherContext *) context;
-
+
cipher->sign_protocol = "application/x-pkcs7-signature";
cipher->encrypt_protocol = "application/x-pkcs7-mime";
cipher->key_protocol = "application/x-pkcs7-signature";
camel_smime_context_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_cipher_context_get_type(),
"CamelSMIMEContext",
(CamelObjectInitFunc) camel_smime_context_init,
(CamelObjectFinalizeFunc) camel_smime_context_finalise);
}
-
+
return type;
}
s->folders = g_ptr_array_new();
s->folders_path = g_hash_table_new(g_str_hash, g_str_equal);
-
+
p->summary_lock = g_mutex_new();
p->io_lock = g_mutex_new();
p->alloc_lock = g_mutex_new();
if (s->store_info_chunks)
e_memchunk_destroy(s->store_info_chunks);
-
+
g_mutex_free(p->summary_lock);
g_mutex_free(p->io_lock);
g_mutex_free(p->alloc_lock);
g_mutex_free(p->ref_lock);
-
+
g_free(p);
}
camel_store_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_object_get_type (), "CamelStoreSummary",
sizeof (CamelStoreSummary),
(CamelObjectInitFunc) camel_store_summary_init,
(CamelObjectFinalizeFunc) camel_store_summary_finalise);
}
-
+
return type;
}
* camel_store_summary_new:
*
* Create a new #CamelStoreSummary object.
- *
+ *
* Returns a new #CamelStoreSummary object
**/
CamelStoreSummary *
* camel_store_summary_set_filename:
* @summary: a #CamelStoreSummary
* @filename: a filename
- *
+ *
* Set the filename where the summary will be loaded to/saved from.
**/
void
/**
* camel_store_summary_count:
* @summary: a #CamelStoreSummary object
- *
+ *
* Get the number of summary items stored in this summary.
- *
+ *
* Returns the number of items int he summary.
**/
int
* camel_store_summary_index:
* @summary: a #CamelStoreSummary object
* @index: record index
- *
+ *
* Retrieve a summary item by index number.
*
* A referenced to the summary item is returned, which may be ref'd or
* free'd as appropriate.
*
* It must be freed using #camel_store_summary_info_free.
- *
+ *
* Returns the summary item, or %NULL if @index is out of range
**/
CamelStoreInfo *
/**
* camel_store_summary_array:
* @summary: a #CamelStoreSummary object
- *
+ *
* Obtain a copy of the summary array. This is done atomically,
* so cannot contain empty entries.
*
CamelStoreInfo *info;
GPtrArray *res = g_ptr_array_new();
int i;
-
+
CAMEL_STORE_SUMMARY_LOCK(s, ref_lock);
CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
* camel_store_summary_array_free:
* @summary: a #CamelStoreSummary object
* @array: the summary array as gotten from #camel_store_summary_array
- *
+ *
* Free the folder summary array.
**/
void
* camel_store_summary_path:
* @summary: a #CamelStoreSummary object
* @path: path to the item
- *
+ *
* Retrieve a summary item by path name.
*
* A referenced to the summary item is returned, which may be ref'd or
}
CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
-
+
if (fclose (in) != 0)
return -1;
fclose (in);
s->flags |= ~CAMEL_STORE_SUMMARY_DIRTY;
errno = i;
-
+
return -1;
}
/**
* camel_store_summary_save:
* @summary: a #CamelStoreSummary object
- *
+ *
* Writes the summary to disk. The summary is only written if changes
* have occured.
- *
+ *
* Returns %0 on succes or %-1 on fail
**/
int
}
CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
-
+
if (fflush (out) != 0 || fsync (fileno (out)) == -1) {
i = errno;
fclose (out);
errno = i;
return -1;
}
-
+
if (fclose (out) != 0)
return -1;
/**
* camel_store_summary_header_load:
* @summary: a #CamelStoreSummary object
- *
+ *
* Only load the header information from the summary,
* keep the rest on disk. This should only be done on
* a fresh summary object.
- *
+ *
* Returns %0 on success or %-1 on fail
**/
int
CAMEL_STORE_SUMMARY_LOCK(s, io_lock);
ret = ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in);
CAMEL_STORE_SUMMARY_UNLOCK(s, io_lock);
-
+
fclose(in);
s->flags &= ~CAMEL_STORE_SUMMARY_DIRTY;
return ret;
* camel_store_summary_add:
* @summary: a #CamelStoreSummary object
* @info: a #CamelStoreInfo
- *
+ *
* Adds a new @info record to the summary. If @info->uid is %NULL,
* then a new uid is automatically re-assigned by calling
* #camel_store_summary_next_uid_string.
* camel_store_summary_add_from_path:
* @summary: a #CamelStoreSummary object
* @path: item path
- *
+ *
* Build a new info record based on the name, and add it to the summary.
*
* Returns the newly added record
* camel_store_summary_info_new_from_path:
* @summary: a #CamelStoreSummary object
* @path: item path
- *
+ *
* Create a new info record from a name.
*
* This info record MUST be freed using
* camel_store_summary_info_free:
* @summary: a #CamelStoreSummary object
* @info: a #CamelStoreInfo
- *
+ *
* Unref and potentially free @info, and all associated memory.
**/
void
CAMEL_STORE_SUMMARY_UNLOCK(s, ref_lock);
- ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_free(s, info);
+ ((CamelStoreSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->store_info_free(s, info);
}
* camel_store_summary_info_ref:
* @summary: a #CamelStoreSummary object
* @info: a #CamelStoreInfo
- *
+ *
* Add an extra reference to @info.
**/
void
/**
* camel_store_summary_touch:
* @summary: a #CamelStoreSummary object
- *
+ *
* Mark the summary as changed, so that a save will force it to be
* written back to disk.
**/
/**
* camel_store_summary_clear:
* @summary: a #CamelStoreSummary object
- *
+ *
* Empty the summary contents.
**/
void
* camel_store_summary_remove:
* @summary: a #CamelStoreSummary object
* @info: a #CamelStoreInfo
- *
+ *
* Remove a specific @info record from the summary.
**/
void
* camel_store_summary_remove_path:
* @summary: a #CamelStoreSummary object
* @path: item path
- *
+ *
* Remove a specific info record from the summary, by @path.
**/
void
* camel_store_summary_remove_index:
* @summary: a #CamelStoreSummary object
* @index: item index
- *
+ *
* Remove a specific info record from the summary, by index.
**/
void
/**
* camel_store_summary_info_new:
* @summary: a #CamelStoreSummary object
- *
+ *
* Allocate a new #CamelStoreInfo, suitable for adding to this
* summary.
- *
+ *
* Returns the newly allocated #CamelStoreInfo
**/
CamelStoreInfo *
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-store.c : Abstract class for an email store */
-/*
+/*
* Authors:
* Bertrand Guiheneuf <bertrand@helixcode.com>
* Dan Winship <danw@ximian.com>
*
* Copyright 1999-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{
CamelObjectClass *camel_object_class = CAMEL_OBJECT_CLASS (camel_store_class);
CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_store_class);
-
+
parent_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ()));
-
+
/* virtual method definition */
camel_store_class->hash_folder_name = g_str_hash;
camel_store_class->compare_folder_name = g_str_equal;
(CamelCopyFunc)g_strdup, g_free);
} else
store->folders = NULL;
-
+
/* set vtrash and vjunk on by default */
store->flags = CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK;
store->mode = CAMEL_STORE_READ|CAMEL_STORE_WRITE;
if (store->folders)
camel_object_bag_destroy(store->folders);
-
+
g_static_rec_mutex_free (&store->priv->folder_lock);
-
+
g_free (store->priv);
}
{
w(g_warning ("CamelStore::get_folder not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
-
+
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_INVALID,
_("Cannot get folder: Invalid operation on this store"));
-
+
return NULL;
}
-/**
+/**
* camel_store_get_folder:
* @store: a #CamelStore object
* @folder_name: name of the folder to get
folder = CS_CLASS (store)->get_folder(store, folder_name, flags, ex);
if (folder) {
CamelVeeFolder *vfolder;
-
+
if ((store->flags & CAMEL_STORE_VTRASH)
&& (vfolder = camel_object_bag_get(store->folders, CAMEL_VTRASH_NAME))) {
camel_vee_folder_add_folder(vfolder, folder);
{
w(g_warning ("CamelStore::create_folder not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
-
+
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_INVALID,
_("Cannot create folder: Invalid operation on this store"));
-
+
return NULL;
}
-/**
+/**
* camel_store_create_folder:
* @store: a #CamelStore object
* @parent_name: name of the new folder's parent, or %NULL
* @folder_name: name of the folder to create
* @ex: a #CamelException
- *
+ *
* Creates a new folder as a child of an existing folder.
* @parent_name can be %NULL to create a new top-level folder.
*
if (store->folders
&& (folder = camel_object_bag_get(store->folders, folder_name))) {
CamelVeeFolder *vfolder;
-
+
if ((store->flags & CAMEL_STORE_VTRASH)
&& (vfolder = camel_object_bag_get(store->folders, CAMEL_VTRASH_NAME))) {
camel_vee_folder_remove_folder(vfolder, folder);
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
}
-/**
+/**
* camel_store_delete_folder:
* @store: a #CamelStore object
* @folder_name: name of the folder to delete
* @ex: a #CamelException
- *
+ *
* Deletes the named folder. The folder must be empty.
**/
void
cs_delete_cached_folder(store, folder_name);
else
camel_exception_xfer(ex, &local);
-
+
CAMEL_STORE_UNLOCK(store, folder_lock);
}
* @old_namein: the current name of the folder
* @new_name: the new name of the folder
* @ex: a #CamelException
- *
+ *
* Rename a named folder to a new name.
**/
void
/* Emit renamed signal */
if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-
+
reninfo.old_base = (char *)old_name;
reninfo.new = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info(store, new_name, flags, ex);
if (reninfo.new != NULL) {
return CS_CLASS (store)->get_folder (store, "inbox", 0, ex);
}
-/**
+/**
* camel_store_get_inbox:
* @store: a #CamelStore object
* @ex: a #CamelException
return get_special(store, CAMEL_VTRASH_FOLDER_JUNK);
}
-/**
+/**
* camel_store_get_trash:
* @store: a #CamelStore object
* @ex: a #CamelException
return camel_store_get_folder(store, CAMEL_VTRASH_NAME, 0, ex);
}
-/**
+/**
* camel_store_get_junk:
* @store: a #CamelStore object
* @ex: a #CamelException
{
w(g_warning ("CamelStore::get_folder_info not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
-
+
return NULL;
}
CamelFolderInfo *fi, *vinfo, *parent;
char *uri, *path;
CamelURL *url;
-
+
g_return_if_fail (info != NULL);
-
+
parent = NULL;
for (fi = info; fi; fi = fi->next) {
if (!strcmp (fi->full_name, name))
break;
parent = fi;
}
-
+
/* create our vTrash/vJunk URL */
url = camel_url_new (info->uri, NULL);
if (((CamelService *) store)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) {
camel_url_set_path (url, path);
g_free (path);
}
-
+
uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
camel_url_free (url);
-
+
if (fi) {
/* We're going to replace the physical Trash/Junk folder with our vTrash/vJunk folder */
vinfo = fi;
* determine that information quickly. If @flags includes
* #CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL, don't include special virtual
* folders (such as vTrash or vJunk).
- *
+ *
* The CAMEL_STORE_FOLDER_INFO_FAST flag should be considered
* deprecated; most backends will behave the same whether it is
* supplied or not. The only guaranteed way to get updated folder
camel_store_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex)
{
CamelFolderInfo *info;
-
+
g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
info = CS_CLASS (store)->get_folder_info (store, top, flags, ex);
-
+
if (info && (top == NULL || *top == '\0') && (flags & CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL) == 0) {
if (info->uri && (store->flags & CAMEL_STORE_VTRASH))
/* the name of the Trash folder, used for deleted messages */
dump_fi(info, 2);
camel_debug_end();
}
-
+
return info;
}
{
const CamelFolderInfo *a = ((CamelFolderInfo **)ap)[0];
const CamelFolderInfo *b = ((CamelFolderInfo **)bp)[0];
-
+
return strcmp (a->full_name, b->full_name);
}
nlen = strlen (namespace);
qsort (folders->pdata, folders->len, sizeof (folders->pdata[0]), folder_info_cmp);
-
+
/* Hash the folders. */
hash = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i < folders->len; i++) {
fi = folders->pdata[i];
g_hash_table_insert (hash, fi->full_name, fi);
}
-
+
/* Now find parents. */
for (i = 0; i < folders->len; i++) {
fi = folders->pdata[i];
pfi->name = g_strdup (pname);
} else
pfi->name = g_strdup (pname);
-
+
url = camel_url_new (fi->uri, NULL);
if (url->fragment)
path = url->fragment;
else
path = url->path + 1;
-
+
sep = strrchr (path, separator);
if (sep)
*sep = '\0';
else
d(g_warning ("huh, no \"%c\" in \"%s\"?", separator, fi->uri));
-
+
pfi->full_name = g_strdup (path);
-
+
/* since this is a "fake" folder node, it is not selectable */
camel_url_set_param (url, "noselect", "yes");
pfi->uri = camel_url_to_string (url, 0);
tail = fi;
}
}
-
+
return top;
}
info->full_name = g_strdup(fi->full_name);
info->unread = fi->unread;
info->flags = fi->flags;
-
+
if (fi->next)
info->next = folder_info_clone_rec(fi->next, parent);
else
{
w(g_warning ("CamelStore::folder_subscribed not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
-
+
return FALSE;
}
CamelProvider *provider;
CamelURL *url0, *url1;
int equal;
-
+
g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
g_return_val_if_fail (uri0 && uri1, FALSE);
-
+
provider = ((CamelService *) store)->provider;
-
+
if (!(url0 = camel_url_new (uri0, NULL)))
return FALSE;
-
+
if (!(url1 = camel_url_new (uri1, NULL))) {
camel_url_free (url0);
return FALSE;
}
-
+
if ((equal = provider->url_equal (url0, url1))) {
const char *name0, *name1;
-
+
if (provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) {
name0 = url0->fragment;
name1 = url1->fragment;
if (name1 == NULL)
g_warning("URI is badly formed, missing folder name: %s", uri1);
-
+
equal = name0 && name1 && CS_CLASS (store)->compare_folder_name (name0, name1);
}
-
+
camel_url_free (url0);
camel_url_free (url1);
-
+
return equal;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-store.h : Abstract class for an email store */
-/*
+/*
*
* Authors: Bertrand Guiheneuf <bertrand@helixcode.com>
* Michael Zucchi <NotZed@ximian.com>
*
* Copyright 1999, 2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
struct _CamelStore {
CamelService parent_object;
struct _CamelStorePrivate *priv;
-
+
CamelObjectBag *folders;
guint32 flags;
guint32 flags,
CamelException *ex);
- CamelFolder * (*get_inbox) (CamelStore *store, CamelException *ex);
+ CamelFolder * (*get_inbox) (CamelStore *store, CamelException *ex);
CamelFolder * (*get_trash) (CamelStore *store, CamelException *ex);
CamelFolder * (*get_junk) (CamelStore *store, CamelException *ex);
-
+
CamelFolderInfo *(*create_folder) (CamelStore *store,
const char *parent_name,
const char *folder_name,
const char *old_name,
const char *new_name,
CamelException *ex);
-
+
void (*sync) (CamelStore *store, int expunge, CamelException *ex);
-
+
CamelFolderInfo *(*get_folder_info) (CamelStore *store,
const char *top,
guint32 flags,
CamelException *ex);
void (*free_folder_info) (CamelStore *store,
CamelFolderInfo *fi);
-
+
gboolean (*folder_subscribed) (CamelStore *store,
const char *folder_name);
void (*subscribe_folder) (CamelStore *store,
sbf->buf = g_malloc(size);
sbf->flags &= ~BUF_USER;
}
-
+
sbf->ptr = sbf->buf;
sbf->end = sbf->buf;
sbf->size = size;
#include "camel-stream-filter.h"
-#define d(x)
+#define d(x)
/* use my malloc debugger? */
/*extern void g_check(void *mp);*/
struct _CamelStreamFilterPrivate {
struct _filter *filters;
int filterid; /* next filter id */
-
+
char *realbuffer; /* buffer - READ_PAD */
char *buffer; /* READ_SIZE bytes */
camel_stream_class->write = do_write;
camel_stream_class->flush = do_flush;
camel_stream_class->close = do_close;
- camel_stream_class->eos = do_eos;
+ camel_stream_class->eos = do_eos;
camel_stream_class->reset = do_reset;
}
camel_stream_filter_init (CamelStreamFilter *obj)
{
struct _CamelStreamFilterPrivate *p;
-
+
_PRIVATE(obj) = p = g_malloc0(sizeof(*p));
p->realbuffer = g_malloc(READ_SIZE + READ_PAD);
p->buffer = p->realbuffer + READ_PAD;
camel_stream_filter_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_STREAM_TYPE, "CamelStreamFilter",
sizeof (CamelStreamFilter),
(CamelObjectInitFunc) camel_stream_filter_init,
(CamelObjectFinalizeFunc) camel_stream_filter_finalize);
}
-
+
return type;
}
* camel_stream_filter_new:
*
* Create a new #CamelStreamFilter object.
- *
+ *
* Returns a new #CamelStreamFilter object.
**/
CamelStreamFilter *
* camel_stream_filter_add:
* @stream: a #CamelStreamFilter object
* @filter: a #CamelMimeFilter object
- *
+ *
* Add a new #CamelMimeFilter to execute during the processing of this
* stream. Each filter added is processed after the previous one.
*
* Note that a filter should only be added to a single stream
* at a time, otherwise unpredictable results may occur.
- *
+ *
* Returns a filter id for the added @filter.
**/
int
* camel_stream_filter_remove:
* @stream: a #CamelStreamFilter object
* @id: Filter id, as returned from #camel_stream_filter_add
- *
+ *
* Remove a processing filter from the stream by id.
**/
void
char *buffer;
size_t presize;
size_t len;
-
+
if (p->last_was_read)
return 0;
-
+
buffer = "";
len = 0;
presize = 0;
f = p->filters;
-
+
d(printf ("\n\nFlushing: Original content (%s): '", ((CamelObject *)filter->source)->klass->name));
d(fwrite(buffer, sizeof(char), len, stdout));
d(printf("'\n"));
{
CamelStreamFilter *filter = (CamelStreamFilter *)stream;
struct _CamelStreamFilterPrivate *p = _PRIVATE(filter);
-
+
if (p->filteredlen > 0)
return FALSE;
-
+
if (!p->flushed)
return FALSE;
-
+
return camel_stream_eos(filter->source);
}
p->filteredlen = 0;
p->flushed = FALSE;
-
+
/* and reset filters */
f = p->filters;
while (f) {
CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream);
CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream);
ssize_t nread;
-
+
if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
n = MIN (seekable->bound_end - seekable->position, n);
-
+
if ((nread = camel_read (stream_fs->fd, buffer, n)) > 0)
seekable->position += nread;
else if (nread == 0)
stream->eos = TRUE;
-
+
return nread;
}
CamelStreamFs *stream_fs = CAMEL_STREAM_FS (stream);
CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream);
ssize_t nwritten;
-
+
if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
n = MIN (seekable->bound_end - seekable->position, n);
-
+
if ((nwritten = camel_write (stream_fs->fd, buffer, n)) > 0)
seekable->position += nwritten;
-
+
return nwritten;
}
{
if (close (((CamelStreamFs *)stream)->fd) == -1)
return -1;
-
+
((CamelStreamFs *)stream)->fd = -1;
return 0;
}
/**
* camel_stream_mem_set_secure:
* @mem: a #CamelStreamMem object
- *
+ *
* Mark the memory stream as secure. At the very least this means the
* data in the buffer will be cleared when the buffer is finalised.
* This only applies to buffers owned by the stream.
CamelStreamMem *stream_mem = CAMEL_STREAM_MEM (stream);
CamelSeekableStream *seekable = CAMEL_SEEKABLE_STREAM (stream);
ssize_t nwrite = n;
-
+
if (seekable->bound_end != CAMEL_STREAM_UNBOUND)
nwrite = MIN(seekable->bound_end - seekable->position, n);
struct _CamelStreamNull {
CamelStream parent;
-
+
size_t written;
};
*
* Authors: David Woodhouse <dwmw2@infradead.org>,
* Jeffrey Stedfast <fejj@ximian.com>
- *
+ *
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU Lesser General Public
camel_stream_process_class_init (CamelStreamProcessClass *camel_stream_process_class)
{
CamelStreamClass *camel_stream_class = (CamelStreamClass *) camel_stream_process_class;
-
+
parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE);
-
+
/* virtual method definition */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_stream_process_init (gpointer object, gpointer klass)
{
CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object);
-
+
stream->sockfd = -1;
stream->childpid = 0;
}
camel_stream_process_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_stream_get_type (),
"CamelStreamProcess",
(CamelObjectInitFunc) camel_stream_process_init,
(CamelObjectFinalizeFunc) camel_stream_process_finalise);
}
-
+
return type;
}
stream_read (CamelStream *stream, char *buffer, size_t n)
{
CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream);
-
+
return camel_read (stream_process->sockfd, buffer, n);
}
stream_write (CamelStream *stream, const char *buffer, size_t n)
{
CamelStreamProcess *stream_process = CAMEL_STREAM_PROCESS (stream);
-
+
return camel_write (stream_process->sockfd, buffer, n);
}
stream_close (CamelStream *object)
{
CamelStreamProcess *stream = CAMEL_STREAM_PROCESS (object);
-
+
if (camel_verbose_debug)
fprintf (stderr, "Process stream close. sockfd %d, childpid %d\n",
stream->sockfd, stream->childpid);
-
+
if (stream->sockfd != -1) {
close (stream->sockfd);
stream->sockfd = -1;
}
-
+
if (stream->childpid) {
int ret, i;
for (i = 0; i < 4; i++) {
break;
}
}
-
+
stream->childpid = 0;
}
-
+
return 0;
}
do_exec_command (int fd, const char *command, char **env)
{
int i, maxopen;
-
+
/* Not a lot we can do if there's an error other than bail. */
if (dup2 (fd, 0) == -1)
exit (1);
if (dup2 (fd, 1) == -1)
exit (1);
-
+
/* What to do with stderr? Possibly put it through a separate pipe
and bring up a dialog box with its output if anything does get
spewed to it? It'd help the user understand what was going wrong
with their command, but it's hard to do cleanly. For now we just
leave it as it is. Perhaps we should close it and reopen /dev/null? */
-
+
maxopen = sysconf (_SC_OPEN_MAX);
for (i = 3; i < maxopen; i++)
fcntl (i, F_SETFD, FD_CLOEXEC);
-
+
setsid ();
#ifdef TIOCNOTTY
- /* Detach from the controlling tty if we have one. Otherwise,
- SSH might do something stupid like trying to use it instead
+ /* Detach from the controlling tty if we have one. Otherwise,
+ SSH might do something stupid like trying to use it instead
of running $SSH_ASKPASS. Doh. */
if ((fd = open ("/dev/tty", O_RDONLY)) != -1) {
ioctl (fd, TIOCNOTTY, NULL);
close (fd);
}
#endif /* TIOCNOTTY */
-
- /* Set up child's environment. We _add_ to it, don't use execle,
+
+ /* Set up child's environment. We _add_ to it, don't use execle,
because otherwise we'd destroy stuff like SSH_AUTH_SOCK etc. */
for ( ; env && *env; env++)
putenv(*env);
-
+
execl ("/bin/sh", "/bin/sh", "-c", command, NULL);
-
+
if (camel_verbose_debug)
fprintf (stderr, "exec failed %d\n", errno);
-
+
exit (1);
}
camel_stream_process_connect (CamelStreamProcess *stream, const char *command, const char **env)
{
int sockfds[2];
-
+
if (stream->sockfd != -1 || stream->childpid)
stream_close (CAMEL_STREAM (stream));
-
+
if (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfds))
return -1;
-
+
stream->childpid = fork ();
if (!stream->childpid) {
do_exec_command (sockfds[1], command, (char **)env);
stream->sockfd = -1;
return -1;
}
-
+
close (sockfds[1]);
stream->sockfd = sockfds[0];
-
+
return 0;
}
struct _CamelStreamProcess {
CamelStream parent;
-
+
int sockfd;
pid_t childpid;
};
{
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
g_return_val_if_fail (n == 0 || buffer, -1);
-
+
return (CS_CLASS (stream)->read) (stream, buffer, n);
}
/**
* camel_stream_close:
* @stream: a #CamelStream object
- *
+ *
* Closes the stream.
- *
+ *
* Returns %0 on success or %-1 on error.
**/
int
camel_stream_close (CamelStream *stream)
{
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-
+
return CS_CLASS (stream)->close (stream);
}
camel_stream_eos (CamelStream *stream)
{
g_return_val_if_fail (CAMEL_IS_STREAM (stream), TRUE);
-
+
return CS_CLASS (stream)->eos (stream);
}
camel_stream_reset (CamelStream *stream)
{
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-
+
return CS_CLASS (stream)->reset (stream);
}
va_list args;
char *string;
ssize_t ret;
-
+
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
-
+
va_start (args, fmt);
string = g_strdup_vprintf (fmt, args);
va_end (args);
-
+
if (!string)
return -1;
-
+
ret = camel_stream_write (stream, string, strlen (string));
g_free (string);
return ret;
{
const char *p = (char *) v;
guint h = 0, g;
-
+
for ( ; *p != '\0'; p++) {
h = (h << 4) + g_ascii_toupper (*p);
if ((g = h & 0xf0000000)) {
h = h ^ g;
}
}
-
+
return h;
}
camel_string_list_free (GList *string_list)
{
if (string_list == NULL)
- return;
-
+ return;
+
g_list_foreach (string_list, free_string, NULL);
g_list_free (string_list);
}
/* find the needle in the haystack neglecting case */
const char *ptr;
guint len;
-
+
g_return_val_if_fail (haystack != NULL, NULL);
g_return_val_if_fail (needle != NULL, NULL);
-
+
len = strlen (needle);
if (len > strlen (haystack))
return NULL;
-
+
if (len == 0)
return (char *) haystack;
-
+
for (ptr = haystack; *(ptr + len - 1) != '\0'; ptr++)
if (!g_ascii_strncasecmp (ptr, needle, len))
return (char *) ptr;
-
+
return NULL;
}
camel_strdown (char *str)
{
register char *s = str;
-
+
while (*s) {
if (*s >= 'A' && *s <= 'Z')
*s += 0x20;
s++;
}
-
+
return str;
}
/**
* camel_tolower:
- * @c:
- *
+ * @c:
+ *
* ASCII to-lower function.
- *
- * Return value:
+ *
+ * Return value:
**/
char camel_tolower(char c)
{
/**
* camel_toupper:
- * @c:
- *
+ * @c:
+ *
* ASCII to-upper function.
- *
- * Return value:
+ *
+ * Return value:
**/
char camel_toupper(char c)
{
void *pcount;
char *pstr;
int count;
-
+
if (str == NULL)
return NULL;
-
+
if (str[0] == '\0') {
if (own)
g_free (str);
return "";
}
-
+
pthread_mutex_lock (&pstring_lock);
if (pstring_table == NULL)
pstring_table = g_hash_table_new (g_str_hash, g_str_equal);
-
+
if (g_hash_table_lookup_extended (pstring_table, str, (void **) &pstr, &pcount)) {
count = GPOINTER_TO_INT (pcount) + 1;
g_hash_table_insert (pstring_table, pstr, GINT_TO_POINTER (count));
pstr = own ? str : g_strdup (str);
g_hash_table_insert (pstring_table, pstr, GINT_TO_POINTER (1));
}
-
+
pthread_mutex_unlock (&pstring_lock);
-
+
return pstr;
}
/**
* camel_pstring_strdup:
* @s: String to copy.
- *
+ *
* Create a new pooled string entry for the string @s. A pooled
* string is a table where common strings are uniquified to the same
* pointer value. They are also refcounted, so freed when no longer
* in use. In a thread-safe manner.
- *
+ *
* The NULL and empty strings are special cased to constant values.
*
* Return value: A pointer to an equivalent string of @s. Use
/**
* camel_pstring_free:
* @s: String to free.
- *
+ *
* De-ref a pooled string. If no more refs exist to this string, it will be deallocated.
*
* NULL and the empty string are special cased.
struct _CamelTcpStreamSSLPrivate {
int sockfd;
SSL *ssl;
-
+
CamelService *service;
char *expected_host;
gboolean ssl_mode;
CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_ssl_class);
CamelStreamClass *camel_stream_class =
CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class);
-
+
parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
-
+
/* virtual method overload */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_stream_class->flush = stream_flush;
camel_stream_class->close = stream_close;
-
+
camel_tcp_stream_class->connect = stream_connect;
camel_tcp_stream_class->getsockopt = stream_getsockopt;
camel_tcp_stream_class->setsockopt = stream_setsockopt;
camel_tcp_stream_class->get_local_address = stream_get_local_address;
camel_tcp_stream_class->get_remote_address = stream_get_remote_address;
-
+
/* init OpenSSL stuff */
SSLeay_add_ssl_algorithms ();
SSL_load_error_strings ();
camel_tcp_stream_ssl_init (gpointer object, gpointer klass)
{
CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
-
+
stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1);
stream->priv->sockfd = -1;
}
camel_tcp_stream_ssl_finalize (CamelObject *object)
{
CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
-
+
if (stream->priv->ssl) {
SSL_shutdown (stream->priv->ssl);
-
+
if (stream->priv->ssl->ctx) {
SSL_CTX_free (stream->priv->ssl->ctx);
}
-
+
SSL_free (stream->priv->ssl);
}
-
+
if (stream->priv->sockfd != -1)
close (stream->priv->sockfd);
-
+
g_free (stream->priv->expected_host);
-
+
g_free (stream->priv);
}
camel_tcp_stream_ssl_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_tcp_stream_get_type (),
"CamelTcpStreamSSL",
(CamelObjectInitFunc) camel_tcp_stream_ssl_init,
(CamelObjectFinalizeFunc) camel_tcp_stream_ssl_finalize);
}
-
+
return type;
}
camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host, guint32 flags)
{
CamelTcpStreamSSL *stream;
-
+
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
-
+
stream->priv->service = service;
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = TRUE;
stream->priv->flags = flags;
-
+
return CAMEL_STREAM (stream);
}
camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host, guint32 flags)
{
CamelTcpStreamSSL *stream;
-
+
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
-
+
stream->priv->service = service;
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = FALSE;
stream->priv->flags = flags;
-
+
return CAMEL_STREAM (stream);
}
camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *stream)
{
SSL *ssl;
-
+
g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (stream), -1);
-
+
if (stream->priv->sockfd != -1 && !stream->priv->ssl_mode) {
ssl = open_ssl_connection (stream->priv->service, stream->priv->sockfd, stream);
if (ssl == NULL) {
stream->priv->sockfd = -1;
return -1;
}
-
+
stream->priv->ssl = ssl;
}
-
+
stream->priv->ssl_mode = TRUE;
-
+
return 0;
}
SSL *ssl = openssl->priv->ssl;
ssize_t nread;
int cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
}
-
+
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
do {
int error, flags, fdmax;
struct timeval timeout;
fd_set rdset;
-
+
flags = fcntl (openssl->priv->sockfd, F_GETFL);
fcntl (openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK);
-
+
fdmax = MAX (openssl->priv->sockfd, cancel_fd) + 1;
-
+
do {
FD_ZERO (&rdset);
FD_SET (openssl->priv->sockfd, &rdset);
FD_SET (cancel_fd, &rdset);
-
+
timeout.tv_sec = 0;
timeout.tv_usec = TIMEOUT_USEC;
errno = EINTR;
return -1;
}
-
+
do {
if (ssl) {
nread = SSL_read (ssl, buffer, n);
}
} while (nread < 0 && errno == EINTR);
} while (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK));
-
+
error = errno;
fcntl (openssl->priv->sockfd, F_SETFL, flags);
errno = error;
}
-
+
return nread;
}
SSL *ssl = openssl->priv->ssl;
ssize_t w, written = 0;
int cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
}
-
+
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
do {
w = write (openssl->priv->sockfd, buffer + written, n - written);
}
} while (w < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-
+
if (w > 0)
written += w;
} while (w != -1 && written < n);
errno = EINTR;
return -1;
}
-
+
do {
if (ssl) {
w = SSL_write (ssl, buffer + written, n - written);
w = write (openssl->priv->sockfd, buffer + written, n - written);
}
} while (w < 0 && errno == EINTR);
-
+
if (w < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
w = 0;
} else
written += w;
} while (w >= 0 && written < n);
-
+
fcntl (openssl->priv->sockfd, F_SETFL, flags);
}
-
+
return written;
}
{
if (ssl) {
SSL_shutdown (ssl);
-
+
if (ssl->ctx)
SSL_CTX_free (ssl->ctx);
-
+
SSL_free (ssl);
}
}
{
close_ssl_connection (((CamelTcpStreamSSL *)stream)->priv->ssl);
((CamelTcpStreamSSL *)stream)->priv->ssl = NULL;
-
+
if (close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == -1)
return -1;
-
+
((CamelTcpStreamSSL *)stream)->priv->sockfd = -1;
return 0;
}
socklen_t len;
int cancel_fd;
int ret, fd;
-
+
/* see if we're cancelled yet */
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
}
-
+
/* setup connect, we do it using a nonblocking socket so we can poll it */
#ifdef ENABLE_IPv6
if (h->h_addrtype == AF_INET6) {
#ifdef ENABLE_IPv6
}
#endif
-
+
fd = socket (h->h_addrtype, SOCK_STREAM, 0);
-
+
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
ret = connect (fd, saddr, len);
close (fd);
return -1;
}
-
+
return fd;
} else {
fd_set rdset, wrset;
int flags, fdmax;
-
+
flags = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
-
+
ret = connect (fd, saddr, len);
if (ret == 0) {
fcntl (fd, F_SETFL, flags);
return fd;
}
-
+
if (errno != EINPROGRESS) {
close (fd);
return -1;
}
-
+
FD_ZERO (&rdset);
FD_ZERO (&wrset);
FD_SET (fd, &wrset);
fdmax = MAX (fd, cancel_fd) + 1;
tv.tv_usec = 0;
tv.tv_sec = 60 * 4;
-
+
if (select (fdmax, &rdset, &wrset, 0, &tv) == 0) {
close (fd);
errno = ETIMEDOUT;
return -1;
}
-
+
if (cancel_fd != -1 && FD_ISSET (cancel_fd, &rdset)) {
close (fd);
errno = EINTR;
return -1;
} else {
len = sizeof (int);
-
+
if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &len) == -1) {
close (fd);
return -1;
}
-
+
if (ret != 0) {
close (fd);
errno = ret;
return -1;
}
}
-
+
fcntl (fd, F_SETFL, flags);
}
-
+
return fd;
}
ok = ccert->trust != CAMEL_CERT_TRUST_NEVER;
camel_certdb_cert_unref (certdb, ccert);
camel_object_unref (certdb);
-
+
return ok;
}
} else {
camel_cert_set_hostname (certdb, ccert, (const char *) stream->priv->expected_host);
camel_cert_set_fingerprint (certdb, ccert, (const char *) fingerprint);
camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN);
-
+
/* Add the certificate to our db */
camel_certdb_add (certdb, ccert);
}
}
-
+
cert_str = g_strdup_printf (_("Issuer: %s\n"
"Subject: %s\n"
"Fingerprint: %s\n"
GET_STRING (X509_get_issuer_name (cert)),
GET_STRING (X509_get_subject_name (cert)),
fingerprint, cert->valid ? _("GOOD") : _("BAD"));
-
+
prompt = g_strdup_printf (_("Bad certificate from %s:\n\n%s\n\n%s\n\n"
"Do you wish to accept anyway?"),
service->url->host, cert_str, x509_strerror (err));
-
+
ok = camel_session_alert_user (service->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE);
g_free (prompt);
-
+
if (ok && ccert) {
camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_FULLY);
camel_certdb_touch (certdb);
}
-
+
if (certdb) {
camel_certdb_cert_unref (certdb, ccert);
camel_object_unref (certdb);
}
-
+
return ok;
}
SSL_CTX *ssl_ctx = NULL;
SSL *ssl = NULL;
int n;
-
+
/* SSLv23_client_method will negotiate with SSL v2, v3, or TLS v1 */
ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
g_return_val_if_fail (ssl_ctx != NULL, NULL);
-
+
SSL_CTX_set_default_verify_paths (ssl_ctx);
SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_PEER, &ssl_verify);
ssl = SSL_new (ssl_ctx);
SSL_set_fd (ssl, sockfd);
-
+
SSL_CTX_set_app_data (ssl_ctx, openssl);
-
+
n = SSL_connect (ssl);
if (n != 1) {
int errnosave = ssl_errno (ssl, n);
-
+
SSL_shutdown (ssl);
-
+
if (ssl->ctx)
SSL_CTX_free (ssl->ctx);
-
+
SSL_free (ssl);
ssl = NULL;
-
+
close (sockfd);
-
+
errno = errnosave;
}
-
+
return ssl;
}
CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream);
SSL *ssl = NULL;
int fd;
-
+
g_return_val_if_fail (host != NULL, -1);
-
+
fd = socket_connect (host, port);
if (fd == -1)
return -1;
-
+
if (openssl->priv->ssl_mode) {
ssl = open_ssl_connection (openssl->priv->service, fd, openssl);
if (!ssl)
return -1;
}
-
+
openssl->priv->sockfd = fd;
openssl->priv->ssl = ssl;
-
+
return 0;
}
stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
{
int optname, optlen;
-
+
if ((optname = get_sockopt_optname (data)) == -1)
return -1;
-
+
if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
int flags;
-
+
flags = fcntl (((CamelTcpStreamSSL *) stream)->priv->sockfd, F_GETFL);
if (flags == -1)
return -1;
-
+
data->value.non_blocking = flags & O_NONBLOCK ? TRUE : FALSE;
-
+
return 0;
}
-
+
return getsockopt (((CamelTcpStreamSSL *) stream)->priv->sockfd,
get_sockopt_level (data),
optname,
stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
{
int optname;
-
+
if ((optname = get_sockopt_optname (data)) == -1)
return -1;
-
+
if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
int flags, set;
-
+
flags = fcntl (((CamelTcpStreamSSL *) stream)->priv->sockfd, F_GETFL);
if (flags == -1)
return -1;
-
+
set = data->value.non_blocking ? O_NONBLOCK : 0;
flags = (flags & ~O_NONBLOCK) | set;
-
+
if (fcntl (((CamelTcpStreamSSL *) stream)->priv->sockfd, F_SETFL, flags) == -1)
return -1;
-
+
return 0;
}
-
+
return setsockopt (((CamelTcpStreamSSL *) stream)->priv->sockfd,
get_sockopt_level (data),
optname,
gpointer address;
socklen_t len;
int family;
-
+
len = MIN_SOCKADDR_BUFLEN;
-
+
if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1)
return NULL;
-
+
if (saddr->sa_family == AF_INET) {
family = CAMEL_TCP_ADDRESS_IPv4;
address = &sin->sin_addr;
#endif
} else
return NULL;
-
+
return camel_tcp_address_new (family, sin->sin_port, len, address);
}
gpointer address;
socklen_t len;
int family;
-
+
len = MIN_SOCKADDR_BUFLEN;
-
+
if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1)
return NULL;
-
+
if (saddr->sa_family == AF_INET) {
family = CAMEL_TCP_ADDRESS_IPv4;
address = &sin->sin_addr;
#endif
} else
return NULL;
-
+
return camel_tcp_address_new (family, sin->sin_port, len, address);
}
CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_raw_class);
CamelStreamClass *camel_stream_class =
CAMEL_STREAM_CLASS (camel_tcp_stream_raw_class);
-
+
parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
-
+
/* virtual method overload */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_stream_class->flush = stream_flush;
camel_stream_class->close = stream_close;
-
+
camel_tcp_stream_class->connect = stream_connect;
camel_tcp_stream_class->getsockopt = stream_getsockopt;
camel_tcp_stream_class->setsockopt = stream_setsockopt;
camel_tcp_stream_raw_init (gpointer object, gpointer klass)
{
CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object);
-
+
stream->sockfd = -1;
}
camel_tcp_stream_raw_finalize (CamelObject *object)
{
CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object);
-
+
if (stream->sockfd != -1)
SOCKET_CLOSE (stream->sockfd);
}
camel_tcp_stream_raw_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_tcp_stream_get_type (),
"CamelTcpStreamRaw",
(CamelObjectInitFunc) camel_tcp_stream_raw_init,
(CamelObjectFinalizeFunc) camel_tcp_stream_raw_finalize);
}
-
+
return type;
}
size_t len = buflen;
ssize_t nwritten;
int val;
-
+
if (buflen == 0)
return 0;
-
+
val = 1 + (int) (10.0 * rand () / (RAND_MAX + 1.0));
-
+
switch (val) {
case 1:
printf ("flaky_tcp_write (%d, ..., %d): (-1) EINTR\n", fd, buflen);
printf (" only wrote %d bytes\n", nwritten);
else
printf ("\n");
-
+
return nwritten;
}
}
size_t len = buflen;
ssize_t nread;
int val;
-
+
if (buflen == 0)
return 0;
-
+
val = 1 + (int) (10.0 * rand () / (RAND_MAX + 1.0));
-
+
switch (val) {
case 1:
printf ("flaky_tcp_read (%d, ..., %d): (-1) EINTR\n", fd, buflen);
printf (" only read %d bytes\n", nread);
else
printf ("\n");
-
+
return nread;
}
}
camel_tcp_stream_raw_new (void)
{
CamelTcpStreamRaw *stream;
-
+
stream = CAMEL_TCP_STREAM_RAW (camel_object_new (camel_tcp_stream_raw_get_type ()));
-
+
return CAMEL_STREAM (stream);
}
stream_read (CamelStream *stream, char *buffer, size_t n)
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
-
+
return camel_read_socket (raw->sockfd, buffer, n);
}
stream_write (CamelStream *stream, const char *buffer, size_t n)
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
-
+
return camel_write_socket (raw->sockfd, buffer, n);
}
{
if (SOCKET_CLOSE (((CamelTcpStreamRaw *)stream)->sockfd) == -1)
return -1;
-
+
((CamelTcpStreamRaw *)stream)->sockfd = -1;
return 0;
}
int cancel_fd;
int errnosav;
int ret, fd;
-
+
/* see if we're cancelled yet */
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
}
-
+
if (h->ai_socktype != SOCK_STREAM) {
errno = EINVAL;
return -1;
if ((fd = socket (h->ai_family, SOCK_STREAM, 0)) == -1)
return -1;
-
+
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
if (connect (fd, h->ai_addr, h->ai_addrlen) == -1) {
errno = errnosav;
return -1;
}
-
+
return fd;
} else {
#ifndef G_OS_WIN32
#endif
int fdmax, status;
fd_set rdset, wrset;
-
+
#ifndef G_OS_WIN32
flags = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
#endif
return fd;
}
-
+
if (!SOCKET_ERROR_IS_EINPROGRESS ()) {
errnosav = errno;
SOCKET_CLOSE (fd);
errno = errnosav;
return -1;
}
-
+
do {
FD_ZERO (&rdset);
FD_ZERO (&wrset);
fdmax = MAX (fd, cancel_fd) + 1;
tv.tv_sec = 60 * 4;
tv.tv_usec = 0;
-
+
status = select (fdmax, &rdset, &wrset, NULL, &tv);
} while (status == -1 && SOCKET_ERROR_IS_EINTR ());
-
+
if (status <= 0) {
SOCKET_CLOSE (fd);
errno = ETIMEDOUT;
return -1;
}
-
+
if (cancel_fd != -1 && FD_ISSET (cancel_fd, &rdset)) {
SOCKET_CLOSE (fd);
errno = EINTR;
return -1;
} else {
len = sizeof (int);
-
+
if (getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &ret, &len) == -1) {
errnosav = errno;
SOCKET_CLOSE (fd);
errno = errnosav;
return -1;
}
-
+
if (ret != 0) {
SOCKET_CLOSE (fd);
errno = ret;
}
#endif
}
-
+
return fd;
}
stream_connect (CamelTcpStream *stream, struct addrinfo *host)
{
CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
-
+
g_return_val_if_fail (host != NULL, -1);
while (host) {
stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
{
int optname, optlen;
-
+
if ((optname = get_sockopt_optname (data)) == -1)
return -1;
-
+
if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
#ifndef G_OS_WIN32
int flags;
-
+
flags = fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_GETFL);
if (flags == -1)
return -1;
-
+
data->value.non_blocking = flags & O_NONBLOCK ? TRUE : FALSE;
#else
data->value.non_blocking = ((CamelTcpStreamRaw *)stream)->is_nonblocking;
#endif
return 0;
}
-
+
return getsockopt (((CamelTcpStreamRaw *)stream)->sockfd,
get_sockopt_level (data),
optname,
stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
{
int optname;
-
+
if ((optname = get_sockopt_optname (data)) == -1)
return -1;
-
+
if (data->option == CAMEL_SOCKOPT_NONBLOCKING) {
#ifndef G_OS_WIN32
int flags, set;
-
+
flags = fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_GETFL);
if (flags == -1)
return -1;
-
+
set = data->value.non_blocking ? O_NONBLOCK : 0;
flags = (flags & ~O_NONBLOCK) | set;
-
+
if (fcntl (((CamelTcpStreamRaw *)stream)->sockfd, F_SETFL, flags) == -1)
return -1;
#else
#endif
return 0;
}
-
+
return setsockopt (((CamelTcpStreamRaw *)stream)->sockfd,
get_sockopt_level (data),
optname,
struct _CamelTcpStreamRaw
{
CamelTcpStream parent_object;
-
+
int sockfd;
#ifdef G_OS_WIN32
int is_nonblocking;
typedef struct {
CamelTcpStreamClass parent_class;
-
+
/* virtual functions */
-
+
} CamelTcpStreamRawClass;
/* Standard Camel function */
struct _CamelTcpStreamSSLPrivate {
PRFileDesc *sockfd;
-
+
struct _CamelSession *session;
char *expected_host;
gboolean ssl_mode;
CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_ssl_class);
CamelStreamClass *camel_stream_class =
CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class);
-
+
parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
-
+
/* virtual method overload */
camel_stream_class->read = stream_read;
camel_stream_class->write = stream_write;
camel_stream_class->flush = stream_flush;
camel_stream_class->close = stream_close;
-
+
camel_tcp_stream_class->connect = stream_connect;
camel_tcp_stream_class->getsockopt = stream_getsockopt;
camel_tcp_stream_class->setsockopt = stream_setsockopt;
camel_tcp_stream_ssl_init (gpointer object, gpointer klass)
{
CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
-
+
stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1);
}
camel_object_unref(stream->priv->session);
g_free (stream->priv->expected_host);
-
+
g_free (stream->priv);
}
camel_tcp_stream_ssl_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_tcp_stream_get_type (),
"CamelTcpStreamSSL",
(CamelObjectInitFunc) camel_tcp_stream_ssl_init,
(CamelObjectFinalizeFunc) camel_tcp_stream_ssl_finalize);
}
-
+
return type;
}
g_assert(CAMEL_IS_SESSION(session));
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
-
+
stream->priv->session = session;
camel_object_ref(session);
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = TRUE;
stream->priv->flags = flags;
-
+
return CAMEL_STREAM (stream);
}
CamelTcpStreamSSL *stream;
g_assert(CAMEL_IS_SESSION(session));
-
+
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
-
+
stream->priv->session = session;
camel_object_ref(session);
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = FALSE;
stream->priv->flags = flags;
-
+
return CAMEL_STREAM (stream);
}
CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
PRFileDesc *cancel_fd;
ssize_t nread;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
}
-
+
cancel_fd = camel_operation_cancel_prfd (NULL);
if (cancel_fd == NULL) {
do {
PRPollDesc pollfds[2];
gboolean nonblock;
int error;
-
+
/* get O_NONBLOCK options */
sockopts.option = PR_SockOpt_Nonblocking;
PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
pollfds[0].in_flags = PR_POLL_READ;
pollfds[1].fd = cancel_fd;
pollfds[1].in_flags = PR_POLL_READ;
-
+
do {
PRInt32 res;
} while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
PR_GetError () == PR_IO_PENDING_ERROR ||
PR_GetError () == PR_WOULD_BLOCK_ERROR));
-
+
/* restore O_NONBLOCK options */
failed:
error = errno;
PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
errno = error;
}
-
+
return nread;
}
CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
ssize_t w, written = 0;
PRFileDesc *cancel_fd;
-
+
if (camel_operation_cancel_check (NULL)) {
errno = EINTR;
return -1;
}
-
+
cancel_fd = camel_operation_cancel_prfd (NULL);
if (cancel_fd == NULL) {
do {
} while (w == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR ||
PR_GetError () == PR_IO_PENDING_ERROR ||
PR_GetError () == PR_WOULD_BLOCK_ERROR));
-
+
if (w > 0)
written += w;
} while (w != -1 && written < n);
PRPollDesc pollfds[2];
gboolean nonblock;
int error;
-
+
/* get O_NONBLOCK options */
sockopts.option = PR_SockOpt_Nonblocking;
PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
nonblock = sockopts.value.non_blocking;
sockopts.value.non_blocking = TRUE;
PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-
+
pollfds[0].fd = tcp_stream_ssl->priv->sockfd;
pollfds[0].in_flags = PR_POLL_WRITE;
pollfds[1].fd = cancel_fd;
pollfds[1].in_flags = PR_POLL_READ;
-
+
do {
PRInt32 res;
if (w == -1)
set_errno (PR_GetError ());
} while (w == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR);
-
+
if (w == -1) {
if (PR_GetError () == PR_IO_PENDING_ERROR ||
PR_GetError () == PR_WOULD_BLOCK_ERROR)
written += w;
}
} while (w != -1 && written < n);
-
+
/* restore O_NONBLOCK options */
error = errno;
sockopts.option = PR_SockOpt_Nonblocking;
PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
errno = error;
}
-
+
if (w == -1)
return -1;
-
+
return written;
}
PR_Shutdown (((CamelTcpStreamSSL *)stream)->priv->sockfd, PR_SHUTDOWN_BOTH);
if (PR_Close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == PR_FAILURE)
return -1;
-
+
((CamelTcpStreamSSL *)stream)->priv->sockfd = NULL;
-
+
return 0;
}
ssl_get_client_auth (void *data, PRFileDesc *sockfd,
struct CERTDistNamesStr *caNames,
struct CERTCertificateStr **pRetCert,
- struct SECKEYPrivateKeyStr **pRetKey)
+ struct SECKEYPrivateKeyStr **pRetKey)
{
SECStatus status = SECFailure;
SECKEYPrivateKey *privkey;
CERTCertificate *cert;
void *proto_win;
-
+
proto_win = SSL_RevealPinArg (sockfd);
-
+
if ((char *) data) {
cert = PK11_FindCertFromNickname ((char *) data, proto_win);
if (cert) {
/* no nickname given, automatically find the right cert */
CERTCertNicknames *names;
int i;
-
- names = CERT_GetCertNicknames (CERT_GetDefaultCertDB (),
+
+ names = CERT_GetCertNicknames (CERT_GetDefaultCertDB (),
SEC_CERT_NICKNAMES_USER,
proto_win);
-
+
if (names != NULL) {
for (i = 0; i < names->numnicknames; i++) {
- cert = PK11_FindCertFromNickname (names->nicknames[i],
+ cert = PK11_FindCertFromNickname (names->nicknames[i],
proto_win);
if (!cert)
continue;
-
+
/* Only check unexpired certs */
if (CERT_CheckCertValidTimes (cert, PR_Now (), PR_FALSE) != secCertTimeValid) {
CERT_DestroyCertificate (cert);
continue;
}
-
+
status = NSS_CmpCertChainWCANames (cert, caNames);
if (status == SECSuccess) {
privkey = PK11_FindKeyByAnyCert (cert, proto_win);
if (privkey)
break;
-
+
status = SECFailure;
break;
}
-
+
CERT_FreeNicknames (names);
}
}
}
-
+
if (status == SECSuccess) {
*pRetCert = cert;
*pRetKey = privkey;
}
-
+
return status;
}
#endif
SECStatus status;
void *pinarg;
char *host;
-
+
cert = SSL_PeerCertificate (sockfd);
pinarg = SSL_RevealPinArg (sockfd);
status = CERT_VerifyCertNow ((CERTCertDBHandle *)data, cert,
checksig, certUsageSSLClient, pinarg);
-
+
if (status != SECSuccess)
return SECFailure;
-
+
/* Certificate is OK. Since this is the client side of an SSL
* connection, we need to verify that the name field in the cert
* matches the desired hostname. This is our defense against
* man-in-the-middle attacks.
*/
-
+
/* SSL_RevealURL returns a hostname, not a URL. */
host = SSL_RevealURL (sockfd);
-
+
if (host && *host) {
status = CERT_VerifyCertName (cert, host);
} else {
PR_SetError (SSL_ERROR_BAD_CERT_DOMAIN, 0);
status = SECFailure;
}
-
+
if (host)
PR_Free (host);
-
+
return secStatus;
}
#endif
char *dir, *path, *fingerprint;
CamelStream *stream;
struct stat st;
-
+
fingerprint = ccert->fingerprint;
-
+
if (ccert->rawcert == NULL)
ccert->rawcert = g_byte_array_new ();
-
+
g_byte_array_set_size (ccert->rawcert, cert->derCert.len);
memcpy (ccert->rawcert->data, cert->derCert.data, cert->derCert.len);
-
+
#ifndef G_OS_WIN32
dir = g_strdup_printf ("%s/.camel_certs", getenv ("HOME"));
#else
g_free (dir);
return;
}
-
+
path = g_strdup_printf ("%s/%s", dir, fingerprint);
g_free (dir);
-
+
stream = camel_stream_fs_new_with_name (path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (stream != NULL) {
if (camel_stream_write (stream, (const char *) ccert->rawcert->data, ccert->rawcert->len) == -1) {
} else {
g_warning ("Could not save cert: %s: %s", path, strerror (errno));
}
-
+
g_free (path);
}
g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (data), SECFailure);
ssl = data;
-
+
cert = SSL_PeerCertificate (sockfd);
if (cert == NULL)
return SECFailure;
prompt = g_strdup_printf (_("SSL Certificate check for %s:\n\n%s\n\nDo you wish to accept?"),
ssl->priv->expected_host, cert_str);
g_free (cert_str);
-
+
/* query the user to find out if we want to accept this certificate */
accept = camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE);
g_free(prompt);
cert->trust = (CERTCertTrust*)PORT_ArenaZAlloc(cert->arena, sizeof(CERTCertTrust));
CERT_DecodeTrustString(cert->trust, "P");
}
-
+
certs[0] = &cert->derCert;
/*CERT_ImportCerts (cert->dbhandle, certUsageSSLServer, 1, certs, NULL, TRUE, FALSE, nick);*/
CERT_ImportCerts(cert->dbhandle, certUsageUserCertImport, 1, certs, NULL, TRUE, FALSE, nick);
}
break;
-
+
case SEC_ERROR_EXPIRED_CERTIFICATE:
printf("expired\n");
enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd)
{
PRFileDesc *ssl_fd;
-
+
ssl_fd = SSL_ImportFD (NULL, fd ? fd : ssl->priv->sockfd);
if (!ssl_fd)
return NULL;
-
+
SSL_OptionSet (ssl_fd, SSL_SECURITY, PR_TRUE);
if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL2) {
SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_TRUE);
else
SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_FALSE);
-
+
SSL_SetURL (ssl_fd, ssl->priv->expected_host);
-
+
/*SSL_GetClientAuthDataHook (sslSocket, ssl_get_client_auth, (void *) certNickname);*/
/*SSL_AuthCertificateHook (ssl_fd, ssl_auth_cert, (void *) CERT_GetDefaultCertDB ());*/
SSL_BadCertHook (ssl_fd, ssl_bad_cert, ssl);
-
+
ssl->priv->ssl_mode = TRUE;
-
+
return ssl_fd;
}
if (PR_Connect (fd, &netaddr, cancel_fd?0:CONNECT_TIMEOUT) == PR_FAILURE) {
int errnosave;
-
+
set_errno (PR_GetError ());
if (PR_GetError () == PR_IN_PROGRESS_ERROR ||
(cancel_fd && (PR_GetError () == PR_CONNECT_TIMEOUT_ERROR ||
poll[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
poll[1].fd = cancel_fd;
poll[1].in_flags = PR_POLL_READ;
-
+
do {
poll[0].out_flags = 0;
poll[1].out_flags = 0;
set_errno (PR_GetError ());
goto exception;
}
-
+
if (poll[1].out_flags == PR_POLL_READ) {
errno = EINTR;
goto exception;
PR_Close (fd);
ssl->priv->sockfd = NULL;
errno = errnosave;
-
+
return -1;
}
-
+
errno = 0;
}
-
+
ssl->priv->sockfd = fd;
return 0;
stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
{
PRSocketOptionData sodata;
-
+
memset ((void *) &sodata, 0, sizeof (sodata));
memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData));
-
+
if (PR_GetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE)
return -1;
-
+
memcpy ((void *) data, (void *) &sodata, sizeof (CamelSockOptData));
-
+
return 0;
}
stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
{
PRSocketOptionData sodata;
-
+
memset ((void *) &sodata, 0, sizeof (sodata));
memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData));
-
+
if (PR_SetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE)
return -1;
-
+
return 0;
}
sin->sin6_scope_id = addr->ipv6.scope_id;
*len = sizeof(*sin);
- return (struct sockaddr *)sin;
+ return (struct sockaddr *)sin;
}
#endif
{
PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd;
PRNetAddr addr;
-
+
if (PR_GetSockName(sockfd, &addr) != PR_SUCCESS)
return NULL;
{
PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd;
PRNetAddr addr;
-
+
if (PR_GetPeerName(sockfd, &addr) != PR_SUCCESS)
return NULL;
struct _CamelTcpStreamSSL {
CamelTcpStream parent_object;
-
+
struct _CamelTcpStreamSSLPrivate *priv;
};
typedef struct {
CamelTcpStreamClass parent_class;
-
+
/* virtual functions */
-
+
} CamelTcpStreamSSLClass;
/* Standard Camel function */
camel_tcp_stream_class_init (CamelTcpStreamClass *camel_tcp_stream_class)
{
/*CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_tcp_stream_class);*/
-
+
parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (CAMEL_STREAM_TYPE));
-
+
/* tcp stream methods */
camel_tcp_stream_class->connect = tcp_connect;
camel_tcp_stream_class->getsockopt = tcp_getsockopt;
camel_tcp_stream_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_STREAM_TYPE,
"CamelTcpStream",
camel_tcp_stream_connect (CamelTcpStream *stream, struct addrinfo *host)
{
g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
-
+
return CTS_CLASS (stream)->connect (stream, host);
}
camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
{
g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
-
+
return CTS_CLASS (stream)->getsockopt (stream, data);
}
camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
{
g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), -1);
-
+
return CTS_CLASS (stream)->setsockopt (stream, data);
}
{
g_return_val_if_fail (CAMEL_IS_TCP_STREAM (stream), NULL);
g_return_val_if_fail(len != NULL, NULL);
-
+
return CTS_CLASS (stream)->get_local_address (stream, len);
}
CAMEL_SOCKOPT_KEEPALIVE, /* keep connections alive */
CAMEL_SOCKOPT_RECVBUFFERSIZE, /* receive buffer size */
CAMEL_SOCKOPT_SENDBUFFERSIZE, /* send buffer size */
-
+
CAMEL_SOCKOPT_IPTIMETOLIVE, /* time to live */
CAMEL_SOCKOPT_IPTYPEOFSERVICE, /* type of service and precedence */
-
+
CAMEL_SOCKOPT_ADDMEMBER, /* add an IP group membership */
CAMEL_SOCKOPT_DROPMEMBER, /* drop an IP group membership */
CAMEL_SOCKOPT_MCASTINTERFACE, /* multicast interface address */
CAMEL_SOCKOPT_MCASTTIMETOLIVE, /* multicast timetolive */
CAMEL_SOCKOPT_MCASTLOOPBACK, /* multicast loopback */
-
+
CAMEL_SOCKOPT_NODELAY, /* don't delay send to coalesce packets */
CAMEL_SOCKOPT_MAXSEGMENT, /* maximum segment size */
CAMEL_SOCKOPT_BROADCAST, /* enable broadcast */
struct _CamelTcpStream {
CamelStream parent_object;
-
+
};
typedef struct {
int (*connect) (CamelTcpStream *stream, struct addrinfo *host);
int (*getsockopt) (CamelTcpStream *stream, CamelSockOptData *data);
int (*setsockopt) (CamelTcpStream *stream, const CamelSockOptData *data);
-
+
struct sockaddr * (*get_local_address) (CamelTcpStream *stream, socklen_t *len);
struct sockaddr * (*get_remote_address) (CamelTcpStream *stream, socklen_t *len);
} CamelTcpStreamClass;
#define w(x)
-#define io(x)
+#define io(x)
#define d(x) /*(printf("%s(%d):%s: ", __FILE__, __LINE__, __PRETTY_FUNCTION__),(x))*/
/* cursor debug */
return;
}
}
-
+
w = g_malloc0(sizeof(*w));
w->word = g_strdup(word);
w->wordid = wordid;
g_hash_table_remove(p->words, ww->word);
g_free(ww->word);
g_free(ww);
- }
+ }
if (camel_key_table_sync(p->word_index) == -1
|| camel_key_table_sync(p->name_index) == -1
}
g_free(records);
}
-
+
if (newcount > 0) {
if (camel_key_file_write(newp->links, &newdata, newcount, newrecords) == -1)
goto fail;
}
camel_block_file_touch_block(newp->blocks, newp->blocks->root_block);
-
+
if (camel_index_sync((CamelIndex *)newidx) == -1)
goto fail;
camel_key_table_set_flags(p->name_index, keyid, 1, 1);
camel_partition_table_remove(p->name_hash, name);
}
-
+
keyid = camel_key_table_add(p->name_index, name, 0, 0);
if (keyid != 0) {
camel_partition_table_add(p->name_hash, name, keyid);
/* see text_index_add_name for when this can be 0 */
if (((CamelTextIndexName *)idn)->priv->nameid != 0) {
CAMEL_TEXT_INDEX_LOCK(idx, lock);
-
+
g_hash_table_foreach(idn->words, (GHFunc)hash_write_word, idn);
-
+
CAMEL_TEXT_INDEX_UNLOCK(idx, lock);
}
/* this cache size and the block cache size have been tuned for about the best
with moderate memory usage. Doubling the memory usage barely affects performance. */
p->word_cache_limit = 4096; /* 1024 = 128K */
-
+
g_static_rec_mutex_init(&p->lock);
}
camel_object_unref((CamelObject *)p->blocks);
if (p->links)
camel_object_unref((CamelObject *)p->links);
-
+
g_static_rec_mutex_free(&p->lock);
-
+
g_free(p);
}
camel_text_index_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_index_get_type(), "CamelTextIndex",
sizeof (CamelTextIndex),
(CamelObjectInitFunc) camel_text_index_init,
(CamelObjectFinalizeFunc) camel_text_index_finalise);
}
-
+
return type;
}
rb->word_index_root = bl->id;
camel_block_file_unref_block(p->blocks, bl);
camel_block_file_touch_block(p->blocks, p->blocks->root_block);
- }
+ }
if (rb->word_hash_root == 0) {
bl = camel_block_file_new_block(p->blocks);
rb->word_hash_root = bl->id;
camel_block_file_unref_block(p->blocks, bl);
camel_block_file_touch_block(p->blocks, p->blocks->root_block);
- }
+ }
if (rb->name_index_root == 0) {
bl = camel_block_file_new_block(p->blocks);
rb->name_index_root = bl->id;
camel_block_file_unref_block(p->blocks, bl);
camel_block_file_touch_block(p->blocks, p->blocks->root_block);
- }
+ }
if (rb->name_hash_root == 0) {
bl = camel_block_file_new_block(p->blocks);
rb->name_hash_root = bl->id;
camel_block_file_unref_block(p->blocks, bl);
camel_block_file_touch_block(p->blocks, p->blocks->root_block);
- }
+ }
p->word_index = camel_key_table_new(p->blocks, rb->word_index_root);
p->word_hash = camel_partition_table_new(p->blocks, rb->word_hash_root);
CamelIndexCursor *idc;
printf("Word: '%s':\n", word);
-
+
idc = camel_index_find((CamelIndex *)idx, word);
while ( (name = camel_index_cursor_next(idc)) ) {
printf(" %s", name);
text_index_name_add_word(idn, p->buffer->str);
/*camel_index_name_add_word(idn, p->buffer->str);*/
}
-
+
g_string_truncate (p->buffer, 0);
}
}
camel_text_index_name_finalise(CamelTextIndexName *idn)
{
CamelTextIndexNamePrivate *p = CIN_PRIVATE(idn);
-
+
g_hash_table_destroy(idn->parent.words);
g_string_free(p->buffer, TRUE);
camel_text_index_name_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_index_name_get_type(), "CamelTextIndexName",
sizeof (CamelTextIndexName),
(CamelObjectInitFunc) camel_text_index_name_init,
(CamelObjectFinalizeFunc) camel_text_index_name_finalise);
}
-
+
return type;
}
if (flags & 1) {
g_free(p->current);
p->current = NULL;
- }
+ }
p->record_index++;
} while (p->current == NULL);
camel_text_index_cursor_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_index_cursor_get_type(), "CamelTextIndexCursor",
sizeof (CamelTextIndexCursor),
(CamelObjectInitFunc) camel_text_index_cursor_init,
(CamelObjectFinalizeFunc) camel_text_index_cursor_finalise);
}
-
+
return type;
}
camel_text_index_key_cursor_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_index_cursor_get_type(), "CamelTextIndexKeyCursor",
sizeof (CamelTextIndexKeyCursor),
(CamelObjectInitFunc) camel_text_index_key_cursor_init,
(CamelObjectFinalizeFunc) camel_text_index_key_cursor_finalise);
}
-
+
return type;
}
line[strlen(line)-1] = 0;
/* see if its already there */
- keyid = camel_partition_table_lookup(cpi, line);
+ keyid = camel_partition_table_lookup(cpi, line);
if (keyid == 0) {
m(printf("Adding word '%s' %d\n", line, index));
camel_partition_table_add(cpi, line, keyid);
m(printf("Lookup word '%s'\n", line));
- keyid = camel_partition_table_lookup(cpi, line);
+ keyid = camel_partition_table_lookup(cpi, line);
m(printf(" key = %08x\n", keyid));
}
while (fgets(line, sizeof(line), fp) != NULL) {
line[strlen(line)-1] = 0;
m(printf("Lookup word '%s' %d\n", line, index));
- keyid = camel_partition_table_lookup(cpi, line);
+ keyid = camel_partition_table_lookup(cpi, line);
m(printf(" key = %08d\n", keyid));
m(printf("Lookup key %08x\n", keyid));
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-transport.c : Abstract class for an email transport */
-/*
+/*
*
- * Author :
+ * Author :
* Dan Winship <danw@ximian.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_transport_class_init (CamelTransportClass *camel_transport_class)
{
CamelObjectClass *camel_object_class = CAMEL_OBJECT_CLASS (camel_transport_class);
-
+
parent_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ()));
-
+
/* virtual method overload */
camel_object_class->setv = transport_setv;
camel_object_class->getv = transport_getv;
camel_transport_init (gpointer object, gpointer klass)
{
CamelTransport *xport = object;
-
+
xport->priv = g_malloc0 (sizeof (struct _CamelTransportPrivate));
xport->priv->send_lock = g_mutex_new ();
}
camel_transport_finalize (CamelObject *object)
{
CamelTransport *xport = CAMEL_TRANSPORT (object);
-
+
g_mutex_free (xport->priv->send_lock);
g_free (xport->priv);
}
camel_transport_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_SERVICE_TYPE,
"CamelTransport",
(CamelObjectInitFunc) camel_transport_init,
(CamelObjectFinalizeFunc) camel_transport_finalize);
}
-
+
return type;
}
CamelException *ex)
{
gboolean sent;
-
+
g_return_val_if_fail (CAMEL_IS_TRANSPORT (transport), FALSE);
g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
g_return_val_if_fail (CAMEL_IS_ADDRESS (from), FALSE);
g_return_val_if_fail (CAMEL_IS_ADDRESS (recipients), FALSE);
-
+
CAMEL_TRANSPORT_LOCK (transport, send_lock);
sent = CT_CLASS (transport)->send_to (transport, message,
from, recipients, ex);
CAMEL_TRANSPORT_UNLOCK (transport, send_lock);
-
+
return sent;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-transport.h : Abstract class for an email transport */
-/*
+/*
*
- * Author :
+ * Author :
* Dan Winship <danw@ximian.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
struct _CamelTransport
{
CamelService parent_object;
-
+
struct _CamelTransportPrivate *priv;
};
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
+/*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-uid-cache.c: UID caching code. */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
struct stat st;
char *dirname, *buf, **uids;
int fd, i;
-
+
dirname = g_path_get_dirname (filename);
if (g_mkdir_with_parents (dirname, 0777) == -1) {
g_free (dirname);
return NULL;
}
-
+
g_free (dirname);
-
+
if ((fd = g_open (filename, O_RDONLY | O_CREAT | O_BINARY, 0666)) == -1)
return NULL;
-
+
if (fstat (fd, &st) == -1) {
close (fd);
return NULL;
}
-
+
buf = g_malloc (st.st_size + 1);
-
+
if (st.st_size > 0 && camel_read (fd, buf, st.st_size) == -1) {
close (fd);
g_free (buf);
return NULL;
}
-
+
buf[st.st_size] = '\0';
-
+
close (fd);
-
+
cache = g_new (CamelUIDCache, 1);
cache->uids = g_hash_table_new (g_str_hash, g_str_equal);
cache->filename = g_strdup (filename);
cache->expired = 0;
cache->size = 0;
cache->fd = -1;
-
+
uids = g_strsplit (buf, "\n", 0);
g_free (buf);
for (i = 0; uids[i]; i++) {
struct _uid_state *state;
-
+
state = g_new (struct _uid_state, 1);
state->level = cache->level;
state->save = TRUE;
-
+
g_hash_table_insert (cache->uids, uids[i], state);
}
-
+
g_free (uids);
-
+
return cache;
}
{
CamelUIDCache *cache = data;
struct _uid_state *state = value;
-
+
if (cache->fd == -1)
return;
-
+
if (state && state->level == cache->level && state->save) {
- if (camel_write (cache->fd, key, strlen (key)) == -1 ||
+ if (camel_write (cache->fd, key, strlen (key)) == -1 ||
camel_write (cache->fd, "\n", 1) == -1) {
cache->fd = -1;
} else {
char *filename;
int errnosav;
int fd;
-
+
filename = g_strdup_printf ("%s~", cache->filename);
if ((fd = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) {
g_free (filename);
return FALSE;
}
-
+
cache->fd = fd;
cache->size = 0;
cache->expired = 0;
g_hash_table_foreach (cache->uids, maybe_write_uid, cache);
-
+
if (fsync (fd) == -1)
goto exception;
-
+
close (fd);
fd = -1;
cache->fd = -1;
if (g_rename (filename, cache->filename) == -1)
goto exception;
-
+
g_free (filename);
-
+
return TRUE;
-
+
exception:
-
+
errnosav = errno;
-
+
#ifdef ENABLE_SPASMOLYTIC
if (fd != -1) {
/*
* more), then we should replace the old cache with
* the new cache as well.
*/
-
+
if (g_stat (cache->filename, &st) == 0 &&
(cache->size > st.st_size || cache->size + cache->expired > st.st_size)) {
if (ftruncate (fd, (off_t) cache->size) != -1) {
cache->expired = 0;
goto overwrite; /* FIXME: no such label */
}
- }
+ }
}
#endif
if (fd != -1) {
g_unlink (filename);
g_free (filename);
-
+
errno = errnosav;
-
+
return FALSE;
}
gpointer old_uid;
char *uid;
int i;
-
+
new_uids = g_ptr_array_new ();
cache->level++;
for (i = 0; i < uids->len; i++) {
struct _uid_state *state;
-
+
uid = uids->pdata[i];
if (g_hash_table_lookup_extended (cache->uids, uid, (void **)&old_uid, (void **)&state)) {
g_hash_table_remove (cache->uids, uid);
state = g_new (struct _uid_state, 1);
state->save = FALSE;
}
-
+
state->level = cache->level;
g_hash_table_insert (cache->uids, g_strdup (uid), state);
}
-
+
return new_uids;
}
{
struct _uid_state *state;
gpointer old_uid;
-
+
g_return_if_fail (uid != NULL);
if (g_hash_table_lookup_extended (cache->uids, uid, (void **)&old_uid, (void **)&state)) {
camel_uid_cache_free_uids (GPtrArray *uids)
{
int i;
-
+
for (i = 0; i < uids->len; i++)
g_free (uids->pdata[i]);
g_ptr_array_free (uids, TRUE);
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-uid-cache.h: UID caching code. */
-/*
+/*
* Authors:
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_url_scanner_new (void)
{
CamelUrlScanner *scanner;
-
+
scanner = g_new (CamelUrlScanner, 1);
scanner->patterns = g_ptr_array_new ();
scanner->trie = e_trie_new (TRUE);
-
+
return scanner;
}
camel_url_scanner_free (CamelUrlScanner *scanner)
{
g_return_if_fail (scanner != NULL);
-
+
g_ptr_array_free (scanner->patterns, TRUE);
e_trie_free (scanner->trie);
g_free (scanner);
camel_url_scanner_add (CamelUrlScanner *scanner, urlpattern_t *pattern)
{
g_return_if_fail (scanner != NULL);
-
+
e_trie_add (scanner->trie, pattern->pattern, scanner->patterns->len);
g_ptr_array_add (scanner->patterns, pattern);
}
const unsigned char *inptr, *inend;
urlpattern_t *pat;
int pattern;
-
+
g_return_val_if_fail (scanner != NULL, FALSE);
g_return_val_if_fail (in != NULL, FALSE);
-
+
inptr = (const unsigned char *) in;
inend = inptr + inlen;
-
+
do {
if (!(pos = e_trie_search (scanner->trie, (const char *)inptr, inlen, &pattern)))
return FALSE;
-
+
pat = g_ptr_array_index (scanner->patterns, pattern);
-
+
match->pattern = pat->pattern;
match->prefix = pat->prefix;
-
+
if (pat->start (in, pos, (const char *)inend, match) && pat->end (in, pos, (const char *)inend, match))
return TRUE;
-
+
inptr = (const unsigned char *) pos;
if (camel_utf8_getc_limit (&inptr, inend) == 0xffff)
break;
-
+
inlen = inend - inptr;
} while (inptr < inend);
-
+
return FALSE;
}
is_open_brace (char c)
{
int i;
-
+
for (i = 0; i < G_N_ELEMENTS (url_braces); i++) {
if (c == url_braces[i].open)
return TRUE;
}
-
+
return FALSE;
}
if (so > 0) {
for (i = 0; i < G_N_ELEMENTS (url_braces); i++) {
if (in[so - 1] == url_braces[i].open) {
- if (open_brace != NULL)
+ if (open_brace != NULL)
*open_brace = url_braces[i].open;
return url_braces[i].close;
}
}
}
-
+
return '\0';
}
camel_url_addrspec_start (const char *in, const char *pos, const char *inend, urlmatch_t *match)
{
register const char *inptr = pos;
-
+
g_assert (*inptr == '@');
-
+
if (inptr > in)
inptr--;
-
+
while (inptr > in) {
if (is_atom (*inptr))
inptr--;
else
break;
-
+
while (inptr > in && is_atom (*inptr))
inptr--;
-
+
if (inptr > in && *inptr == '.')
inptr--;
}
-
+
while (!is_atom (*inptr) || is_open_brace (*inptr))
inptr++;
-
+
if (inptr >= pos)
return FALSE;
-
+
match->um_so = (inptr - in);
-
+
return TRUE;
}
const char *inptr = pos;
int parts = 0, digits;
gboolean got_dot = FALSE;
-
+
g_assert (*inptr == '@');
-
+
inptr++;
-
+
if (*inptr == '[') {
/* domain literal */
do {
inptr++;
-
+
digits = 0;
while (inptr < inend && is_digit (*inptr) && digits < 3) {
inptr++;
digits++;
}
-
+
parts++;
-
+
if (*inptr != '.' && parts != 4)
return FALSE;
} while (parts < 4);
-
+
if (*inptr == ']')
inptr++;
else
return FALSE;
-
+
got_dot = TRUE;
} else {
while (inptr < inend) {
inptr++;
else
break;
-
+
while (inptr < inend && is_domain (*inptr))
inptr++;
-
+
if (inptr < inend && *inptr == '.' && is_domain (inptr[1])) {
if (*inptr == '.')
got_dot = TRUE;
}
}
}
-
+
/* don't allow toplevel domains */
if (inptr == pos + 1 || !got_dot)
return FALSE;
-
+
match->um_eo = (inptr - in);
-
+
return TRUE;
}
camel_url_file_start (const char *in, const char *pos, const char *inend, urlmatch_t *match)
{
match->um_so = (pos - in);
-
+
return TRUE;
}
{
register const char *inptr = pos;
char close_brace;
-
+
inptr += strlen (match->pattern);
-
+
if (*inptr == '/')
inptr++;
-
+
close_brace = url_stop_at_brace (in, match->um_so, NULL);
-
+
while (inptr < inend && is_urlsafe (*inptr) && *inptr != close_brace)
inptr++;
-
+
if (inptr == pos)
return FALSE;
-
+
match->um_eo = (inptr - in);
-
+
return TRUE;
}
if (!is_open_brace (pos[-1]) && !isspace (pos[-1]))
return FALSE;
}
-
+
match->um_so = (pos - in);
-
+
return TRUE;
}
int port;
inptr += strlen (match->pattern);
-
+
close_brace = url_stop_at_brace (in, match->um_so, &open_brace);
/* find the end of the domain */
while (inptr < inend) {
if (!is_atom (*inptr))
break;
-
+
inptr++;
-
+
while (inptr < inend && is_atom (*inptr))
inptr++;
-
- if ((inptr + 1) < inend && *inptr == '.' && (is_atom (inptr[1]) || inptr[1] == '/'))
+
+ if ((inptr + 1) < inend && *inptr == '.' && (is_atom (inptr[1]) || inptr[1] == '/'))
inptr++;
}
-
+
if (*inptr != '@')
inptr = save;
else
inptr++;
-
+
goto domain;
} else if (is_domain (*inptr)) {
domain:
while (inptr < inend) {
if (!is_domain (*inptr))
break;
-
+
inptr++;
-
+
while (inptr < inend && is_domain (*inptr))
inptr++;
-
- if ((inptr + 1) < inend && *inptr == '.' && (is_domain (inptr[1]) || inptr[1] == '/'))
+
+ if ((inptr + 1) < inend && *inptr == '.' && (is_domain (inptr[1]) || inptr[1] == '/'))
inptr++;
}
} else {
return FALSE;
}
-
+
if (inptr < inend) {
switch (*inptr) {
case ':': /* we either have a port or a password */
inptr++;
-
+
if (is_digit (*inptr) || passwd) {
port = (*inptr++ - '0');
-
+
while (inptr < inend && is_digit (*inptr) && port < 65536)
port = (port * 10) + (*inptr++ - '0');
-
+
if (!passwd && (port >= 65536 || *inptr == '@')) {
if (inptr < inend) {
/* this must be a password? */
goto passwd;
}
-
+
inptr--;
}
} else {
passwd:
passwd = TRUE;
save = inptr;
-
+
while (inptr < inend && is_atom (*inptr))
inptr++;
-
+
if ((inptr + 2) < inend) {
if (*inptr == '@') {
inptr++;
if (is_domain (*inptr))
goto domain;
}
-
+
return FALSE;
}
}
-
+
if (inptr >= inend || *inptr != '/')
break;
-
+
/* we have a '/' so there could be a path - fall through */
case '/': /* we've detected a path component to our url */
inptr++;
match->um_eo = (inptr - in);
-
+
return TRUE;
}
table_init_bits (unsigned int mask, const unsigned char *vals)
{
int i;
-
+
for (i = 0; vals[i] != '\0'; i++)
url_scanner_table[vals[i]] |= mask;
}
url_scanner_table_init (void)
{
int i;
-
+
for (i = 0; i < 256; i++) {
url_scanner_table[i] = 0;
if (i < 32)
if (i >= 127)
url_scanner_table[i] |= IS_CTRL;
}
-
+
url_scanner_table[' '] |= IS_SPACE;
url_scanner_table['-'] |= IS_DOMAIN;
-
+
/* not defined to be special in rfc0822, but when scanning
backwards to find the beginning of the email address we do
not want to include this char if we come accross it - so
this is kind of a hack */
url_scanner_table['/'] |= IS_SPECIAL;
-
+
table_init_bits (IS_LWSP, CHARS_LWSP);
table_init_bits (IS_SPECIAL, CHARS_SPECIAL);
table_init_bits (IS_URLSAFE, CHARS_URLSAFE);
int main (int argc, char **argv)
{
int i;
-
+
url_scanner_table_init ();
-
+
printf ("static unsigned char url_scanner_table[256] = {");
for (i = 0; i < 256; i++) {
printf ("%s%3d%s", (i % 16) ? "" : "\n\t",
url_scanner_table[i], i != 255 ? "," : "\n");
}
printf ("};\n\n");
-
+
return 0;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-url.c : utility functions to parse URLs */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright 1999-2001 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
if (!url->path && (url->params || url->query || url->fragment))
g_string_append_c (str, '/');
}
-
+
if (url->path)
append_url_encoded (str, url->path, ";?");
if (url->params && !(flags & CAMEL_URL_HIDE_PARAMS))
g_string_append_c (str, '#');
append_url_encoded (str, url->fragment, NULL);
}
-
+
return_result = str->str;
g_string_free (str, FALSE);
-
+
return return_result;
}
g_datalist_clear (&url->params);
g_free (url->query);
g_free (url->fragment);
-
+
g_free (url);
}
}
ADD_HASH (u->path);
ADD_HASH (u->query);
hash ^= u->port;
-
+
return hash;
}
else
return FALSE;
}
-
+
if (s2 == NULL)
return FALSE;
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-url.h : utility functions to parse URLs */
-/*
+/*
* Authors:
* Bertrand Guiheneuf <bertrand@helixcode.com>
* Dan Winship <danw@ximian.com>
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/**
* camel_utf8_putc:
- * @ptr:
- * @c:
- *
+ * @ptr:
+ * @c:
+ *
* Output a 32 bit unicode character as utf8 octets. At most 4 octets will
* be written to @ptr. @ptr will be advanced to the next character position.
**/
/**
* camel_utf8_getc:
- * @ptr:
- *
+ * @ptr:
+ *
* Get a Unicode character from a utf8 stream. @ptr will be advanced
* to the next character position. Invalid utf8 characters will be
* silently skipped. @ptr should point to a NUL terminated array.
- *
+ *
* Return value: The next Unicode character. @ptr will be advanced to
* the next character always.
**/
r<<=1;
m<<=5;
} while (r & 0x40);
-
+
*ptr = p;
v &= ~m;
/**
* camel_utf8_getc_limit:
- * @ptr:
+ * @ptr:
* @end: must not be NULL.
- *
+ *
* Get the next utf8 char at @ptr, and return it, advancing @ptr to
* the next character. If @end is reached before a full utf8
* character can be read, then the invalid Unicode char 0xffff is
* returned as a sentinel (Unicode 3.1, section 2.7), and @ptr is not
* advanced.
- *
+ *
* Return value: The next utf8 char, or 0xffff.
**/
guint32
do {
if (p >= end)
return 0xffff;
-
+
c = *p++;
if ((c & 0xc0) != 0x80) {
r = c;
r<<=1;
m<<=5;
} while (r & 0x40);
-
+
*ptr = p;
-
+
v &= ~m;
return v;
} else {
/**
* camel_utf7_utf8:
- * @ptr:
- *
+ * @ptr:
+ *
* Convert a modified utf7 string to utf8. If the utf7 string
* contains 8 bit characters, they are treated as iso-8859-1.
- *
+ *
* The IMAP rules [rfc2060] are used in the utf7 encoding.
*
* Return value: The converted string.
/**
* camel_utf8_utf7:
- * @ptr:
- *
+ * @ptr:
+ *
* Convert a utf8 string to a modified utf7 format.
*
* The IMAP rules [rfc2060] are used in the utf7 encoding.
- *
- * Return value:
+ *
+ * Return value:
**/
char *
camel_utf8_utf7(const char *ptr)
/**
* camel_utf8_ucs2:
- * @ptr:
- *
+ * @ptr:
+ *
* Convert a utf8 string into a ucs2 one. The ucs string will be in
* network byte order, and terminated with a 16 bit NULL.
- *
- * Return value:
+ *
+ * Return value:
**/
char *
camel_utf8_ucs2(const char *pptr)
/**
* camel_ucs2_utf8:
- * @ptr:
- *
+ * @ptr:
+ *
* Convert a ucs2 string into a utf8 one. The ucs2 string is treated
* as network byte ordered, and terminated with a 16 bit NUL.
- *
- * Return value:
+ *
+ * Return value:
**/
char *camel_ucs2_utf8(const char *ptr)
{
#include "camel-vee-store.h" /* for open flags */
#include "camel-vee-summary.h"
-#define d(x)
+#define d(x)
#define dd(x) (camel_debug("vfolder")?(x):0)
#define _PRIVATE(o) (((CamelVeeFolder *)(o))->priv)
camel_vee_folder_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_folder_get_type (), "CamelVeeFolder",
sizeof (CamelVeeFolder),
(CamelObjectInitFunc) camel_vee_folder_init,
(CamelObjectFinalizeFunc) camel_vee_folder_finalise);
}
-
+
return type;
}
{
CamelVeeFolder *vf;
char *tmp;
-
+
if (CAMEL_IS_VEE_STORE(parent_store) && strcmp(full, CAMEL_UNMATCHED_NAME) == 0) {
vf = ((CamelVeeStore *)parent_store)->folder_unmatched;
camel_object_ref(vf);
struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);
int i;
CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
-
+
if (vf == (CamelVeeFolder *)sub) {
g_warning("Adding a virtual folder to itself as source, ignored");
return;
if (g_list_find(p->folders, sub) == NULL) {
camel_object_ref((CamelObject *)sub);
p->folders = g_list_append(p->folders, sub);
-
+
CAMEL_FOLDER_LOCK(vf, change_lock);
/* update the freeze state of 'sub' to match our freeze state */
struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);
int i;
CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
-
+
CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);
CAMEL_VEE_FOLDER_LOCK(vf, changed_lock);
CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
return;
}
-
+
camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf);
camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf);
camel_object_unhook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc) folder_renamed, vf);
p->folders = g_list_remove(p->folders, sub);
-
+
/* undo the freeze state that we have imposed on this source folder */
CAMEL_FOLDER_LOCK(vf, change_lock);
for (i = 0; i < ((CamelFolder *)vf)->priv->frozen; i++)
camel_folder_thaw(sub);
CAMEL_FOLDER_UNLOCK(vf, change_lock);
-
+
CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
if (folder_unmatched != NULL) {
while (g_list_find(up->folders, sub)) {
up->folders = g_list_remove(up->folders, sub);
camel_object_unref((CamelObject *)sub);
-
+
/* undo the freeze state that Unmatched has imposed on this source folder */
CAMEL_FOLDER_LOCK(folder_unmatched, change_lock);
for (i = 0; i < ((CamelFolder *)folder_unmatched)->priv->frozen; i++)
if (g_list_find(up->folders, sub) != NULL) {
up->folders = g_list_remove(up->folders, sub);
camel_object_unref((CamelObject *)sub);
-
+
/* undo the freeze state that Unmatched has imposed on this source folder */
CAMEL_FOLDER_LOCK(folder_unmatched, change_lock);
for (i = 0; i < ((CamelFolder *)folder_unmatched)->priv->frozen; i++)
if (CAMEL_IS_VEE_FOLDER(sub))
return;
-
+
camel_object_unref((CamelObject *)sub);
}
/**
* camel_vee_folder_set_folders:
- * @vf:
- * @folders:
- *
+ * @vf:
+ * @folders:
+ *
* Set the whole list of folder sources on a vee folder.
**/
void
/**
* camel_vee_folder_hash_folder:
- * @folder:
- * @:
- *
+ * @folder:
+ * @:
+ *
* Create a hash string representing the folder name, which should be
* unique, and remain static for a given folder.
**/
/**
* camel_vee_folder_get_location:
- * @vf:
- * @vinfo:
+ * @vf:
+ * @vinfo:
* @realuid: if not NULL, set to the uid of the real message, must be
* g_free'd by caller.
- *
+ *
* Find the real folder (and uid)
- *
- * Return value:
+ *
+ * Return value:
**/
CamelFolder *
camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vinfo, char **realuid)
struct _CamelVeeFolderPrivate *p = _PRIVATE(vf);
GHashTable *searched = g_hash_table_new(NULL, NULL);
CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL;
-
+
CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);
-
+
if (vf != folder_unmatched)
expr = g_strdup_printf ("(and %s %s)", vf->expression ? vf->expression : "", expression);
else
expr = g_strdup (expression);
-
+
node = p->folders;
while (node) {
CamelFolder *f = node->data;
int i;
char hash[8];
-
+
/* make sure we only search each folder once - for unmatched folder to work right */
if (g_hash_table_lookup(searched, f) == NULL) {
camel_vee_folder_hash_folder(f, hash);
CamelFolder *f = node->data;
int i;
char hash[8];
-
+
/* make sure we only search each folder once - for unmatched folder to work right */
if (g_hash_table_lookup(searched, f) == NULL) {
camel_vee_folder_hash_folder(f, hash);
if (matches) {
for (i = 0; i < matches->len; i++) {
char *uid = matches->pdata[i], *vuid;
-
+
vuid = g_malloc(strlen(uid)+9);
memcpy(vuid, hash, 8);
strcpy(vuid+8, uid);
count = camel_folder_summary_count(((CamelFolder *)folder_unmatched)->summary);
for (i=0;i<count;i++) {
CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i);
-
+
if (mi) {
if (mi->real->summary == ssummary) {
camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi));
if (mi->real->summary == ssummary) {
char *uid = (char *)camel_message_info_uid(mi), *oldkey;
void *oldval;
-
+
if (g_hash_table_lookup(matchhash, uid+8) == NULL) {
if (last == -1) {
last = start = i;
vinfo = vee_folder_add_uid(vf, sub, uid, hash);
if (vinfo == NULL)
return;
-
+
vuid = camel_message_info_uid(vinfo);
camel_folder_change_info_add_uid(vf->changes, vuid);
}
memcpy(vuid, hash, 8);
strcpy(vuid+8, uid);
-
+
if (!CAMEL_IS_VEE_FOLDER(sub) && folder_unmatched != NULL && g_hash_table_lookup(unmatched_uids, vuid) == NULL) {
dd(printf(" adding uid '%s' to Unmatched [newly unmatched]\n", (char *)uid));
vinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info((CamelFolder *)folder_unmatched, vuid);
unmatched_changes = folder_unmatched->changes;
folder_unmatched->changes = camel_folder_change_info_new();
}
-
+
CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, summary_lock);
}
g_ptr_array_free(newchanged, TRUE);
g_free(vuid);
-
+
if (unmatched_changes) {
camel_object_trigger_event((CamelObject *)folder_unmatched, "folder_changed", unmatched_changes);
camel_folder_change_info_free(unmatched_changes);
}
-
+
if (vf_changes) {
/* If not auto-updating, keep track of changed folders for later re-sync */
if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0) {
CamelVeeFolder *vfolder = (CamelVeeFolder *)folder;
struct _CamelVeeFolderPrivate *p = _PRIVATE(vfolder);
GList *node;
-
+
CAMEL_VEE_FOLDER_LOCK(vfolder, subfolder_lock);
-
+
node = p->folders;
while (node) {
CamelFolder *f = node->data;
-
+
camel_folder_freeze(f);
node = node->next;
}
-
+
CAMEL_VEE_FOLDER_UNLOCK(vfolder, subfolder_lock);
-
+
/* call parent implementation */
CAMEL_FOLDER_CLASS (camel_vee_folder_parent)->freeze(folder);
}
CamelVeeFolder *vfolder = (CamelVeeFolder *)folder;
struct _CamelVeeFolderPrivate *p = _PRIVATE(vfolder);
GList *node;
-
+
CAMEL_VEE_FOLDER_LOCK(vfolder, subfolder_lock);
-
+
node = p->folders;
while (node) {
CamelFolder *f = node->data;
-
+
camel_folder_thaw(f);
node = node->next;
}
-
+
CAMEL_VEE_FOLDER_UNLOCK(vfolder, subfolder_lock);
-
+
/* call parent implementation */
CAMEL_FOLDER_CLASS (camel_vee_folder_parent)->thaw(folder);
}
obj->changes = camel_folder_change_info_new();
obj->search = camel_folder_search_new();
-
+
p->summary_lock = g_mutex_new();
p->subfolder_lock = g_mutex_new();
p->changed_lock = g_mutex_new();
}
g_free(vf->expression);
-
+
g_list_free(p->folders);
g_list_free(p->folders_changed);
camel_folder_change_info_free(vf->changes);
camel_object_unref((CamelObject *)vf->search);
-
+
g_mutex_free(p->summary_lock);
g_mutex_free(p->subfolder_lock);
g_mutex_free(p->changed_lock);
-
+
g_free(p);
}
camel_vee_store_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_store_get_type (), "CamelVeeStore",
sizeof (CamelVeeStore),
(CamelObjectInitFunc) camel_vee_store_init,
(CamelObjectFinalizeFunc) camel_vee_store_finalise);
}
-
+
return type;
}
camel_vee_store_class_init (CamelVeeStoreClass *klass)
{
CamelStoreClass *store_class = (CamelStoreClass *) klass;
-
+
camel_vee_store_parent = (CamelStoreClass *)camel_store_get_type();
/* virtual method overload */
CamelStore *store = (CamelStore *)obj;
/* we dont want a vtrash/vjunk on this one */
- store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK);
+ store->flags &= ~(CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK);
/* Set up unmatched folder */
obj->unmatched_uids = g_hash_table_new (g_str_hash, g_str_equal);
* camel_vee_store_new:
*
* Create a new #CamelVeeStore object.
- *
+ *
* Returns new #CamelVeeStore object
**/
CamelVeeStore *
camel_vtrash_folder_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (camel_vee_folder_get_type (),
"CamelVTrashFolder",
(CamelObjectInitFunc) camel_vtrash_folder_init,
NULL);
}
-
+
return type;
}
camel_vtrash_folder_new (CamelStore *parent_store, camel_vtrash_folder_t type)
{
CamelVTrashFolder *vtrash;
-
+
g_assert(type < CAMEL_VTRASH_FOLDER_LAST);
vtrash = (CamelVTrashFolder *)camel_object_new(camel_vtrash_folder_get_type());
const CamelMessageInfo *info, char **appended_uid,
CamelException *ex)
{
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_(vdata[((CamelVTrashFolder *)folder)->type].error_copy));
}
if (CAMEL_IS_VTRASH_FOLDER (dest)) {
/* Copy to trash is meaningless. */
if (!delete_originals) {
- camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_(vdata[((CamelVTrashFolder *)dest)->type].error_copy));
return;
}
g_warning ("Cannot find uid %s in source folder during transfer", (char *) uids->pdata[i]);
continue;
}
-
+
if (dest == mi->real->summary->folder) {
/* Just unset the flag on the original message */
camel_folder_set_message_flags (source, uids->pdata[i], sbit, 0);
GList *node;
GPtrArray *matches, *result = g_ptr_array_new(), *folder_uids = g_ptr_array_new();
struct _CamelVeeFolderPrivate *p = ((CamelVeeFolder *)folder)->priv;
-
+
CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock);
node = p->folders;
CamelFolder *f = node->data;
int i;
char hash[8];
-
+
camel_vee_folder_hash_folder(f, hash);
/* map the vfolder uid's to the source folder uid's first */
g_ptr_array_set_size(uids, 0);
for (i=0;i<uids->len;i++) {
char *uid = uids->pdata[i];
-
+
if (strlen(uid) >= 8 && strncmp(uid, hash, 8) == 0) {
CamelMessageInfo *mi;
&& (matches = camel_folder_search_by_uids(f, expression, folder_uids, ex))) {
for (i = 0; i < matches->len; i++) {
char *uid = matches->pdata[i], *vuid;
-
+
vuid = g_malloc(strlen(uid)+9);
memcpy(vuid, hash, 8);
strcpy(vuid+8, uid);
}
CAMEL_VEE_FOLDER_UNLOCK(vf, summary_lock);
-
+
if (vf_changes) {
camel_object_trigger_event(vf, "folder_changed", vf_changes);
camel_folder_change_info_free(vf_changes);
camel_vtrash_folder_class_init (CamelVTrashFolderClass *klass)
{
CamelFolderClass *folder_class = (CamelFolderClass *) klass;
-
+
camel_vtrash_folder_parent = CAMEL_VEE_FOLDER_CLASS(camel_vee_folder_get_type());
((CamelObjectClass *)klass)->getv = vtrash_getv;
-
+
folder_class->append_message = vtrash_append_message;
folder_class->transfer_messages_to = vtrash_transfer_messages_to;
folder_class->search_by_expression = vtrash_search_by_expression;
struct _CamelVTrashFolderClass {
CamelVeeFolderClass parent_class;
-
+
};
CamelType camel_vtrash_folder_get_type (void);
{
CamelCertDB *certdb;
char *path;
-
+
if (initialised)
return 0;
PRUint16 indx;
PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 10);
-
+
#ifndef G_OS_WIN32
nss_configdir = g_strdup (configdir);
#else
for (indx = 0; indx < SSL_NumImplementedCiphers; indx++) {
if (!SSL_IS_SSL2_CIPHER(SSL_ImplementedCiphers[indx]))
SSL_CipherPrefSetDefault (SSL_ImplementedCiphers[indx], PR_TRUE);
- }
-
+ }
+
SSL_OptionSetDefault (SSL_ENABLE_SSL2, PR_TRUE);
SSL_OptionSetDefault (SSL_ENABLE_SSL3, PR_TRUE);
SSL_OptionSetDefault (SSL_ENABLE_TLS, PR_TRUE);
SSL_OptionSetDefault (SSL_V2_COMPATIBLE_HELLO, PR_TRUE /* maybe? */);
}
#endif /* HAVE_NSS */
-
+
path = g_strdup_printf ("%s/camel-cert.db", configdir);
certdb = camel_certdb_new ();
camel_certdb_set_filename (certdb, path);
g_free (path);
-
+
/* if we fail to load, who cares? it'll just be a volatile certdb */
camel_certdb_load (certdb);
-
+
/* set this certdb as the default db */
camel_certdb_set_default (certdb);
-
+
camel_object_unref (certdb);
-
+
g_atexit (camel_shutdown);
-
+
initialised = TRUE;
-
+
return 0;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
+/*
*
- * Author :
+ * Author :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-groupwise-folder.c: class for an groupwise folder */
-/*
+/*
* Authors:
* Sivaiah Nallagatla <snallagatla@novell.com>
* parthasarathi susarla <sparthasarathi@novell.com>
* Sankar P <psankar@novell.com>
- *
+ *
*
* Copyright (C) 2004, Novell Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include <config.h>
#endif
#include <errno.h>
static CamelMimeMessage *groupwise_folder_item_to_msg ( CamelFolder *folder, EGwItem *item, CamelException *ex );
-#define d(x)
+#define d(x)
static CamelMimeMessage *
groupwise_folder_get_message( CamelFolder *folder, const char *uid, CamelException *ex )
if(!temp_body){
int len = 0;
EGwConnectionStatus status;
- status = e_gw_connection_get_attachment (cnc,
- e_gw_item_get_msg_body_id (item), 0, -1,
+ status = e_gw_connection_get_attachment (cnc,
+ e_gw_item_get_msg_body_id (item), 0, -1,
(const char **)&temp_body, &len);
if (status != E_GW_CONNECTION_STATUS_OK) {
g_warning ("Could not get Messagebody\n");
convert_to_calendar (item, &cal_buffer, &len);
else if (type == E_GW_ITEM_TYPE_TASK)
convert_to_task (item, &cal_buffer, &len);
- else
+ else
convert_to_note (item, &cal_buffer, &len);
camel_mime_part_set_content(part, cal_buffer, len, "text/calendar");
}
case E_GW_ITEM_TYPE_NOTIFICATION:
case E_GW_ITEM_TYPE_MAIL:
- if (body)
+ if (body)
camel_mime_part_set_content(part, body, strlen(body), "text/html");
else if (temp_body)
camel_mime_part_set_content(part, temp_body, strlen(temp_body), e_gw_item_get_msg_content_type (item));
}
if (recp->type == E_GW_ITEM_RECIPIENT_TO) {
- if (recp->status_enabled)
+ if (recp->status_enabled)
status_opt = g_strconcat (status_opt ? status_opt : "" , "TO", ";",NULL);
camel_header_address_list_append(&to_list, ha);
} else if (recp->type == E_GW_ITEM_RECIPIENT_CC) {
- if (recp->status_enabled)
+ if (recp->status_enabled)
status_opt = g_strconcat (status_opt ? status_opt : "", "CC", ";",NULL);
camel_header_address_list_append(&cc_list,ha);
} else if (recp->type == E_GW_ITEM_RECIPIENT_BC) {
- if (recp->status_enabled)
+ if (recp->status_enabled)
status_opt = g_strconcat (status_opt ? status_opt : "", "BCC", ";",NULL);
camel_header_address_list_append(&bcc_list,ha);
} else {
camel_header_address_unref(ha);
}
if (recp->status_enabled) {
- status_opt = g_strconcat (status_opt,
+ status_opt = g_strconcat (status_opt,
recp->display_name,";",
recp->email,";",
recp->delivered_date ? recp->delivered_date : "", ";",
- recp->opened_date ? recp->opened_date : "", ";",
+ recp->opened_date ? recp->opened_date : "", ";",
recp->accepted_date ? recp->accepted_date : "", ";",
- recp->deleted_date ? recp->deleted_date : "", ";",
+ recp->deleted_date ? recp->deleted_date : "", ";",
recp->declined_date ? recp->declined_date : "", ";",
recp->completed_date ? recp->completed_date : "", ";",
- recp->undelivered_date ? recp->undelivered_date : "", ";",
+ recp->undelivered_date ? recp->undelivered_date : "", ";",
"::", NULL);
}
}
}
- if(to_list) {
+ if(to_list) {
subs_email=camel_header_address_list_encode(to_list);
camel_medium_set_header( CAMEL_MEDIUM(msg), "To", subs_email);
g_free(subs_email);
camel_header_address_list_clear(&to_list);
}
- if(cc_list) {
+ if(cc_list) {
subs_email=camel_header_address_list_encode(cc_list);
camel_medium_set_header( CAMEL_MEDIUM(msg), "Cc", subs_email);
g_free(subs_email);
camel_header_address_list_clear(&cc_list);
}
- if(bcc_list) {
+ if(bcc_list) {
subs_email=camel_header_address_list_encode(bcc_list);
camel_medium_set_header( CAMEL_MEDIUM(msg), "Bcc", subs_email);
g_free(subs_email);
if (org) {
if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
int i;
- for (i = 0; org->display_name[i] != '<' &&
+ for (i = 0; org->display_name[i] != '<' &&
org->display_name[i] != '\0';
i++);
org->display_name[i] = '\0';
}
- if (org->display_name && org->email)
+ if (org->display_name && org->email)
ha=camel_header_address_new_name(org->display_name, org->email);
else if (org->display_name)
ha=camel_header_address_new_group(org->display_name);
ha = NULL;
if (ha) {
- subs_email = camel_header_address_list_encode (ha);
+ subs_email = camel_header_address_list_encode (ha);
camel_medium_set_header (CAMEL_MEDIUM (msg), "From", subs_email);
camel_header_address_unref (ha);
g_free (subs_email);
}
/******************* functions specific to Junk Mail Handling**************/
-static void
+static void
free_node (EGwJunkEntry *entry)
{
if (entry) {
static void
update_junk_list (CamelStore *store, CamelMessageInfo *info, int flag)
{
- gchar **email = NULL, *from = NULL;
+ gchar **email = NULL, *from = NULL;
CamelGroupwiseStore *gw_store= CAMEL_GROUPWISE_STORE(store);
CamelGroupwiseStorePrivate *priv = gw_store->priv;
EGwConnection *cnc = cnc_lookup (priv);
if (e_gw_connection_get_junk_entries (cnc, &list)== E_GW_CONNECTION_STATUS_OK){
while (list) {
entry = list->data;
- if (!g_ascii_strcasecmp (entry->match, email[1])) {
+ if (!g_ascii_strcasecmp (entry->match, email[1])) {
e_gw_connection_remove_junk_entry (cnc, entry->id);
}
list = list->next;
g_strfreev (email);
}
-static void
+static void
move_to_mailbox (CamelFolder *folder, CamelMessageInfo *info, CamelException *ex)
{
CamelFolder *dest;
update_junk_list (folder->parent_store, info, REMOVE_JUNK_ENTRY);
}
-static void
+static void
move_to_junk (CamelFolder *folder, CamelMessageInfo *info, CamelException *ex)
{
CamelFolder *dest;
g_ptr_array_add (uids, (gpointer) uid);
dest = camel_store_get_folder (folder->parent_store, JUNK_FOLDER, 0, ex);
-
+
if (dest)
groupwise_transfer_messages_to (folder, uids, dest, NULL, TRUE, ex);
else {
/********************* back to folder functions*************************/
-static void
+static void
groupwise_sync_summary (CamelFolder *folder, CamelException *ex)
{
camel_folder_summary_save (folder->summary);
deleted_items = deleted_head = NULL;
- if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL ||
+ if (((CamelOfflineStore *) gw_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL ||
((CamelService *)gw_store)->status == CAMEL_SERVICE_DISCONNECTED) {
groupwise_sync_summary (folder, ex);
return;
/**Junk Mail handling**/
if(!info)
continue;
- flags = camel_message_info_flags (info);
+ flags = camel_message_info_flags (info);
- if ((flags & CAMEL_MESSAGE_JUNK) && strcmp(camel_folder_get_name(folder), JUNK_FOLDER)) {
+ if ((flags & CAMEL_MESSAGE_JUNK) && strcmp(camel_folder_get_name(folder), JUNK_FOLDER)) {
/*marked a message junk*/
move_to_junk (folder, info, ex);
camel_folder_summary_remove_uid (folder->summary, camel_message_info_uid(info));
}
if ((flags & CAMEL_GW_MESSAGE_NOJUNK) && !strcmp(camel_folder_get_name(folder), JUNK_FOLDER)) {
- /*message was marked as junk, now unjunk*/
+ /*message was marked as junk, now unjunk*/
move_to_mailbox (folder, info, ex);
camel_folder_summary_remove_uid (folder->summary, camel_message_info_uid(info));
camel_data_cache_remove (gw_folder->cache, "cache", camel_message_info_uid(info), NULL);
if (gw_info && (gw_info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
do_flags_diff (&diff, gw_info->server_flags, gw_info->info.flags);
do_flags_diff (&unset_flags, flags, gw_info->server_flags);
-
+
diff.changed &= folder->permanent_flags;
/* weed out flag changes that we can't sync to the server */
if (g_list_length (deleted_items) == GROUPWISE_BULK_DELETE_LIMIT ) {
CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
- /*
- Sync up the READ changes before deleting the message.
+ /*
+ Sync up the READ changes before deleting the message.
Note that if a message is marked as unread and then deleted,
Evo doesnt not take care of it, as I find that scenario to be impractical.
*/
if (deleted_read_items) {
-
+
/* FIXME: As in many places, we need to handle the return value
and do some error handling. But, we do not have all error codes also
and errors are not returned always either */
}
camel_message_info_free (info);
}
-
+
CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
if (deleted_items) {
}
CamelFolder *
-camel_gw_folder_new(CamelStore *store, const char *folder_name, const char *folder_dir, CamelException *ex)
+camel_gw_folder_new(CamelStore *store, const char *folder_name, const char *folder_dir, CamelException *ex)
{
CamelFolder *folder;
CamelGroupwiseFolder *gw_folder;
else {
/* item_list is prepended to items_full_list and not the other way
- because when we have a large number of items say 50000,
- for each iteration there will be more elements in items_full_list
+ because when we have a large number of items say 50000,
+ for each iteration there will be more elements in items_full_list
and less elements in item_list */
last_element = g_list_last (item_list);
item_list = item_list->next;
}
- i = 0;
+ i = 0;
while (((const char *)item_list->data)[i++]!='@');
((char *)item_list->data)[i-1] = '\0';
}*/
return;
}
- if (!cnc)
+ if (!cnc)
return;
if (camel_folder_is_frozen (folder) ) {
CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
- if (!camel_groupwise_store_connected (gw_store, ex))
+ if (!camel_groupwise_store_connected (gw_store, ex))
goto end1;
if (!strcmp (folder->full_name, "Trash")) {
}
time_string = g_strdup (((CamelGroupwiseSummary *) folder->summary)->time_string);
- t_str = g_strdup (time_string);
+ t_str = g_strdup (time_string);
/*Get the New Items*/
if (!is_proxy) {
}
/*
- * The value in t_str is the one that has to be used for the next set of calls.
+ * The value in t_str is the one that has to be used for the next set of calls.
* so store this value in the summary.
*/
if (summary->time_string)
((CamelGroupwiseSummary *) folder->summary)->time_string = g_strdup (t_str);
camel_folder_summary_touch (folder->summary);
groupwise_sync_summary (folder, ex);
- g_free (t_str);
+ g_free (t_str);
t_str = NULL;
/*
- for ( sl = slist ; sl != NULL; sl = sl->next)
+ for ( sl = slist ; sl != NULL; sl = sl->next)
list = g_list_append (list, sl->data);*/
if (slist && g_slist_length(slist) != 0)
goto end3;
}
- /* The storing of time-stamp to summary code below should be commented if the
+ /* The storing of time-stamp to summary code below should be commented if the
above commented code is uncommented */
/* if (summary->time_string)
g_free (t_str), t_str = NULL;*/
- for ( sl = slist ; sl != NULL; sl = sl->next)
+ for ( sl = slist ; sl != NULL; sl = sl->next)
list = g_list_prepend (list, sl->data);
if (!check_all && slist && g_slist_length(slist) != 0)
is_locked = FALSE;
/*
- * The New and Modified items in the server have been updated in the summary.
+ * The New and Modified items in the server have been updated in the summary.
* Now we have to make sure that all the delted items in the server are deleted
- * from Evolution as well. So we get the id's of all the items on the sever in
+ * from Evolution as well. So we get the id's of all the items on the sever in
* this folder, and update the summary.
*/
/*create a new session thread for the update all operation*/
/*thread creation and queueing done*/
}
-end3:
+end3:
g_list_foreach (list, (GFunc) g_object_unref, NULL);
g_list_free (list);
list = NULL;
}
static void
-gw_update_cache (CamelFolder *folder, GList *list, CamelException *ex, gboolean uid_flag)
+gw_update_cache (CamelFolder *folder, GList *list, CamelException *ex, gboolean uid_flag)
{
CamelGroupwiseMessageInfo *mi = NULL;
CamelMessageInfo *pmi = NULL;
if (uid_flag == FALSE) {
temp_item = (EGwItem *)item_list->data;
id = e_gw_item_get_id (temp_item);
- } else
+ } else
id = (char *) item_list->data;
camel_operation_progress (NULL, (100*i)/total_items);
continue;
}
- mi = (CamelGroupwiseMessageInfo *)camel_message_info_new (folder->summary);
+ mi = (CamelGroupwiseMessageInfo *)camel_message_info_new (folder->summary);
if (mi->info.content == NULL) {
mi->info.content = camel_folder_summary_content_info_new (folder->summary);
- mi->info.content->type = camel_content_type_new ("multipart", "mixed");
+ mi->info.content->type = camel_content_type_new ("multipart", "mixed");
}
}
-
+
rk = e_gw_item_get_recurrence_key (item);
if (rk > 0) {
- recurrence_key = g_strdup_printf("%d", rk);
+ recurrence_key = g_strdup_printf("%d", rk);
camel_message_info_set_user_tag ((CamelMessageInfo*)mi, "recurrence-key", recurrence_key);
- }
+ }
/*all items in the Junk Mail folder should have this flag set*/
if (is_junk)
item_status = e_gw_item_get_item_status (item);
if (item_status & E_GW_ITEM_STAT_READ)
status_flags |= CAMEL_MESSAGE_SEEN;
- else
+ else
mi->info.flags &= ~CAMEL_MESSAGE_SEEN;
if (item_status & E_GW_ITEM_STAT_REPLIED)
status_flags |= CAMEL_MESSAGE_ANSWERED;
- if (exists)
+ if (exists)
mi->info.flags |= status_flags;
- else
+ else
mi->info.flags = status_flags;
priority = e_gw_item_get_priority (item);
mi->info.flags |= CAMEL_MESSAGE_ATTACHMENTS;
if (is_proxy)
mi->info.flags |= CAMEL_MESSAGE_USER_NOT_DELETABLE;
-
+
mi->server_flags = mi->info.flags;
- org = e_gw_item_get_organizer (item);
+ org = e_gw_item_get_organizer (item);
if (org) {
GString *str;
int i;
str = g_string_new ("");
if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
- for (i = 0; org->display_name[i] != '<' &&
+ for (i = 0; org->display_name[i] != '<' &&
org->display_name[i] != '\0';
i++);
str = g_string_append (str, " ");
}
- if (org->display_name[0] == '\0') {
+ if (org->display_name[0] == '\0') {
str = g_string_append (str, org->email);
str = g_string_append (str, " ");
}
- if (org->email && org->email[0]) {
+ if (org->email && org->email[0]) {
g_string_append (str, "<");
str = g_string_append (str, org->email);
g_string_append (str, ">");
}
if (type == E_GW_ITEM_TYPE_APPOINTMENT
- || type == E_GW_ITEM_TYPE_NOTE
+ || type == E_GW_ITEM_TYPE_NOTE
|| type == E_GW_ITEM_TYPE_TASK ) {
temp_date = e_gw_item_get_start_date (item);
if (temp_date) {
if (!exists) {
mi->info.uid = g_strdup (e_gw_item_get_id(item));
- mi->info.size = e_gw_item_get_mail_size (item);
+ mi->info.size = e_gw_item_get_mail_size (item);
mi->info.subject = camel_pstring_strdup(e_gw_item_get_subject(item));
}
}
void
-gw_update_summary ( CamelFolder *folder, GList *list,CamelException *ex)
+gw_update_summary ( CamelFolder *folder, GList *list,CamelException *ex)
{
CamelGroupwiseMessageInfo *mi = NULL;
CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
id = e_gw_item_get_id (item);
mi = (CamelGroupwiseMessageInfo *)camel_folder_summary_uid (folder->summary, id);
- if (mi)
+ if (mi)
exists = TRUE;
if (!exists) {
continue;
}
- mi = camel_message_info_new (folder->summary);
+ mi = camel_message_info_new (folder->summary);
if (mi->info.content == NULL) {
mi->info.content = camel_folder_summary_content_info_new (folder->summary);
mi->info.content->type = camel_content_type_new ("multipart", "mixed");
}
}
-
+
rk = e_gw_item_get_recurrence_key (item);
if (rk > 0) {
- recurrence_key = g_strdup_printf("%d", rk);
+ recurrence_key = g_strdup_printf("%d", rk);
camel_message_info_set_user_tag ((CamelMessageInfo*)mi, "recurrence-key", recurrence_key);
- }
+ }
/*all items in the Junk Mail folder should have this flag set*/
if (is_junk)
if (priority && !(g_ascii_strcasecmp (priority,"High"))) {
mi->info.flags |= CAMEL_MESSAGE_FLAGGED;
}
-
+
if (e_gw_item_has_attachment (item))
mi->info.flags |= CAMEL_MESSAGE_ATTACHMENTS;
- if (is_proxy)
+ if (is_proxy)
mi->info.flags |= CAMEL_MESSAGE_USER_NOT_DELETABLE;
mi->server_flags = mi->info.flags;
- org = e_gw_item_get_organizer (item);
+ org = e_gw_item_get_organizer (item);
if (org) {
GString *str;
int i;
str = g_string_new ("");
if (org->display_name && org->display_name[0] && org->email != NULL && org->email[0] != '\0') {
- for (i = 0; org->display_name[i] != '<' &&
- org->display_name[i] != '\0';
+ for (i = 0; org->display_name[i] != '<' &&
+ org->display_name[i] != '\0';
i++);
org->display_name[i] = '\0';
str = g_string_append (str, " ");
}
- if (org->display_name[0] == '\0') {
-
+ if (org->display_name[0] == '\0') {
+
str = g_string_append (str, org->email);
str = g_string_append (str, " ");
}
- if (org->email && org->email[0]) {
+ if (org->email && org->email[0]) {
g_string_append (str, "<");
str = g_string_append (str, org->email);
g_string_append (str, ">");
time_t time = e_gw_connection_get_date_from_string (temp_date);
time_t actual_time = camel_header_decode_date (ctime(&time), NULL);
mi->info.date_sent = mi->info.date_received = actual_time;
- }
+ }
} else {
temp_date = e_gw_item_get_delivered_date(item);
if (temp_date) {
mi->info.uid = g_strdup(e_gw_item_get_id(item));
if (!exists)
- mi->info.size = e_gw_item_get_mail_size (item);
+ mi->info.size = e_gw_item_get_mail_size (item);
mi->info.subject = camel_pstring_strdup(e_gw_item_get_subject(item));
if (exists) {
body = g_strdup (attachment);
g_free (attachment);
is_text_html = TRUE;
- }
+ }
}//if attachment and len
} // if Mime.822 or TEXT.htm
g_string_free (gstr, FALSE);
is_base64_encoded = FALSE;
} else {
- status = e_gw_connection_get_attachment (cnc,
- attach->id, 0, -1,
+ status = e_gw_connection_get_attachment (cnc,
+ attach->id, 0, -1,
(const char **)&attachment, &len);
}
if (status != E_GW_CONNECTION_STATUS_OK) {
if (attach->contentid) {
gchar **t;
t= g_strsplit_set (attach->contentid, "<>", -1);
- if (!t[1])
+ if (!t[1])
camel_mime_part_set_content_id (part, attach->contentid);
- else
+ else
camel_mime_part_set_content_id (part, t[1]);
g_strfreev (t);
camel_mime_part_set_content_location (part, attach->name);
}
static void
-gw_update_all_items (CamelFolder *folder, GList *item_list, CamelException *ex)
+gw_update_all_items (CamelFolder *folder, GList *item_list, CamelException *ex)
{
CamelGroupwiseFolder *gw_folder = CAMEL_GROUPWISE_FOLDER (folder);
GPtrArray *summary = NULL;
int index = 0;
GList *temp;
CamelFolderChangeInfo *changes = NULL;
- CamelMessageInfo *info;
+ CamelMessageInfo *info;
changes = camel_folder_change_info_new ();
item_list = g_list_reverse (item_list);
/*item_ids : List of ids from the summary*/
while (index < summary->len) {
info = g_ptr_array_index (summary, index);
- temp = NULL;
+ temp = NULL;
if (item_list) {
temp = g_list_find_custom (item_list, (const char *)info->uid, (GCompareFunc) strcmp);
camel_data_cache_remove (gw_folder->cache, "cache", info->uid, NULL);
camel_folder_change_info_remove_uid (changes, info->uid);
CAMEL_GROUPWISE_FOLDER_REC_UNLOCK (folder, cache_lock);
- } else {
+ } else {
item_list = g_list_delete_link (item_list, temp);
}
index ++;
CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (folder->parent_store);
CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
- gw_update_cache (folder, item_list, ex, TRUE);
+ gw_update_cache (folder, item_list, ex, TRUE);
CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
- g_list_foreach (item_list, (GFunc)g_free, NULL);
+ g_list_foreach (item_list, (GFunc)g_free, NULL);
g_list_free (item_list);
}
CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock);
/*Get the container id*/
container_id = camel_groupwise_store_container_id_lookup (gw_store, folder->full_name) ;
-
+
item = camel_groupwise_util_item_from_message (cnc, message, CAMEL_ADDRESS (message->from));
/*Set the source*/
if (!strcmp (folder->name, RECEIVED))
}
if (appended_uid)
- *appended_uid = g_strdup (id);
+ *appended_uid = g_strdup (id);
g_free (id);
CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock);
}
}
static void
-groupwise_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
- CamelFolder *destination, GPtrArray **transferred_uids,
+groupwise_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
+ CamelFolder *destination, GPtrArray **transferred_uids,
gboolean delete_originals, CamelException *ex)
{
int count, index = 0;
if (transferred_uids)
*transferred_uids = NULL;
- if (delete_originals)
+ if (delete_originals)
source_container_id = camel_groupwise_store_container_id_lookup (gw_store, source->full_name) ;
else
source_container_id = NULL;
if (camel_exception_is_set (ex))
break;
- if (delete_originals) {
+ if (delete_originals) {
if ( !strcmp(source->full_name, SENT) ) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("This message is not available in offline mode."));
gw_info->server_flags = gw_info->info.flags;
if (diff.bits & CAMEL_MESSAGE_SEEN) {
-
+
/*
- wrapper is a list wrapper bcos e_gw_connection_mark_read
+ wrapper is a list wrapper bcos e_gw_connection_mark_read
is designed for passing multiple uids. Also, there are is not much
- need/use for a e_gw_connection_mark_ITEM_[un]read
+ need/use for a e_gw_connection_mark_ITEM_[un]read
*/
wrapper = g_list_prepend (wrapper, (char *)uid);
wrapper = NULL;
}
-
+
/* A User may mark a message as Unread and then immediately move it to
some other folder. The following piece of code take care of such scenario.
-
- However, Remember that When a mail is deleted after being marked as unread,
- I am not syncing the read-status.
+
+ However, Remember that When a mail is deleted after being marked as unread,
+ I am not syncing the read-status.
*/
if (unset_flags.bits & CAMEL_MESSAGE_SEEN) {
int i, max;
gboolean delete = FALSE;
GList *deleted_items, *deleted_head;
-
+
deleted_items = deleted_head = NULL;
cnc = cnc_lookup (priv);
camel_folder_class->get_message = groupwise_folder_get_message;
camel_folder_class->rename = groupwise_folder_rename;
camel_folder_class->search_by_expression = groupwise_folder_search_by_expression;
- camel_folder_class->search_by_uids = groupwise_folder_search_by_uids;
+ camel_folder_class->search_by_uids = groupwise_folder_search_by_uids;
camel_folder_class->search_free = groupwise_folder_search_free;
camel_folder_class->append_message = groupwise_append_message;
camel_folder_class->refresh_info = groupwise_refresh_info;
#ifdef ENABLE_THREADS
g_static_mutex_init(&gw_folder->priv->search_lock);
g_static_rec_mutex_init(&gw_folder->priv->cache_lock);
-#endif
+#endif
gw_folder->need_rescan = TRUE;
}
}
-void
+void
convert_to_calendar (EGwItem *item, char **str, int *len)
{
EGwItemOrganizer *org = NULL;
gstr = g_string_append (gstr, "BEGIN:VEVENT\n");
if ((recur_key = e_gw_item_get_recurrence_key (item)) != 0) {
- char *recur_k = g_strdup_printf ("%d", recur_key);
+ char *recur_k = g_strdup_printf ("%d", recur_key);
g_string_append_printf (gstr, "UID:%s\n", recur_k);
g_string_append_printf (gstr, "X-GW-RECURRENCE-KEY:%s\n", recur_k);
g_string_append_c(gstr, *temp);
temp++;
}
- g_string_append(gstr, "\n");
+ g_string_append(gstr, "\n");
}
g_string_append_printf (gstr, "DTSTAMP:%s\n", e_gw_item_get_creation_date (item));
org = e_gw_item_get_organizer (item);
if (org)
- g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
+ g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
org->display_name, org->email);
recp_list = e_gw_item_get_recipient_list (item);
for (rl = recp_list ; rl != NULL ; rl = rl->next) {
EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
- g_string_append_printf (gstr,
+ g_string_append_printf (gstr,
"ATTENDEE;CN= %s;ROLE= REQ-PARTICIPANT:\nMAILTO:%s\n",
recp->display_name, recp->email);
}
g_strfreev (tmp);
}
-static void
+static void
convert_to_task (EGwItem *item, char **str, int *len)
{
EGwItemOrganizer *org = NULL;
org = e_gw_item_get_organizer (item);
if (org)
- g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
+ g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
org->display_name, org->email);
recp_list = e_gw_item_get_recipient_list (item);
for (rl = recp_list ; rl != NULL ; rl = rl->next) {
EGwItemRecipient *recp = (EGwItemRecipient *) rl->data;
- g_string_append_printf (gstr,
+ g_string_append_printf (gstr,
"ATTENDEE;CN= %s;ROLE= REQ-PARTICIPANT:\nMAILTO:%s\n",
recp->display_name, recp->email);
}
g_strfreev (tmp);
}
-static void
+static void
convert_to_note (EGwItem *item, char **str, int *len)
{
EGwItemOrganizer *org = NULL;
org = e_gw_item_get_organizer (item);
if (org)
- g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
+ g_string_append_printf (gstr, "ORGANIZER;CN= %s;ROLE= CHAIR;\n MAILTO:%s\n",
org->display_name, org->email);
-
+
gstr = g_string_append (gstr, "END:VJOURNAL\n");
gstr = g_string_append (gstr, "END:VCALENDAR\n");
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-groupwise-folder.h: class for an groupwise folder */
-/*
+/*
* Authors:
* Sivaiah Nallagatla <snallagatla@novell.com>
* parthasarathi susarla <sparthasarathi@novell.com>
- *
+ *
*
* Copyright (C) 2004, Novell, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
struct _CamelGroupwiseFolderClass {
CamelOfflineFolderClass parent_class;
- /* Virtual methods */
-
+ /* Virtual methods */
+
} ;
camel_groupwise_journal_get_type (void)
{
static CamelType type = NULL;
-
+
if (!type) {
type = camel_type_register (camel_offline_journal_get_type (),
"CamelGroupwiseJournal",
(CamelObjectInitFunc) camel_groupwise_journal_init,
(CamelObjectFinalizeFunc) camel_groupwise_journal_finalize);
}
-
+
return type;
}
camel_groupwise_journal_class_init (CamelGroupwiseJournalClass *klass)
{
CamelOfflineJournalClass *journal_class = (CamelOfflineJournalClass *) klass;
-
+
parent_class = (CamelOfflineJournalClass *) camel_type_get_global_classfuncs (CAMEL_TYPE_OFFLINE_JOURNAL);
-
+
journal_class->entry_free = groupwise_entry_free;
journal_class->entry_load = groupwise_entry_load;
journal_class->entry_write = groupwise_entry_write;
static void
camel_groupwise_journal_init (CamelGroupwiseJournal *journal, CamelGroupwiseJournalClass *klass)
{
-
+
}
static void
camel_groupwise_journal_finalize (CamelObject *object)
{
-
+
}
static void
groupwise_entry_free (CamelOfflineJournal *journal, EDListNode *entry)
{
CamelGroupwiseJournalEntry *groupwise_entry = (CamelGroupwiseJournalEntry *) entry;
-
+
g_free (groupwise_entry->uid);
g_free (groupwise_entry->original_uid);
g_free (groupwise_entry->source_container);
groupwise_entry_load (CamelOfflineJournal *journal, FILE *in)
{
CamelGroupwiseJournalEntry *entry;
-
+
entry = g_malloc0 (sizeof (CamelGroupwiseJournalEntry));
-
+
if (camel_file_util_decode_uint32 (in, &entry->type) == -1)
goto exception;
-
+
switch (entry->type) {
case CAMEL_GROUPWISE_JOURNAL_ENTRY_APPEND:
if (camel_file_util_decode_string (in, &entry->uid) == -1)
default:
goto exception;
}
-
+
return (EDListNode *) entry;
-
+
exception:
-
+
if (entry->type == CAMEL_GROUPWISE_JOURNAL_ENTRY_TRANSFER)
g_free (entry->source_container);
-
+
g_free (entry->uid);
g_free (entry);
-
+
return NULL;
}
groupwise_entry_write (CamelOfflineJournal *journal, EDListNode *entry, FILE *out)
{
CamelGroupwiseJournalEntry *groupwise_entry = (CamelGroupwiseJournalEntry *) entry;
-
+
if (camel_file_util_encode_uint32 (out, groupwise_entry->type) == -1)
return -1;
-
+
switch (groupwise_entry->type) {
case CAMEL_GROUPWISE_JOURNAL_ENTRY_APPEND:
if (camel_file_util_encode_string (out, groupwise_entry->uid))
default:
g_assert_not_reached ();
}
-
+
return 0;
}
CamelMessageInfo *info;
CamelStream *stream;
CamelException lex;
-
+
/* if the message isn't in the cache, the user went behind our backs so "not our problem" */
if (!gw_folder->cache || !(stream = camel_data_cache_get (gw_folder->cache, "cache", entry->uid, ex)))
goto done;
-
+
message = camel_mime_message_new ();
if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) {
camel_object_unref (message);
camel_object_unref (stream);
goto done;
}
-
+
camel_object_unref (stream);
-
+
if (!(info = 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);
}
-
+
camel_exception_init (&lex);
camel_folder_append_message (folder, message, info, NULL, &lex);
camel_message_info_free (info);
camel_object_unref (message);
-
+
if (camel_exception_is_set (&lex)) {
camel_exception_xfer (ex, &lex);
return -1;
}
-
+
done:
-
+
camel_folder_summary_remove_uid (folder->summary, entry->uid);
camel_data_cache_remove (gw_folder->cache, "cache", entry->uid, NULL);
-
+
return 0;
}
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);
camel_exception_xfer (ex, &lex);
goto exception;
}
-
+
g_ptr_array_free (xuids, TRUE);
g_ptr_array_free (uids, TRUE);
camel_object_unref (src);
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;
}
groupwise_entry_play (CamelOfflineJournal *journal, EDListNode *entry, CamelException *ex)
{
CamelGroupwiseJournalEntry *groupwise_entry = (CamelGroupwiseJournalEntry *) entry;
-
+
switch (groupwise_entry->type) {
case CAMEL_GROUPWISE_JOURNAL_ENTRY_APPEND:
return groupwise_entry_play_append (journal, groupwise_entry, ex);
camel_groupwise_journal_new (CamelGroupwiseFolder *folder, const char *filename)
{
CamelOfflineJournal *journal;
-
+
g_return_val_if_fail (CAMEL_IS_GROUPWISE_FOLDER (folder), NULL);
-
+
journal = (CamelOfflineJournal *) camel_object_new (camel_groupwise_journal_get_type ());
camel_offline_journal_construct (journal, (CamelFolder *) folder, filename);
-
+
return journal;
}
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,
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;
}
CamelOfflineJournal *journal = (CamelOfflineJournal *) groupwise_journal;
CamelGroupwiseJournalEntry *entry;
char *uid;
-
+
if (!update_cache (groupwise_journal, message, mi, &uid, ex))
return;
-
+
entry = g_new (CamelGroupwiseJournalEntry, 1);
entry->type = CAMEL_GROUPWISE_JOURNAL_ENTRY_APPEND;
entry->uid = uid;
-
+
e_dlist_addtail (&journal->queue, (EDListNode *) entry);
-
+
if (appended_uid)
*appended_uid = g_strdup (uid);
}
CamelGroupwiseStore *gw_store= CAMEL_GROUPWISE_STORE(journal->folder->parent_store) ;
CamelGroupwiseJournalEntry *entry;
char *uid;
-
+
if (!update_cache (groupwise_journal, message, mi, &uid, ex))
return;
-
+
entry = g_new (CamelGroupwiseJournalEntry, 1);
entry->type = CAMEL_GROUPWISE_JOURNAL_ENTRY_APPEND;
entry->uid = uid;
entry->original_uid = g_strdup (original_uid);
entry->source_container = g_strdup (camel_groupwise_store_container_id_lookup (gw_store, ((CamelFolder *)source_folder)->name));
-
+
e_dlist_addtail (&journal->queue, (EDListNode *) entry);
-
+
if (transferred_uid)
*transferred_uid = g_strdup (uid);
}
struct _CamelGroupwiseJournalEntry {
EDListNode node;
-
+
int type;
char *uid;
struct _CamelGroupwiseJournal {
CamelOfflineJournal parent_object;
-
+
};
struct _CamelGroupwiseJournalClass {
CamelOfflineJournalClass parent_class;
-
+
};
/* interfaces for adding a journal entry */
void camel_groupwise_journal_append (CamelGroupwiseJournal *journal, CamelMimeMessage *message, const CamelMessageInfo *mi,
char **appended_uid, CamelException *ex);
-void camel_groupwise_journal_transfer (CamelGroupwiseJournal *journal, CamelGroupwiseFolder *source_folder, CamelMimeMessage *message,
+void camel_groupwise_journal_transfer (CamelGroupwiseJournal *journal, CamelGroupwiseFolder *source_folder, CamelMimeMessage *message,
const CamelMessageInfo *mi, const char *orginal_uid, char **transferred_uid, CamelException *ex);
G_END_DECLS
*
* Copyright 2004 Novell Inc
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{ CAMEL_PROVIDER_CONF_HIDDEN, "auth-domain", NULL,
NULL, "Groupwise" },
-
- { CAMEL_PROVIDER_CONF_SECTION_END },
+
+ { CAMEL_PROVIDER_CONF_SECTION_END },
{ CAMEL_PROVIDER_CONF_END }
};
CamelServiceAuthType camel_groupwise_password_authtype = {
N_("Password"),
-
+
N_("This option will connect to the GroupWise server using a "
"plaintext password."),
-
+
"",
TRUE
};
groupwise_provider.auto_detect = groupwise_auto_detect_cb;
groupwise_provider.authtypes = g_list_prepend (groupwise_provider.authtypes, &camel_groupwise_password_authtype);
groupwise_provider.translation_domain = GETTEXT_PACKAGE;
-
+
if (use_imap)
groupwise_provider.object_types[CAMEL_PROVIDER_STORE] = imap_provider->object_types [CAMEL_PROVIDER_STORE];
else {
groupwise_provider.object_types[CAMEL_PROVIDER_STORE] = camel_groupwise_store_get_type();
groupwise_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = camel_groupwise_transport_get_type();
- }
-
+ }
+
camel_provider_register (&groupwise_provider);
}
add_hash (&hash, u->authmech);
add_hash (&hash, u->host);
hash ^= u->port;
-
+
return hash;
}
else
return FALSE;
}
-
+
if (s2 == NULL)
return FALSE;
groupwise_url_equal (gconstpointer a, gconstpointer b)
{
const CamelURL *u1 = a, *u2 = b;
-
+
return check_equal (u1->protocol, u2->protocol)
&& check_equal (u1->user, u2->user)
&& check_equal (u1->authmech, u2->authmech)
/*
* Copyright (C) 2002 Ximian Inc.
*
- * Authors: Parthasarathi Susarla <sparthasarathi@novell.com>
+ * Authors: Parthasarathi Susarla <sparthasarathi@novell.com>
*
* Description: Based on the imap implementaion of camelstoresummary
*
ssklass->summary_header_load = summary_header_load;
ssklass->summary_header_save = summary_header_save;
-
+
ssklass->store_info_load = store_info_load;
ssklass->store_info_save = store_info_save;
ssklass->store_info_free = store_info_free;
return ns;
}
-void
+void
camel_groupwise_store_summary_namespace_set(CamelGroupwiseStoreSummary *s, CamelGroupwiseStoreNamespace *ns)
{
d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path));
gint32 version, capabilities, count ;
namespace_clear (s) ;
-
+
if (camel_groupwise_store_summary_parent->summary_header_load ((CamelStoreSummary *)s, in) == -1
|| camel_file_util_decode_fixed_int32(in, &version) == -1)
return -1 ;
summary->capabilities = capabilities ;
if (count == 1) {
- if ((summary->namespace = namespace_load (s, in)) == NULL)
+ if ((summary->namespace = namespace_load (s, in)) == NULL)
return -1 ;
}
return 0 ;
#include <glib/gstdio.h>
#include "camel-debug.h"
-#include "camel-folder.h"
+#include "camel-folder.h"
#include "camel-net-utils.h"
#include "camel-private.h"
#include "camel-session.h"
#include "camel-groupwise-summary.h"
#include "camel-groupwise-utils.h"
-#define d(x)
+#define d(x)
#define CURSOR_ITEM_LIMIT 100
#define JUNK_ENABLE 1
#define JUNK_PERSISTENCE 14
* This is a dirty hack. But it *WORKS*
*/
groupwise_store->list_loaded = 3;
-
+
/*storage path*/
priv->storage_path = camel_session_get_storage_path (session, service, ex);
if (!priv->storage_path)
return;
-
+
/*store summary*/
path = g_alloca (strlen (priv->storage_path) + 32);
sprintf (path, "%s/.summary", priv->storage_path);
camel_store_summary_set_filename ((CamelStoreSummary *)groupwise_store->summary, path);
camel_store_summary_touch ((CamelStoreSummary *)groupwise_store->summary);
camel_store_summary_load ((CamelStoreSummary *) groupwise_store->summary);
-
+
/*host and user*/
priv->server_name = g_strdup (url->host);
priv->user = g_strdup (url->user);
priv->port = g_strdup (property_value);
/*filter*/
- if (camel_url_get_param (url, "filter"))
+ if (camel_url_get_param (url, "filter"))
store->flags |= CAMEL_STORE_FILTER_INBOX;
-
- /*Hash Table*/
+
+ /*Hash Table*/
priv->id_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
priv->name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
priv->parent_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
char *uri;
EGwConnectionErrors errors;
- if (priv->use_ssl && !g_str_equal (priv->use_ssl, "never"))
+ if (priv->use_ssl && !g_str_equal (priv->use_ssl, "never"))
uri = g_strconcat ("https://", priv->server_name, ":", priv->port, "/soap", NULL);
- else
+ else
uri = g_strconcat ("http://", priv->server_name, ":", priv->port, "/soap", NULL);
service->url->passwd = NULL;
-
+
while (!authenticated) {
CamelSession *session = service->session;
d("in groupwise store connect\n");
-
-/* if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL ||
+
+/* if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL ||
(service->status == CAMEL_SERVICE_DISCONNECTED))
return FALSE; */
if (service->status == CAMEL_SERVICE_DISCONNECTED)
}
CAMEL_SERVICE_REC_LOCK (service, connect_lock);
-
+
if (priv->cnc) {
CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
return TRUE;
camel_service_disconnect (service, TRUE, NULL);
return FALSE;
}
-
-
+
+
service->status = CAMEL_SERVICE_CONNECTED;
((CamelOfflineStore *) store)->state = CAMEL_OFFLINE_STORE_NETWORK_AVAIL;
if (!e_gw_connection_get_version (priv->cnc)) {
- camel_session_alert_user(session,
- CAMEL_SESSION_ALERT_WARNING,
+ camel_session_alert_user(session,
+ CAMEL_SESSION_ALERT_WARNING,
_("Some features may not work correctly with your current server version"),
FALSE);
{
CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE (service);
CamelGroupwiseStorePrivate *priv = groupwise_store->priv;
-
+
g_print ("camel_groupwise_store_finalize\n");
if (groupwise_store->summary) {
camel_store_summary_save ((CamelStoreSummary *)groupwise_store->summary);
camel_object_unref (groupwise_store->summary);
}
-
+
if (priv) {
if (priv->user) {
g_free (priv->user);
g_free (priv->base_url);
priv->base_url = NULL;
}
-
+
if (priv->storage_path)
g_free(priv->storage_path);
if(groupwise_store->root_container)
g_free (groupwise_store->root_container);
-
+
if (priv->id_hash)
g_hash_table_destroy (priv->id_hash);
groupwise_disconnect (CamelService *service, gboolean clean, CamelException *ex)
{
CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE (service);
-
+
if (clean) {
CAMEL_SERVICE_REC_LOCK (groupwise_store, connect_lock);
if (groupwise_store->priv && groupwise_store->priv->cnc) {
}
CAMEL_SERVICE_REC_UNLOCK (groupwise_store, connect_lock);
}
-
+
//groupwise_disconnect_cleanup (service, clean, ex);
return TRUE;
}
groupwise_store_query_auth_types (CamelService *service, CamelException *ex)
{
GList *auth_types = NULL;
-
+
d("in query auth types\n");
auth_types = g_list_prepend (auth_types, &camel_groupwise_password_authtype);
return auth_types;
fi->flags |= CAMEL_FOLDER_TYPE_TRASH;
else if (!strcmp (folder_name, "Junk Mail"))
fi->flags |= CAMEL_FOLDER_TYPE_JUNK;
-
+
fi->name = g_strdup(name);
return fi;
}
CamelFolderInfo *fi;
const char *name;
-
+
name = folder_name;
storage_path = g_strdup_printf ("%s/folders", priv->storage_path);
return folder;
}
-static CamelFolder *
+static CamelFolder *
groupwise_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex)
{
CamelGroupwiseStore *gw_store = CAMEL_GROUPWISE_STORE (store);
EGwConnectionStatus status;
GList *list = NULL;
gboolean done = FALSE, all_ok = TRUE;
- const char *position = E_GW_CURSOR_POSITION_END;
+ const char *position = E_GW_CURSOR_POSITION_END;
int count = 0, cursor, summary_count = 0;
CamelStoreInfo *si = NULL;
guint total = 0;
-
+
folder = groupwise_get_folder_from_disk (store, folder_name, flags, ex);
if (folder) {
camel_object_ref (folder);
CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
return NULL;
}
-
+
if (gw_store->current_folder) {
camel_object_unref (gw_store->current_folder);
gw_store->current_folder = NULL;
return NULL;
}
g_free (folder_dir);
-
+
si = camel_store_summary_path ((CamelStoreSummary *)gw_store->summary, folder_name);
if (si) {
total = si->total;
if(!summary_count || !summary->time_string) {
d(g_print ("\n\n** %s **: No summary as yet : using get cursor request\n\n", folder->name);)
- status = e_gw_connection_create_cursor (priv->cnc, container_id,
+ status = e_gw_connection_create_cursor (priv->cnc, container_id,
"peek id recipient attachments distribution subject status options priority startDate created delivered size hasAttachment",
NULL,
&cursor);
camel_folder_summary_clear (folder->summary);
while (!done) {
- status = e_gw_connection_read_cursor (priv->cnc, container_id,
- cursor, FALSE,
+ status = e_gw_connection_read_cursor (priv->cnc, container_id,
+ cursor, FALSE,
CURSOR_ITEM_LIMIT, position, &list);
if (status != E_GW_CONNECTION_STATUS_OK) {
all_ok = FALSE;
g_free (container_id);
return NULL;*/
}
-
+
count += g_list_length (list);
-
+
if (total > 0)
camel_operation_progress (NULL, (100*count)/total);
gw_update_summary (folder, list, ex);
-
+
if (!list)
done = TRUE;
g_list_foreach (list, (GFunc)g_object_unref, NULL);
e_gw_connection_destroy_cursor (priv->cnc, container_id, cursor);
camel_operation_end (NULL);
- }
+ }
if (done && all_ok) {
if (summary->time_string)
g_free (summary->time_string);
return folder;
}
-void
+void
gw_store_reload_folder (CamelGroupwiseStore *gw_store, CamelFolder *folder, guint32 flags, CamelException *ex)
{
CamelGroupwiseStorePrivate *priv = gw_store->priv;
EGwConnectionStatus status;
GList *list = NULL;
gboolean done = FALSE;
- const char *position = E_GW_CURSOR_POSITION_END;
+ const char *position = E_GW_CURSOR_POSITION_END;
int count = 0, cursor, summary_count = 0;
CamelStoreInfo *si = NULL;
guint total = 0;
-
+
camel_exception_clear (ex);
CAMEL_SERVICE_REC_LOCK (gw_store, connect_lock);
CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
return;
}
-
+
if (!E_IS_GW_CONNECTION( priv->cnc)) {
if (!groupwise_connect (CAMEL_SERVICE((CamelStore*)gw_store), ex)) {
CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
return;
}
}
-
+
container_id = g_strdup (g_hash_table_lookup (priv->name_hash, folder->full_name));
si = camel_store_summary_path ((CamelStoreSummary *)gw_store->summary, folder->name);
if(!summary_count || !summary->time_string) {
d(g_print ("\n\n** %s **: Summary missing???? Reloading summary....\n\n", folder->name);)
- status = e_gw_connection_create_cursor (priv->cnc, container_id,
+ status = e_gw_connection_create_cursor (priv->cnc, container_id,
"peek id recipient attachments distribution subject status options priority startDate created delivered size hasAttachment",
NULL,
&cursor);
camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
while (!done) {
- status = e_gw_connection_read_cursor (priv->cnc, container_id,
- cursor, FALSE,
+ status = e_gw_connection_read_cursor (priv->cnc, container_id,
+ cursor, FALSE,
CURSOR_ITEM_LIMIT, position, &list);
if (status != E_GW_CONNECTION_STATUS_OK) {
CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
g_free (container_id);
return;
}
-
+
count += g_list_length (list);
-
+
if (total > 0)
camel_operation_progress (NULL, (100*count)/total);
gw_update_summary (folder, list, ex);
-
+
if (!list)
done = TRUE;
g_list_foreach (list, (GFunc)g_object_unref, NULL);
e_gw_connection_destroy_cursor (priv->cnc, container_id, cursor);
camel_operation_end (NULL);
- }
+ }
if (done) {
if (summary->time_string)
camel_folder_summary_save (folder->summary);
gw_store->current_folder = folder;
-
+
g_free (container_id);
CAMEL_SERVICE_REC_UNLOCK (gw_store, connect_lock);
return;
(type == E_GW_CONTAINER_TYPE_DRAFT) ||
(type == E_GW_CONTAINER_TYPE_CABINET) ||
(type == E_GW_CONTAINER_TYPE_JUNK) ||
- (type == E_GW_CONTAINER_TYPE_TRASH) )
+ (type == E_GW_CONTAINER_TYPE_TRASH) )
fi->flags |= CAMEL_FOLDER_SYSTEM;
/*
parent_hash contains the "parent id <-> container id" combination. So we form
temp = g_hash_table_lookup (priv->id_hash, temp_parent );
if (temp == NULL) {
break;
- }
+ }
str = g_strconcat ( temp, "/", str, NULL);
temp_parent = g_hash_table_lookup (priv->parent_hash, temp_parent);
- }
+ }
fi->full_name = g_strdup (str);
fi->uri = g_strconcat (url, str, NULL);
g_free (str);
si->info.unread = fi->unread;
si->info.flags = fi->flags;
/*refresh info*/
- if (store->current_folder
+ if (store->current_folder
&& !strcmp (store->current_folder->full_name, fi->full_name)
&& type != E_GW_CONTAINER_TYPE_INBOX) {
CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS (store->current_folder))->refresh_info(store->current_folder, ex);
g_free ((char *)url);
url = temp_url;
}
-
+
/*populate the hash table for finding the mapping from container id <-> folder name*/
for (;temp_list != NULL ; temp_list = g_list_next (temp_list) ) {
const char *name, *id, *parent;
}
/*id_hash returns the name for a given container id*/
- g_hash_table_insert (priv->id_hash, g_strdup(id), g_strdup(name));
+ g_hash_table_insert (priv->id_hash, g_strdup(id), g_strdup(name));
/*parent_hash returns the parent container id, given an id*/
g_hash_table_insert (priv->parent_hash, g_strdup(id), g_strdup(parent));
}
for (;folder_list != NULL; folder_list = g_list_next (folder_list)) {
EGwContainerType type;
EGwContainer *container = E_GW_CONTAINER (folder_list->data);
-
+
type = e_gw_container_get_container_type (container);
if (e_gw_container_is_root(container))
}
}
}
-
+
g_free ((char *)url);
e_gw_connection_free_container_list (list);
count = camel_store_summary_count ((CamelStoreSummary *)store->summary);
for (i=0;i<camel_store_summary_count((CamelStoreSummary *)groupwise_store->summary);i++) {
CamelStoreInfo *si = camel_store_summary_index((CamelStoreSummary *)groupwise_store->summary, i);
- if (si == NULL)
+ if (si == NULL)
continue;
-
+
if ( !strcmp(name, camel_groupwise_store_info_full_name (groupwise_store->summary, si))
|| match_path (path, camel_groupwise_store_info_full_name (groupwise_store->summary, si))) {
fi = groupwise_build_folder_info(groupwise_store, NULL, camel_store_info_path((CamelStoreSummary *)groupwise_store->summary, si));
CamelGroupwiseStorePrivate *priv = groupwise_store->priv;
CamelFolderInfo *info = NULL;
char *top_folder = NULL;
-
+
if (top) {
top_folder = g_hash_table_lookup (priv->name_hash, top);
/* 'top' is a valid path, but doesnt have a container id
}*/
}
- if (top && groupwise_is_system_folder (top))
+ if (top && groupwise_is_system_folder (top))
return groupwise_build_folder_info (groupwise_store, NULL, top );
/*
if (!priv->cnc) {
if (groupwise_connect ((CamelService *)store, ex)) {
g_warning ("Could connect!!!\n");
- } else
+ } else
g_warning ("Could not connect..failure connecting\n");
}
if (camel_groupwise_store_connected (groupwise_store, ex)) {
folder_name = "Junk Mail";
parent_id = "";
/* TODO: check for offlining*/
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
status = e_gw_connection_modify_junk_settings (priv->cnc, JUNK_ENABLE, 0, 0, JUNK_PERSISTENCE);
if (status == E_GW_CONNECTION_STATUS_OK) {
root = groupwise_build_folder_info(groupwise_store, parent_name, folder_name);
camel_store_summary_save((CamelStoreSummary *)groupwise_store->summary);
-
+
child_container_id = e_gw_connection_get_container_id (priv->cnc, "Junk Mail");
if (!child_container_id)
g_warning("failed to retrieve id for junk folder");
-
- g_hash_table_insert (priv->id_hash, g_strdup(child_container_id), g_strdup(folder_name));
+
+ g_hash_table_insert (priv->id_hash, g_strdup(child_container_id), g_strdup(folder_name));
g_hash_table_insert (priv->name_hash, g_strdup(folder_name), g_strdup(child_container_id));
g_hash_table_insert (priv->parent_hash, g_strdup(child_container_id), g_strdup(parent_id));
camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root);
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create GroupWise folders in offline mode."));
return NULL;
}
-
+
if(parent_name == NULL) {
parent_name = "";
if (groupwise_is_system_folder (folder_name)) {
root = groupwise_build_folder_info(groupwise_store, parent_name,folder_name);
camel_store_summary_save((CamelStoreSummary *)groupwise_store->summary);
- g_hash_table_insert (priv->id_hash, g_strdup(child_container_id), g_strdup(folder_name));
+ g_hash_table_insert (priv->id_hash, g_strdup(child_container_id), g_strdup(folder_name));
g_hash_table_insert (priv->name_hash, g_strdup(root->full_name), g_strdup(child_container_id));
g_hash_table_insert (priv->parent_hash, g_strdup(child_container_id), g_strdup(parent_id));
return root;
}
-static void
+static void
groupwise_delete_folder(CamelStore *store,
const char *folder_name,
CamelException *ex)
g_hash_table_remove (priv->id_hash, container);
g_hash_table_remove (priv->name_hash, folder_name);
-
+
g_hash_table_remove (priv->parent_hash, container);
}
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
-static void
+static void
groupwise_rename_folder(CamelStore *store,
const char *old_name,
const char *new_name,
char *oldpath, *newpath, *storepath;
const char *container_id;
char *temp_new = NULL;
-
+
if (groupwise_is_system_folder (old_name)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot rename Groupwise folder `%s' to `%s'"),
old_name, new_name);
CAMEL_SERVICE_REC_UNLOCK (groupwise_store, connect_lock);
}
-char *
-groupwise_get_name(CamelService *service, gboolean brief)
+char *
+groupwise_get_name(CamelService *service, gboolean brief)
{
- if(brief)
+ if(brief)
return g_strdup_printf(_("GroupWise server %s"), service->url->host);
else
- return g_strdup_printf(_("GroupWise service for %s on %s"),
+ return g_strdup_printf(_("GroupWise service for %s on %s"),
service->url->user, service->url->host);
}
camel_object_state_read(folder);
return folder;
- } else
+ } else
return NULL;
}
/*
* Function to check if we are both connected and are _actually_
* online. Based on an equivalient function in IMAP
- */
+ */
gboolean
camel_groupwise_store_connected (CamelGroupwiseStore *store, CamelException *ex)
{
return FALSE;
}
-static int
+static int
match_path(const char *path, const char *name)
{
char p, n;
CAMEL_SERVICE_CLASS (camel_groupwise_store_class);
CamelStoreClass *camel_store_class =
CAMEL_STORE_CLASS (camel_groupwise_store_class);
-
+
parent_class = CAMEL_OFFLINE_STORE_CLASS (camel_type_get_global_classfuncs (camel_offline_store_get_type ()));
-
+
camel_service_class->construct = groupwise_store_construct;
camel_service_class->query_auth_types = groupwise_store_query_auth_types;
camel_service_class->get_name = groupwise_get_name;
camel_service_class->connect = groupwise_connect;
camel_service_class->disconnect = groupwise_disconnect;
-
+
camel_store_class->hash_folder_name = groupwise_hash_folder_name;
camel_store_class->compare_folder_name = groupwise_compare_folder_name;
-
+
camel_store_class->get_folder = groupwise_get_folder;
camel_store_class->create_folder = groupwise_create_folder;
camel_store_class->delete_folder = groupwise_delete_folder;
{
CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE (object);
CamelGroupwiseStorePrivate *priv = groupwise_store->priv;
-
+
g_print ("camel_groupwise_store_finalize\n");
if (groupwise_store->summary) {
camel_store_summary_save ((CamelStoreSummary *)groupwise_store->summary);
camel_object_unref (groupwise_store->summary);
}
-
+
if (priv) {
if (priv->user) {
g_free (priv->user);
g_free (priv->base_url);
priv->base_url = NULL;
}
-
+
if (E_IS_GW_CONNECTION (priv->cnc)) {
g_object_unref (priv->cnc);
priv->cnc = NULL;
if(groupwise_store->root_container)
g_free (groupwise_store->root_container);
-
+
if (priv->id_hash)
g_hash_table_destroy (priv->id_hash);
{
CamelGroupwiseStore *groupwise_store = CAMEL_GROUPWISE_STORE (object);
CamelGroupwiseStorePrivate *priv = g_new0 (CamelGroupwiseStorePrivate, 1);
-
+
d("in groupwise store init\n");
priv->server_name = NULL;
priv->port = NULL;
priv->user = NULL;
priv->cnc = NULL;
groupwise_store->priv = priv;
-
+
}
CamelType
camel_groupwise_store_get_type (void)
{
static CamelType camel_groupwise_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_groupwise_store_type == CAMEL_INVALID_TYPE) {
camel_groupwise_store_type =
camel_type_register (camel_offline_store_get_type (),
(CamelObjectInitFunc) camel_groupwise_store_init,
(CamelObjectFinalizeFunc) camel_groupwise_store_finalize);
}
-
+
return camel_groupwise_store_type;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-groupwise-store.h : class for an groupwise store */
-/*
+/*
* Authors: Sivaiah Nallagatla <snallagatla@novell.com>
*
* Copyright (C) 2004 Novell, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
char *root_container;
CamelGroupwiseStorePrivate *priv;
CamelFolder *current_folder;
-
+
/* the parameters field is not to be included not. probably for 2.6*/
/*guint32 parameters;*/
time_t refresh_stamp;
*
* Authors:
* parthasrathi susarla <sparthasrathi@novell.com>
- * Based on the IMAP summary class implementation by:
+ * Based on the IMAP summary class implementation by:
* Michael Zucchi <notzed@ximian.com>
* Dan Winship <danw@ximian.com>
*
static int gw_message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) ;
static CamelMessageContentInfo * gw_content_info_load (CamelFolderSummary *s, FILE *in) ;
static int gw_content_info_save (CamelFolderSummary *s, FILE *out, CamelMessageContentInfo *info) ;
-static gboolean gw_info_set_flags(CamelMessageInfo *info, guint32 flags, guint32 set);
+static gboolean gw_info_set_flags(CamelMessageInfo *info, guint32 flags, guint32 set);
static void camel_groupwise_summary_class_init (CamelGroupwiseSummaryClass *klass);
static void camel_groupwise_summary_init (CamelGroupwiseSummary *obj);
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof(CamelGroupwiseMessageInfo);
s->content_info_size = sizeof(CamelGroupwiseMessageContentInfo);
-
+
/* Meta-summary - Overriding UID len */
s->meta_summary->uid_len = 2048;
}
{
CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (
camel_object_new (camel_groupwise_summary_get_type ()));
-
+
summary->folder = folder ;
camel_folder_summary_set_build_content (summary, TRUE);
camel_folder_summary_set_filename (summary, filename);
if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1
|| camel_file_util_decode_fixed_int32(in, &ims->validity) == -1)
return -1;
-
+
if (camel_file_util_decode_string (in, &ims->time_string) == -1)
return -1;
return 0 ;
static CamelMessageContentInfo *
gw_content_info_load (CamelFolderSummary *s, FILE *in)
-{
+{
if (fgetc (in))
return camel_groupwise_summary_parent->content_info_load (s, in);
else
/* we don't set flags which aren't appropriate for the folder*/
if ((set == (CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN|CAMEL_MESSAGE_SEEN)) && (old & CAMEL_GW_MESSAGE_JUNK))
return FALSE;
-
+
mi->flags = (old & ~flags) | (set & flags);
if (old != mi->flags) {
mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
}
/* This is a hack, we are using CAMEL_MESSAGE_JUNK justo to hide the item
* we make sure this doesn't have any side effects*/
-
+
if ((set == CAMEL_MESSAGE_JUNK_LEARN) && (old & CAMEL_GW_MESSAGE_JUNK)) {
mi->flags |= CAMEL_GW_MESSAGE_NOJUNK | CAMEL_MESSAGE_JUNK;
- /* This has ugly side-effects. Evo will never learn unjunk.
+ /* This has ugly side-effects. Evo will never learn unjunk.
We need to create one CAMEL_MESSAGE_HIDDEN flag which must be used for all hiding operations. We must also get rid of the seperate file that is maintained somewhere in evolution/mail/em-folder-browser.c for hidden messages
*/
camel_folder_summary_touch(mi->summary);
}
- } else if ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK))
+ } else if ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK))
return FALSE;
if (mi->summary && mi->summary->folder && mi->uid) {
void
camel_gw_summary_add_offline (CamelFolderSummary *summary, const char *uid, CamelMimeMessage *message, const CamelMessageInfo *info)
{
- CamelGroupwiseMessageInfo *mi ;
+ CamelGroupwiseMessageInfo *mi ;
const CamelFlag *flag ;
const CamelTag *tag ;
for (i = 0; i < count; i++) {
if (!(info = camel_folder_summary_index (summary, i)))
continue;
-
+
uid = camel_message_info_uid (info);
camel_folder_change_info_remove_uid (changes, uid);
camel_folder_summary_remove_uid (summary, uid);
struct _CamelGroupwiseMessageContentInfo {
CamelMessageContentInfo info ;
-} ;
+} ;
struct _CamelGroupwiseSummary {
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-groupwise-transport.c : class for an groupwise transport */
-/*
+/*
* Authors: Sivaiah Nallagatla <snallagatla@novell.com>
* Parthasarathi Susarla <sparthasarathi@novell.com>
*
* Copyright (C) 2004 Novell, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#include "camel-mime-message.h"
#include "camel-mime-utils.h"
#include "camel-multipart.h"
-#include "camel-session.h"
+#include "camel-session.h"
#include "camel-stream-mem.h"
#include "camel-stream.h"
CamelServiceClass *camel_service_class =
CAMEL_SERVICE_CLASS (camel_groupwise_transport_class);
-
+
parent_class = CAMEL_TRANSPORT_CLASS (camel_type_get_global_classfuncs (camel_transport_get_type ()));
-
+
camel_service_class->connect = groupwise_transport_connect;
camel_service_class->get_name = groupwise_transport_get_name;
camel_service_class->construct = groupwise_transport_construct;
-
+
/* virtual method overload */
camel_transport_class->send_to = groupwise_send_to;
}
static gboolean
-groupwise_send_to (CamelTransport *transport,
+groupwise_send_to (CamelTransport *transport,
CamelMimeMessage *message,
- CamelAddress *from,
+ CamelAddress *from,
CamelAddress *recipients,
CamelException *ex)
{
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, _("Authentication failed"));
return FALSE;
}
-
+
item = camel_groupwise_util_item_from_message (cnc, message, from);
-
+
reply_request = (char *)camel_medium_get_header (CAMEL_MEDIUM (message), "In-Reply-To");
if (reply_request) {
char *id;
id = (char *)g_malloc0 (len-1);
id = memcpy(id, reply_request+2, len-3);
status = e_gw_connection_reply_item (cnc, id, NULL, &temp_item);
- if (status != E_GW_CONNECTION_STATUS_OK)
+ if (status != E_GW_CONNECTION_STATUS_OK)
g_warning ("Could not send a replyRequest...continuing without!!\n");
else {
info = e_gw_item_get_link_info (temp_item);
g_free (id);
}
-
-
+
+
/*Send item*/
status = e_gw_connection_send_item (cnc, item, &sent_item_list);
if (status != E_GW_CONNECTION_STATUS_OK) {
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-groupwise-transport.h : class for an groupwise transport */
-/*
+/*
* Authors: Sivaiah Nallagatla <snallagatla@novell.com>
*
* Copyright (C) 2004 Novell, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{
int total_add,i;
EGwItemRecipient *recipient;
-
+
total_add = camel_address_length (recipients);
for (i=0 ; i<total_add ; i++) {
const char *name = NULL, *addr = NULL;
temp_len = 0;
}
}
-
+
if (camel_content_type_is (type, "text", "html") || camel_content_type_is (type, "multipart", "alternative")) {
if (!filename)
filename = "text.htm";
const char *message_id;
char *msgid;
int len;
-
+
message_id = camel_medium_get_header (CAMEL_MEDIUM (dw), "Message-Id");
/*
* XXX: The following code piece is a screwed up way of doing stuff.
* since it removes the container id portion from the id and which the
* groupwise server needs.
*/
-
+
len = strlen (message_id);
msgid = (char *)g_malloc0 (len-1);
msgid = memcpy(msgid, message_id+2, len-3);
status = e_gw_connection_forward_item (cnc, msgid, NULL, TRUE, &temp_item);
g_free (msgid);
-
+
if (status != E_GW_CONNECTION_STATUS_OK) {
g_warning ("Could not send a forwardRequest...continuing without!!\n");
} else {
attachment->name = g_strdup (temp_attach->name);
g_free (attachment->contentType);
attachment->contentType = g_strdup ("Mail");
- g_free (attachment->data);
+ g_free (attachment->data);
attachment->data = NULL;
attachment->size = 0;
info = e_gw_item_get_link_info (temp_item);
/*Egroupwise item*/
item = e_gw_item_new_empty ();
-
+
/*populate recipient list*/
recipients = CAMEL_ADDRESS (camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO));
recipient_list=add_recipients(recipient_list,recipients,E_GW_ITEM_RECIPIENT_TO);
-
+
recipients = CAMEL_ADDRESS (camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC));
recipient_list=add_recipients(recipient_list,recipients,E_GW_ITEM_RECIPIENT_CC);
-
+
recipients = CAMEL_ADDRESS (camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC));
recipient_list=add_recipients(recipient_list,recipients,E_GW_ITEM_RECIPIENT_BC);
recipient_list = g_slist_reverse (recipient_list);
-
+
/** Get the mime parts from CamelMimemessge **/
mp = (CamelMultipart *)camel_medium_get_content_object (CAMEL_MEDIUM (message));
if(!mp) {
CamelStreamMem *content = (CamelStreamMem *)camel_stream_mem_new ();
CamelDataWrapper *dw = NULL;
CamelContentType *type;
-
+
dw = camel_medium_get_content_object (CAMEL_MEDIUM (message));
type = camel_mime_part_get_content_type((CamelMimePart *)message);
-
+
if (camel_content_type_is (type, "text", "plain")) {
CamelStream *filtered_stream;
CamelMimeFilter *filter;
const char *charset;
char *content_type;
-
+
content_type = camel_content_type_simple (type);
e_gw_item_set_content_type (item, content_type);
g_free (content_type);
-
+
charset = camel_content_type_param (type, "charset");
if (charset && g_ascii_strcasecmp (charset, "US-ASCII") && g_ascii_strcasecmp (charset, "UTF-8")) {
filter = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8");
filtered_stream = (CamelStream *) content;
camel_object_ref (content);
}
-
+
camel_data_wrapper_decode_to_stream (dw, filtered_stream);
camel_stream_flush (filtered_stream);
camel_object_unref (filtered_stream);
-
+
camel_stream_write ((CamelStream *) content, "", 1);
e_gw_item_set_message (item, (const char *)content->buffer->data);
} else {
camel_data_wrapper_decode_to_stream (dw, (CamelStream *) content);
- send_as_attachment (cnc, item, content, type, dw, NULL, NULL, &attach_list);
+ send_as_attachment (cnc, item, content, type, dw, NULL, NULL, &attach_list);
}
-
+
camel_object_unref (content);
}
/*Populate EGwItem*/
e_gw_item_set_subject (item, camel_mime_message_get_subject(message));
/*attachmets*/
e_gw_item_set_attach_id_list (item, attach_list);
-
+
/*send options*/
e_gw_item_set_sendoptions (item, TRUE);
- if ((char *)camel_medium_get_header (CAMEL_MEDIUM(message), X_REPLY_CONVENIENT))
+ if ((char *)camel_medium_get_header (CAMEL_MEDIUM(message), X_REPLY_CONVENIENT))
e_gw_item_set_reply_request (item, TRUE);
-
+
send_options = (char *)camel_medium_get_header (CAMEL_MEDIUM(message), X_REPLY_WITHIN);
- if (send_options) {
+ if (send_options) {
e_gw_item_set_reply_request (item, TRUE);
e_gw_item_set_reply_within (item, send_options);
}
send_options = (char *)camel_medium_get_header (CAMEL_MEDIUM(message), X_TRACK_WHEN);
- /*we check if user has modified the status tracking options, if no then we anyway
+ /*we check if user has modified the status tracking options, if no then we anyway
* set status tracking all*/
if (send_options) {
switch (atoi(send_options)) {
break;
case 1: e_gw_item_set_notify_deleted (item, E_GW_ITEM_NOTIFY_MAIL);
}
- }
-
+ }
+
send_options = (char *)camel_medium_get_header (CAMEL_MEDIUM (message), X_SEND_OPT_PRIORITY);
if (send_options) {
switch (atoi(send_options)) {
case E_GW_SECURITY_FOR_YOUR_EYES_ONLY : e_gw_item_set_security(item, "ForYourEyesOnly");
break;
}
- }
+ }
return item;
}
{
char *temp = NULL;
int len;
-
+
temp = g_strdup (*string);
len = strlen (*string);
type = camel_mime_part_get_content_type(part);
dw = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-
+
if (CAMEL_IS_MULTIPART (dw)) {
do_multipart (cnc, item, (CamelMultipart *) camel_medium_get_content_object ((CamelMedium *) part), attach_list);
continue;
}
-
+
if (type->subtype && !strcmp (type->subtype, "alternative")) {
/* eh... I don't think this code will ever get hit? */
CamelMimePart *temp_part;
const char *cid = NULL;
CamelStreamMem *temp_content = (CamelStreamMem *)camel_stream_mem_new ();
CamelDataWrapper *temp_dw = NULL;
-
+
temp_part = camel_multipart_get_part ((CamelMultipart *)dw, 1);
if (temp_part) {
is_alternative = TRUE;
}
camel_object_unref (temp_content);
continue;
- }
-
+ }
+
if (i == 0 && camel_content_type_is (type, "text", "plain")) {
CamelStream *filtered_stream;
CamelMimeFilter *filter;
const char *charset;
char *content_type;
-
+
content_type = camel_content_type_simple (type);
e_gw_item_set_content_type (item, content_type);
g_free (content_type);
-
+
charset = camel_content_type_param (type, "charset");
if (charset && g_ascii_strcasecmp (charset, "US-ASCII") && g_ascii_strcasecmp (charset, "UTF-8")) {
filter = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8");
filtered_stream = (CamelStream *) content;
camel_object_ref (content);
}
-
+
camel_data_wrapper_decode_to_stream (dw, filtered_stream);
camel_stream_flush (filtered_stream);
camel_object_unref (filtered_stream);
-
+
camel_stream_write ((CamelStream *) content, "", 1);
e_gw_item_set_message (item, (const char *)content->buffer->data);
} else {
filename = camel_mime_part_get_filename (part);
disposition = camel_mime_part_get_disposition (part);
content_id = camel_mime_part_get_content_id (part);
-
+
camel_data_wrapper_decode_to_stream (dw, (CamelStream *) content);
send_as_attachment (cnc, item, content, type, dw, filename, content_id, attach_list);
}
-
+
camel_object_unref (content);
} /*end of for*/
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
+/*
* Copyright (C) 2001 Ximian, Inc.
*
* This library is free software; you can redistribute it and/or
{ CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace",
N_("Namespace") },
{ CAMEL_PROVIDER_CONF_SECTION_END },
-
+
{ CAMEL_PROVIDER_CONF_END }
/* revisit each options in other providers (incl. authdomain) for
* relevancy - harish*/
static CamelServiceAuthType camel_hula_password_authtype = {
N_("Password"),
-
+
N_("This option will connect to the Hula server using a "
"plaintext password."),
-
+
"",
TRUE
};
hula_provider.auto_detect = hula_auto_detect_cb;
hula_provider.authtypes = g_list_prepend (hula_provider.authtypes, &camel_hula_password_authtype);
hula_provider.translation_domain = GETTEXT_PACKAGE;
-
+
hula_provider.object_types[CAMEL_PROVIDER_STORE] = imap_provider->object_types [CAMEL_PROVIDER_STORE];
-
-
+
+
camel_provider_register (&hula_provider);
}
add_hash (&hash, u->authmech);
add_hash (&hash, u->host);
hash ^= u->port;
-
+
return hash;
}
else
return FALSE;
}
-
+
if (s2 == NULL)
return FALSE;
hula_url_equal (gconstpointer a, gconstpointer b)
{
const CamelURL *u1 = a, *u2 = b;
-
+
return check_equal (u1->protocol, u2->protocol)
&& check_equal (u1->user, u2->user)
&& check_equal (u1->authmech, u2->authmech)
{
va_list ap;
char *cmd;
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-
+
if (fmt) {
va_start (ap, fmt);
cmd = imap_command_strdup_vprintf (store, fmt, ap);
store->current_folder = folder;
cmd = imap_command_strdup_printf (store, "SELECT %F", folder->full_name);
}
-
+
if (!imap_command_start (store, folder, cmd, ex)) {
g_free (cmd);
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return NULL;
}
g_free (cmd);
-
+
return imap_read_response (store, ex);
}
va_list ap;
char *cmd;
gboolean ok;
-
+
va_start (ap, fmt);
cmd = imap_command_strdup_vprintf (store, fmt, ap);
va_end (ap);
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
ok = imap_command_start (store, folder, cmd, ex);
g_free (cmd);
-
+
if (!ok)
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return ok;
const char *cmd, CamelException *ex)
{
ssize_t nwritten;
-
+
g_return_val_if_fail(store->ostream!=NULL, FALSE);
g_return_val_if_fail(store->istream!=NULL, FALSE);
-
+
/* Check for current folder */
if (folder && folder != store->current_folder) {
CamelImapResponse *response;
CamelException internal_ex;
-
+
response = camel_imap_command (store, folder, ex, NULL);
if (!response)
return FALSE;
return FALSE;
}
}
-
+
/* Send the command */
if (camel_verbose_debug) {
const char *mask;
-
+
if (!strncmp ("LOGIN \"", cmd, 7))
mask = "LOGIN \"xxx\" xxx";
else if (!strncmp ("LOGIN {", cmd, 7))
mask = "LOGIN xxx xxx";
else
mask = cmd;
-
+
fprintf (stderr, "sending : %c%.5u %s\r\n", store->tag_prefix, store->command, mask);
}
-
+
nwritten = camel_stream_printf (store->ostream, "%c%.5u %s\r\n",
store->tag_prefix, store->command++, cmd);
-
+
if (nwritten == -1) {
if (errno == EINTR)
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
else
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
g_strerror (errno));
-
+
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
return FALSE;
}
-
+
return TRUE;
}
* This method is for sending continuing responses to the IMAP server
* after camel_imap_command() or camel_imap_command_response() returns
* a continuation response.
- *
+ *
* This function assumes you have an exclusive lock on the imap stream.
*
* Return value: as for camel_imap_command(). On failure, the store's
g_return_val_if_fail(store->ostream!=NULL, NULL);
g_return_val_if_fail(store->istream!=NULL, NULL);
-
+
if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 ||
camel_stream_write (store->ostream, "\r\n", 2) == -1) {
if (errno == EINTR)
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return NULL;
}
-
+
return imap_read_response (store, ex);
}
{
CamelImapResponseType type;
char *respbuf;
-
+
if (camel_imap_store_readline (store, &respbuf, ex) < 0) {
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return CAMEL_IMAP_RESPONSE_ERROR;
}
-
+
switch (*respbuf) {
case '*':
if (!g_ascii_strncasecmp (respbuf, "* BYE", 5)) {
type = CAMEL_IMAP_RESPONSE_ERROR;
break;
}
-
+
/* Read the rest of the response. */
type = CAMEL_IMAP_RESPONSE_UNTAGGED;
respbuf = imap_read_untagged (store, respbuf, ex);
camel_session_alert_user(((CamelService *)store)->session, CAMEL_SESSION_ALERT_WARNING, msg, FALSE);
g_free(msg);
}
-
+
break;
case '+':
type = CAMEL_IMAP_RESPONSE_CONTINUATION;
break;
}
*response = respbuf;
-
+
if (type == CAMEL_IMAP_RESPONSE_ERROR ||
type == CAMEL_IMAP_RESPONSE_TAGGED)
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
-
+
return type;
}
CamelImapResponse *response;
CamelImapResponseType type;
char *respbuf, *p;
-
+
/* Get another lock so that when we reach the tagged
* response and camel_imap_command_response unlocks,
* we're still locked. This lock is owned by response
* and gets unlocked when response is freed.
*/
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-
+
response = g_new0 (CamelImapResponse, 1);
if (store->current_folder && camel_disco_store_status (CAMEL_DISCO_STORE (store)) != CAMEL_DISCO_STORE_RESYNCING) {
response->folder = store->current_folder;
camel_object_ref (CAMEL_OBJECT (response->folder));
}
-
+
response->untagged = g_ptr_array_new ();
while ((type = camel_imap_command_response (store, &respbuf, ex))
== CAMEL_IMAP_RESPONSE_UNTAGGED)
g_ptr_array_add (response->untagged, respbuf);
-
+
if (type == CAMEL_IMAP_RESPONSE_ERROR) {
camel_imap_response_free_without_processing (store, response);
return NULL;
}
-
+
response->status = respbuf;
-
+
/* Check for OK or continuation response. */
if (*respbuf == '+')
return response;
p = strchr (respbuf, ' ');
if (p && !g_ascii_strncasecmp (p, " OK", 3))
return response;
-
+
/* We should never get BAD, or anything else but +, OK, or NO
* for that matter. Well, we could get BAD, treat as NO.
*/
camel_imap_response_free_without_processing (store, response);
return NULL;
}
-
+
p += 3;
if (!*p++)
p = NULL;
GPtrArray *data;
GString *str;
char *end, *p, *s, *d;
-
+
p = strrchr (line, '{');
if (!p)
return line;
-
+
data = g_ptr_array_new ();
fulllen = 0;
-
+
while (1) {
str = g_string_new (line);
g_free (line);
fulllen += str->len;
g_ptr_array_add (data, str);
-
+
if (!(p = strrchr (str->str, '{')) || p[1] == '-')
break;
-
+
/* HACK ALERT: We scan the non-literal part of the string, looking for possible s expression braces.
This assumes we're getting s-expressions, which we should be.
This is so if we get a blank line after a literal, in an s-expression, we can keep going, since
else if (*s == ')')
sexp--;
}
-
+
length = strtoul (p + 1, &end, 10);
if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2)
break;
ldigits = end - (p + 1);
-
+
/* Read the literal */
str = g_string_sized_new (length + 2);
str->str[0] = '\n';
nread = 0;
-
+
do {
if ((n = camel_stream_read (store->istream, str->str + nread + 1, length - nread)) == -1) {
if (errno == EINTR)
g_string_free (str, TRUE);
goto lose;
}
-
+
nread += n;
} while (n > 0 && nread < length);
-
+
if (nread < length) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Server response ended too soon."));
fwrite(str->str+1, 1, length, stdout);
printf("<--\n");
}
-
+
/* Fix up the literal, turning CRLFs into LF. Also, if
* we find any embedded NULs, strip them. This is
* dubious, but:
* - WU-imapd 12.264 (at least) will cheerily pass
* NULs along if they are embedded in the message
*/
-
+
s = d = str->str + 1;
end = str->str + 1 + length;
while (s < end) {
}
*d = '\0';
str->len = length + 1;
-
+
/* p points to the "{" in the line that starts the
* literal. The length of the CR-less response must be
* less than or equal to the length of the response
* GString's length would be off...
*/
sprintf (p, "{%0*u}", ldigits, length);
-
+
fulllen += str->len;
g_ptr_array_add (data, str);
g_warning("Server sent empty line after a literal, assuming in error");
} while (line[0] == 0 && sexp > 0);
}
-
+
/* Now reassemble the data. */
p = line = g_malloc (fulllen + 1);
for (i = 0; i < data->len; i++) {
*p = '\0';
g_ptr_array_free (data, TRUE);
return line;
-
+
lose:
for (i = 0; i < data->len; i++)
g_string_free (data->pdata[i], TRUE);
int i, number, exists = 0;
GArray *expunged = NULL;
char *resp, *p;
-
+
if (!response)
return;
-
+
for (i = 0; i < response->untagged->len; i++) {
resp = response->untagged->pdata[i];
-
+
if (response->folder) {
/* Check if it's something we need to handle. */
number = strtoul (resp + 2, &p, 10);
}
g_free (resp);
}
-
+
g_ptr_array_free (response->untagged, TRUE);
g_free (response->status);
-
+
if (response->folder) {
if (exists > 0 || expunged) {
/* Update the summary */
if (expunged)
g_array_free (expunged, TRUE);
}
-
+
camel_object_unref (CAMEL_OBJECT (response->folder));
}
-
+
g_free (response);
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
{
if (!response)
return;
-
+
if (response->folder) {
camel_object_unref (CAMEL_OBJECT (response->folder));
response->folder = NULL;
{
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);
_("IMAP server response did not contain "
"%s information"), type);
}
-
+
camel_imap_response_free (store, response);
return resp;
}
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);
int num, len, i, arglen;
args = g_ptr_array_new ();
-
+
/* Determine the length of the data */
len = strlen (fmt);
p = start = fmt;
p = strchr (start, '%');
if (!p)
break;
-
+
switch (*++p) {
case 'd':
num = va_arg (ap, int);
} else if (*p == 'G') {
string = camel_utf8_utf7(string);
}
-
+
arglen = strlen (string);
g_ptr_array_add (args, string);
if (imap_is_atom (string)) {
break;
}
}
-
+
/* Now write out the string */
outptr = out = g_malloc (len + 1);
p = start = fmt;
strncpy (outptr, start, p - start);
outptr += p - start;
}
-
+
switch (*++p) {
case 'd':
num = GPOINTER_TO_INT (args->pdata[i++]);
outptr += sprintf (outptr, "%d", num);
break;
-
+
case 's':
string = args->pdata[i++];
outptr += sprintf (outptr, "%s", string);
outptr += sprintf (outptr, "{%d+}\r\n%s", len, string);
} else {
char *quoted = imap_quote_string (string);
-
+
outptr += sprintf (outptr, "%s", quoted);
g_free (quoted);
}
}
-
+
if (*p == 'F' || *p == 'G')
g_free (string);
break;
*outptr++ = '%';
*outptr++ = *p;
}
-
+
start = *p ? p + 1 : p;
}
-
+
g_ptr_array_free (args, TRUE);
return out;
{
va_list ap;
char *result;
-
+
va_start (ap, fmt);
result = imap_command_strdup_vprintf (store, fmt, ap);
va_end (ap);
-
+
return result;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-command.h: IMAP command sending/parsing routines */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
* Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2000, 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-folder.c: class for an imap folder */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
+ * Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2000, 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* USA
*/
-#include <config.h>
+#include <config.h>
#include <ctype.h>
#include <errno.h>
#include "camel-imap-utils.h"
#include "camel-imap-wrapper.h"
-#define d(x)
+#define d(x)
/* set to -1 for infinite size (suggested max command-line length is
* 1000 octets (see rfc2683), so we should keep the uid-set length to
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object);
CamelFolder *folder = CAMEL_FOLDER (object);
-
+
folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED |
CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN;
-
+
folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY |
CAMEL_FOLDER_HAS_SEARCH_CAPABILITY);
-
+
imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv));
#ifdef ENABLE_THREADS
g_static_mutex_init(&imap_folder->priv->search_lock);
camel_imap_folder_get_type (void)
{
static CamelType camel_imap_folder_type = CAMEL_INVALID_TYPE;
-
+
if (camel_imap_folder_type == CAMEL_INVALID_TYPE) {
int i;
for (i = 0; i < sizeof (imap_property_list)/sizeof (imap_property_list [0]); i++)
imap_property_list [i].description = _(imap_property_list [i].description);
}
-
+
return camel_imap_folder_type;
}
GData *fetch_data;
int i, count;
char *resp;
-
+
count = camel_folder_summary_count (folder->summary);
-
+
for (i = 0; i < response->untagged->len; i++) {
resp = response->untagged->pdata[i] + 2;
imap_parse_flag_list (&resp, &folder->permanent_flags, NULL);
} else if (!g_ascii_strncasecmp (resp, "OK [PERMANENTFLAGS ", 19)) {
resp += 19;
-
+
/* workaround for broken IMAP servers that send "* OK [PERMANENTFLAGS ()] Permanent flags"
* even tho they do allow storing flags. *Sigh* So many fucking broken IMAP servers out there. */
imap_parse_flag_list (&resp, &perm_flags, NULL);
validity = strtoul (resp + 16, NULL, 10);
} else if (isdigit ((unsigned char)*resp)) {
unsigned long num = strtoul (resp, &resp, 10);
-
+
if (!g_ascii_strncasecmp (resp, " EXISTS", 7)) {
exists = num;
/* Remove from the response so nothing
_("Folder was destroyed and recreated on server."));
return;
}
-
+
/* FIXME: find missing UIDs ? */
return;
}
-
+
if (!imap_summary->validity)
imap_summary->validity = validity;
else if (validity != imap_summary->validity) {
camel_imap_folder_changed (folder, exists, NULL, ex);
return;
}
-
+
/* If we've lost messages, we have to rescan everything */
if (exists < count)
imap_folder->need_rescan = TRUE;
else if (count != 0 && !imap_folder->need_rescan) {
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
-
+
/* Similarly, if the UID of the highest message we
* know about has changed, then that indicates that
* messages have been both added and removed, so we
}
if (uid != 0 || val != count || g_ascii_strncasecmp (resp, " FETCH (", 8) != 0)
continue;
-
+
fetch_data = parse_fetch_response (imap_folder, resp + 7);
uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10);
g_datalist_clear (&fetch_data);
}
camel_imap_response_free_without_processing (store, response);
-
+
info = camel_folder_summary_index (folder->summary, count - 1);
val = strtoul (camel_message_info_uid (info), NULL, 10);
camel_message_info_free(info);
if (uid == 0 || uid != val)
imap_folder->need_rescan = TRUE;
}
-
+
/* Now rescan if we need to */
if (imap_folder->need_rescan) {
imap_rescan (folder, exists, ex);
return;
}
-
+
/* If we don't need to rescan completely, but new messages
* have been added, find out about them.
*/
if (exists > count)
camel_imap_folder_changed (folder, exists, NULL, ex);
-
+
/* And we're done. */
}
-static void
+static void
imap_finalize (CamelObject *object)
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object);
return;
imap_folder->need_rescan = FALSE;
-
+
summary_len = camel_folder_summary_count (folder->summary);
if (summary_len == 0) {
if (exists)
camel_imap_folder_changed (folder, exists, NULL, ex);
return;
}
-
+
/* Check UIDs and flags of all messages we already know of. */
camel_operation_start (NULL, _("Scanning for changed messages in %s"), folder->name);
info = camel_folder_summary_index (folder->summary, summary_len - 1);
return;
}
-
+
/* Free the final tagged response */
g_free (resp);
-
+
/* If we find a UID in the summary that doesn't correspond to
* the UID in the folder, then either: (a) it's a real UID,
* but the message was deleted on the server, or (b) it's a
info = camel_folder_summary_index (folder->summary, i);
iinfo = (CamelImapMessageInfo *)info;
-
+
if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) {
camel_message_info_free(info);
seq = i + 1;
summary_len--;
continue;
}
-
+
/* Update summary flags */
if (new[i].flags != iinfo->server_flags) {
guint32 server_set, server_cleared;
-
+
server_set = new[i].flags & ~iinfo->server_flags;
server_cleared = iinfo->server_flags & ~new[i].flags;
continue;
}
}
-
+
g_ptr_array_add (matches, info);
if (range != -1)
continue;
char *set, *flaglist;
gboolean unset;
int i, j, max;
-
+
if (folder->permanent_flags == 0) {
imap_sync_offline (folder, ex);
return;
}
-
+
camel_exception_init (&local_ex);
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-
+
/* Find a message with changed flags, find all of the other
* messages like it, sync them as a group, mark them as
* updated, and continue.
for (i = 0; i < max; i++) {
if (!(info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i)))
continue;
-
+
if (!(info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
camel_message_info_free((CamelMessageInfo *)info);
continue;
empty-set of flags so... if this is true then we
want to unset the previously set flags.*/
unset = !(info->info.flags & folder->permanent_flags);
-
+
/* Note: get_matching() uses UID_SET_LIMIT to limit
the size of the uid-set string. We don't have to
loop here to flush all the matching uids because
camel_message_info_free(info);
if (matches == NULL)
continue;
-
+
/* Make sure we're connected before issuing commands */
if (!camel_imap_store_connected(store, ex)) {
g_free(set);
}
camel_folder_summary_touch (folder->summary);
}
-
+
for (j = 0; j < matches->len; j++) {
info = matches->pdata[j];
camel_message_info_free(&info->info);
}
g_ptr_array_free (matches, TRUE);
-
+
/* We unlock here so that other threads can have a chance to grab the connect_lock */
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
-
+
/* check for an exception */
if (camel_exception_is_set (&local_ex)) {
camel_exception_xfer (ex, &local_ex);
return;
}
-
+
/* Re-lock the connect_lock */
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
}
-
+
/* Save the summary */
imap_sync_offline (folder, ex);
-
+
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
{
CamelFolderChangeInfo *changes;
int i;
-
+
qsort (uids->pdata, uids->len, sizeof (void *), uid_compar);
-
+
changes = camel_folder_change_info_new ();
-
+
for (i = 0; i < uids->len; i++) {
camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]);
camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
CamelImapResponse *response;
int uid = 0;
char *set;
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
if ((store->capabilities & IMAP_CAPABILITY_UIDPLUS) == 0) {
return;
}
}
-
+
qsort (uids->pdata, uids->len, sizeof (void *), uid_compar);
-
+
while (uid < uids->len) {
set = imap_uid_array_to_set (folder->summary, uids, uid, UID_SET_LIMIT, &uid);
response = camel_imap_command (store, folder, ex,
imap_expunge_uids_online (folder, uids, ex);
return;
}
-
+
/* If we don't have UID EXPUNGE we need to avoid expunging any
* of the wrong messages. So we search for deleted messages,
* and any that aren't in our to-expunge list get temporarily
* marked un-deleted.
*/
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex);
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return;
}
-
+
if (result[8] == ' ') {
char *uid, *lasts = NULL;
unsigned long euid, kuid;
int ei, ki;
-
+
keep_uids = g_ptr_array_new ();
mark_uids = g_ptr_array_new ();
-
+
/* Parse SEARCH response */
for (uid = strtok_r (result + 9, " ", &lasts); uid; uid = strtok_r (NULL, " ", &lasts))
g_ptr_array_add (keep_uids, uid);
qsort (keep_uids->pdata, keep_uids->len,
sizeof (void *), uid_compar);
-
+
/* Fill in "mark_uids", empty out "keep_uids" as needed */
for (ei = ki = 0; ei < uids->len; ei++) {
euid = strtoul (uids->pdata[ei], NULL, 10);
-
+
for (kuid = 0; ki < keep_uids->len; ki++) {
kuid = strtoul (keep_uids->pdata[ki], NULL, 10);
-
+
if (kuid >= euid)
break;
}
-
+
if (euid == kuid)
g_ptr_array_remove_index (keep_uids, ki);
else
/* Empty SEARCH result, meaning nothing is marked deleted
* on server.
*/
-
+
keep_uids = NULL;
mark_uids = uids;
}
-
+
/* Unmark messages to be kept */
-
+
if (keep_uids) {
char *uidset;
int uid = 0;
-
+
while (uid < keep_uids->len) {
uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
-
+
response = camel_imap_command (store, folder, ex,
"UID STORE %s -FLAGS.SILENT (\\Deleted)",
uidset);
-
+
g_free (uidset);
-
+
if (!response) {
g_ptr_array_free (keep_uids, TRUE);
g_ptr_array_free (mark_uids, TRUE);
camel_imap_response_free (store, response);
}
}
-
+
/* Mark any messages that still need to be marked */
if (mark_uids) {
char *uidset;
int uid = 0;
-
+
while (uid < mark_uids->len) {
uidset = imap_uid_array_to_set (folder->summary, mark_uids, uid, UID_SET_LIMIT, &uid);
-
+
response = camel_imap_command (store, folder, ex,
"UID STORE %s +FLAGS.SILENT (\\Deleted)",
uidset);
-
+
g_free (uidset);
-
+
if (!response) {
g_ptr_array_free (keep_uids, TRUE);
g_ptr_array_free (mark_uids, TRUE);
if (mark_uids != uids)
g_ptr_array_free (mark_uids, TRUE);
}
-
+
/* Do the actual expunging */
response = camel_imap_command (store, folder, ex, "EXPUNGE");
if (response)
camel_imap_response_free (store, response);
-
+
/* And fix the remaining messages if we mangled them */
if (keep_uids) {
char *uidset;
int uid = 0;
-
+
while (uid < keep_uids->len) {
uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
-
+
/* Don't pass ex if it's already been set */
response = camel_imap_command (store, folder,
camel_exception_is_set (ex) ? NULL : ex,
"UID STORE %s +FLAGS.SILENT (\\Deleted)",
uidset);
-
+
g_free (uidset);
if (response)
camel_imap_response_free (store, response);
}
-
+
g_ptr_array_free (keep_uids, TRUE);
}
/* now we can free this, now that we're done with keep_uids */
g_free (result);
-
+
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
}
G_LOCK_DEFINE_STATIC (lock);
G_LOCK (lock);
- res = g_strdup_printf ("tempuid-%lx-%d",
+ res = g_strdup_printf ("tempuid-%lx-%d",
(unsigned long) time (NULL),
counter++);
G_UNLOCK (lock);
GByteArray *ba;
char *flagstr, *end;
guint32 flags = 0;
-
+
/* encode any 8bit parts so we avoid sending embedded nul-chars and such */
camel_mime_message_encode_8bit_parts (message);
-
+
/* FIXME: We could avoid this if we knew how big the message was. */
memstream = camel_stream_mem_new ();
ba = g_byte_array_new ();
camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (memstream), ba);
-
+
streamfilter = camel_stream_filter_new_with_stream (memstream);
crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE,
CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
flagstr = imap_create_flag_list (flags, (CamelMessageInfo *)info, folder->permanent_flags);
else
flagstr = NULL;
-
+
response = camel_imap_command (store, NULL, ex, "APPEND %F%s%s {%d}",
folder->full_name, flagstr ? " " : "",
flagstr ? flagstr : "", ba->len);
g_free (flagstr);
-
+
if (!response) {
if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_SERVICE_INVALID && !store->nocustomappend) {
camel_exception_clear(ex);
g_byte_array_free (ba, TRUE);
return NULL;
}
-
+
/* send the rest of our data - the mime message */
response2 = camel_imap_command_continuation (store, (const char *) ba->data, ba->len, ex);
g_byte_array_free (ba, TRUE);
camel_imap_response_free (store, response);
if (!response2)
return response2;
-
+
if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
*uid = camel_strstrcase (response2->status, "[APPENDUID ");
if (*uid)
}
} else
*uid = NULL;
-
+
return response2;
}
response = do_append (folder, message, info, &uid, ex);
if (!response)
return;
-
+
if (uid) {
/* Cache first, since freeing response may trigger a
* summary update that will want this information.
g_free (uid);
} else if (appended_uid)
*appended_uid = NULL;
-
+
camel_imap_response_free (store, response);
-
+
/* Make sure a "folder_changed" is emitted. */
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
if (store->current_folder != folder ||
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
CamelImapResponse *response;
char *uid;
-
+
response = do_append (folder, message, info, &uid, ex);
if (!response)
return;
-
+
if (uid) {
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
const char *olduid = camel_message_info_uid (info);
-
+
CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
camel_imap_message_cache_copy (imap_folder->cache, olduid,
imap_folder->cache, uid, ex);
g_free (uid);
} else if (appended_uid)
*appended_uid = NULL;
-
+
camel_imap_response_free (store, response);
}
CamelImapResponse *response;
char *uidset;
int uid = 0, last=0, i;
-
+
while (uid < uids->len && !camel_exception_is_set (ex)) {
uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid);
return;
count = camel_folder_summary_count (dest->summary);
-
+
qsort (uids->pdata, uids->len, sizeof (void *), uid_compar);
-
+
/* Now copy the messages */
do_copy(source, uids, dest, delete_originals, ex);
if (camel_exception_is_set (ex))
if (store->current_folder != dest ||
camel_folder_summary_count (dest->summary) == count)
camel_folder_refresh_info (dest, ex);
-
+
/* FIXME */
if (transferred_uids)
*transferred_uids = NULL;
const char *uid;
CamelMimeMessage *message;
CamelMessageInfo *info;
-
+
qsort (uids->pdata, uids->len, sizeof (void *), uid_compar);
-
+
/* This is trickier than append_resyncing, because some of
* the messages we are copying may have been copied or
* appended into @source while we were offline, in which case
part_spec_push (struct _part_spec_stack **stack, int part)
{
struct _part_spec_stack *node;
-
+
node = g_new (struct _part_spec_stack, 1);
node->parent = *stack;
node->part = part;
-
+
*stack = node;
}
{
struct _part_spec_stack *node;
int part;
-
+
g_return_val_if_fail (*stack != NULL, 0);
-
+
node = *stack;
*stack = node->parent;
-
+
part = node->part;
g_free (node);
-
+
return part;
}
char *part_spec, *buf;
size_t len = 1;
int part;
-
+
node = ci;
while (node->parent) {
CamelMessageContentInfo *child;
-
+
/* FIXME: is this only supposed to apply if 'node' is a multipart? */
if (node->parent->parent &&
camel_content_type_is (node->parent->type, "message", "*") &&
node = node->parent;
continue;
}
-
+
child = node->parent->childs;
for (part = 1; child; part++) {
if (child == node)
break;
-
+
child = child->next;
}
-
+
part_spec_push (&stack, part);
-
+
len += 2;
while ((part = part / 10))
len++;
-
+
node = node->parent;
}
-
+
buf = part_spec = g_malloc (len);
part_spec[0] = '\0';
-
+
while (stack) {
part = part_spec_pop (&stack);
buf += sprintf (buf, "%d%s", part, stack ? "." : "");
}
-
+
return part_spec;
}
CamelDataWrapper *content = NULL;
CamelStream *stream;
char *part_spec;
-
+
part_spec = content_info_get_part_spec (ci);
d(printf("get content '%s' '%s' (frommsg = %d)\n", part_spec, camel_content_type_format(ci->type), frommsg));
CamelMultipartSigned *body_mp;
char *spec;
int ret;
-
+
/* Note: because we get the content parts uninterpreted anyway, we could potentially
just use the normalmultipart code, except that multipart/signed wont let you yet! */
-
+
body_mp = camel_multipart_signed_new ();
/* need to set this so it grabs the boundary and other info about the signed type */
/* we assume that part->content_type is more accurate/full than ci->type */
camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), CAMEL_DATA_WRAPPER (part)->mime_type);
-
+
spec = g_alloca(strlen(part_spec) + 6);
if (frommsg)
sprintf(spec, part_spec[0] ? "%s.TEXT" : "TEXT", part_spec);
else
strcpy(spec, part_spec);
g_free(part_spec);
-
+
stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, ex);
if (stream) {
ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (body_mp), stream);
return NULL;
}
}
-
+
return (CamelDataWrapper *) body_mp;
} else if (camel_content_type_is (ci->type, "multipart", "*")) {
CamelMultipart *body_mp;
char *child_spec;
int speclen, num, isdigest;
-
+
if (camel_content_type_is (ci->type, "multipart", "encrypted"))
body_mp = (CamelMultipart *) camel_multipart_encrypted_new ();
else
body_mp = camel_multipart_new ();
-
+
/* need to set this so it grabs the boundary and other info about the multipart */
/* we assume that part->content_type is more accurate/full than ci->type */
camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), CAMEL_DATA_WRAPPER (part)->mime_type);
isdigest = camel_content_type_is(((CamelDataWrapper *)part)->mime_type, "multipart", "digest");
-
+
speclen = strlen (part_spec);
child_spec = g_malloc (speclen + 17); /* dot + 10 + dot + MIME + nul */
memcpy (child_spec, part_spec, speclen);
if (speclen > 0)
child_spec[speclen++] = '.';
g_free (part_spec);
-
+
ci = ci->childs;
num = 1;
while (ci) {
stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, FALSE, ex);
if (stream) {
int ret;
-
+
part = camel_mime_part_new ();
ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (part), stream);
camel_object_unref (CAMEL_OBJECT (stream));
g_free (child_spec);
return NULL;
}
-
+
content = get_content (imap_folder, uid, part, ci, FALSE, ex);
}
-
+
if (!stream || !content) {
camel_object_unref (CAMEL_OBJECT (body_mp));
g_free (child_spec);
camel_multipart_add_part (body_mp, part);
camel_object_unref(part);
-
+
ci = ci->next;
}
-
+
g_free (child_spec);
-
+
return (CamelDataWrapper *) body_mp;
} else if (camel_content_type_is (ci->type, "message", "rfc822")) {
content = (CamelDataWrapper *) get_message (imap_folder, uid, ci->childs, ex);
camel_object_unref (CAMEL_OBJECT (msg));
return NULL;
}
-
+
content = get_content (imap_folder, uid, CAMEL_MIME_PART (msg), ci, TRUE, ex);
if (!content) {
camel_object_unref (CAMEL_OBJECT (msg));
camel_data_wrapper_set_mime_type_field(content, camel_mime_part_get_content_type((CamelMimePart *)msg));
camel_medium_set_content_object (CAMEL_MEDIUM (msg), content);
camel_object_unref (CAMEL_OBJECT (content));
-
+
return msg;
}
{
CamelMimeMessage *msg;
int ret;
-
+
if (!stream) {
stream = camel_imap_folder_fetch_data (imap_folder, uid, "",
FALSE, ex);
{
if (!ci->type)
return TRUE;
-
+
if (camel_content_type_is (ci->type, "multipart", "*")
|| camel_content_type_is (ci->type, "message", "rfc822")) {
if (!ci->childs)
GData *fetch_data = NULL;
char *body, *found_uid;
int i;
-
+
CAMEL_SERVICE_REC_LOCK(store, connect_lock);
if (!camel_imap_store_connected(store, ex)) {
CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
_("This message is not currently available"));
goto fail;
}
-
+
response = camel_imap_command (store, folder, ex, "UID FETCH %s BODY", uid);
CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
body = NULL;
}
}
-
+
if (body) {
/* NB: small race here, setting the info.content */
imap_parse_body ((const char **) &body, folder, mi->info.content);
if (fetch_data)
g_datalist_clear (&fetch_data);
-
+
camel_imap_response_free (store, response);
} else {
camel_exception_clear(ex);
camel_message_info_dump((CamelMessageInfo *)mi);
camel_debug_end();
}
-
+
/* FETCH returned OK, but we didn't parse a BODY
* response. Courier will return invalid BODY
* responses for invalidly MIMEd messages, so
camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", store->base_url);
fail:
camel_message_info_free(&mi->info);
-
+
return msg;
}
{
register const unsigned char *inptr;
int *val, colons = 0;
-
+
*hour = *min = *sec = 0;
-
+
val = hour;
for (inptr = *in; *inptr && !isspace ((int) *inptr); inptr++) {
if (*inptr == ':') {
else
*val = (*val * 10) + (*inptr - '0');
}
-
+
*in = inptr;
-
+
return TRUE;
}
unsigned char *buf;
struct tm tm;
time_t date;
-
+
memset ((void *) &tm, 0, sizeof (struct tm));
-
+
tm.tm_mday = strtoul ((char *) inptr, (char **) &buf, 10);
if (buf == inptr || *buf != '-')
return (time_t) -1;
-
+
inptr = buf + 1;
if (inptr[3] != '-')
return (time_t) -1;
-
+
for (n = 0; n < 12; n++) {
if (!g_ascii_strncasecmp ((gchar *) inptr, tm_months[n], 3))
break;
}
-
+
if (n >= 12)
return (time_t) -1;
-
+
tm.tm_mon = n;
-
+
inptr += 4;
-
+
n = strtoul ((char *) inptr, (char **) &buf, 10);
if (buf == inptr || *buf != ' ')
return (time_t) -1;
-
+
tm.tm_year = n - 1900;
-
+
inptr = buf + 1;
if (!decode_time (&inptr, &hour, &min, &sec))
return (time_t) -1;
-
+
tm.tm_hour = hour;
tm.tm_min = min;
tm.tm_sec = sec;
-
+
n = strtol ((char *) inptr, NULL, 10);
-
+
date = e_mktime_utc (&tm);
-
+
/* date is now GMT of the time we want, but not offset by the timezone ... */
-
+
/* this should convert the time to the GMT equiv time */
date -= ((n / 100) * 60 * 60) + (n % 100) * 60;
-
+
return date;
}
CamelImapMessageInfo *mi;
const char *idate;
int seq;
-
+
seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
if (seq < first)
return;
stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
if (!stream)
return;
-
+
if (seq - first >= messages->len)
g_ptr_array_set_size (messages, seq - first + 1);
-
+
msg = camel_mime_message_new ();
if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) {
camel_object_unref (CAMEL_OBJECT (msg));
return;
}
-
+
mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (folder->summary, msg);
camel_object_unref (CAMEL_OBJECT (msg));
-
+
if ((idate = g_datalist_get_data (&data, "INTERNALDATE")))
mi->info.date_received = decode_internaldate ((const unsigned char *) idate);
-
+
if (mi->info.date_received == -1)
mi->info.date_received = mi->info.date_sent;
-
+
messages->pdata[seq - first] = mi;
}
header_spec = g_string_new ("0");
d(printf("Header is : %s", header_spec->str));
-
+
/* Figure out if any of the new messages are already cached (which
* may be the case if we're re-syncing after disconnected operation).
* If so, get their UIDs, FLAGS, and SIZEs. If not, get all that
camel_message_info_free(&mi->info);
} else
uidval = 0;
-
+
size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS);
got = 0;
if (!camel_imap_command_start (store, folder, ex,
return;
}
camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
-
+
/* Parse the responses. We can't add a message to the summary
* until we've gotten its headers, and there's no guarantee
* the server will send the responses in a useful order...
g_free (resp);
if (!data)
continue;
-
+
seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
if (seq < first) {
g_datalist_clear (&data);
continue;
}
-
+
if (g_datalist_get_data (&data, "FLAGS"))
got += IMAP_PRETEND_SIZEOF_FLAGS;
if (g_datalist_get_data (&data, "RFC822.SIZE"))
* will have a clone in his/her message-list,
* but at least we don't crash.
*/
-
+
/* find the previous valid message info */
for (j = seq - first - 1; j >= 0; j--) {
pmi = messages->pdata[j];
if (pmi != NULL)
break;
}
-
+
if (pmi == NULL) {
/* Server response is *really* fucked up,
I guess we just pretend it never happened? */
continue;
}
-
+
mi = (CamelImapMessageInfo *)camel_message_info_clone(pmi);
}
-
+
uid = g_datalist_get_data (&data, "UID");
if (uid)
mi->info.uid = g_strdup (uid);
if ((mi = messages->pdata[i]))
camel_message_info_free(&mi->info);
}
-
+
g_ptr_array_free (messages, TRUE);
-
+
return;
-
+
lose:
if (fetch_data) {
for (i = 0; i < fetch_data->len; i++) {
CamelFolderChangeInfo *changes;
CamelMessageInfo *info;
int len;
-
+
changes = camel_folder_change_info_new ();
if (expunged) {
int i, id;
-
+
for (i = 0; i < expunged->len; i++) {
id = g_array_index (expunged, int, i);
info = camel_folder_summary_index (folder->summary, id - 1);
/* I guess a message that we never retrieved got expunged? */
continue;
}
-
+
camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock);
camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info));
GData *fetch_data;
char *found_uid;
int i;
-
+
/* EXPUNGE responses have to modify the cache, which means
* they have to grab the cache_lock while holding the
* connect_lock.
stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex);
}
CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
-
+
if (stream || cache_only)
return stream;
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
return NULL;
}
-
+
camel_exception_clear (ex);
if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) {
response = camel_imap_command (store, folder, ex,
}
/* We won't need the connect_lock again after this. */
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
-
+
if (!response) {
CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock);
return NULL;
}
-
+
for (i = 0; i < response->untagged->len; i++) {
fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]);
found_uid = g_datalist_get_data (&fetch_data, "UID");
stream = g_datalist_get_data (&fetch_data, "BODY_PART_STREAM");
if (found_uid && stream && !strcmp (uid, found_uid))
break;
-
+
g_datalist_clear (&fetch_data);
stream = NULL;
}
camel_object_ref (CAMEL_OBJECT (stream));
g_datalist_clear (&fetch_data);
}
-
+
return stream;
}
char *start, *part_spec = NULL, *body = NULL, *uid = NULL, *idate = NULL;
gboolean cache_header = TRUE, header = FALSE;
size_t body_len = 0;
-
+
if (*response != '(') {
long seq;
-
+
if (*response != '*' || *(response + 1) != ' ')
return NULL;
seq = strtoul (response + 2, &response, 10);
cache_header = FALSE;
} else if (!g_ascii_strncasecmp (response, "0]", 2))
header = TRUE;
-
+
p = strchr (response, ']');
if (!p || *(p + 1) != ' ')
break;
-
+
if (cache_header)
part_spec = g_strndup (response, p - response);
else
part_spec = g_strdup ("HEADER.FIELDS");
-
+
response = p + 2;
} else {
part_spec = g_strdup ("");
response += 7;
-
+
if (!g_ascii_strncasecmp (response, "HEADER", 6))
header = TRUE;
}
-
+
body = imap_parse_nstring ((const char **) &response, &body_len);
if (!response) {
g_free (part_spec);
break;
}
-
+
if (!body)
body = g_strdup ("");
g_datalist_set_data_full (&data, "BODY_PART_SPEC", part_spec, g_free);
}
} else if (!g_ascii_strncasecmp (response, "UID ", 4)) {
int len;
-
+
len = strcspn (response + 4, " )");
uid = g_strndup (response + 4, len);
g_datalist_set_data_full (&data, "UID", uid, g_free);
response += 4 + len;
} else if (!g_ascii_strncasecmp (response, "INTERNALDATE ", 13)) {
int len;
-
+
response += 13;
if (*response == '"') {
response++;
break;
}
} while (response && *response != ')');
-
+
if (!response || *response != ')') {
g_datalist_clear (&data);
return NULL;
}
-
+
if (uid && body) {
CamelStream *stream;
-
+
if (header && !cache_header) {
stream = camel_stream_mem_new_with_buffer (body, body_len);
} else {
if (stream == NULL)
stream = camel_stream_mem_new_with_buffer (body, body_len);
}
-
+
if (stream)
g_datalist_set_data_full (&data, "BODY_PART_STREAM", stream,
(GDestroyNotify) camel_object_unref);
}
-
+
return data;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-folder.h: class for an imap folder */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
+ * Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2000, 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelDiscoFolderClass parent_class;
- /* Virtual methods */
-
+ /* Virtual methods */
+
} CamelImapFolderClass;
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-message-cache.c: Class for an IMAP message cache */
-/*
- * Author:
+/*
+ * Author:
* Dan Winship <danw@ximian.com>
*
* Copyright (C) 2001 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_imap_message_cache_get_type (void)
{
static CamelType camel_imap_message_cache_type = CAMEL_INVALID_TYPE;
-
+
if (camel_imap_message_cache_type == CAMEL_INVALID_TYPE) {
camel_imap_message_cache_type = camel_type_register (
CAMEL_OBJECT_TYPE, "CamelImapMessageCache",
/**
* camel_imap_message_cache_set_path:
- * @cache:
- * @path:
- *
+ * @cache:
+ * @path:
+ *
* Set the path used for the message cache.
**/
void
{
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
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,
g_free (*path);
return NULL;
}
-
+
return camel_stream_fs_new_with_fd (fd);
}
{
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);
}
{
char *path, *key;
CamelStream *stream;
-
+
stream = insert_setup (cache, uid, part_spec, &path, &key, ex);
if (!stream)
return;
-
+
if (camel_stream_write_to_stream (data_stream, stream) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to cache message %s: %s"),
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"),
{
CamelStream *stream;
char *path, *key;
-
+
if (uid[0] == 0)
return NULL;
-
+
#ifdef G_OS_WIN32
/* See comment in insert_setup() */
if (!*part_spec)
g_free (path);
return stream;
}
-
+
stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0);
if (stream) {
cache_put (cache, uid, key, stream);
_("Failed to cache %s: %s"),
part_spec, g_strerror (errno));
}
-
+
g_free (path);
-
+
return stream;
}
CamelStream *stream;
char *part;
int i;
-
+
subparts = g_hash_table_lookup (source->parts, source_uid);
if (!subparts || !subparts->len)
return;
-
+
for (i = 0; i < subparts->len; i++) {
part = strchr (subparts->pdata[i], '.');
if (!part++)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-message-cache.h: Class for an IMAP message cache */
-/*
- * Author:
+/*
+ * Author:
* Dan Winship <danw@ximian.com>
*
* Copyright (C) 2001 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelFolderClass parent_class;
- /* Virtual methods */
-
+ /* Virtual methods */
+
} CamelImapMessageCacheClass;
CamelServiceAuthType camel_imap_password_authtype = {
N_("Password"),
-
+
N_("This option will connect to the IMAP server using a "
"plaintext password."),
-
+
"",
TRUE
};
add_hash (&hash, u->authmech);
add_hash (&hash, u->host);
hash ^= u->port;
-
+
return hash;
}
else
return FALSE;
}
-
+
if (s2 == NULL)
return FALSE;
-
+
return strcmp (s1, s2) == 0;
}
imap_url_equal (gconstpointer a, gconstpointer b)
{
const CamelURL *u1 = a, *u2 = b;
-
+
return check_equal (u1->protocol, u2->protocol)
&& check_equal (u1->user, u2->user)
&& check_equal (u1->authmech, u2->authmech)
CAMEL_FOLDER_SEARCH_CLASS (camel_imap_search_class);
imap_search_parent_class = (CamelFolderSearchClass *)camel_type_get_global_classfuncs (camel_folder_search_get_type ());
-
+
/* virtual method overload */
camel_folder_search_class->body_contains = imap_body_contains;
}
camel_imap_search_get_type (void)
{
static CamelType camel_imap_search_type = CAMEL_INVALID_TYPE;
-
+
if (camel_imap_search_type == CAMEL_INVALID_TYPE) {
camel_imap_search_type = camel_type_register (
CAMEL_FOLDER_SEARCH_TYPE, "CamelImapSearch",
return -1;
d(printf("Saving search cache entry to '%s': %s\n", mr->hash, mr->terms[0]));
-
+
/* we write the whole thing, then re-write the header magic, saves fancy sync code */
memcpy(&header.mark, " ", 4);
header.termcount = 0;
g_string_append_c (search, '"');
}
camel_search_words_free (words);
-
+
/* We only try search using utf8 if its non us-ascii text? */
if ((words->type & CAMEL_SEARCH_WORD_8BIT) && (store->capabilities & IMAP_CAPABILITY_utf8_search)) {
response = camel_imap_command (store, folder, NULL,
result = camel_imap_response_extract (store, response, "SEARCH", NULL);
if (!result)
return -1;
-
+
p = result + sizeof ("* SEARCH");
for (p = strtok_r (p, " ", &lasts); p; p = strtok_r (NULL, " ", &lasts)) {
uid = strtoul(p, NULL, 10);
CamelImapSearch *is = (CamelImapSearch *)s;
char *uid;
ESExpResult *r;
- CamelMessageInfo *info;
+ CamelMessageInfo *info;
GHashTable *uid_hash = NULL;
GPtrArray *array;
int i, j;
camel_imap_store_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
camel_imap_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type();
type = camel_type_register((CamelType)camel_imap_store_summary_parent, "CamelImapStoreSummary",
(CamelObjectInitFunc) camel_imap_store_summary_init,
(CamelObjectFinalizeFunc) camel_imap_store_summary_finalise);
}
-
+
return type;
}
* camel_imap_store_summary_new:
*
* Create a new CamelImapStoreSummary object.
- *
+ *
* Return value: A new CamelImapStoreSummary widget.
**/
CamelImapStoreSummary *
/**
* camel_imap_store_summary_full_name:
- * @s:
- * @path:
- *
+ * @s:
+ * @path:
+ *
* Retrieve a summary item by full name.
*
* A referenced to the summary item is returned, which may be
* ref'd or free'd as appropriate.
- *
+ *
* Return value: The summary item, or NULL if the @full_name name
* is not available.
* It must be freed using camel_store_summary_info_free().
} else {
if (full_name[len] == ns->sep)
len++;
-
+
prefix = camel_imap_store_summary_full_to_path(s, full_name+len, ns->sep);
if (*ns->path) {
pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix);
if (camel_imap_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1
|| camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_STORE_SUMMARY_VERSION) == -1
|| camel_file_util_encode_fixed_int32(out, is->capabilities) == -1
- || camel_file_util_encode_fixed_int32(out, count) == -1)
+ || camel_file_util_encode_fixed_int32(out, count) == -1)
return -1;
if (is->namespace && namespace_save(s, out, is->namespace) == -1)
#include "camel-imap-summary.h"
#include "camel-imap-utils.h"
-#define d(x)
+#define d(x)
/* Specified in RFC 2060 */
#define IMAP_PORT "143"
CAMEL_STORE_CLASS (camel_imap_store_class);
CamelDiscoStoreClass *camel_disco_store_class =
CAMEL_DISCO_STORE_CLASS (camel_imap_store_class);
-
+
parent_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ()));
-
+
/* virtual method overload */
camel_object_class->setv = imap_setv;
camel_object_class->getv = imap_getv;
-
+
camel_service_class->construct = construct;
camel_service_class->query_auth_types = query_auth_types;
camel_service_class->get_name = imap_get_name;
-
+
camel_store_class->hash_folder_name = hash_folder_name;
camel_store_class->compare_folder_name = compare_folder_name;
camel_store_class->create_folder = create_folder;
camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
camel_object_unref(imap_store->summary);
}
-
+
if (imap_store->base_url)
g_free (imap_store->base_url);
if (imap_store->storage_path)
camel_imap_store_init (gpointer object, gpointer klass)
{
CamelImapStore *imap_store = CAMEL_IMAP_STORE (object);
-
+
imap_store->istream = NULL;
imap_store->ostream = NULL;
-
+
imap_store->dir_sep = '\0';
imap_store->current_folder = NULL;
imap_store->connected = FALSE;
camel_imap_store_get_type (void)
{
static CamelType camel_imap_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_imap_store_type == CAMEL_INVALID_TYPE) {
camel_imap_store_type =
camel_type_register (CAMEL_DISCO_STORE_TYPE,
(CamelObjectInitFunc) camel_imap_store_init,
(CamelObjectFinalizeFunc) camel_imap_store_finalize);
}
-
+
return camel_imap_store_type;
}
imap_store->dir_sep = is->namespace->sep;
}
}
-
+
imap_store->capabilities = is->capabilities;
imap_set_server_level(imap_store);
}
CamelImapStore *store = (CamelImapStore *) object;
guint32 tag, flags;
int i;
-
+
for (i = 0; i < args->argc; i++) {
tag = args->argv[i].tag;
-
+
/* make sure this is an arg we're supposed to handle */
if ((tag & CAMEL_ARG_TAG) <= CAMEL_IMAP_STORE_ARG_FIRST ||
(tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100)
case CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE:
flags = args->argv[i].ca_int ? IMAP_PARAM_OVERRIDE_NAMESPACE : 0;
flags |= (store->parameters & ~IMAP_PARAM_OVERRIDE_NAMESPACE);
-
+
if (store->parameters != flags) {
store->parameters = flags;
/* the current imap code will need to do a reconnect for this to take effect */
/* error?? */
continue;
}
-
+
/* let our parent know that we've handled this arg */
camel_argv_ignore (args, i);
}
-
+
/* FIXME: if we need to reconnect for a change to take affect,
we need to do it here... or, better yet, somehow chain it
up to CamelService's setv implementation. */
-
+
return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
}
CamelImapStore *store = (CamelImapStore *) object;
guint32 tag;
int i;
-
+
for (i = 0; i < args->argc; i++) {
tag = args->argv[i].tag;
-
+
/* make sure this is an arg we're supposed to handle */
if ((tag & CAMEL_ARG_TAG) <= CAMEL_IMAP_STORE_ARG_FIRST ||
(tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100)
continue;
-
+
switch (tag) {
case CAMEL_IMAP_STORE_NAMESPACE:
*args->argv[i].ca_str = store->namespace;
break;
}
}
-
+
return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
}
CamelImapStore *store = CAMEL_IMAP_STORE (service);
CamelImapResponse *response;
char *result;
-
+
/* Find out the IMAP capabilities */
/* We assume we have utf8 capable search until a failed search tells us otherwise */
store->capabilities = IMAP_CAPABILITY_utf8_search;
result = camel_imap_response_extract (store, response, "CAPABILITY ", ex);
if (!result)
return FALSE;
-
+
/* Skip over "* CAPABILITY ". */
parse_capability(store, result+13);
g_free (result);
g_free (result);
}
}
-
+
imap_set_server_level (store);
-
+
if (store->summary->capabilities != store->capabilities) {
store->summary->capabilities = store->capabilities;
camel_store_summary_touch((CamelStoreSummary *)store->summary);
camel_store_summary_save((CamelStoreSummary *)store->summary);
}
-
+
return TRUE;
}
gboolean force_imap4 = FALSE;
gboolean clean_quit = TRUE;
char *buf;
-
+
if (ssl_mode != MODE_CLEAR) {
#ifdef HAVE_SSL
if (ssl_mode == MODE_TLS)
_("Could not connect to %s: %s"),
service->url->host,
g_strerror (errno));
-
+
camel_object_unref (tcp_stream);
-
+
return FALSE;
}
-
+
store->ostream = tcp_stream;
store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
-
+
store->connected = TRUE;
store->preauthed = FALSE;
store->command = 0;
camel_object_unref (store->istream);
store->istream = NULL;
}
-
+
if (store->ostream) {
camel_object_unref (store->ostream);
store->ostream = NULL;
}
-
+
store->connected = FALSE;
-
+
return FALSE;
}
-
+
if (!strncmp(buf, "* PREAUTH", 9))
store->preauthed = TRUE;
-
+
if (strstr (buf, "Courier-IMAP") || getenv("CAMEL_IMAP_BRAINDAMAGED")) {
/* Courier-IMAP is braindamaged. So far this flag only
* works around the fact that Courier-IMAP is known to
store->istream = store->ostream = NULL;
return FALSE;
}
-
+
camel_imap_response_free_without_processing (store, response);
-
+
/* Okay, now toggle SSL/TLS mode */
if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
service->url->host, _("SSL is not available in this build"));
goto exception;
#endif /* HAVE_SSL */
-
+
/* rfc2595, section 4 states that after a successful STLS
command, the client MUST discard prior CAPA responses */
if (!imap_get_capability (service, ex)) {
camel_object_unref (store->istream);
store->istream = NULL;
}
-
+
if (store->ostream) {
camel_object_unref (store->ostream);
store->ostream = NULL;
}
-
+
store->connected = FALSE;
-
+
return FALSE;
}
- if (store->capabilities & IMAP_CAPABILITY_LOGINDISABLED ) {
+ if (store->capabilities & IMAP_CAPABILITY_LOGINDISABLED ) {
clean_quit = TRUE;
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to connect to IMAP server %s in secure mode: %s"),
char *full_cmd;
char *child_env[7];
- /* Put full details in the environment, in case the connection
+ /* Put full details in the environment, in case the connection
program needs them */
buf = camel_url_to_string(service->url, 0);
child_env[i++] = g_strdup_printf("URL=%s", buf);
full_cmd = tmp;
break;
}
-
+
len = pc - buf;
var = NULL;
full_cmd = tmp;
buf = pc + 2;
}
-
+
g_free(cmd_copy);
cmd_stream = camel_stream_process_new ();
-
+
ret = camel_stream_process_connect (CAMEL_STREAM_PROCESS(cmd_stream),
full_cmd, (const char **)child_env);
while (i)
g_free(child_env[--i]);
-
+
if (ret == -1) {
if (errno == EINTR)
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
serv = "imap";
port = IMAP_PORT;
}
-
+
if (service->url->port) {
serv = g_alloca (16);
sprintf (serv, "%d", service->url->port);
port = NULL;
}
-
+
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
camel_exception_clear (ex);
ai = camel_getaddrinfo(service->url->host, port, &hints, ex);
}
-
+
if (ai == NULL)
return FALSE;
-
+
ret = connect_to_server (service, ai, mode, ex);
-
+
camel_freeaddrinfo (ai);
-
+
return ret;
}
CamelServiceAuthType *authtype;
GList *sasl_types, *t, *next;
gboolean connected;
-
+
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
return NULL;
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
connected = store->istream != NULL && store->connected;
if (!connected)
CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
if (!connected)
return NULL;
-
+
sasl_types = camel_sasl_authtype_list (FALSE);
for (t = sasl_types; t; t = next) {
authtype = t->data;
next = t->next;
-
+
if (!g_hash_table_lookup (store->authtypes, authtype->authproto)) {
sasl_types = g_list_remove_link (sasl_types, t);
g_list_free_1 (t);
}
}
-
+
return g_list_prepend (sasl_types, &camel_imap_password_authtype);
}
fi->name = g_strdup (_("Trash"));
else
fi->name = g_strdup (name);
-
+
return fi;
}
static void
-imap_folder_effectively_unsubscribed(CamelImapStore *imap_store,
+imap_folder_effectively_unsubscribed(CamelImapStore *imap_store,
const char *folder_name, CamelException *ex)
{
CamelFolderInfo *fi;
name++;
else
name = folder_name;
-
+
storage_path = g_strdup_printf ("%s/folders", imap_store->storage_path);
folder_dir = imap_path_to_physical (storage_path, folder_name);
g_free (storage_path);
g_free (folder_dir);
goto event;
}
-
+
summary_file = g_strdup_printf ("%s/summary", folder_dir);
summary = camel_imap_summary_new (NULL, summary_file);
if (!summary) {
g_free (folder_dir);
goto event;
}
-
+
cache = camel_imap_message_cache_new (folder_dir, summary, ex);
if (cache)
camel_imap_message_cache_clear (cache);
-
+
camel_object_unref (cache);
camel_object_unref (summary);
-
+
g_unlink (summary_file);
g_free (summary_file);
-
+
journal_file = g_strdup_printf ("%s/journal", folder_dir);
g_unlink (journal_file);
g_free (journal_file);
state_file = g_strdup_printf("%s/subfolders", folder_dir);
g_rmdir(state_file);
g_free(state_file);
-
+
g_rmdir (folder_dir);
g_free (folder_dir);
-
+
event:
camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, folder_name);
}
static gboolean
-imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name,
+imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name,
CamelException *ex)
{
CamelImapResponse *response;
{
GPtrArray *folders;
int i;
-
+
folders = camel_object_bag_list(CAMEL_STORE (store)->folders);
-
+
for (i = 0; i <folders->len; i++) {
CamelFolder *folder = folders->pdata[i];
if (camel_exception_is_set (ex) &&
imap_check_folder_still_extant (store, folder->full_name, ex) == FALSE) {
gchar *namedup;
-
+
/* the folder was deleted (may happen when we come back online
* after being offline */
-
+
namedup = g_strdup (folder->full_name);
camel_object_unref(folder);
imap_folder_effectively_unsubscribed (store, namedup, ex);
} else
camel_object_unref(folder);
}
-
+
g_ptr_array_free (folders, TRUE);
}
#endif
CamelImapResponse *response;
char *resp;
char *sasl_resp;
-
+
response = camel_imap_command (store, NULL, ex, "AUTHENTICATE %s", mech);
if (!response)
return FALSE;
-
+
sasl = camel_sasl_new ("imap", mech, CAMEL_SERVICE (store));
while (!camel_sasl_authenticated (sasl)) {
resp = camel_imap_response_extract_continuation (store, response, ex);
if (!resp)
goto lose;
-
+
sasl_resp = camel_sasl_challenge_base64 (sasl, imap_next_word (resp), ex);
g_free (resp);
if (!sasl_resp || camel_exception_is_set (ex))
goto break_and_lose;
-
+
response = camel_imap_command_continuation (store, sasl_resp, strlen (sasl_resp), ex);
g_free (sasl_resp);
if (!response)
goto lose;
}
-
+
resp = camel_imap_response_extract_continuation (store, response, NULL);
if (resp) {
/* Oops. SASL claims we're done, but the IMAP server
g_free (resp);
goto lose;
}
-
+
camel_object_unref (sasl);
-
+
return TRUE;
-
+
break_and_lose:
/* Get the server out of "waiting for continuation data" mode. */
response = camel_imap_command_continuation (store, "*", 1, NULL);
if (response)
camel_imap_response_free (store, response);
-
+
lose:
if (!camel_exception_is_set (ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Bad authentication response from server."));
}
-
+
camel_object_unref (sasl);
-
+
return FALSE;
}
char *errbuf = NULL;
gboolean authenticated = FALSE;
const char *auth_domain;
-
+
auth_domain = camel_url_get_param (service->url, "auth-domain");
-
+
if (store->preauthed) {
if (camel_verbose_debug)
fprintf(stderr, "Server %s has preauthenticated us.\n",
service->url->authmech);
return FALSE;
}
-
+
authtype = camel_sasl_authtype (service->url->authmech);
if (!authtype) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
service->url->authmech);
return FALSE;
}
-
+
if (!authtype->need_password) {
authenticated = try_auth (store, authtype->authproto, ex);
if (!authenticated)
return FALSE;
}
}
-
+
while (!authenticated) {
if (errbuf) {
/* We need to un-cache the password before prompting again */
if (!connect_to_server_wrapper (service, ex))
return FALSE;
}
-
+
if (authtype)
authenticated = try_auth (store, authtype->authproto, ex);
else {
can_work_offline (CamelDiscoStore *disco_store)
{
CamelImapStore *store = CAMEL_IMAP_STORE (disco_store);
-
+
return camel_store_summary_count((CamelStoreSummary *)store->summary) != 0;
}
camel_service_disconnect (service, TRUE, NULL);
return FALSE;
}
-
+
/* Get namespace and hierarchy separator */
if ((store->capabilities & IMAP_CAPABILITY_NAMESPACE) &&
!(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) {
response = camel_imap_command (store, NULL, ex, "NAMESPACE");
if (!response)
goto done;
-
+
result = camel_imap_response_extract (store, response, "NAMESPACE", ex);
if (!result)
goto done;
-
+
#if 0
/* new code... */
namespaces = imap_parse_namespace_response (result);
imap_namespaces_destroy (namespaces);
/* end new code */
#endif
-
+
name = camel_strstrcase (result, "NAMESPACE ((");
if (name) {
char *sep;
-
+
name += 12;
store->namespace = imap_parse_string ((const char **) &name, &len);
if (name && *name++ == ' ') {
}
g_free (result);
}
-
+
if (!store->namespace)
store->namespace = g_strdup ("");
-
+
if (!store->dir_sep) {
if (store->server_level >= IMAP_LEVEL_IMAP4REV1) {
/* This idiom means "tell me the hierarchy separator
}
if (!response)
goto done;
-
+
result = camel_imap_response_extract (store, response, "LIST", NULL);
if (result) {
imap_parse_list_response (store, result, NULL, &store->dir_sep, NULL);
store->dir_sep = '/'; /* Guess */
}
-
+
/* canonicalize the namespace to end with dir_sep */
len = strlen (store->namespace);
if (len && store->namespace[len - 1] != store->dir_sep) {
gchar *tmp;
-
+
tmp = g_strdup_printf ("%s%c", store->namespace, store->dir_sep);
g_free (store->namespace);
store->namespace = tmp;
}
-
+
ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep);
camel_imap_store_summary_namespace_set(store->summary, ns);
-
+
if ((store->parameters & IMAP_PARAM_SUBSCRIPTIONS)
&& camel_store_summary_count((CamelStoreSummary *)store->summary) == 0) {
CamelStoreInfo *si;
char *pattern;
-
+
get_folders_sync(store, store->namespace, ex);
if (camel_exception_is_set(ex))
goto done;
if (!disco_store->diary)
return FALSE;
-
+
store->connected = !camel_exception_is_set (ex);
return store->connected;
camel_object_unref(store->istream);
store->istream = NULL;
}
-
+
if (store->ostream) {
camel_stream_close(store->ostream);
camel_object_unref(store->ostream);
store->ostream = NULL;
}
-
+
store->connected = FALSE;
if (store->current_folder) {
camel_object_unref (store->current_folder);
store->current_folder = NULL;
}
-
+
if (store->authtypes) {
g_hash_table_foreach_remove (store->authtypes,
free_key, NULL);
g_hash_table_destroy (store->authtypes);
store->authtypes = NULL;
}
-
+
if (store->namespace && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) {
g_free (store->namespace);
store->namespace = NULL;
}
-
+
return TRUE;
}
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
CamelImapResponse *response;
-
+
if (store->connected && clean) {
response = camel_imap_command (store, NULL, NULL, "LOGOUT");
camel_imap_response_free (store, response);
}
-
+
imap_disconnect_offline (service, clean, ex);
-
+
return TRUE;
}
camel_message_info_free(info);
}
}
-
+
return FALSE;
}
CamelImapStore *imap_store = (CamelImapStore *) store;
CamelImapResponse *response;
CamelFolder *current_folder;
-
+
CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock);
if (!camel_imap_store_connected(imap_store, ex))
imap_status_item_free (struct imap_status_item *items)
{
struct imap_status_item *next;
-
+
while (items != NULL) {
next = items->next;
g_free (items->name);
struct imap_status_item *items, *item, *tail;
CamelImapResponse *response;
char *status, *name, *p;
-
+
/* FIXME: we assume the server is STATUS-capable */
-
+
response = camel_imap_command (imap_store, NULL, NULL,
"STATUS %F (%s)",
folder_name,
camel_exception_clear (&ex);
return NULL;
}
-
+
if (!(status = camel_imap_response_extract (imap_store, response, "STATUS", NULL)))
return NULL;
-
+
p = status + strlen ("* STATUS ");
while (*p == ' ')
p++;
-
+
/* skip past the mailbox string */
if (*p == '"') {
p++;
p++;
break;
}
-
+
p++;
}
} else {
while (*p != ' ')
p++;
}
-
+
while (*p == ' ')
p++;
-
+
if (*p++ != '(') {
g_free (status);
return NULL;
}
-
+
while (*p == ' ')
p++;
-
+
if (*p == ')') {
g_free (status);
return NULL;
}
-
+
items = NULL;
tail = (struct imap_status_item *) &items;
-
+
do {
name = p;
while (*p != ' ')
p++;
-
+
item = g_malloc (sizeof (struct imap_status_item));
item->next = NULL;
item->name = g_strndup (name, p - name);
item->value = strtoul (p, &p, 10);
-
+
tail->next = item;
tail = item;
-
+
while (*p == ' ')
p++;
} while (*p != ')');
-
+
g_free (status);
-
+
return items;
}
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
return NULL;
}
-
+
if (!g_ascii_strcasecmp (folder_name, "INBOX"))
folder_name = "INBOX";
if (!response) {
char *folder_real, *parent_name, *parent_real;
const char *c;
-
+
if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_USER_CANCEL) {
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
return NULL;
}
-
+
camel_exception_clear (ex);
-
+
if (!(flags & CAMEL_STORE_FOLDER_CREATE)) {
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("No such folder %s"), folder_name);
return NULL;
}
-
+
parent_name = strrchr(folder_name, '/');
c = parent_name ? parent_name+1 : folder_name;
while (*c && *c != imap_store->dir_sep && !strchr ("#%*", *c))
c++;
-
+
if (*c != '\0') {
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH,
} else {
parent_real = NULL;
}
-
+
if (parent_real != NULL) {
gboolean need_convert = FALSE;
char *resp, *thisone;
guint32 flags;
int i;
-
+
if (!(response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %G", parent_real))) {
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
g_free (parent_name);
g_free (parent_real);
return NULL;
}
-
+
/* FIXME: does not handle unexpected circumstances very well */
for (i = 0; i < response->untagged->len; i++) {
resp = response->untagged->pdata[i];
-
+
if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone))
continue;
-
+
if (!strcmp (parent_name, thisone)) {
if (flags & CAMEL_FOLDER_NOINFERIORS)
need_convert = TRUE;
}
-
+
g_free (thisone);
}
-
+
camel_imap_response_free (imap_store, response);
-
+
/* if not, check if we can delete it and recreate it */
if (need_convert) {
struct imap_status_item *items, *item;
guint32 messages = 0;
CamelException lex;
char *name;
-
+
item = items = get_folder_status (imap_store, parent_name, "MESSAGES");
while (item != NULL) {
if (!g_ascii_strcasecmp (item->name, "MESSAGES")) {
messages = item->value;
break;
}
-
+
item = item->next;
}
-
+
imap_status_item_free (items);
-
+
if (messages > 0) {
camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
_("The parent folder is not allowed to contain subfolders"));
g_free (parent_real);
return NULL;
}
-
+
/* delete the old parent and recreate it */
camel_exception_init (&lex);
delete_folder (store, parent_name, &lex);
g_free (parent_real);
return NULL;
}
-
+
/* add the dirsep to the end of parent_name */
name = g_strdup_printf ("%s%c", parent_real, imap_store->dir_sep);
response = camel_imap_command (imap_store, NULL, ex, "CREATE %G",
name);
g_free (name);
-
+
if (!response) {
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
g_free (parent_name);
} else
camel_imap_response_free (imap_store, response);
}
-
+
g_free (parent_real);
}
-
+
g_free (parent_name);
folder_real = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, imap_store->dir_sep);
camel_imap_store_summary_add_from_full(imap_store->summary, folder_real, imap_store->dir_sep);
camel_imap_response_free (imap_store, response);
-
+
response = camel_imap_command (imap_store, NULL, NULL, "SELECT %F", folder_name);
}
g_free(folder_real);
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot create folder `%s': folder exists."),
folder_name);
-
+
camel_imap_response_free_without_processing (imap_store, response);
-
+
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
-
+
return NULL;
}
}
}
camel_imap_response_free_without_processing (imap_store, response);
-
+
CAMEL_SERVICE_REC_UNLOCK (imap_store, connect_lock);
-
+
return new_folder;
}
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("No such folder %s"), folder_name);
}
-
+
return new_folder;
}
if (!camel_imap_store_connected(imap_store, ex))
goto fail;
-
+
/* make sure this folder isn't currently SELECTed */
response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX");
if (!response)
else
npath = g_strdup(new_name);
nfull = camel_imap_store_summary_path_to_full(imap_store->summary, npath, imap_store->dir_sep);
-
+
/* workaround for broken server (courier uses '.') that doesn't rename
subordinate folders as required by rfc 2060 */
if (imap_store->dir_sep == '.') {
if (!camel_imap_store_connected(imap_store, ex))
goto fail;
-
+
/* make sure this folder isn't currently SELECTed - it's
actually possible to rename INBOX but if you do another
INBOX will immediately be created by the server */
manage_subscriptions(store, old_name, TRUE);
goto fail;
}
-
+
camel_imap_response_free (imap_store, response);
/* rename summary, and handle broken server */
g_warning ("Could not rename message cache '%s' to '%s': %s: cache reset",
oldpath, newpath, strerror (errno));
}
-
+
g_free (oldpath);
g_free (newpath);
fail:
gboolean need_convert;
int i = 0, flags;
const char *c;
-
+
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
return NULL;
if (!parent_name)
parent_name = "";
-
+
c = folder_name;
while (*c && *c != imap_store->dir_sep && !strchr ("#%*", *c))
c++;
-
+
if (*c != '\0') {
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH,
_("The folder name \"%s\" is invalid because it contains the character \"%c\""),
folder_name, *c);
return NULL;
}
-
+
/* check if the parent allows inferiors */
/* FIXME: use storesummary directly */
g_free(parent_real);
return NULL;
}
-
+
/* FIXME: does not handle unexpected circumstances very well */
for (i = 0; i < response->untagged->len && !need_convert; i++) {
resp = response->untagged->pdata[i];
-
+
if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone))
continue;
-
+
if (strcmp (thisone, parent_name) == 0) {
if (flags & CAMEL_FOLDER_NOINFERIORS)
need_convert = TRUE;
g_free(thisone);
}
-
+
camel_imap_response_free (imap_store, response);
-
+
camel_exception_init (&internal_ex);
-
+
/* if not, check if we can delete it and recreate it */
if (need_convert) {
struct imap_status_item *items, *item;
guint32 messages = 0;
char *name;
-
+
item = items = get_folder_status (imap_store, parent_name, "MESSAGES");
while (item != NULL) {
if (!g_ascii_strcasecmp (item->name, "MESSAGES")) {
messages = item->value;
break;
}
-
+
item = item->next;
}
-
+
imap_status_item_free (items);
-
+
if (messages > 0) {
camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
_("The parent folder is not allowed to contain subfolders"));
g_free(parent_real);
return NULL;
}
-
+
/* delete the old parent and recreate it */
delete_folder (store, parent_name, &internal_ex);
if (camel_exception_is_set (&internal_ex)) {
camel_exception_xfer (ex, &internal_ex);
return NULL;
}
-
+
/* add the dirsep to the end of parent_name */
name = g_strdup_printf ("%s%c", parent_real, imap_store->dir_sep);
response = camel_imap_command (imap_store, NULL, ex, "CREATE %G",
name);
g_free (name);
-
+
if (!response) {
g_free(parent_real);
return NULL;
root = imap_build_folder_info(imap_store, parent_name);
}
-
+
/* ok now we can create the folder */
real_name = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, imap_store->dir_sep);
full_name = imap_concat (imap_store, parent_real, real_name);
g_free(real_name);
response = camel_imap_command (imap_store, NULL, ex, "CREATE %G", full_name);
-
+
if (response) {
CamelImapStoreInfo *si;
CamelFolderInfo *fi;
g_free (full_name);
g_free(parent_real);
-
+
return root;
}
if (!g_ascii_strcasecmp(fi->full_name, "inbox")) {
flags |= CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_TYPE_INBOX;
fi->name = g_strdup (_("Inbox"));
- } else
+ } else
fi->name = g_strdup(camel_store_info_name(imap_store->summary, si));
-
+
/* HACK: some servers report noinferiors for all folders (uw-imapd)
We just translate this into nochildren, and let the imap layer enforce
it. See create folder */
if (flags & CAMEL_FOLDER_NOINFERIORS)
flags = (flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_NOCHILDREN;
fi->flags = flags;
-
+
url = camel_url_new (imap_store->base_url, NULL);
path = alloca(strlen(fi->full_name)+2);
sprintf(path, "/%s", fi->full_name);
if (store->namespace && store->namespace[0]) {
char *pattern;
-
+
get_folders_sync(store, "INBOX", &m->ex);
if (camel_exception_is_set(&m->ex))
goto done;
get_folders_sync(imap_store, "INBOX", ex);
if (camel_exception_is_set(ex))
goto fail;
-
+
i = strlen(imap_store->namespace)-1;
pattern = g_alloca(i+5);
strcpy(pattern, imap_store->namespace);
}
} else {
char *name;
-
+
name = camel_imap_store_summary_full_from_path(imap_store->summary, top);
if (name == NULL)
name = camel_imap_store_summary_path_to_full(imap_store->summary, top, imap_store->dir_sep);
if (si == NULL)
continue;
-
+
if ((!strcmp(name, camel_imap_store_info_full_name(imap_store->summary, si))
|| imap_match_pattern(imap_store->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si))
|| (include_inbox && !g_ascii_strcasecmp (camel_imap_store_info_full_name(imap_store->summary, si), "INBOX")))
it. See create folder */
if (fi->flags & CAMEL_FOLDER_NOINFERIORS)
fi->flags = (fi->flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_NOCHILDREN;
-
+
/* blah, this gets lost somewhere, i can't be bothered finding out why */
if (!g_ascii_strcasecmp(fi->full_name, "inbox"))
fi->flags = (fi->flags & ~CAMEL_FOLDER_TYPE_MASK) | CAMEL_FOLDER_TYPE_INBOX;
-
+
if (si->flags & CAMEL_FOLDER_NOSELECT) {
CamelURL *url = camel_url_new(fi->uri, NULL);
-
+
camel_url_set_param (url, "noselect", "yes");
g_free(fi->uri);
fi->uri = camel_url_to_string (url, 0);
if (!camel_imap_store_connected (imap_store, ex))
goto done;
-
+
response = camel_imap_command (imap_store, NULL, ex,
"SUBSCRIBE %F", folder_name);
if (!response)
goto done;
camel_imap_response_free (imap_store, response);
-
+
si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name);
if (si) {
if ((si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) {
}
camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
}
-
+
if (imap_store->renaming) {
/* we don't need to emit a "folder_subscribed" signal
if we are in the process of renaming folders, so we
fi = imap_build_folder_info(imap_store, folder_name);
fi->flags |= CAMEL_FOLDER_NOCHILDREN;
-
+
camel_object_trigger_event (CAMEL_OBJECT (store), "folder_subscribed", fi);
camel_folder_info_free (fi);
done:
CamelImapResponse *response;
CAMEL_SERVICE_REC_LOCK(store, connect_lock);
-
+
if (!camel_imap_store_connected (imap_store, ex))
goto done;
-
+
response = camel_imap_command (imap_store, NULL, ex,
"UNSUBSCRIBE %F", folder_name);
if (!response)
{
CamelMessageInfo *info;
int i, max;
-
+
max = camel_folder_summary_count (folder->summary);
for (i = 0; i < max; i++) {
info = camel_folder_summary_index (folder->summary, i);
return TRUE;
}
}
-
+
return FALSE;
}
#endif
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Server unexpectedly disconnected: %s"),
g_strerror (errno));
-
+
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
g_byte_array_free (ba, TRUE);
return -1;
}
-
+
if (camel_verbose_debug) {
fprintf (stderr, "received: ");
fwrite (ba->data, 1, ba->len, stderr);
}
-
+
/* camel-imap-command.c:imap_read_untagged expects the CRLFs
to be stripped off and be nul-terminated *sigh* */
nread = ba->len - 1;
ba->data[nread - 1] = '\0';
nread--;
}
-
+
*dest = ba->data;
g_byte_array_free (ba, FALSE);
-
+
return nread;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-store.h : class for an imap store */
-/*
+/*
* Authors: Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2000 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#define IMAP_FETCH_MINIMAL_HEADERS 3
struct _CamelImapStore {
- CamelDiscoStore parent_object;
-
+ CamelDiscoStore parent_object;
+
CamelStream *istream;
CamelStream *ostream;
struct _CamelImapStoreSummary *summary;
-
+
/* Information about the command channel / connection status */
guint connected:1;
guint preauthed:1;
char tag_prefix;
guint32 command;
CamelFolder *current_folder;
-
+
/* Information about the server */
CamelImapServerLevel server_level;
guint32 capabilities, parameters;
/* NB: namespace should be handled by summary->namespace */
char *namespace, dir_sep, *base_url, *storage_path;
GHashTable *authtypes;
-
+
time_t refresh_stamp;
guint32 headers;
summary_header_load (CamelFolderSummary *s, FILE *in)
{
CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s);
-
+
if (camel_imap_summary_parent->summary_header_load (s, in) == -1)
return -1;
/* Version 1 */
if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1)
return -1;
-
+
if (ims->version == 2) {
/* Version 2: for compat with version 2 of the imap4 summary files */
int have_mlist;
-
+
if (camel_file_util_decode_fixed_int32 (in, &have_mlist) == -1)
return -1;
}
-
+
if (camel_file_util_decode_fixed_int32(in, &ims->validity) == -1)
return -1;
-
+
if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) {
g_warning("Unkown summary version\n");
errno = EINVAL;
CamelMimeMessage *message,
const CamelMessageInfo *info);
-void camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary,
+void camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary,
const char *uid,
const CamelMessageInfo *info);
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-types.h: IMAP types */
-/*
+/*
* Copyright (C) 2001 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
imap_next_word (const char *buf)
{
const char *word;
-
+
/* skip over current word */
word = buf;
while (*word && *word != ' ')
word++;
-
+
/* skip over white space */
while (*word && *word == ' ')
word++;
-
+
return word;
}
imap_namespace_destroy (struct _namespace *namespace)
{
struct _namespace *node, *next;
-
+
node = namespace;
while (node) {
next = node->next;
const char *inptr;
char *astring;
size_t len;
-
+
inptr = *in;
-
+
list = NULL;
tail = (struct _namespace *) &list;
-
+
if (g_ascii_strncasecmp (inptr, "NIL", 3) != 0) {
if (*inptr++ != '(')
goto exception;
-
+
while (*inptr && *inptr != ')') {
if (*inptr++ != '(')
goto exception;
-
+
node = g_new (struct _namespace, 1);
node->next = NULL;
-
+
/* get the namespace prefix */
astring = imap_parse_astring (&inptr, &len);
if (!astring) {
g_free (node);
goto exception;
}
-
+
/* decode IMAP's modified UTF-7 into UTF-8 */
node->prefix = imap_mailbox_decode ((const unsigned char *) astring, len);
g_free (astring);
g_free (node);
goto exception;
}
-
+
tail->next = node;
tail = node;
-
+
/* get the namespace directory delimiter */
inptr = imap_next_word (inptr);
-
+
if (!g_ascii_strncasecmp (inptr, "NIL", 3)) {
inptr = imap_next_word (inptr);
node->delim = '\0';
} else if (*inptr++ == '"') {
if (*inptr == '\\')
inptr++;
-
+
node->delim = *inptr++;
-
+
if (*inptr++ != '"')
goto exception;
} else
goto exception;
-
+
if (*inptr == ' ') {
/* parse extra flags... for now we
don't save them, but in the future
we may want to? */
while (*inptr == ' ')
inptr++;
-
+
while (*inptr && *inptr != ')') {
/* this should be a QSTRING or ATOM */
inptr = imap_next_word (inptr);
/* skip over the param list */
imap_skip_list (&inptr);
}
-
+
while (*inptr == ' ')
inptr++;
}
}
-
+
if (*inptr++ != ')')
goto exception;
-
+
/* there shouldn't be spaces according to the
ABNF grammar, but we all know how closely
people follow specs */
while (*inptr == ' ')
inptr++;
}
-
+
if (*inptr == ')')
inptr++;
} else {
inptr += 3;
}
-
+
*in = inptr;
*namespace = list;
-
+
return TRUE;
-
+
exception:
-
+
/* clean up any namespaces we may have allocated */
imap_namespace_destroy (list);
-
+
return FALSE;
}
namespace_dump (struct _namespace *namespace)
{
struct _namespace *node;
-
+
if (namespace) {
printf ("(");
node = namespace;
printf ("\"%c\")", node->delim);
else
printf ("NUL)");
-
+
node = node->next;
if (node)
printf (" ");
}
-
+
printf (")");
} else {
printf ("NIL");
{
struct _namespaces *namespaces;
const char *inptr;
-
+
d(printf ("parsing: %s\n", response));
-
+
if (*response != '*')
return NULL;
-
+
inptr = imap_next_word (response);
if (g_ascii_strncasecmp (inptr, "NAMESPACE", 9) != 0)
return NULL;
-
+
inptr = imap_next_word (inptr);
-
+
namespaces = g_new (struct _namespaces, 1);
namespaces->personal = NULL;
namespaces->other = NULL;
namespaces->shared = NULL;
-
+
if (!imap_namespace_decode (&inptr, &namespaces->personal))
goto exception;
-
+
if (*inptr != ' ')
goto exception;
-
+
while (*inptr == ' ')
inptr++;
-
+
if (!imap_namespace_decode (&inptr, &namespaces->other))
goto exception;
-
+
if (*inptr != ' ')
goto exception;
-
+
while (*inptr == ' ')
inptr++;
-
+
if (!imap_namespace_decode (&inptr, &namespaces->shared))
goto exception;
-
+
d(namespaces_dump (namespaces));
-
+
return namespaces;
-
+
exception:
-
+
imap_namespaces_destroy (namespaces);
-
+
return NULL;
}
gboolean is_lsub = FALSE;
const char *word;
size_t len;
-
+
if (*buf != '*')
return FALSE;
-
+
word = imap_next_word (buf);
if (g_ascii_strncasecmp (word, "LIST", 4) && g_ascii_strncasecmp (word, "LSUB", 4))
return FALSE;
-
+
/* check if we are looking at an LSUB response */
if (word[1] == 'S' || word[1] == 's')
is_lsub = TRUE;
-
+
/* get the flags */
word = imap_next_word (word);
if (*word != '(')
return FALSE;
-
+
if (flags)
*flags = 0;
-
+
word++;
while (*word != ')') {
len = strcspn (word, " )");
else if (!g_ascii_strncasecmp (word, "\\HasNoChildren", len))
*flags |= CAMEL_FOLDER_NOCHILDREN;
}
-
+
word += len;
while (*word == ' ')
word++;
}
-
+
/* get the directory separator */
word = imap_next_word (word);
if (!strncmp (word, "NIL", 3)) {
return FALSE;
} else
return FALSE;
-
+
if (folder) {
char *astring;
char *mailbox;
-
+
/* get the folder name */
word = imap_next_word (word);
astring = imap_parse_astring (&word, &len);
g_free (astring);
if (!mailbox)
return FALSE;
-
+
/* Kludge around Courier imap's LSUB response for INBOX when it
* isn't subscribed to.
*
*/
if (is_lsub && flags && !g_ascii_strcasecmp (mailbox, "INBOX"))
*flags &= ~CAMEL_FOLDER_NOSELECT;
-
+
*folder = mailbox;
}
-
+
return TRUE;
}
GPtrArray *heirarchy;
char **paths;
const char *p;
-
+
p = folder_name;
if (*p == store->dir_sep)
p++;
-
+
heirarchy = g_ptr_array_new ();
-
+
while (*p) {
if (*p == '"') {
p++;
p++;
continue;
}
-
+
if (*p == store->dir_sep)
g_ptr_array_add (heirarchy, g_strndup (folder_name, p - folder_name));
-
+
p++;
}
-
+
g_ptr_array_add (heirarchy, g_strdup (folder_name));
g_ptr_array_add (heirarchy, NULL);
-
+
paths = (char **) heirarchy->pdata;
g_ptr_array_free (heirarchy, FALSE);
-
+
return paths;
}
/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1,
/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define imap_is_atom_char(c) ((imap_atom_specials[(c)&0xff] & 0x01) != 0)
{
const char *str = *str_p;
char *out;
-
+
if (!str)
return NULL;
else if (*str == '"') {
char *p;
size_t size;
-
+
str++;
size = strcspn (str, "\"") + 1;
p = out = g_malloc (size);
-
+
/* a quoted string cannot be broken into multiple lines */
while (*str && *str != '"' && *str != '\n') {
if (*str == '\\')
*str_p = NULL;
return NULL;
}
-
+
out = g_strndup (str, *len);
*str_p = str + *len;
return out;
} else if (type == IMAP_ASTRING && imap_is_atom_char ((unsigned char)*str)) {
while (imap_is_atom_char ((unsigned char) *str))
str++;
-
+
*len = str - *str_p;
out = g_strndup (*str_p, *len);
*str_p += *len;
skip_asn (const char **str_p)
{
const char *str = *str_p;
-
+
if (!str)
return;
else if (*str == '"') {
*str_p = NULL;
} else if (*str == '{') {
unsigned long len;
-
+
len = strtoul (str + 1, (char **) &str, 10);
if (*str != '}' || *(str + 1) != '\n' ||
strlen (str + 2) < len) {
const char *parms = *parms_p;
char *name, *value;
size_t len;
-
+
if (!g_ascii_strncasecmp (parms, "nil", 3)) {
*parms_p += 3;
return 0;
}
-
+
if (*parms++ != '(')
return -1;
-
+
while (parms && *parms != ')') {
name = imap_parse_nstring (&parms, &len);
skip_char (&parms, ' ');
value = imap_parse_nstring (&parms, &len);
-
+
if (name && value)
camel_content_type_set_param (type, name, value);
g_free (name);
g_free (value);
-
+
if (parms && *parms == ' ')
parms++;
}
-
+
if (!parms || *parms++ != ')')
return -1;
-
+
*parms_p = parms;
-
+
return 0;
}
size_t len;
size_t size;
char *p;
-
+
if (*inptr++ != '(')
return NULL;
-
+
if (ci == NULL) {
ci = camel_folder_summary_content_info_new (folder->summary);
g_ptr_array_add (cis, ci);
}
-
+
if (*inptr == '(') {
/* body_type_mpart */
CamelMessageContentInfo *tail, *children = NULL;
-
+
tail = (CamelMessageContentInfo *) &children;
-
+
do {
if (!(child = imap_body_decode (&inptr, NULL, folder, cis)))
return NULL;
-
+
child->parent = ci;
tail->next = child;
tail = child;
} while (*inptr == '(');
-
+
if (*inptr++ != ' ')
return NULL;
-
+
if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) {
subtype = imap_parse_string (&inptr, &len);
} else {
subtype = NULL;
inptr += 3;
}
-
+
ctype = camel_content_type_new ("multipart", subtype ? subtype : "mixed");
g_free (subtype);
-
+
if (*inptr++ != ')') {
camel_content_type_unref (ctype);
return NULL;
}
-
+
ci->type = ctype;
ci->childs = children;
} else {
} else {
return NULL;
}
-
+
if (*inptr++ != ' ') {
g_free (type);
return NULL;
}
-
+
if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) {
subtype = imap_parse_string (&inptr, &len);
if (inptr == NULL) {
subtype = NULL;
inptr += 3;
}
-
+
camel_strdown (type);
camel_strdown (subtype);
ctype = camel_content_type_new (type, subtype);
g_free (subtype);
g_free (type);
-
+
if (*inptr++ != ' ')
goto exception;
-
+
/* content-type params */
if (parse_params (&inptr, ctype) == -1)
goto exception;
-
+
if (*inptr++ != ' ')
goto exception;
-
+
/* content-id */
if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) {
id = imap_parse_string (&inptr, &len);
goto exception;
} else
inptr += 3;
-
+
if (*inptr++ != ' ')
goto exception;
-
+
/* description */
if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) {
description = imap_parse_string (&inptr, &len);
goto exception;
} else
inptr += 3;
-
+
if (*inptr++ != ' ')
goto exception;
-
+
/* encoding */
if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) {
encoding = imap_parse_string (&inptr, &len);
goto exception;
} else
inptr += 3;
-
+
if (*inptr++ != ' ')
goto exception;
-
+
/* size */
size = strtoul ((const char *) inptr, &p, 10);
goto exception;
inptr = (const unsigned char *) p;
-
+
if (camel_content_type_is (ctype, "message", "rfc822")) {
/* body_type_msg */
if (*inptr++ != ' ')
goto exception;
-
+
/* envelope */
imap_skip_list (&inptr);
-
+
if (!inptr || *inptr++ != ' ')
goto exception;
-
+
/* body */
if (!(child = imap_body_decode (&inptr, NULL, folder, cis)))
goto exception;
child->parent = ci;
-
+
if (!inptr || *inptr++ != ' ')
goto exception;
-
+
/* lines */
strtoul ((const char *) inptr, &p, 10);
inptr = (const unsigned char *) p;
} else if (camel_content_type_is (ctype, "text", "*")) {
if (!inptr || *inptr++ != ' ')
goto exception;
-
+
/* lines */
strtoul ((const char *) inptr, &p, 10);
inptr = (const unsigned char *) p;
} else {
/* body_type_basic */
}
-
+
if (!inptr || *inptr++ != ')')
goto exception;
-
+
ci->type = ctype;
ci->id = id;
ci->description = description;
ci->size = size;
ci->childs = child;
}
-
+
*in = inptr;
-
+
return ci;
-
+
exception:
-
+
camel_content_type_unref (ctype);
g_free (id);
g_free (description);
g_free (encoding);
-
+
return NULL;
}
CamelMessageContentInfo *child;
GPtrArray *children;
int i;
-
+
if (!inptr || *inptr != '(') {
*body_p = NULL;
return;
}
-
+
children = g_ptr_array_new ();
-
+
if (!(imap_body_decode (&inptr, ci, folder, children))) {
for (i = 0; i < children->len; i++) {
child = children->pdata[i];
-
+
/* content_info_free will free all the child
* nodes, but we don't want that. */
child->next = NULL;
child->parent = NULL;
child->childs = NULL;
-
+
camel_folder_summary_content_info_free (folder->summary, child);
}
*body_p = NULL;
} else {
*body_p = inptr;
}
-
+
g_ptr_array_free (children, TRUE);
}
const char *p;
char *quoted, *q;
int len;
-
+
g_assert (strchr (str, '\r') == NULL);
-
+
len = strlen (str);
p = str;
while ((p = strpbrk (p, "\"\\"))) {
len++;
p++;
}
-
+
quoted = q = g_malloc (len + 3);
*q++ = '"';
for (p = str; *p; ) {
}
*q++ = '"';
*q = '\0';
-
+
return quoted;
}
{
CamelMessageInfo *info;
unsigned long uid;
-
+
info = camel_folder_summary_index (summary, index);
uid = strtoul (camel_message_info_uid (info), NULL, 10);
camel_message_info_free(info);
* *not* included in the returned set string.
*
* Note: @uids MUST be in sorted order for this code to work properly.
- *
+ *
* Return value: the set, which the caller must free with g_free()
**/
char *
int si, scount;
GString *gset;
char *set;
-
+
g_return_val_if_fail (uids->len > uid, NULL);
-
+
gset = g_string_new (uids->pdata[uid]);
last_uid = strtoul (uids->pdata[uid], NULL, 10);
next_summary_uid = 0;
scount = camel_folder_summary_count (summary);
-
+
for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) {
/* Find the next UID in the summary after the one we
* just wrote out.
next_summary_uid = get_summary_uid_numeric (summary, si);
if (last_uid >= next_summary_uid)
next_summary_uid = (unsigned long) -1;
-
+
/* Now get the next UID from @uids */
this_uid = strtoul (uids->pdata[uid], NULL, 10);
if (this_uid == next_summary_uid || this_uid == last_uid + 1)
}
g_string_append_printf (gset, ",%lu", this_uid);
}
-
+
last_uid = this_uid;
}
-
+
if (range)
g_string_append_printf (gset, ":%lu", last_uid);
-
+
*lastuid = uid;
-
+
set = gset->str;
g_string_free (gset, FALSE);
-
+
return set;
}
char *p, *q;
unsigned long uid, suid;
int si, scount;
-
+
arr = g_ptr_array_new ();
scount = camel_folder_summary_count (summary);
-
+
p = (char *)uids;
si = 0;
do {
if (p == q)
goto lose;
g_ptr_array_add (arr, g_strndup (p, q - p));
-
+
if (*q == ':') {
/* Find the summary entry for the UID after the one
* we just saw.
}
if (si >= scount)
suid = uid + 1;
-
+
uid = strtoul (q + 1, &p, 10);
if (p == q + 1)
goto lose;
-
+
/* Add each summary UID until we find one
* larger than the end of the range
*/
} else
p = q;
} while (*p++ == ',');
-
+
return arr;
-
+
lose:
g_warning ("Invalid uid set %s", uids);
imap_uid_array_free (arr);
imap_uid_array_free (GPtrArray *arr)
{
int i;
-
+
for (i = 0; i < arr->len; i++)
g_free (arr->pdata[i]);
g_ptr_array_free (arr, TRUE);
imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix)
{
size_t len;
-
+
len = strlen (prefix);
if (len == 0 || prefix[len - 1] == imap_store->dir_sep)
return g_strdup_printf ("%s%s", prefix, suffix);
buf = g_alloca (inlen + 1);
memcpy (buf, in, inlen);
buf[inlen] = 0;
-
+
return camel_utf8_utf7 (buf);
}
imap_mailbox_decode (const unsigned char *in, size_t inlen)
{
char *buf;
-
+
buf = g_alloca (inlen + 1);
memcpy (buf, in, inlen);
buf[inlen] = 0;
-
+
return camel_utf7_utf8 (buf);
}
g_free (imap_wrapper->uid);
if (imap_wrapper->part)
g_free (imap_wrapper->part_spec);
-
+
g_mutex_free (imap_wrapper->priv->lock);
-
+
g_free (imap_wrapper->priv);
}
imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper, CamelStream *stream)
{
CamelDataWrapper *data_wrapper = (CamelDataWrapper *) imap_wrapper;
-
+
camel_object_ref (stream);
data_wrapper->stream = stream;
data_wrapper->offline = FALSE;
-
+
camel_object_unref (imap_wrapper->folder);
imap_wrapper->folder = NULL;
g_free (imap_wrapper->uid);
write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
{
CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper);
-
+
CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock);
if (data_wrapper->offline) {
CamelStream *datastream;
-
+
datastream = camel_imap_folder_fetch_data (
imap_wrapper->folder, imap_wrapper->uid,
imap_wrapper->part_spec, FALSE, NULL);
#endif
return -1;
}
-
+
imap_wrapper_hydrate (imap_wrapper, datastream);
camel_object_unref (datastream);
}
CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
-
+
return parent_class->write_to_stream (data_wrapper, stream);
}
(CamelObjectInitFunc) object_init,
(CamelObjectFinalizeFunc) object_finalise);
}
-
+
return type;
}
driver = CAMEL_IMAPP_DRIVER (camel_object_new (CAMEL_IMAPP_DRIVER_TYPE));
ie = driver->engine = camel_imapp_engine_new(stream);
-
+
camel_imapp_engine_add_handler(ie, "FETCH", (CamelIMAPPEngineFunc)driver_resp_fetch, driver);
camel_imapp_engine_add_handler(ie, "EXPUNGE", (CamelIMAPPEngineFunc)driver_resp_expunge, driver);
camel_imapp_engine_add_handler(ie, "EXISTS", (CamelIMAPPEngineFunc)driver_resp_exists, driver);
}
summary = ((CamelFolder *)folder)->summary;
-
+
ic = camel_imapp_engine_command_new(id->engine, "SELECT", NULL, "SELECT %t", folder->raw_name);
camel_imapp_engine_command_queue(id->engine, ic);
while (camel_imapp_engine_iterate(id->engine, ic)>0)
count = camel_folder_summary_count(summary);
for (j=0;j<sizeof(flag_table)/sizeof(flag_table[0]);j++) {
int flush;
-
+
if ((orset & flag_table[j].flag) == 0)
continue;
|| (!on && (((flags ^ sflags) & ~flags) & flag_table[j].flag))) {
if (ic == NULL)
ic = camel_imapp_engine_command_new(id->engine, "STORE", NULL, "UID STORE ");
- flush = imapp_uidset_add(&ss, ic, camel_message_info_uid(info));
+ flush = imapp_uidset_add(&ss, ic, camel_message_info_uid(info));
}
camel_message_info_free((CamelMessageInfo *)info);
}
if (id->list_commands) {
GSList *top = id->list_commands;
-
+
id->list_commands = top->next;
ic = top->data;
g_slist_free_1(top);
if (depth < 10
&& (linfo->name[0] == 0 || linfo->name[strlen(linfo->name)-1] != c)) {
CamelIMAPPCommand *ic;
-
+
ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %t%c%%", linfo->name, c);
id->list_commands = g_slist_prepend(id->list_commands, ic);
camel_imapp_engine_command_queue(id->engine, ic);
case IMAP_UIDVALIDITY:
sdata->uidvalidity = sinfo->u.uidvalidity;
break;
-#if 0
+#if 0
/* not defined yet ... */
case IMAP_UIDNEXT:
printf("got uidnext for folder: %d\n", sinfo->u.uidnext);
break;
-#endif
+#endif
case IMAP_UNSEEN:
sdata->unseen = sinfo->u.unseen;
break;
info->info.uid = g_strdup(uidtmp);
printf("inserting empty uid %s\n", uidtmp);
}
-
+
camel_folder_summary_add(summary, (CamelMessageInfo *)info);
}
info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, id-1);
#include "camel-imapp-stream.h"
#include "camel-imapp-utils.h"
-#define e(x)
+#define e(x)
#define c(x) /* command build debug */
static void imap_engine_command_addv(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, va_list ap);
(CamelObjectInitFunc) object_init,
(CamelObjectFinalizeFunc) object_finalise);
}
-
+
return type;
}
struct _handler *h;
const unsigned char *p;
unsigned char *o, c;
-
+
h = g_malloc0(sizeof(*h) + strlen(response));
h->func = func;
h->data = data;
int tok;
struct _handler *h;
struct _status_info *sinfo;
-
+
e(printf("got untagged response\n"));
id = 0;
tok = camel_imapp_stream_token(imap->stream, &token, &len);
if (imap->select_response)
imap->select_response->uidvalidity = sinfo->u.uidvalidity;
break;
-#if 0
+#if 0
/* not defined yet ... */
case IMAP_UIDNEXT:
printf("got uidnext for folder: %d\n", sinfo->u.uidnext);
break;
-#endif
+#endif
case IMAP_UNSEEN:
if (imap->select_response)
imap->select_response->unseen = sinfo->u.unseen;
{
CamelIMAPPCommand *ic;
CamelIMAPPCommandPart *cp;
-
+
printf("got continuation response\n");
ic = imap->literal;
char *resp;
unsigned char *token;
int tok, len;
-
+
tok = camel_imapp_stream_token(imap->stream, &token, &len);
resp = camel_sasl_challenge_base64((CamelSasl *)cp->ob, token, ex);
if (camel_exception_is_set(ex))
camel_exception_throw_ex(ex);
camel_exception_free(ex);
-
+
printf("got auth continuation, feeding token '%s' back to auth mech\n", resp);
-
+
camel_stream_write((CamelStream *)imap->stream, resp, strlen(resp));
-
+
/* we want to keep getting called until we get a status reponse from the server
ignore what sasl tells us */
imap->literal = ic;
-
+
break; }
default:
/* should we just ignore? */
camel_exception_throw(1, "continuation response for non-continuation request");
}
-
+
camel_imapp_engine_skip(imap);
-
+
cp = cp->next;
if (cp->next) {
ic->current = cp;
printf("%p: queueing continuation\n", ic);
camel_stream_printf((CamelStream *)imap->stream, "\r\n");
}
-
+
if (imap->literal == NULL) {
ic = (CamelIMAPPCommand *)e_dlist_remhead(&imap->queue);
if (ic) {
} else {
camel_exception_throw(1, "got response tag unexpectedly: %s", token);
}
-
+
if (imap->literal != NULL) {
printf("Warning: continuation command '%s' finished with outstanding continuation\n", imap->literal->name);
ic = imap->literal;
e_dlist_addtail(&imap->done, (EDListNode *)ic);
imap->literal = NULL;
}
-
+
ic = (CamelIMAPPCommand *)e_dlist_remhead(&imap->queue);
if (ic) {
printf("found outstanding op, queueing\n");
camel_imapp_engine_command_queue(imap, ic);
}
-
+
return 1;
}
CamelIMAPPCommandPart *cp;
CamelStreamNull *null;
unsigned int ob_size = 0;
-
+
switch(type & CAMEL_IMAPP_COMMAND_MASK) {
case CAMEL_IMAPP_COMMAND_DATAWRAPPER:
case CAMEL_IMAPP_COMMAND_STREAM:
c(printf("command has %d parts\n", len(&ic->parts)));
if (ic->mem->buffer->len > 0)
imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_SIMPLE, NULL);
-
+
c(printf("command has %d parts\n", len(&ic->parts)));
camel_object_unref((CamelObject *)ic->mem);
/* see if we need to pre-queue a select command to select the right folder first */
if (ic->select && (imap->last_select == NULL || strcmp(ic->select, imap->last_select) != 0)) {
CamelIMAPPCommand *select;
-
+
/* of course ... we can't do anything like store/search if we have to select
first, because it'll mess up all the sequence numbers ... hrm ... bugger */
camel_imapp_engine_command_queue(imap, select);
/* how does it get freed? handle inside engine? */
}
-
+
/* first, check if command can be sent yet ... queue if not */
if (imap->literal != NULL) {
printf("%p: queueing while literal active\n", ic);
guint32 recent;
guint32 uidvalidity;
guint32 unseen;
- guint32 permanentflags;
+ guint32 permanentflags;
};
enum {
#include "camel-imapp-exception.h"
#include "camel-imapp-stream.h"
-#define t(x)
+#define t(x)
#define io(x) x
static CamelObjectClass *parent_class = NULL;
}
is->literal -= max;
-
+
return max;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-folder.c : class for a imap folder */
-/*
+/*
* Authors: Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
imap_folder_class_init (CamelIMAPPFolderClass *camel_imapp_folder_class)
{
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_imapp_folder_class);
-
+
parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type());
-
+
/* virtual method overload */
camel_folder_class->refresh_info = imap_refresh_info;
camel_folder_class->sync = imap_sync;
-
+
camel_folder_class->get_message = imap_get_message;
}
folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY |
CAMEL_FOLDER_HAS_SEARCH_CAPABILITY);
-
+
folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT |
CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER;
camel_imapp_folder_get_type (void)
{
static CamelType camel_imapp_folder_type = CAMEL_INVALID_TYPE;
-
+
if (!camel_imapp_folder_type) {
camel_imapp_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelIMAPPFolder",
sizeof (CamelIMAPPFolder),
imap_folder_init,
(CamelObjectFinalizeFunc) imap_finalize);
}
-
+
return camel_imapp_folder_type;
}
char *root;
d(printf("opening imap folder '%s'\n", path));
-
+
folder = CAMEL_FOLDER (camel_object_new (CAMEL_IMAPP_FOLDER_TYPE));
camel_folder_construct(folder, store, path, path);
}
#endif
-static void
+static void
imap_refresh_info (CamelFolder *folder, CamelException *ex)
{
printf("imapp refresh info?\n");
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-folder.h : Class for a IMAP folder */
-/*
+/*
* Authors: Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-provider.c: pop3 provider registration code */
-/*
+/*
* Authors :
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
static CamelProvider imapp_provider = {
"imapp",
-
+
N_("IMAP+"),
-
+
N_("Experimental IMAP 4(.1) client\n"
"This is untested and unsupported code, you want to use plain imap instead.\n\n"
" !!! DO NOT USE THIS FOR PRODUCTION EMAIL !!!\n"),
"mail",
-
+
CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL,
-
+
CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,
-
+
imapp_conf_entries,
-
+
/* ... */
};
CamelServiceAuthType camel_imapp_password_authtype = {
N_("Password"),
-
+
N_("This option will connect to the IMAP server using a "
"plaintext password."),
-
+
"",
TRUE
};
camel_imapp_store_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
camel_imapp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type();
type = camel_type_register((CamelType)camel_imapp_store_summary_parent, "CamelIMAPPStoreSummary",
(CamelObjectInitFunc) camel_imapp_store_summary_init,
(CamelObjectFinalizeFunc) camel_imapp_store_summary_finalise);
}
-
+
return type;
}
* camel_imapp_store_summary_new:
*
* Create a new CamelIMAPPStoreSummary object.
- *
+ *
* Return value: A new CamelIMAPPStoreSummary widget.
**/
CamelIMAPPStoreSummary *
/**
* camel_imapp_store_summary_full_name:
- * @s:
- * @path:
- *
+ * @s:
+ * @path:
+ *
* Retrieve a summary item by full name.
*
* A referenced to the summary item is returned, which may be
* ref'd or free'd as appropriate.
- *
+ *
* Return value: The summary item, or NULL if the @full_name name
* is not available.
* It must be freed using camel_store_summary_info_free().
} else {
if (full_name[len] == ns->sep)
len++;
-
+
prefix = camel_imapp_store_summary_full_to_path(s, full_name+len, ns->sep);
if (*ns->path) {
pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix);
if (camel_imapp_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1
|| camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_STORE_SUMMARY_VERSION) == -1
|| camel_file_util_encode_fixed_int32(out, is->capabilities) == -1
- || camel_file_util_encode_fixed_int32(out, count) == -1)
+ || camel_file_util_encode_fixed_int32(out, count) == -1)
return -1;
if (is->namespace && namespace_save(s, out, is->namespace) == -1)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-store.c : class for a imap store */
-/*
+/*
* Authors: Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_imapp_store_class);
parent_class = CAMEL_STORE_CLASS(camel_type_get_global_classfuncs(camel_store_get_type()));
-
+
/* virtual method overload */
camel_service_class->construct = imap_construct;
/*camel_service_class->get_name = imap_get_name;*/
CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
if (camel_exception_is_set(ex))
return;
-
+
CAMEL_TRY {
store->summary = camel_imapp_store_summary_new();
root = camel_session_get_storage_path(service->session, service, ex);
port = "143";
}
-#ifdef HAVE_SSL
+#ifdef HAVE_SSL
if (camel_url_get_param (service->url, "use_ssl")) {
if (try_starttls)
tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS);
} else {
tcp_stream = camel_tcp_stream_raw_new ();
}
-#else
+#else
tcp_stream = camel_tcp_stream_raw_new ();
#endif /* HAVE_SSL */
if (ex->id)
camel_exception_throw_ex(ex);
-
+
ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai);
camel_freeaddrinfo(ai);
if (ret == -1) {
#ifdef HAVE_SSL
const char *use_ssl;
int i, ssl_mode;
-
+
use_ssl = camel_url_get_param (service->url, "use_ssl");
if (use_ssl) {
for (i = 0; ssl_options[i].value; i++)
ssl_mode = ssl_options[i].mode;
} else
ssl_mode = USE_SSL_NEVER;
-
+
if (ssl_mode == USE_SSL_ALWAYS) {
/* First try the ssl port */
if (!connect_to_server (service, ssl_mode, FALSE, ex)) {
return FALSE;
}
}
-
+
return TRUE;
} else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) {
/* If the server supports STARTTLS, use it */
store_get_login(struct _CamelIMAPPDriver *driver, char **login, char **pass, CamelIMAPPStore *store)
{
store_get_pass(store);
-
+
*login = g_strdup(((CamelService *)store)->url->user);
*pass = g_strdup(((CamelService *)store)->url->passwd);
}
if (store->cache == NULL) {
char *root;
-
+
root = camel_session_get_storage_path(service->session, service, ex);
if (root) {
store->cache = camel_data_cache_new(root, 0, ex);
CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service);
/* FIXME: logout */
-
+
if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex))
return FALSE;
camel_object_unref(store->driver);
store->driver = NULL;
}
-
+
return TRUE;
}
folder_info_dump(fi->child, depth+2);
fi = fi->next;
}
-
+
}
static CamelFolderInfo *
} CAMEL_CATCH (e) {
camel_exception_xfer(ex, e);
} CAMEL_DONE;
-
+
camel_imapp_engine_command_free(istore->driver->engine, ic);
printf("got folder list:\n");
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-imap-store.h : class for an imap store */
-/*
+/*
* Authors: Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#include "camel-imapp-exception.h"
#include "camel-imapp-stream.h"
-#define t(x)
+#define t(x)
#define io(x) x
static void setup_table(void);
}
is->literal -= max;
-
+
return max;
}
/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#define imap_is_atom(c) ((imap_specials[(c)&0xff] & 0x01) != 0)
}
return 0;
-}
+}
static int
summary_header_save(CamelFolderSummary *s, FILE *out)
struct _imap_keyword { char *name; camel_imapp_id_t id; };
/*
gperf input file
- best hash generated using: gperf -o -s-2 -k1,'$' -t -H imap_hash -N imap_tokenise -L ANSI-C
+ best hash generated using: gperf -o -s-2 -k1,'$' -t -H imap_hash -N imap_tokenise -L ANSI-C
*/
#define TOTAL_KEYWORDS 23
imap_free_body(list);
list = next;
}
-
+
if (cinfo->type)
camel_content_type_unref(cinfo->type);
g_free(cinfo->id);
if (tok == ')')
break;
camel_imapp_stream_ungettoken(is, tok, token, len);
-
+
camel_imapp_stream_astring(is, &token);
param = alloca(strlen(token)+1);
strcpy(param, token);
dinfo->refcount = 1;
/* should be string */
camel_imapp_stream_astring(is, &token);
-
+
dinfo->disposition = g_strdup(token);
imap_parse_param_list(is, &dinfo->params);
case IMAP_TOK_TOKEN:
default:
camel_exception_throw(1, "body_fld_disp: expecting nil or list");
}
-
+
p(printf("body_fld_lang\n"));
/* body_fld_lang ::= nstring / "(" 1#string ")" */
-
+
/* we just drop the lang string/list, save it somewhere? */
-
+
tok = camel_imapp_stream_token(is, &token, &len);
switch (tok) {
case '(':
{
unsigned char *token, *type;
struct _CamelMessageContentInfo *cinfo;
-
+
/* body_fields ::= body_fld_param SPACE body_fld_id SPACE
body_fld_desc SPACE body_fld_enc SPACE
body_fld_octets */
camel_imapp_stream_astring(is, &token);
cinfo->type = camel_content_type_new(type, token);
imap_parse_param_list(is, &cinfo->type->params);
-
+
/* body_fld_id ::= nstring */
camel_imapp_stream_nstring(is, &token);
cinfo->id = g_strdup(token);
-
+
/* body_fld_desc ::= nstring */
camel_imapp_stream_nstring(is, &token);
cinfo->description = g_strdup(token);
-
+
/* body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
"QUOTED-PRINTABLE") <">) / string */
camel_imapp_stream_astring(is, &token);
cinfo->encoding = g_strdup(token);
-
+
/* body_fld_octets ::= number */
cinfo->size = camel_imapp_stream_number(is);
} CAMEL_CATCH(ex) {
return (CamelMessageInfo *)minfo;
}
-
+
struct _CamelMessageContentInfo *
imap_parse_body(CamelIMAPPStream *is)
{
} else {
/* body_type_1part ::= (body_type_basic / body_type_msg / body_type_text)
[SPACE body_ext_1part]
-
+
body_type_basic ::= media_basic SPACE body_fields
body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines
body_type_msg ::= media_message SPACE body_fields SPACE envelope
camel_imapp_stream_ungettoken(is, tok, token, len);
}
camel_imapp_stream_nstring_stream(is, &finfo->body);
- finfo->got |= FETCH_BODY;
+ finfo->got |= FETCH_BODY;
} else {
camel_exception_throw(1, "unknown body response");
}
sinfo->condition = IMAP_UNKNOWN;
printf("Got unknown response code: %s: ignored\n", token);
}
-
+
/* ignore anything we dont know about */
do {
tok = camel_imapp_stream_token(is, &token, &len);
struct _list_info * volatile linfo;
linfo = g_malloc0(sizeof(*linfo));
-
+
CAMEL_TRY {
/* mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
"\Noselect" / "\Unmarked" / flag_extension) ")"
/* ********************************************************************** */
-/* should this just return a FolderInfo?
+/* should this just return a FolderInfo?
should this just return the name & flags & separator by reference? */
struct _list_info {
guint32 flags:24;
g_free(local_folder->index_path);
camel_folder_change_info_free(local_folder->changes);
-
+
g_mutex_free(local_folder->priv->search_lock);
-
+
g_free(local_folder->priv);
}
int forceindex, len;
CamelURL *url;
CamelLocalStore *ls = (CamelLocalStore *)parent_store;
-
+
folder = (CamelFolder *)lf;
name = g_path_get_basename(full_name);
((CamelService *)folder->parent_store)->url->protocol);
else
/* a full path + protocol */
- folder->description = g_strdup_printf(_("%s (%s)"), path,
+ folder->description = g_strdup_printf(_("%s (%s)"), path,
((CamelService *)folder->parent_store)->url->protocol);
}
*arg->ca_str = folder->description;
local_delete(CamelFolder *folder)
{
CamelLocalFolder *lf = (CamelLocalFolder *)folder;
-
+
if (lf->index)
camel_index_delete(lf->index);
*
* Copyright (C) 1999 Ximian (www.ximian.com/).
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelFolderClass parent_class;
- /* Virtual methods */
-
+ /* Virtual methods */
+
/* summary factory, only used at init */
CamelLocalSummary *(*create_summary)(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index);
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
+ *
* Authors: Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2000 Ximian (www.ximian.com).
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{
const CamelURL *u = v;
guint hash = 0;
-
+
#define ADD_HASH(s) if (s) hash ^= g_str_hash (s);
-
+
ADD_HASH (u->protocol);
ADD_HASH (u->user);
ADD_HASH (u->authmech);
ADD_HASH (u->path);
ADD_HASH (u->query);
hash ^= u->port;
-
+
return hash;
}
else
return FALSE;
}
-
+
if (s2 == NULL)
return FALSE;
*
* Copyright (C) 2000 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_local_store_class);
CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_local_store_class);
-
+
parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ()));
/* virtual method overload */
camel_local_store_get_type (void)
{
static CamelType camel_local_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_local_store_type == CAMEL_INVALID_TYPE) {
camel_local_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelLocalStore",
sizeof (CamelLocalStore),
NULL,
(CamelObjectFinalizeFunc) camel_local_store_finalize);
}
-
+
return camel_local_store_type;
}
strcpy(path, ((CamelLocalStore *)store)->toplevel_dir);
if (G_IS_DIR_SEPARATOR(path[len-1]))
path[len-1] = '\0';
-
+
if (!g_path_is_absolute(path)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Store root %s is not an absolute path"), path);
path, g_strerror (errno));
return NULL;
}
-
+
/* need to create the dir heirarchy */
if (g_mkdir_with_parents (path, 0777) == -1 && errno != EEXIST) {
camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
path, g_strerror (errno));
return NULL;
}
-
+
return (CamelFolder *) 0xdeadbeef;
}
CamelFolder *lf;
char *name;
char *str;
-
+
/* remove metadata only */
name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name);
str = g_strdup_printf("%s.ev-summary", name);
} else {
camel_exception_clear (&lex);
}
-
+
if (str == NULL)
str = g_strdup_printf ("%s.cmeta", name);
-
+
if (g_unlink (str) == -1 && errno != ENOENT) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder meta file `%s': %s"),
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-mbox-store.h : class for an mbox store */
-/*
+/*
*
* Copyright (C) 2000 Ximian, Inc. <bertrand@helixcode.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
G_BEGIN_DECLS
typedef struct {
- CamelStore parent_object;
+ CamelStore parent_object;
char *toplevel_dir;
} CamelLocalStore;
camel_local_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_folder_summary_get_type(), "CamelLocalSummary",
sizeof (CamelLocalSummary),
(CamelObjectInitFunc) camel_local_summary_init,
(CamelObjectFinalizeFunc) camel_local_summary_finalise);
}
-
+
return type;
}
camel_local_summary_class_init(CamelLocalSummaryClass *klass)
{
CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass;
-
+
camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
sklass->summary_header_load = summary_header_load;
}
printf("\nMemory used by summary:\n\n");
- printf("Total of %d messages\n", camel_folder_summary_count(s));
+ printf("Total of %d messages\n", camel_folder_summary_count(s));
printf("Total: %d bytes (ave %f)\n", stats.citotal + stats.mitotal,
(double)(stats.citotal+stats.mitotal)/(double)camel_folder_summary_count(s));
printf("Message Info: %d (ave %f)\n", stats.mitotal, (double)stats.mitotal/(double)stats.micount);
/**
* camel_local_summary_write_headers:
- * @fd:
- * @header:
- * @xevline:
+ * @fd:
+ * @header:
+ * @xevline:
* @status:
* @xstatus:
- *
+ *
* Write a bunch of headers to the file @fd. IF xevline is non NULL, then
* an X-Evolution header line is created at the end of all of the headers.
* If @status is non NULL, then a Status header line is also written.
* The headers written are termianted with a blank line.
- *
+ *
* Return value: -1 on error, otherwise the number of bytes written.
**/
int
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not save summary: %s: %s"),
cls->folder_path, g_strerror (errno));
-
+
g_warning ("Could not save summary for %s: %s", cls->folder_path, strerror (errno));
}
char *xev;
d(printf("Adding message to summary\n"));
-
+
mi = (CamelLocalMessageInfo *)camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg);
if (mi) {
d(printf("Added, uid = %s\n", mi->uid));
camel_message_info_set_user_flag((CamelMessageInfo *)mi, flag->name, TRUE);
flag = flag->next;
}
-
+
while (tag) {
camel_message_info_set_user_tag((CamelMessageInfo *)mi, tag->name, tag->value);
tag = tag->next;
if (flag || tag) {
val = g_string_new ("");
-
+
if (flag) {
while (flag) {
g_string_append (val, flag->name);
}
ret = out->str;
g_string_free (out, FALSE);
-
+
return ret;
}
if (mi == NULL)
return 0;
- /* check for additional data */
+ /* check for additional data */
header = strchr(xev, ';');
if (header) {
params = camel_header_param_list_decode(header+1);
/* shortcut, no need to look it up in the index library */
doindex = TRUE;
}
-
+
if (cls->index
&& (doindex
|| cls->index_force
camel_folder_summary_set_index(s, NULL);
}
}
-
+
return (CamelMessageInfo *)mi;
}
guint32 version; /* file version being loaded */
char *folder_path; /* name of matching folder */
-
+
CamelIndex *index;
unsigned int index_force:1; /* do we force index during creation? */
unsigned int check_force:1; /* does a check force a full check? */
*
* Copyright (C) 1999, 2003 Ximian Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
(CamelObjectInitFunc) maildir_init,
(CamelObjectFinalizeFunc) maildir_finalize);
}
-
+
return camel_maildir_folder_type;
}
CamelMessageInfo *mi;
CamelMaildirMessageInfo *mdi;
char *name, *dest = NULL;
-
+
d(printf("Appending message\n"));
/* add it to the summary/assign the uid, etc */
mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex);
if (camel_exception_is_set (ex))
return;
-
+
mdi = (CamelMaildirMessageInfo *)mi;
d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename));
output_stream = camel_stream_fs_new_with_name (name, O_WRONLY|O_CREAT, 0600);
if (output_stream == NULL)
goto fail_write;
-
+
if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1
|| camel_stream_close (output_stream) == -1)
goto fail_write;
-
+
/* now move from tmp to cur (bypass new, does it matter?) */
dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi));
if (rename (name, dest) == -1)
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot append message to maildir folder: %s: %s"),
name, g_strerror (errno));
-
+
if (output_stream) {
camel_object_unref (CAMEL_OBJECT (output_stream));
unlink (name);
}
-
+
g_free (name);
g_free (dest);
}
*
* Copyright (C) 1999 Ximian Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelLocalFolderClass parent_class;
-
+
/* Virtual methods */
-
+
} CamelMaildirFolderClass;
/* public methods */
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
static gboolean scan_equal(const void *a, const void *b)
{
const struct _scan_node *v1 = a, *v2 = b;
-
+
return v1->inode == v2->inode && v1->dnode == v2->dnode;
}
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelLocalStore parent_object;
-
+
} CamelMaildirStore;
typedef struct {
CamelLocalStoreClass parent_class;
-
+
} CamelMaildirStoreClass;
/* public methods */
camel_maildir_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_local_summary_get_type (), "CamelMaildirSummary",
sizeof(CamelMaildirSummary),
(CamelObjectInitFunc)camel_maildir_summary_init,
(CamelObjectFinalizeFunc)camel_maildir_summary_finalise);
}
-
+
return type;
}
* @index: Index if one is reqiured.
*
* Create a new CamelMaildirSummary object.
- *
+ *
* Return value: A new #CamelMaildirSummary object.
**/
CamelMaildirSummary
}
*p = 0;
-
+
return g_strdup(buf);
}
while ( (d = readdir(dir)) ) {
if (d->d_name[0] == '.')
continue;
-
+
/* map the filename -> uid */
uid = strchr(d->d_name, ':');
if (uid) {
uid = g_strndup(d->d_name, uid-d->d_name);
else
uid = g_strdup(d->d_name);
-
+
info = g_hash_table_lookup(left, uid);
if (info) {
camel_message_info_free(info);
#else
# ifdef DOEPOOLV
info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name, FALSE);
-# else
+# else
g_free(mdi->filename);
mdi->filename = g_strdup(d->d_name);
# endif
*
* Copyright (C) 1999, 2003 Ximian Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
filter_from = (CamelMimeFilter *) camel_mime_filter_from_new();
camel_stream_filter_add((CamelStreamFilter *) filter_stream, filter_from);
camel_object_unref (filter_from);
-
+
if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, filter_stream) == -1 ||
camel_stream_write (filter_stream, "\n", 1) == -1 ||
camel_stream_flush (filter_stream) == -1)
goto fail_write;
-
+
/* filter stream ref's the output stream itself, so we need to unref it too */
camel_object_unref (filter_stream);
camel_object_unref (output_stream);
g_free(fromline);
-
+
/* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */
/* the stat really shouldn't fail, we just wrote to it */
if (g_stat (lf->folder_path, &st) == 0) {
((CamelFolderSummary *) mbs)->time = st.st_mtime;
mbs->folder_size = st.st_size;
}
-
+
/* unlock as soon as we can */
camel_local_folder_unlock(lf);
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot append message to mbox file: %s: %s"),
lf->folder_path, g_strerror (errno));
-
+
if (output_stream) {
/* reset the file to original size */
do {
retval = ftruncate (((CamelStreamFs *) output_stream)->fd, mbs->folder_size);
} while (retval == -1 && errno == EINTR);
-
+
camel_object_unref (output_stream);
}
-
+
if (filter_stream)
camel_object_unref (filter_stream);
-
+
g_free(fromline);
-
+
/* remove the summary info so we are not out-of-sync with the mbox */
camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (mbs), camel_message_info_uid (mi));
-
+
/* and tell the summary it's up-to-date */
if (g_stat (lf->folder_path, &st) == 0) {
((CamelFolderSummary *) mbs)->time = st.st_mtime;
mbs->folder_size = st.st_size;
}
-
+
fail:
/* make sure we unlock the folder - before we start triggering events into appland */
camel_local_folder_unlock(lf);
camel_local_folder_unlock(lf);
return NULL;
}
-
+
retry:
/* get the message summary info */
info = (CamelMboxMessageInfo *) camel_folder_summary_uid(folder->summary, uid);
frompos = info->frompos;
camel_message_info_free((CamelMessageInfo *)info);
-
+
/* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache
the whole message in memory if the stream is non-seekable (which it is when built from a parser
with no stream). This means we dont have to lock the mbox for the life of the message, but only
_("The folder appears to be irrecoverably corrupted."));
goto fail;
}
-
+
message = camel_mime_message_new();
if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) {
camel_exception_setv(ex, errno==EINTR?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_SYSTEM,
if (parser)
camel_object_unref((CamelObject *)parser);
-
+
/* use the opportunity to notify of changes (particularly if we had a rebuild) */
if (camel_folder_change_info_changed(lf->changes)) {
camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes);
camel_folder_change_info_clear(lf->changes);
}
-
+
return message;
}
*
* Copyright (C) 1999 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelLocalFolderClass parent_class;
- /* Virtual methods */
-
+ /* Virtual methods */
+
} CamelMboxFolderClass;
/* public methods */
*
* Copyright(C) 2000 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
#include "camel-mbox-folder.h"
#include "camel-mbox-store.h"
-#define d(x)
+#define d(x)
static CamelLocalStoreClass *parent_class = NULL;
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mbox_store_class);
parent_class =(CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type());
-
+
/* virtual method overload */
camel_store_class->get_folder = get_folder;
camel_store_class->delete_folder = delete_folder;
camel_store_class->rename_folder = rename_folder;
camel_store_class->create_folder = create_folder;
-
+
camel_store_class->get_folder_info = get_folder_info;
camel_store_class->free_folder_info = camel_store_free_folder_info_full;
camel_mbox_store_get_type(void)
{
static CamelType camel_mbox_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_mbox_store_type == CAMEL_INVALID_TYPE) {
camel_mbox_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMboxStore",
sizeof(CamelMboxStore),
NULL,
NULL);
}
-
+
return camel_mbox_store_type;
}
ignore_file(const char *filename, gboolean sbd)
{
int flen, len, i;
-
+
/* TODO: Should probably just be 1 regex */
flen = strlen(filename);
if (flen > 0 && filename[flen-1] == '~')
if (len < flen && !strcmp(filename + flen - len, extensions[i]))
return TRUE;
}
-
+
if (sbd && flen > 4 && !strcmp(filename + flen - 4, ".sbd"))
return TRUE;
-
+
return FALSE;
}
{
struct stat st;
char *name;
-
+
if (!((CamelStoreClass *) parent_class)->get_folder(store, folder_name, flags, ex))
return NULL;
-
+
name = camel_local_store_get_full_path(store, folder_name);
-
+
if (g_stat(name, &st) == -1) {
char *basename;
char *dirname;
int fd;
-
+
if (errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot get folder `%s': %s"),
g_free(name);
return NULL;
}
-
+
if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Cannot get folder `%s': folder does not exist."),
g_free(name);
return NULL;
}
-
+
/* sanity check the folder name */
basename = g_path_get_basename (folder_name);
-
+
if (basename[0] == '.' || ignore_file (basename, TRUE)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot create a folder by this name."));
return NULL;
}
g_free (basename);
-
+
dirname = g_path_get_dirname(name);
if (g_mkdir_with_parents(dirname, 0777) == -1 && errno != EEXIST) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
g_free(name);
return NULL;
}
-
+
g_free(dirname);
-
+
fd = g_open(name, O_LARGEFILE | O_WRONLY | O_CREAT | O_APPEND | O_BINARY, 0666);
if (fd == -1) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
g_free(name);
return NULL;
}
-
+
g_free(name);
close(fd);
} else if (!S_ISREG(st.st_mode)) {
return NULL;
} else
g_free(name);
-
+
return camel_mbox_folder_new(store, folder_name, flags, ex);
}
CamelFolder *lf;
char *name, *path;
struct stat st;
-
+
name = camel_local_store_get_full_path(store, folder_name);
path = g_strdup_printf("%s.sbd", name);
-
+
if (g_rmdir(path) == -1 && errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s':\n%s"),
g_free(name);
return;
}
-
+
g_free(path);
-
+
if (g_stat(name, &st) == -1) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s':\n%s"),
g_free(name);
return;
}
-
+
if (!S_ISREG(st.st_mode)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("`%s' is not a regular file."), name);
g_free(name);
return;
}
-
+
if (st.st_size != 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_NON_EMPTY,
_("Folder `%s' is not empty. Not deleted."),
g_free(name);
return;
}
-
+
if (g_unlink(name) == -1 && errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not delete folder `%s':\n%s"),
g_free(name);
return;
}
-
+
/* FIXME: we have to do our own meta cleanup here rather than
* calling our parent class' delete_folder() method since our
* naming convention is different. Need to find a way for
g_free(name);
return;
}
-
+
g_free(path);
-
+
path = camel_local_store_get_meta_path(store, folder_name, ".ev-summary-meta");
if (g_unlink(path) == -1 && errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
g_free(name);
return;
}
-
+
g_free(path);
path = camel_local_store_get_meta_path(store, folder_name, ".ibex");
g_free(name);
return;
}
-
+
g_free(path);
path = NULL;
char *path, *name, *dir;
CamelFolder *folder;
struct stat st;
-
+
if (!g_path_is_absolute(toplevel_dir)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Store root %s is not an absolute path"), toplevel_dir);
return NULL;
}
-
+
if (folder_name[0] == '.' || ignore_file(folder_name, TRUE)) {
camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot create a folder by this name."));
return NULL;
}
-
+
if (parent_name && *parent_name)
name = g_strdup_printf("%s/%s", parent_name, folder_name);
else
name = g_strdup(folder_name);
-
+
path = camel_local_store_get_full_path(store, name);
-
+
dir = g_path_get_dirname(path);
if (g_mkdir_with_parents(dir, 0777) == -1 && errno != EEXIST) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create directory `%s': %s."),
dir, g_strerror(errno));
-
+
g_free(path);
g_free(name);
g_free(dir);
-
+
return NULL;
}
-
+
g_free(dir);
-
+
if (g_stat(path, &st) == 0 || errno != ENOENT) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
_("Cannot create folder: %s: %s"),
path, errno ? g_strerror(errno) :
_("Folder already exists"));
-
+
g_free(path);
g_free(name);
-
+
return NULL;
}
-
+
g_free(path);
-
+
folder =((CamelStoreClass *)((CamelObject *) store)->klass)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex);
if (folder) {
camel_object_unref(folder);
info =((CamelStoreClass *)((CamelObject *) store)->klass)->get_folder_info(store, name, 0, ex);
}
-
+
g_free(name);
-
+
return info;
}
struct stat st;
int ret = -1;
int err = 0;
-
+
if (ext != NULL) {
oldpath = camel_local_store_get_meta_path(ls, old_name, ext);
newpath = camel_local_store_get_meta_path(ls, new_name, ext);
oldpath = camel_local_store_get_full_path(ls, old_name);
newpath = camel_local_store_get_full_path(ls, new_name);
}
-
+
if (g_stat(oldpath, &st) == -1) {
if (missingok && errno == ENOENT) {
ret = 0;
ret = -1;
#endif
}
-
+
g_free(oldpath);
g_free(newpath);
-
+
return ret;
}
CamelLocalFolder *folder = NULL;
char *oldibex, *newibex, *newdir;
int errnosav;
-
+
if (new[0] == '.' || ignore_file(new, TRUE)) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("The new folder name is illegal."));
return;
}
-
+
/* try to rollback failures, has obvious races */
-
+
oldibex = camel_local_store_get_meta_path(store, old, ".ibex");
newibex = camel_local_store_get_meta_path(store, new, ".ibex");
-
+
newdir = g_path_get_dirname(newibex);
if (g_mkdir_with_parents(newdir, 0777) == -1) {
if (errno != EEXIST) {
g_free(oldibex);
g_free(newibex);
g_free(newdir);
-
+
return;
}
-
+
g_free(newdir);
newdir = NULL;
}
-
+
folder = camel_object_bag_get(store->folders, old);
if (folder && folder->index) {
if (camel_index_rename(folder->index, newibex) == -1 && errno != ENOENT) {
goto ibex_failed;
}
}
-
+
if (xrename(store, old, new, ".ev-summary", TRUE) == -1) {
errnosav = errno;
goto summary_failed;
errnosav = errno;
goto cmeta_failed;
}
-
+
if (xrename(store, old, new, ".sbd", TRUE) == -1) {
errnosav = errno;
goto subdir_failed;
}
-
+
if (xrename(store, old, new, NULL, FALSE) == -1) {
errnosav = errno;
goto base_failed;
}
-
+
g_free(oldibex);
g_free(newibex);
-
+
if (folder)
camel_object_unref(folder);
-
+
return;
-
+
base_failed:
xrename(store, new, old, ".sbd", TRUE);
subdir_failed:
xrename(store, new, old, ".cmeta", TRUE);
-cmeta_failed:
+cmeta_failed:
xrename(store, new, old, ".ev-summary", TRUE);
xrename(store, new, old, ".ev-summary-meta", TRUE);
summary_failed:
g_rmdir(newdir);
g_free(newdir);
}
-
+
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not rename '%s' to %s: %s"),
old, new, g_strerror(errnosav));
-
+
g_free(newibex);
g_free(oldibex);
-
+
if (folder)
camel_object_unref(folder);
}
inode_hash(const void *d)
{
const struct _inode *v = d;
-
+
return v->inode ^ v->dnode;
}
inode_equal(const void *a, const void *b)
{
const struct _inode *v1 = a, *v2 = b;
-
+
return v1->inode == v2->inode && v1->dnode == v2->dnode;
}
/* This should be fast enough not to have to test for INFO_FAST */
path = camel_local_store_get_meta_path(store, fi->full_name, ".ev-summary");
folderpath = camel_local_store_get_full_path(store, fi->full_name);
-
+
mbs = (CamelMboxSummary *)camel_mbox_summary_new(NULL, path, folderpath, NULL);
if (camel_folder_summary_header_load((CamelFolderSummary *)mbs) != -1) {
fi->unread = ((CamelFolderSummary *)mbs)->unread_count;
GHashTable *folder_hash;
const char *dent;
GDir *dir;
-
+
tail = folders = NULL;
-
+
if (!(dir = g_dir_open(root, 0, NULL)))
return NULL;
-
+
folder_hash = g_hash_table_new(g_str_hash, g_str_equal);
-
+
/* FIXME: it would be better if we queue'd up the recursive
* scans till the end so that we can limit the number of
* directory descriptors open at any given time... */
-
+
while ((dent = g_dir_read_name(dir))) {
char *short_name, *full_name, *path, *ext;
struct stat st;
-
+
if (dent[0] == '.')
continue;
-
+
if (ignore_file(dent, FALSE))
continue;
-
+
path = g_strdup_printf("%s/%s", root, dent);
if (g_stat(path, &st) == -1) {
g_free(path);
continue;
}
-#ifndef G_OS_WIN32
+#ifndef G_OS_WIN32
if (S_ISDIR(st.st_mode)) {
struct _inode in = { st.st_dev, st.st_ino };
-
+
if (g_hash_table_lookup(visited, &in)) {
g_free(path);
continue;
}
}
-#endif
+#endif
short_name = g_strdup(dent);
if ((ext = strrchr(short_name, '.')) && !strcmp(ext, ".sbd"))
*ext = '\0';
-
+
if (name != NULL)
full_name = g_strdup_printf("%s/%s", name, short_name);
else
full_name = g_strdup(short_name);
-
+
if ((fi = g_hash_table_lookup(folder_hash, short_name)) != NULL) {
g_free(short_name);
g_free(full_name);
-
+
if (S_ISDIR(st.st_mode)) {
fi->flags =(fi->flags & ~CAMEL_FOLDER_NOCHILDREN) | CAMEL_FOLDER_CHILDREN;
} else {
} else {
fi = camel_folder_info_new ();
fi->parent = parent;
-
+
camel_url_set_fragment (url, full_name);
-
+
fi->uri = camel_url_to_string (url, 0);
fi->name = short_name;
fi->full_name = full_name;
fi->flags = CAMEL_FOLDER_NOSELECT;
else
fi->flags = CAMEL_FOLDER_NOCHILDREN;
-
+
if (tail == NULL)
folders = fi;
else
tail->next = fi;
-
+
tail = fi;
-
+
g_hash_table_insert(folder_hash, fi->name, fi);
}
-
+
if (!S_ISDIR(st.st_mode)) {
fill_fi(store, fi, flags);
} else if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) {
struct _inode in = { st.st_dev, st.st_ino };
-
+
if (g_hash_table_lookup(visited, &in) == NULL) {
#ifndef G_OS_WIN32
struct _inode *inew = g_new(struct _inode, 1);
-
+
*inew = in;
g_hash_table_insert(visited, inew, inew);
#endif
fi->flags =(fi->flags & ~CAMEL_FOLDER_CHILDREN) | CAMEL_FOLDER_NOCHILDREN;
}
}
-
+
g_free(path);
}
-
+
g_dir_close(dir);
-
+
g_hash_table_destroy(folder_hash);
-
+
return folders;
}
char *basename;
struct stat st;
CamelURL *url;
-
+
top = top ? top : "";
path = camel_local_store_get_full_path(store, top);
-
+
if (*top == '\0') {
/* requesting root dir scan */
if (g_stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
g_free(path);
return NULL;
}
-
+
visited = g_hash_table_new(inode_hash, inode_equal);
#ifndef G_OS_WIN32
inode = g_malloc0(sizeof(*inode));
inode->dnode = st.st_dev;
inode->inode = st.st_ino;
-
+
g_hash_table_insert(visited, inode, inode);
#endif
url = camel_url_copy (((CamelService *) store)->url);
fi->full_name = g_strdup(top);
fi->unread = -1;
fi->total = -1;
-
+
subdir = g_strdup_printf("%s.sbd", path);
if (g_stat(subdir, &st) == 0) {
if (S_ISDIR(st.st_mode))
fill_fi(store, fi, flags);
} else
fill_fi(store, fi, flags);
-
+
camel_url_free (url);
-
+
if (fi->child)
fi->flags |= CAMEL_FOLDER_CHILDREN;
else
fi->flags |= CAMEL_FOLDER_NOCHILDREN;
-
+
g_free(subdir);
-
+
g_hash_table_foreach(visited, inode_free, NULL);
g_hash_table_destroy(visited);
g_free(path);
-
+
return fi;
}
const char *inptr = full_name;
int subdirs = 0;
char *path, *p;
-
+
while (*inptr != '\0') {
if (G_IS_DIR_SEPARATOR (*inptr))
subdirs++;
inptr++;
}
-
+
path = g_malloc (strlen (ls->toplevel_dir) + (inptr - full_name) + (4 * subdirs) + 1);
p = g_stpcpy (path, ls->toplevel_dir);
-
+
inptr = full_name;
while (*inptr != '\0') {
while (!G_IS_DIR_SEPARATOR (*inptr) && *inptr != '\0')
*p++ = *inptr++;
-
+
if (G_IS_DIR_SEPARATOR (*inptr)) {
p = g_stpcpy (p, ".sbd/");
inptr++;
-
+
/* strip extranaeous '/'s */
while (G_IS_DIR_SEPARATOR (*inptr))
inptr++;
}
}
-
+
*p = '\0';
-
+
return path;
}
/*#define USE_HIDDEN_META_FILES*/
#ifdef USE_HIDDEN_META_FILES
char *name, *slash;
-
+
name = g_alloca (strlen (full_name) + strlen (ext) + 2);
if ((slash = strrchr (full_name, '/')))
sprintf (name, "%.*s.%s%s", slash - full_name + 1, full_name, slash + 1, ext);
else
sprintf (name, ".%s%s", full_name, ext);
-
+
return mbox_get_full_path(ls, name);
#else
char *full_path, *path;
-
+
full_path = mbox_get_full_path(ls, full_name);
path = g_strdup_printf ("%s%s", full_path, ext);
g_free (full_path);
-
+
return path;
#endif
}
*
* Copyright (C) 2000 Ximian, Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
G_BEGIN_DECLS
typedef struct {
- CamelLocalStore parent_object;
-
+ CamelLocalStore parent_object;
+
} CamelMboxStore;
typedef struct {
camel_mbox_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_local_summary_get_type(), "CamelMboxSummary",
sizeof (CamelMboxSummary),
(CamelObjectInitFunc) camel_mbox_summary_init,
(CamelObjectFinalizeFunc) camel_mbox_summary_finalise);
}
-
+
return type;
}
static gboolean
{
CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *)klass;
CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass;
-
+
camel_mbox_summary_parent = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type());
sklass->summary_header_load = summary_header_load;
#ifdef STATUS_PINE
sklass->info_set_flags = mbox_info_set_flags;
#endif
-
+
lklass->encode_x_evolution = mbox_summary_encode_x_evolution;
lklass->check = mbox_summary_check;
lklass->sync = mbox_summary_sync;
camel_mbox_summary_init(CamelMboxSummary *obj)
{
struct _CamelFolderSummary *s = (CamelFolderSummary *)obj;
-
+
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof(CamelMboxMessageInfo);
s->content_info_size = sizeof(CamelMboxMessageContentInfo);
* camel_mbox_summary_new:
*
* Create a new CamelMboxSummary object.
- *
+ *
* Return value: A new CamelMboxSummary widget.
**/
CamelMboxSummary *
p = uidstr = camel_message_info_uid(mi);
while (*p && isdigit(*p))
p++;
-
+
if (*p == 0 && sscanf(uidstr, "%u", &uid) == 1) {
return g_strdup_printf("%08x-%04x", uid, mi->info.flags & 0xffff);
} else {
mi->frompos = -1;
}
-
+
return (CamelMessageInfo *)mi;
}
mbi->frompos = camel_mime_parser_tell_start_from(mp);
}
-
+
return mi;
}
mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_load(s, in);
if (mi) {
CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
-
+
if (camel_file_util_decode_off_t(in, &mbi->frompos) == -1)
goto error;
}
-
+
return mi;
error:
camel_message_info_free(mi);
camel_operation_end(NULL);
return -1;
}
-
+
if (fstat(fd, &st) == 0)
size = st.st_size;
while (camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) {
CamelMessageInfo *info;
off_t pc = camel_mime_parser_tell_start_from (mp) + 1;
-
+
camel_operation_progress (NULL, (int) (((float) pc / size) * 100));
info = camel_folder_summary_add_from_parser(s, mp);
camel_message_info_free(mi);
}
mbs->changes = NULL;
-
+
/* update the file size/mtime in the summary */
if (ok != -1) {
if (g_stat(cls->folder_path, &st) == 0) {
tmpname = NULL;
camel_operation_end(NULL);
-
+
return 0;
error:
if (fd != -1)
close(fd);
-
+
if (fdout != -1)
close(fdout);
-
+
if (tmpname)
g_unlink(tmpname);
camel_object_unref((CamelObject *)mp);
camel_operation_end(NULL);
-
+
return 0;
error:
if (fd != -1)
camel_message_info_free((CamelMessageInfo *)info);
}
}
-
+
return 0;
error:
g_free(xevnew);
-
+
if (mp)
camel_object_unref((CamelObject *)mp);
if (info)
{
size_t i;
char *p;
-
+
p = status;
for (i = 0; i < G_N_ELEMENTS (status_flags); i++)
if (status_flags[i].flag & flags)
guint32 flags = 0;
size_t i;
char c;
-
+
p = status;
while ((c = *p++)) {
for (i = 0; i < G_N_ELEMENTS (status_flags); i++)
if (status_flags[i].tag == c)
flags |= status_flags[i].flag;
}
-
+
return flags;
}
*
* Copyright (C) 1999, 2003 Ximian Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex);
if (camel_exception_is_set (ex))
return;
-
+
d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi)));
-
+
/* write it out, use the uid we got from the summary */
name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi));
output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600);
if (output_stream == NULL)
goto fail_write;
-
+
if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1
|| camel_stream_close (output_stream) == -1)
goto fail_write;
-
+
/* close this? */
camel_object_unref (CAMEL_OBJECT (output_stream));
g_free(name);
-
+
camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed",
((CamelLocalFolder *)mh_folder)->changes);
camel_folder_change_info_clear (((CamelLocalFolder *)mh_folder)->changes);
-
+
if (appended_uid)
*appended_uid = g_strdup(camel_message_info_uid(mi));
return;
-
+
fail_write:
-
+
/* remove the summary info so we are not out-of-sync with the mh folder */
camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary),
camel_message_info_uid (mi));
-
+
if (errno == EINTR)
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("MH append message canceled"));
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot append message to mh folder: %s: %s"),
name, g_strerror (errno));
-
+
if (output_stream) {
camel_object_unref (CAMEL_OBJECT (output_stream));
unlink (name);
}
-
+
g_free (name);
}
*
* Copyright (C) 1999 Ximian Inc.
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelLocalFolderClass parent_class;
-
+
/* Virtual methods */
-
+
} CamelMhFolderClass;
/* public methods */
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
tmpnew = g_alloca (strlen (root) + 16);
sprintf (tmpnew, "%s.folders~", root);
-
+
out = camel_stream_fs_new_with_name(tmpnew, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if (out == NULL)
goto fail;
g_free (name);
return NULL;
}
-
+
g_free(name);
return camel_mh_folder_new(store, folder_name, flags, ex);
char *base;
base = strrchr(path, '/');
-
+
camel_url_set_fragment (url, path);
-
+
/* Build the folder info structure. */
fi = camel_folder_info_new();
fi->uri = camel_url_to_string (url, 0);
if (path[0]) {
fullpath = alloca (strlen (root) + strlen (path) + 2);
sprintf (fullpath, "%s/%s", root, path);
- } else
+ } else
fullpath = (char *)root;
if (stat(fullpath, &st) == -1 || !S_ISDIR(st.st_mode))
if (strncmp(top, line, toplen) != 0
|| (line[toplen] != 0 && line[toplen] != '/'))
continue;
-
+
/* check is not sub-subdir if not recursive */
if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0
&& (tmp = strrchr(line, '/'))
static gboolean inode_equal(const void *a, const void *b)
{
const struct _inode *v1 = a, *v2 = b;
-
+
return v1->inode == v2->inode && v1->dnode == v2->dnode;
}
CamelFolderInfo *fi = NULL;
CamelURL *url;
char *root;
-
+
root = ((CamelService *)store)->url->path;
-
+
url = camel_url_copy (((CamelService *) store)->url);
-
+
/* use .folders if we are supposed to */
if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) {
folders_scan(store, url, root, top, &fi, flags);
g_hash_table_foreach(visited, inode_free, NULL);
g_hash_table_destroy(visited);
}
-
+
camel_url_free (url);
-
+
return fi;
}
*
* Authors: Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelLocalStoreClass parent_class;
-
+
} CamelMhStoreClass;
/* public methods */
camel_mh_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_local_summary_get_type (), "CamelMhSummary",
sizeof(CamelMhSummary),
(CamelObjectInitFunc)camel_mh_summary_init,
(CamelObjectFinalizeFunc)camel_mh_summary_finalise);
}
-
+
return type;
}
* camel_mh_summary_new:
*
* Create a new CamelMhSummary object.
- *
+ *
* Return value: A new #CamelMhSummary object.
**/
CamelMhSummary *camel_mh_summary_new(struct _CamelFolder *folder, const char *filename, const char *mhdir, CamelIndex *index)
/* FIXME: put this in folder_summary::remove()? */
if (cls->index)
camel_index_delete_name(cls->index, (char *)uid);
-
+
camel_folder_change_info_remove_uid(changes, uid);
camel_folder_summary_remove((CamelFolderSummary *)cls, (CamelMessageInfo *)info);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*-
- *
+ *
* Authors: Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2001-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
}
retry++;
}
-
+
close (mf->lockfd);
mf->lockfd = -1;
-
+
return -1;
}
*
* Copyright (C) 2001 Ximian Inc (www.ximian.com/)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
*
* Copyright (C) 2001 Ximian Inc (www.ximian.com/)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
{
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_spool_store_class);
CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_spool_store_class);
-
+
parent_class = CAMEL_STORE_CLASS(camel_mbox_store_get_type());
/* virtual method overload */
camel_spool_store_get_type (void)
{
static CamelType camel_spool_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_spool_store_type == CAMEL_INVALID_TYPE) {
camel_spool_store_type = camel_type_register (camel_mbox_store_get_type(), "CamelSpoolStore",
sizeof (CamelSpoolStore),
NULL,
NULL);
}
-
+
return camel_spool_store_type;
}
}
if (path != NULL) {
- fi = spool_new_fi(store, parent, fip, path, CAMEL_FOLDER_NOSELECT);
+ fi = spool_new_fi(store, parent, fip, path, CAMEL_FOLDER_NOSELECT);
fip = &fi->child;
parent = fi;
}
-
+
while ( (d = readdir(dir)) ) {
if (strcmp(d->d_name, ".") == 0
|| strcmp(d->d_name, "..") == 0)
continue;
-
+
tmp = g_strdup_printf("%s/%s", name, d->d_name);
if (stat(tmp, &st) == 0) {
if (path)
} else if (S_ISDIR(st.st_mode)) {
struct _inode in = { st.st_dev, st.st_ino };
-
+
/* see if we've visited already */
if (g_hash_table_lookup(visited, &in) == NULL) {
struct _inode *inew = g_malloc(sizeof(*inew));
-
+
*inew = in;
g_hash_table_insert(visited, inew, inew);
static gboolean inode_equal(const void *a, const void *b)
{
const struct _inode *v1 = a, *v2 = b;
-
+
return v1->inode == v2->inode && v1->dnode == v2->dnode;
}
*
* Copyright (C) 2001 Ximian Inc (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
} camel_spool_store_t;
typedef struct {
- CamelMboxStore parent_object;
+ CamelMboxStore parent_object;
camel_spool_store_t type;
} CamelSpoolStore;
camel_spool_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_mbox_summary_get_type(), "CamelSpoolSummary",
sizeof (CamelSpoolSummary),
(CamelObjectInitFunc) camel_spool_summary_init,
(CamelObjectFinalizeFunc) camel_spool_summary_finalise);
}
-
+
return type;
}
camel_spool_summary_init(CamelSpoolSummary *obj)
{
struct _CamelFolderSummary *s = (CamelFolderSummary *)obj;
-
+
/* message info size is from mbox parent */
/* and a unique file version */
unlink(tmpname);
camel_operation_end(NULL);
-
+
return 0;
error:
if (fd != -1)
close(fd);
-
+
if (fdout != -1)
close(fdout);
-
+
if (tmpname[0] != '\0')
unlink(tmpname);
d(printf("Have to add new headers, re-syncing from the start to accomplish this\n"));
if (((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_full((CamelMboxSummary *)cls, FALSE, changeinfo, ex) == -1)
return -1;
-
+
if (stat(cls->folder_path, &st) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Unknown error: %s"),
struct _CamelSpoolSummary {
CamelMboxSummary parent;
-
+
};
struct _CamelSpoolSummaryClass {
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-auth.c : authentication for nntp */
-/*
+/*
*
* Copyright (C) 2000 Ximian, Inc. <toshok@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-auth.h : authentication for nntp */
-/*
+/*
*
- * Author : Chris Toshok <toshok@ximian.com>
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 1999 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-folder.c : Class for a news folder
*
- * Authors : Chris Toshok <toshok@ximian.com>
+ * Authors : Chris Toshok <toshok@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2001-2003 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
nntp_store = (CamelNNTPStore *) folder->parent_store;
nntp_folder = (CamelNNTPFolder *) folder;
-
+
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
camel_nntp_command(nntp_store, ex, nntp_folder, &line, NULL);
changes = nntp_folder->changes;
nntp_folder->changes = camel_folder_change_info_new();
}
-
+
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
-
+
if (changes) {
camel_object_trigger_event ((CamelObject *) folder, "folder_changed", changes);
camel_folder_change_info_free (changes);
} 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;
}
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);
nntp_store = (CamelNNTPStore *) folder->parent_store;
nntp_folder = (CamelNNTPFolder *) folder;
-
+
article = alloca(strlen(uid)+1);
strcpy(article, uid);
msgid = strchr (article, ',');
*msgid++ = 0;
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
-
+
/* Lookup in cache, NEWS is global messageid's so use a global cache path */
stream = camel_data_cache_get (nntp_store->cache, "cache", msgid, NULL);
if (stream == NULL) {
if (stream == NULL)
goto fail;
}
-
+
message = camel_mime_message_new ();
if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) {
if (errno == EINTR)
} else {
changes = NULL;
}
-
+
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
-
+
if (changes) {
camel_object_trigger_event ((CamelObject *) folder, "folder_changed", changes);
camel_folder_change_info_free (changes);
}
-
+
return message;
}
{
CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder);
GPtrArray *matches;
-
+
CAMEL_NNTP_FOLDER_LOCK(nntp_folder, search_lock);
-
+
if (nntp_folder->search == NULL)
nntp_folder->search = camel_folder_search_new ();
-
+
camel_folder_search_set_folder (nntp_folder->search, folder);
matches = camel_folder_search_search(nntp_folder->search, expression, NULL, ex);
-
+
CAMEL_NNTP_FOLDER_UNLOCK(nntp_folder, search_lock);
-
+
return matches;
}
if (uids->len == 0)
return g_ptr_array_new();
-
+
CAMEL_NNTP_FOLDER_LOCK(folder, search_lock);
-
+
if (nntp_folder->search == NULL)
nntp_folder->search = camel_folder_search_new ();
-
+
camel_folder_search_set_folder (nntp_folder->search, folder);
matches = camel_folder_search_search(nntp_folder->search, expression, uids, ex);
-
+
CAMEL_NNTP_FOLDER_UNLOCK(folder, search_lock);
-
+
return matches;
}
nntp_folder_search_free (CamelFolder *folder, GPtrArray *result)
{
CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder);
-
+
camel_folder_search_free_result (nntp_folder->search, result);
}
-static void
+static void
nntp_folder_append_message_online (CamelFolder *folder, CamelMimeMessage *mime_message,
const CamelMessageInfo *info, char **appended_uid,
CamelException *ex)
unsigned int u;
struct _camel_header_raw *header, *savedhdrs, *n, *tail;
char *group, *line;
-
+
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
-
+
/* send 'POST' command */
ret = camel_nntp_command (nntp_store, ex, NULL, &line, "post");
if (ret != 340) {
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
return;
}
-
+
/* the 'Newsgroups: ' header */
group = g_strdup_printf ("Newsgroups: %s\r\n", folder->full_name);
-
+
/* setup stream filtering */
crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
filtered_stream = camel_stream_filter_new_with_stream (stream);
camel_stream_filter_add (filtered_stream, crlffilter);
camel_object_unref (crlffilter);
-
+
/* remove mail 'To', 'CC', and 'BCC' headers */
savedhdrs = NULL;
tail = (struct _camel_header_raw *) &savedhdrs;
-
+
header = (struct _camel_header_raw *) &CAMEL_MIME_PART (mime_message)->headers;
n = header->next;
while (n != NULL) {
} else {
header = n;
}
-
+
n = header->next;
}
-
+
/* write the message */
if (camel_stream_write(stream, group, strlen(group)) == -1
|| camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_message), CAMEL_STREAM (filtered_stream)) == -1
header->next = savedhdrs;
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
-
+
return;
}
CamelException *ex)
{
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("You cannot post NNTP messages while working offline!"));
+ _("You cannot post NNTP messages while working offline!"));
}
/* I do not know what to do this exactly. Looking at the IMAP implementation for this, it
_("You cannot copy messages from a NNTP folder!"));
}
-static void
+static void
nntp_folder_init (CamelNNTPFolder *nntp_folder, CamelNNTPFolderClass *klass)
{
struct _CamelNNTPFolderPrivate *p;
-
+
nntp_folder->changes = camel_folder_change_info_new ();
p = nntp_folder->priv = g_malloc0 (sizeof (*nntp_folder->priv));
p->search_lock = g_mutex_new ();
p->cache_lock = g_mutex_new ();
}
-static void
+static void
nntp_folder_finalise (CamelNNTPFolder *nntp_folder)
{
struct _CamelNNTPFolderPrivate *p;
-
+
camel_folder_summary_save (((CamelFolder*) nntp_folder)->summary);
-
+
p = nntp_folder->priv;
g_mutex_free (p->search_lock);
g_mutex_free (p->cache_lock);
{
CamelDiscoFolderClass *camel_disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_nntp_folder_class);
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_nntp_folder_class);
-
+
parent_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ()));
folder_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ()));
-
+
/* virtual method definition */
-
+
/* virtual method overload */
camel_disco_folder_class->sync_online = nntp_folder_sync_online;
camel_disco_folder_class->sync_resyncing = nntp_folder_sync_offline;
- camel_disco_folder_class->sync_offline = nntp_folder_sync_offline;
+ camel_disco_folder_class->sync_offline = nntp_folder_sync_offline;
camel_disco_folder_class->cache_message = nntp_folder_cache_message;
camel_disco_folder_class->append_online = nntp_folder_append_message_online;
camel_disco_folder_class->append_resyncing = nntp_folder_append_message_online;
camel_disco_folder_class->transfer_resyncing = nntp_folder_transfer_message;
camel_disco_folder_class->transfer_offline = nntp_folder_transfer_message;
camel_disco_folder_class->refresh_info_online = nntp_folder_refresh_info_online;
-
+
camel_folder_class->set_message_flags = nntp_folder_set_message_flags;
camel_folder_class->get_message = nntp_folder_get_message;
camel_folder_class->search_by_expression = nntp_folder_search_by_expression;
camel_nntp_folder_get_type (void)
{
static CamelType camel_nntp_folder_type = CAMEL_INVALID_TYPE;
-
+
if (camel_nntp_folder_type == CAMEL_INVALID_TYPE) {
camel_nntp_folder_type = camel_type_register (CAMEL_DISCO_FOLDER_TYPE, "CamelNNTPFolder",
sizeof (CamelNNTPFolder),
(CamelObjectInitFunc) nntp_folder_init,
(CamelObjectFinalizeFunc) nntp_folder_finalise);
}
-
+
return camel_nntp_folder_type;
}
CamelService *service;
CamelStoreInfo *si;
gboolean subscribed = TRUE;
-
+
service = (CamelService *) parent;
root = camel_session_get_storage_path (service->session, service, ex);
if (root == NULL)
return NULL;
-
+
/* If this doesn't work, stuff wont save, but let it continue anyway */
g_mkdir_with_parents (root, 0777);
-
+
folder = (CamelFolder *) camel_object_new (CAMEL_NNTP_FOLDER_TYPE);
nntp_folder = (CamelNNTPFolder *)folder;
-
+
camel_folder_construct (folder, parent, folder_name, folder_name);
folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY|CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
-
+
nntp_folder->storage_path = g_build_filename (root, folder->full_name, NULL);
g_free (root);
-
+
root = g_strdup_printf ("%s.cmeta", nntp_folder->storage_path);
camel_object_set(nntp_folder, NULL, CAMEL_OBJECT_STATE_FILE, root, NULL);
camel_object_state_read(nntp_folder);
folder->summary = (CamelFolderSummary *) camel_nntp_summary_new (folder, root);
g_free(root);
camel_folder_summary_load (folder->summary);
-
+
si = camel_store_summary_path ((CamelStoreSummary *) ((CamelNNTPStore*) parent)->summary, folder_name);
if (si) {
subscribed = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0;
camel_store_summary_info_free ((CamelStoreSummary *) ((CamelNNTPStore*) parent)->summary, si);
}
-
+
if (subscribed) {
camel_folder_refresh_info(folder, ex);
if (camel_exception_is_set(ex)) {
folder = NULL;
}
}
-
+
return folder;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-folder.h : NNTP group (folder) support. */
-/*
+/*
*
- * Author : Chris Toshok <toshok@ximian.com>
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 2000 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct _CamelNNTPFolderClass {
CamelDiscoFolderClass parent;
- /* Virtual methods */
-
+ /* Virtual methods */
+
} CamelNNTPFolderClass;
/* public methods */
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-grouplist.c : getting/updating the list of newsgroups on the server. */
-/*
- * Author : Chris Toshok <toshok@ximian.com>
+/*
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 2000 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
entry->low = atoi (split_line[2]);
g_strfreev (split_line);
-
+
list->group_list = g_list_prepend (list->group_list, entry);
}
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-grouplist.h : getting/updating the list of newsgroups on the server. */
-/*
- * Author : Chris Toshok <toshok@ximian.com>
+/*
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 2000 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
for (i = 0; i < group->ranges->len; i ++) {
guint range_low = g_array_index (group->ranges, ArticleRange, i).low;
guint range_high = g_array_index (group->ranges, ArticleRange, i).high;
-
+
/* if it's already part of a range, return immediately. */
if (low >= range_low &&
low <= range_high &&
tmp_range.high = high;
group->ranges = g_array_append_val (group->ranges, tmp_range);
newsrc->dirty = TRUE;
- }
+ }
}
int
if (group) {
for (i = 0; i < group->ranges->len; i++) {
- if (num >= g_array_index (group->ranges, ArticleRange, i).low &&
+ if (num >= g_array_index (group->ranges, ArticleRange, i).low &&
num <= g_array_index (group->ranges, ArticleRange, i).high) {
ret = TRUE;
break;
return FALSE;
}
-gboolean
+gboolean
camel_nntp_newsrc_group_is_subscribed (CamelNNTPNewsrc *newsrc, const char *group_name)
{
NewsrcGroup *group;
fprintf (fp, "\n");
}
-void
+void
camel_nntp_newsrc_write_to_file(CamelNNTPNewsrc *newsrc, FILE *fp)
{
struct newsrc_fp newsrc_fp;
return NULL;
(*p) ++;
-
+
/* if we just incremented to the end of the buffer, return NULL */
if (**p == '\0')
return NULL;
newsrc->filename = filename;
newsrc->groups = g_hash_table_new (g_str_hash, g_str_equal);
newsrc->lock = g_mutex_new();
-
+
if ((fd = g_open(filename, O_RDONLY, 0)) == -1) {
g_warning ("~/.newsrc-%s not present.\n", server);
return newsrc;
*
* Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-provider.c: nntp provider registration code */
-/*
+/*
* Authors :
* Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
news_provider.url_equal = nntp_url_equal;
news_provider.authtypes = g_list_append (NULL, &camel_nntp_password_authtype);
news_provider.translation_domain = GETTEXT_PACKAGE;
-
+
camel_provider_register(&news_provider);
}
add_hash (&hash, u->user);
add_hash (&hash, u->host);
hash ^= u->port;
-
+
return hash;
}
else
return FALSE;
}
-
+
if (s2 == NULL)
return FALSE;
nntp_url_equal (gconstpointer a, gconstpointer b)
{
const CamelURL *u1 = a, *u2 = b;
-
+
return check_equal(u1->protocol, u2->protocol)
&& check_equal (u1->user, u2->user)
&& check_equal (u1->host, u2->host)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-resp-codes.h : #defines for all the response codes we care about */
-/*
+/*
*
* Copyright (C) 2000 Ximian, Inc. <toshok@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_nntp_store_summary_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
camel_nntp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type();
type = camel_type_register((CamelType)camel_nntp_store_summary_parent, "CamelNNTPStoreSummary",
(CamelObjectInitFunc) camel_nntp_store_summary_init,
(CamelObjectFinalizeFunc) camel_nntp_store_summary_finalise);
}
-
+
return type;
}
{
int count, i;
CamelNNTPStoreInfo *info;
-
+
count = camel_store_summary_count ((CamelStoreSummary *) s);
for (i = 0; i < count; i++) {
info = (CamelNNTPStoreInfo *)camel_store_summary_index ((CamelStoreSummary *) s, i);
camel_store_summary_info_free ((CamelStoreSummary *) s, (CamelStoreInfo *)info);
}
}
-
+
return NULL;
}
*p = 0;
} else
path = (char *) full_name;
-
+
return camel_utf7_utf8 (path);
}
int state=0;
char *subpath, *last = NULL;
CamelStoreInfo *si;
-
+
/* check to see if we have a subpath of path already defined */
subpath = g_alloca (strlen (path) + 1);
strcpy (subpath, path);
*last = 0;
}
} while (si == NULL && last);
-
+
/* path is already present, use the raw version we have */
if (si && strlen (subpath) == strlen (path)) {
f = g_strdup (camel_nntp_store_info_full_name (s, si));
camel_store_summary_info_free ((CamelStoreSummary *) s, si);
return f;
}
-
+
f = full = g_alloca (strlen (path)*2+1);
if (si)
p = path + strlen (subpath);
else
p = path;
-
+
while ((c = camel_utf8_getc ((const unsigned char **) &p))) {
switch (state) {
case 0:
}
}
camel_utf8_putc ((unsigned char **) &f, c);
-
+
/* merge old path part if required */
f = camel_utf8_utf7 (full);
if (si) {
camel_store_summary_info_free ((CamelStoreSummary *) s, si);
f = full;
}
-
+
return f;
}
char *pathu8;
int len;
char *full_name;
-
+
d(printf("adding full name '%s' '%c'\n", full, dir_sep));
-
+
len = strlen (full);
full_name = g_alloca (len+1);
strcpy(full_name, full);
if (full_name[len-1] == dir_sep)
full_name[len-1] = 0;
-
+
info = camel_nntp_store_summary_full_name (s, full_name);
if (info) {
camel_store_summary_info_free ((CamelStoreSummary *) s, (CamelStoreInfo *) info);
d(printf(" already there\n"));
return info;
}
-
+
pathu8 = camel_nntp_store_summary_full_to_path (s, full_name, dir_sep);
-
+
info = (CamelNNTPStoreInfo *) camel_store_summary_add_from_path ((CamelStoreSummary *) s, pathu8);
if (info) {
d(printf(" '%s' -> '%s'\n", pathu8, full_name));
camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_NNTP_STORE_INFO_FULL_NAME, full_name);
} else
d(printf(" failed\n"));
-
+
return info;
}
{
CamelNNTPStoreSummary *is = (CamelNNTPStoreSummary *) s;
gint32 version, nil;
-
+
if (camel_nntp_store_summary_parent->summary_header_load ((CamelStoreSummary *) s, in) == -1
|| camel_file_util_decode_fixed_int32 (in, &version) == -1)
return -1;
-
+
is->version = version;
-
+
if (version < CAMEL_NNTP_STORE_SUMMARY_VERSION_0) {
g_warning("Store summary header version too low");
return -1;
}
-
+
if (fread (is->last_newslist, 1, NNTP_DATE_SIZE, in) < NNTP_DATE_SIZE)
return -1;
-
+
camel_file_util_decode_fixed_int32 (in, &nil);
return 0;
summary_header_save (CamelStoreSummary *s, FILE *out)
{
CamelNNTPStoreSummary *is = (CamelNNTPStoreSummary *) s;
-
+
/* always write as latest version */
if (camel_nntp_store_summary_parent->summary_header_save ((CamelStoreSummary *) s, out) == -1
|| camel_file_util_encode_fixed_int32 (out, CAMEL_NNTP_STORE_SUMMARY_VERSION) == -1
|| fwrite (is->last_newslist, 1, NNTP_DATE_SIZE, out) < NNTP_DATE_SIZE
|| camel_file_util_encode_fixed_int32 (out, 0) == -1)
return -1;
-
+
return 0;
}
store_info_load (CamelStoreSummary *s, FILE *in)
{
CamelNNTPStoreInfo *ni;
-
+
ni = (CamelNNTPStoreInfo *) camel_nntp_store_summary_parent->store_info_load (s, in);
if (ni) {
if (camel_file_util_decode_string (in, &ni->full_name) == -1) {
}
/* set the URL */
}
-
+
return (CamelStoreInfo *) ni;
}
store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi)
{
CamelNNTPStoreInfo *isi = (CamelNNTPStoreInfo *)mi;
-
+
if (camel_nntp_store_summary_parent->store_info_save (s, out, mi) == -1
|| camel_file_util_encode_string (out, isi->full_name) == -1
|| camel_file_util_encode_uint32(out, isi->first) == -1
|| camel_file_util_encode_uint32(out, isi->last) == -1)
return -1;
-
+
return 0;
}
store_info_free (CamelStoreSummary *s, CamelStoreInfo *mi)
{
CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *) mi;
-
+
g_free (nsi->full_name);
camel_nntp_store_summary_parent->store_info_free (s, mi);
}
store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type)
{
CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *)mi;
-
+
/* FIXME: Locks? */
-
+
g_assert (mi != NULL);
-
+
switch (type) {
case CAMEL_NNTP_STORE_INFO_FULL_NAME:
return nsi->full_name;
store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str)
{
CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *)mi;
-
+
g_assert(mi != NULL);
-
+
switch (type) {
case CAMEL_NNTP_STORE_INFO_FULL_NAME:
d(printf("Set full name %s -> %s\n", nsi->full_name, str));
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
+/*
*
* Copyright (C) 2001-2003 Ximian, Inc. <www.ximain.com>
*
* Authors: Christopher Toshok <toshok@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
unsigned char *buf;
unsigned int len;
char *path;
-
+
CAMEL_SERVICE_REC_LOCK(store, connect_lock);
if (ssl_mode != MODE_CLEAR) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Could not connect to %s: %s"),
service->url->host, _("SSL unavailable"));
-
+
goto fail;
#endif /* HAVE_SSL */
} else {
tcp_stream = camel_tcp_stream_raw_new ();
}
-
+
if (camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai) == -1) {
if (errno == EINTR)
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
_("Could not connect to %s: %s"),
service->url->host,
g_strerror (errno));
-
+
camel_object_unref (tcp_stream);
-
+
goto fail;
}
-
+
store->stream = (CamelNNTPStream *) camel_nntp_stream_new (tcp_stream);
camel_object_unref (tcp_stream);
-
+
/* Read the greeting, if any. */
if (camel_nntp_stream_line (store->stream, &buf, &len) == -1) {
if (errno == EINTR)
&& service->url->user[0]
&& camel_nntp_try_authenticate(store, ex) != NNTP_AUTH_ACCEPTED)
goto fail;
-
+
/* set 'reader' mode & ignore return code, also ping the server, inn goes offline very quickly otherwise */
if (camel_nntp_raw_command_auth (store, ex, (char **) &buf, "mode reader") == -1
|| camel_nntp_raw_command_auth (store, ex, (char **) &buf, "date") == -1)
if (xover_setup(store, ex) == -1)
goto fail;
-
+
path = g_build_filename (store->storage_path, ".ev-journal", NULL);
disco_store->diary = camel_disco_diary_new (disco_store, path, ex);
- g_free (path);
-
+ g_free (path);
+
retval = TRUE;
g_free(store->current_folder);
store->current_folder = NULL;
-
+
fail:
CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
return retval;
int mode, ret, i;
char *serv;
const char *port;
-
+
if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) {
for (i = 0; ssl_options[i].value; i++)
if (!strcmp (ssl_options[i].value, ssl_mode))
serv = "nntp";
port = NNTP_PORT;
}
-
+
if (service->url->port) {
serv = g_alloca (16);
sprintf (serv, "%d", service->url->port);
port = NULL;
}
-
+
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
}
if (ai == NULL)
return FALSE;
-
+
ret = connect_to_server (service, ai, mode, ex);
-
+
camel_freeaddrinfo (ai);
-
+
return ret;
}
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(service);
CamelDiscoStore *disco_store = (CamelDiscoStore *) nntp_store;
char *path;
-
+
if (nntp_store->storage_path == NULL)
return FALSE;
-
+
/* setup store-wide cache */
if (nntp_store->cache == NULL) {
nntp_store->cache = camel_data_cache_new (nntp_store->storage_path, 0, ex);
if (nntp_store->cache == NULL)
return FALSE;
-
+
/* Default cache expiry - 2 weeks old, or not visited in 5 days */
camel_data_cache_set_expire_age (nntp_store->cache, 60*60*24*14);
camel_data_cache_set_expire_access (nntp_store->cache, 60*60*24*5);
- }
-
+ }
+
path = g_build_filename (nntp_store->storage_path, ".ev-journal", NULL);
disco_store->diary = camel_disco_diary_new (disco_store, path, ex);
g_free (path);
-
+
if (!disco_store->diary)
return FALSE;
-
+
return TRUE;
}
{
CamelNNTPStore *store = CAMEL_NNTP_STORE (service);
char *line;
-
+
CAMEL_SERVICE_REC_LOCK(store, connect_lock);
-
+
if (clean) {
camel_nntp_raw_command (store, ex, &line, "quit");
camel_exception_clear(ex);
}
-
+
if (!service_class->disconnect (service, clean, ex)) {
CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
return FALSE;
}
-
+
camel_object_unref (store->stream);
store->stream = NULL;
g_free(store->current_folder);
store->current_folder = NULL;
CAMEL_SERVICE_REC_UNLOCK(store, connect_lock);
-
+
return TRUE;
}
nntp_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex)
{
CamelDiscoStore *disco = CAMEL_DISCO_STORE(service);
-
+
if (!service_class->disconnect (service, clean, ex))
return FALSE;
-
+
if (disco->diary) {
camel_object_unref (disco->diary);
disco->diary = NULL;
}
-
+
return TRUE;
}
return g_strdup_printf ("%s", service->url->host);
else
return g_strdup_printf (_("USENET News via %s"), service->url->host);
-
+
}
extern CamelServiceAuthType camel_nntp_password_authtype;
{
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
CamelFolder *folder;
-
+
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
-
+
folder = camel_nntp_folder_new(store, folder_name, ex);
-
+
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
-
+
return folder;
}
{
char *resptr, *tmp;
const char *ptr2;
-
+
resptr = tmp = g_malloc0 (strlen (name) + 1);
-
+
while ((ptr2 = strchr (name, '.'))) {
if (ptr2 == name) {
name++;
continue;
}
-
+
*resptr++ = *name;
*resptr++ = '.';
name = ptr2 + 1;
}
-
+
strcpy (resptr, name);
return tmp;
}
url = camel_url_new_with_base (base_url, path);
fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
camel_url_free (url);
-
+
return fi;
}
fi = camel_folder_info_new ();
fi->full_name = g_strdup (name);
-
+
if (short_notation)
fi->name = nntp_newsgroup_name_short (name);
else
fi->name = g_strdup (name);
-
+
fi->unread = -1;
-
+
path = alloca(strlen(fi->full_name)+2);
sprintf(path, "/%s", fi->full_name);
url = camel_url_new_with_base (base_url, path);
fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
camel_url_free (url);
-
+
return fi;
}
int i;
CamelStoreInfo *si;
CamelFolderInfo *first = NULL, *last = NULL, *fi = NULL;
-
+
/* since we do not do a tree, any request that is not for root is sure to give no results */
if (top != NULL && top[0] != 0)
return NULL;
-
+
for (i=0;(si = camel_store_summary_index ((CamelStoreSummary *) store->summary, i));i++) {
if (si == NULL)
continue;
}
camel_store_summary_info_free ((CamelStoreSummary *) store->summary, si);
}
-
+
return first;
}
char *tmpname;
char *top = g_strconcat(orig_top?orig_top:"", ".", NULL);
int toplen = strlen(top);
-
+
for (i = 0; (si = camel_store_summary_index ((CamelStoreSummary *) store->summary, i)); i++) {
if ((subscribed_or_flag || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED))
&& (root_or_flag || strncmp (si->path, top, toplen) == 0)) {
the item we added last, we need to add a portion of this item to
the list as a placeholder */
if (!last ||
- strncmp(si->path, last->full_name, strlen(last->full_name)) != 0 ||
+ strncmp(si->path, last->full_name, strlen(last->full_name)) != 0 ||
si->path[strlen(last->full_name)] != '.') {
tmpname = g_strdup(si->path);
*(strchr(tmpname + toplen, '.')) = '\0';
}
camel_store_summary_info_free((CamelStoreSummary *)store->summary, si);
}
-
+
g_free(top);
return first;
}
CamelFolderInfo *fi = NULL;
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
-
+
if (top == NULL)
top = "";
-
+
if (online && (top == NULL || top[0] == 0)) {
/* we may need to update */
if (summary->last_newslist[0] != 0) {
/* Some servers don't support date (!), so fallback if they dont */
if (!nntp_get_date (nntp_store, NULL))
goto do_complete_list_nodate;
-
+
ret = camel_nntp_command (nntp_store, ex, NULL, (char **) &line, "newgroups %s", date);
if (ret == -1)
goto error;
g_hash_table_foreach(all, store_info_remove, nntp_store->summary);
g_hash_table_destroy(all);
}
-
+
/* sort the list */
g_ptr_array_sort (CAMEL_STORE_SUMMARY (nntp_store->summary)->folders, store_info_sort);
if (ret < 0)
goto error;
-
+
camel_store_summary_save ((CamelStoreSummary *) nntp_store->summary);
}
-
+
fi = nntp_store_get_cached_folder_info (nntp_store, top, flags, ex);
error:
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
{
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(store);
CamelFolderInfo *first = NULL;
-
+
dd(printf("g_f_i: fast %d subscr %d recursive %d online %d top \"%s\"\n",
flags & CAMEL_STORE_FOLDER_INFO_FAST,
flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE,
online,
top?top:""));
-
+
if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)
first = nntp_store_get_subscribed_folder_info (nntp_store, top, flags, ex);
else
first = nntp_store_get_folder_info_all (nntp_store, top, flags, online, ex);
-
+
return first;
}
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store);
CamelStoreInfo *si;
int truth = FALSE;
-
+
si = camel_store_summary_path ((CamelStoreSummary *) nntp_store->summary, folder_name);
if (si) {
truth = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0;
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(store);
CamelStoreInfo *si;
CamelFolderInfo *fi;
-
+
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
-
+
si = camel_store_summary_path(CAMEL_STORE_SUMMARY(nntp_store->summary), folder_name);
if (!si) {
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
return;
}
}
-
+
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
}
CamelFolderInfo *fi;
CamelStoreInfo *fitem;
CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock);
-
+
fitem = camel_store_summary_path(CAMEL_STORE_SUMMARY(nntp_store->summary), folder_name);
-
+
if (!fitem) {
camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
_("You cannot unsubscribe to this newsgroup:\n\n"
return;
}
}
-
+
CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock);
}
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (object);
struct _CamelNNTPStorePrivate *p = nntp_store->priv;
struct _xover_header *xover, *xn;
-
+
camel_service_disconnect ((CamelService *)object, TRUE, NULL);
-
+
if (nntp_store->summary) {
camel_store_summary_save ((CamelStoreSummary *) nntp_store->summary);
camel_object_unref (nntp_store->summary);
- }
+ }
camel_object_unref (nntp_store->mem);
nntp_store->mem = NULL;
if (nntp_store->stream)
camel_object_unref (nntp_store->stream);
-
+
if (nntp_store->base_url)
g_free (nntp_store->base_url);
if (nntp_store->storage_path)
if (nntp_store->cache)
camel_object_unref(nntp_store->cache);
-
+
g_free(p);
}
parent_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ()));
service_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ()));
-
+
/* virtual method overload */
camel_service_class->construct = nntp_construct;
camel_service_class->query_auth_types = nntp_store_query_auth_types;
camel_service_class->get_name = nntp_store_get_name;
-
+
camel_disco_store_class->can_work_offline = nntp_can_work_offline;
camel_disco_store_class->connect_online = nntp_connect_online;
camel_disco_store_class->connect_offline = nntp_connect_offline;
camel_disco_store_class->get_folder_online = nntp_get_folder;
camel_disco_store_class->get_folder_resyncing = nntp_get_folder;
camel_disco_store_class->get_folder_offline = nntp_get_folder;
-
+
camel_disco_store_class->get_folder_info_online = nntp_get_folder_info_online;
camel_disco_store_class->get_folder_info_resyncing = nntp_get_folder_info_online;
camel_disco_store_class->get_folder_info_offline = nntp_get_folder_info_offline;
-
+
camel_store_class->free_folder_info = camel_store_free_folder_info_full;
-
+
camel_store_class->folder_subscribed = nntp_store_folder_subscribed;
camel_store_class->subscribe_folder = nntp_store_subscribe_folder;
camel_store_class->unsubscribe_folder = nntp_store_unsubscribe_folder;
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(service);
CamelURL *summary_url;
char *tmp;
-
+
/* construct the parent first */
CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
if (camel_exception_is_set (ex))
return;
-
+
/* find out the storage path, base url */
nntp_store->storage_path = camel_session_get_storage_path (session, service, ex);
if (!nntp_store->storage_path)
return;
-
+
/* FIXME */
nntp_store->base_url = camel_url_to_string (service->url, (CAMEL_URL_HIDE_PASSWORD |
CAMEL_URL_HIDE_PARAMS |
CAMEL_URL_HIDE_AUTH));
-
+
tmp = g_build_filename (nntp_store->storage_path, ".ev-store-summary", NULL);
nntp_store->summary = camel_nntp_store_summary_new ();
- camel_store_summary_set_filename ((CamelStoreSummary *) nntp_store->summary, tmp);
+ camel_store_summary_set_filename ((CamelStoreSummary *) nntp_store->summary, tmp);
summary_url = camel_url_new (nntp_store->base_url, NULL);
camel_store_summary_set_uri_base ((CamelStoreSummary *) nntp_store->summary, summary_url);
g_free (tmp);
-
+
camel_url_free (summary_url);
if (camel_store_summary_load ((CamelStoreSummary *)nntp_store->summary) == 0)
;
-
+
/* get options */
if (camel_url_get_param (url, "show_short_notation"))
nntp_store->do_short_folder_notation = TRUE;
nntp_store->cache = camel_data_cache_new(nntp_store->storage_path, 0, ex);
if (nntp_store->cache == NULL)
return;
-
+
/* Default cache expiry - 2 weeks old, or not visited in 5 days */
camel_data_cache_set_expire_age(nntp_store->cache, 60*60*24*14);
camel_data_cache_set_expire_access(nntp_store->cache, 60*60*24*5);
CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(object);
CamelStore *store = CAMEL_STORE (object);
struct _CamelNNTPStorePrivate *p;
-
+
store->flags = CAMEL_STORE_SUBSCRIPTIONS;
-
+
nntp_store->mem = (CamelStreamMem *)camel_stream_mem_new();
-
+
p = nntp_store->priv = g_malloc0(sizeof(*p));
}
camel_nntp_store_get_type (void)
{
static CamelType camel_nntp_store_type = CAMEL_INVALID_TYPE;
-
+
if (camel_nntp_store_type == CAMEL_INVALID_TYPE) {
camel_nntp_store_type =
camel_type_register (CAMEL_DISCO_STORE_TYPE,
(CamelObjectInitFunc) nntp_store_init,
(CamelObjectFinalizeFunc) nntp_store_finalize);
}
-
+
return camel_nntp_store_type;
}
CamelSession *session = camel_service_get_session (service);
int ret;
char *line = NULL;
-
+
if (!service->url->user) {
camel_exception_setv(ex, CAMEL_EXCEPTION_INVALID_PARAM,
_("Authentication requested but no username provided"));
prompt, "password", CAMEL_SESSION_PASSWORD_SECRET, ex);
g_free(prompt);
g_free(base);
-
+
if (!service->url->passwd)
return -1;
}
va_list ap;
int ret, retry;
unsigned int u;
-
+
if (((CamelDiscoStore *)store)->status == CAMEL_DISCO_STORE_OFFLINE) {
camel_exception_setv(ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED,
_("Not connected."));
return -1;
}
-
+
retry = 0;
do {
retry ++;
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-store.h : class for an nntp store */
-/*
+/*
*
* Copyright (C) 2000 Ximian, Inc. <toshok@ximian.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
};
struct _CamelNNTPStore {
- CamelDiscoStore parent_object;
-
+ CamelDiscoStore parent_object;
+
struct _CamelNNTPStorePrivate *priv;
-
+
guint32 extensions;
-
+
unsigned int posting_allowed:1;
unsigned int do_short_folder_notation:1;
unsigned int folder_hierarchy_relative:1;
struct _CamelNNTPStoreSummary *summary;
-
+
struct _CamelNNTPStream *stream;
struct _CamelStreamMem *mem;
-
+
struct _CamelDataCache *cache;
-
+
char *current_folder, *storage_path, *base_url;
struct _xover_header *xover;
camel_nntp_summary_get_type(void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register(camel_folder_summary_get_type(), "CamelNNTPSummary",
sizeof (CamelNNTPSummary),
(CamelObjectInitFunc) camel_nntp_summary_init,
(CamelObjectFinalizeFunc) camel_nntp_summary_finalise);
}
-
+
return type;
}
camel_nntp_summary_class_init(CamelNNTPSummaryClass *klass)
{
CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass;
-
+
camel_nntp_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
sklass->message_info_new_from_header = message_info_new_from_header;
camel_folder_summary_set_filename((CamelFolderSummary *)cns, path);
camel_folder_summary_set_build_content((CamelFolderSummary *)cns, FALSE);
-
+
return cns;
}
mi->uid = cns->priv->uid;
cns->priv->uid = NULL;
}
-
+
return (CamelMessageInfo *)mi;
}
n = strtoul(line, &line, 10);
if (n != i)
g_warning("retrieved message '%u' when i expected '%u'?\n", n, i);
-
+
/* FIXME: use camel-mime-utils.c function for parsing msgid? */
if ((msgid = strchr(line, '<')) && (line = strchr(msgid+1, '>'))){
line[1] = 0;
count--;
i--;
}
-
+
camel_message_info_free(mi);
}
}
camel_message_info_free(mi);
}
}
-
+
if (si->info.unread != unread
|| si->info.total != count
|| si->first != f
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-grouplist.h : getting/updating the list of newsgroups on the server. */
-/*
- * Author : Chris Toshok <toshok@ximian.com>
+/*
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 2000 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-utils.c : utilities used by the nntp code. */
-/*
- * Author : Chris Toshok <toshok@ximian.com>
+/*
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 2000 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
date = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_DATE].index];
message_id = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_MESSAGE_ID].index];
bytes = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_BYTES].index];
-
+
/* if the overview format flagged this
field as "full", skip over the
preceding field name and colon */
char *line;
int line_length;
- line = camel_stream_buffer_read_line (
+ line = camel_stream_buffer_read_line (
CAMEL_STREAM_BUFFER ( nntp_istream ));
line_length = strlen ( line );
char *brk;
CamelMessageInfo *minfo;
int ret;
-
+
minfo = camel_folder_summary_index(summary, index);
if(minfo == NULL)
return 0;
tmp = g_strdup(camel_message_info_uid(minfo));
camel_message_info_free(minfo);
-
+
if((brk = strchr(tmp, ',')) == NULL)
ret = 0;
else {
*brk = 0;
ret = atoi(tmp);
}
-
+
g_free(tmp);
-
+
return ret;
}
if(last_summary < first_message)
camel_folder_summary_clear(folder->summary);
else {
- while(uid_num(folder->summary, 0) < first_message)
+ while(uid_num(folder->summary, 0) < first_message)
camel_folder_summary_remove_index(folder->summary, 0);
-
+
if(last_summary >= last_message)
return;
-
+
first_message = last_summary;
}
}
-
+
if (status == NNTP_NO_SUCH_GROUP) {
/* XXX throw invalid group exception */
- camel_exception_setv (ex,
+ camel_exception_setv (ex,
CAMEL_EXCEPTION_FOLDER_INVALID,
"group %s not found on server",
folder->name);
#if 0
get_HEAD_headers (nntp_store, folder, first_message, last_message, ex);
#endif
- }
+ }
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-utils.h : Utilities for the NNTP provider */
-/*
+/*
*
- * Author : Chris Toshok <toshok@ximian.com>
+ * Author : Chris Toshok <toshok@ximian.com>
*
* Copyright (C) 1999 Ximian .
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
if (pe->stream)
camel_object_unref(pe->stream);
-
+
g_list_free(pe->auth);
if (pe->apop)
g_free(pe->apop);
pe->capa = CAMEL_POP3_CAP_APOP;
pe->auth = g_list_append (pe->auth, &camel_pop3_apop_authtype);
}
-
+
pe->auth = g_list_prepend (pe->auth, &camel_pop3_password_authtype);
-
+
return 0;
}
pe->stream = (CamelPOP3Stream *)camel_pop3_stream_new(source);
pe->state = CAMEL_POP3_ENGINE_AUTH;
pe->flags = flags;
-
+
if (read_greeting (pe) == -1) {
camel_object_unref (pe);
return NULL;
}
-
+
get_capabilities (pe);
-
+
return pe;
}
camel_pop3_engine_reget_capabilities (CamelPOP3Engine *engine)
{
g_return_if_fail (CAMEL_IS_POP3_ENGINE (engine));
-
+
get_capabilities (engine);
}
get_capabilities(CamelPOP3Engine *pe)
{
CamelPOP3Command *pc;
-
+
if (!(pe->flags & CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS)) {
pc = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_capa, NULL, "CAPA\r\n");
while (camel_pop3_engine_iterate(pe, pc) > 0)
;
camel_pop3_engine_command_free(pe, pc);
-
+
if (pe->state == CAMEL_POP3_ENGINE_TRANSACTION && !(pe->capa & CAMEL_POP3_CAP_UIDL)) {
/* check for UIDL support manually */
pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, "UIDL 1\r\n");
while (camel_pop3_engine_iterate (pe, pc) > 0)
;
-
+
if (pc->state == CAMEL_POP3_COMMAND_OK)
pe->capa |= CAMEL_POP3_CAP_UIDL;
-
+
camel_pop3_engine_command_free (pe, pc);
}
}
/* Set next command */
pe->current = (CamelPOP3Command *)e_dlist_remhead(&pe->active);
-
+
/* check the queue for sending any we can now send also */
pw = (CamelPOP3Command *)pe->queue.head;
pn = pw->next;
pc->func = func;
pc->func_data = data;
pc->flags = flags;
-
+
va_start(ap, fmt);
pc->data = g_strdup_vprintf(fmt, ap);
pc->state = CAMEL_POP3_COMMAND_IDLE;
struct _CamelPOP3Engine {
CamelObject parent;
-
+
guint32 flags;
-
+
camel_pop3_engine_t state;
GList *auth; /* authtypes supported */
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-folder.c : class for a pop3 folder */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_pop3_folder_class_init (CamelPOP3FolderClass *camel_pop3_folder_class)
{
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_pop3_folder_class);
-
+
parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type());
-
+
/* virtual method overload */
camel_folder_class->refresh_info = pop3_refresh_info;
camel_folder_class->sync = pop3_sync;
-
+
camel_folder_class->get_message_count = pop3_get_message_count;
camel_folder_class->get_uids = pop3_get_uids;
camel_folder_class->free_uids = camel_folder_free_shallow;
-
+
camel_folder_class->get_message = pop3_get_message;
camel_folder_class->set_message_flags = pop3_set_message_flags;
}
camel_pop3_folder_get_type (void)
{
static CamelType camel_pop3_folder_type = CAMEL_INVALID_TYPE;
-
+
if (!camel_pop3_folder_type) {
camel_pop3_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelPOP3Folder",
sizeof (CamelPOP3Folder),
NULL,
(CamelObjectFinalizeFunc) pop3_finalize);
}
-
+
return camel_pop3_folder_type;
}
;
camel_pop3_engine_command_free(pop3_store->engine, fi[0]->cmd);
}
-
+
g_free(fi[0]->uid);
g_free(fi[0]);
}
-
+
g_ptr_array_free(pop3_folder->uids, TRUE);
g_hash_table_destroy(pop3_folder->uids_uid);
}
CamelFolder *folder;
d(printf("opening pop3 INBOX folder\n"));
-
+
folder = CAMEL_FOLDER (camel_object_new (CAMEL_POP3_FOLDER_TYPE));
camel_folder_construct (folder, parent, "inbox", "inbox");
-
+
/* mt-ok, since we dont have the folder-lock for new() */
camel_folder_refresh_info (folder, ex);/* mt-ok */
if (camel_exception_is_set (ex)) {
camel_object_unref (CAMEL_OBJECT (folder));
folder = NULL;
}
-
+
return folder;
}
unsigned int id;
CamelPOP3FolderInfo *fi;
CamelPOP3Folder *folder = data;
-
+
do {
ret = camel_pop3_stream_line(stream, &line, &len);
if (ret>=0) {
} while (ret>0);
}
-static void
+static void
pop3_refresh_info (CamelFolder *folder, CamelException *ex)
{
CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store);
}
/* TODO: check every id has a uid & commands returned OK too? */
-
+
camel_pop3_engine_command_free(pop3_store->engine, pcl);
-
+
if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) {
camel_pop3_engine_command_free(pop3_store->engine, pcu);
} else {
/* dont need this anymore */
g_hash_table_destroy(pop3_folder->uids_id);
-
+
camel_operation_end (NULL);
return;
}
time_t temp, message_time;
pop3_folder = CAMEL_POP3_FOLDER (folder);
- pop3_store = CAMEL_POP3_STORE (CAMEL_FOLDER(pop3_folder)->parent_store);
+ pop3_store = CAMEL_POP3_STORE (CAMEL_FOLDER(pop3_folder)->parent_store);
temp = time(&temp);
d(printf("%s(%d): pop3_folder->uids->len=[%d]\n", __FILE__, __LINE__, pop3_folder->uids->len));
int day_lag = time_diff/(60*60*24);
d(printf("%s(%d): message_time= [%ld]\n", __FILE__, __LINE__, message_time));
- d(printf("%s(%d): day_lag=[%d] \t days_to_delete=[%d]\n",
+ d(printf("%s(%d): day_lag=[%d] \t days_to_delete=[%d]\n",
__FILE__, __LINE__, day_lag, days_to_delete));
if( day_lag > days_to_delete)
while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) {
; /* do nothing - iterating until end */
}
-
+
camel_pop3_engine_command_free(pop3_store->engine, fi->cmd);
fi->cmd = NULL;
}
d(printf("%s(%d): Deleting old messages\n", __FILE__, __LINE__));
- fi->cmd = camel_pop3_engine_command_new(pop3_store->engine,
+ fi->cmd = camel_pop3_engine_command_new(pop3_store->engine,
0,
NULL,
NULL,
} else {
fi->err = 0;
}
-
+
camel_object_unref((CamelObject *)fi->stream);
fi->stream = NULL;
}
goto fail;
}
}
-
+
/* check to see if we have safely written flag set */
if (pop3_store->cache == NULL
|| (stream = camel_data_cache_get(pop3_store->cache, "cache", fi->uid, NULL)) == NULL
last = MIN(i+10, pop3_folder->uids->len);
for (;i<last;i++) {
CamelPOP3FolderInfo *pfi = pop3_folder->uids->pdata[i];
-
+
if (pfi->uid && pfi->cmd == NULL) {
pfi->stream = camel_data_cache_add(pop3_store->cache, "cache", pfi->uid, NULL);
if (pfi->stream) {
pop3_get_message_count (CamelFolder *folder)
{
CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder);
-
+
return pop3_folder->uids->len;
}
if (fi[0]->uid)
g_ptr_array_add(uids, fi[0]->uid);
}
-
+
return uids;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-folder.h : Class for a POP3 folder */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelFolderClass parent_class;
- /* Virtual methods */
-
+ /* Virtual methods */
+
} CamelPOP3FolderClass;
/* public methods */
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-provider.c: pop3 provider registration code */
-/*
+/*
* Authors :
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
static CamelProvider pop3_provider = {
"pop",
-
+
N_("POP"),
-
+
N_("For connecting to and downloading mail from POP servers."),
-
+
"mail",
-
+
CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
CAMEL_PROVIDER_SUPPORTS_SSL,
-
+
CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,
-
+
pop3_conf_entries,
-
+
/* ... */
};
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-store.c : class for a pop3 store */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
static gboolean pop3_disconnect (CamelService *service, gboolean clean, CamelException *ex);
static GList *query_auth_types (CamelService *service, CamelException *ex);
-static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
+static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
guint32 flags, CamelException *ex);
static CamelFolder *get_trash (CamelStore *store, CamelException *ex);
CAMEL_STORE_CLASS (camel_pop3_store_class);
parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ()));
-
+
/* virtual method overload */
camel_service_class->query_auth_types = query_auth_types;
camel_service_class->connect = pop3_connect;
int clean_quit = TRUE;
int ret;
const gchar *delete_days;
-
+
if (ssl_mode != MODE_CLEAR) {
#ifdef HAVE_SSL
if (ssl_mode == MODE_TLS) {
camel_object_unref (tcp_stream);
return FALSE;
}
-
+
if (ssl_mode != MODE_TLS) {
camel_object_unref (tcp_stream);
return TRUE;
}
-
+
#ifdef HAVE_SSL
/* as soon as we send a STLS command, all hope is lost of a clean QUIT if problems arise */
clean_quit = FALSE;
;
camel_pop3_engine_command_free (store->engine, pc);
}
-
+
camel_object_unref (CAMEL_OBJECT (store->engine));
camel_object_unref (CAMEL_OBJECT (tcp_stream));
store->engine = NULL;
-
+
return FALSE;
}
serv = "pop3";
port = POP3S_PORT;
}
-
+
if (service->url->port) {
serv = g_alloca (16);
sprintf (serv, "%d", service->url->port);
port = NULL;
}
-
+
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
camel_exception_clear (ex);
ai = camel_getaddrinfo(service->url->host, port, &hints, ex);
}
-
+
if (ai == NULL)
return FALSE;
-
+
ret = connect_to_server (service, ai, mode, ex);
-
+
camel_freeaddrinfo (ai);
-
+
return ret;
}
}
camel_object_unref((CamelObject *)sasl);
return 0;
-
+
ioerror:
if (errno == EINTR) {
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled"));
return try_sasl(store, service->url->authmech, ex) == -1;
l = l->next;
}
-
+
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID,
_("Unable to connect to POP server %s: "
"No support for requested authentication mechanism."),
CAMEL_SERVICE (store)->url->host);
return FALSE;
}
-
+
while ((status = camel_pop3_engine_iterate(store->engine, pcp)) > 0)
;
-
+
if (status == -1) {
if (errno == EINTR) {
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled"));
CamelSession *session;
char *errbuf = NULL;
int status;
-
+
session = camel_service_get_session (service);
-
+
if (store->cache == NULL) {
char *root;
}
}
}
-
+
if (!connect_to_server_wrapper (service, ex))
return FALSE;
-
+
while (1) {
status = pop3_try_authenticate (service, reprompt, errbuf, ex);
g_free (errbuf);
errbuf = NULL;
-
+
/* we only re-prompt if we failed to authenticate, any other error and we just abort */
if (status == 0 && camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE) {
errbuf = g_markup_printf_escaped ("%s\n\n", camel_exception_get_description (ex));
} else
break;
}
-
+
g_free (errbuf);
-
+
if (status == -1 || camel_exception_is_set(ex)) {
camel_service_disconnect(service, TRUE, ex);
return FALSE;
}
-
+
/* Now that we are in the TRANSACTION state, try regetting the capabilities */
store->engine->state = CAMEL_POP3_ENGINE_TRANSACTION;
camel_pop3_engine_reget_capabilities (store->engine);
-
+
return TRUE;
}
pop3_disconnect (CamelService *service, gboolean clean, CamelException *ex)
{
CamelPOP3Store *store = CAMEL_POP3_STORE (service);
-
+
if (clean) {
CamelPOP3Command *pc;
-
+
pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "QUIT\r\n");
while (camel_pop3_engine_iterate(store->engine, NULL) > 0)
;
camel_pop3_engine_command_free(store->engine, pc);
}
-
+
if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex))
return FALSE;
-
+
camel_object_unref((CamelObject *)store->engine);
store->engine = NULL;
-
+
return TRUE;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-pop3-store.h : class for an pop3 store */
-/*
+/*
* Authors:
* Dan Winship <danw@ximian.com>
* Michael Zucchi <notzed@ximian.com>
*
* Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
CamelPOP3Engine *engine; /* pop processing engine */
struct _CamelDataCache *cache;
-
+
guint delete_after;
} CamelPOP3Store;
stream_write(CamelStream *stream, const char *buffer, size_t n)
{
CamelPOP3Stream *is = (CamelPOP3Stream *)stream;
-
+
if (strncmp (buffer, "PASS ", 5) != 0)
dd(printf("POP3_STREAM_WRITE(%d):\n%.*s\n", (int)n, (int)n, buffer));
else
dd(printf("POP3_STREAM_WRITE(%d):\nPASS xxxxxxxx\n", (int)n));
-
+
return camel_stream_write(is->source, buffer, n);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-sendmail-provider.c: sendmail provider registration code */
-/*
+/*
* Authors :
* Dan Winship <danw@ximian.com>
*
* Copyright (C) 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_provider_module_init(void)
{
sendmail_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = camel_sendmail_transport_get_type();
-
+
sendmail_provider.url_hash = camel_url_hash;
sendmail_provider.url_equal = camel_url_equal;
sendmail_provider.translation_domain = GETTEXT_PACKAGE;
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-sendmail-transport.c: Sendmail-based transport class. */
-/*
+/*
*
* Authors: Dan Winship <danw@ximian.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
camel_sendmail_transport_get_type (void)
{
static CamelType camel_sendmail_transport_type = CAMEL_INVALID_TYPE;
-
+
if (camel_sendmail_transport_type == CAMEL_INVALID_TYPE) {
camel_sendmail_transport_type =
camel_type_register (CAMEL_TRANSPORT_TYPE, "CamelSendmailTransport",
(CamelObjectInitFunc) NULL,
NULL);
}
-
+
return camel_sendmail_transport_type;
}
sigset_t mask, omask;
CamelStream *out;
pid_t pid;
-
+
if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &from_addr))
return FALSE;
-
+
len = camel_address_length (recipients);
argv = g_malloc ((len + 6) * sizeof (char *));
argv[0] = "sendmail";
argv[2] = "-f";
argv[3] = from_addr;
argv[4] = "--";
-
+
for (i = 0; i < len; i++) {
if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
g_free (argv);
return FALSE;
}
-
+
argv[i + 5] = addr;
}
-
+
argv[i + 5] = NULL;
-
+
/* unlink the bcc headers */
savedbcc = NULL;
tail = (struct _camel_header_raw *) &savedbcc;
-
+
header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers;
n = header->next;
while (n != NULL) {
} else {
header = n;
}
-
+
n = header->next;
}
-
+
if (pipe (fd) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not create pipe to sendmail: "
"%s: mail not sent"),
g_strerror (errno));
-
+
/* restore the bcc headers */
header->next = savedbcc;
-
+
return FALSE;
}
-
+
/* Block SIGCHLD so the calling application doesn't notice
* sendmail exiting before we do.
*/
sigemptyset (&mask);
sigaddset (&mask, SIGCHLD);
sigprocmask (SIG_BLOCK, &mask, &omask);
-
+
pid = fork ();
switch (pid) {
case -1:
close (fd[1]);
sigprocmask (SIG_SETMASK, &omask, NULL);
g_free (argv);
-
+
/* restore the bcc headers */
header->next = savedbcc;
-
+
return FALSE;
case 0:
/* Child process */
dup2 (nullfd, STDERR_FILENO);*/
close (nullfd);
close (fd[1]);
-
+
execv (SENDMAIL_PATH, (char **)argv);
_exit (255);
}
g_free (argv);
-
+
/* Parent process. Write the message out. */
close (fd[0]);
out = camel_stream_fs_new_with_fd (fd[1]);
-
+
/* workaround for lame sendmail implementations that can't handle CRLF eoln sequences */
filter = camel_stream_filter_new_with_stream (out);
crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
camel_stream_filter_add (filter, crlf);
camel_object_unref (crlf);
camel_object_unref (out);
-
+
out = (CamelStream *) filter;
if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), out) == -1
|| camel_stream_close (out) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Could not send message: %s"),
g_strerror (errno));
-
+
/* Wait for sendmail to exit. */
while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR)
;
-
+
sigprocmask (SIG_SETMASK, &omask, NULL);
-
+
/* restore the bcc headers */
header->next = savedbcc;
-
+
return FALSE;
}
-
+
camel_object_unref (CAMEL_OBJECT (out));
-
+
/* Wait for sendmail to exit. */
while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR)
;
-
+
sigprocmask (SIG_SETMASK, &omask, NULL);
-
+
/* restore the bcc headers */
header->next = savedbcc;
-
+
if (!WIFEXITED (wstat)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("sendmail exited with signal %s: "
}
return FALSE;
}
-
+
return TRUE;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-sendmail-transport.h: Sendmail-based transport class */
-/*
+/*
*
- * Author :
+ * Author :
* Dan Winship <danw@ximian.com>
*
* Copyright 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
smtp_provider.url_hash = camel_url_hash;
smtp_provider.url_equal = camel_url_equal;
smtp_provider.translation_domain = GETTEXT_PACKAGE;
-
+
camel_provider_register(&smtp_provider);
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-smtp-transport.c : class for a smtp transport */
-/*
+/*
* Authors: Jeffrey Stedfast <fejj@ximian.com>
*
* Copyright (C) 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
CAMEL_TRANSPORT_CLASS (camel_smtp_transport_class);
CamelServiceClass *camel_service_class =
CAMEL_SERVICE_CLASS (camel_smtp_transport_class);
-
+
parent_class = CAMEL_TRANSPORT_CLASS (camel_type_get_global_classfuncs (camel_transport_get_type ()));
-
+
/* virtual method overload */
camel_service_class->construct = smtp_construct;
camel_service_class->connect = smtp_connect;
camel_service_class->disconnect = smtp_disconnect;
camel_service_class->query_auth_types = query_auth_types;
camel_service_class->get_name = get_name;
-
+
camel_transport_class->send_to = smtp_send_to;
}
camel_smtp_transport_init (gpointer object)
{
CamelSmtpTransport *smtp = CAMEL_SMTP_TRANSPORT (object);
-
+
smtp->flags = 0;
smtp->connected = FALSE;
}
camel_smtp_transport_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (CAMEL_TRANSPORT_TYPE,
"CamelSmtpTransport",
(CamelObjectInitFunc) camel_smtp_transport_init,
NULL);
}
-
+
return type;
}
return _("Start mail input; end with <CRLF>.<CRLF>");
case 554:
return _("Transaction failed");
-
+
/* AUTH error codes: */
case 432:
return _("A password transition is needed");
return _("Temporary authentication failure");
case 530:
return _("Authentication required");
-
+
default:
return _("Unknown");
}
CamelStream *tcp_stream;
char *respbuf = NULL;
int ret;
-
+
if (!CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex))
return FALSE;
-
+
/* set some smtp transport defaults */
transport->flags = 0;
transport->authtypes = NULL;
-
+
if (ssl_mode != MODE_CLEAR) {
#ifdef HAVE_SSL
if (ssl_mode == MODE_TLS) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Could not connect to %s: %s"),
service->url->host, _("SSL unavailable"));
-
+
return FALSE;
#endif /* HAVE_SSL */
} else {
tcp_stream = camel_tcp_stream_raw_new ();
}
-
+
if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) {
if (errno == EINTR)
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
_("Could not connect to %s: %s"),
service->url->host, g_strerror (errno));
-
+
camel_object_unref (tcp_stream);
-
+
return FALSE;
}
-
+
transport->connected = TRUE;
-
+
/* get the localaddr - needed later by smtp_helo */
transport->localaddr = camel_tcp_stream_get_local_address (CAMEL_TCP_STREAM (tcp_stream), &transport->localaddrlen);
-
+
transport->ostream = tcp_stream;
transport->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
-
+
/* Read the greeting, note whether the server is ESMTP or not. */
do {
/* Check for "220" */
g_strerror (errno));
goto exception_cleanup;
}
-
+
respbuf = NULL;
-
+
do {
/* Check for "220 Ready for TLS" */
g_free (respbuf);
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "220", 3)) {
smtp_set_exception (transport, FALSE, respbuf, _("STARTTLS command failed"), ex);
g_free (respbuf);
goto exception_cleanup;
}
} while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */
-
+
/* Okay, now toggle SSL/TLS mode */
if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
int mode, ret, i;
char *serv;
const char *port;
-
+
if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) {
for (i = 0; ssl_options[i].value; i++)
if (!strcmp (ssl_options[i].value, ssl_mode))
serv = "smtp";
port = SMTP_PORT;
}
-
+
if (service->url->port) {
serv = g_alloca (16);
sprintf (serv, "%d", service->url->port);
port = NULL;
}
-
+
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = PF_UNSPEC;
camel_exception_clear (ex);
ai = camel_getaddrinfo(service->url->host, port, &hints, ex);
}
-
+
if (ai == NULL)
return FALSE;
-
+
ret = connect_to_server (service, ai, mode, ex);
-
+
camel_freeaddrinfo (ai);
-
+
return ret;
}
{
CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
gboolean has_authtypes;
-
+
/* We (probably) need to check popb4smtp before we connect ... */
if (service->url->authmech && !strcmp (service->url->authmech, "POPB4SMTP")) {
int truth;
GByteArray *chal;
CamelSasl *sasl;
-
+
sasl = camel_sasl_new ("smtp", "POPB4SMTP", service);
chal = camel_sasl_challenge (sasl, NULL, ex);
truth = camel_sasl_authenticated (sasl);
if (chal)
g_byte_array_free (chal, TRUE);
camel_object_unref (sasl);
-
+
if (!truth)
return FALSE;
-
+
return connect_to_server_wrapper (service, ex);
}
-
+
if (!connect_to_server_wrapper (service, ex))
return FALSE;
-
+
/* check to see if AUTH is required, if so...then AUTH ourselves */
has_authtypes = transport->authtypes ? g_hash_table_size (transport->authtypes) > 0 : FALSE;
if (service->url->authmech && (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) && has_authtypes) {
CamelServiceAuthType *authtype;
gboolean authenticated = FALSE;
char *errbuf = NULL;
-
+
if (!g_hash_table_lookup (transport->authtypes, service->url->authmech)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("SMTP server %s does not support requested "
camel_service_disconnect (service, TRUE, NULL);
return FALSE;
}
-
+
authtype = camel_sasl_authtype (service->url->authmech);
if (!authtype) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
camel_service_disconnect (service, TRUE, NULL);
return FALSE;
}
-
+
if (!authtype->need_password) {
/* authentication mechanism doesn't need a password,
so if it fails there's nothing we can do */
return FALSE;
}
}
-
+
/* keep trying to login until either we succeed or the user cancels */
while (!authenticated) {
if (errbuf) {
}
}
}
-
+
return TRUE;
}
smtp_disconnect (CamelService *service, gboolean clean, CamelException *ex)
{
CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
-
+
/*if (!service->connected)
* return TRUE;
*/
-
+
if (transport->connected && clean) {
/* send the QUIT command to the SMTP server */
smtp_quit (transport, ex);
}
-
+
if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex))
return FALSE;
-
+
if (transport->authtypes) {
g_hash_table_foreach (transport->authtypes, authtypes_free, NULL);
g_hash_table_destroy (transport->authtypes);
transport->authtypes = NULL;
}
-
+
if (transport->istream) {
camel_object_unref (transport->istream);
transport->istream = NULL;
}
-
+
if (transport->ostream) {
camel_object_unref (transport->ostream);
transport->ostream = NULL;
}
-
+
g_free(transport->localaddr);
transport->localaddr = NULL;
-
+
transport->connected = FALSE;
-
+
return TRUE;
}
CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
CamelServiceAuthType *authtype;
GList *types, *t, *next;
-
+
if (!connect_to_server_wrapper (service, ex))
return NULL;
-
+
types = g_list_copy (service->provider->authtypes);
for (t = types; t; t = next) {
authtype = t->data;
next = t->next;
-
+
if (!g_hash_table_lookup (transport->authtypes, authtype->authproto)) {
types = g_list_remove_link (types, t);
g_list_free_1 (t);
}
}
-
+
smtp_disconnect (service, TRUE, NULL);
-
+
return types;
}
gboolean has_8bit_parts;
const char *addr;
int i, len;
-
+
if (!smtp_transport->connected) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED,
_("Cannot send message: service not connected."));
return FALSE;
}
-
+
if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &addr)) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot send message: sender address not valid."));
return FALSE;
}
-
+
camel_operation_start (NULL, _("Sending message"));
-
+
/* find out if the message has 8bit mime parts */
has_8bit_parts = camel_mime_message_has_8bit_parts (message);
-
+
/* rfc1652 (8BITMIME) requires that you notify the ESMTP daemon that
you'll be sending an 8bit mime message at "MAIL FROM:" time. */
if (!smtp_mail (smtp_transport, addr, has_8bit_parts, ex)) {
camel_operation_end (NULL);
return FALSE;
}
-
+
len = camel_address_length (recipients);
if (len == 0) {
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
camel_operation_end (NULL);
return FALSE;
}
-
+
cia = CAMEL_INTERNET_ADDRESS (recipients);
for (i = 0; i < len; i++) {
char *enc;
-
+
if (!camel_internet_address_get (cia, i, NULL, &addr)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
_("Cannot send message: one or more invalid recipients"));
camel_operation_end (NULL);
return FALSE;
}
-
+
enc = camel_internet_address_encode_address(NULL, NULL, addr);
if (!smtp_rcpt (smtp_transport, enc, ex)) {
g_free(enc);
}
g_free(enc);
}
-
+
if (!smtp_data (smtp_transport, message, ex)) {
camel_operation_end (NULL);
return FALSE;
}
-
+
/* reset the service for our next transfer session */
if (!smtp_rset (smtp_transport, ex))
camel_exception_clear (ex);
-
+
camel_operation_end (NULL);
-
+
return TRUE;
}
smtp_next_token (const char *buf)
{
const unsigned char *token;
-
+
token = (const unsigned char *) buf;
while (*token && !isspace ((int) *token))
token++;
-
+
while (*token && isspace ((int) *token))
token++;
-
+
return (const char *) token;
}
} else
*outptr++ = *inptr++;
}
-
+
*outptr = '\0';
-
+
return outbuf;
}
g_string_free (string, TRUE);
goto fake_status_code;
}
-
+
g_string_append (string, token);
if (*(rbuf + 3) == '-') {
g_free (buffer);
const char *token, *numeric = NULL;
struct sockaddr *addr;
socklen_t addrlen;
-
+
/* these are flags that we set, so unset them in case we
are being called a second time (ie, after a STARTTLS) */
transport->flags &= ~(CAMEL_SMTP_TRANSPORT_8BITMIME |
CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES |
CAMEL_SMTP_TRANSPORT_STARTTLS);
-
+
if (transport->authtypes) {
g_hash_table_foreach (transport->authtypes, authtypes_free, NULL);
g_hash_table_destroy (transport->authtypes);
transport->authtypes = NULL;
}
-
+
camel_operation_start_transient (NULL, _("SMTP Greeting"));
-
+
addr = transport->localaddr;
addrlen = transport->localaddrlen;
-
+
if (camel_getnameinfo (addr, addrlen, &name, NULL, NI_NUMERICHOST, NULL) != 0) {
name = g_strdup ("localhost.localdomain");
} else {
char *cmdbuf, *respbuf = NULL, *challenge;
gboolean auth_challenge = FALSE;
CamelSasl *sasl = NULL;
-
+
camel_operation_start_transient (NULL, _("SMTP Authentication"));
-
+
sasl = camel_sasl_new ("smtp", mech, CAMEL_SERVICE (transport));
if (!sasl) {
camel_operation_end (NULL);
_("Error creating SASL authentication object."));
return FALSE;
}
-
+
challenge = camel_sasl_challenge_base64 (sasl, NULL, ex);
if (challenge) {
auth_challenge = TRUE;
} else {
cmdbuf = g_strdup_printf ("AUTH %s\r\n", mech);
}
-
+
d(fprintf (stderr, "sending : %s", cmdbuf));
if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
g_free (cmdbuf);
goto lose;
}
g_free (cmdbuf);
-
+
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
while (!camel_sasl_authenticated (sasl)) {
if (!respbuf) {
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("AUTH command failed: %s"), g_strerror (errno));
goto lose;
}
-
+
/* the server challenge/response should follow a 334 code */
if (strncmp (respbuf, "334", 3) != 0) {
smtp_set_exception (transport, FALSE, respbuf, _("AUTH command failed"), ex);
g_free (respbuf);
goto lose;
}
-
+
if (FALSE) {
broken_smtp_server:
d(fprintf (stderr, "Your SMTP server's implementation of the %s SASL\n"
"for the first time (specifically Section 4).\n",
mech));
}
-
+
/* eat whtspc */
for (challenge = respbuf + 4; isspace (*challenge); challenge++);
-
+
challenge = camel_sasl_challenge_base64 (sasl, challenge, ex);
g_free (respbuf);
if (challenge == NULL)
goto break_and_lose;
-
+
/* send our challenge */
cmdbuf = g_strdup_printf ("%s\r\n", challenge);
g_free (challenge);
goto lose;
}
g_free (cmdbuf);
-
+
/* get the server's response */
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
}
-
+
/* check that the server says we are authenticated */
if (!respbuf || strncmp (respbuf, "235", 3)) {
if (respbuf && auth_challenge && !strncmp (respbuf, "334", 3)) {
g_free (respbuf);
goto lose;
}
-
+
g_free (respbuf);
camel_object_unref (sasl);
camel_operation_end (NULL);
-
+
return TRUE;
-
+
break_and_lose:
/* Get the server out of "waiting for continuation data" mode. */
d(fprintf (stderr, "sending : *\n"));
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
g_free (respbuf);
-
+
lose:
if (!camel_exception_is_set (ex)) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
_("Bad authentication response from server.\n"));
}
-
+
camel_object_unref (sasl);
camel_operation_end (NULL);
-
+
return FALSE;
}
{
/* we gotta tell the smtp server who we are. (our email addy) */
char *cmdbuf, *respbuf = NULL;
-
+
if (transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME && has_8bit_parts)
cmdbuf = g_strdup_printf ("MAIL FROM:<%s> BODY=8BITMIME\r\n", sender);
else
cmdbuf = g_strdup_printf ("MAIL FROM:<%s>\r\n", sender);
-
+
d(fprintf (stderr, "sending : %s", cmdbuf));
-
+
if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
g_free (cmdbuf);
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("MAIL FROM command failed: %s: mail not sent"),
g_strerror (errno));
-
+
camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
+
return FALSE;
}
g_free (cmdbuf);
-
+
do {
/* Check for "250 Sender OK..." */
g_free (respbuf);
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "250", 3)) {
smtp_set_exception (transport, TRUE, respbuf, _("MAIL FROM command failed"), ex);
g_free (respbuf);
}
} while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
g_free (respbuf);
-
+
return TRUE;
}
/* we gotta tell the smtp server who we are going to be sending
* our email to */
char *cmdbuf, *respbuf = NULL;
-
+
cmdbuf = g_strdup_printf ("RCPT TO:<%s>\r\n", recipient);
-
+
d(fprintf (stderr, "sending : %s", cmdbuf));
-
+
if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
g_free (cmdbuf);
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("RCPT TO command failed: %s: mail not sent"),
g_strerror (errno));
-
+
camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
+
return FALSE;
}
g_free (cmdbuf);
-
+
do {
/* Check for "250 Recipient OK..." */
g_free (respbuf);
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "250", 3)) {
char *message;
-
+
message = g_strdup_printf (_("RCPT TO <%s> failed"), recipient);
smtp_set_exception (transport, TRUE, respbuf, message, ex);
g_free (message);
}
} while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
g_free (respbuf);
-
+
return TRUE;
}
CamelStreamFilter *filtered_stream;
CamelMimeFilter *crlffilter;
int ret;
-
+
/* If the server doesn't support 8BITMIME, set our required encoding to be 7bit */
if (!(transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME))
enctype = CAMEL_BESTENC_7BIT;
-
+
/* FIXME: should we get the best charset too?? */
/* Changes the encoding of all mime parts to fit within our required
encoding type and also force any text parts with long lines (longer
than 998 octets) to wrap by QP or base64 encoding them. */
camel_mime_message_set_best_encoding (message, CAMEL_BESTENC_GET_ENCODING, enctype);
-
+
cmdbuf = g_strdup ("DATA\r\n");
-
+
d(fprintf (stderr, "sending : %s", cmdbuf));
-
+
if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
g_free (cmdbuf);
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("DATA command failed: %s: mail not sent"),
g_strerror (errno));
-
+
camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
+
return FALSE;
}
g_free (cmdbuf);
-
+
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "354", 3)) {
/* we should have gotten instructions on how to use the DATA command:
* 354 Enter mail, end with "." on a line by itself
g_free (respbuf);
return FALSE;
}
-
+
g_free (respbuf);
respbuf = NULL;
-
+
/* setup stream filtering */
crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
filtered_stream = camel_stream_filter_new_with_stream (transport->ostream);
camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlffilter));
camel_object_unref (crlffilter);
-
+
/* unlink the bcc headers */
savedbcc = NULL;
tail = (struct _camel_header_raw *) &savedbcc;
-
+
header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers;
n = header->next;
while (n != NULL) {
} else {
header = n;
}
-
+
n = header->next;
}
-
+
/* write the message */
ret = camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (filtered_stream));
-
+
/* restore the bcc headers */
header->next = savedbcc;
-
+
if (ret == -1) {
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("DATA command failed: %s: mail not sent"),
g_strerror (errno));
-
+
camel_object_unref (filtered_stream);
-
+
camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
+
return FALSE;
}
-
+
camel_stream_flush (CAMEL_STREAM (filtered_stream));
camel_object_unref (filtered_stream);
-
+
/* terminate the message body */
-
+
d(fprintf (stderr, "sending : \\r\\n.\\r\\n\n"));
-
+
if (camel_stream_write (transport->ostream, "\r\n.\r\n", 5) == -1) {
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("DATA command failed: %s: mail not sent"),
g_strerror (errno));
-
+
camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
+
return FALSE;
}
-
+
do {
/* Check for "250 Sender OK..." */
g_free (respbuf);
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "250", 3)) {
smtp_set_exception (transport, TRUE, respbuf, _("DATA command failed"), ex);
g_free (respbuf);
}
} while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
g_free (respbuf);
-
+
return TRUE;
}
{
/* we are going to reset the smtp server (just to be nice) */
char *cmdbuf, *respbuf = NULL;
-
+
cmdbuf = g_strdup ("RSET\r\n");
-
+
d(fprintf (stderr, "sending : %s", cmdbuf));
-
+
if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
g_free (cmdbuf);
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("RSET command failed: %s"), g_strerror (errno));
-
+
camel_service_disconnect ((CamelService *) transport, FALSE, NULL);
-
+
return FALSE;
}
g_free (cmdbuf);
-
+
do {
/* Check for "250" */
g_free (respbuf);
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "250", 3)) {
smtp_set_exception (transport, TRUE, respbuf, _("RSET command failed"), ex);
g_free (respbuf);
}
} while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
g_free (respbuf);
-
+
return TRUE;
}
{
/* we are going to reset the smtp server (just to be nice) */
char *cmdbuf, *respbuf = NULL;
-
+
cmdbuf = g_strdup ("QUIT\r\n");
-
+
d(fprintf (stderr, "sending : %s", cmdbuf));
-
+
if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) {
g_free (cmdbuf);
camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM,
_("QUIT command failed: %s"), g_strerror (errno));
-
+
return FALSE;
}
g_free (cmdbuf);
-
+
do {
/* Check for "221" */
g_free (respbuf);
respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream));
-
+
d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
-
+
if (!respbuf || strncmp (respbuf, "221", 3)) {
smtp_set_exception (transport, FALSE, respbuf, _("QUIT command failed"), ex);
g_free (respbuf);
} while (*(respbuf+3) == '-'); /* if we got "221-" then loop again */
g_free (respbuf);
-
+
return TRUE;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-smtp-transport.h : class for an smtp transfer */
-/*
+/*
* Authors:
* Jeffrey Stedfast <fejj@stampede.org>
*
* Copyright (C) 2000 Ximian, Inc. (www.ximian.com)
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
typedef struct {
CamelTransport parent_object;
-
+
CamelStream *istream, *ostream;
-
+
guint32 flags;
-
+
gboolean connected;
struct sockaddr *localaddr;
socklen_t localaddrlen;
-
+
GHashTable *authtypes;
} CamelSmtpTransport;
#define MAX_LOOP (10000)
#define MAX_THREADS (5)
-#define d(x)
+#define d(x)
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
camel_test_push("provider %s", local_providers[j]);
path = g_strdup_printf("%s:///tmp/camel-test/%s", local_providers[j], local_providers[j]);
-
+
for (i=0;i<MAX_THREADS;i++)
pthread_create(&threads[i], 0, worker, NULL);
-
- for (i=0;i<MAX_THREADS;i++)
+
+ for (i=0;i<MAX_THREADS;i++)
pthread_join(threads[i], NULL);
-
+
test_free(path);
camel_test_pull();
#define MAX_LOOP (10000)
#define MAX_THREADS (5)
-#define d(x)
+#define d(x)
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
char *expr;
} searches[] = {
{ { 1, 1, 0 }, "(header-matches \"subject\" \"Test1 message99 subject\")" },
-
+
{ { 100, 50, 0 }, "(header-contains \"subject\" \"subject\")" },
{ { 100, 50, 0 }, "(header-contains \"subject\" \"Subject\")" },
{ { 100/13+1, 50/13+1, 0 }, "(user-flag \"every13\")" },
{ { 1, 1, 0 }, "(= \"7tag1\" (user-tag \"every7\"))" },
{ { 100/11+1, 50/11+1, 0 }, "(= \"11tag\" (user-tag \"every11\"))" },
-
+
{ { 100/13 + 100/17 + 1, 50/13 + 50/17 + 2, 0 }, "(user-flag \"every13\" \"every17\")" },
{ { 100/13 + 100/17 + 1, 50/13 + 50/17 + 2, 0 }, "(or (user-flag \"every13\") (user-flag \"every17\"))" },
{ { 1, 0, 0 }, "(and (user-flag \"every13\") (user-flag \"every17\"))" },
-
+
{ { 0, 0, 0 }, "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"Test2\"))" },
/* we get 11 here as the header-contains is a substring match */
{ { 11, 6, 0 }, "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"subject\"))" },
{ { 1, 1, 0 }, "(and (header-contains \"subject\" \"Test19\") (header-contains \"subject\" \"subject\"))" },
{ { 0, 0, 0 }, "(and (header-contains \"subject\" \"Test191\") (header-contains \"subject\" \"subject\"))" },
{ { 1, 1, 0 }, "(and (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"message99\"))" },
-
+
{ { 22, 11, 0 }, "(or (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"Test2\"))" },
{ { 2, 1, 0 }, "(or (header-contains \"subject\" \"Test16\") (header-contains \"subject\" \"Test99\"))" },
{ { 1, 1, 0 }, "(or (header-contains \"subject\" \"Test123\") (header-contains \"subject\" \"Test99\"))" },
{ { 100, 50, 0 }, "(or (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"subject\"))" },
{ { 11, 6, 0 }, "(or (header-contains \"subject\" \"Test1\") (header-contains \"subject\" \"message99\"))" },
-
+
/* 72000 is 24*60*100 == half the 'sent date' of the messages */
{ { 100/2, 50/2, 0 }, "(> 72000 (get-sent-date))" },
{ { 100/2-1, 50/2, 0 }, "(< 72000 (get-sent-date))" },
{ { 1, 0, 0 }, "(= 72000 (get-sent-date))" },
{ { 0, 0, 0 }, "(= 72001 (get-sent-date))" },
-
+
{ { (100/2-1)/17+1, (50/2-1)/17+1, 0 }, "(and (user-flag \"every17\") (< 72000 (get-sent-date)))" },
{ { (100/2-1)/17+1, (50/2-1)/17, 0 }, "(and (user-flag \"every17\") (> 72000 (get-sent-date)))" },
{ { (100/2-1)/13+1, (50/2-1)/13+1, 0 }, "(and (user-flag \"every13\") (< 72000 (get-sent-date)))" },
{ { (100/2-1)/13+1, (50/2-1)/13+1, 0 }, "(and (user-flag \"every13\") (> 72000 (get-sent-date)))" },
-
+
{ { 100/2+100/2/17, 50/2+50/2/17, 0 }, "(or (user-flag \"every17\") (< 72000 (get-sent-date)))" },
{ { 100/2+100/2/17+1, 50/2+50/2/17+1, 0 }, "(or (user-flag \"every17\") (> 72000 (get-sent-date)))" },
{ { 100/2+100/2/13, 50/2+50/2/13+1, 0 }, "(or (user-flag \"every13\") (< 72000 (get-sent-date)))" },
#define MAX_MESSAGES (100)
#define MAX_THREADS (10)
-#define d(x)
+#define d(x)
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
store = camel_session_get_store(session, path, ex);
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
test_free(path);
-
+
if (index == 0)
folder = camel_store_get_folder(store, "testbox", CAMEL_STORE_FOLDER_CREATE, ex);
else
mailboxes[i].folder = folder = camel_store_get_folder(store, mailboxes[i].name, CAMEL_STORE_FOLDER_CREATE, ex);
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
check(folder != NULL);
-
+
/* we need an empty folder for this to work */
test_folder_counts(folder, 0, 0);
pull();
mbox = camel_stream_fs_new_with_name("/tmp/camel-test/inbox", O_WRONLY|O_CREAT|O_EXCL, 0600);
for (j=0;j<100;j++) {
char *content, *subject;
-
+
push("creating test message");
msg = test_message_create_simple();
content = g_strdup_printf("data%d content\n", j);
test_free(content);
subject = g_strdup_printf("Test%d message%d subject", j, 100-j);
camel_mime_message_set_subject(msg, subject);
-
+
camel_mime_message_set_date(msg, j*60*24, 0);
pull();
-
+
camel_stream_printf(mbox, "From \n");
check(camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, mbox) != -1);
-#if 0
+#if 0
push("appending simple message %d", j);
camel_folder_append_message(folder, msg, NULL, ex);
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
pull();
-#endif
+#endif
test_free(subject);
-
+
check_unref(msg, 1);
}
check(camel_stream_close(mbox) != -1);
check(camel_address_length(CAMEL_ADDRESS(addr)) == camel_address_length(CAMEL_ADDRESS(addr2)));
for (j=0;j<camel_address_length(CAMEL_ADDRESS(addr));j++) {
-
+
check(camel_internet_address_get(addr, j, &r1, &a1) == TRUE);
check(camel_internet_address_get(addr2, j, &r2, &a2) == TRUE);
dump_action(int id, struct _state *s, void *d)
{
struct _stack *node;
-
+
printf("\nThread %d:\n", id);
-
+
node = s->state;
if (node) {
printf("Current action:\n");
indie = 1;
printf("\n\nReceived fatal signal %d\n", sig);
g_hash_table_foreach(info_table, (GHFunc)dump_action, 0);
-
+
if (camel_test_verbose > 2) {
printf("Attach debugger to pid %d to debug\n", getpid());
sleep(1000);
}
return info;
}
-
+
void camel_test_init(int argc, char **argv)
{
struct stat st;
char *path;
int i;
-
+
setup = 1;
-
+
/* yeah, we do need ot thread init, even though camel isn't compiled with enable threads */
g_thread_init (NULL);
-
+
path = g_strdup_printf ("/tmp/camel-test");
if (mkdir (path, 0700) == -1 && errno != EEXIST)
abort ();
-
+
if (stat (path, &st) == -1)
abort ();
-
+
if (!S_ISDIR (st.st_mode) || access (path, R_OK | W_OK | X_OK) == -1)
abort ();
-
+
camel_init (path, FALSE);
g_free (path);
-
+
camel_type_init ();
-
+
info_table = g_hash_table_new(0, 0);
-
+
signal(SIGSEGV, die);
signal(SIGABRT, die);
const unsigned char *inptr = in, *start = inptr;
const unsigned char *inend = in + inlen;
int octets;
-
+
while (inptr < inend) {
octets = 0;
while (inptr < inend && octets < 16) {
printf ("%.2X ", *inptr++);
octets++;
}
-
+
while (octets < 16) {
printf (" ");
octets++;
}
-
+
printf (" ");
-
+
while (start < inptr) {
fputc (isprint ((int) *start) ? *start : '.', stdout);
start++;
}
-
+
fputc ('\n', stdout);
}
}
content = (CamelStreamMem *)camel_stream_mem_new();
camel_data_wrapper_decode_to_stream(dw, (CamelStream *)content);
-
+
if (content->buffer->len != len) {
printf ("original text:\n");
hexdump (text, len);
-
+
printf ("new text:\n");
hexdump (content->buffer->data, content->buffer->len);
}
-
+
check_msg(content->buffer->len == len, "buffer->len = %d, len = %d", content->buffer->len, len);
check_msg(memcmp(content->buffer->data, text, content->buffer->len) == 0, "len = %d", len);
{
CamelMimeMessage *msg2;
CamelStreamMem *mem1, *mem2;
-
+
mem1 = (CamelStreamMem *) camel_stream_mem_new ();
check_msg(camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg, (CamelStream *) mem1) != -1, "write_to_stream 1 failed");
camel_stream_reset ((CamelStream *) mem1);
-
+
msg2 = camel_mime_message_new ();
check_msg(camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) msg2, (CamelStream *) mem1) != -1, "construct_from_stream 1 failed");
camel_stream_reset ((CamelStream *) mem1);
-
+
mem2 = (CamelStreamMem *) camel_stream_mem_new ();
check_msg(camel_data_wrapper_write_to_stream ((CamelDataWrapper *) msg2, (CamelStream *) mem2) != -1, "write_to_stream 2 failed");
camel_stream_reset ((CamelStream *) mem2);
-
+
if (mem1->buffer->len != mem2->buffer->len) {
CamelDataWrapper *content;
-
+
printf ("mem1 stream:\n%.*s\n", mem1->buffer->len, mem1->buffer->data);
printf ("mem2 stream:\n%.*s\n\n", mem2->buffer->len, mem2->buffer->data);
}
check_unref(msg2, 1);
-
+
check_msg (mem1->buffer->len == mem2->buffer->len,
"mem1->buffer->len = %d, mem2->buffer->len = %d",
mem1->buffer->len, mem2->buffer->len);
-
+
check_msg (memcmp (mem1->buffer->data, mem2->buffer->data, mem1->buffer->len) == 0, "msg/stream compare");
-
+
camel_object_unref (mem1);
camel_object_unref (mem2);
-
+
return 0;
}
printf("%s part encoding: %s\n", s, camel_transfer_encoding_to_string(part->encoding));
containee = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-
+
if (containee == NULL)
return;
printf ("%sContent-Type: %s\n", s, mime_type);
g_free (mime_type);
printf("%s encoding: %s\n", s, camel_transfer_encoding_to_string(((CamelDataWrapper *)containee)->encoding));
-
+
/* using the object types is more accurate than using the mime/types */
if (CAMEL_IS_MULTIPART (containee)) {
parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
for (i = 0; i < parts; i++) {
CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (containee), i);
-
+
message_dump_rec(msg, part, depth+1);
}
} else if (CAMEL_IS_MIME_MESSAGE (containee)) {
camel_test_session_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (
camel_session_get_type (),
NULL,
NULL);
}
-
+
return type;
}
camel_test_session_new (const char *path)
{
CamelSession *session;
-
+
session = CAMEL_SESSION (camel_object_new (CAMEL_TEST_SESSION_TYPE));
-
+
camel_session_construct (session, path);
-
+
return session;
}
typedef struct _CamelTestSession {
CamelSession parent_object;
-
+
} CamelTestSession;
typedef struct _CamelTestSessionClass {
CamelSessionClass parent_class;
-
+
} CamelTestSessionClass;
CamelType camel_test_session_get_type (void);
test_message_write_file(msg, "test1.msg");
check_unref(msg, 1);
pull();
-
+
push("read from test1.msg");
msg2 = test_message_read_file("test1.msg");
pull();
text = texts[j].text;
len = texts[j].len;
for (i=0;i<CAMEL_TRANSFER_NUM_ENCODINGS;i++) {
-
+
push("test simple message, encoding %s", camel_transfer_encoding_to_string(i));
msg = test_message_create_simple();
test_message_write_file(msg, "test1.msg");
check_unref(msg, 1);
pull();
-
+
push("read from test1.msg");
msg2 = test_message_read_file("test1.msg");
pull();
check(strcmp(format, test_address[i].utf8) == 0);
test_free(format);
pull();
-
+
push("Comparing re-encoded output");
addr2 = CAMEL_INTERNET_ADDRESS(camel_internet_address_new());
enc = camel_address_encode(CAMEL_ADDRESS(addr));
unlink("test3.msg");
test_message_write_file(msg, "test3.msg");
pull();
-
+
push("read from test3.msg");
msg2 = test_message_read_file("test3.msg");
pull();
CamelDataWrapper *content;
char *mime_type;
int i = 0;
-
+
while (i < depth) {
printf (" ");
i++;
}
-
+
content = camel_medium_get_content_object ((CamelMedium *) mime_part);
-
+
mime_type = camel_data_wrapper_get_mime_type (content);
printf ("Content-Type: %s\n", mime_type);
g_free (mime_type);
-
+
if (CAMEL_IS_MULTIPART (content)) {
guint num, index = 0;
-
+
num = camel_multipart_get_number ((CamelMultipart *) content);
while (index < num) {
mime_part = camel_multipart_get_part ((CamelMultipart *) content, index);
struct dirent *dent;
DIR *dir;
int fd;
-
+
camel_test_init (argc, argv);
-
+
camel_test_start ("Message Test Suite");
-
+
if (!(dir = opendir ("../data/messages")))
return 77;
-
+
while ((dent = readdir (dir)) != NULL) {
CamelMimeMessage *message;
CamelStream *stream;
char *filename;
struct stat st;
-
+
if (dent->d_name[0] == '.')
continue;
-
+
filename = g_strdup_printf ("../data/messages/%s", dent->d_name);
if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
g_free (filename);
continue;
}
-
+
if ((fd = open (filename, O_RDONLY)) == -1) {
g_free (filename);
continue;
}
-
+
push ("testing message `%s`", filename);
g_free (filename);
-
+
stream = camel_stream_fs_new_with_fd (fd);
message = camel_mime_message_new ();
camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream);
camel_stream_reset (stream);
-
+
/*dump_mime_struct ((CamelMimePart *) message, 0);*/
test_message_compare (message);
-
+
camel_object_unref (message);
camel_object_unref (stream);
-
+
pull ();
}
-
+
closedir (dir);
-
+
camel_test_end ();
-
+
return 0;
}
#define CHUNK_SIZE 4096
-int
+int
main (int argc, char **argv)
{
ssize_t comp_progress, comp_correct_chunk, comp_filter_chunk;
struct dirent *dent;
int i, test = 0;
DIR *dir;
-
+
camel_test_init(argc, argv);
-
+
dir = opendir (SOURCEDIR);
if (!dir)
return 1;
-
+
while ((dent = readdir (dir))) {
char *infile, *outfile, *charset, *work;
const char *ext;
-
+
ext = strrchr (dent->d_name, '.');
if (!(!strncmp (dent->d_name, "charset-", 8) && ext && !strcmp (ext, ".in")))
continue;
-
+
work = g_strdup_printf ("Charset filter, test case %d (%s)", test++, dent->d_name);
camel_test_start (work);
g_free (work);
-
+
infile = g_strdup_printf ("%s/%s", SOURCEDIR, dent->d_name);
if (!(source = camel_stream_fs_new_with_name (infile, 0, O_RDONLY))) {
camel_test_fail ("Failed to open input case in \"%s\"", infile);
continue;
}
g_free (infile);
-
+
outfile = g_strdup_printf ("%s/%.*s.out", SOURCEDIR, ext - dent->d_name, dent->d_name);
-
+
if (!(correct = camel_stream_fs_new_with_name (outfile, 0, O_RDONLY))) {
camel_test_fail ("Failed to open correct output in \"%s\"", outfile);
g_free (outfile);
continue;
}
g_free (outfile);
-
+
if (!(filter = camel_stream_filter_new_with_stream (CAMEL_STREAM (source)))) {
camel_test_fail ("Couldn't create CamelStreamFilter??");
continue;
}
-
+
charset = g_strdup (dent->d_name + 8);
ext = strchr (charset, '.');
*((char *) ext) = '\0';
-
+
if (!(f = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8"))) {
camel_test_fail ("Couldn't create CamelMimeFilterCharset??");
g_free (charset);
continue;
}
g_free (charset);
-
+
camel_stream_filter_add (filter, f);
camel_object_unref (f);
-
+
camel_test_push ("Running filter and comparing to correct result");
-
+
comp_progress = 0;
-
+
while (1) {
comp_correct_chunk = camel_stream_read (correct, comp_correct, CHUNK_SIZE);
comp_filter_chunk = 0;
-
+
if (comp_correct_chunk == 0)
break;
-
+
while (comp_filter_chunk < comp_correct_chunk) {
ssize_t delta;
-
- delta = camel_stream_read (CAMEL_STREAM (filter),
- comp_filter + comp_filter_chunk,
+
+ delta = camel_stream_read (CAMEL_STREAM (filter),
+ comp_filter + comp_filter_chunk,
CHUNK_SIZE - comp_filter_chunk);
-
+
if (delta == 0) {
camel_test_fail ("Chunks are different sizes: correct is %d, "
"filter is %d, %d bytes into stream",
comp_correct_chunk, comp_filter_chunk, comp_progress);
}
-
+
comp_filter_chunk += delta;
}
-
+
for (i = 0; i < comp_filter_chunk; i++) {
if (comp_correct[i] != comp_filter[i]) {
camel_test_fail ("Difference: correct is %c, filter is %c, "
"%d bytes into stream",
- comp_correct[i],
+ comp_correct[i],
comp_filter[i],
comp_progress + i);
}
}
-
+
comp_progress += comp_filter_chunk;
}
-
+
camel_test_pull ();
-
+
/* inefficient */
camel_test_push ("Cleaning up");
camel_object_unref (CAMEL_OBJECT (filter));
camel_object_unref (CAMEL_OBJECT (correct));
camel_object_unref (CAMEL_OBJECT (source));
camel_test_pull ();
-
+
camel_test_end ();
}
-
+
closedir (dir);
-
+
return 0;
}
CRLF_DONE
};
-int
+int
main (int argc, char **argv)
{
CamelStream *source;
ssize_t comp_progress, comp_correct_chunk, comp_filter_chunk;
int comp_i;
char comp_correct[CHUNK_SIZE], comp_filter[CHUNK_SIZE];
-
+
camel_test_init(argc, argv);
-
+
for (i = 0; i < NUM_CASES; i++) {
int j;
-
+
work = g_strdup_printf ("CRLF/DOT filter, test case %d", i);
camel_test_start (work);
g_free (work);
-
+
for (j = CRLF_ENCODE; j < CRLF_DONE; j++) {
CamelMimeFilterCRLFDirection direction;
char *infile = NULL, *outfile = NULL;
-
+
switch (j) {
case CRLF_ENCODE:
camel_test_push ("Test of the encoder");
default:
break;
}
-
+
camel_test_push ("Initializing objects");
source = camel_stream_fs_new_with_name (infile, 0, O_RDONLY);
if (!source) {
continue;
}
g_free (infile);
-
+
correct = camel_stream_fs_new_with_name (outfile, 0, O_RDONLY);
if (!correct) {
camel_test_fail ("Failed to open correct output in \"%s\"", outfile);
continue;
}
g_free (outfile);
-
+
filter = camel_stream_filter_new_with_stream (CAMEL_STREAM (source));
if (!filter) {
camel_test_fail ("Couldn't create CamelStreamFilter??");
continue;
}
-
+
sh = camel_mime_filter_crlf_new (direction, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS);
if (!sh) {
camel_test_fail ("Couldn't create CamelMimeFilterCrlf??");
continue;
}
-
+
camel_stream_filter_add (filter, sh);
camel_test_pull ();
-
+
camel_test_push ("Running filter and comparing to correct result");
-
+
comp_progress = 0;
-
+
while (1) {
comp_correct_chunk = camel_stream_read (correct, comp_correct, CHUNK_SIZE);
comp_filter_chunk = 0;
-
+
if (comp_correct_chunk == 0)
break;
-
+
while (comp_filter_chunk < comp_correct_chunk) {
ssize_t delta;
-
- delta = camel_stream_read (CAMEL_STREAM (filter),
- comp_filter + comp_filter_chunk,
+
+ delta = camel_stream_read (CAMEL_STREAM (filter),
+ comp_filter + comp_filter_chunk,
CHUNK_SIZE - comp_filter_chunk);
-
+
if (delta == 0) {
camel_test_fail ("Chunks are different sizes: correct is %d, "
"filter is %d, %d bytes into stream",
comp_correct_chunk, comp_filter_chunk, comp_progress);
}
-
+
comp_filter_chunk += delta;
}
-
+
for (comp_i = 0; comp_i < comp_filter_chunk; comp_i++) {
if (comp_correct[comp_i] != comp_filter[comp_i]) {
camel_test_fail ("Difference: correct is %c, filter is %c, "
"%d bytes into stream",
- comp_correct[comp_i],
+ comp_correct[comp_i],
comp_filter[comp_i],
comp_progress + comp_i);
}
}
-
+
comp_progress += comp_filter_chunk;
}
-
+
camel_test_pull ();
-
+
/* inefficient */
camel_test_push ("Cleaning up");
camel_object_unref (CAMEL_OBJECT (filter));
camel_object_unref (CAMEL_OBJECT (source));
camel_object_unref (CAMEL_OBJECT (sh));
camel_test_pull ();
-
+
camel_test_pull ();
}
-
+
camel_test_end ();
}
-
+
return 0;
}
check_count(indisk, 2);
id = camel_stream_filter_add((CamelStreamFilter *)filter, f);
check_count(f, 2);
-
+
check(camel_stream_write_to_stream(filter, (CamelStream *)in) > 0);
check_msg(in->buffer->len == out->buffer->len
&& memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0,
camel_test_pull();
}
-int
+int
main (int argc, char **argv)
{
int i;
camel_test_init(argc, argv);
-
+
camel_test_start("HTML Stream filtering");
for (i=0;i<100;i++) {
"Tasmiania with fur\r\n=46rom here or there ?\r\n" },
};
-int
+int
main (int argc, char **argv)
{
CamelStreamFilter *filter;
CamelMimeFilter *sh;
int i;
-
+
camel_test_init(argc, argv);
camel_test_start("canonicalisation filter tests");
}
camel_test_end();
-
+
return 0;
}
{ "=?iso-8859-1?q?th?= =?iso-8859-1?q?is?= is some text", "this is some text", 0 },
{ "=?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=",
"If you can read this you understand the example.", 0 },
-#if 0
+#if 0
/* And oddly enough, camel fails on these, removed for now */
/* second half: brokenly encoded rfc2047 words */
{
char *decoded;
int i;
-
+
camel_test_init (argc, argv);
-
+
camel_test_start ("rfc2047 decoding");
-
+
for (i = 0; i < G_N_ELEMENTS (test1); i++) {
camel_test_push ("rfc2047 decoding[%d] '%s'", i, test1[i].encoded);
decoded = camel_header_decode_string (test1[i].encoded, "iso-8859-1");
g_free (decoded);
camel_test_pull ();
}
-
+
camel_test_end ();
-
+
camel_test_start ("rfc2047 ctext decoding");
-
+
for (i = 0; i < G_N_ELEMENTS (test2); i++) {
camel_test_push ("rfc2047 ctext decoding[%d] '%s'", i, test2[i].encoded);
decoded = camel_header_format_ctext (test2[i].encoded, "iso-8859-1");
g_free (decoded);
camel_test_pull ();
}
-
+
camel_test_end ();
-
+
return 0;
}
char *html, *url, *p;
int i, errors = 0;
guint32 flags;
-
+
camel_test_init (argc, argv);
-
+
camel_test_start ("URL scanning");
-
+
flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
for (i = 0; i < num_url_tests; i++) {
camel_test_push ("'%s' => '%s'", url_tests[i].text, url_tests[i].url ? url_tests[i].url : "None");
-
+
html = camel_text_to_html (url_tests[i].text, flags, 0);
-
+
url = strstr (html, "href=\"");
if (url) {
url += 6;
p = strchr (url, '"');
if (p)
*p = '\0';
-
+
while ((p = strstr (url, "&")))
memmove (p + 1, p + 5, strlen (p + 5) + 1);
}
-
+
if ((url && (!url_tests[i].url || strcmp (url, url_tests[i].url) != 0)) ||
(!url && url_tests[i].url)) {
printf ("FAILED on \"%s\" -> %s\n (got %s)\n\n",
url ? url : "(nothing)");
errors++;
}
-
+
g_free (html);
}
-
+
printf ("\n%d errors\n", errors);
-
+
camel_test_end ();
-
+
return errors;
}
typedef struct _CamelPgpSession {
CamelSession parent_object;
-
+
} CamelPgpSession;
typedef struct _CamelPgpSessionClass {
CamelSessionClass parent_class;
-
+
} CamelPgpSessionClass;
{
CamelSessionClass *camel_session_class =
CAMEL_SESSION_CLASS (camel_pgp_session_class);
-
+
/* virtual method override */
camel_session_class->get_password = get_password;
}
camel_pgp_session_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (
camel_test_session_get_type (),
(CamelObjectInitFunc) init,
NULL);
}
-
+
return type;
}
camel_pgp_session_new (const char *path)
{
CamelSession *session;
-
+
session = CAMEL_SESSION (camel_object_new (CAMEL_PGP_SESSION_TYPE));
-
+
camel_session_construct (session, path);
-
+
return session;
}
int ret;
camel_test_init (argc, argv);
-
+
/* clear out any camel-test data */
system ("/bin/rm -rf /tmp/camel-test");
system ("/bin/mkdir /tmp/camel-test");
setenv ("GNUPGHOME", "/tmp/camel-test/.gnupg", 1);
-
+
/* import the gpg keys */
if ((ret = system ("gpg < /dev/null > /dev/null 2>&1")) == -1)
return 77;
else if (WEXITSTATUS (ret) == 127)
return 77;
-
+
system ("gpg --import ../data/camel-test.gpg.pub > /dev/null 2>&1");
system ("gpg --import ../data/camel-test.gpg.sec > /dev/null 2>&1");
-
+
session = camel_pgp_session_new ("/tmp/camel-test");
-
+
ex = camel_exception_new ();
-
+
ctx = camel_gpg_context_new (session);
camel_gpg_context_set_always_trust (CAMEL_GPG_CONTEXT (ctx), TRUE);
-
+
camel_test_start ("Test of PGP/MIME functions");
-
+
mime_part = camel_mime_part_new ();
camel_mime_part_set_content (mime_part, test_msg, strlen (test_msg), "text/plain");
camel_mime_part_set_description (mime_part, "Test of PGP/MIME multipart/signed stuff");
-
+
camel_test_push ("PGP/MIME signing");
mps = camel_multipart_signed_new ();
camel_multipart_signed_sign (mps, ctx, mime_part, "no.user@no.domain", CAMEL_CIPHER_HASH_SHA1, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
camel_test_pull ();
-
+
camel_object_unref (mime_part);
camel_exception_clear (ex);
-
+
camel_test_push ("PGP/MIME verify");
valid = camel_multipart_signed_verify (mps, ctx, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid));
camel_cipher_validity_free (valid);
camel_test_pull ();
-
+
camel_object_unref (mps);
camel_exception_clear (ex);
-
+
mime_part = camel_mime_part_new ();
camel_mime_part_set_content (mime_part, test_msg, strlen (test_msg), "text/plain");
camel_mime_part_set_description (mime_part, "Test of PGP/MIME multipart/encrypted stuff");
-
+
camel_test_push ("PGP/MIME encrypt");
recipients = g_ptr_array_new ();
g_ptr_array_add (recipients, "no.user@no.domain");
-
+
mpe = camel_multipart_encrypted_new ();
camel_multipart_encrypted_encrypt (mpe, mime_part, ctx, "no.user@no.domain", recipients, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
g_ptr_array_free (recipients, TRUE);
camel_test_pull ();
-
+
camel_exception_clear (ex);
camel_object_unref (mime_part);
-
+
camel_test_push ("PGP/MIME decrypt");
mime_part = camel_multipart_encrypted_decrypt (mpe, ctx, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
camel_object_unref (mime_part);
camel_object_unref (mpe);
camel_test_pull ();
-
+
camel_object_unref (CAMEL_OBJECT (ctx));
camel_object_unref (CAMEL_OBJECT (session));
-
+
camel_test_end ();
-
+
return 0;
}
typedef struct _CamelPgpSession {
CamelSession parent_object;
-
+
} CamelPgpSession;
typedef struct _CamelPgpSessionClass {
CamelSessionClass parent_class;
-
+
} CamelPgpSessionClass;
{
CamelSessionClass *camel_session_class =
CAMEL_SESSION_CLASS (camel_pgp_session_class);
-
+
/* virtual method override */
camel_session_class->get_password = get_password;
}
camel_pgp_session_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (
camel_test_session_get_type (),
(CamelObjectInitFunc) init,
NULL);
}
-
+
return type;
}
camel_pgp_session_new (const char *path)
{
CamelSession *session;
-
+
session = CAMEL_SESSION (camel_object_new (CAMEL_PGP_SESSION_TYPE));
-
+
camel_session_construct (session, path);
-
+
return session;
}
if (getenv("CAMEL_TEST_GPG") == NULL)
return 77;
-
+
camel_test_init (argc, argv);
-
+
/* clear out any camel-test data */
system ("/bin/rm -rf /tmp/camel-test");
system ("/bin/mkdir /tmp/camel-test");
setenv ("GNUPGHOME", "/tmp/camel-test/.gnupg", 1);
-
+
/* import the gpg keys */
if ((ret = system ("gpg < /dev/null > /dev/null 2>&1")) == -1)
return 77;
system ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.sec > /dev/null 2>&1");
session = camel_pgp_session_new ("/tmp/camel-test");
-
+
ex = camel_exception_new ();
-
+
ctx = camel_gpg_context_new (session);
camel_gpg_context_set_always_trust (CAMEL_GPG_CONTEXT (ctx), TRUE);
-
+
camel_test_start ("Test of PGP functions");
stream1 = camel_stream_mem_new ();
return 77;
}
camel_test_pull ();
-
+
camel_exception_clear (ex);
-
+
camel_test_push ("PGP verify");
valid = camel_cipher_verify (ctx, sigpart, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid));
camel_cipher_validity_free (valid);
camel_test_pull ();
-
+
camel_object_unref(conpart);
camel_object_unref(sigpart);
-
+
stream1 = camel_stream_mem_new ();
camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44);
camel_stream_reset (stream1);
camel_object_unref(dw);
encpart = camel_mime_part_new();
-
+
camel_exception_clear (ex);
-
+
camel_test_push ("PGP encrypt");
recipients = g_ptr_array_new ();
g_ptr_array_add (recipients, "no.user@no.domain");
camel_test_pull ();
camel_exception_clear (ex);
-
+
camel_test_push ("PGP decrypt");
outpart = camel_mime_part_new();
valid = camel_cipher_decrypt (ctx, encpart, outpart, ex);
camel_object_unref(outpart);
camel_test_pull ();
-
+
camel_object_unref (CAMEL_OBJECT (ctx));
camel_object_unref (CAMEL_OBJECT (session));
-
+
camel_test_end ();
-
+
return 0;
}
typedef struct _CamelTestSession {
CamelSession parent_object;
-
+
} CamelTestSession;
typedef struct _CamelTestSessionClass {
CamelSessionClass parent_class;
-
+
} CamelTestSessionClass;
{
CamelSessionClass *camel_session_class =
CAMEL_SESSION_CLASS (camel_test_session_class);
-
+
/* virtual method override */
camel_session_class->get_password = get_password;
}
camel_test_session_get_type (void)
{
static CamelType type = CAMEL_INVALID_TYPE;
-
+
if (type == CAMEL_INVALID_TYPE) {
type = camel_type_register (
camel_test_session_get_type (),
(CamelObjectInitFunc) init,
NULL);
}
-
+
return type;
}
camel_test_session_new (const char *path)
{
CamelSession *session;
-
+
session = CAMEL_SESSION (camel_object_new (CAMEL_TEST_SESSION_TYPE));
-
+
camel_session_construct (session, path);
-
+
return session;
}
GPtrArray *recipients;
GByteArray *buf;
char *before, *after;
-
+
camel_test_init (argc, argv);
-
+
ex = camel_exception_new ();
-
+
/* clear out any camel-test data */
system ("/bin/rm -rf /tmp/camel-test");
-
+
session = camel_test_session_new ("/tmp/camel-test");
-
+
ctx = camel_smime_context_new (session);
-
+
camel_test_start ("Test of S/MIME PKCS7 functions");
-
+
stream1 = camel_stream_mem_new ();
camel_stream_write (stream1, "Hello, I am a test stream.", 25);
camel_stream_reset (stream1);
-
+
stream2 = camel_stream_mem_new ();
-
+
camel_test_push ("PKCS7 signing");
camel_smime_sign (ctx, "smime@xtorshun.org", CAMEL_CIPHER_HASH_SHA1,
stream1, stream2, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
camel_test_pull ();
-
+
camel_exception_clear (ex);
-
+
camel_test_push ("PKCS7 verify");
camel_stream_reset (stream1);
camel_stream_reset (stream2);
check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid));
camel_cipher_validity_free (valid);
camel_test_pull ();
-
+
camel_object_unref (CAMEL_OBJECT (stream1));
camel_object_unref (CAMEL_OBJECT (stream2));
-
+
stream1 = camel_stream_mem_new ();
stream2 = camel_stream_mem_new ();
stream3 = camel_stream_mem_new ();
-
+
camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44);
camel_stream_reset (stream1);
-
+
camel_exception_clear (ex);
-
+
camel_test_push ("PKCS7 encrypt");
recipients = g_ptr_array_new ();
g_ptr_array_add (recipients, "smime@xtorshun.org");
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
g_ptr_array_free (recipients, TRUE);
camel_test_pull ();
-
+
camel_stream_reset (stream2);
camel_exception_clear (ex);
-
+
camel_test_push ("PKCS7 decrypt");
camel_smime_decrypt (ctx, stream2, stream3, ex);
check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex));
g_free (before);
g_free (after);
camel_test_pull ();
-
+
camel_object_unref (CAMEL_OBJECT (ctx));
camel_object_unref (CAMEL_OBJECT (session));
-
+
camel_test_end ();
-
+
return 0;
}
check_unref(ss, 1);
check(close(fd) == -1);
pull();
-
+
(void)unlink("stream.txt");
}
push("stream subrange %d-%d", ranges[i].lower, ranges[i].upper);
sus = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus != NULL);
-
+
test_seekable_substream_writepart((CamelStream *)sus, j);
test_seekable_substream_readpart((CamelStream *)sus);
-
+
sus2 = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus2 != NULL);
test_seekable_substream_readpart((CamelStream *)sus2);
-
+
check_unref(sus, 1);
check_unref(sus2, 1);
pull();
sus2 = (CamelSeekableSubstream *)camel_seekable_substream_new(ss, ranges[i].lower, ranges[i].upper);
check(sus2 != NULL);
test_seekable_substream_readpart((CamelStream *)sus2);
-
+
check_unref(sus, 1);
check_unref(sus2, 1);
pull();