#include <string.h>
#include <ctype.h>
#include <errno.h>
-#include <netdb.h>
#if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
# include <wchar.h>
#include "intl.h"
#include "utils.h"
+#include "socket.h"
#include "statusbar.h"
#include "logwindow.h"
} \
}
+gint scan_mailto_url(const gchar *mailto, gchar **to, gchar **cc, gchar **bcc,
+ gchar **subject, gchar **body)
+{
+ gchar *tmp_mailto;
+ gchar *p;
+
+ Xstrdup_a(tmp_mailto, mailto, return -1);
+
+ if (!strncmp(tmp_mailto, "mailto:", 7))
+ tmp_mailto += 7;
+
+ p = strchr(tmp_mailto, '?');
+ if (p) {
+ *p = '\0';
+ p++;
+ }
+
+ if (to && !*to)
+ *to = g_strdup(tmp_mailto);
+
+ while (p) {
+ gchar *field, *value;
+
+ field = p;
+
+ p = strchr(p, '=');
+ if (!p) break;
+ *p = '\0';
+ p++;
+
+ value = p;
+
+ p = strchr(p, '&');
+ if (p) {
+ *p = '\0';
+ p++;
+ }
+
+ if (*value == '\0') continue;
+
+ if (cc && !*cc && !g_strcasecmp(field, "cc")) {
+ *cc = g_strdup(value);
+ } else if (bcc && !*bcc && !g_strcasecmp(field, "bcc")) {
+ *bcc = g_strdup(value);
+ } else if (subject && !*subject &&
+ !g_strcasecmp(field, "subject")) {
+ *subject = g_malloc(strlen(value) + 1);
+ decode_uri(*subject, value);
+ } else if (body && !*body && !g_strcasecmp(field, "body")) {
+ *body = g_malloc(strlen(value) + 1);
+ decode_uri(*body, value);
+ }
+ }
+
+ return 0;
+}
+
/*
* We need this wrapper around g_get_home_dir(), so that
* we can fix some Windoze things here. Should be done in glibc of course
return header_dir;
}
+gchar *get_tmp_dir(void)
+{
+ static gchar *tmp_dir = NULL;
+
+ if (!tmp_dir)
+ tmp_dir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ TMP_DIR, NULL);
+
+ return tmp_dir;
+}
+
gchar *get_tmp_file(void)
{
- static gchar *tmp_file = NULL;
+ gchar *tmp_file;
+ static guint32 id = 0;
- if (!tmp_file)
- tmp_file = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
- "tmpfile", NULL);
+ tmp_file = g_strdup_printf("%s%ctmpfile.%08x",
+ get_tmp_dir(), G_DIR_SEPARATOR, id++);
return tmp_file;
}
gchar *get_domain_name(void)
{
static gchar *domain_name = NULL;
- struct hostent *myfqdn = NULL;
if (!domain_name) {
- gchar buf[BUFFSIZE] = "";
+ gchar buf[128] = "";
+ struct hostent *hp;
if (gethostname(buf, sizeof(buf)) < 0) {
perror("gethostname");
- strcpy(buf, "unknown");
- } else {
- myfqdn = gethostbyname(buf);
- if (myfqdn != NULL) {
- memset(buf, '\0', strlen(buf));
- strcpy(buf, myfqdn->h_name);
- } else {
- perror("gethostbyname");
- strcpy(buf, "unknown");
- }
- }
+ domain_name = "unknown";
+ } else {
+ buf[sizeof(buf) - 1] = '\0';
+ if ((hp = my_gethostbyname(buf)) == NULL) {
+ perror("gethostbyname");
+ domain_name = g_strdup(buf);
+ } else {
+ domain_name = g_strdup(hp->h_name);
+ }
+ }
- domain_name = g_strdup(buf);
+ debug_print("domain name = %s\n", domain_name);
}
return domain_name;
{
struct stat s;
+ if (file == NULL)
+ return FALSE;
+
if (stat(file, &s) < 0) {
if (ENOENT != errno) FILE_OP_ERROR(file, "stat");
return FALSE;
{
struct stat s;
+ if (dir == NULL)
+ return FALSE;
+
if (stat(dir, &s) < 0) {
if (ENOENT != errno) FILE_OP_ERROR(dir, "stat");
return FALSE;
{
struct stat s;
+ if (file == NULL)
+ return FALSE;
+
if (stat(file, &s) < 0) {
if (ENOENT != errno) FILE_OP_ERROR(file, "stat");
return FALSE;
if (chdir(dir) < 0) {
FILE_OP_ERROR(dir, "chdir");
+ g_free(prev_dir);
return -1;
}
if ((dp = opendir(".")) == NULL) {
FILE_OP_ERROR(dir, "opendir");
+ g_free(prev_dir);
return -1;
}
if (chdir(dir) < 0) {
FILE_OP_ERROR(dir, "chdir");
+ g_free(prev_dir);
return -1;
}
if ((dp = opendir(".")) == NULL) {
FILE_OP_ERROR(dir, "opendir");
+ g_free(prev_dir);
return -1;
}
return 0;
}
+gint remove_numbered_files_not_in_list(const gchar *dir, GSList *numberlist)
+{
+ DIR *dp;
+ struct dirent *d;
+ gchar *prev_dir;
+ gint fileno;
+
+ prev_dir = g_get_current_dir();
+
+ if (chdir(dir) < 0) {
+ FILE_OP_ERROR(dir, "chdir");
+ g_free(prev_dir);
+ return -1;
+ }
+
+ if ((dp = opendir(".")) == NULL) {
+ FILE_OP_ERROR(dir, "opendir");
+ g_free(prev_dir);
+ return -1;
+ }
+
+ while ((d = readdir(dp)) != NULL) {
+ fileno = to_number(d->d_name);
+ if (fileno >= 0 && (g_slist_find(numberlist, GINT_TO_POINTER(fileno)) == NULL)) {
+ debug_print("removing unwanted file %d from %s\n", fileno, dir);
+ if (is_dir_exist(d->d_name))
+ continue;
+ if (unlink(d->d_name) < 0)
+ FILE_OP_ERROR(d->d_name, "unlink");
+ }
+ }
+
+ closedir(dp);
+
+ if (chdir(prev_dir) < 0) {
+ FILE_OP_ERROR(prev_dir, "chdir");
+ g_free(prev_dir);
+ return -1;
+ }
+
+ g_free(prev_dir);
+
+ return 0;
+}
+
gint remove_all_numbered_files(const gchar *dir)
{
return remove_numbered_files(dir, 0, UINT_MAX);
if (chdir(dir) < 0) {
FILE_OP_ERROR(dir, "chdir");
+ g_free(prev_dir);
return -1;
}
if ((dp = opendir(".")) == NULL) {
FILE_OP_ERROR(dir, "opendir");
+ g_free(prev_dir);
return -1;
}
}
#endif
-gint copy_file(const gchar *src, const gchar *dest)
+
+/*
+ * Append src file body to the tail of dest file.
+ * Now keep_backup has no effects.
+ */
+gint append_file(const gchar *src, const gchar *dest, gboolean keep_backup)
+{
+ FILE *src_fp, *dest_fp;
+ gint n_read;
+ gchar buf[BUFSIZ];
+
+ gboolean err = FALSE;
+
+ if ((src_fp = fopen(src, "rb")) == NULL) {
+ FILE_OP_ERROR(src, "fopen");
+ return -1;
+ }
+
+ if ((dest_fp = fopen(dest, "ab")) == NULL) {
+ FILE_OP_ERROR(dest, "fopen");
+ fclose(src_fp);
+ return -1;
+ }
+
+ if (change_file_mode_rw(dest_fp, dest) < 0) {
+ FILE_OP_ERROR(dest, "chmod");
+ g_warning(_("can't change file mode\n"));
+ }
+
+ while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), src_fp)) > 0) {
+ if (n_read < sizeof(buf) && ferror(src_fp))
+ break;
+ if (fwrite(buf, n_read, 1, dest_fp) < 1) {
+ g_warning(_("writing to %s failed.\n"), dest);
+ fclose(dest_fp);
+ fclose(src_fp);
+ unlink(dest);
+ return -1;
+ }
+ }
+
+ if (ferror(src_fp)) {
+ FILE_OP_ERROR(src, "fread");
+ err = TRUE;
+ }
+ fclose(src_fp);
+ if (fclose(dest_fp) == EOF) {
+ FILE_OP_ERROR(dest, "fclose");
+ err = TRUE;
+ }
+
+ if (err) {
+ unlink(dest);
+ return -1;
+ }
+
+ return 0;
+}
+
+gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup)
{
FILE *src_fp, *dest_fp;
gint n_read;
return -1;
}
+ if (keep_backup == FALSE && dest_bak)
+ unlink(dest_bak);
+
g_free(dest_bak);
return 0;
}
-gint move_file(const gchar *src, const gchar *dest)
+gint move_file(const gchar *src, const gchar *dest, gboolean overwrite)
{
- if (is_file_exist(dest)) {
- g_warning(_("move_file(): file %s already exists."), dest);
+ if (overwrite == FALSE && is_file_exist(dest)) {
+ g_warning("move_file(): file %s already exists.", dest);
return -1;
}
return -1;
}
- if (copy_file(src, dest) < 0) return -1;
+ if (copy_file(src, dest, FALSE) < 0) return -1;
unlink(src);
return 0;
}
+gint copy_file_part(FILE *fp, off_t offset, size_t length, const gchar *dest)
+{
+ FILE *dest_fp;
+ gint n_read;
+ gint bytes_left, to_read;
+ gchar buf[BUFSIZ];
+ gboolean err = FALSE;
+
+ if (fseek(fp, offset, SEEK_SET) < 0) {
+ perror("fseek");
+ return -1;
+ }
+
+ if ((dest_fp = fopen(dest, "wb")) == NULL) {
+ FILE_OP_ERROR(dest, "fopen");
+ return -1;
+ }
+
+ if (change_file_mode_rw(dest_fp, dest) < 0) {
+ FILE_OP_ERROR(dest, "chmod");
+ g_warning("can't change file mode\n");
+ }
+
+ bytes_left = length;
+ to_read = MIN(bytes_left, sizeof(buf));
+
+ while ((n_read = fread(buf, sizeof(gchar), to_read, fp)) > 0) {
+ if (n_read < to_read && ferror(fp))
+ break;
+ if (fwrite(buf, n_read, 1, dest_fp) < 1) {
+ g_warning(_("writing to %s failed.\n"), dest);
+ fclose(dest_fp);
+ unlink(dest);
+ return -1;
+ }
+ bytes_left -= n_read;
+ if (bytes_left == 0)
+ break;
+ to_read = MIN(bytes_left, sizeof(buf));
+ }
+
+ if (ferror(fp)) {
+ perror("fread");
+ err = TRUE;
+ }
+ if (fclose(dest_fp) == EOF) {
+ FILE_OP_ERROR(dest, "fclose");
+ err = TRUE;
+ }
+
+ if (err) {
+ unlink(dest);
+ return -1;
+ }
+
+ return 0;
+}
+
/* convert line endings into CRLF. If the last line doesn't end with
* linebreak, add it.
*/
} else if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') {
r = fputs(buf, dest_fp);
} else {
- if (len > 1)
+ if (len > 1) {
r = fwrite(buf, len - 1, 1, dest_fp);
+ if (r != 1)
+ r = EOF;
+ }
if (r != EOF)
r = fputs("\r\n", dest_fp);
}
tmp_file = get_tmp_file();
- if (canonicalize_file(file, tmp_file) < 0)
+ if (canonicalize_file(file, tmp_file) < 0) {
+ g_free(tmp_file);
return -1;
+ }
- if (rename(tmp_file, file) < 0) {
- FILE_OP_ERROR(file, "rename");
+ if (move_file(tmp_file, file, TRUE) < 0) {
+ g_warning("can't replace %s .\n", file);
unlink(tmp_file);
+ g_free(tmp_file);
return -1;
}
+ g_free(tmp_file);
return 0;
}
gint fd;
FILE *fp;
- tmpdir = g_get_tmp_dir();
+ tmpdir = get_tmp_dir();
tmplen = strlen(tmpdir);
progname = g_get_prgname();
proglen = strlen(progname);
return fp;
}
+gint str_write_to_file(const gchar *str, const gchar *file)
+{
+ FILE *fp;
+ size_t len;
+
+ g_return_val_if_fail(str != NULL, -1);
+ g_return_val_if_fail(file != NULL, -1);
+
+ if ((fp = fopen(file, "wb")) == NULL) {
+ FILE_OP_ERROR(file, "fopen");
+ return -1;
+ }
+
+ len = strlen(str);
+ if (len == 0) {
+ fclose(fp);
+ return 0;
+ }
+
+ if (fwrite(str, len, 1, fp) != 1) {
+ FILE_OP_ERROR(file, "fwrite");
+ fclose(fp);
+ unlink(file);
+ return -1;
+ }
+
+ if (fclose(fp) == EOF) {
+ FILE_OP_ERROR(file, "fclose");
+ unlink(file);
+ return -1;
+ }
+
+ return 0;
+}
+
+gchar *file_read_to_str(const gchar *file)
+{
+ GByteArray *array;
+ FILE *fp;
+ gchar buf[BUFSIZ];
+ gint n_read;
+ gchar *str;
+
+ g_return_val_if_fail(file != NULL, NULL);
+
+ if ((fp = fopen(file, "rb")) == NULL) {
+ FILE_OP_ERROR(file, "fopen");
+ return NULL;
+ }
+
+ array = g_byte_array_new();
+
+ while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
+ if (n_read < sizeof(buf) && ferror(fp))
+ break;
+ g_byte_array_append(array, buf, n_read);
+ }
+
+ if (ferror(fp)) {
+ FILE_OP_ERROR(file, "fread");
+ fclose(fp);
+ g_byte_array_free(array, TRUE);
+ return NULL;
+ }
+
+ fclose(fp);
+
+ buf[0] = '\0';
+ g_byte_array_append(array, buf, 1);
+ str = (gchar *)array->data;
+ g_byte_array_free(array, FALSE);
+
+ return str;
+}
+
gint execute_async(gchar *const argv[])
{
pid_t pid;
if (subject == NULL) return FALSE;
else return 0 == g_strncasecmp(subject, "Re: ", 4);
}
+
+FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
+{
+ int fd;
+
+ *filename = g_strdup_printf("%s%csylpheed.XXXXXX", dir, G_DIR_SEPARATOR);
+ fd = mkstemp(*filename);
+
+ return fdopen(fd, "w+");
+}