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

Last change on this file since 13672 was 13672, checked in by lh92, 17 years ago

added a new action 'status' which generats a page of the current translation status of gti

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