00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <ctype.h>
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 #include <limits.h>
00018 #ifdef HAVE_LIBOPENSSL
00019 #include <openssl/evp.h>
00020 #endif
00021 #include <klone/klone.h>
00022 #include <klone/translat.h>
00023 #include <klone/parser.h>
00024 #include <klone/utils.h>
00025 #include <klone/os.h>
00026 #include <klone/io.h>
00027 #include <klone/codec.h>
00028 #include <klone/codecs.h>
00029
00030 #define tr_err(...) \
00031 do { con_p_ctx(p); con_err(__VA_ARGS__); } while(0)
00032 #define tr_err_if(expr) \
00033 do { if( (expr) ) { con_p_ctx(p); con("%s", #expr); goto err; } } while(0)
00034 #define tr_err_ifm(expr, ...) \
00035 do { if( (expr) ) { con_p_ctx(p); con(__VA_ARGS__); goto err; } } while(0)
00036
00037 static int preprocess(io_t *in, io_t *out);
00038
00039
00040 static void con_p_ctx(parser_t *p)
00041 {
00042 char fn[U_FILENAME_MAX];
00043
00044 dbg_err_if(io_name_get(p->in, fn, U_FILENAME_MAX));
00045
00046
00047 fprintf(stderr, "[%s:%d]: error: ", fn, p->code_line);
00048 err:
00049 return;
00050 }
00051
00052 static int is_a_script(const char *filename)
00053 {
00054 static const char *script_ext[] = {
00055 ".klone", ".kl1", ".klc",
00056 ".klx",
00057 NULL
00058 };
00059 const char **ext;
00060
00061 dbg_return_if(filename == NULL, 0);
00062
00063
00064 for(ext = script_ext; *ext; ++ext)
00065 {
00066
00067 if(u_match_ext(filename, *ext))
00068 return 1;
00069 }
00070 return 0;
00071 }
00072
00073 static int process_directive_include(parser_t *p, char *inc_file)
00074 {
00075 enum { BUFSZ = 4096 };
00076 char buf[U_FILENAME_MAX], *pc;
00077 char file[U_FILENAME_MAX];
00078 io_t *io = NULL;
00079
00080 dbg_return_if (p == NULL, ~0);
00081 dbg_return_if (inc_file == NULL, ~0);
00082
00083 dbg_err_if(io_name_get(p->in, file, U_FILENAME_MAX));
00084 dbg_err_if(io_name_get(p->in, buf, U_FILENAME_MAX));
00085
00086
00087 dbg_err_if((pc = strrchr(buf, '/')) == NULL);
00088 ++pc; *pc = 0;
00089
00090 dbg_err_if(strlen(buf) + strlen(inc_file) >= BUFSZ);
00091
00092 strcat(buf, inc_file);
00093
00094
00095 tr_err_ifm(u_file_open(buf, O_RDONLY, &io),
00096 "unable to open included file %s", buf);
00097
00098 dbg_err_if(io_printf(p->out, "<%% #line 1 \"%s\" \n %%>", buf));
00099
00100 dbg_err_if(preprocess(io, p->out));
00101
00102 dbg_err_if(io_printf(p->out, "<%% #line %d \"%s\" \n %%>",
00103 p->code_line, file));
00104
00105 io_free(io);
00106
00107 return 0;
00108 err:
00109 if(io)
00110 io_free(io);
00111 return ~0;
00112 }
00113
00114 static int process_directive(parser_t *p, char *buf)
00115 {
00116 char *tok, *pp;
00117
00118 dbg_return_if (p == NULL, ~0);
00119 dbg_return_if (buf == NULL, ~0);
00120
00121
00122 tr_err_ifm((tok = strtok_r(buf, " \t", &pp)) == NULL,
00123 "bad or missing preprocessor command");
00124
00125 if(strcasecmp(tok, "include") == 0)
00126 {
00127
00128 tr_err_ifm((tok = strtok_r(NULL, " \t\"", &pp)) == NULL,
00129 "bad or missing include filename");
00130
00131 dbg_err_if(process_directive_include(p, tok));
00132 } else {
00133 tr_err("unknown preprocessor directive: %s", tok);
00134 }
00135
00136 return 0;
00137 err:
00138 return ~0;
00139 }
00140
00141 static int parse_directive(parser_t *p, void *arg, const char *buf, size_t sz)
00142 {
00143 enum { LINE_BUFSZ = 1024 };
00144 char line[LINE_BUFSZ];
00145 io_t *io = NULL;
00146
00147 u_unused_args(arg);
00148
00149 dbg_return_if (p == NULL, ~0);
00150 dbg_return_if (buf == NULL, ~0);
00151
00152 dbg_err_if(io_mem_create((char*)buf, sz, 0, &io));
00153
00154 while(io_gets(io, line, LINE_BUFSZ) > 0)
00155 dbg_err_if(process_directive(p, line));
00156
00157 io_free(io);
00158
00159 return 0;
00160 err:
00161 if(io)
00162 io_free(io);
00163 return ~0;
00164 }
00165
00166 static int cb_pre_html_block(parser_t *p, void *arg, const char *buf, size_t sz)
00167 {
00168 u_unused_args(arg);
00169
00170 dbg_err_if (p == NULL);
00171
00172 dbg_err_if(io_write(p->out, buf, sz) < 0);
00173
00174 return 0;
00175 err:
00176 return ~0;
00177 }
00178
00179 static int cb_pre_code_block(parser_t *p, int cmd, void *arg, const char *buf,
00180 size_t sz)
00181 {
00182 char file[U_FILENAME_MAX];
00183
00184 dbg_err_if (p == NULL);
00185
00186 if(cmd == '@')
00187 {
00188 dbg_err_if(parse_directive(p, arg, buf, sz));
00189 } else {
00190 dbg_err_if(io_name_get(p->in, file, U_FILENAME_MAX));
00191 if(cmd != '=')
00192 dbg_err_if(io_printf(p->out, "<%%%c #line %d \"%s\" \n%%>",
00193 (cmd == 0 ? ' ' : cmd), p->code_line, file));
00194 else
00195 dbg_err_if(io_printf(p->out, "<%% #line %d \"%s\" \n%%>",
00196 p->code_line, file));
00197
00198 dbg_err_if(io_printf(p->out, "<%%%c ", (cmd == 0 ? ' ' : cmd)) < 0);
00199 dbg_err_if(io_write(p->out, buf, sz) < 0);
00200 dbg_err_if(io_printf(p->out, "%%>") < 0);
00201 }
00202 return 0;
00203 err:
00204 return ~0;
00205 }
00206
00207 static int preprocess(io_t *in, io_t *out)
00208 {
00209 parser_t *p = NULL;
00210
00211
00212 dbg_err_if(parser_create(&p));
00213
00214 parser_set_io(p, in, out);
00215
00216 parser_set_cb_code(p, cb_pre_code_block);
00217 parser_set_cb_html(p, cb_pre_html_block);
00218
00219 dbg_err_if(parser_run(p));
00220
00221 parser_free(p);
00222
00223 return 0;
00224 err:
00225 if(p)
00226 parser_free(p);
00227 return ~0;
00228 }
00229
00230 int translate(trans_info_t *pti)
00231 {
00232 io_t *in = NULL, *out = NULL, *tmp = NULL;
00233 codec_t *gzip = NULL, *aes = NULL;
00234 char tname[U_FILENAME_MAX];
00235
00236 dbg_return_if (pti == NULL, ~0);
00237
00238
00239 con_err_ifm(u_file_open(pti->file_in, O_RDONLY, &in),
00240 "unable to open %s", pti->file_in);
00241
00242
00243 con_err_ifm(u_file_open(pti->file_out, O_CREAT | O_TRUNC | O_WRONLY, &out),
00244 "unable to open %s", pti->file_out);
00245
00246
00247 if(is_a_script(pti->file_in))
00248 {
00249
00250 con_err_if(u_tmpfile_open(&tmp));
00251
00252
00253 dbg_err_if(preprocess(in, tmp));
00254
00255
00256 io_seek(tmp, 0);
00257
00258
00259 dbg_err_if(translate_script_to_c(tmp, out, pti));
00260
00261
00262 dbg_err_if(io_name_get(tmp, tname, U_FILENAME_MAX));
00263
00264
00265 io_free(tmp);
00266
00267
00268 unlink(tname);
00269 } else {
00270
00271 #ifdef HAVE_LIBZ
00272 if(pti->comp)
00273 {
00274
00275 dbg_err_if(codec_gzip_create(GZIP_COMPRESS, &gzip));
00276 dbg_err_if(io_codec_add_tail(in, gzip));
00277 gzip = NULL;
00278 }
00279 #endif
00280 #ifdef HAVE_LIBOPENSSL
00281
00282 if(pti->encrypt)
00283 {
00284
00285 dbg_err_if(codec_cipher_create(CIPHER_ENCRYPT, EVP_aes_256_cbc(),
00286 pti->key, NULL, &aes));
00287 dbg_err_if(io_codec_add_tail(in, aes));
00288 aes = NULL;
00289 }
00290 #endif
00291 dbg_err_if(translate_opaque_to_c(in, out, pti));
00292 }
00293
00294 io_free(in);
00295 io_free(out);
00296
00297 return 0;
00298 err:
00299 if(pti && strlen(pti->emsg))
00300 con("%s", pti->emsg);
00301 if(gzip)
00302 codec_free(gzip);
00303 if(tmp)
00304 io_free(tmp);
00305 if(in)
00306 io_free(in);
00307 if(out)
00308 io_free(out);
00309 return ~0;
00310 }