ooxml_crypt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +58 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/ext/ooxml_crypt/extconf.rb +18 -0
- data/ext/ooxml_crypt/ooxml_crypt.c +27 -0
- data/ext/ooxml_crypt/ooxml_crypt.h +7 -0
- data/lib/ooxml_crypt/version.rb +5 -0
- data/lib/ooxml_crypt.rb +75 -0
- data/vendor/cybozulib/.github/workflows/main.yml +12 -0
- data/vendor/cybozulib/.gitignore +5 -0
- data/vendor/cybozulib/CMakeLists.txt +6 -0
- data/vendor/cybozulib/COPYRIGHT +27 -0
- data/vendor/cybozulib/Makefile +26 -0
- data/vendor/cybozulib/bin/libeay32.dll +0 -0
- data/vendor/cybozulib/bin/libmecab.dll +0 -0
- data/vendor/cybozulib/bin/ssleay32.dll +0 -0
- data/vendor/cybozulib/common.mk +116 -0
- data/vendor/cybozulib/common.props +25 -0
- data/vendor/cybozulib/cybozulib.sln +286 -0
- data/vendor/cybozulib/debug.props +14 -0
- data/vendor/cybozulib/include/cybozu/array.hpp +197 -0
- data/vendor/cybozulib/include/cybozu/atoi.hpp +238 -0
- data/vendor/cybozulib/include/cybozu/atomic.hpp +146 -0
- data/vendor/cybozulib/include/cybozu/base64.hpp +210 -0
- data/vendor/cybozulib/include/cybozu/benchmark.hpp +212 -0
- data/vendor/cybozulib/include/cybozu/bfd.hpp +105 -0
- data/vendor/cybozulib/include/cybozu/bit_operation.hpp +139 -0
- data/vendor/cybozulib/include/cybozu/bitvector.hpp +358 -0
- data/vendor/cybozulib/include/cybozu/condition_variable.hpp +113 -0
- data/vendor/cybozulib/include/cybozu/condition_variable_cs.hpp +74 -0
- data/vendor/cybozulib/include/cybozu/config.hpp +392 -0
- data/vendor/cybozulib/include/cybozu/critical_section.hpp +60 -0
- data/vendor/cybozulib/include/cybozu/crypto.hpp +321 -0
- data/vendor/cybozulib/include/cybozu/csucvector.hpp +624 -0
- data/vendor/cybozulib/include/cybozu/csv.hpp +294 -0
- data/vendor/cybozulib/include/cybozu/data_type.hpp +27 -0
- data/vendor/cybozulib/include/cybozu/endian.hpp +224 -0
- data/vendor/cybozulib/include/cybozu/env.hpp +63 -0
- data/vendor/cybozulib/include/cybozu/event.hpp +122 -0
- data/vendor/cybozulib/include/cybozu/exception.hpp +253 -0
- data/vendor/cybozulib/include/cybozu/file.hpp +626 -0
- data/vendor/cybozulib/include/cybozu/fmindex.hpp +291 -0
- data/vendor/cybozulib/include/cybozu/format.hpp +93 -0
- data/vendor/cybozulib/include/cybozu/frequency.hpp +264 -0
- data/vendor/cybozulib/include/cybozu/hash.hpp +67 -0
- data/vendor/cybozulib/include/cybozu/inttype.hpp +174 -0
- data/vendor/cybozulib/include/cybozu/itoa.hpp +336 -0
- data/vendor/cybozulib/include/cybozu/json.hpp +120 -0
- data/vendor/cybozulib/include/cybozu/line_stream.hpp +149 -0
- data/vendor/cybozulib/include/cybozu/link_libeay32.hpp +21 -0
- data/vendor/cybozulib/include/cybozu/link_mpir.hpp +18 -0
- data/vendor/cybozulib/include/cybozu/link_ssleay32.hpp +19 -0
- data/vendor/cybozulib/include/cybozu/log.hpp +237 -0
- data/vendor/cybozulib/include/cybozu/minixml.hpp +452 -0
- data/vendor/cybozulib/include/cybozu/mmap.hpp +143 -0
- data/vendor/cybozulib/include/cybozu/mutex.hpp +144 -0
- data/vendor/cybozulib/include/cybozu/nlp/mecab.hpp +96 -0
- data/vendor/cybozulib/include/cybozu/nlp/plsi.hpp +315 -0
- data/vendor/cybozulib/include/cybozu/nlp/random.hpp +74 -0
- data/vendor/cybozulib/include/cybozu/nlp/sparse.hpp +529 -0
- data/vendor/cybozulib/include/cybozu/nlp/svd.hpp +486 -0
- data/vendor/cybozulib/include/cybozu/nlp/tfidf.hpp +226 -0
- data/vendor/cybozulib/include/cybozu/nlp/top_score.hpp +75 -0
- data/vendor/cybozulib/include/cybozu/option.hpp +743 -0
- data/vendor/cybozulib/include/cybozu/parallel.hpp +88 -0
- data/vendor/cybozulib/include/cybozu/pcg.hpp +72 -0
- data/vendor/cybozulib/include/cybozu/process.hpp +324 -0
- data/vendor/cybozulib/include/cybozu/quit_signal_handler.hpp +66 -0
- data/vendor/cybozulib/include/cybozu/random_generator.hpp +144 -0
- data/vendor/cybozulib/include/cybozu/regex.hpp +463 -0
- data/vendor/cybozulib/include/cybozu/select8.hpp +279 -0
- data/vendor/cybozulib/include/cybozu/serializer.hpp +363 -0
- data/vendor/cybozulib/include/cybozu/sha1.hpp +209 -0
- data/vendor/cybozulib/include/cybozu/sha2.hpp +506 -0
- data/vendor/cybozulib/include/cybozu/siphash.hpp +105 -0
- data/vendor/cybozulib/include/cybozu/socket.hpp +785 -0
- data/vendor/cybozulib/include/cybozu/ssl.hpp +203 -0
- data/vendor/cybozulib/include/cybozu/stacktrace.hpp +291 -0
- data/vendor/cybozulib/include/cybozu/stream.hpp +269 -0
- data/vendor/cybozulib/include/cybozu/string.hpp +1746 -0
- data/vendor/cybozulib/include/cybozu/string_operation.hpp +365 -0
- data/vendor/cybozulib/include/cybozu/sucvector.hpp +378 -0
- data/vendor/cybozulib/include/cybozu/test.hpp +373 -0
- data/vendor/cybozulib/include/cybozu/thread.hpp +229 -0
- data/vendor/cybozulib/include/cybozu/time.hpp +281 -0
- data/vendor/cybozulib/include/cybozu/tls.hpp +115 -0
- data/vendor/cybozulib/include/cybozu/unordered_map.hpp +13 -0
- data/vendor/cybozulib/include/cybozu/unordered_set.hpp +13 -0
- data/vendor/cybozulib/include/cybozu/v128.hpp +376 -0
- data/vendor/cybozulib/include/cybozu/wavelet_matrix.hpp +345 -0
- data/vendor/cybozulib/include/cybozu/xorshift.hpp +189 -0
- data/vendor/cybozulib/include/cybozu/zlib.hpp +325 -0
- data/vendor/cybozulib/include/sais.hxx +364 -0
- data/vendor/cybozulib/misc/make_select8tbl.cpp +26 -0
- data/vendor/cybozulib/mk.bat +37 -0
- data/vendor/cybozulib/readme.md +29 -0
- data/vendor/cybozulib/release.props +12 -0
- data/vendor/cybozulib/sample/Makefile +30 -0
- data/vendor/cybozulib/sample/csucvector_smpl.cpp +42 -0
- data/vendor/cybozulib/sample/data/svd/org/test1.S +4 -0
- data/vendor/cybozulib/sample/data/svd/org/test1.U +4 -0
- data/vendor/cybozulib/sample/data/svd/org/test1.V +6 -0
- data/vendor/cybozulib/sample/data/svd/test1 +4 -0
- data/vendor/cybozulib/sample/data/svd/test2 +4 -0
- data/vendor/cybozulib/sample/desymbol.cpp +127 -0
- data/vendor/cybozulib/sample/exception_smpl.cpp +46 -0
- data/vendor/cybozulib/sample/fmindex_smpl.cpp +231 -0
- data/vendor/cybozulib/sample/log_smpl.cpp +19 -0
- data/vendor/cybozulib/sample/mecab_smpl.cpp +37 -0
- data/vendor/cybozulib/sample/option2_smpl.cpp +68 -0
- data/vendor/cybozulib/sample/option_smpl.cpp +42 -0
- data/vendor/cybozulib/sample/plsi_smpl.cpp +207 -0
- data/vendor/cybozulib/sample/proj/exception_smpl.vcproj +184 -0
- data/vendor/cybozulib/sample/proj/mecab_smpl.vcproj +184 -0
- data/vendor/cybozulib/sample/proj/ssl_smpl/ssl_smpl.vcxproj +85 -0
- data/vendor/cybozulib/sample/proj/ssl_smpl.vcproj +347 -0
- data/vendor/cybozulib/sample/proj/stacktrace_smpl/stacktrace_smpl.vcxproj +85 -0
- data/vendor/cybozulib/sample/proj/svd_smpl.vcproj +184 -0
- data/vendor/cybozulib/sample/quit_signal_handler.cpp +30 -0
- data/vendor/cybozulib/sample/serializer_smpl.cpp +196 -0
- data/vendor/cybozulib/sample/socket_smpl.cpp +82 -0
- data/vendor/cybozulib/sample/ssl_smpl.cpp +39 -0
- data/vendor/cybozulib/sample/stacktrace_smpl.cpp +52 -0
- data/vendor/cybozulib/sample/svd_bench_smpl.cpp +143 -0
- data/vendor/cybozulib/sample/svd_smpl.cpp +94 -0
- data/vendor/cybozulib/sample/wm_bench_smpl.cpp +182 -0
- data/vendor/cybozulib/sample/zlib_smpl.cpp +41 -0
- data/vendor/cybozulib/src/Makefile +8 -0
- data/vendor/cybozulib/src/base/Makefile +19 -0
- data/vendor/cybozulib/test/Makefile +12 -0
- data/vendor/cybozulib/test/base/Makefile +37 -0
- data/vendor/cybozulib/test/base/array_test.cpp +173 -0
- data/vendor/cybozulib/test/base/atoi_test.cpp +774 -0
- data/vendor/cybozulib/test/base/atomic_test.cpp +49 -0
- data/vendor/cybozulib/test/base/base64_test.cpp +113 -0
- data/vendor/cybozulib/test/base/bit_operation_test.cpp +134 -0
- data/vendor/cybozulib/test/base/bitvector_test.cpp +204 -0
- data/vendor/cybozulib/test/base/condition_variable_cs_test.cpp +92 -0
- data/vendor/cybozulib/test/base/condition_variable_test.cpp +88 -0
- data/vendor/cybozulib/test/base/config_test.cpp +236 -0
- data/vendor/cybozulib/test/base/crypto_test.cpp +122 -0
- data/vendor/cybozulib/test/base/csucvector_test.cpp +63 -0
- data/vendor/cybozulib/test/base/csv_test.cpp +182 -0
- data/vendor/cybozulib/test/base/data/a.xml +26 -0
- data/vendor/cybozulib/test/base/endian_test.cpp +56 -0
- data/vendor/cybozulib/test/base/env_test.cpp +22 -0
- data/vendor/cybozulib/test/base/event_test.cpp +41 -0
- data/vendor/cybozulib/test/base/file_test.cpp +233 -0
- data/vendor/cybozulib/test/base/fmindex_test.cpp +118 -0
- data/vendor/cybozulib/test/base/format_test.cpp +12 -0
- data/vendor/cybozulib/test/base/frequency_test.cpp +104 -0
- data/vendor/cybozulib/test/base/itoa_test.cpp +522 -0
- data/vendor/cybozulib/test/base/line_stream_test.cpp +208 -0
- data/vendor/cybozulib/test/base/mecab_test.cpp +41 -0
- data/vendor/cybozulib/test/base/minixml_test.cpp +103 -0
- data/vendor/cybozulib/test/base/mmap_test.cpp +15 -0
- data/vendor/cybozulib/test/base/option_test.cpp +487 -0
- data/vendor/cybozulib/test/base/parallel_test.cpp +48 -0
- data/vendor/cybozulib/test/base/proj/array_test/array_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/atoi_test/atoi_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/atomic_test/atomic_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/base64_test/base64_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/condition_variable_cs_test/condition_variable_cs_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/condition_variable_test/condition_variable_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/config_test/config_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/csv_test/csv_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/endian_test/endian_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/env_test/env_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/event_test/event_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/file_test/file_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/itoa_test/itoa_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/mecab_test/mecab_test.vcxproj +88 -0
- data/vendor/cybozulib/test/base/proj/minixml_test/minixml_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/mmap_test/mmap_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/serializer_test/serializer_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/sha1_test/sha1_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/stream_test/stream_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/string_operation_test/string_operation_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/string_test/string_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/thread_test/thread_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/time_test/time_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/tls_test/tls_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/proj/zlib_test/zlib_test.vcxproj +86 -0
- data/vendor/cybozulib/test/base/random_generator_test.cpp +28 -0
- data/vendor/cybozulib/test/base/regex_test.cpp +74 -0
- data/vendor/cybozulib/test/base/serializer_test.cpp +483 -0
- data/vendor/cybozulib/test/base/sha1_test.cpp +61 -0
- data/vendor/cybozulib/test/base/sha2_test.cpp +191 -0
- data/vendor/cybozulib/test/base/siphash_test.cpp +33 -0
- data/vendor/cybozulib/test/base/socket_test.cpp +76 -0
- data/vendor/cybozulib/test/base/stream_test.cpp +101 -0
- data/vendor/cybozulib/test/base/string_operation_test.cpp +340 -0
- data/vendor/cybozulib/test/base/string_test.cpp +1705 -0
- data/vendor/cybozulib/test/base/sucvector_test.cpp +312 -0
- data/vendor/cybozulib/test/base/thread_test.cpp +62 -0
- data/vendor/cybozulib/test/base/time_test.cpp +164 -0
- data/vendor/cybozulib/test/base/tls_test.cpp +50 -0
- data/vendor/cybozulib/test/base/wavelet_matrix_test.cpp +145 -0
- data/vendor/cybozulib/test/base/zlib_test.cpp +371 -0
- data/vendor/cybozulib/test/nlp/Makefile +27 -0
- data/vendor/cybozulib/test/nlp/proj/random_test.vcproj +184 -0
- data/vendor/cybozulib/test/nlp/proj/sparse_test.vcproj +184 -0
- data/vendor/cybozulib/test/nlp/proj/svd_test.vcproj +184 -0
- data/vendor/cybozulib/test/nlp/random_test.cpp +62 -0
- data/vendor/cybozulib/test/nlp/sparse_test.cpp +347 -0
- data/vendor/cybozulib/test/nlp/svd_test.cpp +234 -0
- data/vendor/cybozulib/test/nlp/top_score_test.cpp +40 -0
- data/vendor/cybozulib/tool/create_vcproj.py +186 -0
- data/vendor/cybozulib/tool/vcproj_tmpl.py +185 -0
- data/vendor/msoffice/COPYRIGHT +27 -0
- data/vendor/msoffice/Makefile +29 -0
- data/vendor/msoffice/bin/64/msoc.dll +0 -0
- data/vendor/msoffice/bin/64/msocsample.exe +0 -0
- data/vendor/msoffice/bin/64/msoffice-crypt.exe +0 -0
- data/vendor/msoffice/bin/msoc.dll +0 -0
- data/vendor/msoffice/bin/msocsample.exe +0 -0
- data/vendor/msoffice/bin/msoffice-crypt.exe +0 -0
- data/vendor/msoffice/common.mk +71 -0
- data/vendor/msoffice/common.props +26 -0
- data/vendor/msoffice/debug.props +14 -0
- data/vendor/msoffice/include/attack.hpp +211 -0
- data/vendor/msoffice/include/cfb.hpp +777 -0
- data/vendor/msoffice/include/crypto_util.hpp +450 -0
- data/vendor/msoffice/include/custom_sha1.hpp +342 -0
- data/vendor/msoffice/include/decode.hpp +240 -0
- data/vendor/msoffice/include/encode.hpp +221 -0
- data/vendor/msoffice/include/make_dataspace.hpp +316 -0
- data/vendor/msoffice/include/msoc.h +129 -0
- data/vendor/msoffice/include/resource.hpp +7 -0
- data/vendor/msoffice/include/standard_encryption.hpp +145 -0
- data/vendor/msoffice/include/uint32vec.hpp +179 -0
- data/vendor/msoffice/include/util.hpp +212 -0
- data/vendor/msoffice/lib/.emptydir +0 -0
- data/vendor/msoffice/misc/decrypt-xls.vbs +46 -0
- data/vendor/msoffice/mk.bat +1 -0
- data/vendor/msoffice/mkdll.bat +3 -0
- data/vendor/msoffice/msoc.def +13 -0
- data/vendor/msoffice/msocsample.py +178 -0
- data/vendor/msoffice/msoffice12.sln +31 -0
- data/vendor/msoffice/readme.md +110 -0
- data/vendor/msoffice/release.props +28 -0
- data/vendor/msoffice/src/Makefile +19 -0
- data/vendor/msoffice/src/attack.cpp +124 -0
- data/vendor/msoffice/src/cfb_test.cpp +77 -0
- data/vendor/msoffice/src/minisample.c +54 -0
- data/vendor/msoffice/src/msocdll.cpp +276 -0
- data/vendor/msoffice/src/msocsample.c +136 -0
- data/vendor/msoffice/src/msoffice-crypt.cpp +219 -0
- data/vendor/msoffice/src/proj/attack/attack.vcxproj +88 -0
- data/vendor/msoffice/src/proj/main/msoffice-crypt.vcxproj +88 -0
- data/vendor/msoffice/src/sha1.cpp +234 -0
- data/vendor/msoffice/test/Makefile +20 -0
- data/vendor/msoffice/test/cfb_test.cpp +74 -0
- data/vendor/msoffice/test/hash_test.cpp +59 -0
- data/vendor/msoffice/test/proj/cfb/cfb_test.vcxproj +90 -0
- data/vendor/msoffice/test/proj/hash/hash_test.vcxproj +90 -0
- data/vendor/msoffice/test/sampl.bat +8 -0
- data/vendor/msoffice/test_all.py +46 -0
- data/vendor/update +4 -0
- metadata +351 -0
|
@@ -0,0 +1,777 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
/**
|
|
3
|
+
@file
|
|
4
|
+
@brief compound file binary format
|
|
5
|
+
Copyright (C) 2012 Cybozu Labs, Inc., all rights reserved.
|
|
6
|
+
*/
|
|
7
|
+
#include <assert.h>
|
|
8
|
+
#include <vector>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <algorithm>
|
|
11
|
+
#include <map>
|
|
12
|
+
#include <cybozu/endian.hpp>
|
|
13
|
+
#include <cybozu/time.hpp>
|
|
14
|
+
#include <cybozu/string.hpp>
|
|
15
|
+
#include "util.hpp"
|
|
16
|
+
|
|
17
|
+
namespace ms { namespace cfb {
|
|
18
|
+
|
|
19
|
+
typedef std::vector<uint32_t> UintVec;
|
|
20
|
+
typedef std::map<uint32_t, UintVec> ChainMap;
|
|
21
|
+
|
|
22
|
+
const uint32_t MAXREGSECT = 0xfffffffa;
|
|
23
|
+
const uint32_t DIFSECT = 0xfffffffc;
|
|
24
|
+
const uint32_t FATSECT = 0xfffffffd;
|
|
25
|
+
const uint32_t ENDOFCHAIN = 0xfffffffe;
|
|
26
|
+
const uint32_t FREESECT = 0xffffffff;
|
|
27
|
+
const uint32_t NOSTREAM = 0xffffffff;
|
|
28
|
+
|
|
29
|
+
enum ObjectType {
|
|
30
|
+
Unallocated = 0,
|
|
31
|
+
StorageObject = 1,
|
|
32
|
+
StreamObject = 2,
|
|
33
|
+
RootStorageObject = 5
|
|
34
|
+
};
|
|
35
|
+
enum ColorFlag {
|
|
36
|
+
Red = 0,
|
|
37
|
+
Black = 1
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
inline std::string toStr(uint32_t v)
|
|
41
|
+
{
|
|
42
|
+
switch (v) {
|
|
43
|
+
case DIFSECT:
|
|
44
|
+
return "DIF";
|
|
45
|
+
case FATSECT:
|
|
46
|
+
return "FAT";
|
|
47
|
+
case ENDOFCHAIN:
|
|
48
|
+
return "END";
|
|
49
|
+
case FREESECT:
|
|
50
|
+
return "FREE";
|
|
51
|
+
default:
|
|
52
|
+
return cybozu::itoa(v);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
inline std::string toStr(ObjectType objectType)
|
|
57
|
+
{
|
|
58
|
+
switch (objectType) {
|
|
59
|
+
case Unallocated:
|
|
60
|
+
return "Unallocated";
|
|
61
|
+
case StorageObject:
|
|
62
|
+
return "StorageObject";
|
|
63
|
+
case StreamObject:
|
|
64
|
+
return "StreamObject";
|
|
65
|
+
case RootStorageObject:
|
|
66
|
+
return "RootStorageObject";
|
|
67
|
+
default:
|
|
68
|
+
throw cybozu::Exception("invalid ObjectType");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
inline std::string toStr(ColorFlag colorFlag)
|
|
73
|
+
{
|
|
74
|
+
switch (colorFlag) {
|
|
75
|
+
case Red:
|
|
76
|
+
return "Red";
|
|
77
|
+
case Black:
|
|
78
|
+
return "Black";
|
|
79
|
+
default:
|
|
80
|
+
throw cybozu::Exception("invalid ColorFlag");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
template<class T>
|
|
85
|
+
inline void putCompact(const T& vec)
|
|
86
|
+
{
|
|
87
|
+
uint32_t prev = 0xfffffff0;
|
|
88
|
+
bool isFirst = true;
|
|
89
|
+
for (size_t j = 0, n = vec.size(); j < n; j++) {
|
|
90
|
+
uint32_t v = vec[j];
|
|
91
|
+
if (v == prev + 1 && j != n - 1) {
|
|
92
|
+
if (isFirst) {
|
|
93
|
+
printf(" ..");
|
|
94
|
+
isFirst = false;
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
if (!isFirst && j > 1) {
|
|
98
|
+
printf(" %s", toStr(vec[j - 1]).c_str());
|
|
99
|
+
}
|
|
100
|
+
printf(" %s", toStr(v).c_str());
|
|
101
|
+
isFirst = true;
|
|
102
|
+
}
|
|
103
|
+
prev = v;
|
|
104
|
+
}
|
|
105
|
+
putchar('\n');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
struct Header {
|
|
109
|
+
enum { firstNumDIFAT = 109 };
|
|
110
|
+
uint32_t minorVersion;
|
|
111
|
+
uint32_t majorVersion;
|
|
112
|
+
uint32_t sectorShift;
|
|
113
|
+
uint32_t numDirectorySectors;
|
|
114
|
+
uint32_t numFatSectors;
|
|
115
|
+
uint32_t firstDirectorySectorLocation;
|
|
116
|
+
uint32_t transactionSignatureNumber;
|
|
117
|
+
uint32_t firstMiniFatSectorLocation;
|
|
118
|
+
uint32_t numMiniFatSectors;
|
|
119
|
+
uint32_t firstDifatSectorLocation;
|
|
120
|
+
uint32_t numDifatSectors;
|
|
121
|
+
UintVec difat;
|
|
122
|
+
uint32_t sectorSize;
|
|
123
|
+
explicit Header(const char *data = 0, uint32_t dataSize = 0)
|
|
124
|
+
: minorVersion(0x003e)
|
|
125
|
+
, majorVersion(3)
|
|
126
|
+
, sectorShift(9)
|
|
127
|
+
, numDirectorySectors(0)
|
|
128
|
+
, numFatSectors(0)
|
|
129
|
+
, firstDirectorySectorLocation(ENDOFCHAIN)
|
|
130
|
+
, transactionSignatureNumber(0)
|
|
131
|
+
, firstMiniFatSectorLocation(ENDOFCHAIN)
|
|
132
|
+
, numMiniFatSectors(0)
|
|
133
|
+
, firstDifatSectorLocation(ENDOFCHAIN)
|
|
134
|
+
, numDifatSectors(0)
|
|
135
|
+
, sectorSize(1u << sectorShift)
|
|
136
|
+
{
|
|
137
|
+
analyze(data, dataSize);
|
|
138
|
+
}
|
|
139
|
+
void addDifat(const char *data, size_t num)
|
|
140
|
+
{
|
|
141
|
+
for (uint32_t i = 0; i < num; i++) {
|
|
142
|
+
uint32_t v = cybozu::Get32bitAsLE(data + i * 4);
|
|
143
|
+
if (v == FREESECT) continue;
|
|
144
|
+
difat.push_back(v);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
void analyze(const char *data, uint32_t dataSize)
|
|
148
|
+
{
|
|
149
|
+
if (data == 0) return;
|
|
150
|
+
if (dataSize < 512) {
|
|
151
|
+
throw cybozu::Exception("ms:cfb:Header:short dataSize") << dataSize;
|
|
152
|
+
}
|
|
153
|
+
if (memcmp(data, "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1", 8) != 0) {
|
|
154
|
+
throw cybozu::Exception("ms:cfb:Header:invalid header signature");
|
|
155
|
+
}
|
|
156
|
+
if (!isZero(data + 8, 16)) {
|
|
157
|
+
throw cybozu::Exception("ms:cfb:Header:invalid header CLSID");
|
|
158
|
+
}
|
|
159
|
+
uint32_t byteOrder, miniSectorShift, miniStreamCutoffSize;
|
|
160
|
+
struct {
|
|
161
|
+
int size;
|
|
162
|
+
size_t pos;
|
|
163
|
+
uint32_t *p;
|
|
164
|
+
} tbl[] = {
|
|
165
|
+
{ 16, 0x18, &minorVersion },
|
|
166
|
+
{ 16, 0x1a, &majorVersion },
|
|
167
|
+
{ 16, 0x1c, &byteOrder },
|
|
168
|
+
{ 16, 0x1e, §orShift },
|
|
169
|
+
{ 16, 0x20, &miniSectorShift },
|
|
170
|
+
{ 32, 0x28, &numDirectorySectors },
|
|
171
|
+
{ 32, 0x2c, &numFatSectors },
|
|
172
|
+
{ 32, 0x30, &firstDirectorySectorLocation },
|
|
173
|
+
{ 32, 0x34, &transactionSignatureNumber },
|
|
174
|
+
{ 32, 0x38, &miniStreamCutoffSize },
|
|
175
|
+
{ 32, 0x3c, &firstMiniFatSectorLocation },
|
|
176
|
+
{ 32, 0x40, &numMiniFatSectors },
|
|
177
|
+
{ 32, 0x44, &firstDifatSectorLocation },
|
|
178
|
+
{ 32, 0x48, &numDifatSectors },
|
|
179
|
+
};
|
|
180
|
+
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
181
|
+
const char *p = data + tbl[i].pos;
|
|
182
|
+
*tbl[i].p = (tbl[i].size == 16) ? cybozu::Get16bitAsLE(p) : cybozu::Get32bitAsLE(p);
|
|
183
|
+
}
|
|
184
|
+
sectorSize = 1u << sectorShift;
|
|
185
|
+
|
|
186
|
+
MS_ASSERT(minorVersion == 0x3eu || minorVersion == 0x3bu);
|
|
187
|
+
MS_ASSERT(majorVersion == 3 || majorVersion == 4);
|
|
188
|
+
MS_ASSERT_EQUAL(byteOrder, 0xfffeu);
|
|
189
|
+
MS_ASSERT((majorVersion == 3 && sectorShift == 9) || (majorVersion == 4 && sectorShift == 0xc));
|
|
190
|
+
MS_ASSERT_EQUAL(miniSectorShift, 6u);
|
|
191
|
+
if (!isZero(data + 0x22, 6)) {
|
|
192
|
+
throw cybozu::Exception("ms:cfb:Header:invalid reserved");
|
|
193
|
+
}
|
|
194
|
+
MS_ASSERT(majorVersion == 4 || numDirectorySectors == 0);
|
|
195
|
+
MS_ASSERT_EQUAL(miniStreamCutoffSize, 0x1000u);
|
|
196
|
+
addDifat(data + 0x4c, firstNumDIFAT);
|
|
197
|
+
addExtraDifat(data, dataSize);
|
|
198
|
+
put();
|
|
199
|
+
}
|
|
200
|
+
// input firstDifatSectorLocation, numDifatSectors
|
|
201
|
+
void addExtraDifat(const char *data, uint32_t dataSize)
|
|
202
|
+
{
|
|
203
|
+
uint32_t pos = firstDifatSectorLocation;
|
|
204
|
+
if (pos == ENDOFCHAIN) return;
|
|
205
|
+
for (;;) {
|
|
206
|
+
const char *p = data + 512 + pos * sectorSize;
|
|
207
|
+
if (p >= data + dataSize) throw cybozu::Exception("ms:cfb:Header:addExtraDifat:large pos") << pos << dataSize;
|
|
208
|
+
for (uint32_t i = 0; i < sectorSize / 4 - 1; i++) {
|
|
209
|
+
uint32_t v = cybozu::Get32bitAsLE(p + i * 4);
|
|
210
|
+
if (v == FREESECT) continue;
|
|
211
|
+
difat.push_back(v);
|
|
212
|
+
}
|
|
213
|
+
uint32_t v = cybozu::Get32bitAsLE(p + sectorSize - 4);
|
|
214
|
+
if (v == ENDOFCHAIN) {
|
|
215
|
+
if (difat.size() != numFatSectors) {
|
|
216
|
+
put();
|
|
217
|
+
throw cybozu::Exception("ms:cfb:Header:addExtraDifat:bad numFatSectors") << difat.size() << numFatSectors;
|
|
218
|
+
}
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
pos = v;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/*
|
|
225
|
+
data has 512 bytes
|
|
226
|
+
*/
|
|
227
|
+
void write(char *data) const
|
|
228
|
+
{
|
|
229
|
+
memcpy(data, "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1", 8); // magic number
|
|
230
|
+
memset(data + 8, 0, 16); // CLSID
|
|
231
|
+
memset(data + 0x22, 0, 6); // reserved
|
|
232
|
+
const uint32_t byteOrder = 0xfffe;
|
|
233
|
+
const uint32_t miniSectorShift = 6;
|
|
234
|
+
const uint32_t miniStreamCutoffSize = 0x1000;
|
|
235
|
+
struct {
|
|
236
|
+
int size;
|
|
237
|
+
size_t pos;
|
|
238
|
+
uint32_t v;
|
|
239
|
+
} tbl[] = {
|
|
240
|
+
{ 16, 0x18, minorVersion },
|
|
241
|
+
{ 16, 0x1a, majorVersion },
|
|
242
|
+
{ 16, 0x1c, byteOrder },
|
|
243
|
+
{ 16, 0x1e, sectorShift },
|
|
244
|
+
{ 16, 0x20, miniSectorShift },
|
|
245
|
+
{ 32, 0x28, numDirectorySectors },
|
|
246
|
+
{ 32, 0x2c, numFatSectors },
|
|
247
|
+
{ 32, 0x30, firstDirectorySectorLocation },
|
|
248
|
+
{ 32, 0x34, transactionSignatureNumber },
|
|
249
|
+
{ 32, 0x38, miniStreamCutoffSize },
|
|
250
|
+
{ 32, 0x3c, firstMiniFatSectorLocation },
|
|
251
|
+
{ 32, 0x40, numMiniFatSectors },
|
|
252
|
+
{ 32, 0x44, firstDifatSectorLocation },
|
|
253
|
+
{ 32, 0x48, numDifatSectors },
|
|
254
|
+
};
|
|
255
|
+
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
256
|
+
char *p = data + tbl[i].pos;
|
|
257
|
+
if (tbl[i].size == 16) {
|
|
258
|
+
cybozu::Set16bitAsLE(p, static_cast<uint16_t>(tbl[i].v));
|
|
259
|
+
} else {
|
|
260
|
+
cybozu::Set32bitAsLE(p, tbl[i].v);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const uint32_t difatSize = static_cast<uint32_t>(difat.size());
|
|
264
|
+
for (uint32_t i = 0; i < std::min<uint32_t>(difatSize, firstNumDIFAT); i++) {
|
|
265
|
+
cybozu::Set32bitAsLE(data + 0x4c + i * 4, difat[i]);
|
|
266
|
+
}
|
|
267
|
+
for (uint32_t i = difatSize; i < firstNumDIFAT; i++) {
|
|
268
|
+
cybozu::Set32bitAsLE(data + 0x4c + i * 4, NOSTREAM);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
void put() const
|
|
272
|
+
{
|
|
273
|
+
if (!isDebug()) return;
|
|
274
|
+
printf("version : major = %u, minor = 0x%04x\n", majorVersion, minorVersion);
|
|
275
|
+
printf("sectorShift = %u\n", sectorShift);
|
|
276
|
+
printf("numDirectorySectors = %u\n", numDirectorySectors);
|
|
277
|
+
printf("numFatSectors = %u\n", numFatSectors);
|
|
278
|
+
printf("firstDirectorySectorLocation = %u\n", firstDirectorySectorLocation);
|
|
279
|
+
printf("transactionSignatureNumber = %u\n", transactionSignatureNumber);
|
|
280
|
+
printf("firstMiniFatSectorLocation = %s\n", toStr(firstMiniFatSectorLocation).c_str());
|
|
281
|
+
printf("numMiniFatSectors = %u\n", numMiniFatSectors);
|
|
282
|
+
printf("firstDifatSectorLocation = %s\n", toStr(firstDifatSectorLocation).c_str());
|
|
283
|
+
printf("numDifatSectors = %u\n", numDifatSectors);
|
|
284
|
+
printf("difat size=%d\n", (int)difat.size());
|
|
285
|
+
putCompact(difat);
|
|
286
|
+
}
|
|
287
|
+
private:
|
|
288
|
+
bool isZero(const char *data, uint32_t dataSize) const
|
|
289
|
+
{
|
|
290
|
+
for (uint32_t i = 0; i < dataSize; i++) {
|
|
291
|
+
if (data[i]) return false;
|
|
292
|
+
}
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
struct FatSectors {
|
|
298
|
+
ChainMap chains;
|
|
299
|
+
void makeFatIdx1(UintVec& fatIdx, const char *data, uint32_t sectorSize) const
|
|
300
|
+
{
|
|
301
|
+
for (size_t i = 0; i < sectorSize; i += 4) {
|
|
302
|
+
uint32_t v = cybozu::Get32bitAsLE(data + i);
|
|
303
|
+
fatIdx.push_back(v);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
void makeFatIdx(UintVec& fatIdx, const char *data, uint32_t sectorSize, const UintVec& difat) const
|
|
307
|
+
{
|
|
308
|
+
for (size_t i = 0; i < difat.size(); i++) {
|
|
309
|
+
uint32_t fatId = difat[i];
|
|
310
|
+
if (fatId == NOSTREAM) continue;
|
|
311
|
+
// QQQ:check fatId size
|
|
312
|
+
makeFatIdx1(fatIdx, data + fatId * sectorSize, sectorSize);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/*
|
|
316
|
+
@note destroy fatIdx
|
|
317
|
+
*/
|
|
318
|
+
void makeChains(ChainMap& chains, UintVec& fatIdx) const
|
|
319
|
+
{
|
|
320
|
+
for (uint32_t i = 0, n = (uint32_t)fatIdx.size(); i < n; i++) {
|
|
321
|
+
uint32_t v = fatIdx[i];
|
|
322
|
+
if (v != FREESECT && v != FATSECT && v != DIFSECT) {
|
|
323
|
+
UintVec& c = chains[i];
|
|
324
|
+
c.push_back(i);
|
|
325
|
+
while (v != ENDOFCHAIN) {
|
|
326
|
+
if (v == NOSTREAM) break;
|
|
327
|
+
if (v >= fatIdx.size()) {
|
|
328
|
+
throw cybozu::Exception("ms:cfb:FatSectors:bad idx") << v;
|
|
329
|
+
}
|
|
330
|
+
c.push_back(v);
|
|
331
|
+
uint32_t& next = fatIdx[v];
|
|
332
|
+
v = next;
|
|
333
|
+
next = FREESECT;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
void analyze(const char *data, uint32_t sectorSize, const UintVec& difat)
|
|
339
|
+
{
|
|
340
|
+
UintVec fatIdx;
|
|
341
|
+
makeFatIdx(fatIdx, data, sectorSize, difat);
|
|
342
|
+
makeChains(chains, fatIdx);
|
|
343
|
+
}
|
|
344
|
+
void analyzeMini(const char *data, uint32_t sectorSize, uint32_t firstMiniFatSectorLocation)
|
|
345
|
+
{
|
|
346
|
+
UintVec fatIdx;
|
|
347
|
+
makeFatIdx1(fatIdx, data + firstMiniFatSectorLocation * sectorSize, sectorSize);
|
|
348
|
+
makeChains(chains, fatIdx);
|
|
349
|
+
}
|
|
350
|
+
void put() const
|
|
351
|
+
{
|
|
352
|
+
for (ChainMap::const_iterator i = chains.begin(), ie = chains.end(); i != ie; ++i) {
|
|
353
|
+
putCompact(i->second);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const UintVec* query(uint32_t id) const
|
|
357
|
+
{
|
|
358
|
+
ChainMap::const_iterator i = chains.find(id);
|
|
359
|
+
if (i == chains.end()) return 0;
|
|
360
|
+
return &(i->second);
|
|
361
|
+
}
|
|
362
|
+
const UintVec& get(uint32_t id) const
|
|
363
|
+
{
|
|
364
|
+
const UintVec *p = query(id);
|
|
365
|
+
if (p == 0) {
|
|
366
|
+
throw cybozu::Exception("ms:cfb:FatSectors:get") << id;
|
|
367
|
+
}
|
|
368
|
+
return *p;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
struct DirectoryEntry {
|
|
373
|
+
struct FileTime {
|
|
374
|
+
uint32_t dwLowDateTime;
|
|
375
|
+
uint32_t dwHighDateTime;
|
|
376
|
+
FileTime()
|
|
377
|
+
: dwLowDateTime(0)
|
|
378
|
+
, dwHighDateTime(0)
|
|
379
|
+
{
|
|
380
|
+
}
|
|
381
|
+
std::string toString() const
|
|
382
|
+
{
|
|
383
|
+
if (dwLowDateTime == 0 && dwHighDateTime == 0) return "not set";
|
|
384
|
+
cybozu::Time time;
|
|
385
|
+
time.setByFILETIME(dwLowDateTime, dwHighDateTime);
|
|
386
|
+
return time.toString();
|
|
387
|
+
}
|
|
388
|
+
void setCurrentTime()
|
|
389
|
+
{
|
|
390
|
+
cybozu::Time time;
|
|
391
|
+
|
|
392
|
+
}
|
|
393
|
+
void get(const char *data)
|
|
394
|
+
{
|
|
395
|
+
dwLowDateTime = cybozu::Get32bitAsLE(data);
|
|
396
|
+
dwHighDateTime = cybozu::Get32bitAsLE(data + 4);
|
|
397
|
+
}
|
|
398
|
+
void set(char *data) const
|
|
399
|
+
{
|
|
400
|
+
cybozu::Set32bitAsLE(data, dwLowDateTime);
|
|
401
|
+
cybozu::Set32bitAsLE(data + 4, dwHighDateTime);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
cybozu::String16 directoryEntryName;
|
|
405
|
+
uint16_t directoryEntryNameLength;
|
|
406
|
+
ObjectType objectType;
|
|
407
|
+
ColorFlag colorFlag;
|
|
408
|
+
uint32_t leftSiblingId;
|
|
409
|
+
uint32_t rightSiblingId;
|
|
410
|
+
uint32_t childId;
|
|
411
|
+
std::string clsid;
|
|
412
|
+
uint32_t stateBits;
|
|
413
|
+
FileTime creationTime;
|
|
414
|
+
FileTime modifiedTime;
|
|
415
|
+
uint32_t startingSectorLocation;
|
|
416
|
+
uint64_t streamSize;
|
|
417
|
+
std::string content;
|
|
418
|
+
|
|
419
|
+
// directoryEntryNameLength = directoryEntryName.size() * 2 + 2
|
|
420
|
+
DirectoryEntry(const char *data = 0)
|
|
421
|
+
: directoryEntryName()
|
|
422
|
+
, directoryEntryNameLength(0)
|
|
423
|
+
, objectType(Unallocated)
|
|
424
|
+
, colorFlag(Red)
|
|
425
|
+
, leftSiblingId(0)
|
|
426
|
+
, rightSiblingId(0)
|
|
427
|
+
, childId(0)
|
|
428
|
+
, clsid()
|
|
429
|
+
, stateBits(0)
|
|
430
|
+
, creationTime()
|
|
431
|
+
, modifiedTime()
|
|
432
|
+
, startingSectorLocation(0)
|
|
433
|
+
, streamSize(0)
|
|
434
|
+
{
|
|
435
|
+
if (data) analyze(data);
|
|
436
|
+
}
|
|
437
|
+
void analyze(const char *data)
|
|
438
|
+
{
|
|
439
|
+
directoryEntryNameLength = getDirectoryEntryNameLength(data + 0x40);
|
|
440
|
+
|
|
441
|
+
directoryEntryName = getDirectoryEntryName(data, directoryEntryNameLength);
|
|
442
|
+
objectType = getObjectType(data + 0x42);
|
|
443
|
+
colorFlag = getColorFlag(data + 0x43);
|
|
444
|
+
leftSiblingId = getId(data + 0x44);
|
|
445
|
+
rightSiblingId = getId(data + 0x48);
|
|
446
|
+
childId = getId(data + 0x4c);
|
|
447
|
+
clsid.assign(reinterpret_cast<const char*>(data + 0x50), 16);
|
|
448
|
+
stateBits = cybozu::Get32bitAsLE(data + 0x60);
|
|
449
|
+
creationTime.get(data + 0x64);
|
|
450
|
+
modifiedTime.get(data + 0x6c);
|
|
451
|
+
startingSectorLocation = cybozu::Get32bitAsLE(data + 0x74);
|
|
452
|
+
streamSize = cybozu::Get64bitAsLE(data + 0x78);
|
|
453
|
+
if (streamSize >= uint64_t(0x100000000ULL)) {
|
|
454
|
+
printf("warning too large size=%lld\n", (long long)streamSize);
|
|
455
|
+
// clear upper 32bit if version 3
|
|
456
|
+
streamSize &= 0xffffffff;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
void set(
|
|
460
|
+
const cybozu::String16& name,
|
|
461
|
+
ObjectType objectType,
|
|
462
|
+
ColorFlag colorFlag,
|
|
463
|
+
uint32_t leftSiblingId,
|
|
464
|
+
uint32_t rightSiblingId,
|
|
465
|
+
uint32_t childId,
|
|
466
|
+
const std::string& clsid,
|
|
467
|
+
uint32_t stateBits,
|
|
468
|
+
const FileTime& creationTime,
|
|
469
|
+
const FileTime& modifiedTime,
|
|
470
|
+
uint32_t startingSectorLocation,
|
|
471
|
+
const std::string& content)
|
|
472
|
+
{
|
|
473
|
+
setDirectoryEntryName(name);
|
|
474
|
+
this->objectType = objectType;
|
|
475
|
+
this->colorFlag = colorFlag;
|
|
476
|
+
setId(this->leftSiblingId, leftSiblingId, "leftSiblingId");
|
|
477
|
+
setId(this->rightSiblingId, rightSiblingId, "rightSiblingId");
|
|
478
|
+
setId(this->childId, childId, "childId");
|
|
479
|
+
if (!clsid.empty() && clsid.size() != 16) throw cybozu::Exception("ms:cfb:DirectoryEntry:bad clsid") << hex(clsid);
|
|
480
|
+
this->stateBits = stateBits;
|
|
481
|
+
this->creationTime = creationTime;
|
|
482
|
+
this->modifiedTime = modifiedTime;
|
|
483
|
+
this->startingSectorLocation = startingSectorLocation;
|
|
484
|
+
this->streamSize = content.size();
|
|
485
|
+
this->content = content;
|
|
486
|
+
}
|
|
487
|
+
/*
|
|
488
|
+
write directory entry to out(128byte)
|
|
489
|
+
*/
|
|
490
|
+
void write(char *data) const
|
|
491
|
+
{
|
|
492
|
+
memset(data, 0, 64);
|
|
493
|
+
memcpy(data, directoryEntryName.c_str(), (directoryEntryName.size() + 1) * 2);
|
|
494
|
+
{
|
|
495
|
+
uint16_t len = directoryEntryNameLength > 2 ? directoryEntryNameLength : 0;
|
|
496
|
+
cybozu::Set16bitAsLE(data + 0x40, len);
|
|
497
|
+
}
|
|
498
|
+
data[0x42] = static_cast<char>(objectType);
|
|
499
|
+
data[0x43] = static_cast<char>(colorFlag);
|
|
500
|
+
cybozu::Set32bitAsLE(data + 0x44, leftSiblingId);
|
|
501
|
+
cybozu::Set32bitAsLE(data + 0x48, rightSiblingId);
|
|
502
|
+
cybozu::Set32bitAsLE(data + 0x4c, childId);
|
|
503
|
+
if (clsid.empty()) {
|
|
504
|
+
memset(data + 0x50, 0, 16);
|
|
505
|
+
} else {
|
|
506
|
+
MS_ASSERT(clsid.size() == 16);
|
|
507
|
+
memcpy(data + 0x50, clsid.c_str(), 16);
|
|
508
|
+
}
|
|
509
|
+
cybozu::Set32bitAsLE(data + 0x60, stateBits);
|
|
510
|
+
creationTime.set(data + 0x64);
|
|
511
|
+
modifiedTime.set(data + 0x6c);
|
|
512
|
+
cybozu::Set32bitAsLE(data + 0x74, startingSectorLocation);
|
|
513
|
+
cybozu::Set64bitAsLE(data + 0x78, streamSize);
|
|
514
|
+
}
|
|
515
|
+
void writeContent(char *data, uint32_t sectorSize) const
|
|
516
|
+
{
|
|
517
|
+
const size_t size = content.size();
|
|
518
|
+
if (size == 0) return;
|
|
519
|
+
memcpy(data, &content[0], size);
|
|
520
|
+
const size_t r = size % sectorSize;
|
|
521
|
+
if (r > 0) {
|
|
522
|
+
memset(data + size, 0, sectorSize - r);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
void put() const
|
|
526
|
+
{
|
|
527
|
+
if (!isDebug()) return;
|
|
528
|
+
printf("directoryEntryName = ");
|
|
529
|
+
#ifdef _WIN32
|
|
530
|
+
if (directoryEntryName.empty()) {
|
|
531
|
+
printf("<none>");
|
|
532
|
+
} else {
|
|
533
|
+
printf("%S", &directoryEntryName[0]);
|
|
534
|
+
}
|
|
535
|
+
#else
|
|
536
|
+
printf("%s", toHex(reinterpret_cast<const char*>(&directoryEntryName[0]), directoryEntryNameLength).c_str());
|
|
537
|
+
#endif
|
|
538
|
+
printf("(%u)\n", directoryEntryNameLength);
|
|
539
|
+
printf("objectType = %d(%s)\n", objectType, toStr(objectType).c_str());
|
|
540
|
+
printf("colorFlag = %d(%s)\n", colorFlag, toStr(colorFlag).c_str());
|
|
541
|
+
printf("leftSiblingId = %s, ", toStr(leftSiblingId).c_str());
|
|
542
|
+
printf("rightSiblingId = %s\n", toStr(rightSiblingId).c_str());
|
|
543
|
+
printf("childId = %s\n", toStr(childId).c_str());
|
|
544
|
+
printf("clsid = %s, ", toHex(clsid.c_str(), clsid.size()).c_str());
|
|
545
|
+
printf("stateBits = 0x%08x\n", stateBits);
|
|
546
|
+
printf("creation/modified Time = %s / %s\n", creationTime.toString().c_str(), modifiedTime.toString().c_str());
|
|
547
|
+
printf("startingSectorLocation = %s\n", toStr(startingSectorLocation).c_str());
|
|
548
|
+
printf("streamSize = %lld\n", (long long)streamSize);
|
|
549
|
+
if (content.empty()) {
|
|
550
|
+
printf("data=<empty>\n");
|
|
551
|
+
} else {
|
|
552
|
+
if (isDebug(2)) {
|
|
553
|
+
std::string fileName = cybozu::ToUtf8(directoryEntryName) + ".dump";
|
|
554
|
+
for (size_t i = 0; i < fileName.size(); i++) {
|
|
555
|
+
char c = fileName[i];
|
|
556
|
+
if (!isprint(c)) fileName[i] = '_';
|
|
557
|
+
}
|
|
558
|
+
saveFile(fileName, content);
|
|
559
|
+
}
|
|
560
|
+
if (streamSize <= 256) {
|
|
561
|
+
printf("data=\n");
|
|
562
|
+
dump16(content, content.size());
|
|
563
|
+
} else {
|
|
564
|
+
printf("data=[");
|
|
565
|
+
for (size_t i = 0; i < 5; i++) {
|
|
566
|
+
printf("%02x:", (uint8_t)content[i]);
|
|
567
|
+
}
|
|
568
|
+
printf(" ... ");
|
|
569
|
+
for (size_t i = content.size() - 5; i < content.size(); i++) {
|
|
570
|
+
printf("%02x:", (uint8_t)content[i]);
|
|
571
|
+
}
|
|
572
|
+
printf("]\n");
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
private:
|
|
577
|
+
uint16_t getDirectoryEntryNameLength(const char *data) const
|
|
578
|
+
{
|
|
579
|
+
uint16_t len = cybozu::Get16bitAsLE(data);
|
|
580
|
+
MS_ASSERT(len <= 64);
|
|
581
|
+
MS_ASSERT((len & 1) == 0);
|
|
582
|
+
return len;
|
|
583
|
+
}
|
|
584
|
+
bool isValidEntryNameChar(uint16_t c) const
|
|
585
|
+
{
|
|
586
|
+
return c != 0 && c != '/' && c != ':' && c != '!';
|
|
587
|
+
}
|
|
588
|
+
bool isValidId(uint32_t id) const
|
|
589
|
+
{
|
|
590
|
+
return id <= MAXREGSECT || id == NOSTREAM;
|
|
591
|
+
}
|
|
592
|
+
uint32_t getId(const char *data) const
|
|
593
|
+
{
|
|
594
|
+
uint32_t id = cybozu::Get32bitAsLE(data);
|
|
595
|
+
if (!isValidId(id)) throw cybozu::Exception("ms:cfb:DirectoryEntry:getId:bad id") << id;
|
|
596
|
+
return id;
|
|
597
|
+
}
|
|
598
|
+
void setId(uint32_t& out, uint32_t id, const char *idName)
|
|
599
|
+
{
|
|
600
|
+
if (!isValidId(id)) throw cybozu::Exception("ms:cfb:DirectoryEntry:setId:bad") << idName << id;
|
|
601
|
+
out = id;
|
|
602
|
+
}
|
|
603
|
+
cybozu::String16 getDirectoryEntryName(const char *data, uint16_t nameLength) const
|
|
604
|
+
{
|
|
605
|
+
cybozu::String16 str;
|
|
606
|
+
if (nameLength == 0) return str;
|
|
607
|
+
const uint16_t *p = reinterpret_cast<const uint16_t*>(data);
|
|
608
|
+
const int len = (nameLength - 2) / 2;
|
|
609
|
+
for (int i = 0; i < len; i++) {
|
|
610
|
+
uint16_t c = p[i];
|
|
611
|
+
if (!isValidEntryNameChar(c)) {
|
|
612
|
+
throw cybozu::Exception("ms:cfb:DirectoryEntry:getDirectoryEntryName:bad char") << i << c;
|
|
613
|
+
}
|
|
614
|
+
str += c;
|
|
615
|
+
}
|
|
616
|
+
MS_ASSERT(p[len] == 0);
|
|
617
|
+
return str;
|
|
618
|
+
}
|
|
619
|
+
void setDirectoryEntryName(const cybozu::String16& name)
|
|
620
|
+
{
|
|
621
|
+
const size_t len = name.size();
|
|
622
|
+
if (len > 31) throw cybozu::Exception("ms:cfb:DirectoryEntry:setDirectoryEntryName:bad length") << len;
|
|
623
|
+
directoryEntryNameLength = uint16_t((len + 1) * 2);
|
|
624
|
+
for (size_t i = 0; i < len; i++) {
|
|
625
|
+
uint16_t c = name[i];
|
|
626
|
+
if (!isValidEntryNameChar(c)) {
|
|
627
|
+
throw cybozu::Exception("ms:cfb:DirectoryEntry:setDirectoryEntryName:bad char") << i << c;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
directoryEntryName = name;
|
|
631
|
+
}
|
|
632
|
+
ObjectType getObjectType(const char *data) const
|
|
633
|
+
{
|
|
634
|
+
const char v = *data;
|
|
635
|
+
MS_ASSERT(v == 0 || v == 1 || v == 2 || v == 5);
|
|
636
|
+
return static_cast<ObjectType>(v);
|
|
637
|
+
}
|
|
638
|
+
ColorFlag getColorFlag(const char *data) const
|
|
639
|
+
{
|
|
640
|
+
const char v = *data;
|
|
641
|
+
MS_ASSERT(v == 0 || v == 1);
|
|
642
|
+
return static_cast<ColorFlag>(v);
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
struct DirectoryEntryVec : std::vector<DirectoryEntry> {
|
|
647
|
+
void analyze(const char *data, uint32_t sectorSize, const UintVec& chain)
|
|
648
|
+
{
|
|
649
|
+
for (size_t i = 0; i < chain.size(); i++) {
|
|
650
|
+
const char *p = data + sectorSize * (chain[i] + 1);
|
|
651
|
+
for (size_t j = 0; j < sectorSize; j += 128) {
|
|
652
|
+
DirectoryEntry dir(p + j);
|
|
653
|
+
if (!dir.directoryEntryName.empty()) {
|
|
654
|
+
push_back(dir);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
void load(std::string& content, const char *data, uint64_t dataSize, const UintVec& chain, uint64_t blockSize)
|
|
660
|
+
{
|
|
661
|
+
for (size_t i = 0, n = chain.size(); i < n; i++) {
|
|
662
|
+
if (content.size() >= dataSize) break;
|
|
663
|
+
uint64_t pos = chain[i] * blockSize;
|
|
664
|
+
const char *p = &data[pos];
|
|
665
|
+
content.insert(content.end(), p, p + blockSize);
|
|
666
|
+
}
|
|
667
|
+
dprintf("dataSize=%d, content.size()=%d\n", (int)dataSize, (int)content.size());
|
|
668
|
+
if (dataSize > content.size()) throw cybozu::Exception("ms:cfb:DirectoryEntryVec:short size") << dataSize << content.size();
|
|
669
|
+
content.resize((size_t)dataSize);
|
|
670
|
+
}
|
|
671
|
+
void setContents(const char *data, uint32_t sectorSize, const FatSectors& fats, const FatSectors& miniFats)
|
|
672
|
+
{
|
|
673
|
+
data += sectorSize;
|
|
674
|
+
std::string miniData;
|
|
675
|
+
for (size_t i = 0; i < size(); i++) {
|
|
676
|
+
DirectoryEntry& dir = (*this)[i];
|
|
677
|
+
switch (dir.objectType) {
|
|
678
|
+
case RootStorageObject:
|
|
679
|
+
{
|
|
680
|
+
const UintVec *v = fats.query(dir.startingSectorLocation);
|
|
681
|
+
if (v) {
|
|
682
|
+
load(miniData, data, dir.streamSize, *v, sectorSize);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
break;
|
|
686
|
+
case StreamObject: // file
|
|
687
|
+
{
|
|
688
|
+
/*
|
|
689
|
+
https://msdn.microsoft.com/en-us/library/dd941946.aspx
|
|
690
|
+
Any user-defined data stream that is greater than or equal to this cutoff
|
|
691
|
+
size must be allocated as normal sectors from the FAT.
|
|
692
|
+
*/
|
|
693
|
+
const uint64_t cutoffSize = 4096;
|
|
694
|
+
const uint64_t miniSectorSize = 64;
|
|
695
|
+
const uint32_t pos = dir.startingSectorLocation;
|
|
696
|
+
|
|
697
|
+
const UintVec *v;
|
|
698
|
+
if (dir.streamSize < cutoffSize && (v = miniFats.query(pos)) != 0) {
|
|
699
|
+
load(dir.content, &miniData[0], dir.streamSize, *v, miniSectorSize);
|
|
700
|
+
} else {
|
|
701
|
+
load(dir.content, data, dir.streamSize, fats.get(pos), sectorSize);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
break;
|
|
705
|
+
case StorageObject: // dir
|
|
706
|
+
break;
|
|
707
|
+
case Unallocated:
|
|
708
|
+
default:
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
size_t getAllSectorNum(size_t sectorSize) const
|
|
714
|
+
{
|
|
715
|
+
size_t num = 0;
|
|
716
|
+
for (size_t i = 0; i < size(); i++) {
|
|
717
|
+
const DirectoryEntry& dir = (*this)[i];
|
|
718
|
+
if (dir.objectType == StreamObject && dir.content.size() > 4096) {
|
|
719
|
+
dprintf("size=%d\n", (int)dir.content.size());
|
|
720
|
+
num += (dir.content.size() + sectorSize - 1) / sectorSize;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return num;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
struct CompoundFile {
|
|
728
|
+
Header header;
|
|
729
|
+
FatSectors fats;
|
|
730
|
+
FatSectors miniFats;
|
|
731
|
+
DirectoryEntryVec dirs;
|
|
732
|
+
explicit CompoundFile(const char *data = 0, uint32_t dataSize = 0)
|
|
733
|
+
: header(data, dataSize)
|
|
734
|
+
{
|
|
735
|
+
if (data) analyze(data, dataSize);
|
|
736
|
+
}
|
|
737
|
+
void analyze(const char *data, uint32_t dataSize)
|
|
738
|
+
{
|
|
739
|
+
dprintf("dataSize=%lld(0x%llx)\n", (long long)dataSize, (long long)dataSize);
|
|
740
|
+
const uint32_t version = header.majorVersion;
|
|
741
|
+
MS_ASSERT_EQUAL(version, 3u);
|
|
742
|
+
const uint32_t sectorSize = header.sectorSize;
|
|
743
|
+
dprintf("sectorSize=%u\n", sectorSize);
|
|
744
|
+
if (header.firstDirectorySectorLocation >= dataSize / sectorSize) {
|
|
745
|
+
throw cybozu::Exception("ms:cfb:CompoundFile:analyze:large size") << header.firstDirectorySectorLocation;
|
|
746
|
+
}
|
|
747
|
+
fats.analyze(data + 512, sectorSize, header.difat);
|
|
748
|
+
if (header.numMiniFatSectors > 0) {
|
|
749
|
+
dprintf("# of mini fat sectors = %d\n", header.numMiniFatSectors);
|
|
750
|
+
if (header.firstMiniFatSectorLocation + 1 >= dataSize / sectorSize) {
|
|
751
|
+
throw cybozu::Exception("ms:cfb:CompoundFile:analyze:bad firstMiniFatSectorLocation") << header.firstMiniFatSectorLocation;
|
|
752
|
+
}
|
|
753
|
+
miniFats.analyzeMini(data + 512, sectorSize, header.firstMiniFatSectorLocation);
|
|
754
|
+
}
|
|
755
|
+
dprintf("analyze dirs\n");
|
|
756
|
+
dirs.analyze(data, sectorSize, fats.chains[header.firstDirectorySectorLocation]);
|
|
757
|
+
dprintf("load contents\n");
|
|
758
|
+
dirs.setContents(data, sectorSize, fats, miniFats);
|
|
759
|
+
}
|
|
760
|
+
void put() const
|
|
761
|
+
{
|
|
762
|
+
if (!isDebug()) return;
|
|
763
|
+
header.put();
|
|
764
|
+
printf("FatSectors\n");
|
|
765
|
+
fats.put();
|
|
766
|
+
printf("mini FatSectors\n");
|
|
767
|
+
miniFats.put();
|
|
768
|
+
for (size_t i = 0; i < dirs.size(); i++) {
|
|
769
|
+
printf("----------------------------\n");
|
|
770
|
+
printf("DirectoryEntry %lld\n", (long long)i);
|
|
771
|
+
dirs[i].put();
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
} } // ms::cfb
|
|
777
|
+
|