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

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

Minor changes: better comments.

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