summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2012-11-26 16:36:18 +0000
committerPaul Gardiner <paulg.artifex@glidos.net>2012-11-27 10:40:23 +0000
commit4c2e89d670317b898ece971c7b4d111e473c9575 (patch)
tree64be7ca7253eab543e910d61c433282e5399de7d
parenteaaf501fa47616691ab10b151022b4c91cc210b4 (diff)
downloadmupdf-4c2e89d670317b898ece971c7b4d111e473c9575.tar.xz
Forms: avoid directly saving to the original file
MuPDF needs access to the original file when saving, and in any case directly overwritting the original file has much more potential for data loss than use of a temporary file.
-rw-r--r--apps/jstest_main.c4
-rw-r--r--apps/pdfapp.c70
-rw-r--r--apps/pdfapp.h2
-rw-r--r--apps/win_main.c63
-rw-r--r--apps/x11_main.c5
5 files changed, 130 insertions, 14 deletions
diff --git a/apps/jstest_main.c b/apps/jstest_main.c
index ff7f9497..b5d90144 100644
--- a/apps/jstest_main.c
+++ b/apps/jstest_main.c
@@ -107,6 +107,10 @@ int wingetsavepath(pdfapp_t *app, char *buf, int len)
return 0;
}
+void winreplacefile(char *source, char *target)
+{
+}
+
void wincursor(pdfapp_t *app, int curs)
{
}
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index 598b40b5..9760385b 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -187,6 +187,7 @@ void pdfapp_open(pdfapp_t *app, char *filename, int reload)
}
}
+ app->docpath = fz_strdup(ctx, filename);
app->doctitle = filename;
if (strrchr(app->doctitle, '\\'))
app->doctitle = strrchr(app->doctitle, '\\') + 1;
@@ -248,6 +249,10 @@ void pdfapp_close(pdfapp_t *app)
fz_free(app->ctx, app->doctitle);
app->doctitle = NULL;
+ if (app->docpath)
+ fz_free(app->ctx, app->docpath);
+ app->docpath = NULL;
+
if (app->image)
fz_drop_pixmap(app->ctx, app->image);
app->image = NULL;
@@ -277,6 +282,32 @@ void pdfapp_close(pdfapp_t *app)
fz_flush_warnings(app->ctx);
}
+static int gen_tmp_file(char *buf, int len)
+{
+ int i;
+ char *name = strrchr(buf, '/');
+
+ if (name == NULL)
+ name = strrchr(buf, '\\');
+
+ if (name != NULL)
+ name++;
+ else
+ name = buf;
+
+ for (i = 0; i < 10000; i++)
+ {
+ FILE *f;
+ snprintf(name, buf+len-name, "tmp%04d", i);
+ f = fopen(buf, "r");
+ if (f == NULL)
+ return 1;
+ fclose(f);
+ }
+
+ return 0;
+}
+
static int pdfapp_save(pdfapp_t *app)
{
char buf[PATH_MAX];
@@ -290,7 +321,44 @@ static int pdfapp_save(pdfapp_t *app)
opts.do_garbage = 1;
opts.do_linear = 0;
- fz_write_document(app->doc, buf, &opts);
+ if (strcmp(buf, app->docpath) == 0)
+ {
+ if (gen_tmp_file(buf, PATH_MAX))
+ {
+ int written;
+
+ fz_var(written);
+ fz_try(app->ctx)
+ {
+ fz_write_document(app->doc, buf, &opts);
+ written = 1;
+ }
+ fz_catch(app->ctx)
+ {
+ written = 0;
+ }
+
+ if (written)
+ {
+ char buf2[PATH_MAX];
+ strncpy(buf2, app->docpath, PATH_MAX);
+ pdfapp_close(app);
+ winreplacefile(buf, buf2);
+ pdfapp_open(app, buf2, 1);
+ }
+
+ return written;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ fz_write_document(app->doc, buf, &opts);
+ return 1;
+ }
return 1;
}
diff --git a/apps/pdfapp.h b/apps/pdfapp.h
index 2cdceb39..22e4ba67 100644
--- a/apps/pdfapp.h
+++ b/apps/pdfapp.h
@@ -40,11 +40,13 @@ extern int wingetsavepath(pdfapp_t*, char *buf, int len);
extern void winalert(pdfapp_t *, fz_alert_event *alert);
extern void winprint(pdfapp_t *);
extern void winadvancetimer(pdfapp_t *, float duration);
+extern void winreplacefile(char *source, char *target);
struct pdfapp_s
{
/* current document params */
fz_document *doc;
+ char *docpath;
char *doctitle;
fz_outline *outline;
diff --git a/apps/win_main.c b/apps/win_main.c
index 165cbd07..3ae482ec 100644
--- a/apps/win_main.c
+++ b/apps/win_main.c
@@ -19,6 +19,8 @@
#define WM_MOUSEWHEEL 0x020A
#endif
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+
#define ID_ABOUT 0x1000
#define ID_DOCINFO 0x1001
@@ -37,8 +39,10 @@ static int justcopied = 0;
static pdfapp_t gapp;
-static wchar_t wbuf[1024];
-static char filename[1024];
+#define PATH_MAX (1024)
+
+static wchar_t wbuf[PATH_MAX];
+static char filename[PATH_MAX];
/*
* Create registry keys to associate MuPDF with PDF and XPS files.
@@ -189,24 +193,30 @@ int winfilename(wchar_t *buf, int len)
int wingetsavepath(pdfapp_t *app, char *buf, int len)
{
- OPENFILENAMEA ofn;
- buf[0] = 0;
- if (strlen(filename) < (unsigned int)len)
- strcpy(buf, filename);
+ wchar_t twbuf[PATH_MAX];
+ OPENFILENAME ofn;
+
+ wcscpy(twbuf, wbuf);
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwndframe;
- ofn.lpstrFile = buf;
- ofn.nMaxFile = len;
+ ofn.lpstrFile = twbuf;
+ ofn.nMaxFile = PATH_MAX;
ofn.lpstrInitialDir = NULL;
- ofn.lpstrTitle = "MuPDF: Save PDF file";
- ofn.lpstrFilter = "Documents (*.pdf;*.xps;*.cbz;*.zip)\0*.zip;*.cbz;*.xps;*.pdf\0PDF Files (*.pdf)\0*.pdf\0XPS Files (*.xps)\0*.xps\0CBZ Files (*.cbz;*.zip)\0*.zip;*.cbz\0All Files\0*\0\0";
+ ofn.lpstrTitle = L"MuPDF: Save PDF file";
+ ofn.lpstrFilter = L"Documents (*.pdf;*.xps;*.cbz;*.zip)\0*.zip;*.cbz;*.xps;*.pdf\0PDF Files (*.pdf)\0*.pdf\0XPS Files (*.xps)\0*.xps\0CBZ Files (*.cbz;*.zip)\0*.zip;*.cbz\0All Files\0*\0\0";
ofn.Flags = OFN_HIDEREADONLY;
- if (GetSaveFileNameA(&ofn))
+ if (GetSaveFileName(&ofn))
{
- if (strlen(buf) < sizeof(filename))
- strcpy(filename, buf);
+ int code = WideCharToMultiByte(CP_UTF8, 0, twbuf, -1, buf, MIN(PATH_MAX, len), NULL, NULL);
+ if (code == 0)
+ {
+ winerror(&gapp, "cannot convert filename to utf-8");
+ return 0;
+ }
+ wcscpy(wbuf, twbuf);
+ strcpy(filename, buf);
return 1;
}
else
@@ -215,6 +225,33 @@ int wingetsavepath(pdfapp_t *app, char *buf, int len)
}
}
+void winreplacefile(char *source, char *target)
+{
+ wchar_t wsource[PATH_MAX];
+ wchar_t wtarget[PATH_MAX];
+
+ int sz = MultiByteToWideChar(CP_UTF8, 0, source, -1, wsource, PATH_MAX);
+ if (sz == 0)
+ {
+ winerror(&gapp, "cannot convert filename to Unicode");
+ return;
+ }
+
+ sz = MultiByteToWideChar(CP_UTF8, 0, target, -1, wtarget, PATH_MAX);
+ if (sz == 0)
+ {
+ winerror(&gapp, "cannot convert filename to Unicode");
+ return;
+ }
+
+#if (_WIN32_WINNT >= 0x0500)
+ ReplaceFile(wtarget, wsource, NULL, REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL);
+#else
+ DeleteFile(wtarget);
+ MoveFile(wsource, wtarget);
+#endif
+}
+
static char pd_filename[256] = "The file is encrypted.";
static char pd_password[256] = "";
static char td_textinput[1024] = "";
diff --git a/apps/x11_main.c b/apps/x11_main.c
index 9933242a..f4f8b24f 100644
--- a/apps/x11_main.c
+++ b/apps/x11_main.c
@@ -273,6 +273,11 @@ int wingetsavepath(pdfapp_t *app, char *buf, int len)
return 0;
}
+void winreplacefile(char *source, char *target)
+{
+ rename(source, target);
+}
+
void cleanup(pdfapp_t *app)
{
fz_context *ctx = app->ctx;