ooxml_crypt 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|