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

Last change on this file since 30620 was 30620, checked in by ak19, 8 years ago

The %s in the perlmodule strings was being replaced with the entire contents of the buffer when it was written out, when generating excel spreadsheet xml. So use fwrite instead of printf, as it doesn't do special formatting

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