source: gsdl/trunk/runtime-src/src/recpt/gtiaction.cpp@ 17545

Last change on this file since 17545 was 17545, checked in by mdewsnip, 16 years ago

Moved the xml_safe() function from gtiaction into gsdltools, so it can be used by other classes.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 32.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.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
657char* xml_get_attribute(const char** attributes, char* attribute_name)
658{
659 for (int i = 0; (attributes[i] != NULL); i += 2) {
660 if (strcmp(attribute_name, attributes[i]) == 0) {
661 return strdup(attributes[i+1]);
662 }
663 }
664
665 return NULL;
666}
667
668
669static void XMLCALL gti_response_xml_start_element(void* user_data, const char* element_name_cstr, const char** attributes)
670{
671 GTI_Response* gti_response = (GTI_Response*) user_data;
672 text_t element_name = element_name_cstr;
673 cerr << "In startElement() for " << element_name << endl;
674
675 if (element_name == "GTIError") {
676 gti_response->recorded_text = "";
677 gti_response->is_recording_text = true;
678 }
679
680 if (element_name == "TranslationFile") {
681 int translation_file_index = gti_response->translation_files_index_to_key_mapping.size();
682 gti_response->translation_file_key = xml_get_attribute(attributes, "key");
683 gti_response->translation_files_index_to_key_mapping[translation_file_index] = gti_response->translation_file_key;
684 gti_response->translation_files_key_to_target_file_path_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "target_file_path");
685 gti_response->translation_files_key_to_num_chunks_translated_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_translated");
686 gti_response->translation_files_key_to_num_chunks_requiring_translation_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_translation");
687 gti_response->translation_files_key_to_num_chunks_requiring_updating_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_updating");
688 }
689
690 if (element_name == "ChunksMatchingQuery") {
691 gti_response->num_chunks_matching_query = xml_get_attribute(attributes, "size");
692 }
693
694 if (element_name == "Chunk") {
695 gti_response->chunk_key = xml_get_attribute(attributes, "key");
696 }
697
698 if (element_name == "SourceFileText") {
699 gti_response->source_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
700 gti_response->recorded_text = "";
701 gti_response->is_recording_text = true;
702 }
703
704 if (element_name == "TargetFileText") {
705 if (xml_get_attribute(attributes, "date") != NULL) {
706 gti_response->target_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
707 }
708 gti_response->recorded_text = "";
709 gti_response->is_recording_text = true;
710 }
711}
712
713
714static void XMLCALL gti_response_xml_end_element(void* user_data, const char* element_name_cstr)
715{
716 GTI_Response* gti_response = (GTI_Response*) user_data;
717 text_t element_name = element_name_cstr;
718
719 if (element_name == "GTIError") {
720 gti_response->error_message = to_uni(gti_response->recorded_text);
721 gti_response->is_recording_text = false;
722 }
723
724 if (element_name == "SourceFileText") {
725 gti_response->source_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
726 gti_response->is_recording_text = false;
727 }
728
729 if (element_name == "TargetFileText") {
730 gti_response->target_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
731 gti_response->is_recording_text = false;
732 }
733}
734
735
736static void XMLCALL gti_response_xml_character_data(void *user_data, const char* text_cstr, int text_length)
737{
738 GTI_Response* gti_response = (GTI_Response*) user_data;
739 if (gti_response->is_recording_text) {
740 gti_response->recorded_text.appendcarr(text_cstr, text_length);
741 }
742}
743
744
745
746text_t gtiaction::do_gti_request(text_t gti_arguments, ostream& logout)
747{
748 // Send the request to gti.pl and read the XML output
749 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
750 char* gti_command_cstr = gti_command.getcstr();
751 FILE *gti_pipe = popen(gti_command_cstr, "r");
752 delete[] gti_command_cstr;
753 if (gti_pipe == NULL) {
754 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
755 return "";
756 }
757
758 // Read the gti.pl response
759 text_t gti_response_xml_text;
760 while (!feof(gti_pipe)) {
761 char buffer[1024];
762 gti_response_xml_text.appendcarr(buffer, fread(buffer, 1, 1024, gti_pipe));
763 }
764 pclose(gti_pipe);
765
766 return gti_response_xml_text;
767}
768
769
770
771GTI_Response gtiaction::parse_gti_response(text_t gti_response_xml_text, ostream& logout)
772{
773 GTI_Response gti_response;
774 gti_response.is_recording_text = false;
775
776 // Parse the gti.pl response (XML)
777 logout << "Parsing GTI command response: " << gti_response_xml_text << endl;
778 XML_Parser xml_parser = XML_ParserCreate(NULL);
779 XML_SetUserData(xml_parser, &gti_response);
780 XML_SetElementHandler(xml_parser, gti_response_xml_start_element, gti_response_xml_end_element);
781 XML_SetCharacterDataHandler(xml_parser, gti_response_xml_character_data);
782
783 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
784 int parse_status = XML_Parse(xml_parser, gti_response_xml_text_cstr, strlen(gti_response_xml_text_cstr), XML_TRUE);
785 delete[] gti_response_xml_text_cstr;
786 if (parse_status == XML_STATUS_ERROR) {
787 logout << "Parse error " << XML_ErrorString(XML_GetErrorCode(xml_parser)) << " at line " << XML_GetCurrentLineNumber(xml_parser) << endl;
788 return gti_response;
789 }
790
791 XML_ParserFree(xml_parser);
792
793 logout << "Finished parse." << endl;
794 return gti_response;
795}
796
797
798
799void gtiaction::do_gti_submission(text_t gti_arguments, text_t gti_submission, ostream& logout)
800{
801 // Send the submission to gti.pl
802 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
803 char* gti_command_cstr = gti_command.getcstr();
804 FILE *gti_pipe = popen(gti_command_cstr, "w");
805 delete[] gti_command_cstr;
806 if (gti_pipe == NULL) {
807 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
808 return;
809 }
810
811 // Write the gti.pl submission
812 char* gti_submission_cstr = gti_submission.getcstr();
813 fwrite(gti_submission_cstr, 1, strlen(gti_submission_cstr), gti_pipe);
814 delete[] gti_submission_cstr;
815
816 pclose(gti_pipe);
817}
818
819
820
821#endif // GSDL_USE_GTI_ACTION
Note: See TracBrowser for help on using the repository browser.