source: main/trunk/greenstone2/runtime-src/src/recpt/gtiaction.cpp@ 28913

Last change on this file since 28913 was 28913, checked in by ak19, 10 years ago

6th commit for security of cgiargs. Looked over all occurrences of setmacro in *action.cpp files

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 34.1 KB
Line 
1/**********************************************************************
2 *
3 * gtiaction.cpp --
4 * Copyright (C) 2005 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26
27#include "gsdl_modules_cfg.h"
28#ifdef GSDL_USE_GTI_ACTION
29
30
31#include <expat.h>
32#include <stdio.h>
33#include <sys/utsname.h>
34#include "gtiaction.h"
35#include "cgiutils.h"
36#include "fileutil.h"
37#include "gsdlunicode.h"
38
39
40
41gtiaction::gtiaction()
42{
43 cgiarginfo arg_ainfo;
44
45 arg_ainfo.shortname = "tlc";
46 arg_ainfo.longname = "translation target language code";
47 arg_ainfo.multiplechar = true;
48 arg_ainfo.multiplevalue = false;
49 arg_ainfo.defaultstatus = cgiarginfo::weak;
50 arg_ainfo.savedarginfo = cgiarginfo::must;
51 argsinfo.addarginfo (&cerr, arg_ainfo);
52
53 arg_ainfo.shortname = "tfk";
54 arg_ainfo.longname = "translation file key";
55 arg_ainfo.multiplechar = true;
56 arg_ainfo.multiplevalue = false;
57 arg_ainfo.defaultstatus = cgiarginfo::weak;
58 arg_ainfo.savedarginfo = cgiarginfo::must;
59 argsinfo.addarginfo (&cerr, arg_ainfo);
60
61 arg_ainfo.shortname = "ncpp";
62 arg_ainfo.longname = "number of chunks per page";
63 arg_ainfo.multiplechar = true;
64 arg_ainfo.multiplevalue = false;
65 arg_ainfo.defaultstatus = cgiarginfo::weak;
66 arg_ainfo.argdefault = "1";
67 arg_ainfo.savedarginfo = cgiarginfo::must;
68 argsinfo.addarginfo (&cerr, arg_ainfo);
69}
70
71
72
73gtiaction::~gtiaction()
74{
75 delete[] set_gsdlhome_cstr;
76 delete[] set_gsdlos_cstr;
77}
78
79
80
81bool gtiaction::init (ostream& /*logout*/)
82{
83 // Set GSDLHOME and GSDLOS environment variables
84 text_t set_gsdlhome = "GSDLHOME=" + gsdlhome;
85 text_t set_gsdlos = "GSDLOS=";
86
87#if defined (__WIN32__)
88 set_gsdlos += "windows";
89#else
90 struct utsname *buf = new struct utsname();
91 if (uname(buf) == -1) {
92 // uname failed, so this must be linux
93 set_gsdlos += "linux";
94 }
95 else {
96 text_t gsdlos = buf->sysname;
97 lc(gsdlos);
98 set_gsdlos += gsdlos;
99 }
100 delete buf;
101#endif
102
103 // These will be cleaned up in the destructor
104 set_gsdlhome_cstr = set_gsdlhome.getcstr();
105 set_gsdlos_cstr = set_gsdlos.getcstr();
106 putenv(set_gsdlhome_cstr);
107 putenv(set_gsdlos_cstr);
108
109 return true;
110}
111
112
113
114bool gtiaction::check_cgiargs(cgiargsinfoclass& /*argsinfo*/, cgiargsclass& args,
115 recptprotolistclass* /*protos*/, ostream& logout)
116{
117 // Authenticate the user, except for the "home" and "lang" pages
118 if (args["p"] != "home" && args["p"] != "lang" && args["p"] != "status") {
119 args["uan"] = 1;
120 args["ug"] = "langadmin_" + args["tlc"];
121 }
122
123 return true;
124}
125
126
127
128bool gtiaction::do_action(cgiargsclass& args, recptprotolistclass* /*protos*/,
129 browsermapclass* /*browsers*/, displayclass& disp,
130 outconvertclass& outconvert, ostream& textout,
131 ostream& logout)
132{
133 // Special case for producing Excel spreadsheets, as these are downloaded
134 if (args["p"] == "excel") {
135 return produce_excel_spreadsheet(args, logout);
136 }
137
138 textout << outconvert << disp << ("_gti:header_\n") << ("_gti:content_\n") << ("_gti:footer_\n");
139 return true;
140}
141
142
143
144void gtiaction::get_cgihead_info(cgiargsclass& args, recptprotolistclass* /*protos*/,
145 response_t& response, text_t& response_data,
146 ostream& logout)
147{
148 // Special case for producing Excel spreadsheets, as these are downloaded
149 if (args["p"] == "excel") {
150 printf("Content-Disposition: attachment; filename=\"Greenstone-%s-%s.xml\"\n", args["tlc"].getcstr(), args["tfk"].getcstr());
151 response = content;
152 response_data = "text/xml";
153 return;
154 }
155
156 response = content;
157 response_data = "text/html";
158}
159
160
161
162void gtiaction::define_internal_macros(displayclass& disp, cgiargsclass& args,
163 recptprotolistclass* protos, ostream& logout)
164{
165 // logout << endl << "Arguments: " << args << endl;
166 logout << endl << "CGI arg p: " << args["p"] << endl;
167
168 // For some reason this must be done as well as setting the macro in gti.dm
169 // is that still true??
170 disp.setmacro("preflink", displayclass::defaultpackage, "_gti:preflink_");
171
172 // Define the page content for the GTI home page
173 if (args["p"] == "home") {
174 define_gti_home_page(disp, args, logout);
175 return;
176 }
177
178 // Define the page content for the GTI language page
179 if (args["p"] == "lang") {
180 define_gti_lang_page(disp, args, logout);
181 return;
182 }
183
184 // Define the page content for the GTI search page
185 if (args["p"] == "find") {
186 define_gti_find_page(disp, args, logout);
187 return;
188 }
189
190 // Define the page content for the GTI offline page
191 if (args["p"] == "offline") {
192 define_gti_offline_page(disp, args, logout);
193 return;
194 }
195
196 // Define the page content for the GTI view status page
197 if (args["p"] == "status") {
198 define_gti_status_page(disp, args, logout);
199 return;
200 }
201
202 // Process user translations
203 if (args["p"] == "submit") {
204 process_gti_submissions(disp, args, logout, true);
205 }
206
207 if (args["p"] == "glihelp") {
208 produce_glihelp_zipfile(disp, args, logout);
209 }
210
211 // Define the page content for the GTI core pages (containing the translation input forms)
212 define_gti_core_page(disp, args, logout);
213}
214
215
216
217void gtiaction::define_gti_home_page(displayclass& disp, cgiargsclass& args, ostream& logout)
218{
219 disp.setmacro("gtiformcontent", "gti", "_gti:gtihome_");
220
221 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
222
223 // Get the languages specified in the main.cfg file, and put them into a map to sort by name
224 text_tmap gti_languages_name_code_mapping;
225 languageinfo_tmap::const_iterator loaded_language = loaded_languages.begin();
226 while (loaded_language != loaded_languages.end()) {
227 // English is not a valid GTI target language, since it is the source language
228 if (loaded_language->first != "en") {
229 gti_languages_name_code_mapping[loaded_language->second.longname] = loaded_language->first;
230 }
231 ++loaded_language;
232 }
233
234 // Set the gtitlcselection macro
235 text_t gti_tlc_selection = "<select name=\"tlc\">\n";
236 text_tmap::iterator gti_language = gti_languages_name_code_mapping.begin();
237 while (gti_language != gti_languages_name_code_mapping.end()) {
238 gti_tlc_selection += "<option value=\"" + gti_language->second + "\">" + gti_language->first + "</option>\n";
239 ++gti_language;
240 }
241 gti_tlc_selection += "</select>";
242 disp.setmacro("gtitlcselection", "gti", gti_tlc_selection);
243}
244
245
246
247void gtiaction::define_gti_lang_page(displayclass& disp, cgiargsclass& args, ostream& logout)
248{
249 // Get the target language code from the CGI arguments
250 text_t target_language_code = args["tlc"];
251
252 disp.setmacro("gtiformcontent", "gti", "_gti:gtilang_");
253
254 // Send a request to gti.pl to get the valid translation files
255 text_t gti_arguments = "get-language-status " + target_language_code;
256 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
257 if (gti_response.error_message != "") {
258 // An error has occurred
259 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
260 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
261 return;
262 }
263
264 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
265 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
266
267 // Set the gtitfkselection macro
268 text_t gti_tfk_selection = "<table>";
269 text_tmap::iterator translation_file = gti_response.translation_files_index_to_key_mapping.begin();
270 while (translation_file != gti_response.translation_files_index_to_key_mapping.end()) {
271 text_t translation_file_key = translation_file->second;
272
273 gti_tfk_selection += "<tr><td>";
274 gti_tfk_selection += "<input type=\"radio\" name=\"tfk\" value=\"" + translation_file_key + "\"></td>\n";
275 gti_tfk_selection += "<td>_textgti" + translation_file_key + "_</td></tr>\n";
276
277 text_t num_chunks_translated = gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key];
278 text_t num_chunks_requiring_translation = gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key];
279 text_t num_chunks_requiring_updating = gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key];
280 gti_tfk_selection += "<tr><td></td><td>_gtitranslationfilestatus_(" + num_chunks_translated + "," + num_chunks_requiring_translation + "," + num_chunks_requiring_updating + ")</td></tr>\n";
281 ++translation_file;
282 }
283 gti_tfk_selection += "</table>";
284 disp.setmacro("gtitfkselection", "gti", gti_tfk_selection);
285}
286
287
288
289void gtiaction::define_gti_status_page(displayclass& disp, cgiargsclass& args, ostream& logout)
290{
291 disp.setmacro("gtiformcontent", "gti", "_gti:gtistatus_");
292
293 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
294
295 // Get the languages specified in the main.cfg file, and put them into a map to sort by name
296 text_tmap gti_languages_name_code_mapping;
297 languageinfo_tmap::const_iterator loaded_language = loaded_languages.begin();
298 while (loaded_language != loaded_languages.end()) {
299 // English is not a valid GTI target language, since it is the source language
300 if (loaded_language->first != "en") {
301 gti_languages_name_code_mapping[loaded_language->second.longname] = loaded_language->first;
302 }
303 ++loaded_language;
304 }
305
306 // Get the languages, for each language, send a request to gti.pl to get the valid translation files and the current status for each file
307 text_t gti_status_table = "<table class=\"status\">\n";
308 text_tmap::iterator gti_language = gti_languages_name_code_mapping.begin();
309 bool first_lang = true;
310 while (gti_language != gti_languages_name_code_mapping.end()) {
311 // Send a request to gti.pl to get the valid translation files
312 text_t gti_arguments = "get-language-status " + gti_language->second;
313 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
314 if (gti_response.error_message != "") {
315 // An error has occurred
316 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
317 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
318 return;
319 }
320
321 text_tmap::iterator translation_file = gti_response.translation_files_index_to_key_mapping.begin();
322
323 text_t lang_status_temp = "<tr><td class=\"first\">" + gti_language->first + "</td>\n";
324 text_t files_temp = "<tr><th class=\"status\">_textgtilanguage_</th>\n";
325 text_t number_of_strings_temp = "<tr><td class=\"first\"><b>_textgtitotalnumberoftranslations_</b></td>\n";
326
327 while (translation_file != gti_response.translation_files_index_to_key_mapping.end()) {
328 text_t translation_file_key = translation_file->second;
329
330 text_t num_chunks_translated = gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key];
331 text_t num_chunks_requiring_translation = gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key];
332 text_t num_chunks_requiring_updating = gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key];
333
334 lang_status_temp += "<td class=\"status\">";
335 if(num_chunks_translated.getint() > 0){
336 lang_status_temp += "<div class=\"nowrap\"><div class=\"done\">";
337 lang_status_temp += num_chunks_translated+"</div><div class=\"plus\">+</div><div class=\"update\">";
338 lang_status_temp += num_chunks_requiring_updating+"</div><div class=\"plus\">+</div><div class=\"todo\">";
339 lang_status_temp += num_chunks_requiring_translation+"</div></div>";
340 }
341 lang_status_temp += "</td>\n";
342
343
344 //lang_status_temp += "<td valign=\"top\" nowrap>_gtitranslationfilestatus2_(" + num_chunks_translated + "," + num_chunks_requiring_translation + "," + num_chunks_requiring_updating + ")</td>";
345
346 // List the file names as the first row of the status table
347 // Add up number of strings need to be translate in each file, as the second line of the status table
348 if (first_lang) {
349 files_temp += "<th class=\"status\">_textgti" + translation_file_key + "_</th>\n";
350 int int_number_of_strings = num_chunks_translated.getint() + num_chunks_requiring_translation.getint();
351 number_of_strings_temp += "<td class=\"status\"><b>";
352 number_of_strings_temp.appendint(int_number_of_strings);
353 number_of_strings_temp += "</b></td>\n";
354 }
355 ++translation_file;
356 }
357
358 if(first_lang) {
359 gti_status_table += files_temp + "</tr>" + number_of_strings_temp + "</tr>";
360 first_lang = false;
361 }
362
363 gti_status_table += lang_status_temp + "</tr>";
364 ++gti_language;
365 }
366 gti_status_table += "\n</table>";
367 disp.setmacro("gtistatustable", "gti", gti_status_table);
368}
369
370
371
372void gtiaction::define_gti_find_page(displayclass& disp, cgiargsclass& args, ostream& logout)
373{
374 // Get the target language code and file to translate from the CGI arguments
375 text_t target_language_code = args["tlc"];
376 text_t translation_file_key = args["tfk"];
377 text_t query_string = to_utf8(args["q"]);
378
379 // Process user corrections
380 if (args["sp"] != "") {
381 process_gti_submissions(disp, args, logout, false);
382 }
383
384 disp.setmacro("gtiformcontent", "gti", "_gti:gtifind_");
385
386 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
387 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
388 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
389 disp.setmacro("gtitranslationfiledescHtmlsafe", "gti", "_gti:textgti" + encodeForHTML(translation_file_key) + "_");
390
391 if (query_string == "") {
392 // No query, so no search results
393 disp.setmacro("gtifindformcontent", "gti", "");
394 return;
395 }
396
397 // Display text right to left if target language is Arabic or Farsi or Urdu
398 if (target_language_code == "ar" || target_language_code == "fa" || target_language_code == "ur") {
399 disp.setmacro("gtitextdirection", "gti", "rtl");
400 }
401 else {
402 disp.setmacro("gtitextdirection", "gti", "ltr");
403 }
404
405 // Send a request to gti.pl to get the valid translation files
406 logout << "Query argument: " << query_string << endl;
407 text_t gti_arguments = "search-chunks " + target_language_code + " " + translation_file_key + " " + query_string;
408 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
409 if (gti_response.error_message != "") {
410 // An error has occurred
411 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
412 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
413 return;
414 }
415
416 disp.setmacro("gtinumchunksmatchingquery", "gti", gti_response.num_chunks_matching_query);
417
418 // Loop through the chunks returned, displaying them on the page
419 text_t gti_find_form_content = "_gtifindformheader_\n";
420 text_tmap::iterator chunk_key_iterator = gti_response.target_file_chunks_key_to_text_mapping.begin();
421 while (chunk_key_iterator != gti_response.target_file_chunks_key_to_text_mapping.end()) {
422 text_t chunk_key = chunk_key_iterator->first;
423
424 // Need to escape any underscores in the chunk key to show it correctly on the page
425 text_t chunk_key_escaped = escape_all(chunk_key, '_');
426
427 // Need to escape any backslashes, underscores, commas, parentheses, and single quotes in the chunk text
428 text_t target_file_chunk_text = gti_response.target_file_chunks_key_to_text_mapping[chunk_key];
429 text_t target_file_chunk_text_escaped = escape_all(target_file_chunk_text, '\\');
430 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '_');
431 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ',');
432 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '(');
433 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ')');
434 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '"');
435 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '\'');
436
437 // This chunk matches the query
438 gti_find_form_content += "_gtichunkmatchingquery_(" + chunk_key_escaped + "," + target_file_chunk_text_escaped + ")\n";
439
440 chunk_key_iterator++;
441 }
442 gti_find_form_content += "_gtifindformfooter_\n";
443
444 disp.setmacro("gtifindformcontent", "gti", gti_find_form_content);
445}
446
447
448
449void gtiaction::define_gti_offline_page(displayclass& disp, cgiargsclass& args, ostream& logout)
450{
451 // Get the target language code and file to translate from the CGI arguments
452 text_t target_language_code = args["tlc"];
453 text_t translation_file_key = args["tfk"];
454
455 disp.setmacro("gtiformcontent", "gti", "_gti:gtioffline_");
456
457 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
458 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
459 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
460 disp.setmacro("gtitranslationfiledescHtmlsafe", "gti", "_gti:textgti" + encodeForHTML(translation_file_key) + "_");
461}
462
463
464
465void gtiaction::define_gti_core_page(displayclass& disp, cgiargsclass& args, ostream& logout)
466{
467 // Get the target language code and file to translate from the CGI arguments
468 text_t target_language_code = args["tlc"];
469 text_t translation_file_key = args["tfk"];
470 text_t num_chunks_per_page = args["ncpp"];
471 logout << "Num chunks per page: " << num_chunks_per_page << endl;
472
473 disp.setmacro("gtiformcontent", "gti", "_gti:gticore_");
474
475 // Display text right to left if target language is Arabic or Farsi or Urdu
476 if (target_language_code == "ar" || target_language_code == "fa" || target_language_code == "ur") {
477 disp.setmacro("gtitextdirection", "gti", "rtl");
478 }
479 else {
480 disp.setmacro("gtitextdirection", "gti", "ltr");
481 }
482
483 // Send a request to gti.pl to get the first string to translate
484 text_t gti_arguments = "get-first-n-chunks-requiring-work " + target_language_code + " " + translation_file_key + " " + num_chunks_per_page;
485 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
486 if (gti_response.error_message != "") {
487 // An error has occurred
488 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
489 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
490 return;
491 }
492
493 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
494 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
495 if (translation_file_key == "glihelp") {
496 disp.setmacro("gtitargetfilepath", "gti", "_gtidownloadglihelp_");
497 } else {
498 disp.setmacro("gtitargetfilepath", "gti", gti_response.translation_files_key_to_target_file_path_mapping[translation_file_key]);
499 }
500 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
501 disp.setmacro("gtitranslationfiledescHtmlsafe", "gti", "_gti:textgti" + encodeForHTML(translation_file_key) + "_");
502 disp.setmacro("gtiviewtranslationfileinaction", "gti", "_gti:gtiview" + translation_file_key + "inaction_");
503 disp.setmacro("gtiviewtranslationfileinactionHtmlsafe", "gti", "_gti:gtiview" + encodeForHTML(translation_file_key) + "inaction_");
504
505 disp.setmacro("gtinumchunkstranslated", "gti", gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key]);
506 disp.setmacro("gtinumchunksrequiringtranslation", "gti", gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key]);
507 disp.setmacro("gtinumchunksrequiringupdating", "gti", gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key]);
508
509 // Check if the translation file is finished
510 if (gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key] == "0" && gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key] == "0") {
511 disp.setmacro("gtiformcontent", "gti", "_gti:gtidone_");
512 return;
513 }
514
515 // Loop through the chunks returned, displaying them on the page
516 text_t gti_core_form_content = "";
517 text_tmap::iterator chunk_key_iterator = gti_response.source_file_chunks_key_to_text_mapping.begin();
518 while (chunk_key_iterator != gti_response.source_file_chunks_key_to_text_mapping.end()) {
519 text_t chunk_key = chunk_key_iterator->first;
520
521 // Need to escape any underscores in the chunk key to show it correctly on the page
522 text_t chunk_key_escaped = escape_all(chunk_key, '_');
523
524 // Need to escape any backslashes, underscores, commas, parentheses, and single quotes in the chunk text
525 text_t source_file_chunk_text = gti_response.source_file_chunks_key_to_text_mapping[chunk_key];
526 text_t source_file_chunk_text_escaped = escape_all(source_file_chunk_text, '\\');
527 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '_');
528 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, ',');
529 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '(');
530 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, ')');
531 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '\'');
532 text_t target_file_chunk_text = gti_response.target_file_chunks_key_to_text_mapping[chunk_key];
533 text_t target_file_chunk_text_escaped = escape_all(target_file_chunk_text, '\\');
534 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '_');
535 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ',');
536 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '(');
537 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ')');
538 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '\'');
539
540 text_t source_file_chunk_date = gti_response.source_file_chunks_key_to_date_mapping[chunk_key];
541 text_t target_file_chunk_date = gti_response.target_file_chunks_key_to_date_mapping[chunk_key];
542
543 // This chunk requires translation
544 if (target_file_chunk_text == "") {
545 gti_core_form_content += "_gtichunkrequiringtranslation_(" + chunk_key_escaped + "," + source_file_chunk_text_escaped + "," + source_file_chunk_date + ")\n";
546 }
547 // This chunk requires updating
548 else {
549 gti_core_form_content += "_gtichunkrequiringupdating_(" + chunk_key_escaped + "," + source_file_chunk_text_escaped + "," + source_file_chunk_date + "," + target_file_chunk_text_escaped + "," + target_file_chunk_date + ")\n";
550 }
551
552 chunk_key_iterator++;
553 }
554
555 disp.setmacro("gticoreformcontent", "gti", gti_core_form_content);
556}
557
558
559
560void gtiaction::process_gti_submissions(displayclass& disp, cgiargsclass& args, ostream& logout, bool force_submission)
561{
562 // Get the target language code and file to translate from the CGI arguments
563 text_t target_language_code = args["tlc"];
564 text_t translation_file_key = args["tfk"];
565 text_t submitter_username = args["un"];
566
567 // Submitted chunk arguments contain the language code followed by "::"
568 char* source_chunk_key_start_cstr = ((text_t) "en" + "%3A%3A").getcstr();
569 char* target_chunk_key_start_cstr = (target_language_code + "%3A%3A").getcstr();
570
571 // Find the cgi arguments with submitted chunk information
572 text_t submission_text;
573 cgiargsclass::const_iterator cgi_argument = args.begin();
574 while (cgi_argument != args.end()) {
575 char* cgi_argument_name_cstr = cgi_argument->first.getcstr();
576
577 // Source file text
578 if (strncmp(cgi_argument_name_cstr, source_chunk_key_start_cstr, strlen(source_chunk_key_start_cstr)) == 0) {
579 submission_text += "<SourceFileText key=\"";
580 text_t source_key = &cgi_argument_name_cstr[strlen(source_chunk_key_start_cstr)];
581 decode_cgi_arg(source_key);
582 submission_text += source_key;
583 //submission_text += &cgi_argument_name_cstr[strlen(source_chunk_key_start_cstr)];
584 submission_text += "\">\n";
585
586 text_t source_value = xml_safe(decode_commas(args[cgi_argument->first]));
587 // if (args["w"] != "utf-8") {
588 // source_value = to_utf8(source_value);
589 // }
590 submission_text += source_value + "\n";
591 submission_text += "</SourceFileText>\n";
592 }
593 // Target file text
594 if (strncmp(cgi_argument_name_cstr, target_chunk_key_start_cstr, strlen(target_chunk_key_start_cstr)) == 0) {
595 submission_text += "<TargetFileText key=\"";
596 text_t target_key = &cgi_argument_name_cstr[strlen(target_chunk_key_start_cstr)];
597 decode_cgi_arg(target_key);
598 submission_text += target_key;
599 //submission_text += &cgi_argument_name_cstr[strlen(target_chunk_key_start_cstr)];
600 submission_text += "\">\n";
601
602 text_t target_value = xml_safe(decode_commas(args[cgi_argument->first]));
603 // if (args["w"] != "utf-8") {
604 // target_value = to_utf8(target_value);
605 // }
606 submission_text += target_value + "\n";
607 submission_text += "</TargetFileText>\n";
608 }
609
610 delete[] cgi_argument_name_cstr;
611 ++cgi_argument;
612 }
613
614 logout << "Submission text: " << submission_text << endl;
615
616 // Send the submission to gti.pl
617 text_t gti_arguments = "submit-translations " + target_language_code + " " + translation_file_key + " " + submitter_username;
618 if (force_submission) {
619 gti_arguments += " -force_submission";
620 }
621 do_gti_submission(gti_arguments, submission_text, logout);
622 logout << "Done." << endl;
623
624 delete[] source_chunk_key_start_cstr;
625 delete[] target_chunk_key_start_cstr;
626}
627
628
629
630bool gtiaction::produce_excel_spreadsheet(cgiargsclass& args, ostream& logout)
631{
632 // Get the target language code and file to translate from the CGI arguments
633 text_t target_language_code = args["tlc"];
634 text_t translation_file_key = args["tfk"];
635 text_t target_chunk_type = args["tct"];
636
637 // Send a request to gti.pl to get the Excel spreadsheet data
638 text_t gti_arguments = "";
639 if (target_chunk_type == "work") {
640 gti_arguments = "get-first-n-chunks-requiring-work " + target_language_code + " " + translation_file_key + " " + "10000" + " | /opt/jdk1.6.0/bin/java -cp /home/nzdl/gti:/home/nzdl/gti/xalan.jar ApplyXSLT /home/nzdl/gti/gti-generate-excel-xml.xsl -";
641 } else {
642 gti_arguments = "get-all-chunks " + target_language_code + " " + translation_file_key + " | /opt/jdk1.6.0/bin/java -cp /home/nzdl/gti:/home/nzdl/gti/xalan.jar ApplyXSLT /home/nzdl/gti/gti-generate-excel-xml.xsl -";
643 }
644
645 text_t gti_response_xml_text = do_gti_request(gti_arguments, logout);
646 if (gti_response_xml_text == "") {
647 // An error has occurred
648 return false;
649 }
650
651 // Write the Excel spreadsheet data to the browser
652 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
653 printf(gti_response_xml_text_cstr);
654 delete[] gti_response_xml_text_cstr;
655
656 return true;
657}
658
659bool gtiaction::produce_glihelp_zipfile(displayclass& disp, cgiargsclass& args, ostream& logout)
660{
661 text_t target_language_code = args["tlc"];
662 text_t gti_arguments = "create-glihelp-zip-file " + target_language_code;
663
664 do_gti_request(gti_arguments, logout);
665
666 disp.setmacro("gtiglihelpzipfilepath", "gti", target_language_code + "_GLIHelp.zip");
667 disp.setmacro("gtiglihelpzipfilepathUrlsafe", "gti", encodeForURL(target_language_code) + "_GLIHelp.zip");
668
669 return true;
670}
671
672
673text_t gtiaction::escape_all(text_t text_string, char character_to_escape)
674{
675 text_t text_string_escaped = "";
676
677 text_t::iterator text_string_character = text_string.begin();
678 while (text_string_character != text_string.end()) {
679 if (*text_string_character == character_to_escape) {
680 text_string_escaped += "\\";
681 }
682 text_string_escaped.push_back(*text_string_character);
683 text_string_character++;
684 }
685
686 return text_string_escaped;
687}
688
689
690
691char* xml_get_attribute(const char** attributes, char* attribute_name)
692{
693 for (int i = 0; (attributes[i] != NULL); i += 2) {
694 if (strcmp(attribute_name, attributes[i]) == 0) {
695 return strdup(attributes[i+1]);
696 }
697 }
698
699 return NULL;
700}
701
702
703static void XMLCALL gti_response_xml_start_element(void* user_data, const char* element_name_cstr, const char** attributes)
704{
705 GTI_Response* gti_response = (GTI_Response*) user_data;
706 text_t element_name = element_name_cstr;
707 cerr << "In startElement() for " << element_name << endl;
708
709 if (element_name == "GTIError") {
710 gti_response->recorded_text = "";
711 gti_response->is_recording_text = true;
712 }
713
714 if (element_name == "TranslationFile") {
715 int translation_file_index = gti_response->translation_files_index_to_key_mapping.size();
716 gti_response->translation_file_key = xml_get_attribute(attributes, "key");
717 gti_response->translation_files_index_to_key_mapping[translation_file_index] = gti_response->translation_file_key;
718 gti_response->translation_files_key_to_target_file_path_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "target_file_path");
719 gti_response->translation_files_key_to_num_chunks_translated_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_translated");
720 gti_response->translation_files_key_to_num_chunks_requiring_translation_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_translation");
721 gti_response->translation_files_key_to_num_chunks_requiring_updating_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_updating");
722 }
723
724 if (element_name == "ChunksMatchingQuery") {
725 gti_response->num_chunks_matching_query = xml_get_attribute(attributes, "size");
726 }
727
728 if (element_name == "Chunk") {
729 gti_response->chunk_key = xml_get_attribute(attributes, "key");
730 }
731
732 if (element_name == "SourceFileText") {
733 gti_response->source_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
734 gti_response->recorded_text = "";
735 gti_response->is_recording_text = true;
736 }
737
738 if (element_name == "TargetFileText") {
739 if (xml_get_attribute(attributes, "date") != NULL) {
740 gti_response->target_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
741 }
742 gti_response->recorded_text = "";
743 gti_response->is_recording_text = true;
744 }
745}
746
747
748static void XMLCALL gti_response_xml_end_element(void* user_data, const char* element_name_cstr)
749{
750 GTI_Response* gti_response = (GTI_Response*) user_data;
751 text_t element_name = element_name_cstr;
752
753 if (element_name == "GTIError") {
754 gti_response->error_message = to_uni(gti_response->recorded_text);
755 gti_response->is_recording_text = false;
756 }
757
758 if (element_name == "SourceFileText") {
759 gti_response->source_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
760 gti_response->is_recording_text = false;
761 }
762
763 if (element_name == "TargetFileText") {
764 gti_response->target_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
765 gti_response->is_recording_text = false;
766 }
767}
768
769
770static void XMLCALL gti_response_xml_character_data(void *user_data, const char* text_cstr, int text_length)
771{
772 GTI_Response* gti_response = (GTI_Response*) user_data;
773 if (gti_response->is_recording_text) {
774 gti_response->recorded_text.appendcarr(text_cstr, text_length);
775 }
776}
777
778
779
780text_t gtiaction::do_gti_request(text_t gti_arguments, ostream& logout)
781{
782 // Send the request to gti.pl and read the XML output
783 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
784 char* gti_command_cstr = gti_command.getcstr();
785 FILE *gti_pipe = popen(gti_command_cstr, "r");
786 delete[] gti_command_cstr;
787 if (gti_pipe == NULL) {
788 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
789 return "";
790 }
791
792 // Read the gti.pl response
793 text_t gti_response_xml_text;
794 while (!feof(gti_pipe)) {
795 char buffer[1024];
796 gti_response_xml_text.appendcarr(buffer, fread(buffer, 1, 1024, gti_pipe));
797 }
798 pclose(gti_pipe);
799
800 return gti_response_xml_text;
801}
802
803
804
805GTI_Response gtiaction::parse_gti_response(text_t gti_response_xml_text, ostream& logout)
806{
807 GTI_Response gti_response;
808 gti_response.is_recording_text = false;
809
810 // Parse the gti.pl response (XML)
811 logout << "Parsing GTI command response: " << gti_response_xml_text << endl;
812 XML_Parser xml_parser = XML_ParserCreate(NULL);
813 XML_SetUserData(xml_parser, &gti_response);
814 XML_SetElementHandler(xml_parser, gti_response_xml_start_element, gti_response_xml_end_element);
815 XML_SetCharacterDataHandler(xml_parser, gti_response_xml_character_data);
816
817 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
818 int parse_status = XML_Parse(xml_parser, gti_response_xml_text_cstr, strlen(gti_response_xml_text_cstr), XML_TRUE);
819 delete[] gti_response_xml_text_cstr;
820 if (parse_status == XML_STATUS_ERROR) {
821 logout << "Parse error " << XML_ErrorString(XML_GetErrorCode(xml_parser)) << " at line " << XML_GetCurrentLineNumber(xml_parser) << endl;
822 return gti_response;
823 }
824
825 XML_ParserFree(xml_parser);
826
827 logout << "Finished parse." << endl;
828 return gti_response;
829}
830
831
832
833void gtiaction::do_gti_submission(text_t gti_arguments, text_t gti_submission, ostream& logout)
834{
835 // Send the submission to gti.pl
836 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
837 char* gti_command_cstr = gti_command.getcstr();
838 FILE *gti_pipe = popen(gti_command_cstr, "w");
839 delete[] gti_command_cstr;
840 if (gti_pipe == NULL) {
841 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
842 return;
843 }
844
845 // Write the gti.pl submission
846 char* gti_submission_cstr = gti_submission.getcstr();
847 fwrite(gti_submission_cstr, 1, strlen(gti_submission_cstr), gti_pipe);
848 delete[] gti_submission_cstr;
849
850 pclose(gti_pipe);
851}
852
853
854
855#endif // GSDL_USE_GTI_ACTION
Note: See TracBrowser for help on using the repository browser.