1 /* Copyright (C) 2018-2020 Greenbone Networks GmbH
2 *
3 * SPDX-License-Identifier: AGPL-3.0-or-later
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file gmp_tickets.c
21 * @brief GVM GMP layer: Tickets
22 *
23 * GMP tickets.
24 */
25
26 #include "gmp_tickets.h"
27 #include "gmp_base.h"
28 #include "gmp_get.h"
29 #include "manage_tickets.h"
30
31 #include <glib.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <gvm/util/xmlutils.h>
36
37 #undef G_LOG_DOMAIN
38 /**
39 * @brief GLib log domain.
40 */
41 #define G_LOG_DOMAIN "md gmp"
42
43
44 /* GET_TICKETS. */
45
46 /**
47 * @brief The get_tickets command.
48 */
49 typedef struct
50 {
51 get_data_t get; ///< Get args.
52 } get_tickets_t;
53
54 /**
55 * @brief Parser callback data.
56 *
57 * This is initially 0 because it's a global variable.
58 */
59 static get_tickets_t get_tickets_data;
60
61 /**
62 * @brief Reset command data.
63 */
64 static void
get_tickets_reset()65 get_tickets_reset ()
66 {
67 get_data_reset (&get_tickets_data.get);
68 memset (&get_tickets_data, 0, sizeof (get_tickets_t));
69 }
70
71 /**
72 * @brief Handle command start element.
73 *
74 * @param[in] attribute_names All attribute names.
75 * @param[in] attribute_values All attribute values.
76 */
77 void
get_tickets_start(const gchar ** attribute_names,const gchar ** attribute_values)78 get_tickets_start (const gchar **attribute_names,
79 const gchar **attribute_values)
80 {
81 get_data_parse_attributes (&get_tickets_data.get, "ticket",
82 attribute_names,
83 attribute_values);
84 }
85
86 /**
87 * @brief Handle end element.
88 *
89 * @param[in] gmp_parser GMP parser.
90 * @param[in] error Error parameter.
91 */
92 void
get_tickets_run(gmp_parser_t * gmp_parser,GError ** error)93 get_tickets_run (gmp_parser_t *gmp_parser, GError **error)
94 {
95 iterator_t tickets;
96 int count, filtered, ret, first;
97
98 count = 0;
99
100 ret = init_get ("get_tickets",
101 &get_tickets_data.get,
102 "Tickets",
103 &first);
104 if (ret)
105 {
106 switch (ret)
107 {
108 case 99:
109 SEND_TO_CLIENT_OR_FAIL
110 (XML_ERROR_SYNTAX ("get_tickets",
111 "Permission denied"));
112 break;
113 default:
114 internal_error_send_to_client (error);
115 get_tickets_reset ();
116 return;
117 }
118 get_tickets_reset ();
119 return;
120 }
121
122 /* Setup the iterator. */
123
124 ret = init_ticket_iterator (&tickets, &get_tickets_data.get);
125 if (ret)
126 {
127 switch (ret)
128 {
129 case 1:
130 if (send_find_error_to_client ("get_tickets",
131 "ticket",
132 get_tickets_data.get.id,
133 gmp_parser))
134 {
135 error_send_to_client (error);
136 get_tickets_reset ();
137 return;
138 }
139 break;
140 case 2:
141 if (send_find_error_to_client
142 ("get_tickets", "filter",
143 get_tickets_data.get.filt_id, gmp_parser))
144 {
145 error_send_to_client (error);
146 get_tickets_reset ();
147 return;
148 }
149 break;
150 case -1:
151 SEND_TO_CLIENT_OR_FAIL
152 (XML_INTERNAL_ERROR ("get_tickets"));
153 break;
154 }
155 get_tickets_reset ();
156 return;
157 }
158
159 /* Loop through tickets, sending XML. */
160
161 SEND_GET_START ("ticket");
162 while (1)
163 {
164 iterator_t results;
165
166 ret = get_next (&tickets, &get_tickets_data.get, &first,
167 &count, init_ticket_iterator);
168 if (ret == 1)
169 break;
170 if (ret == -1)
171 {
172 internal_error_send_to_client (error);
173 get_tickets_reset ();
174 return;
175 }
176
177 /* Send generic GET command elements. */
178
179 SEND_GET_COMMON (ticket, &get_tickets_data.get, &tickets);
180
181 /* Send ticket info. */
182
183 SENDF_TO_CLIENT_OR_FAIL ("<assigned_to>"
184 "<user id=\"%s\">"
185 "<name>%s</name>"
186 "</user>"
187 "</assigned_to>"
188 "<severity>%1.1f</severity>"
189 "<host>%s</host>"
190 "<location>%s</location>"
191 "<solution_type>%s</solution_type>"
192 "<status>%s</status>"
193 "<open_time>%s</open_time>"
194 "<open_note>%s</open_note>"
195 "<nvt oid=\"%s\"/>",
196 ticket_iterator_user_id (&tickets),
197 ticket_iterator_user_name (&tickets),
198 ticket_iterator_severity (&tickets),
199 ticket_iterator_host (&tickets),
200 ticket_iterator_location (&tickets),
201 ticket_iterator_solution_type (&tickets),
202 ticket_iterator_status (&tickets),
203 ticket_iterator_open_time (&tickets),
204 ticket_iterator_open_note (&tickets),
205 ticket_iterator_nvt_oid (&tickets));
206
207 if (ticket_iterator_task_id (&tickets))
208 SENDF_TO_CLIENT_OR_FAIL ("<task id=\"%s\">"
209 "<name>%s</name>"
210 "<trash>%i</trash>"
211 "</task>",
212 ticket_iterator_task_id (&tickets),
213 ticket_iterator_task_name (&tickets),
214 task_in_trash_id (ticket_iterator_task_id
215 (&tickets)));
216
217 if (ticket_iterator_report_id (&tickets))
218 {
219 gchar *timestamp;
220
221 if (report_timestamp (ticket_iterator_report_id (&tickets),
222 ×tamp))
223 g_error ("%s: error getting timestamp of report, aborting",
224 __func__);
225
226 SENDF_TO_CLIENT_OR_FAIL ("<report id=\"%s\">"
227 "<timestamp>%s</timestamp>"
228 "</report>",
229 ticket_iterator_report_id (&tickets),
230 timestamp);
231 }
232
233 /* Send timestamps. */
234
235 if (ticket_iterator_fixed_time (&tickets)
236 && strlen (ticket_iterator_fixed_time (&tickets)))
237 SENDF_TO_CLIENT_OR_FAIL ("<fixed_time>%s</fixed_time>",
238 ticket_iterator_fixed_time (&tickets));
239
240 if (ticket_iterator_fixed_note (&tickets))
241 SENDF_TO_CLIENT_OR_FAIL ("<fixed_note>%s</fixed_note>",
242 ticket_iterator_fixed_note (&tickets));
243
244 if (ticket_iterator_closed_time (&tickets)
245 && strlen (ticket_iterator_closed_time (&tickets)))
246 SENDF_TO_CLIENT_OR_FAIL ("<closed_time>%s</closed_time>",
247 ticket_iterator_closed_time (&tickets));
248
249 if (ticket_iterator_closed_note (&tickets))
250 SENDF_TO_CLIENT_OR_FAIL ("<closed_note>%s</closed_note>",
251 ticket_iterator_closed_note (&tickets));
252
253 if (ticket_iterator_fix_verified_time (&tickets)
254 && strlen (ticket_iterator_fix_verified_time (&tickets)))
255 {
256 SENDF_TO_CLIENT_OR_FAIL ("<fix_verified_time>%s</fix_verified_time>",
257 ticket_iterator_fix_verified_time (&tickets));
258 if (ticket_iterator_fix_verified_report_id (&tickets))
259 {
260 gchar *timestamp;
261
262 if (report_timestamp (ticket_iterator_fix_verified_report_id
263 (&tickets),
264 ×tamp))
265 g_error ("%s: error getting timestamp of verified report,"
266 " aborting",
267 __func__);
268
269 SENDF_TO_CLIENT_OR_FAIL ("<fix_verified_report>"
270 "<report id=\"%s\">"
271 "<timestamp>%s</timestamp>"
272 "</report>"
273 "</fix_verified_report>",
274 ticket_iterator_fix_verified_report_id
275 (&tickets),
276 timestamp);
277 }
278 }
279
280 /* Send results that are linked to ticket. */
281
282 if (init_ticket_result_iterator (&results,
283 get_iterator_uuid (&tickets),
284 get_tickets_data.get.trash))
285 {
286 internal_error_send_to_client (error);
287 get_tickets_reset ();
288 return;
289 }
290 while (next (&results))
291 SENDF_TO_CLIENT_OR_FAIL ("<result id=\"%s\"/>",
292 ticket_result_iterator_result_id (&results));
293 cleanup_iterator (&results);
294
295 SENDF_TO_CLIENT_OR_FAIL ("<orphan>%i</orphan>"
296 "</ticket>",
297 ticket_iterator_orphan (&tickets));
298 count++;
299 }
300 cleanup_iterator (&tickets);
301 filtered = get_tickets_data.get.id
302 ? 1
303 : ticket_count (&get_tickets_data.get);
304 SEND_GET_END ("ticket", &get_tickets_data.get, count, filtered);
305
306 get_tickets_reset ();
307 }
308
309
310 /* CREATE_TICKET. */
311
312 /**
313 * @brief The create_ticket command.
314 */
315 typedef struct
316 {
317 context_data_t *context; ///< XML parser context.
318 } create_ticket_t;
319
320 /**
321 * @brief Parser callback data.
322 *
323 * This is initially 0 because it's a global variable.
324 */
325 static create_ticket_t create_ticket_data;
326
327 /**
328 * @brief Reset command data.
329 */
330 static void
create_ticket_reset()331 create_ticket_reset ()
332 {
333 if (create_ticket_data.context->first)
334 {
335 free_entity (create_ticket_data.context->first->data);
336 g_slist_free_1 (create_ticket_data.context->first);
337 }
338 g_free (create_ticket_data.context);
339 memset (&create_ticket_data, 0, sizeof (create_ticket_t));
340 }
341
342 /**
343 * @brief Start a command.
344 *
345 * @param[in] gmp_parser GMP parser.
346 * @param[in] attribute_names All attribute names.
347 * @param[in] attribute_values All attribute values.
348 */
349 void
create_ticket_start(gmp_parser_t * gmp_parser,const gchar ** attribute_names,const gchar ** attribute_values)350 create_ticket_start (gmp_parser_t *gmp_parser,
351 const gchar **attribute_names,
352 const gchar **attribute_values)
353 {
354 memset (&create_ticket_data, 0, sizeof (create_ticket_t));
355 create_ticket_data.context = g_malloc0 (sizeof (context_data_t));
356 create_ticket_element_start (gmp_parser, "create_ticket", attribute_names,
357 attribute_values);
358 }
359
360 /**
361 * @brief Start element.
362 *
363 * @param[in] gmp_parser GMP parser.
364 * @param[in] name Element name.
365 * @param[in] attribute_names All attribute names.
366 * @param[in] attribute_values All attribute values.
367 */
368 void
create_ticket_element_start(gmp_parser_t * gmp_parser,const gchar * name,const gchar ** attribute_names,const gchar ** attribute_values)369 create_ticket_element_start (gmp_parser_t *gmp_parser, const gchar *name,
370 const gchar **attribute_names,
371 const gchar **attribute_values)
372 {
373 xml_handle_start_element (create_ticket_data.context, name, attribute_names,
374 attribute_values);
375 }
376
377 /**
378 * @brief Execute command.
379 *
380 * @param[in] gmp_parser GMP parser.
381 * @param[in] error Error parameter.
382 */
383 void
create_ticket_run(gmp_parser_t * gmp_parser,GError ** error)384 create_ticket_run (gmp_parser_t *gmp_parser, GError **error)
385 {
386 entity_t entity, copy, comment, result, assigned_to, user, open_note;
387 ticket_t new_ticket;
388 const char *result_id, *user_id;
389
390 entity = (entity_t) create_ticket_data.context->first->data;
391
392 copy = entity_child (entity, "copy");
393
394 if (copy)
395 {
396 /* Copy from an existing ticket and exit. */
397
398 comment = entity_child (entity, "comment");
399 switch (copy_ticket (comment ? entity_text (comment) : "",
400 entity_text (copy),
401 &new_ticket))
402 {
403 case 0:
404 {
405 char *uuid;
406 uuid = ticket_uuid (new_ticket);
407 SENDF_TO_CLIENT_OR_FAIL (XML_OK_CREATED_ID ("create_ticket"),
408 uuid);
409 log_event ("ticket", "Ticket", uuid, "created");
410 free (uuid);
411 break;
412 }
413 case 1:
414 SEND_TO_CLIENT_OR_FAIL
415 (XML_ERROR_SYNTAX ("create_ticket",
416 "Ticket exists already"));
417 log_event_fail ("ticket", "Ticket", NULL, "created");
418 break;
419 case 2:
420 if (send_find_error_to_client ("create_ticket", "ticket",
421 entity_text (copy),
422 gmp_parser))
423 {
424 error_send_to_client (error);
425 return;
426 }
427 log_event_fail ("ticket", "Ticket", NULL, "created");
428 break;
429 case 99:
430 SEND_TO_CLIENT_OR_FAIL
431 (XML_ERROR_SYNTAX ("create_ticket",
432 "Permission denied"));
433 log_event_fail ("ticket", "Ticket", NULL, "created");
434 break;
435 case -1:
436 default:
437 SEND_TO_CLIENT_OR_FAIL
438 (XML_INTERNAL_ERROR ("create_ticket"));
439 log_event_fail ("ticket", "Ticket", NULL, "created");
440 break;
441 }
442 create_ticket_reset ();
443 return;
444 }
445
446 /* Check given info. */
447
448 comment = entity_child (entity, "comment");
449
450 open_note = entity_child (entity, "open_note");
451 if (open_note == NULL)
452 {
453 SEND_TO_CLIENT_OR_FAIL
454 (XML_ERROR_SYNTAX ("create_ticket",
455 "CREATE_TICKET requires an OPEN_NOTE"));
456 create_ticket_reset ();
457 return;
458 }
459
460 result = entity_child (entity, "result");
461 if (result == NULL)
462 {
463 SEND_TO_CLIENT_OR_FAIL
464 (XML_ERROR_SYNTAX ("create_ticket",
465 "CREATE_TICKET requires a RESULT"));
466 create_ticket_reset ();
467 return;
468 }
469
470 assigned_to = entity_child (entity, "assigned_to");
471 if (assigned_to == NULL)
472 {
473 SEND_TO_CLIENT_OR_FAIL
474 (XML_ERROR_SYNTAX ("create_ticket",
475 "CREATE_TICKET requires an ASSIGNED_TO element"));
476 create_ticket_reset ();
477 return;
478 }
479
480 user = entity_child (assigned_to, "user");
481 if (user == NULL)
482 {
483 SEND_TO_CLIENT_OR_FAIL
484 (XML_ERROR_SYNTAX ("create_ticket",
485 "CREATE_TICKET requires USER in ASSIGNED_TO"));
486 create_ticket_reset ();
487 return;
488 }
489
490 /* Create ticket from given info. */
491
492 result_id = entity_attribute (result, "id");
493 user_id = entity_attribute (user, "id");
494
495 if ((result_id == NULL) || (strlen (result_id) == 0))
496 SEND_TO_CLIENT_OR_FAIL
497 (XML_ERROR_SYNTAX ("create_ticket",
498 "CREATE_TICKET RESULT must have an id"
499 " attribute"));
500 else if ((user_id == NULL) || (strlen (user_id) == 0))
501 SEND_TO_CLIENT_OR_FAIL
502 (XML_ERROR_SYNTAX ("create_ticket",
503 "CREATE_TICKET USER must have an id"
504 " attribute"));
505 else if (strlen (entity_text (open_note)) == 0)
506 SEND_TO_CLIENT_OR_FAIL
507 (XML_ERROR_SYNTAX ("create_ticket",
508 "CREATE_TICKET OPEN_NOTE is empty"));
509 else switch (create_ticket
510 (comment ? entity_text (comment) : "",
511 result_id,
512 user_id,
513 entity_text (open_note),
514 &new_ticket))
515 {
516 case 0:
517 {
518 char *uuid = ticket_uuid (new_ticket);
519 SENDF_TO_CLIENT_OR_FAIL (XML_OK_CREATED_ID ("create_ticket"),
520 uuid);
521 log_event ("ticket", "Ticket", uuid, "created");
522 free (uuid);
523 break;
524 }
525 case 1:
526 log_event_fail ("ticket", "Ticket", NULL, "created");
527 if (send_find_error_to_client ("create_ticket", "user", user_id,
528 gmp_parser))
529 {
530 error_send_to_client (error);
531 return;
532 }
533 break;
534 case 2:
535 log_event_fail ("ticket", "Ticket", NULL, "created");
536 if (send_find_error_to_client ("create_ticket", "result", result_id,
537 gmp_parser))
538 {
539 error_send_to_client (error);
540 return;
541 }
542 break;
543 case 98:
544 SEND_TO_CLIENT_OR_FAIL
545 (XML_ERROR_SYNTAX ("create_ticket",
546 "Permission to create permission denied"));
547 log_event_fail ("ticket", "Ticket", NULL, "created");
548 break;
549 case 99:
550 SEND_TO_CLIENT_OR_FAIL
551 (XML_ERROR_SYNTAX ("create_ticket",
552 "Permission denied"));
553 log_event_fail ("ticket", "Ticket", NULL, "created");
554 break;
555 case -1:
556 default:
557 SEND_TO_CLIENT_OR_FAIL (XML_INTERNAL_ERROR ("create_ticket"));
558 log_event_fail ("ticket", "Ticket", NULL, "created");
559 break;
560 }
561
562 create_ticket_reset ();
563 }
564
565 /**
566 * @brief End element.
567 *
568 * @param[in] gmp_parser GMP parser.
569 * @param[in] error Error parameter.
570 * @param[in] name Element name.
571 *
572 * @return 0 success, 1 command finished.
573 */
574 int
create_ticket_element_end(gmp_parser_t * gmp_parser,GError ** error,const gchar * name)575 create_ticket_element_end (gmp_parser_t *gmp_parser, GError **error,
576 const gchar *name)
577 {
578 xml_handle_end_element (create_ticket_data.context, name);
579 if (create_ticket_data.context->done)
580 {
581 create_ticket_run (gmp_parser, error);
582 return 1;
583 }
584 return 0;
585 }
586
587 /**
588 * @brief Add text to element.
589 *
590 * @param[in] text Text.
591 * @param[in] text_len Text length.
592 */
593 void
create_ticket_element_text(const gchar * text,gsize text_len)594 create_ticket_element_text (const gchar *text, gsize text_len)
595 {
596 xml_handle_text (create_ticket_data.context, text, text_len);
597 }
598
599
600 /* MODIFY_TICKET. */
601
602 /**
603 * @brief The modify_ticket command.
604 */
605 typedef struct
606 {
607 context_data_t *context; ///< XML parser context.
608 } modify_ticket_t;
609
610 /**
611 * @brief Parser callback data.
612 *
613 * This is initially 0 because it's a global variable.
614 */
615 static modify_ticket_t modify_ticket_data;
616
617 /**
618 * @brief Reset command data.
619 */
620 static void
modify_ticket_reset()621 modify_ticket_reset ()
622 {
623 if (modify_ticket_data.context->first)
624 {
625 free_entity (modify_ticket_data.context->first->data);
626 g_slist_free_1 (modify_ticket_data.context->first);
627 }
628 g_free (modify_ticket_data.context);
629 memset (&modify_ticket_data, 0, sizeof (modify_ticket_t));
630 }
631
632 /**
633 * @brief Start a command.
634 *
635 * @param[in] gmp_parser GMP parser.
636 * @param[in] attribute_names All attribute names.
637 * @param[in] attribute_values All attribute values.
638 */
639 void
modify_ticket_start(gmp_parser_t * gmp_parser,const gchar ** attribute_names,const gchar ** attribute_values)640 modify_ticket_start (gmp_parser_t *gmp_parser,
641 const gchar **attribute_names,
642 const gchar **attribute_values)
643 {
644 memset (&modify_ticket_data, 0, sizeof (modify_ticket_t));
645 modify_ticket_data.context = g_malloc0 (sizeof (context_data_t));
646 modify_ticket_element_start (gmp_parser, "modify_ticket", attribute_names,
647 attribute_values);
648 }
649
650 /**
651 * @brief Start element.
652 *
653 * @param[in] gmp_parser GMP parser.
654 * @param[in] name Element name.
655 * @param[in] attribute_names All attribute names.
656 * @param[in] attribute_values All attribute values.
657 */
658 void
modify_ticket_element_start(gmp_parser_t * gmp_parser,const gchar * name,const gchar ** attribute_names,const gchar ** attribute_values)659 modify_ticket_element_start (gmp_parser_t *gmp_parser, const gchar *name,
660 const gchar **attribute_names,
661 const gchar **attribute_values)
662 {
663 xml_handle_start_element (modify_ticket_data.context, name, attribute_names,
664 attribute_values);
665 }
666
667 /**
668 * @brief Execute command.
669 *
670 * @param[in] gmp_parser GMP parser.
671 * @param[in] error Error parameter.
672 */
673 void
modify_ticket_run(gmp_parser_t * gmp_parser,GError ** error)674 modify_ticket_run (gmp_parser_t *gmp_parser, GError **error)
675 {
676 entity_t entity, comment, status, open_note, fixed_note, closed_note;
677 entity_t assigned_to;
678 const char *ticket_id, *user_id;
679
680 entity = (entity_t) modify_ticket_data.context->first->data;
681
682 ticket_id = entity_attribute (entity, "ticket_id");
683
684 /* Check the given info. */
685
686 comment = entity_child (entity, "comment");
687 status = entity_child (entity, "status");
688 open_note = entity_child (entity, "open_note");
689 fixed_note = entity_child (entity, "fixed_note");
690 closed_note = entity_child (entity, "closed_note");
691
692 assigned_to = entity_child (entity, "assigned_to");
693 if (assigned_to)
694 {
695 entity_t user;
696
697 user = entity_child (assigned_to, "user");
698 if (user == NULL)
699 {
700 SEND_TO_CLIENT_OR_FAIL
701 (XML_ERROR_SYNTAX ("modify_ticket",
702 "MODIFY_TICKET requires USER in ASSIGNED_TO"));
703 modify_ticket_reset ();
704 return;
705 }
706
707 user_id = entity_attribute (user, "id");
708 if ((user_id == NULL) || (strlen (user_id) == 0))
709 {
710 SEND_TO_CLIENT_OR_FAIL
711 (XML_ERROR_SYNTAX ("modify_ticket",
712 "MODIFY_TICKET USER must have an id"
713 " attribute"));
714 modify_ticket_reset ();
715 return;
716 }
717 }
718 else
719 user_id = NULL;
720
721 /* Modify the ticket. */
722
723 if (ticket_id == NULL)
724 SEND_TO_CLIENT_OR_FAIL
725 (XML_ERROR_SYNTAX ("modify_ticket",
726 "MODIFY_TICKET requires a ticket_id"
727 " attribute"));
728 else switch (modify_ticket
729 (ticket_id,
730 comment ? entity_text (comment) : NULL,
731 status ? entity_text (status) : NULL,
732 open_note ? entity_text (open_note) : NULL,
733 fixed_note ? entity_text (fixed_note) : NULL,
734 closed_note ? entity_text (closed_note) : NULL,
735 user_id))
736 {
737 case 0:
738 SENDF_TO_CLIENT_OR_FAIL (XML_OK ("modify_ticket"));
739 log_event ("ticket", "Ticket", ticket_id, "modified");
740 break;
741 case 1:
742 SEND_TO_CLIENT_OR_FAIL
743 (XML_ERROR_SYNTAX ("modify_ticket",
744 "Ticket exists already"));
745 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
746 break;
747 case 2:
748 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
749 if (send_find_error_to_client ("modify_ticket", "ticket", ticket_id,
750 gmp_parser))
751 {
752 error_send_to_client (error);
753 return;
754 }
755 break;
756 case 3:
757 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
758 if (send_find_error_to_client ("modify_ticket", "user", user_id,
759 gmp_parser))
760 {
761 error_send_to_client (error);
762 return;
763 }
764 break;
765 case 4:
766 SEND_TO_CLIENT_OR_FAIL
767 (XML_ERROR_SYNTAX ("modify_ticket",
768 "Error in status"));
769 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
770 break;
771 case 5:
772 SEND_TO_CLIENT_OR_FAIL
773 (XML_ERROR_SYNTAX ("modify_ticket",
774 "Fixed STATUS requires a FIXED_NOTE"));
775 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
776 break;
777 case 6:
778 SEND_TO_CLIENT_OR_FAIL
779 (XML_ERROR_SYNTAX ("modify_ticket",
780 "Closed STATUS requires a CLOSED_NOTE"));
781 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
782 break;
783 case 7:
784 SEND_TO_CLIENT_OR_FAIL
785 (XML_ERROR_SYNTAX ("modify_ticket",
786 "Open STATUS requires an OPEN_NOTE"));
787 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
788 break;
789 case 99:
790 SEND_TO_CLIENT_OR_FAIL
791 (XML_ERROR_SYNTAX ("modify_ticket",
792 "Permission denied"));
793 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
794 break;
795 case -1:
796 default:
797 SEND_TO_CLIENT_OR_FAIL
798 (XML_INTERNAL_ERROR ("modify_ticket"));
799 log_event_fail ("ticket", "Ticket", ticket_id, "modified");
800 break;
801 }
802
803 modify_ticket_reset ();
804 }
805
806 /**
807 * @brief End element.
808 *
809 * @param[in] gmp_parser GMP parser.
810 * @param[in] error Error parameter.
811 * @param[in] name Element name.
812 *
813 * @return 0 success, 1 command finished.
814 */
815 int
modify_ticket_element_end(gmp_parser_t * gmp_parser,GError ** error,const gchar * name)816 modify_ticket_element_end (gmp_parser_t *gmp_parser, GError **error,
817 const gchar *name)
818 {
819 xml_handle_end_element (modify_ticket_data.context, name);
820 if (modify_ticket_data.context->done)
821 {
822 modify_ticket_run (gmp_parser, error);
823 return 1;
824 }
825 return 0;
826 }
827
828 /**
829 * @brief Add text to element.
830 *
831 * @param[in] text Text.
832 * @param[in] text_len Text length.
833 */
834 void
modify_ticket_element_text(const gchar * text,gsize text_len)835 modify_ticket_element_text (const gchar *text, gsize text_len)
836 {
837 xml_handle_text (modify_ticket_data.context, text, text_len);
838 }
839
840
841 /* Result ticket support. */
842
843 /**
844 * @brief Buffer ticket XML for a result.
845 *
846 * @param[in] buffer Buffer.
847 * @param[in] result Result.
848 *
849 * @return 0 success, -1 internal error.
850 */
851 int
buffer_result_tickets_xml(GString * buffer,result_t result)852 buffer_result_tickets_xml (GString *buffer, result_t result)
853 {
854 iterator_t tickets;
855 int ret;
856
857 ret = init_result_ticket_iterator (&tickets, result);
858
859 if (ret == 0)
860 {
861 buffer_xml_append_printf (buffer, "<tickets>");
862 while (next (&tickets))
863 buffer_xml_append_printf (buffer,
864 "<ticket id=\"%s\"/>",
865 result_ticket_iterator_ticket_id
866 (&tickets));
867 buffer_xml_append_printf (buffer, "</tickets>");
868 cleanup_iterator (&tickets);
869 }
870
871 return ret;
872 }
873