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

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