Commit 2bda88f0 authored by Slava Monich's avatar Slava Monich

[mms-lib] Convert text parts to utf-8. JB#50506

Those operators who convert text attachments to utf-8, seem to
only understand utf-8 as a charset. If they see utf-8, they do
nothing; if they see anything else, they interpret that as us-ascii
and convert it to utf-8 (which typically messes things up).

Therefore, we need to convert text parts into utf-8 and specify
utf-8 charset in the attachment part header. That way it should
always work.

This automatic utf-8 conversion can be turned off with a command
line option, or via config file. By default, conversion is on.
parent 754e0edf
/*
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -403,18 +403,21 @@ mms_app_parse_options(
gboolean disable_dbus_log = FALSE;
gint size_limit_kb = -1;
gdouble megapixels = -1;
MMSConfig* config = &opt->global.config;
MMSSettingsSimDataCopy* settings = &opt->settings;
char* root_dir_help = g_strdup_printf(
"Root directory for MMS files [%s]",
opt->global.config.root_dir);
config->root_dir);
char* retry_secs_help = g_strdup_printf(
"Retry period in seconds [%d]",
opt->global.config.retry_secs);
config->retry_secs);
char* network_idle_secs_help = g_strdup_printf(
"Network inactivity timeout in seconds [%d]",
opt->global.config.network_idle_secs);
config->network_idle_secs);
char* idle_secs_help = g_strdup_printf(
"Service inactivity timeout in seconds [%d]",
opt->global.config.idle_secs);
config->idle_secs);
char* description = gutil_log_description(NULL, 0);
GOptionContext* options;
......@@ -428,12 +431,12 @@ mms_app_parse_options(
{ "root-dir", 'd', 0, G_OPTION_ARG_FILENAME,
&root_dir, root_dir_help, "DIR" },
{ "retry-secs", 'r', 0, G_OPTION_ARG_INT,
&opt->global.config.retry_secs, retry_secs_help, "SEC" },
&config->retry_secs, retry_secs_help, "SEC" },
{ "network-idle-secs", 'n', 0, G_OPTION_ARG_INT,
&opt->global.config.network_idle_secs,
&config->network_idle_secs,
network_idle_secs_help, "SEC" },
{ "idle-secs", 'i', 0, G_OPTION_ARG_INT,
&opt->global.config.idle_secs, idle_secs_help, "SEC" },
&config->idle_secs, idle_secs_help, "SEC" },
{ "size-limit", 's', 0, G_OPTION_ARG_INT,
&size_limit_kb, "Maximum size for outgoing messages", "KB" },
{ "pix-limit", 'p', 0, G_OPTION_ARG_DOUBLE,
......@@ -445,12 +448,15 @@ mms_app_parse_options(
{ "keep-running", 'k', 0, G_OPTION_ARG_NONE, &keep_running,
"Keep running after everything is done", NULL },
{ "keep-temp-files", 't', 0, G_OPTION_ARG_NONE,
&opt->global.config.keep_temp_files,
&config->keep_temp_files,
"Don't delete temporary files", NULL },
{ "preserve-encoding", 'e', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,
&config->convert_to_utf8,
"Don't convert text parts to UTF-8", NULL },
{ "attic", 'a', 0, G_OPTION_ARG_NONE,
&opt->global.config.attic_enabled,
&config->attic_enabled,
"Store unrecognized push messages in the attic", NULL },
#define OPT_VERBOSE_INDEX 13
#define OPT_VERBOSE_INDEX 14
{ "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
mms_app_option_verbose, "Be verbose (equivalent to -l=verbose)",
NULL },
......@@ -560,28 +566,28 @@ mms_app_parse_options(
GINFO("Starting");
#endif
if (size_limit_kb >= 0) {
opt->settings.data.size_limit = size_limit_kb * 1024;
settings->data.size_limit = size_limit_kb * 1024;
opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_SIZE_LIMIT;
}
if (megapixels >= 0) {
opt->settings.data.max_pixels = (int)(megapixels*1000)*1000;
settings->data.max_pixels = (int)(megapixels*1000)*1000;
opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_MAX_PIXELS;
}
if (ua) {
g_free(opt->settings.user_agent);
opt->settings.data.user_agent = opt->settings.user_agent = ua;
g_free(settings->user_agent);
settings->data.user_agent = settings->user_agent = ua;
opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_USER_AGENT;
ua = NULL;
}
if (uaprof) {
g_free(opt->settings.uaprof);
opt->settings.data.uaprof = opt->settings.uaprof = uaprof;
g_free(settings->uaprof);
settings->data.uaprof = settings->uaprof = uaprof;
opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_UAPROF;
uaprof = NULL;
}
if (root_dir) {
g_free(opt->global.root_dir);
opt->global.config.root_dir = opt->global.root_dir = root_dir;
config->root_dir = opt->global.root_dir = root_dir;
root_dir = NULL;
}
if (keep_running) opt->flags |= MMS_ENGINE_FLAG_KEEP_RUNNING;
......
......@@ -28,6 +28,7 @@ SRC = \
mms_attachment.c \
mms_attachment_image.c \
mms_attachment_jpeg.c \
mms_attachment_text.c \
mms_codec.c \
mms_connection.c \
mms_connman.c \
......
/*
* Copyright (C) 2014-2019 Jolla Ltd.
* Copyright (C) 2014-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2019 Open Mobile Platform LLC.
* Copyright (C) 2014-2020 Jolla Ltd.
* Copyright (C) 2014-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*/
#ifndef JOLLA_MMS_SETTINGS_H
#define JOLLA_MMS_SETTINGS_H
#ifndef SAILFISH_MMS_SETTINGS_H
#define SAILFISH_MMS_SETTINGS_H
#include "mms_lib_types.h"
......@@ -24,6 +24,7 @@ struct mms_config {
int retry_secs; /* Retry timeout in seconds */
int network_idle_secs; /* Network inactivity timeout */
int idle_secs; /* Service inactivity timeout */
gboolean convert_to_utf8; /* Convert text parts to UTF-8 */
gboolean keep_temp_files; /* Keep temporary files around */
gboolean attic_enabled; /* Keep unrecognized push message in attic */
};
......@@ -145,7 +146,7 @@ mms_settings_sim_data_copy(
#define mms_settings_sim_data_reset(data) \
mms_settings_sim_data_copy(data,NULL)
#endif /* JOLLA_MMS_SETTINGS_H */
#endif /* SAILFISH_MMS_SETTINGS_H */
/*
* Local Variables:
......
......@@ -28,6 +28,7 @@ SOURCES += \
src/mms_attachment.c \
src/mms_attachment_image.c \
src/mms_attachment_jpeg.c \
src/mms_attachment_text.c \
src/mms_attachment_qt.cpp \
src/mms_codec.c \
src/mms_connection.c \
......
/*
* Copyright (C) 2013-2016 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -17,6 +18,8 @@
#include "mms_settings.h"
#include "mms_codec.h"
#include "gutil_strv.h"
#ifdef HAVE_MAGIC
# include <magic.h>
#endif
......@@ -27,7 +30,6 @@
GLOG_MODULE_DEFINE("mms-attachment");
#define MMS_ATTACHMENT_DEFAULT_TYPE "application/octet-stream"
#define CONTENT_TYPE_PARAM_NAME "name"
G_DEFINE_TYPE(MMSAttachment, mms_attachment, G_TYPE_OBJECT)
......@@ -58,8 +60,7 @@ mms_attachment_finalize(
MMSAttachment* at = MMS_ATTACHMENT(object);
GVERBOSE_("%p", at);
if (at->map) g_mapped_file_unref(at->map);
if (!at->config->keep_temp_files &&
!(at->flags & MMS_ATTACHMENT_KEEP_FILES)) {
if (!at->config->keep_temp_files) {
char* dir = g_path_get_dirname(at->original_file);
remove(at->original_file);
rmdir(dir);
......@@ -201,6 +202,7 @@ mms_attachment_write_smil(
return FALSE;
}
static
char*
mms_attachment_guess_content_type(
const char* path)
......@@ -239,6 +241,38 @@ mms_attachment_guess_content_type(
return content_type;
}
static
char*
mms_attachment_guess_text_encoding(
const char* path)
{
char* encoding = NULL;
const char* detected = NULL;
#ifdef HAVE_MAGIC
/* Use magic to determine mime type */
magic_t magic = magic_open(MAGIC_MIME_ENCODING);
if (magic) {
if (magic_load(magic, NULL) == 0) {
detected = magic_file(magic, path);
}
}
#endif
if (detected) {
GDEBUG("%s: detected %s", path, detected);
encoding = g_strdup(detected);
} else {
encoding = g_strdup(MMS_DEFAULT_CHARSET);
}
#ifdef HAVE_MAGIC
if (magic) magic_close(magic);
#endif
return encoding;
}
MMSAttachment*
mms_attachment_new_smil(
const MMSConfig* config,
......@@ -259,7 +293,8 @@ mms_attachment_new_smil(
if (ok) {
MMSAttachmentInfo ai;
ai.file_name = path;
ai.content_type = SMIL_CONTENT_TYPE "; charset=utf-8";
ai.content_type = SMIL_CONTENT_TYPE "; "
CONTENT_TYPE_PARAM_CHARSET "=" MMS_DEFAULT_CHARSET;
ai.content_id = NULL;
smil = mms_attachment_new(config, &ai, error);
GASSERT(smil && (smil->flags & MMS_ATTACHMENT_SMIL));
......@@ -290,30 +325,51 @@ mms_attachment_new(
char* media_type = NULL;
char* name = g_path_get_basename(path);
char* content_type = NULL;
GType type;
GType type = MMS_TYPE_ATTACHMENT;
MMSAttachment* at;
MMSAttachmentClass* klass;
/*
* We always need to provide charset for text attachments because
* operators may (and often do) want to convert those to their
* favorite charset, in which case they need to know the original
* one (some just blindly assume us-ascii and mess things up).
*/
if (info->content_type && info->content_type[0]) {
char** ct = mms_parse_http_content_type(info->content_type);
if (ct) {
char** ptr;
gboolean append_name = TRUE;
if (!strcmp(ct[0], SMIL_CONTENT_TYPE)) {
flags |= MMS_ATTACHMENT_SMIL;
}
gboolean append_charset = g_str_has_prefix(ct[0],
MEDIA_TYPE_TEXT_PREFIX);
for (ptr = ct+1; *ptr; ptr+=2) {
if (!g_ascii_strcasecmp(ptr[0], CONTENT_TYPE_PARAM_NAME)) {
const char* p = ptr[0];
if (!g_ascii_strcasecmp(p, CONTENT_TYPE_PARAM_NAME)) {
g_free(ptr[1]);
ptr[1] = g_strdup(name);
append_name = FALSE;
} else if (append_charset && !g_ascii_strcasecmp(p,
CONTENT_TYPE_PARAM_CHARSET)) {
/* Charset is provided by the caller */
append_charset = FALSE;
}
}
if (append_name) {
const guint len = g_strv_length(ct);
ct = g_renew(gchar*, ct, len+3);
ct[len] = g_strdup(CONTENT_TYPE_PARAM_NAME);
ct[len+1] = g_strdup(name);
ct[len+2] = NULL;
ct = gutil_strv_addv(ct,
CONTENT_TYPE_PARAM_NAME, name,
NULL);
}
if (append_charset) {
char* enc = mms_attachment_guess_text_encoding(path);
if (enc) {
ct = gutil_strv_addv(ct,
CONTENT_TYPE_PARAM_CHARSET, enc,
NULL);
g_free(enc);
}
}
content_type = mms_unparse_http_content_type(ct);
media_type = g_strdup(ct[0]);
......@@ -322,40 +378,37 @@ mms_attachment_new(
}
if (!content_type) {
const char* default_charset = "utf-8";
char* detected = NULL;
const char* charset = NULL;
const char* ct[6];
int n = 0;
media_type = mms_attachment_guess_content_type(path);
if (!strcmp(media_type, SMIL_CONTENT_TYPE)) {
flags |= MMS_ATTACHMENT_SMIL;
charset = default_charset;
} else {
if (g_str_has_prefix(media_type, MEDIA_TYPE_TEXT_PREFIX)) {
charset = default_charset;
}
if (g_str_has_prefix(media_type, MEDIA_TYPE_TEXT_PREFIX)) {
detected = mms_attachment_guess_text_encoding(path);
charset = detected;
}
ct[n++] = media_type;
if (charset) {
ct[n++] = "charset";
ct[n++] = CONTENT_TYPE_PARAM_CHARSET;
ct[n++] = charset;
}
ct[n++] = CONTENT_TYPE_PARAM_NAME;
ct[n++] = name;
ct[n++] = NULL;
content_type = mms_unparse_http_content_type((char**)ct);
g_free(detected);
}
GDEBUG("%s: %s", path, content_type);
if (!strcmp(media_type, "image/jpeg")) {
if (!strcmp(media_type, SMIL_CONTENT_TYPE)) {
flags |= MMS_ATTACHMENT_SMIL;
} else if (!strcmp(media_type, "image/jpeg")) {
type = MMS_TYPE_ATTACHMENT_JPEG;
} else if (g_str_has_prefix(media_type, MEDIA_TYPE_IMAGE_PREFIX)) {
type = MMS_TYPE_ATTACHMENT_IMAGE;
} else {
type = MMS_TYPE_ATTACHMENT;
} else if (g_str_has_prefix(media_type, MEDIA_TYPE_TEXT_PREFIX)) {
type = MMS_TYPE_ATTACHMENT_TEXT;
}
at = g_object_new(type, NULL);
......@@ -369,8 +422,16 @@ mms_attachment_new(
g_strdup(info->content_id) :
g_strdup(at->content_location);
path = NULL;
g_free(media_type);
return at;
klass = MMS_ATTACHMENT_GET_CLASS(at);
if (!klass->fn_init || klass->fn_init(at)) {
GDEBUG("%s: %s", at->file_name, at->content_type);
return at;
}
/* Init failed */
mms_attachment_unref(at);
}
g_free(path);
}
......
/*
* Copyright (C) 2013-2014 Jolla Ltd.
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -12,8 +14,8 @@
*
*/
#ifndef JOLLA_MMS_ATTACHMENT_H
#define JOLLA_MMS_ATTACHMENT_H
#ifndef SAILFISH_MMS_ATTACHMENT_H
#define SAILFISH_MMS_ATTACHMENT_H
#include "mms_lib_types.h"
......@@ -30,13 +32,17 @@ struct _mms_attachment {
unsigned int flags; /* Flags: */
#define MMS_ATTACHMENT_SMIL (0x01)
#define MMS_ATTACHMENT_KEEP_FILES (0x02)
#define MMS_ATTACHMENT_RESIZABLE (0x04)
#define MMS_ATTACHMENT_RESIZABLE (0x02)
};
#define CONTENT_TYPE_PARAM_NAME "name"
#define CONTENT_TYPE_PARAM_CHARSET "charset"
#define MMS_DEFAULT_CHARSET "utf-8"
typedef struct mms_attachment_class {
GObjectClass parent;
gboolean (*fn_init)(
MMSAttachment* attachment);
void (*fn_reset)(
MMSAttachment* attachment);
gboolean (*fn_resize)(
......@@ -45,9 +51,11 @@ typedef struct mms_attachment_class {
} MMSAttachmentClass;
GType mms_attachment_get_type(void);
GType mms_attachment_text_get_type(void);
GType mms_attachment_image_get_type(void);
GType mms_attachment_jpeg_get_type(void);
#define MMS_TYPE_ATTACHMENT (mms_attachment_get_type())
#define MMS_TYPE_ATTACHMENT_TEXT (mms_attachment_text_get_type())
#define MMS_TYPE_ATTACHMENT_IMAGE (mms_attachment_image_get_type())
#define MMS_TYPE_ATTACHMENT_JPEG (mms_attachment_jpeg_get_type())
......@@ -77,16 +85,12 @@ void
mms_attachment_reset(
MMSAttachment* attachment);
char*
mms_attachment_guess_content_type(
const char* path);
gboolean
mms_attachment_resize(
MMSAttachment* attachment,
const MMSSettingsSimData* settings);
#endif /* JOLLA_MMS_ATTACHMENT_H */
#endif /* SAILFISH_MMS_ATTACHMENT_H */
/*
* Local Variables:
......
/*
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -54,18 +55,12 @@ const char*
mms_attachment_image_prepare_filename(
MMSAttachmentImage* image)
{
char* original = image->attachment.original_file;
if (image->resized) {
remove(image->resized);
image->attachment.file_name = image->attachment.original_file;
image->attachment.file_name = original;
} else {
char* dir = g_path_get_dirname(image->attachment.original_file);
char* fname = g_path_get_basename(image->attachment.original_file);
char* subdir = g_build_filename(dir, MMS_RESIZE_DIR, NULL);
g_mkdir_with_parents(subdir, MMS_DIR_PERM);
image->resized = g_build_filename(subdir, fname, NULL);
g_free(dir);
g_free(fname);
g_free(subdir);
image->resized = mms_prepare_filename(original, MMS_CONVERT_DIR);
}
return image->resized;
}
......@@ -300,8 +295,7 @@ mms_attachment_image_finalize(
GObject* object)
{
MMSAttachmentImage* image = MMS_ATTACHMENT_IMAGE(object);
if (!image->attachment.config->keep_temp_files &&
!(image->attachment.flags & MMS_ATTACHMENT_KEEP_FILES)) {
if (!image->attachment.config->keep_temp_files) {
mms_remove_file_and_dir(image->resized);
}
g_free(image->resized);
......
/*
* Copyright (C) 2020 Jolla Ltd.
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "mms_attachment.h"
#include "mms_settings.h"
#include "mms_codec.h"
#include "mms_file_util.h"
#include <gutil_strv.h>
/* Logging */
#define GLOG_MODULE_NAME mms_attachment_log
#include <gutil_log.h>
typedef struct mms_attachment_text {
MMSAttachment attachment;
char* utf8file;
} MMSAttachmentText;
typedef MMSAttachmentClass MMSAttachmentTextClass;
G_DEFINE_TYPE(MMSAttachmentText, mms_attachment_text, MMS_TYPE_ATTACHMENT)
#define MMS_ATTACHMENT_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
MMS_TYPE_ATTACHMENT_TEXT, MMSAttachmentText))
static
void
mms_attachment_text_convert_to_utf8(
MMSAttachment* at)
{
MMSAttachmentText* self = MMS_ATTACHMENT_TEXT(at);
char** ct = mms_parse_http_content_type(at->content_type);
const int n = gutil_strv_length(ct);
int i, cs_pos = 0;
/* Find current charset */
for (i = 1; i < n; i += 2) {
if (!g_ascii_strcasecmp(ct[i], CONTENT_TYPE_PARAM_CHARSET)) {
cs_pos = i;
break;
}
}
if (cs_pos > 0) {
/* Check if it's already UTF-8 or US-ASCII */
const char* charset = ct[cs_pos + 1];
if (g_ascii_strcasecmp(charset, MMS_DEFAULT_CHARSET) &&
g_ascii_strcasecmp(charset, "US=ASCII")) {
/* Conversion is needed */
GError* err = NULL;
gsize utf8size;
const char* in = at->original_file;
const gchar* indata = g_mapped_file_get_contents(at->map);
const gsize insize = g_mapped_file_get_length(at->map);
gchar* utf8 = g_convert(indata, insize, MMS_DEFAULT_CHARSET,
charset, NULL, &utf8size, &err);
if (utf8) {
char* out = mms_prepare_filename(in, MMS_CONVERT_DIR);
if (g_file_set_contents(out, utf8, utf8size, &err)) {
GMappedFile* map = g_mapped_file_new(out, FALSE, &err);
if (map) {
GDEBUG("%s (%d bytes) -> %s (%d bytes)", in,
(int)insize, out, (int)utf8size);
/* Substitute file mapping */
g_mapped_file_unref(at->map);
at->file_name = self->utf8file = out;
at->map = map;
out = NULL;
/* Update content type header */
g_free(at->content_type);
g_free(ct[cs_pos + 1]);
ct[cs_pos + 1] = g_strdup(MMS_DEFAULT_CHARSET);
at->content_type = mms_unparse_http_content_type(ct);
} else {
GERR("Failed to map %s: %s", out, GERRMSG(err));
g_error_free(err);
}
} else {
GERR("Failed to write %s: %s", out, GERRMSG(err));
g_error_free(err);
}
g_free(out);
g_free(utf8);
} else {
GERR("Failed to convert %s: %s", in, GERRMSG(err));
g_error_free(err);
}
} else {
GDEBUG("%s: no conversion required", at->file_name);
}
}
g_strfreev(ct);
}
static
gboolean
mms_attachment_text_init_attachment(
MMSAttachment* at)
{
if (at->config->convert_to_utf8) {
mms_attachment_text_convert_to_utf8(at);
} else {
GDEBUG("%s: preserving charset", at->file_name);
}
return TRUE;
}
static
void
mms_attachment_text_finalize(
GObject* object)
{
MMSAttachmentText* self = MMS_ATTACHMENT_TEXT(object);
if (!self->attachment.config->keep_temp_files) {
mms_remove_file_and_dir(self->utf8file);
}
g_free(self->utf8file);
G_OBJECT_CLASS(mms_attachment_text_parent_class)->finalize(object);
}
static
void
mms_attachment_text_class_init(
MMSAttachmentTextClass* klass)
{
klass->fn_init = mms_attachment_text_init_attachment;
G_OBJECT_CLASS(klass)->finalize = mms_attachment_text_finalize;
}
static
void
mms_attachment_text_init(
MMSAttachmentText* self)
{
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/
/*
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -92,6 +93,28 @@ mms_remove_file_and_dir(
}
}
/**
* Builds a file name with the same basename but in the subdirectory
* relative to the original file. Creates the subdirectory.
*/
char*
mms_prepare_filename(
const char* file,
const char* subdir)
{
char* dir = g_path_get_dirname(file);
char* fname = g_path_get_basename(file);
char* newdir = g_build_filename(dir, subdir, NULL);
char* out;
g_mkdir_with_parents(newdir, MMS_DIR_PERM);
out = g_build_filename(newdir, fname, NULL);
g_free(dir);
g_free(fname);
g_free(newdir);
return out;
}
/**
* Creates a file in the specified directory. Creates the directory if
* it doesn't exist. If file already exists, truncates it. Returns file
......
/*
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -29,7 +30,7 @@
#define MMS_MESSAGE_DIR "msg"
#define MMS_PARTS_DIR "parts"
#define MMS_ENCODE_DIR "encode"
#define MMS_RESIZE_DIR "resize"
#define MMS_CONVERT_DIR "convert"
#define MMS_NOTIFICATION_IND_FILE "m-notification.ind"
#define MMS_NOTIFYRESP_IND_FILE "m-notifyresp.ind"
......@@ -50,12 +51,19 @@ void
mms_remove_file_and_dir(
const char* file);
char*
mms_prepare_filename(
const char* file,
const char* subdir)
G_GNUC_WARN_UNUSED_RESULT;
int
mms_create_file(
const char* dir,
const char* fname,
char** path,
GError** error);
GError** error)
G_GNUC_WARN_UNUSED_RESULT;
gboolean
mms_write_file(
......
/*
* Copyright (C) 2013-2018 Jolla Ltd.
* Copyright (C) 2013-2018 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2013-2020 Jolla Ltd.
* Copyright (C) 2013-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -70,6 +71,7 @@ mms_lib_default_config(
config->idle_secs = MMS_CONFIG_DEFAULT_IDLE_SECS;
config->keep_temp_files = FALSE;
config->attic_enabled = FALSE;
config->convert_to_utf8 = TRUE;
}
/*
......