diff --git a/src/scripting/scripting.c b/src/scripting/scripting.c index 67645737..b396544b 100644 --- a/src/scripting/scripting.c +++ b/src/scripting/scripting.c @@ -36,7 +36,7 @@ report_scripting_error(struct module *module, struct session *ses, if (!ses) { if (list_empty(terminals)) { - usrerror("%s error] %s", module->name, msg); + usrerror("[%s error] %s", module->name, msg); return; } diff --git a/src/util/string.c b/src/util/string.c index ee1cfa15..b8865568 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -4,8 +4,13 @@ #include "config.h" #endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* XXX: fseeko, ftello */ +#endif + #include #include +#include #include #include @@ -325,6 +330,46 @@ add_string_to_string(struct string *string, struct string *from) return add_bytes_to_string(string, from->source, from->length); } +struct string * +add_file_to_string(struct string *string, unsigned char *filename) +{ + FILE *file; + off_t filelen; + int newlength; + + assertm(string && filename, "[add_file_to_string]"); + if_assert_failed { return NULL; } + + check_string_magic(string); + + file = fopen(filename, "rb"); + if (!file) return NULL; + + if (fseeko(file, 0, SEEK_END)) goto err; + + filelen = ftello(file); + if (filelen == -1) goto err; + + if (fseeko(file, 0, SEEK_SET)) goto err; + + newlength = string->length + filelen; + if (!realloc_string(string, newlength)) goto err; + + string->length += fread(string->source + string->length, 1, + (size_t) filelen, file); + string->source[string->length] = 0; + fclose(file); + + if (string->length != newlength) goto err; + + return string; + +err: + fclose(file); + + return NULL; +} + struct string * string_concat(struct string *string, ...) { diff --git a/src/util/string.h b/src/util/string.h index 6d8715bd..7390061c 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -157,6 +157,7 @@ struct string *add_to_string(struct string *string, const unsigned char *source); struct string *add_char_to_string(struct string *string, unsigned char character); struct string *add_string_to_string(struct string *to, struct string *from); +struct string *add_file_to_string(struct string *string, unsigned char *filename); struct string *add_crlf_to_string(struct string *string); /* Adds each C string to @string until a terminating NULL is met. */ diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index 680216b7..f8e66ded 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -311,37 +311,6 @@ save_textarea_file(unsigned char *value) return filename; } -static unsigned char * -load_textarea_file(unsigned char *filename, size_t maxlength) -{ - unsigned char *value = NULL; - FILE *file = fopen(filename, "rb+"); - off_t filelen = -1; - - if (!file) return NULL; - - if (!fseeko(file, 0, SEEK_END)) { - filelen = ftello(file); - if (filelen != -1 && fseeko(file, 0, SEEK_SET)) - filelen = -1; - } - - if (filelen >= 0 && filelen <= maxlength) { - value = mem_alloc((size_t) (filelen + 1)); - if (value) { - size_t bread; - - bread = fread(value, 1, (size_t) filelen, file); - value[bread] = 0; - } - } - - fclose(file); - unlink(filename); - - return value; -} - void textarea_edit(int op, struct terminal *term_, struct form_state *fs_, struct document_view *doc_view_, struct link *link_) @@ -403,17 +372,39 @@ textarea_edit(int op, struct terminal *term_, struct form_state *fs_, textarea_editor = 1; } else if (op == 1 && fs) { - unsigned char *value = load_textarea_file(fn, fc_maxlength); + struct string file; - if (value) { - mem_free(fs->value); - fs->value = value; - fs->state = strlen(value); - - if (doc_view && link) - draw_form_entry(term, doc_view, link); + if (!init_string(&file) + || !add_file_to_string(&file, fn)) { + textarea_editor = 0; + goto free_and_return; } + if (file.length > fc_maxlength) { + file.source[fc_maxlength] = '\0'; + info_box(term, MSGBOX_FREE_TEXT, N_("Warning"), + ALIGN_CENTER, + msg_text(term, + N_("You have exceeded the textarea's" + " size limit: your input is %d" + " bytes, but the maximum is %u" + " bytes.\n\n" + "Your input has been truncated," + " but you can still recover the" + " text that you entered from" + " this file: %s"), file.length, + fc_maxlength, fn)); + } else { + unlink(fn); + } + + mem_free(fs->value); + fs->value = file.source; + fs->state = file.length; + + if (doc_view && link) + draw_form_entry(term, doc_view, link); + textarea_editor = 0; goto free_and_return; }