new fortune, plus site avenger mods
[feisty_meow.git] / nucleus / applications / bundler / common_bundle.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : common bundler definitions                                        *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 2007-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include "common_bundle.h"
16
17 #include <basis/byte_array.h>
18 #include <basis/contracts.h>
19 #include <filesystem/byte_filer.h>
20 #include <filesystem/file_time.h>
21 #include <structures/object_packers.h>
22 #include <structures/set.h>
23
24 using namespace basis;
25 using namespace filesystem;
26 using namespace structures;
27
28 manifest_chunk::~manifest_chunk()
29 {}
30
31 int manifest_chunk::packed_filetime_size()
32 {
33   static file_time hidden_comparison_object;
34   return hidden_comparison_object.packed_size();
35 }
36
37 void manifest_chunk::pack(byte_array &target) const
38 {
39   structures::obscure_attach(target, _size);
40   _payload.pack(target);
41   structures::attach(target, _flags);
42   _parms.pack(target);
43   _keywords.pack(target);
44   target += c_filetime;
45 }
46
47 bool manifest_chunk::unpack(byte_array &source)
48 {
49   if (!structures::obscure_detach(source, _size)) return false;
50   if (!_payload.unpack(source)) return false;
51   if (!structures::detach(source, _flags)) return false;
52   if (!_parms.unpack(source)) return false;
53   if (!_keywords.unpack(source)) return false;
54   if (source.length() < 8) return false;
55   c_filetime = source.subarray(0, 7);
56   source.zap(0, 7);
57   return true;
58 }
59
60 bool manifest_chunk::read_an_int(byte_filer &bundle, un_int &found)
61 {
62   FUNCDEF("read_an_int");
63   byte_array temp;
64   if (bundle.read(temp, sizeof(int)) != sizeof(int)) return false;
65   if (!structures::detach(temp, found)) return false;
66   return true;
67 }
68
69 bool manifest_chunk::read_an_obscured_int(byte_filer &bundle, un_int &found)
70 {
71   FUNCDEF("read_an_obscured_int");
72   byte_array temp;
73   if (bundle.read(temp, 2 * sizeof(int)) != 2 * sizeof(int)) return false;
74   if (!structures::obscure_detach(temp, found)) return false;
75   return true;
76 }
77
78 bool manifest_chunk::read_a_filetime(byte_filer &bundle, byte_array &found)
79 {
80   FUNCDEF("read_a_filetime");
81   byte_array temp;
82   // the trick below only works because we know we have a constant sized packed version
83   // for the file time.
84   if (bundle.read(temp, packed_filetime_size()) != packed_filetime_size()) return false;
85   found = temp;
86   return true;
87 }
88
89 astring manifest_chunk::read_a_string(byte_filer &bundle)
90 {
91   FUNCDEF("read_a_string");
92   astring found;
93   byte_array temp;
94   // read in the zero-terminated character string.
95   while (!bundle.eof()) {
96     // read a single byte out of the file.
97     if (bundle.read(temp, 1) <= 0)
98       break;
99     if (temp[0]) {
100       // add the byte to the string we're accumulating.
101       found += temp[0];
102     } else {
103       // this string is done now.
104       break;
105     }
106   }
107   return found;
108 }
109
110 bool manifest_chunk::read_manifest(byte_filer &bundle, manifest_chunk &curr)
111 {
112   curr._size = 0;
113   bool worked = read_an_obscured_int(bundle, curr._size);
114   if (!worked)
115     return false;
116   byte_array temp;
117   curr._payload = read_a_string(bundle);
118   if (!curr._payload) return false;  
119   worked = read_an_int(bundle, curr._flags);
120   if (!worked)
121     return false;
122   curr._parms = read_a_string(bundle);
123     // it's valid for the _parms to be empty.
124 //if (curr._parms.length()) { printf("parms len=%d are: \"%s\"\n", curr._parms.length(), curr._parms.s()); }
125   // now get the keywords list, if it exists.
126   un_int key_elems = 0;  // number of keywords.
127   worked = read_an_obscured_int(bundle, key_elems);  // get number of elements.
128   if (!worked)
129     return false;
130   curr._keywords.reset();
131   for (int i = 0; i < (int)key_elems; i++) {
132     astring found = read_a_string(bundle);
133     if (!found) return false;  // not allowed an empty keyword.
134     curr._keywords += found;
135   }
136   worked = read_a_filetime(bundle, curr.c_filetime);
137   return worked;
138 }
139