From e52922a9db9d4e85c256387ec72b40ad742b58c8 Mon Sep 17 00:00:00 2001 From: John McNamara Date: Thu, 17 Dec 2015 00:21:22 +0000 Subject: [PATCH] Added tests for worksheet protect. --- .indent.pro | 3 + include/xlsxwriter/worksheet.h | 3 + src/styles.c | 6 +- src/workbook.c | 2 +- src/worksheet.c | 63 ++- test/functional/src/test_protect01.c | 29 ++ test/functional/src/test_protect02.c | 31 ++ test/functional/src/test_protect03.c | 31 ++ test/functional/test_protect.py | 23 ++ test/functional/xlsx_files/protect01.xlsx | Bin 0 -> 7083 bytes test/functional/xlsx_files/protect02.xlsx | Bin 0 -> 7110 bytes test/functional/xlsx_files/protect03.xlsx | Bin 0 -> 7123 bytes .../test_worksheet_write_sheet_protection.c | 358 +++++++++++++++++- 13 files changed, 541 insertions(+), 8 deletions(-) create mode 100644 test/functional/src/test_protect01.c create mode 100644 test/functional/src/test_protect02.c create mode 100644 test/functional/src/test_protect03.c create mode 100644 test/functional/test_protect.py create mode 100644 test/functional/xlsx_files/protect01.xlsx create mode 100644 test/functional/xlsx_files/protect02.xlsx create mode 100644 test/functional/xlsx_files/protect03.xlsx diff --git a/.indent.pro b/.indent.pro index 05e3e6f6..a81d71c1 100644 --- a/.indent.pro +++ b/.indent.pro @@ -64,8 +64,10 @@ -T lxw_heading_pair -T lxw_merged_range -T lxw_packager +-T lxw_panes -T lxw_part_name -T lxw_print_area +-T lxw_protection -T lxw_rel_tuple -T lxw_relationships -T lxw_repeat_cols @@ -73,6 +75,7 @@ -T lxw_row -T lxw_row_col_options -T lxw_row_t +-T lxw_selection -T lxw_sst -T lxw_styles -T lxw_theme diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h index 9379d1f3..2ed2ccd9 100644 --- a/include/xlsxwriter/worksheet.h +++ b/include/xlsxwriter/worksheet.h @@ -2188,6 +2188,9 @@ void worksheet_hide_zero(lxw_worksheet *worksheet); */ void worksheet_set_tab_color(lxw_worksheet *worksheet, lxw_color_t color); +void worksheet_protect(lxw_worksheet *worksheet, char *password, + lxw_protection *options); + lxw_worksheet *_new_worksheet(lxw_worksheet_init_data *init_data); void _free_worksheet(lxw_worksheet *worksheet); void _worksheet_assemble_xml_file(lxw_worksheet *worksheet); diff --git a/src/styles.c b/src/styles.c index d2b5664b..06c9cbd1 100644 --- a/src/styles.c +++ b/src/styles.c @@ -212,7 +212,7 @@ _write_font_name(lxw_styles *self, const char *font_name) _INIT_ATTRIBUTES(); - if (strlen(font_name)) + if (*font_name) _PUSH_ATTRIBUTES_STR("val", font_name); else _PUSH_ATTRIBUTES_STR("val", LXW_DEFAULT_FONT_NAME); @@ -250,7 +250,7 @@ _write_font_scheme(lxw_styles *self, const char *font_scheme) _INIT_ATTRIBUTES(); - if (strlen(font_scheme)) + if (*font_scheme) _PUSH_ATTRIBUTES_STR("val", font_scheme); else _PUSH_ATTRIBUTES_STR("val", "minor"); @@ -350,7 +350,7 @@ _write_font(lxw_styles *self, lxw_format *format) /* Only write the scheme element for the default font type if it * is a hyperlink. */ - if ((!strlen(format->font_name) + if ((!*format->font_name || strcmp(LXW_DEFAULT_FONT_NAME, format->font_name) == 0) && !format->hyperlink) { _write_font_scheme(self, format->font_scheme); diff --git a/src/workbook.c b/src/workbook.c index 2d218f7f..5a2ece82 100644 --- a/src/workbook.c +++ b/src/workbook.c @@ -335,7 +335,7 @@ _prepare_num_formats(lxw_workbook *self) /* Check if there is a user defined number format string. */ num_format = format->num_format; - if (strlen(num_format)) { + if (*num_format) { /* Look up the num_format in the hash table. */ hash_element = _hash_key_exists(num_formats, num_format, strlen(num_format)); diff --git a/src/worksheet.c b/src/worksheet.c index 77c04657..617983aa 100644 --- a/src/worksheet.c +++ b/src/worksheet.c @@ -653,6 +653,38 @@ _cell_cmp(lxw_cell *cell1, lxw_cell *cell2) return 0; } +/* + * Hash a worksheet password. Based on the algorithm provided by Daniel Rentz + * of OpenOffice. + */ +uint16_t +_hash_password(char *password) +{ + uint8_t count; + uint8_t i; + uint16_t hash = 0x0000; + + count = strlen(password); + + for (i = 0; i < count; i++) { + uint32_t low_15; + uint32_t high_15; + uint32_t letter = password[i] << (i + 1); + + low_15 = letter & 0x7fff; + high_15 = letter & (0x7fff << 15); + high_15 = high_15 >> 15; + letter = low_15 | high_15; + + hash ^= letter; + } + + hash ^= count; + hash ^= 0xCE4B; + + return hash; +} + /***************************************************************************** * * XML functions. @@ -1016,7 +1048,7 @@ _worksheet_write_split_panes(lxw_worksheet *self) * Write the element. */ STATIC void -_worksheet_write_selection(lxw_worksheet *self, lxw_selection * selection) +_worksheet_write_selection(lxw_worksheet *self, lxw_selection *selection) { struct xml_attribute_list attributes; struct xml_attribute *attribute; @@ -2374,7 +2406,7 @@ worksheet_write_string(lxw_worksheet *self, char *string_copy; int8_t err; - if (!string || !strlen(string)) { + if (!string || !*string) { /* Treat a NULL or empty string with formatting as a blank cell. */ /* Null strings without formats should be ignored. */ if (format) @@ -2633,7 +2665,7 @@ worksheet_write_url_opt(lxw_worksheet *self, size_t i; enum cell_types link_type = HYPERLINK_URL; - if (!url || !strlen(url)) + if (!url || !*url) return -LXW_ERROR_WORKSHEET_NULL_STRING_IGNORED; /* Check the Excel limit of URLS per worksheet. */ @@ -3660,3 +3692,28 @@ worksheet_set_tab_color(lxw_worksheet *self, lxw_color_t color) { self->tab_color = color; } + +/* + * Set the worksheet protection flags to prevent modification of worksheet + * objects. + */ +void +worksheet_protect(lxw_worksheet *self, char *password, + lxw_protection *options) +{ + struct lxw_protection *protect = &self->protection; + + /* Copy any user parameters to the internal structure. */ + if (options) + memcpy(protect, options, sizeof(lxw_protection)); + + /* Zero the hash storage in case of copied initialization data. */ + protect->hash[0] = '\0'; + + if (password) { + uint16_t hash = _hash_password(password); + lxw_snprintf(protect->hash, 5, "%X", hash); + } + + protect->is_configured = LXW_TRUE; +} diff --git a/test/functional/src/test_protect01.c b/test/functional/src/test_protect01.c new file mode 100644 index 00000000..56f93b0d --- /dev/null +++ b/test/functional/src/test_protect01.c @@ -0,0 +1,29 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = new_workbook("test_protect01.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + lxw_format *unlocked = workbook_add_format(workbook); + format_set_unlocked(unlocked); + + lxw_format *hidden = workbook_add_format(workbook); + format_set_unlocked(hidden); + format_set_hidden(hidden); + + worksheet_write_number(worksheet, CELL("A1"), 1 , NULL); + worksheet_write_number(worksheet, CELL("A2"), 2, unlocked); + worksheet_write_number(worksheet, CELL("A3"), 3, hidden); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_protect02.c b/test/functional/src/test_protect02.c new file mode 100644 index 00000000..ee70a774 --- /dev/null +++ b/test/functional/src/test_protect02.c @@ -0,0 +1,31 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = new_workbook("test_protect02.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + lxw_format *unlocked = workbook_add_format(workbook); + format_set_unlocked(unlocked); + + lxw_format *hidden = workbook_add_format(workbook); + format_set_unlocked(hidden); + format_set_hidden(hidden); + + worksheet_protect(worksheet, NULL, NULL); + + worksheet_write_number(worksheet, CELL("A1"), 1 , NULL); + worksheet_write_number(worksheet, CELL("A2"), 2, unlocked); + worksheet_write_number(worksheet, CELL("A3"), 3, hidden); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_protect03.c b/test/functional/src/test_protect03.c new file mode 100644 index 00000000..46fa209f --- /dev/null +++ b/test/functional/src/test_protect03.c @@ -0,0 +1,31 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = new_workbook("test_protect03.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + + lxw_format *unlocked = workbook_add_format(workbook); + format_set_unlocked(unlocked); + + lxw_format *hidden = workbook_add_format(workbook); + format_set_unlocked(hidden); + format_set_hidden(hidden); + + worksheet_protect(worksheet, "password", NULL); + + worksheet_write_number(worksheet, CELL("A1"), 1 , NULL); + worksheet_write_number(worksheet, CELL("A2"), 2, unlocked); + worksheet_write_number(worksheet, CELL("A3"), 3, hidden); + + return workbook_close(workbook); +} diff --git a/test/functional/test_protect.py b/test/functional/test_protect.py new file mode 100644 index 00000000..fb4922db --- /dev/null +++ b/test/functional/test_protect.py @@ -0,0 +1,23 @@ +############################################################################### +# +# Tests for libxlsxwriter. +# +# Copyright 2014-2015, John McNamara, jmcnamara@cpan.org +# + +import base_test_class + +class TestCompareXLSXFiles(base_test_class.XLSXBaseTest): + """ + Test file created with libxlsxwriter against a file created by Excel. + + """ + + def test_protect01(self): + self.run_exe_test('test_protect01') + + def test_protect02(self): + self.run_exe_test('test_protect02') + + def test_protect03(self): + self.run_exe_test('test_protect03') diff --git a/test/functional/xlsx_files/protect01.xlsx b/test/functional/xlsx_files/protect01.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..81582e7d05715932ad167a5593708bf0f0768615 GIT binary patch literal 7083 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 literal 0 HcmV?d00001 diff --git a/test/unit/worksheet/test_worksheet_write_sheet_protection.c b/test/unit/worksheet/test_worksheet_write_sheet_protection.c index c394a2a5..f7b40731 100644 --- a/test/unit/worksheet/test_worksheet_write_sheet_protection.c +++ b/test/unit/worksheet/test_worksheet_write_sheet_protection.c @@ -20,7 +20,6 @@ CTEST(worksheet, write_write_sheet_protection01) { lxw_worksheet *worksheet = _new_worksheet(NULL); worksheet->file = testfile; - //worksheet_protect(worksheet, $password, \%options); worksheet->protection.is_configured = 1; _worksheet_write_sheet_protection(worksheet); @@ -28,3 +27,360 @@ CTEST(worksheet, write_write_sheet_protection01) { _free_worksheet(worksheet); } + + +/* 2. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection02) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + worksheet_protect(worksheet, "password", NULL); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + +/* 3. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection03) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.no_select_locked_cells = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 4. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection04) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.format_cells = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 5. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection05) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.format_columns = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 6. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection06) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.format_rows = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 7. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection07) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.insert_columns = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 8. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection08) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.insert_rows = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 9. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection09) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.insert_hyperlinks = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 10. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection10) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.delete_columns = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 11. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection11) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.delete_rows = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 12. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection12) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.sort = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 13. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection13) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.autofilter = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 14. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection14) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.pivot_tables = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 15. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection15) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.objects = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 16. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection16) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = {.scenarios = 1}; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 17. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection17) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = { + .format_cells = 1, + .no_select_locked_cells = 1, + .no_select_unlocked_cells = 1, + }; + + worksheet_protect(worksheet, NULL, &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +} + + +/* 18. Test the _write_sheet_protection() method. */ +CTEST(worksheet, write_write_sheet_protection18) { + char* got; + char exp[] = ""; + FILE* testfile = tmpfile(); + + lxw_worksheet *worksheet = _new_worksheet(NULL); + worksheet->file = testfile; + + lxw_protection options = { + .objects = 1, + .scenarios = 1, + .format_cells = 1, + .format_columns = 1, + .format_rows = 1, + .insert_columns = 1, + .insert_rows = 1, + .insert_hyperlinks = 1, + .delete_columns = 1, + .delete_rows = 1, + .no_select_locked_cells = 1, + .sort = 1, + .autofilter = 1, + .pivot_tables = 1, + .no_select_unlocked_cells = 1, + }; + + worksheet_protect(worksheet, "drowssap", &options); + _worksheet_write_sheet_protection(worksheet); + + RUN_XLSX_STREQ(exp, got); + + _free_worksheet(worksheet); +}