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

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

Now deals with "<" and ">" characters correctly in the submitted text strings.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 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 disp.setmacro("imagepref", displayclass::defaultpackage, "_gti:imagepref_");
153
154 // Define the page content for the GTI home page
155 if (args["p"] == "home") {
156 define_gti_home_page(disp, args, logout);
157 return;
158 }
159
160 // Define the page content for the GTI language page
161 if (args["p"] == "lang") {
162 define_gti_lang_page(disp, args, logout);
163 return;
164 }
165
166 // Define the page content for the GTI search page
167 if (args["p"] == "find") {
168 define_gti_find_page(disp, args, logout);
169 return;
170 }
171
172 // Process user translations
173 if (args["p"] == "submit") {
174 process_gti_submissions(disp, args, logout, true);
175 }
176
177 // Define the page content for the GTI core pages (containing the translation input forms)
178 define_gti_core_page(disp, args, logout);
179}
180
181
182
183void gtiaction::define_gti_home_page(displayclass& disp, cgiargsclass& args, ostream& logout)
184{
185 disp.setmacro("gtiformcontent", "gti", "_gti:gtihome_");
186
187 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
188
189 // Get the languages specified in the main.cfg file, and put them into a map to sort by name
190 text_tmap gti_languages_name_code_mapping;
191 languageinfo_tmap::const_iterator loaded_language = loaded_languages.begin();
192 while (loaded_language != loaded_languages.end()) {
193 // English is not a valid GTI target language, since it is the source language
194 if (loaded_language->first != "en") {
195 gti_languages_name_code_mapping[loaded_language->second.longname] = loaded_language->first;
196 }
197 ++loaded_language;
198 }
199
200 // Set the gtitlcselection macro
201 text_t gti_tlc_selection = "<select name=\"tlc\">\n";
202 text_tmap::iterator gti_language = gti_languages_name_code_mapping.begin();
203 while (gti_language != gti_languages_name_code_mapping.end()) {
204 gti_tlc_selection += "<option value=\"" + gti_language->second + "\">" + gti_language->first + "</option>\n";
205 ++gti_language;
206 }
207 gti_tlc_selection += "</select>";
208 disp.setmacro("gtitlcselection", "gti", gti_tlc_selection);
209}
210
211
212
213void gtiaction::define_gti_lang_page(displayclass& disp, cgiargsclass& args, ostream& logout)
214{
215 // Get the target language code from the CGI arguments
216 text_t target_language_code = args["tlc"];
217
218 disp.setmacro("gtiformcontent", "gti", "_gti:gtilang_");
219
220 // Send a request to gti.pl to get the valid translation files
221 text_t gti_arguments = "get-language-status " + target_language_code;
222 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
223 if (gti_response.error_message != "") {
224 // An error has occurred
225 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
226 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
227 return;
228 }
229
230 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
231 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
232
233 // Set the gtitfkselection macro
234 text_t gti_tfk_selection = "<table>";
235 text_tmap::iterator translation_file = gti_response.translation_files_index_to_key_mapping.begin();
236 while (translation_file != gti_response.translation_files_index_to_key_mapping.end()) {
237 text_t translation_file_key = translation_file->second;
238
239 gti_tfk_selection += "<tr><td>";
240 gti_tfk_selection += "<input type=\"radio\" name=\"tfk\" value=\"" + translation_file_key + "\"></td>\n";
241 gti_tfk_selection += "<td>_textgti" + translation_file_key + "_</td></tr>\n";
242
243 text_t num_chunks_translated = gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key];
244 text_t num_chunks_requiring_translation = gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key];
245 text_t num_chunks_requiring_updating = gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key];
246 gti_tfk_selection += "<tr><td></td><td>_gtitranslationfilestatus_(" + num_chunks_translated + "," + num_chunks_requiring_translation + "," + num_chunks_requiring_updating + ")</td></tr>\n";
247 ++translation_file;
248 }
249 gti_tfk_selection += "</table>";
250 disp.setmacro("gtitfkselection", "gti", gti_tfk_selection);
251}
252
253
254
255void gtiaction::define_gti_find_page(displayclass& disp, cgiargsclass& args, ostream& logout)
256{
257 // Get the target language code and file to translate from the CGI arguments
258 text_t target_language_code = args["tlc"];
259 text_t translation_file_key = args["tfk"];
260 text_t query_string = to_utf8(args["q"]);
261
262 // Process user corrections
263 if (args["sp"] != "") {
264 process_gti_submissions(disp, args, logout, false);
265 }
266
267 disp.setmacro("gtiformcontent", "gti", "_gti:gtifind_");
268
269 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
270 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
271 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
272
273 if (query_string == "") {
274 // No query, so no search results
275 disp.setmacro("gtifindformcontent", "gti", "");
276 return;
277 }
278
279 // Display text right to left if target language is Arabic or Farsi
280 if (target_language_code == "ar" || target_language_code == "fa") {
281 disp.setmacro("gtitextdirection", "gti", "rtl");
282 }
283 else {
284 disp.setmacro("gtitextdirection", "gti", "ltr");
285 }
286
287 // Send a request to gti.pl to get the valid translation files
288 logout << "Query argument: " << query_string << endl;
289 text_t gti_arguments = "search-chunks " + target_language_code + " " + translation_file_key + " " + query_string;
290 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
291 if (gti_response.error_message != "") {
292 // An error has occurred
293 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
294 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
295 return;
296 }
297
298 disp.setmacro("gtinumchunksmatchingquery", "gti", gti_response.num_chunks_matching_query);
299
300 // Loop through the chunks returned, displaying them on the page
301 text_t gti_find_form_content = "_gtifindformheader_\n";
302 text_tmap::iterator chunk_key_iterator = gti_response.target_file_chunks_key_to_text_mapping.begin();
303 while (chunk_key_iterator != gti_response.target_file_chunks_key_to_text_mapping.end()) {
304 text_t chunk_key = chunk_key_iterator->first;
305
306 // Need to escape any underscores in the chunk key to show it correctly on the page
307 text_t chunk_key_escaped = escape_all(chunk_key, '_');
308
309 // Need to escape any backslashes, underscores, commas, parentheses, and single quotes in the chunk text
310 text_t target_file_chunk_text = gti_response.target_file_chunks_key_to_text_mapping[chunk_key];
311 text_t target_file_chunk_text_escaped = escape_all(target_file_chunk_text, '\\');
312 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '_');
313 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ',');
314 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '(');
315 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ')');
316 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '"');
317 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '\'');
318
319 // This chunk matches the query
320 gti_find_form_content += "_gtichunkmatchingquery_(" + chunk_key_escaped + "," + target_file_chunk_text_escaped + ")\n";
321
322 chunk_key_iterator++;
323 }
324 gti_find_form_content += "_gtifindformfooter_\n";
325
326 disp.setmacro("gtifindformcontent", "gti", gti_find_form_content);
327}
328
329
330
331void gtiaction::define_gti_core_page(displayclass& disp, cgiargsclass& args, ostream& logout)
332{
333 // Get the target language code and file to translate from the CGI arguments
334 text_t target_language_code = args["tlc"];
335 text_t translation_file_key = args["tfk"];
336 text_t num_chunks_per_page = args["ncpp"];
337 logout << "Num chunks per page: " << num_chunks_per_page << endl;
338
339 disp.setmacro("gtiformcontent", "gti", "_gti:gticore_");
340
341 // Display text right to left if target language is Arabic or Farsi
342 if (target_language_code == "ar" || target_language_code == "fa") {
343 disp.setmacro("gtitextdirection", "gti", "rtl");
344 }
345 else {
346 disp.setmacro("gtitextdirection", "gti", "ltr");
347 }
348
349 // Send a request to gti.pl to get the first string to translate
350 text_t gti_arguments = "get-first-n-chunks-requiring-work " + target_language_code + " " + translation_file_key + " " + num_chunks_per_page;
351 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
352 if (gti_response.error_message != "") {
353 // An error has occurred
354 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
355 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
356 return;
357 }
358
359 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
360 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
361 disp.setmacro("gtitargetfilepath", "gti", gti_response.translation_files_key_to_target_file_path_mapping[translation_file_key]);
362 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
363 disp.setmacro("gtiviewtranslationfileinaction", "gti", "_gti:gtiview" + translation_file_key + "inaction_");
364
365 disp.setmacro("gtinumchunkstranslated", "gti", gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key]);
366 disp.setmacro("gtinumchunksrequiringtranslation", "gti", gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key]);
367 disp.setmacro("gtinumchunksrequiringupdating", "gti", gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key]);
368
369 // Check if the translation file is finished
370 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") {
371 disp.setmacro("gtiformcontent", "gti", "_gti:gtidone_");
372 return;
373 }
374
375 // Loop through the chunks returned, displaying them on the page
376 text_t gti_core_form_content = "";
377 text_tmap::iterator chunk_key_iterator = gti_response.source_file_chunks_key_to_text_mapping.begin();
378 while (chunk_key_iterator != gti_response.source_file_chunks_key_to_text_mapping.end()) {
379 text_t chunk_key = chunk_key_iterator->first;
380
381 // Need to escape any underscores in the chunk key to show it correctly on the page
382 text_t chunk_key_escaped = escape_all(chunk_key, '_');
383
384 // Need to escape any backslashes, underscores, commas, parentheses, and single quotes in the chunk text
385 text_t source_file_chunk_text = gti_response.source_file_chunks_key_to_text_mapping[chunk_key];
386 text_t source_file_chunk_text_escaped = escape_all(source_file_chunk_text, '\\');
387 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '_');
388 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, ',');
389 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '(');
390 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, ')');
391 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '\'');
392 text_t target_file_chunk_text = gti_response.target_file_chunks_key_to_text_mapping[chunk_key];
393 text_t target_file_chunk_text_escaped = escape_all(target_file_chunk_text, '\\');
394 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '_');
395 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ',');
396 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '(');
397 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ')');
398 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '\'');
399
400 text_t source_file_chunk_date = gti_response.source_file_chunks_key_to_date_mapping[chunk_key];
401 text_t target_file_chunk_date = gti_response.target_file_chunks_key_to_date_mapping[chunk_key];
402
403 // This chunk requires translation
404 if (target_file_chunk_text == "") {
405 gti_core_form_content += "_gtichunkrequiringtranslation_(" + chunk_key_escaped + "," + source_file_chunk_text_escaped + "," + source_file_chunk_date + ")\n";
406 }
407 // This chunk requires updating
408 else {
409 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";
410 }
411
412 chunk_key_iterator++;
413 }
414
415 disp.setmacro("gticoreformcontent", "gti", gti_core_form_content);
416}
417
418
419
420void gtiaction::process_gti_submissions(displayclass& disp, cgiargsclass& args, ostream& logout, bool force_submission)
421{
422 // Get the target language code and file to translate from the CGI arguments
423 text_t target_language_code = args["tlc"];
424 text_t translation_file_key = args["tfk"];
425
426 // Submitted chunk arguments contain the language code followed by "::"
427 char* source_chunk_key_start_cstr = ((text_t) "en" + "%3A%3A").getcstr();
428 char* target_chunk_key_start_cstr = (target_language_code + "%3A%3A").getcstr();
429
430 // Find the cgi arguments with submitted chunk information
431 text_t submission_text;
432 cgiargsclass::const_iterator cgi_argument = args.begin();
433 while (cgi_argument != args.end()) {
434 char* cgi_argument_name_cstr = cgi_argument->first.getcstr();
435
436 // Source file text
437 if (strncmp(cgi_argument_name_cstr, source_chunk_key_start_cstr, strlen(source_chunk_key_start_cstr)) == 0) {
438 submission_text += "<SourceFileText key=\"";
439 submission_text += &cgi_argument_name_cstr[strlen(source_chunk_key_start_cstr)];
440 submission_text += "\">\n";
441 submission_text += to_utf8(xml_safe(args[cgi_argument->first])) + "\n";
442 submission_text += "</SourceFileText>\n";
443 }
444 // Target file text
445 if (strncmp(cgi_argument_name_cstr, target_chunk_key_start_cstr, strlen(target_chunk_key_start_cstr)) == 0) {
446 submission_text += "<TargetFileText key=\"";
447 submission_text += &cgi_argument_name_cstr[strlen(target_chunk_key_start_cstr)];
448 submission_text += "\">\n";
449 submission_text += to_utf8(xml_safe(args[cgi_argument->first])) + "\n";
450 submission_text += "</TargetFileText>\n";
451 }
452
453 delete[] cgi_argument_name_cstr;
454 ++cgi_argument;
455 }
456
457 logout << "Submission text: " << submission_text << endl;
458
459 // Send the submission to gti.pl
460 text_t gti_arguments = "submit-translations " + target_language_code + " " + translation_file_key;
461 if (force_submission) {
462 gti_arguments += " -force_submission";
463 }
464 do_gti_submission(gti_arguments, submission_text, logout);
465 logout << "Done." << endl;
466
467 delete[] source_chunk_key_start_cstr;
468 delete[] target_chunk_key_start_cstr;
469}
470
471
472
473text_t gtiaction::escape_all(text_t text_string, char character_to_escape)
474{
475 text_t text_string_escaped = "";
476
477 text_t::iterator text_string_character = text_string.begin();
478 while (text_string_character != text_string.end()) {
479 if (*text_string_character == character_to_escape) {
480 text_string_escaped += "\\";
481 }
482 text_string_escaped.push_back(*text_string_character);
483 text_string_character++;
484 }
485
486 return text_string_escaped;
487}
488
489
490
491text_t gtiaction::xml_safe(const text_t &text_string)
492{
493 text_t text_string_safe;
494 text_t::const_iterator here = text_string.begin();
495 text_t::const_iterator end = text_string.end();
496 while (here != end) {
497 if (*here == '<') text_string_safe += "&lt;";
498 else if (*here == '>') text_string_safe += "&gt;";
499 else text_string_safe.push_back(*here);
500 ++here;
501 }
502
503 return text_string_safe;
504}
505
506
507
508char* xml_get_attribute(const char** attributes, char* attribute_name)
509{
510 for (int i = 0; (attributes[i] != NULL); i += 2) {
511 if (strcmp(attribute_name, attributes[i]) == 0) {
512 return strdup(attributes[i+1]);
513 }
514 }
515
516 return NULL;
517}
518
519
520static void XMLCALL gti_response_xml_start_element(void* user_data, const char* element_name_cstr, const char** attributes)
521{
522 GTI_Response* gti_response = (GTI_Response*) user_data;
523 text_t element_name = element_name_cstr;
524 cerr << "In startElement() for " << element_name << endl;
525
526 if (element_name == "GTIError") {
527 gti_response->recorded_text = "";
528 gti_response->is_recording_text = true;
529 }
530
531 if (element_name == "TranslationFile") {
532 int translation_file_index = gti_response->translation_files_index_to_key_mapping.size();
533 gti_response->translation_file_key = xml_get_attribute(attributes, "key");
534 gti_response->translation_files_index_to_key_mapping[translation_file_index] = gti_response->translation_file_key;
535 gti_response->translation_files_key_to_target_file_path_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "target_file_path");
536 gti_response->translation_files_key_to_num_chunks_translated_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_translated");
537 gti_response->translation_files_key_to_num_chunks_requiring_translation_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_translation");
538 gti_response->translation_files_key_to_num_chunks_requiring_updating_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_updating");
539 }
540
541 if (element_name == "ChunksMatchingQuery") {
542 gti_response->num_chunks_matching_query = xml_get_attribute(attributes, "size");
543 }
544
545 if (element_name == "Chunk") {
546 gti_response->chunk_key = xml_get_attribute(attributes, "key");
547 }
548
549 if (element_name == "SourceFileText") {
550 gti_response->source_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
551 gti_response->recorded_text = "";
552 gti_response->is_recording_text = true;
553 }
554
555 if (element_name == "TargetFileText") {
556 if (xml_get_attribute(attributes, "date") != NULL) {
557 gti_response->target_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
558 }
559 gti_response->recorded_text = "";
560 gti_response->is_recording_text = true;
561 }
562}
563
564
565static void XMLCALL gti_response_xml_end_element(void* user_data, const char* element_name_cstr)
566{
567 GTI_Response* gti_response = (GTI_Response*) user_data;
568 text_t element_name = element_name_cstr;
569
570 if (element_name == "GTIError") {
571 gti_response->error_message = to_uni(gti_response->recorded_text);
572 gti_response->is_recording_text = false;
573 }
574
575 if (element_name == "SourceFileText") {
576 gti_response->source_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
577 gti_response->is_recording_text = false;
578 }
579
580 if (element_name == "TargetFileText") {
581 gti_response->target_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
582 gti_response->is_recording_text = false;
583 }
584}
585
586
587static void XMLCALL gti_response_xml_character_data(void *user_data, const char* text_cstr, int text_length)
588{
589 GTI_Response* gti_response = (GTI_Response*) user_data;
590 if (gti_response->is_recording_text) {
591 gti_response->recorded_text.appendcarr(text_cstr, text_length);
592 }
593}
594
595
596
597text_t gtiaction::do_gti_request(text_t gti_arguments, ostream& logout)
598{
599 // Send the request to gti.pl and read the XML output
600 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
601 char* gti_command_cstr = gti_command.getcstr();
602 FILE *gti_pipe = popen(gti_command_cstr, "r");
603 delete[] gti_command_cstr;
604 if (gti_pipe == NULL) {
605 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
606 return "";
607 }
608
609 // Read the gti.pl response
610 text_t gti_response_xml_text;
611 while (!feof(gti_pipe)) {
612 char buffer[1024];
613 gti_response_xml_text.appendcarr(buffer, fread(buffer, 1, 1024, gti_pipe));
614 }
615 pclose(gti_pipe);
616
617 return gti_response_xml_text;
618}
619
620
621
622GTI_Response gtiaction::parse_gti_response(text_t gti_response_xml_text, ostream& logout)
623{
624 GTI_Response gti_response;
625 gti_response.is_recording_text = false;
626
627 // Parse the gti.pl response (XML)
628 logout << "Parsing GTI command response: " << gti_response_xml_text << endl;
629 XML_Parser xml_parser = XML_ParserCreate(NULL);
630 XML_SetUserData(xml_parser, &gti_response);
631 XML_SetElementHandler(xml_parser, gti_response_xml_start_element, gti_response_xml_end_element);
632 XML_SetCharacterDataHandler(xml_parser, gti_response_xml_character_data);
633
634 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
635 int parse_status = XML_Parse(xml_parser, gti_response_xml_text_cstr, strlen(gti_response_xml_text_cstr), XML_TRUE);
636 delete[] gti_response_xml_text_cstr;
637 if (parse_status == XML_STATUS_ERROR) {
638 logout << "Parse error " << XML_ErrorString(XML_GetErrorCode(xml_parser)) << " at line " << XML_GetCurrentLineNumber(xml_parser) << endl;
639 return gti_response;
640 }
641
642 XML_ParserFree(xml_parser);
643
644 logout << "Finished parse." << endl;
645 return gti_response;
646}
647
648
649
650void gtiaction::do_gti_submission(text_t gti_arguments, text_t gti_submission, ostream& logout)
651{
652 // Send the submission to gti.pl
653 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
654 char* gti_command_cstr = gti_command.getcstr();
655 FILE *gti_pipe = popen(gti_command_cstr, "w");
656 delete[] gti_command_cstr;
657 if (gti_pipe == NULL) {
658 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
659 return;
660 }
661
662 // Write the gti.pl submission
663 char* gti_submission_cstr = gti_submission.getcstr();
664 fwrite(gti_submission_cstr, 1, strlen(gti_submission_cstr), gti_pipe);
665 delete[] gti_submission_cstr;
666
667 pclose(gti_pipe);
668}
669
670
671
672#endif // GSDL_USE_GTI_ACTION
Note: See TracBrowser for help on using the repository browser.