1 /*
2 Copyright (C) 2009 Justin Karneges
3
4 This file is free software; unlimited permission is given to copy and/or
5 distribute it, with or without modifications, as long as this notice is
6 preserved.
7 */
8
9 #include "embed.h"
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14
15 #if defined(WIN32) || defined(_WIN32)
16 # define QC_OS_WIN
17 # include <windows.h>
18 #endif
19
20 // this hash stuff is total overkill but i was bored
21
22 static const char *BLOCKSIG_ID = "QCONF_CONFIGWIN_BLOCKSIG";
23
calc_hash(const char * in,int len)24 static unsigned int calc_hash(const char *in, int len)
25 {
26 unsigned int x;
27 int n;
28
29 x = 0;
30 for(n = 0; n < len; ++n)
31 {
32 x <<= 4;
33 x ^= (unsigned int)in[n];
34 }
35 return x;
36 }
37
38 // result should be "QCONF_CONFIGWIN_BLOCKSIG_68b7e7d7"
39 //
40 // the basic idea here is that we use this string as a marker for our
41 // appended data section, but we don't want to include this actual
42 // string in our code otherwise it could be misinterpretted as the
43 // marker
blocksig()44 static char *blocksig()
45 {
46 char *blocksig_data;
47 int idlen;
48 unsigned int hash;
49 char hashstr[9];
50 int n;
51
52 idlen = strlen(BLOCKSIG_ID);
53 hash = calc_hash(BLOCKSIG_ID, idlen);
54 blocksig_data = (char *)malloc(idlen + 1 + 8 + 1);
55 memcpy(blocksig_data, BLOCKSIG_ID, idlen);
56 blocksig_data[idlen] = '_';
57 sprintf(hashstr, "%08x", hash);
58 for(n = 0; n < 8; ++n)
59 blocksig_data[idlen + 1 + n] = hashstr[n];
60 blocksig_data[idlen + 1 + 8] = 0;
61
62 return blocksig_data;
63 }
64
app_file_path(const char * argv0)65 static char *app_file_path(const char *argv0)
66 {
67 #ifdef QC_OS_WIN
68 char module_name[MAX_PATH+1];
69 (void)argv0;
70 GetModuleFileNameA(0, module_name, MAX_PATH);
71 module_name[MAX_PATH] = 0;
72 return strdup(module_name);
73 #else
74 return strdup(argv0);
75 #endif
76 }
77
find_partial(const char * in,int in_size,const char * sub,int sub_size)78 static int find_partial(const char *in, int in_size, const char *sub, int sub_size)
79 {
80 int n;
81 int size;
82
83 for(n = 0; n < in_size; ++n)
84 {
85 if(sub_size < in_size - n)
86 size = sub_size;
87 else
88 size = in_size - n;
89 if(memcmp(in + n, sub, size) == 0)
90 return n;
91 }
92
93 return -1;
94 }
95
seek_string(FILE * fp,const char * str)96 static int seek_string(FILE *fp, const char *str)
97 {
98 char block[8192];
99 int str_at;
100 int str_len;
101 int size;
102 int ret;
103 int pos;
104
105 str_len = strlen(str);
106 str_at = 0;
107 pos = ftell(fp);
108 while(!feof(fp))
109 {
110 size = fread(block, 1, 8192, fp);
111 if(size < 1)
112 break;
113
114 ret = find_partial(block, size, str + str_at, str_len - str_at);
115 if(ret != -1)
116 {
117 if(str_at + (size - ret) >= str_len)
118 {
119 if(fseek(fp, pos + ret - str_at + str_len, SEEK_SET) != 0)
120 return 0;
121
122 return 1;
123 }
124 else
125 str_at += (size - ret);
126 }
127
128 pos += size;
129 }
130
131 return 0;
132 }
133
read32(const unsigned char * in)134 unsigned int read32(const unsigned char *in)
135 {
136 unsigned int out = in[0];
137 out <<= 8;
138 out += in[1];
139 out <<= 8;
140 out += in[2];
141 out <<= 8;
142 out += in[3];
143 return out;
144 }
145
146 // format is:
147 // <blocksig> <uint32 size> <data....>
148
import_data(const char * argv0,const char * sig,unsigned char ** ret_data,unsigned int * ret_size)149 static int import_data(const char *argv0, const char *sig, unsigned char **ret_data, unsigned int *ret_size)
150 {
151 char *fname;
152 FILE *fp;
153 int ret;
154 unsigned char buf[4];
155 unsigned int size;
156 unsigned char *data;
157
158 fname = app_file_path(argv0);
159 if(!fname)
160 return 0;
161 fp = fopen(fname, "rb");
162 if(!fp)
163 return 0;
164 if(!seek_string(fp, sig))
165 return 0;
166 ret = fread(buf, 4, 1, fp);
167 if(ret < 1)
168 return 0;
169 size = read32(buf);
170 data = (unsigned char *)malloc(size);
171 if(!data)
172 return 0;
173 ret = fread(data, size, 1, fp);
174 if(ret < 1)
175 {
176 free(data);
177 return 0;
178 }
179 fclose(fp);
180
181 *ret_data = data;
182 *ret_size = size;
183 return 1;
184 }
185
embed_get_data(const char * argv0,unsigned char ** ret_data,unsigned int * ret_size)186 int embed_get_data(const char *argv0, unsigned char **ret_data, unsigned int *ret_size)
187 {
188 char *sig;
189 int ret;
190
191 sig = blocksig();
192 //printf("%s\n", sig);
193 ret = import_data(argv0, sig, ret_data, ret_size);
194 free(sig);
195
196 return ret;
197 }
198