Skip to content

Commit 2a1d0c0

Browse files
authored
fix wvware (#422)
1 parent 7f8d45b commit 2a1d0c0

5 files changed

Lines changed: 74 additions & 74 deletions

File tree

src/odr/internal/html/wvware_wrapper.cpp

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ namespace {
3939
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wv.h#L2776-L2814
4040
/// to allow for more state variables.
4141
struct TranslationState : public expand_data {
42-
explicit TranslationState(html::HtmlWriter _out)
43-
: expand_data{}, out(std::move(_out)) {}
42+
explicit TranslationState(html::HtmlWriter _out, const HtmlConfig &_config,
43+
std::string _cache_path)
44+
: expand_data{}, out(std::move(_out)), config{&_config},
45+
cache_path{std::move(_cache_path)} {}
4446

4547
char *charset = nullptr;
4648
PAP *ppap = nullptr;
@@ -52,12 +54,14 @@ struct TranslationState : public expand_data {
5254
std::size_t figure_number = 0;
5355

5456
html::HtmlWriter out;
57+
const HtmlConfig *config;
58+
std::string cache_path;
5559
};
5660

5761
/// Originally from `text.c` `wvConvertUnicodeToHtml`
5862
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/text.c#L1999-L2154
5963
int convert_unicode_to_html(wvParseStruct *ps, std::uint16_t char16) {
60-
auto *data = (TranslationState *)ps->userData;
64+
auto *data = static_cast<TranslationState *>(ps->userData);
6165
auto &out = data->out;
6266

6367
switch (char16) {
@@ -103,14 +107,6 @@ int convert_unicode_to_html(wvParseStruct *ps, std::uint16_t char16) {
103107
return 1;
104108
/* end german characters */
105109
case 0x2026:
106-
#if 0
107-
/*
108-
this just looks awful in netscape 4.5, so im going to do a very foolish
109-
thing and just put ... instead of this
110-
*/
111-
printf ("&#133;");
112-
/*is there a proper html name for ... &ellipse;? Yes, &hellip; -- MV */
113-
#endif
114110
out.out() << "&hellip;";
115111
return 1;
116112
case 0x2019:
@@ -208,19 +204,17 @@ thing and just put ... instead of this
208204
default:
209205
break;
210206
}
211-
/* Debugging aid: */
212-
/* if (char16 >= 0x100) printf("[%x]", char16); */
213207
return 0;
214208
}
215209

216210
/// Originally from `text.c` `wvOutputFromUnicode`
217211
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/text.c#L757-L840
218212
void output_from_unicode(wvParseStruct *ps, std::uint16_t eachchar,
219213
char *outputtype) {
220-
auto *data = (TranslationState *)ps->userData;
214+
auto *data = static_cast<TranslationState *>(ps->userData);
221215
auto &out = data->out;
222216

223-
GIConv g_iconv_handle = (GIConv)-1;
217+
GIConv g_iconv_handle;
224218
int need_swapping;
225219
gchar *ibuf, *obuf;
226220
std::size_t ibuflen, obuflen, len, count, i;
@@ -296,7 +290,7 @@ void output_from_unicode(wvParseStruct *ps, std::uint16_t eachchar,
296290
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L661-L676
297291
/// simplified to HTML output
298292
void strange_no_graphic_data(wvParseStruct *ps, int graphicstype) {
299-
auto *data = (TranslationState *)ps->userData;
293+
auto *data = static_cast<TranslationState *>(ps->userData);
300294
auto &out = data->out;
301295

302296
std::cerr << "Strange No Graphic Data in the 0x01/0x08 graphic\n";
@@ -310,18 +304,18 @@ void strange_no_graphic_data(wvParseStruct *ps, int graphicstype) {
310304
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L1239-L1287
311305
/// simplified to HTML output
312306
void print_graphics(wvParseStruct *ps, int graphicstype, int width, int height,
313-
const std::string &source) {
307+
const std::string &path) {
314308
// upstream converts to PNG, we just use the original format as the browser
315309
// should support them
316310

317-
auto *data = (TranslationState *)ps->userData;
311+
auto *data = static_cast<TranslationState *>(ps->userData);
318312
auto &out = data->out;
319313

320314
// TODO export/embed image
321315

322316
out.out() << R"(<img width=")" << width << R"(" height=")" << height
323317
<< R"(" alt=")" << std::hex << graphicstype << R"( graphic" src=")"
324-
<< source << R"("/><br/>)";
318+
<< path << R"("/><br/>)";
325319
}
326320

327321
void handle_bitmap(wvParseStruct * /*ps*/, const std::string &name,
@@ -343,17 +337,16 @@ void handle_bitmap(wvParseStruct * /*ps*/, const std::string &name,
343337
fclose(fd);
344338
}
345339

346-
int handle_metafile(wvParseStruct * /*ps*/, const char *name,
340+
int handle_metafile(wvParseStruct * /*ps*/, const std::string &name,
347341
MetaFileBlip *bitmap) {
348342
wvStream *pwv = bitmap->m_pvBits;
349343
FILE *fd = nullptr;
350344
std::size_t size = 0, i;
351345
std::uint8_t decompressf = 0;
352346

353-
fd = fopen(name, "wb");
347+
fd = fopen(name.c_str(), "wb");
354348
if (fd == nullptr) {
355-
fprintf(stderr, "\nCannot open %s for writing\n", name);
356-
exit(1);
349+
throw std::runtime_error("Cannot open " + name + " file for writing");
357350
}
358351
size = wvStream_size(pwv);
359352
wvStream_rewind(pwv);
@@ -393,20 +386,26 @@ int handle_metafile(wvParseStruct * /*ps*/, const char *name,
393386
}
394387

395388
std::string figure_name(wvParseStruct *ps) {
396-
auto *data = (TranslationState *)ps->userData;
389+
auto *data = static_cast<TranslationState *>(ps->userData);
397390

398391
std::size_t number = data->figure_number++;
399392
std::string name = "figure" + std::to_string(number);
400393

401394
return name;
402395
}
403396

397+
std::string figure_path(wvParseStruct *ps) {
398+
auto *data = static_cast<TranslationState *>(ps->userData);
399+
400+
return data->cache_path + "/" + figure_name(ps);
401+
}
402+
404403
std::string html_graphic(wvParseStruct *ps, Blip *blip) {
405-
std::string name;
404+
std::string path;
406405
wvStream *fd;
407406
char test[3];
408407

409-
name = figure_name(ps);
408+
path = figure_path(ps);
410409

411410
/*
412411
temp hack to test older included bmps in word 6 and 7,
@@ -424,47 +423,47 @@ std::string html_graphic(wvParseStruct *ps, Blip *blip) {
424423
test[1] = (char)read_8ubit(fd);
425424
wvStream_rewind(fd);
426425
if (!(strcmp(test, "BM"))) {
427-
name += ".bmp";
428-
handle_bitmap(ps, name, &blip->blip.bitmap);
429-
return name;
426+
path += ".bmp";
427+
handle_bitmap(ps, path, &blip->blip.bitmap);
428+
return path;
430429
}
431430
default:
432431
break;
433432
}
434433

435434
switch (blip->type) {
436435
case msoblipWMF:
437-
name += ".wmf";
438-
handle_metafile(ps, name.c_str(), &blip->blip.metafile);
436+
path += ".wmf";
437+
handle_metafile(ps, path, &blip->blip.metafile);
439438
break;
440439
case msoblipEMF:
441-
name += ".emf";
442-
handle_metafile(ps, name.c_str(), &blip->blip.metafile);
440+
path += ".emf";
441+
handle_metafile(ps, path, &blip->blip.metafile);
443442
break;
444443
case msoblipPICT:
445-
name += ".pict";
446-
handle_metafile(ps, name.c_str(), &blip->blip.metafile);
444+
path += ".pict";
445+
handle_metafile(ps, path, &blip->blip.metafile);
447446
break;
448447
case msoblipJPEG:
449-
name += ".jpg";
450-
handle_bitmap(ps, name.c_str(), &blip->blip.bitmap);
448+
path += ".jpg";
449+
handle_bitmap(ps, path, &blip->blip.bitmap);
451450
break;
452451
case msoblipDIB:
453-
name += ".dib";
454-
handle_bitmap(ps, name.c_str(), &blip->blip.bitmap);
452+
path += ".dib";
453+
handle_bitmap(ps, path, &blip->blip.bitmap);
455454
break;
456455
case msoblipPNG:
457-
name += ".png";
458-
handle_bitmap(ps, name.c_str(), &blip->blip.bitmap);
456+
path += ".png";
457+
handle_bitmap(ps, path, &blip->blip.bitmap);
459458
break;
460459
}
461-
return name;
460+
return path;
462461
}
463462

464463
/// Originally from `wvWare.c` `myelehandler`
465464
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L503-L599
466465
int element_handler(wvParseStruct *ps, wvTag tag, void *props, int /*dirty*/) {
467-
auto *data = (TranslationState *)ps->userData;
466+
auto *data = static_cast<TranslationState *>(ps->userData);
468467
data->anSttbfAssoc = &ps->anSttbfAssoc;
469468
data->lfo = &ps->lfo;
470469
data->lfolvl = ps->lfolvl;
@@ -548,7 +547,7 @@ int element_handler(wvParseStruct *ps, wvTag tag, void *props, int /*dirty*/) {
548547
/// Originally from `wvWare.c` `mydochandler`
549548
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L601-L659
550549
int document_handler(wvParseStruct *ps, wvTag tag) {
551-
auto *data = (TranslationState *)ps->userData;
550+
auto *data = static_cast<TranslationState *>(ps->userData);
552551
data->anSttbfAssoc = &ps->anSttbfAssoc;
553552
data->lfo = &ps->lfo;
554553
data->lfolvl = ps->lfolvl;
@@ -601,7 +600,7 @@ int document_handler(wvParseStruct *ps, wvTag tag) {
601600
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L1556-L1605
602601
int char_handler(wvParseStruct *ps, std::uint16_t eachchar,
603602
std::uint8_t chartype, std::uint16_t lid) {
604-
auto *data = (TranslationState *)ps->userData;
603+
auto *data = static_cast<TranslationState *>(ps->userData);
605604

606605
switch (eachchar) {
607606
case 19:
@@ -645,7 +644,7 @@ int char_handler(wvParseStruct *ps, std::uint16_t eachchar,
645644
/// Originally from `wvWare.c` `mySpecCharProc`
646645
/// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L1289-L1553
647646
int special_char_handler(wvParseStruct *ps, std::uint16_t eachchar, CHP *achp) {
648-
auto *data = (TranslationState *)ps->userData;
647+
auto *data = static_cast<TranslationState *>(ps->userData);
649648
auto &state = data->special_char_handler_state;
650649
auto &out = data->out;
651650

@@ -698,9 +697,9 @@ int special_char_handler(wvParseStruct *ps, std::uint16_t eachchar, CHP *achp) {
698697
wvGetPICF(wvQuerySupported(&ps->fib, nullptr), &picf, ps->data);
699698
f = picf.rgb;
700699
if (wv0x01(&blip, f, picf.lcb - picf.cbHeader) != 0) {
701-
std::string name = html_graphic(ps, &blip);
700+
std::string path = html_graphic(ps, &blip);
702701
print_graphics(ps, 0x01, (int)wvTwipsToHPixels(picf.dxaGoal),
703-
(int)wvTwipsToVPixels(picf.dyaGoal), name);
702+
(int)wvTwipsToVPixels(picf.dyaGoal), path);
704703
} else {
705704
strange_no_graphic_data(ps, 0x01);
706705
}
@@ -722,17 +721,17 @@ int special_char_handler(wvParseStruct *ps, std::uint16_t eachchar, CHP *achp) {
722721

723722
data->props = fspa;
724723
if (wv0x08(&blip, (int)fspa->spid, ps) != 0) {
725-
std::string name = html_graphic(ps, &blip);
724+
std::string path = html_graphic(ps, &blip);
726725
print_graphics(
727726
ps, 0x08,
728727
(int)wvTwipsToHPixels((short)(fspa->xaRight - fspa->xaLeft)),
729728
(int)wvTwipsToVPixels((short)(fspa->yaBottom - fspa->yaTop)),
730-
name);
729+
path);
731730
} else {
732731
strange_no_graphic_data(ps, 0x08);
733732
}
734733
} else {
735-
std::cerr << "nooffspa was <=0! Ignoring.\n";
734+
std::cerr << "nooffspa was <=0! Ignoring.\n";
736735
}
737736
} else {
738737
std::cerr << "pre word8 0x08 graphic, unsupported at the moment\n";
@@ -753,9 +752,9 @@ int special_char_handler(wvParseStruct *ps, std::uint16_t eachchar, CHP *achp) {
753752

754753
if (0 == memcmp(symbol, ps->fonts.ffn[achp->ftcSym].xszFfn, 12)) {
755754
if ((state.message == 0) && (strcasecmp("UTF-8", data->charset) != 0)) {
756-
std::cerr
757-
<< "Symbol font detected (too late sorry!), rerun wvHtml with option --charset utf-8\n\
758-
option to support correct symbol font conversion to a viewable format.\n";
755+
std::cerr << "Symbol font detected (too late sorry!), rerun wvHtml "
756+
"with option --charset utf-8\noption to support correct "
757+
"symbol font conversion to a viewable format.\n";
759758
state.message++;
760759
}
761760
output_from_unicode(ps, wvConvertSymbolToUnicode(achp->xchSym - 61440),
@@ -798,8 +797,10 @@ option to support correct symbol font conversion to a viewable format.\n";
798797

799798
class HtmlServiceImpl : public HtmlService {
800799
public:
801-
HtmlServiceImpl(WvWareLegacyMicrosoftFile oldms_file, HtmlConfig config)
802-
: HtmlService(std::move(config)), m_oldms_file{std::move(oldms_file)} {
800+
HtmlServiceImpl(WvWareLegacyMicrosoftFile oldms_file, HtmlConfig config,
801+
std::string cache_path)
802+
: HtmlService(std::move(config)), m_oldms_file{std::move(oldms_file)},
803+
m_cache_path{std::move(cache_path)} {
803804
m_views.emplace_back(
804805
std::make_shared<HtmlView>(*this, "document", "document.html"));
805806
}
@@ -854,7 +855,7 @@ class HtmlServiceImpl : public HtmlService {
854855
wvSetSpecialCharHandler(&ps, special_char_handler);
855856

856857
state_data handle;
857-
TranslationState translation_state(out);
858+
TranslationState translation_state(out, config(), m_cache_path);
858859

859860
wvInitStateData(&handle);
860861

@@ -885,6 +886,8 @@ class HtmlServiceImpl : public HtmlService {
885886
WvWareLegacyMicrosoftFile m_oldms_file;
886887

887888
HtmlViews m_views;
889+
890+
std::string m_cache_path;
888891
};
889892

890893
} // namespace
@@ -896,10 +899,8 @@ odr::HtmlService
896899
html::create_wvware_oldms_service(const WvWareLegacyMicrosoftFile &oldms_file,
897900
const std::string &cache_path,
898901
HtmlConfig config) {
899-
(void)cache_path;
900-
901-
return odr::HtmlService(
902-
std::make_unique<HtmlServiceImpl>(oldms_file, std::move(config)));
902+
return odr::HtmlService(std::make_unique<HtmlServiceImpl>(
903+
oldms_file, std::move(config), cache_path));
903904
}
904905

905906
} // namespace odr::internal

src/odr/internal/oldms_wvware/wvware_oldms_file.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ struct WvWareLegacyMicrosoftFile::ParserState {
1313

1414
wvParseStruct ps{};
1515
int encryption_flag{};
16+
17+
~ParserState() { wvOLEFree(&ps); }
1618
};
1719

1820
WvWareLegacyMicrosoftFile::WvWareLegacyMicrosoftFile(
@@ -44,10 +46,6 @@ WvWareLegacyMicrosoftFile::WvWareLegacyMicrosoftFile(
4446
open();
4547
}
4648

47-
WvWareLegacyMicrosoftFile::~WvWareLegacyMicrosoftFile() {
48-
wvOLEFree(&m_parser_state->ps);
49-
}
50-
5149
void WvWareLegacyMicrosoftFile::open() {
5250
wvInit();
5351

@@ -68,7 +66,6 @@ void WvWareLegacyMicrosoftFile::open() {
6866
}
6967

7068
if (ret != 0) {
71-
wvOLEFree(&m_parser_state->ps);
7269
throw std::runtime_error("wvInitParser failed");
7370
}
7471
}

src/odr/internal/oldms_wvware/wvware_oldms_file.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class WvWareLegacyMicrosoftFile final : public abstract::DocumentFile {
2121
public:
2222
explicit WvWareLegacyMicrosoftFile(std::shared_ptr<common::DiskFile> file);
2323
explicit WvWareLegacyMicrosoftFile(std::shared_ptr<common::MemoryFile> file);
24-
~WvWareLegacyMicrosoftFile() final;
2524

2625
[[nodiscard]] std::shared_ptr<abstract::File> file() const noexcept final;
2726

Submodule odr-public updated 34 files

test/src/html_output_test.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,23 @@ TEST_P(HtmlOutputTests, html_meta) {
8181
GTEST_SKIP();
8282
}
8383

84-
// TODO check wvware decryption
85-
if ((test_file.type == FileType::legacy_word_document) &&
86-
(engine == DecoderEngine::wvware)) {
87-
GTEST_SKIP();
88-
}
89-
9084
if (file.is_document_file()) {
9185
DocumentFile document_file = file.document_file();
9286

9387
EXPECT_EQ(test_file.password.has_value(),
9488
document_file.password_encrypted());
89+
90+
// TODO wvware decryption
91+
if (test_file.password.has_value() &&
92+
(test_file.type == FileType::legacy_word_document) &&
93+
(engine == DecoderEngine::wvware)) {
94+
GTEST_SKIP();
95+
}
96+
9597
if (test_file.password.has_value()) {
9698
EXPECT_TRUE(document_file.decrypt(test_file.password.value()));
9799
}
100+
98101
EXPECT_EQ(test_file.type, document_file.file_type());
99102
}
100103

0 commit comments

Comments
 (0)