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

Last change on this file since 28973 was 28973, checked in by ak19, 7 years ago

All the changes required to get the GTI installed on a local greenstone using the latest gs2 src code from svn, since this has the security updates. 1. ApplyXSLT in build-src needed a lot of code additions since runtime-src's gtiaction.cpp needs to send the xml file from stdin using a pipe command. ApplyXSLT used to read stdin from a piped cmd differently, expecting DocStart and DocEnd embedding tags to mark the start and stop of each stream. This is still used by code in BasePlugout, so ApplyXSLT has been modified to take a minus-c parameter when requested to read from stdin without special embedding tag markers, such as when gtiaction calls it. ApplyXSLT uses an internal StreamGobbler class to read the stdin since it takes a while for xml generated by the gti.pl (which is piped in) to come in to ApplyXSLT. 2. The inner StreamGobbler class needed to be added into the ApplyXSLT jar file, so the Makefile.in has been updated. 3. In runtime-src, added in missing header files and updated the code that generated the spreadsheets on GTI, since it was firstly hardcoded to use paths on /home/nzdl, and the code that generated the spreadsheets when running ApplyXSLT/xalan.jar no longer worked as it had been coded.

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