cdf.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  1. /*-
  2. * Copyright (c) 2008 Christos Zoulas
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  15. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  16. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  18. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /*
  27. * Parse composite document files, the format used in Microsoft Office
  28. * document files before they switched to zipped xml.
  29. * Info from: http://sc.openoffice.org/compdocfileformat.pdf
  30. */
  31. #include "file.h"
  32. #ifndef lint
  33. FILE_RCSID("@(#)$File: cdf.c,v 1.30 2009/05/06 14:29:47 christos Exp $")
  34. #endif
  35. #include <assert.h>
  36. #ifdef CDF_DEBUG
  37. #include <err.h>
  38. #endif
  39. #include <stdlib.h>
  40. #include <unistd.h>
  41. #include <string.h>
  42. #include <time.h>
  43. #include <ctype.h>
  44. #ifndef EFTYPE
  45. #define EFTYPE EINVAL
  46. #endif
  47. #include "cdf.h"
  48. #ifndef __arraycount
  49. #define __arraycount(a) (sizeof(a) / sizeof(a[0]))
  50. #endif
  51. #ifdef CDF_DEBUG
  52. #define DPRINTF(a) printf a, fflush(stdout)
  53. #else
  54. #define DPRINTF(a)
  55. #endif
  56. static union {
  57. char s[4];
  58. uint32_t u;
  59. } cdf_bo;
  60. #define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304)
  61. #define CDF_TOLE8(x) (NEED_SWAP ? cdf_tole8(x) : (uint64_t)(x))
  62. #define CDF_TOLE4(x) (NEED_SWAP ? cdf_tole4(x) : (uint32_t)(x))
  63. #define CDF_TOLE2(x) (NEED_SWAP ? cdf_tole2(x) : (uint16_t)(x))
  64. /*
  65. * swap a short
  66. */
  67. uint16_t
  68. cdf_tole2(uint16_t sv)
  69. {
  70. uint16_t rv;
  71. uint8_t *s = (uint8_t *)(void *)&sv;
  72. uint8_t *d = (uint8_t *)(void *)&rv;
  73. d[0] = s[1];
  74. d[1] = s[0];
  75. return rv;
  76. }
  77. /*
  78. * swap an int
  79. */
  80. uint32_t
  81. cdf_tole4(uint32_t sv)
  82. {
  83. uint32_t rv;
  84. uint8_t *s = (uint8_t *)(void *)&sv;
  85. uint8_t *d = (uint8_t *)(void *)&rv;
  86. d[0] = s[3];
  87. d[1] = s[2];
  88. d[2] = s[1];
  89. d[3] = s[0];
  90. return rv;
  91. }
  92. /*
  93. * swap a quad
  94. */
  95. uint64_t
  96. cdf_tole8(uint64_t sv)
  97. {
  98. uint64_t rv;
  99. uint8_t *s = (uint8_t *)(void *)&sv;
  100. uint8_t *d = (uint8_t *)(void *)&rv;
  101. d[0] = s[7];
  102. d[1] = s[6];
  103. d[2] = s[5];
  104. d[3] = s[4];
  105. d[4] = s[3];
  106. d[5] = s[2];
  107. d[6] = s[1];
  108. d[7] = s[0];
  109. return rv;
  110. }
  111. #define CDF_UNPACK(a) \
  112. (void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a)
  113. #define CDF_UNPACKA(a) \
  114. (void)memcpy((a), &buf[len], sizeof(a)), len += sizeof(a)
  115. void
  116. cdf_swap_header(cdf_header_t *h)
  117. {
  118. size_t i;
  119. h->h_magic = CDF_TOLE8(h->h_magic);
  120. h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]);
  121. h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]);
  122. h->h_revision = CDF_TOLE2(h->h_revision);
  123. h->h_version = CDF_TOLE2(h->h_version);
  124. h->h_byte_order = CDF_TOLE2(h->h_byte_order);
  125. h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2);
  126. h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2);
  127. h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat);
  128. h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory);
  129. h->h_min_size_standard_stream =
  130. CDF_TOLE4(h->h_min_size_standard_stream);
  131. h->h_secid_first_sector_in_short_sat =
  132. CDF_TOLE4(h->h_secid_first_sector_in_short_sat);
  133. h->h_num_sectors_in_short_sat =
  134. CDF_TOLE4(h->h_num_sectors_in_short_sat);
  135. h->h_secid_first_sector_in_master_sat =
  136. CDF_TOLE4(h->h_secid_first_sector_in_master_sat);
  137. h->h_num_sectors_in_master_sat =
  138. CDF_TOLE4(h->h_num_sectors_in_master_sat);
  139. for (i = 0; i < __arraycount(h->h_master_sat); i++)
  140. h->h_master_sat[i] = CDF_TOLE4(h->h_master_sat[i]);
  141. }
  142. void
  143. cdf_unpack_header(cdf_header_t *h, char *buf)
  144. {
  145. size_t i;
  146. size_t len = 0;
  147. CDF_UNPACK(h->h_magic);
  148. CDF_UNPACKA(h->h_uuid);
  149. CDF_UNPACK(h->h_revision);
  150. CDF_UNPACK(h->h_version);
  151. CDF_UNPACK(h->h_byte_order);
  152. CDF_UNPACK(h->h_sec_size_p2);
  153. CDF_UNPACK(h->h_short_sec_size_p2);
  154. CDF_UNPACKA(h->h_unused0);
  155. CDF_UNPACK(h->h_num_sectors_in_sat);
  156. CDF_UNPACK(h->h_secid_first_directory);
  157. CDF_UNPACKA(h->h_unused1);
  158. CDF_UNPACK(h->h_min_size_standard_stream);
  159. CDF_UNPACK(h->h_secid_first_sector_in_short_sat);
  160. CDF_UNPACK(h->h_num_sectors_in_short_sat);
  161. CDF_UNPACK(h->h_secid_first_sector_in_master_sat);
  162. CDF_UNPACK(h->h_num_sectors_in_master_sat);
  163. for (i = 0; i < __arraycount(h->h_master_sat); i++)
  164. CDF_UNPACK(h->h_master_sat[i]);
  165. }
  166. void
  167. cdf_swap_dir(cdf_directory_t *d)
  168. {
  169. d->d_namelen = CDF_TOLE2(d->d_namelen);
  170. d->d_left_child = CDF_TOLE4(d->d_left_child);
  171. d->d_right_child = CDF_TOLE4(d->d_right_child);
  172. d->d_storage = CDF_TOLE4(d->d_storage);
  173. d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]);
  174. d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]);
  175. d->d_flags = CDF_TOLE4(d->d_flags);
  176. d->d_created = CDF_TOLE8(d->d_created);
  177. d->d_modified = CDF_TOLE8(d->d_modified);
  178. d->d_stream_first_sector = CDF_TOLE4(d->d_stream_first_sector);
  179. d->d_size = CDF_TOLE4(d->d_size);
  180. }
  181. void
  182. cdf_swap_class(cdf_classid_t *d)
  183. {
  184. d->cl_dword = CDF_TOLE4(d->cl_dword);
  185. d->cl_word[0] = CDF_TOLE2(d->cl_word[0]);
  186. d->cl_word[1] = CDF_TOLE2(d->cl_word[1]);
  187. }
  188. void
  189. cdf_unpack_dir(cdf_directory_t *d, char *buf)
  190. {
  191. size_t len = 0;
  192. CDF_UNPACKA(d->d_name);
  193. CDF_UNPACK(d->d_namelen);
  194. CDF_UNPACK(d->d_type);
  195. CDF_UNPACK(d->d_color);
  196. CDF_UNPACK(d->d_left_child);
  197. CDF_UNPACK(d->d_right_child);
  198. CDF_UNPACK(d->d_storage);
  199. CDF_UNPACKA(d->d_storage_uuid);
  200. CDF_UNPACK(d->d_flags);
  201. CDF_UNPACK(d->d_created);
  202. CDF_UNPACK(d->d_modified);
  203. CDF_UNPACK(d->d_stream_first_sector);
  204. CDF_UNPACK(d->d_size);
  205. CDF_UNPACK(d->d_unused0);
  206. }
  207. static int
  208. cdf_check_stream_offset(const cdf_stream_t *sst, const void *p, size_t tail)
  209. {
  210. const char *b = (const char *)sst->sst_tab;
  211. const char *e = ((const char *)p) + tail;
  212. if (e >= b && (size_t)(e - b) < sst->sst_dirlen * sst->sst_len)
  213. return 0;
  214. DPRINTF((stderr, "offset begin %p end %p %zu >= %zu\n", b, e,
  215. (size_t)(e - b), sst->sst_dirlen * sst->sst_len));
  216. errno = EFTYPE;
  217. return -1;
  218. }
  219. static ssize_t
  220. cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len)
  221. {
  222. size_t siz = (size_t)off + len;
  223. if ((off_t)(off + len) != (off_t)siz) {
  224. errno = EINVAL;
  225. return -1;
  226. }
  227. if (info->i_buf != NULL && info->i_len >= siz) {
  228. (void)memcpy(buf, &info->i_buf[off], len);
  229. return (ssize_t)len;
  230. }
  231. if (info->i_fd == -1)
  232. return -1;
  233. if (lseek(info->i_fd, off, SEEK_SET) == (off_t)-1)
  234. return -1;
  235. if (read(info->i_fd, buf, len) != (ssize_t)len)
  236. return -1;
  237. return (ssize_t)len;
  238. }
  239. int
  240. cdf_read_header(const cdf_info_t *info, cdf_header_t *h)
  241. {
  242. char buf[512];
  243. (void)memcpy(cdf_bo.s, "\01\02\03\04", 4);
  244. if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1)
  245. return -1;
  246. cdf_unpack_header(h, buf);
  247. cdf_swap_header(h);
  248. if (h->h_magic != CDF_MAGIC) {
  249. DPRINTF(("Bad magic 0x%llx != 0x%llx\n",
  250. (unsigned long long)h->h_magic,
  251. (unsigned long long)CDF_MAGIC));
  252. goto out;
  253. }
  254. if (h->h_sec_size_p2 > 20) {
  255. DPRINTF(("Bad sector size 0x%u\n", h->h_sec_size_p2));
  256. goto out;
  257. }
  258. if (h->h_short_sec_size_p2 > 20) {
  259. DPRINTF(("Bad short sector size 0x%u\n",
  260. h->h_short_sec_size_p2));
  261. goto out;
  262. }
  263. return 0;
  264. out:
  265. errno = EFTYPE;
  266. return -1;
  267. }
  268. ssize_t
  269. cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len,
  270. const cdf_header_t *h, cdf_secid_t id)
  271. {
  272. assert((size_t)CDF_SEC_SIZE(h) == len);
  273. return cdf_read(info, (off_t)CDF_SEC_POS(h, id),
  274. ((char *)buf) + offs, len);
  275. }
  276. ssize_t
  277. cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs,
  278. size_t len, const cdf_header_t *h, cdf_secid_t id)
  279. {
  280. assert((size_t)CDF_SHORT_SEC_SIZE(h) == len);
  281. (void)memcpy(((char *)buf) + offs,
  282. ((const char *)sst->sst_tab) + CDF_SHORT_SEC_POS(h, id), len);
  283. return len;
  284. }
  285. /*
  286. * Read the sector allocation table.
  287. */
  288. int
  289. cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
  290. {
  291. size_t i, j, k;
  292. size_t ss = CDF_SEC_SIZE(h);
  293. cdf_secid_t *msa, mid, sec;
  294. size_t nsatpersec = (ss / sizeof(mid)) - 1;
  295. for (i = 0; i < __arraycount(h->h_master_sat); i++)
  296. if (h->h_master_sat[i] == CDF_SECID_FREE)
  297. break;
  298. #define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss))
  299. if (h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec ||
  300. i > CDF_SEC_LIMIT) {
  301. DPRINTF(("Number of sectors in master SAT too big %u %zu\n",
  302. h->h_num_sectors_in_master_sat, i));
  303. errno = EFTYPE;
  304. return -1;
  305. }
  306. sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i;
  307. DPRINTF(("sat_len = %zu ss = %zu\n", sat->sat_len, ss));
  308. if ((sat->sat_tab = calloc(sat->sat_len, ss)) == NULL)
  309. return -1;
  310. for (i = 0; i < __arraycount(h->h_master_sat); i++) {
  311. if (h->h_master_sat[i] < 0)
  312. break;
  313. if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
  314. h->h_master_sat[i]) != (ssize_t)ss) {
  315. DPRINTF(("Reading sector %d", h->h_master_sat[i]));
  316. goto out1;
  317. }
  318. }
  319. if ((msa = calloc(1, ss)) == NULL)
  320. goto out1;
  321. mid = h->h_secid_first_sector_in_master_sat;
  322. for (j = 0; j < h->h_num_sectors_in_master_sat; j++) {
  323. if (mid < 0)
  324. goto out;
  325. if (j >= CDF_LOOP_LIMIT) {
  326. DPRINTF(("Reading master sector loop limit"));
  327. errno = EFTYPE;
  328. goto out2;
  329. }
  330. if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) {
  331. DPRINTF(("Reading master sector %d", mid));
  332. goto out2;
  333. }
  334. for (k = 0; k < nsatpersec; k++, i++) {
  335. sec = CDF_TOLE4(msa[k]);
  336. if (sec < 0)
  337. goto out;
  338. if (i >= sat->sat_len) {
  339. DPRINTF(("Out of bounds reading MSA %u >= %u",
  340. i, sat->sat_len));
  341. errno = EFTYPE;
  342. goto out2;
  343. }
  344. if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
  345. sec) != (ssize_t)ss) {
  346. DPRINTF(("Reading sector %d",
  347. CDF_TOLE4(msa[k])));
  348. goto out2;
  349. }
  350. }
  351. mid = CDF_TOLE4(msa[nsatpersec]);
  352. }
  353. out:
  354. sat->sat_len = i;
  355. free(msa);
  356. return 0;
  357. out2:
  358. free(msa);
  359. out1:
  360. free(sat->sat_tab);
  361. return -1;
  362. }
  363. size_t
  364. cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
  365. {
  366. size_t i, j;
  367. cdf_secid_t maxsector = (cdf_secid_t)(sat->sat_len * size);
  368. DPRINTF(("Chain:"));
  369. for (j = i = 0; sid >= 0; i++, j++) {
  370. DPRINTF((" %d", sid));
  371. if (j >= CDF_LOOP_LIMIT) {
  372. DPRINTF(("Counting chain loop limit"));
  373. errno = EFTYPE;
  374. return (size_t)-1;
  375. }
  376. if (sid > maxsector) {
  377. DPRINTF(("Sector %d > %d\n", sid, maxsector));
  378. errno = EFTYPE;
  379. return (size_t)-1;
  380. }
  381. sid = CDF_TOLE4(sat->sat_tab[sid]);
  382. }
  383. DPRINTF(("\n"));
  384. return i;
  385. }
  386. int
  387. cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
  388. const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn)
  389. {
  390. size_t ss = CDF_SEC_SIZE(h), i, j;
  391. ssize_t nr;
  392. scn->sst_len = cdf_count_chain(sat, sid, ss);
  393. scn->sst_dirlen = len;
  394. if (scn->sst_len == (size_t)-1)
  395. return -1;
  396. scn->sst_tab = calloc(scn->sst_len, ss);
  397. if (scn->sst_tab == NULL)
  398. return -1;
  399. for (j = i = 0; sid >= 0; i++, j++) {
  400. if (j >= CDF_LOOP_LIMIT) {
  401. DPRINTF(("Read long sector chain loop limit"));
  402. errno = EFTYPE;
  403. goto out;
  404. }
  405. if (i >= scn->sst_len) {
  406. DPRINTF(("Out of bounds reading long sector chain "
  407. "%u > %u\n", i, scn->sst_len));
  408. errno = EFTYPE;
  409. goto out;
  410. }
  411. if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h,
  412. sid)) != (ssize_t)ss) {
  413. if (i == scn->sst_len - 1 && nr > 0) {
  414. /* Last sector might be truncated */
  415. return 0;
  416. }
  417. DPRINTF(("Reading long sector chain %d", sid));
  418. goto out;
  419. }
  420. sid = CDF_TOLE4(sat->sat_tab[sid]);
  421. }
  422. return 0;
  423. out:
  424. free(scn->sst_tab);
  425. return -1;
  426. }
  427. int
  428. cdf_read_short_sector_chain(const cdf_header_t *h,
  429. const cdf_sat_t *ssat, const cdf_stream_t *sst,
  430. cdf_secid_t sid, size_t len, cdf_stream_t *scn)
  431. {
  432. size_t ss = CDF_SHORT_SEC_SIZE(h), i, j;
  433. scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h));
  434. scn->sst_dirlen = len;
  435. if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1)
  436. return -1;
  437. scn->sst_tab = calloc(scn->sst_len, ss);
  438. if (scn->sst_tab == NULL)
  439. return -1;
  440. for (j = i = 0; sid >= 0; i++, j++) {
  441. if (j >= CDF_LOOP_LIMIT) {
  442. DPRINTF(("Read short sector chain loop limit"));
  443. errno = EFTYPE;
  444. goto out;
  445. }
  446. if (i >= scn->sst_len) {
  447. DPRINTF(("Out of bounds reading short sector chain "
  448. "%u > %u\n", i, scn->sst_len));
  449. errno = EFTYPE;
  450. goto out;
  451. }
  452. if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h,
  453. sid) != (ssize_t)ss) {
  454. DPRINTF(("Reading short sector chain %d", sid));
  455. goto out;
  456. }
  457. sid = CDF_TOLE4(ssat->sat_tab[sid]);
  458. }
  459. return 0;
  460. out:
  461. free(scn->sst_tab);
  462. return -1;
  463. }
  464. int
  465. cdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
  466. const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
  467. cdf_secid_t sid, size_t len, cdf_stream_t *scn)
  468. {
  469. if (len < h->h_min_size_standard_stream)
  470. return cdf_read_short_sector_chain(h, ssat, sst, sid, len,
  471. scn);
  472. else
  473. return cdf_read_long_sector_chain(info, h, sat, sid, len, scn);
  474. }
  475. int
  476. cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
  477. const cdf_sat_t *sat, cdf_dir_t *dir)
  478. {
  479. size_t i, j;
  480. size_t ss = CDF_SEC_SIZE(h), ns, nd;
  481. char *buf;
  482. cdf_secid_t sid = h->h_secid_first_directory;
  483. ns = cdf_count_chain(sat, sid, ss);
  484. if (ns == (size_t)-1)
  485. return -1;
  486. nd = ss / CDF_DIRECTORY_SIZE;
  487. dir->dir_len = ns * nd;
  488. dir->dir_tab = calloc(dir->dir_len, sizeof(dir->dir_tab[0]));
  489. if (dir->dir_tab == NULL)
  490. return -1;
  491. if ((buf = malloc(ss)) == NULL) {
  492. free(dir->dir_tab);
  493. return -1;
  494. }
  495. for (j = i = 0; i < ns; i++, j++) {
  496. if (j >= CDF_LOOP_LIMIT) {
  497. DPRINTF(("Read dir loop limit"));
  498. errno = EFTYPE;
  499. goto out;
  500. }
  501. if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) {
  502. DPRINTF(("Reading directory sector %d", sid));
  503. goto out;
  504. }
  505. for (j = 0; j < nd; j++) {
  506. cdf_unpack_dir(&dir->dir_tab[i * nd + j],
  507. &buf[j * CDF_DIRECTORY_SIZE]);
  508. }
  509. sid = CDF_TOLE4(sat->sat_tab[sid]);
  510. }
  511. if (NEED_SWAP)
  512. for (i = 0; i < dir->dir_len; i++)
  513. cdf_swap_dir(&dir->dir_tab[i]);
  514. free(buf);
  515. return 0;
  516. out:
  517. free(dir->dir_tab);
  518. free(buf);
  519. return -1;
  520. }
  521. int
  522. cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h,
  523. const cdf_sat_t *sat, cdf_sat_t *ssat)
  524. {
  525. size_t i, j;
  526. size_t ss = CDF_SEC_SIZE(h);
  527. cdf_secid_t sid = h->h_secid_first_sector_in_short_sat;
  528. ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h));
  529. if (ssat->sat_len == (size_t)-1)
  530. return -1;
  531. ssat->sat_tab = calloc(ssat->sat_len, ss);
  532. if (ssat->sat_tab == NULL)
  533. return -1;
  534. for (j = i = 0; sid >= 0; i++, j++) {
  535. if (j >= CDF_LOOP_LIMIT) {
  536. DPRINTF(("Read short sat sector loop limit"));
  537. errno = EFTYPE;
  538. goto out;
  539. }
  540. if (i >= ssat->sat_len) {
  541. DPRINTF(("Out of bounds reading short sector chain "
  542. "%u > %u\n", i, ssat->sat_len));
  543. errno = EFTYPE;
  544. goto out;
  545. }
  546. if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) !=
  547. (ssize_t)ss) {
  548. DPRINTF(("Reading short sat sector %d", sid));
  549. goto out;
  550. }
  551. sid = CDF_TOLE4(sat->sat_tab[sid]);
  552. }
  553. return 0;
  554. out:
  555. free(ssat->sat_tab);
  556. return -1;
  557. }
  558. int
  559. cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
  560. const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn)
  561. {
  562. size_t i;
  563. const cdf_directory_t *d;
  564. for (i = 0; i < dir->dir_len; i++)
  565. if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE)
  566. break;
  567. /* If the it is not there, just fake it; some docs don't have it */
  568. if (i == dir->dir_len)
  569. goto out;
  570. d = &dir->dir_tab[i];
  571. /* If the it is not there, just fake it; some docs don't have it */
  572. if (d->d_stream_first_sector < 0)
  573. goto out;
  574. return cdf_read_long_sector_chain(info, h, sat,
  575. d->d_stream_first_sector, d->d_size, scn);
  576. out:
  577. scn->sst_tab = NULL;
  578. scn->sst_len = 0;
  579. scn->sst_dirlen = 0;
  580. return 0;
  581. }
  582. static int
  583. cdf_namecmp(const char *d, const uint16_t *s, size_t l)
  584. {
  585. for (; l--; d++, s++)
  586. if (*d != CDF_TOLE2(*s))
  587. return (unsigned char)*d - CDF_TOLE2(*s);
  588. return 0;
  589. }
  590. int
  591. cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h,
  592. const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
  593. const cdf_dir_t *dir, cdf_stream_t *scn)
  594. {
  595. size_t i;
  596. const cdf_directory_t *d;
  597. static const char name[] = "\05SummaryInformation";
  598. for (i = 0; i < dir->dir_len; i++)
  599. if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_USER_STREAM &&
  600. cdf_namecmp(name, dir->dir_tab[i].d_name, sizeof(name))
  601. == 0)
  602. break;
  603. if (i == dir->dir_len) {
  604. DPRINTF(("Cannot find summary information section\n"));
  605. errno = EFTYPE;
  606. return -1;
  607. }
  608. d = &dir->dir_tab[i];
  609. return cdf_read_sector_chain(info, h, sat, ssat, sst,
  610. d->d_stream_first_sector, d->d_size, scn);
  611. }
  612. int
  613. cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
  614. cdf_property_info_t **info, size_t *count, size_t *maxcount)
  615. {
  616. const cdf_section_header_t *shp;
  617. cdf_section_header_t sh;
  618. const uint32_t *p, *q, *e;
  619. int16_t s16;
  620. int32_t s32;
  621. uint32_t u32;
  622. int64_t s64;
  623. uint64_t u64;
  624. cdf_timestamp_t tp;
  625. size_t i, o, nelements, j;
  626. cdf_property_info_t *inp;
  627. if (offs > UINT32_MAX / 4) {
  628. errno = EFTYPE;
  629. goto out;
  630. }
  631. shp = (const void *)((const char *)sst->sst_tab + offs);
  632. if (cdf_check_stream_offset(sst, shp, sizeof(*shp)) == -1)
  633. goto out;
  634. sh.sh_len = CDF_TOLE4(shp->sh_len);
  635. #define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
  636. if (sh.sh_len > CDF_SHLEN_LIMIT) {
  637. errno = EFTYPE;
  638. goto out;
  639. }
  640. sh.sh_properties = CDF_TOLE4(shp->sh_properties);
  641. #define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp)))
  642. if (sh.sh_properties > CDF_PROP_LIMIT)
  643. goto out;
  644. DPRINTF(("section len: %u properties %u\n", sh.sh_len,
  645. sh.sh_properties));
  646. if (*maxcount) {
  647. if (*maxcount > CDF_PROP_LIMIT)
  648. goto out;
  649. *maxcount += sh.sh_properties;
  650. inp = realloc(*info, *maxcount * sizeof(*inp));
  651. } else {
  652. *maxcount = sh.sh_properties;
  653. inp = malloc(*maxcount * sizeof(*inp));
  654. }
  655. if (inp == NULL)
  656. goto out;
  657. *info = inp;
  658. inp += *count;
  659. *count += sh.sh_properties;
  660. p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
  661. e = (const void *)(((const char *)shp) + sh.sh_len);
  662. if (cdf_check_stream_offset(sst, e, 0) == -1)
  663. goto out;
  664. for (i = 0; i < sh.sh_properties; i++) {
  665. q = (const uint32_t *)((const char *)p +
  666. CDF_TOLE4(p[(i << 1) + 1])) - 2;
  667. if (q > e) {
  668. DPRINTF(("Ran of the end %p > %p\n", q, e));
  669. goto out;
  670. }
  671. inp[i].pi_id = CDF_TOLE4(p[i << 1]);
  672. inp[i].pi_type = CDF_TOLE4(q[0]);
  673. DPRINTF(("%d) id=%x type=%x offs=%x\n", i, inp[i].pi_id,
  674. inp[i].pi_type, (const char *)q - (const char *)p));
  675. if (inp[i].pi_type & CDF_VECTOR) {
  676. nelements = CDF_TOLE4(q[1]);
  677. o = 2;
  678. } else {
  679. nelements = 1;
  680. o = 1;
  681. }
  682. if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED))
  683. goto unknown;
  684. switch (inp[i].pi_type & CDF_TYPEMASK) {
  685. case CDF_EMPTY:
  686. break;
  687. case CDF_SIGNED16:
  688. if (inp[i].pi_type & CDF_VECTOR)
  689. goto unknown;
  690. (void)memcpy(&s16, &q[o], sizeof(s16));
  691. inp[i].pi_s16 = CDF_TOLE2(s16);
  692. break;
  693. case CDF_SIGNED32:
  694. if (inp[i].pi_type & CDF_VECTOR)
  695. goto unknown;
  696. (void)memcpy(&s32, &q[o], sizeof(s32));
  697. inp[i].pi_s32 = CDF_TOLE4(s32);
  698. break;
  699. case CDF_BOOL:
  700. case CDF_UNSIGNED32:
  701. if (inp[i].pi_type & CDF_VECTOR)
  702. goto unknown;
  703. (void)memcpy(&u32, &q[o], sizeof(u32));
  704. inp[i].pi_u32 = CDF_TOLE4(u32);
  705. break;
  706. case CDF_SIGNED64:
  707. if (inp[i].pi_type & CDF_VECTOR)
  708. goto unknown;
  709. (void)memcpy(&s64, &q[o], sizeof(s64));
  710. inp[i].pi_s64 = CDF_TOLE4(s64);
  711. break;
  712. case CDF_UNSIGNED64:
  713. if (inp[i].pi_type & CDF_VECTOR)
  714. goto unknown;
  715. (void)memcpy(&u64, &q[o], sizeof(u64));
  716. inp[i].pi_u64 = CDF_TOLE4(u64);
  717. break;
  718. case CDF_LENGTH32_STRING:
  719. if (nelements > 1) {
  720. size_t nelem = inp - *info;
  721. if (*maxcount > CDF_PROP_LIMIT
  722. || nelements > CDF_PROP_LIMIT)
  723. goto out;
  724. *maxcount += nelements;
  725. inp = realloc(*info, *maxcount * sizeof(*inp));
  726. if (inp == NULL)
  727. goto out;
  728. *info = inp;
  729. inp = *info + nelem;
  730. }
  731. DPRINTF(("nelements = %d\n", nelements));
  732. for (j = 0; j < nelements; j++, i++) {
  733. uint32_t l = CDF_TOLE4(q[o]);
  734. inp[i].pi_str.s_len = l;
  735. inp[i].pi_str.s_buf = (const char *)(&q[o+1]);
  736. DPRINTF(("l = %d, r = %d, s = %s\n", l,
  737. CDF_ROUND(l, sizeof(l)),
  738. inp[i].pi_str.s_buf));
  739. l = 4 + CDF_ROUND(l, sizeof(l));
  740. o += l >> 2;
  741. }
  742. i--;
  743. break;
  744. case CDF_FILETIME:
  745. if (inp[i].pi_type & CDF_VECTOR)
  746. goto unknown;
  747. (void)memcpy(&tp, &q[o], sizeof(tp));
  748. inp[i].pi_tp = CDF_TOLE8(tp);
  749. break;
  750. case CDF_CLIPBOARD:
  751. if (inp[i].pi_type & CDF_VECTOR)
  752. goto unknown;
  753. break;
  754. default:
  755. unknown:
  756. DPRINTF(("Don't know how to deal with %x\n",
  757. inp[i].pi_type));
  758. goto out;
  759. }
  760. }
  761. return 0;
  762. out:
  763. free(*info);
  764. return -1;
  765. }
  766. int
  767. cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
  768. cdf_property_info_t **info, size_t *count)
  769. {
  770. size_t i, maxcount;
  771. const cdf_summary_info_header_t *si = sst->sst_tab;
  772. const cdf_section_declaration_t *sd = (const void *)
  773. ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
  774. if (cdf_check_stream_offset(sst, si, sizeof(*si)) == -1 ||
  775. cdf_check_stream_offset(sst, sd, sizeof(*sd)) == -1)
  776. return -1;
  777. ssi->si_byte_order = CDF_TOLE2(si->si_byte_order);
  778. ssi->si_os_version = CDF_TOLE2(si->si_os_version);
  779. ssi->si_os = CDF_TOLE2(si->si_os);
  780. ssi->si_class = si->si_class;
  781. cdf_swap_class(&ssi->si_class);
  782. ssi->si_count = CDF_TOLE2(si->si_count);
  783. *count = 0;
  784. maxcount = 0;
  785. *info = NULL;
  786. for (i = 0; i < CDF_TOLE4(si->si_count); i++) {
  787. if (i >= CDF_LOOP_LIMIT) {
  788. DPRINTF(("Unpack summary info loop limit"));
  789. errno = EFTYPE;
  790. return -1;
  791. }
  792. if (cdf_read_property_info(sst, CDF_TOLE4(sd->sd_offset),
  793. info, count, &maxcount) == -1)
  794. return -1;
  795. }
  796. return 0;
  797. }
  798. int
  799. cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id)
  800. {
  801. return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-"
  802. "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0],
  803. id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0],
  804. id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4],
  805. id->cl_six[5]);
  806. }
  807. static const struct {
  808. uint32_t v;
  809. const char *n;
  810. } vn[] = {
  811. { CDF_PROPERTY_CODE_PAGE, "Code page" },
  812. { CDF_PROPERTY_TITLE, "Title" },
  813. { CDF_PROPERTY_SUBJECT, "Subject" },
  814. { CDF_PROPERTY_AUTHOR, "Author" },
  815. { CDF_PROPERTY_KEYWORDS, "Keywords" },
  816. { CDF_PROPERTY_COMMENTS, "Comments" },
  817. { CDF_PROPERTY_TEMPLATE, "Template" },
  818. { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" },
  819. { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" },
  820. { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" },
  821. { CDF_PROPERTY_LAST_PRINTED, "Last Printed" },
  822. { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" },
  823. { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" },
  824. { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" },
  825. { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" },
  826. { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" },
  827. { CDF_PROPERTY_THUMBNAIL, "Thumbnail" },
  828. { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" },
  829. { CDF_PROPERTY_SECURITY, "Security" },
  830. { CDF_PROPERTY_LOCALE_ID, "Locale ID" },
  831. };
  832. int
  833. cdf_print_property_name(char *buf, size_t bufsiz, uint32_t p)
  834. {
  835. size_t i;
  836. for (i = 0; i < __arraycount(vn); i++)
  837. if (vn[i].v == p)
  838. return snprintf(buf, bufsiz, "%s", vn[i].n);
  839. return snprintf(buf, bufsiz, "0x%x", p);
  840. }
  841. int
  842. cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts)
  843. {
  844. size_t len = 0;
  845. int days, hours, mins, secs;
  846. ts /= CDF_TIME_PREC;
  847. secs = ts % 60;
  848. ts /= 60;
  849. mins = ts % 60;
  850. ts /= 60;
  851. hours = ts % 24;
  852. ts /= 24;
  853. days = ts;
  854. if (days) {
  855. len += snprintf(buf + len, bufsiz - len, "%dd+", days);
  856. if (len >= bufsiz)
  857. return len;
  858. }
  859. if (days || hours) {
  860. len += snprintf(buf + len, bufsiz - len, "%.2d:", hours);
  861. if (len >= bufsiz)
  862. return len;
  863. }
  864. len += snprintf(buf + len, bufsiz - len, "%.2d:", mins);
  865. if (len >= bufsiz)
  866. return len;
  867. len += snprintf(buf + len, bufsiz - len, "%.2d", secs);
  868. return len;
  869. }
  870. #ifdef CDF_DEBUG
  871. void
  872. cdf_dump_header(const cdf_header_t *h)
  873. {
  874. size_t i;
  875. #define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b)
  876. #define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \
  877. h->h_ ## b, 1 << h->h_ ## b)
  878. DUMP("%d", revision);
  879. DUMP("%d", version);
  880. DUMP("0x%x", byte_order);
  881. DUMP2("%d", sec_size_p2);
  882. DUMP2("%d", short_sec_size_p2);
  883. DUMP("%d", num_sectors_in_sat);
  884. DUMP("%d", secid_first_directory);
  885. DUMP("%d", min_size_standard_stream);
  886. DUMP("%d", secid_first_sector_in_short_sat);
  887. DUMP("%d", num_sectors_in_short_sat);
  888. DUMP("%d", secid_first_sector_in_master_sat);
  889. DUMP("%d", num_sectors_in_master_sat);
  890. for (i = 0; i < __arraycount(h->h_master_sat); i++) {
  891. if (h->h_master_sat[i] == CDF_SECID_FREE)
  892. break;
  893. (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n",
  894. "master_sat", i, h->h_master_sat[i]);
  895. }
  896. }
  897. void
  898. cdf_dump_sat(const char *prefix, const cdf_sat_t *sat, size_t size)
  899. {
  900. size_t i, j, s = size / sizeof(cdf_secid_t);
  901. for (i = 0; i < sat->sat_len; i++) {
  902. (void)fprintf(stderr, "%s[%zu]:\n%.6d: ", prefix, i, i * s);
  903. for (j = 0; j < s; j++) {
  904. (void)fprintf(stderr, "%5d, ",
  905. CDF_TOLE4(sat->sat_tab[s * i + j]));
  906. if ((j + 1) % 10 == 0)
  907. (void)fprintf(stderr, "\n%.6d: ",
  908. i * s + j + 1);
  909. }
  910. (void)fprintf(stderr, "\n");
  911. }
  912. }
  913. void
  914. cdf_dump(void *v, size_t len)
  915. {
  916. size_t i, j;
  917. unsigned char *p = v;
  918. char abuf[16];
  919. (void)fprintf(stderr, "%.4x: ", 0);
  920. for (i = 0, j = 0; i < len; i++, p++) {
  921. (void)fprintf(stderr, "%.2x ", *p);
  922. abuf[j++] = isprint(*p) ? *p : '.';
  923. if (j == 16) {
  924. j = 0;
  925. abuf[15] = '\0';
  926. (void)fprintf(stderr, "%s\n%.4x: ", abuf, i + 1);
  927. }
  928. }
  929. (void)fprintf(stderr, "\n");
  930. }
  931. void
  932. cdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst)
  933. {
  934. size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
  935. CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
  936. cdf_dump(sst->sst_tab, ss * sst->sst_len);
  937. }
  938. void
  939. cdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h,
  940. const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
  941. const cdf_dir_t *dir)
  942. {
  943. size_t i, j;
  944. cdf_directory_t *d;
  945. char name[__arraycount(d->d_name)];
  946. cdf_stream_t scn;
  947. struct timespec ts;
  948. static const char *types[] = { "empty", "user storage",
  949. "user stream", "lockbytes", "property", "root storage" };
  950. for (i = 0; i < dir->dir_len; i++) {
  951. d = &dir->dir_tab[i];
  952. for (j = 0; j < sizeof(name); j++)
  953. name[j] = (char)CDF_TOLE2(d->d_name[j]);
  954. (void)fprintf(stderr, "Directory %zu: %s\n", i, name);
  955. if (d->d_type < __arraycount(types))
  956. (void)fprintf(stderr, "Type: %s\n", types[d->d_type]);
  957. else
  958. (void)fprintf(stderr, "Type: %d\n", d->d_type);
  959. (void)fprintf(stderr, "Color: %s\n",
  960. d->d_color ? "black" : "red");
  961. (void)fprintf(stderr, "Left child: %d\n", d->d_left_child);
  962. (void)fprintf(stderr, "Right child: %d\n", d->d_right_child);
  963. (void)fprintf(stderr, "Flags: 0x%x\n", d->d_flags);
  964. cdf_timestamp_to_timespec(&ts, d->d_created);
  965. (void)fprintf(stderr, "Created %s", ctime(&ts.tv_sec));
  966. cdf_timestamp_to_timespec(&ts, d->d_modified);
  967. (void)fprintf(stderr, "Modified %s", ctime(&ts.tv_sec));
  968. (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector);
  969. (void)fprintf(stderr, "Size %d\n", d->d_size);
  970. switch (d->d_type) {
  971. case CDF_DIR_TYPE_USER_STORAGE:
  972. (void)fprintf(stderr, "Storage: %d\n", d->d_storage);
  973. break;
  974. case CDF_DIR_TYPE_USER_STREAM:
  975. if (sst == NULL)
  976. break;
  977. if (cdf_read_sector_chain(info, h, sat, ssat, sst,
  978. d->d_stream_first_sector, d->d_size, &scn) == -1) {
  979. warn("Can't read stream for %s at %d len %d",
  980. name, d->d_stream_first_sector, d->d_size);
  981. break;
  982. }
  983. cdf_dump_stream(h, &scn);
  984. free(scn.sst_tab);
  985. break;
  986. default:
  987. break;
  988. }
  989. }
  990. }
  991. void
  992. cdf_dump_property_info(const cdf_property_info_t *info, size_t count)
  993. {
  994. cdf_timestamp_t tp;
  995. struct timespec ts;
  996. char buf[64];
  997. size_t i;
  998. for (i = 0; i < count; i++) {
  999. cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
  1000. (void)fprintf(stderr, "%zu) %s: ", i, buf);
  1001. switch (info[i].pi_type) {
  1002. case CDF_SIGNED16:
  1003. (void)fprintf(stderr, "signed 16 [%hd]\n",
  1004. info[i].pi_s16);
  1005. break;
  1006. case CDF_SIGNED32:
  1007. (void)fprintf(stderr, "signed 32 [%d]\n",
  1008. info[i].pi_s32);
  1009. break;
  1010. case CDF_UNSIGNED32:
  1011. (void)fprintf(stderr, "unsigned 32 [%u]\n",
  1012. info[i].pi_u32);
  1013. break;
  1014. case CDF_LENGTH32_STRING:
  1015. (void)fprintf(stderr, "string %u [%.*s]\n",
  1016. info[i].pi_str.s_len,
  1017. info[i].pi_str.s_len, info[i].pi_str.s_buf);
  1018. break;
  1019. case CDF_FILETIME:
  1020. tp = info[i].pi_tp;
  1021. if (tp < 1000000000000000LL) {
  1022. cdf_print_elapsed_time(buf, sizeof(buf), tp);
  1023. (void)fprintf(stderr, "timestamp %s\n", buf);
  1024. } else {
  1025. cdf_timestamp_to_timespec(&ts, tp);
  1026. (void)fprintf(stderr, "timestamp %s",
  1027. ctime(&ts.tv_sec));
  1028. }
  1029. break;
  1030. case CDF_CLIPBOARD:
  1031. (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32);
  1032. break;
  1033. default:
  1034. DPRINTF(("Don't know how to deal with %x\n",
  1035. info[i].pi_type));
  1036. break;
  1037. }
  1038. }
  1039. }
  1040. void
  1041. cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst)
  1042. {
  1043. char buf[128];
  1044. cdf_summary_info_header_t ssi;
  1045. cdf_property_info_t *info;
  1046. size_t count;
  1047. (void)&h;
  1048. if (cdf_unpack_summary_info(sst, &ssi, &info, &count) == -1)
  1049. return;
  1050. (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order);
  1051. (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff,
  1052. ssi.si_os_version >> 8);
  1053. (void)fprintf(stderr, "Os %d\n", ssi.si_os);
  1054. cdf_print_classid(buf, sizeof(buf), &ssi.si_class);
  1055. (void)fprintf(stderr, "Class %s\n", buf);
  1056. (void)fprintf(stderr, "Count %d\n", ssi.si_count);
  1057. cdf_dump_property_info(info, count);
  1058. free(info);
  1059. }
  1060. #endif
  1061. #ifdef TEST
  1062. int
  1063. main(int argc, char *argv[])
  1064. {
  1065. int i;
  1066. cdf_header_t h;
  1067. cdf_sat_t sat, ssat;
  1068. cdf_stream_t sst, scn;
  1069. cdf_dir_t dir;
  1070. cdf_info_t info;
  1071. if (argc < 2) {
  1072. (void)fprintf(stderr, "Usage: %s <filename>\n", getprogname());
  1073. return -1;
  1074. }
  1075. info.i_buf = NULL;
  1076. info.i_len = 0;
  1077. for (i = 1; i < argc; i++) {
  1078. if ((info.i_fd = open(argv[1], O_RDONLY)) == -1)
  1079. err(1, "Cannot open `%s'", argv[1]);
  1080. if (cdf_read_header(&info, &h) == -1)
  1081. err(1, "Cannot read header");
  1082. #ifdef CDF_DEBUG
  1083. cdf_dump_header(&h);
  1084. #endif
  1085. if (cdf_read_sat(&info, &h, &sat) == -1)
  1086. err(1, "Cannot read sat");
  1087. #ifdef CDF_DEBUG
  1088. cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h));
  1089. #endif
  1090. if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1)
  1091. err(1, "Cannot read ssat");
  1092. #ifdef CDF_DEBUG
  1093. cdf_dump_sat("SSAT", &h, &ssat, CDF_SHORT_SEC_SIZE(&h));
  1094. #endif
  1095. if (cdf_read_dir(&info, &h, &sat, &dir) == -1)
  1096. err(1, "Cannot read dir");
  1097. if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1)
  1098. err(1, "Cannot read short stream");
  1099. #ifdef CDF_DEBUG
  1100. cdf_dump_stream(&h, &sst);
  1101. #endif
  1102. #ifdef CDF_DEBUG
  1103. cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir);
  1104. #endif
  1105. if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
  1106. &scn) == -1)
  1107. err(1, "Cannot read summary info");
  1108. #ifdef CDF_DEBUG
  1109. cdf_dump_summary_info(&h, &scn);
  1110. #endif
  1111. (void)close(info.i_fd);
  1112. }
  1113. return 0;
  1114. }
  1115. #endif