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

Last change on this file since 13017 was 12565, checked in by mdewsnip, 18 years ago

A fix to compensate for the change to the way commas in CGI values are dealt with by default.

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