source: gsdl/trunk/src/recpt/gtiaction.cpp@ 15597

Last change on this file since 15597 was 13941, checked in by nzdl, 17 years ago

when processing the submissions, the translation keys are encoded to be URL safe but not decoded, so translator cannot find the source string with the wrong keys. Added the decode function.

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