1 /*
2  * Copyright (C) 2006-2021 Registro.br. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * 1. Redistribution of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY REGISTRO.BR ``AS IS AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIE OF FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16  * EVENT SHALL REGISTRO.BR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
19  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
21  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
22  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
23  * DAMAGE.
24  */
25 /* $Id$ */
26 /** @file SheppObjSet.H
27  *  @brief shepp specific objects information setting class
28  */
29 
30 #ifndef __SHEPP_OBJ_SET_H__
31 #define __SHEPP_OBJ_SET_H__
32 
33 #include "CommonData.H"
34 #include "DomainUpdateCmd.H"
35 #include "DefRegUpdateCmd.H"
36 #include "RGPRestore.H"
37 #include "ClaimsNotice.H"
38 
39 /// shepp specific objects information setting class
40 class SheppObjSet {
41 public:
42 
43 	/// reads an IpRange object from args
44 	/**
45 	   @param input     IP range command-line param
46 	   @param ipRange   IpRange object to be filled
47 	   @return 0 if ok, -1 ortherwise
48 	*/
parse_iprange(const string & input,IpRange & ipRange)49 	static int parse_iprange(const string &input, IpRange &ipRange) {
50 		string error_msg("");
51 
52 		string version;
53 		string range;
54 		string ipBegin;
55 		string ipEnd;
56 
57 		if (SheppStrUtil::split(input, version, range, "=", false) != 0 ||
58 		    SheppStrUtil::split(range, ipBegin, ipEnd, "-", false) != 0) {
59 			return -1;
60 		}
61 
62 		ipRange.set_version(version);
63 		ipRange.set_ipBegin(ipBegin);
64 		ipRange.set_ipEnd(ipEnd);
65 
66 		return 0;
67 	}
68 
69 	//used by both contact and domain
70 
71 	/// fills an AuthInfo based on input command line
72 	/**
73 	   @param auth    reference to an AuthInfo object to be set
74 	   @param words   vector with command-line arguments
75 	   @return 0 if ok, -1 otherwise
76 	*/
authInfo(AuthInfo & auth,vector<string> & words)77 	static int authInfo(AuthInfo &auth, vector<string> &words)
78 	{
79 		words.erase(words.begin());
80 
81 		if (words.size() <= 0) {
82 			return -1;
83 		}
84 
85 		string pw;
86 		string roid;
87 		if (SheppStrUtil::split(words[0], pw, roid, ":", true) != 0) {
88 			return -1;
89 		}
90 
91 		auth.set_pw(pw);
92 		auth.set_roid(roid);
93 
94 		words.erase(words.begin());
95 
96 		return 0;
97 	}
98 
99 	//domain specific
100 
101 	/// fills a NameServer based on input command line
102 	/**
103 	   @param ns      reference to a NameServer object to be set
104 	   @param words   vector with command-line arguments
105 	   @return 0 if ok, -1 otherwise
106 	*/
nameServer(NameServer & ns,vector<string> & words)107 	static int nameServer(NameServer &ns, vector<string> &words)
108 	{
109 		words.erase(words.begin());
110 		if (words.empty()) {
111 			return -1;
112 		}
113 
114 		string ips;
115 		SheppStrUtil::split(words[0], ns.name, ips, ",", true);
116 
117 		if (ips != "") {
118 			string this_ip;
119 			do {
120 				if (SheppStrUtil::split(ips, this_ip, ips, ",", true) != 0) {
121 					return -1;
122 				}
123 
124 				NSIPAddr ip;
125 				if (SheppStrUtil::split(this_ip, ip.version, ip.addr, ":", false)
126 				    != 0) {
127 					return -1;
128 				}
129 
130 				ns.ips.insert(ip);
131 			} while (ips != "");
132 		}
133 
134 		words.erase(words.begin());
135 
136 		return 0;
137 	}
138 
139 	/// fills a Status based on input command line
140 	/**
141 	   @param status      reference to a Status object to be set
142 	   @param words       vector with command-line arguments
143 	   @return 0 if ok, -1 otherwise
144 	*/
status(DomainUpdateCmd::Status & st,vector<string> & words)145 	static int status(DomainUpdateCmd::Status &st, vector<string> &words)
146 	{
147 		string status;
148 		string lang;
149 		string description;
150 
151 		if (SheppStrUtil::split(words[0], status, lang, ":", false) != 0) {
152 			return -1;
153 		}
154 		words.erase(words.begin());
155 
156 		if (SheppStrUtil::split(lang, lang, description, ":", false) != 0) {
157 			return -1;
158 		}
159 
160 		SheppStrUtil::quote_gathering(words, description);
161 
162 		st.s = status;
163 		st.lang = lang;
164 		st.msg = description;
165 
166 		return 0;
167 	}
168 
169 	/// fills a Status based on input command line
170 	/**
171 	   @param status      reference to a Status object to be set
172 	   @param words       vector with command-line arguments
173 	   @return 0 if ok, -1 otherwise
174 	*/
status(DefRegUpdateCmd::Status & st,vector<string> & words)175 	static int status(DefRegUpdateCmd::Status &st, vector<string> &words)
176 	{
177 		string status;
178 		string lang;
179 		string description;
180 
181 		if (SheppStrUtil::split(words[0], status, lang, ":", false) != 0) {
182 			return -1;
183 		}
184 		words.erase(words.begin());
185 
186 		if (SheppStrUtil::split(lang, lang, description, ":", false) != 0) {
187 			return -1;
188 		}
189 
190 		SheppStrUtil::quote_gathering(words, description);
191 
192 		st.set_status(status);
193 		st.set_lang(lang);
194 		st.set_msg(description);
195 
196 		return 0;
197 	}
198 
199 	/// fills a DSInfo based on input command line
200 	/**
201 	   @param ds      reference to a DSInfo object to be set
202 	   @param words   vector with command-line arguments
203 	   @return 0 if ok, -1 otherwise
204 	*/
dsInfo(DSInfo & ds,vector<string> & words,string & error_msg)205 	static int dsInfo(DSInfo &ds, vector<string> &words, string &error_msg)
206 	{
207 		words.erase(words.begin()); // -ds
208 
209 		// must have at least 4 elements: keytag, algorithm, digtype and digest
210 		if (words.size() < 4) {
211 			error_msg = "not enough arguments for DS";
212 			return -1;
213 		}
214 
215 		// parse the key tag: check if it has only numbers
216 		string c;
217 		for (unsigned int i = 0; i < words[0].length(); i++) {
218 			c = words[0][i];
219 			if (c != "0" && atoi(c.c_str()) == 0) {
220 				error_msg = "keyTag must be a number";
221 				return -1;
222 			}
223 		}
224 
225 		int key_tag = atoi(words[0].c_str());
226 		if (key_tag < 0) {
227 			error_msg = "keyTag cannot be a negative number";
228 			return -1;
229 		}
230 		ds.set_key_tag(key_tag);
231 
232 		int alg = atoi(words[1].c_str());
233 		if (alg < 0) {
234 			error_msg = "alg cannot be a negative number";
235 			return -1;
236 		}
237 		ds.set_algo(alg);
238 
239 		int dig_type = atoi(words[2].c_str());
240 		if (dig_type < 0) {
241 			error_msg = "digestType cannot be a negative number";
242 			return -1;
243 		}
244 		ds.set_digest_type(dig_type);
245 		ds.set_digest(words[3]);
246 
247 		words.erase(words.begin(), words.begin() + 4);
248 
249 		//optional parameters
250 		while (!words.empty()) {
251 			if (words[0] == "-maxlife") {
252 				if (words.size() < 2) {
253 					error_msg = "maxSigLife value missing";
254 					return -1;
255 				}
256 				words.erase(words.begin()); // -maxlife
257 				int maxlife = atoi(words[0].c_str());
258 				if (maxlife < 0) {
259 					error_msg = "maxSigLife cannot be a negative number";
260 					return -1;
261 				}
262 				ds.set_max_sig_life(maxlife);
263 				words.erase(words.begin()); // maxlife value
264 			} else if (words[0] == "-keyData") {
265 				KeyData dnskey;
266 				if (SheppObjSet::keyData(dnskey, words, error_msg) != 0) {
267 					return -1;
268 				}
269 				ds.set_key_data(dnskey);
270 			} else {
271 				break;
272 			}
273 		}
274 
275 		return 0;
276 	}
277 
278 	/// fills a ReverseDSInfo based on input command line
279 	/**
280 	   @param ds      reference to a ReverseDSInfo object to be set
281 	   @param words   vector with command-line arguments
282 	   @return 0 if ok, -1 otherwise
283 	*/
dsInfo(ReverseDSInfo & ds,vector<string> & words,string & error_msg)284 	static int dsInfo(ReverseDSInfo &ds, vector<string> &words, string &error_msg)
285 	{
286 		words.erase(words.begin()); // -ds
287 
288 		// must have at least 5 elements: ipRange, keytag, algorithm,
289 		// digtype and digest
290 		if (words.size() < 5) {
291 			error_msg = "not enough arguments for DS";
292 			return -1;
293 		}
294 
295 		IpRange ipRange;
296 		if (parse_iprange(words[0], ipRange) != 0) {
297 			error_msg = "invalid IP range";
298 			return -1;
299 		}
300 		ds.set_ipRange(ipRange);
301 
302 		// parse the key tag: check if it has only numbers
303 		string c;
304 		for (unsigned int i = 0; i < words[1].length(); i++) {
305 			c = words[1][i];
306 			if (c != "0" && atoi(c.c_str()) == 0) {
307 				error_msg = "keyTag must be a number";
308 				return -1;
309 			}
310 		}
311 
312 		int key_tag = atoi(words[1].c_str());
313 		if (key_tag < 0) {
314 			error_msg = "keyTag cannot be a negative number";
315 			return -1;
316 		}
317 		ds.set_key_tag(key_tag);
318 
319 		int alg = atoi(words[2].c_str());
320 		if (alg < 0) {
321 			error_msg = "alg cannot be a negative number";
322 			return -1;
323 		}
324 		ds.set_algo(alg);
325 
326 		int dig_type = atoi(words[3].c_str());
327 		if (dig_type < 0) {
328 			error_msg = "digestType cannot be a negative number";
329 			return -1;
330 		}
331 		ds.set_digest_type(dig_type);
332 		ds.set_digest(words[4]);
333 
334 		words.erase(words.begin(), words.begin() + 5);
335 		return 0;
336 	}
337 
338 	/// fills a KeyData based on input command line
339 	/**
340 	   @param dnskey  reference to a KeyData object to be set
341 	   @param words   vector with command-line arguments
342 	   @return 0 if ok, -1 otherwise
343 	*/
keyData(KeyData & dnskey,vector<string> & words,string & error_msg)344 	static int keyData(KeyData &dnskey, vector<string> &words, string &error_msg)
345 	{
346 		if (words.size() < 5) {
347 			error_msg = "not enough arguments for keyData";
348 			return -1;
349 		}
350 
351 		int flags = atoi(words[1].c_str());
352 		int protocol = atoi(words[2].c_str());
353 		int algorithm = atoi(words[3].c_str());
354 
355 		if (flags < 0 || protocol < 0 || algorithm < 0) {
356 			error_msg = "keyData flags, protocol and alg cannot be negative numbers";
357 			return -1;
358 		}
359 
360 		dnskey.set_flags(flags);
361 		dnskey.set_protocol(protocol);
362 		dnskey.set_algorithm(algorithm);
363 		dnskey.set_pub_key(words[4]);
364 
365 		words.erase(words.begin(), words.begin() + 5);
366 
367 		return 0;
368 	}
369 
370 	//contact specific
371 
372 	/// fills a PostalInfo based on input command line
373 	/**
374 	   @param postal      reference to a PostalInfo object to be set
375 	   @param words       vector with command-line arguments
376 	   @param error_msg   string to hold error msg on return -1
377 	   @param relaxed     true for update, false for create
378 	   @return 0 if ok, -1 otherwise
379 	*/
postalInfo(PostalInfo & postal,vector<string> & words,string & error_msg,bool relaxed)380 	static int postalInfo(PostalInfo &postal, vector<string> &words,
381 	                      string &error_msg, bool relaxed)
382 	{
383 		//type
384 		string postal_type = words[0];
385 		words.erase(words.begin());
386 		if (SheppStrUtil::quote_gathering(words, postal_type) != 0) {
387 			error_msg = "error setting postalInfo type";
388 			return -1;
389 		}
390 		postal.set_type(postal_type);
391 
392 		while (!words.empty()) {
393 			if (words[0] == "-name") {
394 				//name
395 				words.erase(words.begin());
396 				if (words.empty()) {
397 					error_msg = "unspecified contact name";
398 					return -1;
399 				}
400 				string postal_name = words[0];
401 				words.erase(words.begin());
402 				if (SheppStrUtil::quote_gathering(words, postal_name) != 0) {
403 					error_msg = "error setting contact name";
404 					return -1;
405 				}
406 				postal.set_name(postal_name);
407 			} else if (words[0] == "-org") {
408 				//org
409 				words.erase(words.begin());
410 				if (words.empty()) {
411 					error_msg = "unspecified organization";
412 					return -1;
413 				}
414 				string postal_org = words[0];
415 				words.erase(words.begin());
416 				if (SheppStrUtil::quote_gathering(words, postal_org) != 0) {
417 					error_msg = "error setting organization";
418 					return -1;
419 				}
420 				postal.set_org(postal_org);
421 			} else if (words[0] == "-street1") {
422 				//street1
423 				words.erase(words.begin());
424 				if (words.empty()) {
425 					error_msg = "unspecified address street/line 1";
426 					return -1;
427 				}
428 				string postal_str1 = words[0];
429 				words.erase(words.begin());
430 				if (SheppStrUtil::quote_gathering(words, postal_str1) != 0) {
431 					error_msg = "error setting address street/line 1";
432 					return -1;
433 				}
434 				postal.set_str1(postal_str1);
435 			} else if (words[0] == "-street2") {
436 				//street2
437 				words.erase(words.begin());
438 				if (words.empty()) {
439 					error_msg = "unspecified address number/line 2";
440 					return -1;
441 				}
442 				string postal_str2 = words[0];
443 				words.erase(words.begin());
444 				if (SheppStrUtil::quote_gathering(words, postal_str2) != 0) {
445 					error_msg = "error setting address number/line 2";
446 					return -1;
447 				}
448 				postal.set_str2(postal_str2);
449 			} else if (words[0] == "-street3") {
450 				//street3
451 				words.erase(words.begin());
452 				if (words.empty()) {
453 					error_msg = "unspecified street3";
454 					return -1;
455 				}
456 				string postal_str3 = words[0];
457 				words.erase(words.begin());
458 				if (SheppStrUtil::quote_gathering(words, postal_str3) != 0) {
459 					error_msg = "error setting address line 3";
460 					return -1;
461 				}
462 				postal.set_str3(postal_str3);
463 			} else if (words[0] == "-city") {
464 				//city
465 				words.erase(words.begin());
466 				if (words.empty()) {
467 					error_msg = "unspecified city";
468 					return -1;
469 				}
470 				string postal_city = words[0];
471 				words.erase(words.begin());
472 				if (SheppStrUtil::quote_gathering(words, postal_city) != 0) {
473 					error_msg = "error setting city";
474 					return -1;
475 				}
476 				postal.set_city(postal_city);
477 			} else if (words[0] == "-state") {
478 				//state
479 				words.erase(words.begin());
480 				if (words.empty()) {
481 					error_msg = "unspecified state";
482 					return -1;
483 				}
484 				string postal_sp = words[0];
485 				words.erase(words.begin());
486 				if (SheppStrUtil::quote_gathering(words, postal_sp) != 0) {
487 					error_msg = "error setting state/province";
488 					return -1;
489 				}
490 				postal.set_sp(postal_sp);
491 			} else if (words[0] == "-pc") {
492 				//pc
493 				words.erase(words.begin());
494 				if (words.empty()) {
495 					error_msg = "unspecified postal code";
496 					return -1;
497 				}
498 				string postal_pc = words[0];
499 				words.erase(words.begin());
500 				if (SheppStrUtil::quote_gathering(words, postal_pc) != 0) {
501 					error_msg = "error setting postal code";
502 					return -1;
503 				}
504 				postal.set_pc(postal_pc);
505 			} else if (words[0] == "-cc") {
506 				//cc
507 				words.erase(words.begin());
508 				if (words.empty()) {
509 					error_msg = "unspecified country code";
510 					return -1;
511 				}
512 				string postal_cc = words[0];
513 				words.erase(words.begin());
514 				if (SheppStrUtil::quote_gathering(words, postal_cc) != 0) {
515 					error_msg = "error setting country code";
516 					return -1;
517 				}
518 				postal.set_cc(postal_cc);
519 			} else {
520 				break;
521 			}
522 		}
523 
524 		//relaxed: update; !relaxed: create
525 		if (!relaxed) {
526 			if (postal.get_name() == "") {
527 				error_msg = "name is mandatory";
528 				return -1;
529 			}
530 
531 			if (postal.get_str1() == "") {
532 				error_msg = "address street/line 1 is mandatory";
533 				return -1;
534 			}
535 
536 			if (postal.get_city() == "") {
537 				error_msg = "city is mandatory";
538 				return -1;
539 			}
540 
541 			if (postal.get_cc() == "") {
542 				error_msg = "country code is mandatory";
543 				return -1;
544 			}
545 		} else {
546 			if (postal.get_name() == "" &&
547 			    postal.get_org() == "" &&
548 			    postal.get_str1() == "" &&
549 			    postal.get_str2() == "" &&
550 			    postal.get_str3() == "" &&
551 			    postal.get_city() == "" &&
552 			    postal.get_sp() == "" &&
553 			    postal.get_pc() == "" &&
554 			    postal.get_cc() == "") {
555 				error_msg = "empty postal info";
556 				return -1;
557 			}
558 		}
559 
560 		return 0;
561 	}
562 
563 	/// fills a Phone based on input command line
564 	/**
565 	   @param phone   reference to a Phone object to be set
566 	   @param words   vector with command-line arguments
567 	   @return 0 if ok, -1 otherwise
568 	*/
phone(CommonData::Phone & phone,vector<string> & words)569 	static int phone(CommonData::Phone &phone, vector<string> &words)
570 	{
571 		if (words.empty() ||
572 		    SheppStrUtil::split(words[0], phone.number, phone.ext, ":", true)
573 		    != 0) {
574 			return -1;
575 		}
576 		words.erase(words.begin());
577 		return 0;
578 	}
579 
580 	/// fills a Disclose based on input command line
581 	/**
582 	   @param disclose   reference to a Disclose object to be set
583 	   @param word       input string with disclose info
584 	   @return 0 if ok, -1 otherwise
585 	*/
disclose(CommonData::Disclose & disclose,string word)586 	static int disclose(CommonData::Disclose &disclose, string word)
587 	{
588 		string opt1 = word;
589 		string opt2;
590 		while (opt1 != "" &&
591 		       SheppStrUtil::split(opt1, opt1, opt2, ",", true) == 0) {
592 			if (opt1 == "name_int") {
593 				disclose.name_int = true;
594 			} else if (opt1 == "name_loc") {
595 				disclose.name_loc = true;
596 			} else if (opt1 == "org_int") {
597 				disclose.org_int = true;
598 			} else if (opt1 == "org_loc") {
599 				disclose.org_loc = true;
600 			} else if (opt1 == "addr_int") {
601 				disclose.addr_int = true;
602 			} else if (opt1 == "addr_loc") {
603 				disclose.addr_loc = true;
604 			} else if (opt1 == "voice") {
605 				disclose.voice = true;
606 			} else if (opt1 == "fax") {
607 				disclose.fax = true;
608 			} else if (opt1 == "email") {
609 				disclose.email = true;
610 			} else {
611 				return -1;
612 			}
613 			opt1 = opt2;
614 		}
615 		return 0;
616 	}
617 
618 	// brorg specific
619 
620 	/// fills a map of contacts based on input command line
621 	/**
622 	   @param contacts    reference to the map of contacts to be filled
623 	   @param args        input string with contacts info
624 	   @param error_msg   string to hold error msg on return -1
625 	   @return 0 if ok, -1 otherwise
626 	*/
contacts(map<string,string,less<string>> & contacts,string args,string & error_msg)627 	static int contacts(map<string, string, less<string> > &contacts,
628 	                    string args, string &error_msg)
629 	{
630 		string one = args;
631 		string rest;
632 
633 		do {
634 			if (SheppStrUtil::split(one, one, rest, ",", true) != 0) {
635 				error_msg = "invalid contact";
636 				return -1;
637 			}
638 
639 			string key;
640 			string value;
641 			if (SheppStrUtil::split(one, key, value, "=", false) != 0) {
642 				error_msg = "invalid contact";
643 				return -1;
644 			}
645 
646 			contacts[key] = value;
647 
648 			one = rest;
649 		} while (one != "");
650 
651 		return 0;
652 	}
653 
654 	/// Fill a claims notice object
655 	/**
656 	   @param notice Object to be filled
657 	   @param words parameters
658 	   @param errorMsg Error message, if any
659 	   @return 0 if ok, -1 otherwise
660 	 */
claimsNotice(ClaimsNotice & notice,vector<string> & words,string & error)661 	static int claimsNotice(ClaimsNotice &notice, vector<string> &words, string &error)
662 	{
663 		words.erase(words.begin());
664 		if (words.size() < 3) {
665 			error = "not enough arguments for Claims Notice";
666 			return -1;
667 		}
668 
669 		notice.set_id(words[0]);
670 		notice.set_acceptedDate(words[1]);
671 		notice.set_notAfter(words[2]);
672 		words.erase(words.begin(), words.begin() + 3);
673 		return 0;
674 	}
675 
676 	/// fill a registry grace period structure
677 	/**
678 	   @param words       RGP command-line params
679 	   @param rgp_restore RGP object to be filled
680 	   @param error_msg   When the funciton returns -1, the error will
681                         be stored here
682 	   @return 0 if ok, -1 otherwise
683 	*/
rgpRestore(vector<string> & words,RGPRestore & rgp_restore,string & error_msg)684 	static int rgpRestore(vector<string> &words,
685 	                      RGPRestore &rgp_restore,
686 	                      string &error_msg)
687 	{
688 		words.erase(words.begin()); // -rgp
689 
690 		if (words.empty()) {
691 			error_msg = "invalid number of arguments for RGP";
692 			return -1;
693 		}
694 
695 		rgp_restore.set_operation(RGPRestore::Operation::fromString(words[0]));
696 		if (rgp_restore.get_operation() == RGPRestore::Operation::NONE) {
697 			error_msg = "invalid RGP operation";
698 			return -1;
699 		}
700 
701 		words.erase(words.begin()); // operation
702 		bool fillReport = false;
703 
704 		while(!words.empty()) {
705 			if (words[0] == "-rgp-report") {
706 				if (rgp_restore.get_operation() == RGPRestore::Operation::REQUEST) {
707 					error_msg = "RGP request do not have -rgp-report parameters";
708 					return -1;
709 				}
710 
711 				words.erase(words.begin()); // -rgp-report
712 
713 				RGPReport rgp_report = rgp_restore.get_report();
714 
715 				if (words.empty()) {
716 					error_msg = "pre data is missing in RGP report";
717 					return -1;
718 				}
719 
720 				string pre_data = words[0];
721 				words.erase(words.begin());
722 				if (SheppStrUtil::quote_gathering(words, pre_data) != 0) {
723 					error_msg = "invalid pre data in RGP report";
724 					return -1;
725 				}
726 				rgp_report.set_pre_data(pre_data);
727 
728 				if (words.empty()) {
729 					error_msg = "post data is missing in RGP report";
730 					return -1;
731 				}
732 
733 				string post_data = words[0];
734 				words.erase(words.begin());
735 				if (SheppStrUtil::quote_gathering(words, post_data) != 0) {
736 					error_msg = "invalid post data in RGP report";
737 					return -1;
738 				}
739 				rgp_report.set_post_data(post_data);
740 
741 				if (words.empty()) {
742 					error_msg = "del time is missing in RGP report";
743 					return -1;
744 				}
745 
746 				rgp_report.set_del_time(words[0]);
747 				words.erase(words.begin()); // del_time
748 
749 				if (words.empty()) {
750 					error_msg = "res time is missing in RGP report";
751 					return -1;
752 				}
753 
754 				rgp_report.set_res_time(words[0]);
755 				words.erase(words.begin()); // res_time
756 
757 				if (words.empty()) {
758 					error_msg = "res reason is missing in RGP report";
759 					return -1;
760 				}
761 
762 				string res_reason = words[0];
763 				words.erase(words.begin());
764 				if (SheppStrUtil::quote_gathering(words, res_reason) != 0) {
765 					error_msg = "invalid res reason in RGP report";
766 					return -1;
767 				}
768 				rgp_report.set_res_reason(res_reason);
769 
770 				if (words.empty()) {
771 					error_msg = "statement is missing in RGP report";
772 					return -1;
773 				}
774 
775 				string statement1 = words[0];
776 				words.erase(words.begin());
777 				if (SheppStrUtil::quote_gathering(words, statement1) != 0) {
778 					error_msg = "invalid statement in RGP report";
779 					return -1;
780 				}
781 				rgp_report.set_statement1(statement1);
782 
783 				if (words.empty()) {
784 					error_msg = "statement is missing in RGP report";
785 					return -1;
786 				}
787 
788 				string statement2 = words[0];
789 				words.erase(words.begin());
790 				if (SheppStrUtil::quote_gathering(words, statement2) != 0) {
791 					error_msg = "invalid statement in RGP report";
792 					return -1;
793 				}
794 				rgp_report.set_statement2(statement2);
795 
796 				rgp_restore.set_report(rgp_report);
797 				fillReport = true;
798 
799 			} else if (words[0] == "-rgp-other") {
800 				words.erase(words.begin()); // -rgp-other
801 
802 				if (words.empty()) {
803 					error_msg = "other value missing in RGP report";
804 					return -1;
805 				}
806 
807 				string other = words[0];
808 				words.erase(words.begin());
809 				if (SheppStrUtil::quote_gathering(words, other) != 0) {
810 					error_msg = "invalid other in RGP report";
811 					return -1;
812 				}
813 
814 				RGPReport rgp_report = rgp_restore.get_report();
815 				rgp_report.set_other(other);
816 				rgp_restore.set_report(rgp_report);
817 
818 			} else {
819 				break;
820 			}
821 		}
822 
823 		if (rgp_restore.get_operation() == RGPRestore::Operation::REPORT && !fillReport) {
824 			error_msg = "RGP report fields are mandatory";
825 			return -1;
826 		}
827 
828 		return 0;
829 	}
830 };
831 
832 #endif //__SHEPP_OBJ_SET_H__
833