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

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

GTI on nzdl needs path to java executable. Since a custom javahome property can be set in gsdlsite.cfg, this is now read in if site from gsdlsite.cfg by common-src's gsdlsitecfg.cpp and set as an env var with putenv(), following Dr Bainbridge's idea. This env var is then read back in using getenv in gtiaction.cpp, so that it can run the appropriate java.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 35.5 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 //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 -";
661
662 // don't actually need to add toplevel gsdlhome to classpath
663 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";
664
665 } else {
666 //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 -";
667
668 // don't actually need to add toplevel gsdlhome to classpath
669 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";
670 }
671
672 text_t gti_response_xml_text = do_gti_request(gti_arguments, logout);
673 if (gti_response_xml_text == "") {
674 // An error has occurred
675 return false;
676 }
677
678 // Write the Excel spreadsheet data to the browser
679 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
680 printf(gti_response_xml_text_cstr);
681 delete[] gti_response_xml_text_cstr;
682
683 return true;
684}
685
686bool gtiaction::produce_glihelp_zipfile(displayclass& disp, cgiargsclass& args, ostream& logout)
687{
688 text_t target_language_code = args["tlc"];
689 text_t gti_arguments = "create-glihelp-zip-file " + target_language_code;
690
691 do_gti_request(gti_arguments, logout);
692
693 disp.setmacro("gtiglihelpzipfilepath", "gti", target_language_code + "_GLIHelp.zip");
694 disp.setmacro("gtiglihelpzipfilepathUrlsafe", "gti", encodeForURL(target_language_code) + "_GLIHelp.zip");
695
696 return true;
697}
698
699
700text_t gtiaction::escape_all(text_t text_string, char character_to_escape)
701{
702 text_t text_string_escaped = "";
703
704 text_t::iterator text_string_character = text_string.begin();
705 while (text_string_character != text_string.end()) {
706 if (*text_string_character == character_to_escape) {
707 text_string_escaped += "\\";
708 }
709 text_string_escaped.push_back(*text_string_character);
710 text_string_character++;
711 }
712
713 return text_string_escaped;
714}
715
716
717
718char* xml_get_attribute(const char** attributes, char* attribute_name)
719{
720 for (int i = 0; (attributes[i] != NULL); i += 2) {
721 if (strcmp(attribute_name, attributes[i]) == 0) {
722 return strdup(attributes[i+1]);
723 }
724 }
725
726 return NULL;
727}
728
729
730static void XMLCALL gti_response_xml_start_element(void* user_data, const char* element_name_cstr, const char** attributes)
731{
732 GTI_Response* gti_response = (GTI_Response*) user_data;
733 text_t element_name = element_name_cstr;
734 cerr << "In startElement() for " << element_name << endl;
735
736 if (element_name == "GTIError") {
737 gti_response->recorded_text = "";
738 gti_response->is_recording_text = true;
739 }
740
741 if (element_name == "TranslationFile") {
742 int translation_file_index = gti_response->translation_files_index_to_key_mapping.size();
743 gti_response->translation_file_key = xml_get_attribute(attributes, "key");
744 gti_response->translation_files_index_to_key_mapping[translation_file_index] = gti_response->translation_file_key;
745 gti_response->translation_files_key_to_target_file_path_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "target_file_path");
746 gti_response->translation_files_key_to_num_chunks_translated_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_translated");
747 gti_response->translation_files_key_to_num_chunks_requiring_translation_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_translation");
748 gti_response->translation_files_key_to_num_chunks_requiring_updating_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_updating");
749 }
750
751 if (element_name == "ChunksMatchingQuery") {
752 gti_response->num_chunks_matching_query = xml_get_attribute(attributes, "size");
753 }
754
755 if (element_name == "Chunk") {
756 gti_response->chunk_key = xml_get_attribute(attributes, "key");
757 }
758
759 if (element_name == "SourceFileText") {
760 gti_response->source_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
761 gti_response->recorded_text = "";
762 gti_response->is_recording_text = true;
763 }
764
765 if (element_name == "TargetFileText") {
766 if (xml_get_attribute(attributes, "date") != NULL) {
767 gti_response->target_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
768 }
769 gti_response->recorded_text = "";
770 gti_response->is_recording_text = true;
771 }
772}
773
774
775static void XMLCALL gti_response_xml_end_element(void* user_data, const char* element_name_cstr)
776{
777 GTI_Response* gti_response = (GTI_Response*) user_data;
778 text_t element_name = element_name_cstr;
779
780 if (element_name == "GTIError") {
781 gti_response->error_message = to_uni(gti_response->recorded_text);
782 gti_response->is_recording_text = false;
783 }
784
785 if (element_name == "SourceFileText") {
786 gti_response->source_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
787 gti_response->is_recording_text = false;
788 }
789
790 if (element_name == "TargetFileText") {
791 gti_response->target_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
796
797static void XMLCALL gti_response_xml_character_data(void *user_data, const char* text_cstr, int text_length)
798{
799 GTI_Response* gti_response = (GTI_Response*) user_data;
800 if (gti_response->is_recording_text) {
801 gti_response->recorded_text.appendcarr(text_cstr, text_length);
802 }
803}
804
805
806
807text_t gtiaction::do_gti_request(text_t gti_arguments, ostream& logout)
808{
809 // Send the request to gti.pl and read the XML output
810 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
811 char* gti_command_cstr = gti_command.getcstr();
812 FILE *gti_pipe = popen(gti_command_cstr, "r");
813 delete[] gti_command_cstr;
814 if (gti_pipe == NULL) {
815 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
816 return "";
817 }
818
819 // Read the gti.pl response
820 text_t gti_response_xml_text;
821 while (!feof(gti_pipe)) {
822 char buffer[1024];
823 gti_response_xml_text.appendcarr(buffer, fread(buffer, 1, 1024, gti_pipe));
824 }
825 pclose(gti_pipe);
826
827 return gti_response_xml_text;
828}
829
830
831
832GTI_Response gtiaction::parse_gti_response(text_t gti_response_xml_text, ostream& logout)
833{
834 GTI_Response gti_response;
835 gti_response.is_recording_text = false;
836
837 // Parse the gti.pl response (XML)
838 logout << "Parsing GTI command response: " << gti_response_xml_text << endl;
839 XML_Parser xml_parser = XML_ParserCreate(NULL);
840 XML_SetUserData(xml_parser, &gti_response);
841 XML_SetElementHandler(xml_parser, gti_response_xml_start_element, gti_response_xml_end_element);
842 XML_SetCharacterDataHandler(xml_parser, gti_response_xml_character_data);
843
844 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
845 int parse_status = XML_Parse(xml_parser, gti_response_xml_text_cstr, strlen(gti_response_xml_text_cstr), XML_TRUE);
846 delete[] gti_response_xml_text_cstr;
847 if (parse_status == XML_STATUS_ERROR) {
848 logout << "Parse error " << XML_ErrorString(XML_GetErrorCode(xml_parser)) << " at line " << XML_GetCurrentLineNumber(xml_parser) << endl;
849 return gti_response;
850 }
851
852 XML_ParserFree(xml_parser);
853
854 logout << "Finished parse." << endl;
855 return gti_response;
856}
857
858
859
860void gtiaction::do_gti_submission(text_t gti_arguments, text_t gti_submission, ostream& logout)
861{
862 // Send the submission to gti.pl
863 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
864 char* gti_command_cstr = gti_command.getcstr();
865 FILE *gti_pipe = popen(gti_command_cstr, "w");
866 delete[] gti_command_cstr;
867 if (gti_pipe == NULL) {
868 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
869 return;
870 }
871
872 // Write the gti.pl submission
873 char* gti_submission_cstr = gti_submission.getcstr();
874 fwrite(gti_submission_cstr, 1, strlen(gti_submission_cstr), gti_pipe);
875 delete[] gti_submission_cstr;
876
877 pclose(gti_pipe);
878}
879
880
881
882#endif // GSDL_USE_GTI_ACTION
Note: See TracBrowser for help on using the repository browser.