poe

Уређивач .po фајлова
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 62618b41c8f768e3ee54b5b8ce35abdf569991e2
родитељ 96168a6f1bbaa3db3191512ab8f8d8c87f79012e
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Wed, 22 Sep 2021 20:28:41 +0200

Fix: very long msgids/msgstrs (over 1024 characters) were truncated

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
MTODO | 2+-
Mpo.c | 221++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mpo.h | 11++++++++---
Mpoe.c | 36++++++++++++++++++++++++++++++------
Mutil.c | 2+-
Mutil.h | 5++++-
измењених датотека: 6, додавања: 206(+), брисања: 71(-)

diff --git a/TODO b/TODO @@ -1,7 +1,7 @@ TODO ==== - [ ] Fix: very long msgids/msgstrs get truncated (lftp) + [x] Fix: very long msgids/msgstrs get truncated (lftp) < > Sort by flag/column? diff --git a/po.c b/po.c @@ -28,10 +28,16 @@ init_po_entry(struct PoEntry* entry) entry->flags = FL_NONE; entry->obsolete = 0; entry->msgid = NULL; + entry->msgid_size = 0; + entry->msgid_len = 0; entry->msgid_plural = NULL; + entry->msgid_plural_size = 0; + entry->msgid_plural_len = 0; entry->plural_forms = NULL; entry->msgstr = NULL; entry->msgstr_count = 0; + entry->msgstr_size = NULL; + entry->msgstr_len = NULL; entry->comments = NULL; entry->comment_lines = 0; entry->trans_comments = NULL; @@ -52,6 +58,10 @@ free_po_entry(struct PoEntry* entry) free(*msgstr++); free(entry->msgstr); } + if (entry->msgstr_size) + free(entry->msgstr_size); + if (entry->msgstr_len) + free(entry->msgstr_len); if (entry->msgid_plural) free(entry->msgid_plural); if (entry->plural_forms) @@ -95,30 +105,34 @@ set_flags(struct PoEntry* entry, const Flags flags) struct PoEntry* set_msgid(struct PoEntry* entry, const char* msgid, int append) { - uint32_t umsgid[MAXMSG]; + uint32_t umsgid[MAXMSGLINE]; + size_t msgid_size = 0; if (!entry) return NULL; - u8_string_to_unicode(umsgid, msgid, MAXMSG); - return u32_set_msgid(entry, umsgid, append); + msgid_size = u8_string_to_unicode(umsgid, msgid, MAXMSGLINE); + return u32_set_msgid(entry, umsgid, msgid_size, append); } struct PoEntry* set_msgid_plural(struct PoEntry* entry, const char* msgid_plural, int append) { - uint32_t umsgid_plural[MAXMSG]; + uint32_t umsgid_plural[MAXMSGLINE]; + size_t msgid_plural_size = 0; if (!entry) return NULL; - u8_string_to_unicode(umsgid_plural, msgid_plural, MAXMSG); - return u32_set_msgid_plural(entry, umsgid_plural, append); + msgid_plural_size + = u8_string_to_unicode(umsgid_plural, msgid_plural, MAXMSGLINE); + return u32_set_msgid_plural(entry, umsgid_plural, msgid_plural_size, + append); } struct PoEntry* set_plural_forms(struct PoEntry* entry, const char* plural_forms, int append) { - uint32_t uplural_forms[MAXMSG]; + uint32_t uplural_forms[MAXMSGLINE]; if (!entry) return NULL; - u8_string_to_unicode(uplural_forms, plural_forms, MAXMSG); + u8_string_to_unicode(uplural_forms, plural_forms, MAXMSGLINE); return u32_set_plural_forms(entry, uplural_forms, append); } @@ -126,47 +140,80 @@ struct PoEntry* set_msgstr(struct PoEntry* entry, const char* msgstr, int msgstr_index, int append, struct DrawState* state) { - uint32_t umsgstr[MAXMSG]; + uint32_t umsgstr[MAXMSGLINE]; if (!entry) return NULL; - u8_string_to_unicode(umsgstr, msgstr, MAXMSG); + u8_string_to_unicode(umsgstr, msgstr, MAXMSGLINE); return u32_set_msgstr(entry, umsgstr, msgstr_index, append, state); } struct PoEntry* -u32_set_msgid(struct PoEntry* entry, const uint32_t* msgid, int append) +u32_set_msgid(struct PoEntry* entry, const uint32_t* msgid, size_t msgid_size, + int append) { + size_t msgid_len = 0; if (!entry) return NULL; + if (msgid) + msgid_len = u32_strlen(msgid); if (!entry->msgid) { - entry->msgid = calloc(MAXMSG, sizeof(uint32_t)); + entry->msgid_size = MSGDELTA; + entry->msgid_len = 0; + entry->msgid = calloc(entry->msgid_size, sizeof(uint32_t)); if (!entry->msgid) return NULL; } + else if (entry->msgid_len + msgid_len >= entry->msgid_size) + { + entry->msgid_size += MSGDELTA; + entry->msgid = realloc(entry->msgid, + entry->msgid_size * sizeof(uint32_t)); + if (!entry->msgid_plural) + return NULL; + } + entry->msgid_len += msgid_len; if (append) - u32_strncat(entry->msgid, msgid, MAXMSG); + u32_strncat(entry->msgid, msgid, entry->msgid_size); else - u32_strncpy(entry->msgid, msgid, MAXMSG); + u32_strncpy(entry->msgid, msgid, entry->msgid_size); return entry; } struct PoEntry* u32_set_msgid_plural(struct PoEntry* entry, const uint32_t* msgid_plural, - int append) + size_t msgid_plural_size, int append) { + size_t msgid_plural_len = 0; if (!entry) return NULL; + if (msgid_plural) + msgid_plural_len = u32_strlen(msgid_plural); if (!entry->msgid_plural) { - entry->msgid_plural = calloc(MAXMSG, sizeof(uint32_t)); + entry->msgid_plural_size = MSGDELTA; + entry->msgid_plural_len = 0; + entry->msgid_plural + = calloc(entry->msgid_plural_size, sizeof(uint32_t)); if (!entry->msgid_plural) return NULL; } + else if (entry->msgid_plural_size + msgid_plural_len + >= entry->msgid_plural_size) + { + entry->msgid_plural_size += MSGDELTA; + entry->msgid_plural = realloc(entry->msgid_plural, + entry->msgid_plural_size * sizeof(uint32_t)); + if (!entry->msgid_plural) + return NULL; + } + entry->msgid_plural_len += msgid_plural_len; if (append) - u32_strncat(entry->msgid_plural, msgid_plural, MAXMSG); + u32_strncat(entry->msgid_plural, msgid_plural, + entry->msgid_plural_size); else - u32_strncpy(entry->msgid_plural, msgid_plural, MAXMSG); + u32_strncpy(entry->msgid_plural, msgid_plural, + entry->msgid_plural_size); return entry; } @@ -178,14 +225,14 @@ u32_set_plural_forms(struct PoEntry* entry, const uint32_t* plural_forms, return NULL; if (!entry->plural_forms) { - entry->plural_forms = calloc(MAXMSG, sizeof(uint32_t)); + entry->plural_forms = calloc(MAXMSGLINE, sizeof(uint32_t)); if (!entry->plural_forms) return NULL; } if (append) - u32_strncat(entry->plural_forms, plural_forms, MAXMSG); + u32_strncat(entry->plural_forms, plural_forms, MAXMSGLINE); else - u32_strncpy(entry->plural_forms, plural_forms, MAXMSG); + u32_strncpy(entry->plural_forms, plural_forms, MAXMSGLINE); return entry; } @@ -193,40 +240,72 @@ struct PoEntry* u32_set_msgstr(struct PoEntry* entry, const uint32_t* msgstr, int msgstr_index, int append, struct DrawState* state) { + size_t msgstr_len = 0; if (!entry) return NULL; + if (msgstr) + msgstr_len = u32_strlen(msgstr); if (entry->msgstr_count == 0 || msgstr_index + 1 > entry->msgstr_count) { - uint32_t** newmsgstr = NULL; - entry->msgstr_count = msgstr_index + 1; + uint32_t** newmsgstr = NULL; + size_t* newmsgstr_size = NULL; + size_t* newmsgstr_len = NULL; + entry->msgstr_count = msgstr_index + 1; if (!entry->msgstr) { newmsgstr = calloc(entry->msgstr_count, sizeof(uint32_t*)); + newmsgstr_size + = calloc(entry->msgstr_count, sizeof(size_t)); + newmsgstr_len + = calloc(entry->msgstr_count, sizeof(size_t)); /* when the .po file is not a standard text file (no LF * at end) */ if (state->untranslated_count > 0) state->untranslated_count--; } else - newmsgstr = realloc(entry->msgstr, - entry->msgstr_count * sizeof(uint32_t*)); - if (!newmsgstr) + { + newmsgstr = realloc(entry->msgstr, + entry->msgstr_count * sizeof(uint32_t*)); + newmsgstr_size = realloc(entry->msgstr_size, + entry->msgstr_count * sizeof(size_t)); + newmsgstr_len = realloc(entry->msgstr_len, + entry->msgstr_count * sizeof(size_t)); + } + if (!newmsgstr || !newmsgstr_size || !newmsgstr_len) return NULL; *(newmsgstr + msgstr_index) = NULL; entry->msgstr = newmsgstr; + entry->msgstr_size = newmsgstr_size; + entry->msgstr_len = newmsgstr_len; } if (!*(entry->msgstr + msgstr_index)) { + *(entry->msgstr_size + msgstr_index) = MSGDELTA; + *(entry->msgstr_len + msgstr_index) = 0; *(entry->msgstr + msgstr_index) - = calloc(MAXMSG, sizeof(uint32_t)); - if (!*(entry->msgstr + msgstr_index)) - return NULL; + = calloc(*(entry->msgstr_size + msgstr_index), + sizeof(uint32_t)); } + else if (*(entry->msgstr_len + msgstr_index) + msgstr_len + >= *(entry->msgstr_size + msgstr_index)) + { + *(entry->msgstr_size + msgstr_index) += MSGDELTA; + *(entry->msgstr + msgstr_index) + = realloc(*(entry->msgstr + msgstr_index), + *(entry->msgstr_size + msgstr_index) + * sizeof(uint32_t)); + } + *(entry->msgstr_len + msgstr_index) += msgstr_len; + if (!*(entry->msgstr + msgstr_index)) + return NULL; if (append) - u32_strncat(*(entry->msgstr + msgstr_index), msgstr, MAXMSG); + u32_strncat(*(entry->msgstr + msgstr_index), msgstr, + *(entry->msgstr_size + msgstr_index)); else - u32_strncpy(*(entry->msgstr + msgstr_index), msgstr, MAXMSG); + u32_strncpy(*(entry->msgstr + msgstr_index), msgstr, + *(entry->msgstr_size + msgstr_index)); return entry; } @@ -421,23 +500,23 @@ save_loop_entries_start: goto save_loop_entries_done; if (current->comment_lines > 0) { - char u8_comment[MAXCOMMENTLINE * 6]; + char u8_comment[MAXCOMMENTLINE * UTF8REPMAX]; for (size_t c = 0; c < current->comment_lines; c++) { unicode_string_to_u8(u8_comment, - *(current->comments + c), MAXCOMMENTLINE * 6); + *(current->comments + c), MAXCOMMENTLINE * UTF8REPMAX); fprintf(output, "#%s%s\n", current->obsolete ? "~" : "", u8_comment); } } if (current->trans_comment_lines > 0) { - char u8_trans_comment[MAXCOMMENTLINE * 6]; + char u8_trans_comment[MAXCOMMENTLINE * UTF8REPMAX]; for (size_t tc = 0; tc < current->trans_comment_lines; tc++) { unicode_string_to_u8(u8_trans_comment, *(current->trans_comments + tc), - MAXCOMMENTLINE * 6); + MAXCOMMENTLINE * UTF8REPMAX); fprintf(output, "#.%s%s\n", u8_trans_comment[0] == 0 ? "" : " ", u8_trans_comment); @@ -487,8 +566,11 @@ save_loop_entries_start: if (current->msgid) { - char msgid[MAXMSG]; - unicode_string_to_u8(msgid, current->msgid, MAXMSG); + size_t msgid_size = current->msgid_size * UTF8REPMAX; + /*char* msgid = calloc(current->msgid_size, UTF8REPMAX);*/ + /*if (!msgid)*/ + /*return SAVE_ERR_CANT_ALLOC;*/ + /*unicode_string_to_u8(msgid, current->msgid, msgid_size);*/ size_t actual_lines = 0; size_t num_lines = u32_lines_in_string(current->msgid, &actual_lines); @@ -503,15 +585,19 @@ save_loop_entries_start: fprintf(output, "msgid \"\"\n"); for (size_t i = 0; i < num_lines; i++) { - pmsgid_split = msgid_split + i; - int last = i == num_lines - 1; - char u8_msgid[MAXMSG * 6]; + pmsgid_split = msgid_split + i; + int last = i == num_lines - 1; + char* u8_msgid = calloc(current->msgid_size, + UTF8REPMAX); + if (!u8_msgid) + return SAVE_ERR_CANT_ALLOC; size_t len = u32_strlen(pmsgid_split->text); unicode_string_to_u8(u8_msgid, - pmsgid_split->text, MAXMSG * 6); + pmsgid_split->text, msgid_size); if (!(last && len == 0)) fprintf(output, "\"%s%s\"\n", u8_msgid, last ? "" : "\\n"); + free(u8_msgid); } for (size_t i = 0; i < num_lines; i++) { @@ -522,20 +608,27 @@ save_loop_entries_start: } else { - char u8_msgid[MAXMSG * 6]; + char* u8_msgid + = calloc(current->msgid_size, UTF8REPMAX); + if (!u8_msgid) + return SAVE_ERR_CANT_ALLOC; unicode_string_to_u8(u8_msgid, current->msgid, - MAXMSG * 6); + msgid_size); fprintf(output, "msgid \"%s\"\n", u8_msgid); + free(u8_msgid); } + /*free(msgid);*/ } else fprintf(output, "msgid \"\"\n"); if (current->msgid_plural) { - char msgid_plural[MAXMSG]; - unicode_string_to_u8(msgid_plural, current->msgid_plural, - MAXMSG); + size_t msgid_plural_size + = current->msgid_plural_size * UTF8REPMAX; + /*char msgid_plural[MAXMSG];*/ + /*unicode_string_to_u8(msgid_plural, current->msgid_plural,*/ + /*MAXMSG);*/ size_t actual_lines = 0; size_t num_lines = u32_lines_in_string(current->msgid_plural, &actual_lines); @@ -553,13 +646,18 @@ save_loop_entries_start: { pmsgid_split = msgid_split + i; int last = i == num_lines - 1; - char u8_msgid[MAXMSG * 6]; + char* u8_msgid + = calloc(current->msgid_plural_size, + UTF8REPMAX); + if (!u8_msgid) + return SAVE_ERR_CANT_ALLOC; size_t len = u32_strlen(pmsgid_split->text); unicode_string_to_u8(u8_msgid, - pmsgid_split->text, MAXMSG * 6); + pmsgid_split->text, msgid_plural_size); if (!(last && len == 0)) fprintf(output, "\"%s%s\"\n", u8_msgid, last ? "" : "\\n"); + free(u8_msgid); } for (size_t i = 0; i < num_lines; i++) { @@ -570,10 +668,14 @@ save_loop_entries_start: } else { - char u8_msgid[MAXMSG * 6]; + char* u8_msgid = calloc(current->msgid_plural_size, + UTF8REPMAX); + if (!u8_msgid) + return SAVE_ERR_CANT_ALLOC; unicode_string_to_u8(u8_msgid, current->msgid_plural, - MAXMSG * 6); + msgid_plural_size); fprintf(output, "msgid_plural \"%s\"\n", u8_msgid); + free(u8_msgid); } } @@ -603,10 +705,11 @@ save_loop_entries_start: { pmsgstr_split = msgstr_split + i; int last = i == num_lines - 1; - char u8_msgstr[MAXMSG * 6]; + char u8_msgstr[MAXMSGLINE * UTF8REPMAX]; size_t len = u32_strlen(pmsgstr_split->text); unicode_string_to_u8(u8_msgstr, - pmsgstr_split->text, MAXMSG * 6); + pmsgstr_split->text, + MAXMSGLINE * UTF8REPMAX); if (first_entry && starts_with(u8_msgstr, @@ -646,9 +749,9 @@ save_loop_entries_start: fprintf(output, "msgstr[%d] \"\"\n", i); else { - char u8_msgstr[MAXMSG * 6]; + char u8_msgstr[MAXMSGLINE * UTF8REPMAX]; unicode_string_to_u8(u8_msgstr, *current->msgstr, - MAXMSG * 6); + MAXMSGLINE * UTF8REPMAX); fprintf(output, "msgstr \"%s\"\n", u8_msgstr); } } @@ -673,12 +776,12 @@ save_loop_entries_start: { pmsgstr_split = msgstr_split + i; int last = i == num_lines - 1; - char u8_msgstr[MAXMSG * 6]; + char u8_msgstr[MAXMSGLINE * UTF8REPMAX]; size_t len = u32_strlen( pmsgstr_split->text); unicode_string_to_u8(u8_msgstr, pmsgstr_split->text, - MAXMSG * 6); + MAXMSGLINE * UTF8REPMAX); if (!(last && len == 0)) fprintf(output, "\"%s%s\"\n", u8_msgstr, @@ -693,9 +796,10 @@ save_loop_entries_start: } else { - char u8_msgstr[MAXMSG * 6]; + char u8_msgstr[MAXMSGLINE * UTF8REPMAX]; unicode_string_to_u8(u8_msgstr, - *(current->msgstr + m), MAXMSG * 6); + *(current->msgstr + m), + MAXMSGLINE * UTF8REPMAX); fprintf(output, "msgstr[%ld] \"%s\"\n", m, u8_msgstr); } @@ -1071,4 +1175,3 @@ update_statistics(const struct PoEntry* entries, struct DrawState* state, current++; } } - diff --git a/po.h b/po.h @@ -71,10 +71,16 @@ struct PoEntry { Flags flags; int obsolete; uint32_t* msgid; + size_t msgid_size; + size_t msgid_len; uint32_t* msgid_plural; + size_t msgid_plural_size; + size_t msgid_plural_len; uint32_t* plural_forms; uint32_t** msgstr; int msgstr_count; + size_t* msgstr_size; + size_t* msgstr_len; uint32_t** comments; size_t comment_lines; uint32_t** trans_comments; @@ -95,9 +101,9 @@ struct PoEntry* set_plural_forms(struct PoEntry* entry, struct PoEntry* set_msgstr(struct PoEntry* entry, const char* msgstr, int msgstr_index, int append, struct DrawState* state); struct PoEntry* u32_set_msgid(struct PoEntry* entry, const uint32_t* msgid, - int append); + size_t msgid_size, int append); struct PoEntry* u32_set_msgid_plural(struct PoEntry* entry, - const uint32_t* msgid_plural, int append); + const uint32_t* msgid_plural, size_t msgid_plural_size, int append); struct PoEntry* u32_set_plural_forms(struct PoEntry* entry, const uint32_t* plural_forms, int append); struct PoEntry* u32_set_msgstr(struct PoEntry* entry, const uint32_t* msgstr, @@ -114,4 +120,3 @@ int parse_po_line(const char* line, struct DrawState* dstate, int* msgstr_index); void update_statistics(const struct PoEntry* entries, struct DrawState* state, struct PoEntry* entry); - diff --git a/poe.c b/poe.c @@ -180,6 +180,13 @@ load_info(struct DrawState* state) struct BufferLine* newbuf = NULL; struct BufferLine* pnewbuf = NULL; + if (state->info_buffer) + { + for (size_t i = 0; i < state->info_rows_count; i++) + free_bufferline(state->info_buffer + i); + free(state->info_buffer); + } + state->info_rows_maxlen = 0; if (current->msgid) @@ -364,6 +371,13 @@ load_msgstr(struct DrawState* state) struct BufferLine* newbuf = NULL; struct BufferLine* pnewbuf = NULL; + if (state->input_buffer) + { + for (size_t i = 0; i < state->input_rows_count; i++) + free_bufferline(state->input_buffer + i); + free(state->input_buffer); + } + newbuf = calloc(num_lines, sizeof(struct BufferLine)); if (!newbuf) return NULL; @@ -413,25 +427,34 @@ load_msgstr(struct DrawState* state) void save_msgstr(struct DrawState* state) { - uint32_t to_save[MAXMSG]; + uint32_t* to_save = NULL; + size_t to_save_size = 0; state->show_edit = 0; state->edit_info_focused = 0; if (state->input_buffer) { + to_save_size = state->input_rows_count * MAXMSGLINE; + to_save = calloc(to_save_size, sizeof(uint32_t)); + if (!to_save) + { + strcpy(state->error, errors[ERR_CANT_ALLOC]); + return; + } struct BufferLine* pinput_buffer = NULL; for (size_t i = 0; i < state->input_rows_count; i++) { pinput_buffer = state->input_buffer + i; if (i == 0) u32_strncpy(to_save, pinput_buffer->text, - MAXMSG); + to_save_size * sizeof(uint32_t)); else { - u32_strncat(to_save, (uint32_t*)L"\\n", MAXMSG); + u32_strncat(to_save, (uint32_t*)L"\\n", + to_save_size * sizeof(uint32_t)); u32_strncat(to_save, pinput_buffer->text, - MAXMSG); + to_save_size * sizeof(uint32_t)); } free_bufferline(pinput_buffer); } @@ -443,12 +466,14 @@ save_msgstr(struct DrawState* state) free_bufferline(state->info_buffer + i); free(state->info_buffer); state->info_buffer = NULL; - u32_encode_tabs(to_save, MAXBUFLINE); + u32_encode_tabs(to_save, to_save_size * sizeof(uint32_t)); u32_set_msgstr(&state->entries[state->msgid_number - 1], to_save, state->msgstr_index, 0, state); state->input_changed_fuzzy = UNCHANGED; tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR); + if (to_save) + free(to_save); } void @@ -2088,4 +2113,3 @@ main(int argc, char** argv) free_drawstate(&state); return 0; } - diff --git a/util.c b/util.c @@ -192,7 +192,7 @@ u32_u8_strncpy(uint32_t* to, const char* from, size_t max) size_t u8_u32_strncpy(char* to, const uint32_t* from, size_t max) { - char* cfrom = calloc(u32_strlen(from) * 6 + 1, 1); + char* cfrom = calloc(u32_strlen(from) * UTF8REPMAX + 1, 1); if (!cfrom) return 0; unicode_string_to_u8(cfrom, from, max); diff --git a/util.h b/util.h @@ -20,8 +20,11 @@ enum { #define MAXBUFLINE 4096 #define MAXDATEBUF 80 #define MAXFLAGSBUF (4 + 1) -#define MAXMSG 1024 +#define MAXMSGLINE 1024 +#define MSGDELTA 1024 #define MAXPATH 1024 +/* maximum chars for UTF-8 representations of Unicode chars, per Unicode char */ +#define UTF8REPMAX 6 size_t u8_string_to_unicode(uint32_t* us, const char* s, const size_t max); size_t unicode_string_to_u8(char* s, const uint32_t* us, const size_t max);