Line data Source code
1 : // Snap Websites Server -- path canonicalization
2 : // Copyright (c) 2011-2019 Made to Order Software Corp. All Rights Reserved
3 : //
4 : // https://snapwebsites.org/
5 : // contact@m2osw.com
6 : //
7 : // This program is free software; you can redistribute it and/or modify
8 : // it under the terms of the GNU General Public License as published by
9 : // the Free Software Foundation; either version 2 of the License, or
10 : // (at your option) any later version.
11 : //
12 : // This program is distributed in the hope that it will be useful,
13 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : // GNU General Public License for more details.
16 : //
17 : // You should have received a copy of the GNU General Public License
18 : // along with this program; if not, write to the Free Software
19 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 : #pragma once
21 :
22 : #include "snapwebsites/snap_parser.h"
23 : #include "snapwebsites/snap_string_list.h"
24 :
25 : #include <QtSerialization/QSerializationReader.h>
26 : #include <QtSerialization/QSerializationFieldTag.h>
27 : #include <QtSerialization/QSerializationWriter.h>
28 :
29 : #include <QMap>
30 :
31 : namespace snap
32 : {
33 :
34 0 : class snap_uri_exception : public snap_exception
35 : {
36 : public:
37 0 : explicit snap_uri_exception(char const * what_msg) : snap_exception("snap_uri", what_msg) {}
38 : explicit snap_uri_exception(std::string const & what_msg) : snap_exception("snap_uri", what_msg) {}
39 0 : explicit snap_uri_exception(QString const & what_msg) : snap_exception("snap_uri", what_msg) {}
40 : };
41 :
42 0 : class snap_uri_exception_invalid_uri : public snap_uri_exception
43 : {
44 : public:
45 : explicit snap_uri_exception_invalid_uri(char const * what_msg) : snap_uri_exception(what_msg) {}
46 : explicit snap_uri_exception_invalid_uri(std::string const & what_msg) : snap_uri_exception(what_msg) {}
47 0 : explicit snap_uri_exception_invalid_uri(QString const & what_msg) : snap_uri_exception(what_msg) {}
48 : };
49 :
50 0 : class snap_uri_exception_invalid_parameter : public snap_uri_exception
51 : {
52 : public:
53 0 : explicit snap_uri_exception_invalid_parameter(char const * what_msg) : snap_uri_exception(what_msg) {}
54 : explicit snap_uri_exception_invalid_parameter(std::string const & what_msg) : snap_uri_exception(what_msg) {}
55 0 : explicit snap_uri_exception_invalid_parameter(QString const & what_msg) : snap_uri_exception(what_msg) {}
56 : };
57 :
58 0 : class snap_uri_exception_invalid_path : public snap_uri_exception
59 : {
60 : public:
61 : explicit snap_uri_exception_invalid_path(char const * what_msg) : snap_uri_exception(what_msg) {}
62 : explicit snap_uri_exception_invalid_path(std::string const & what_msg) : snap_uri_exception(what_msg) {}
63 0 : explicit snap_uri_exception_invalid_path(QString const & what_msg) : snap_uri_exception(what_msg) {}
64 : };
65 :
66 0 : class snap_uri_exception_out_of_bounds : public snap_uri_exception
67 : {
68 : public:
69 : explicit snap_uri_exception_out_of_bounds(char const * what_msg) : snap_uri_exception(what_msg) {}
70 : explicit snap_uri_exception_out_of_bounds(std::string const & what_msg) : snap_uri_exception(what_msg) {}
71 0 : explicit snap_uri_exception_out_of_bounds(QString const & what_msg) : snap_uri_exception(what_msg) {}
72 : };
73 :
74 0 : class snap_uri_exception_exclusive_parameters : public snap_uri_exception
75 : {
76 : public:
77 0 : explicit snap_uri_exception_exclusive_parameters(char const * what_msg) : snap_uri_exception(what_msg) {}
78 : explicit snap_uri_exception_exclusive_parameters(std::string const & what_msg) : snap_uri_exception(what_msg) {}
79 : explicit snap_uri_exception_exclusive_parameters(QString const & what_msg) : snap_uri_exception(what_msg) {}
80 : };
81 :
82 :
83 :
84 :
85 :
86 :
87 :
88 : // Helper class to handle URIs
89 : // http://tools.ietf.org/html/rfc3986
90 0 : class snap_uri
91 : {
92 : public:
93 : // types used by this class
94 : typedef QMap<QString, QString> snap_uri_options_t;
95 :
96 : // constructors
97 : snap_uri();
98 : snap_uri(QString const & uri);
99 :
100 : // URI handling
101 : bool set_uri(QString const & uri);
102 : QString const & get_original_uri() const;
103 : QString get_uri(bool use_hash_bang = false) const;
104 : QString get_website_uri(bool include_port = false) const;
105 :
106 : // get a part by name
107 : QString get_part(QString const & name, int part = -1) const;
108 :
109 : // protocol handling
110 : void set_protocol(QString const & uri_protocol);
111 : QString const & protocol() const;
112 :
113 : // domain & sub-domains handling
114 : void set_domain(QString const & full_domain_name);
115 : QString full_domain() const;
116 : QString const & top_level_domain() const;
117 : QString const & domain() const;
118 : QString sub_domains() const;
119 : int sub_domain_count() const;
120 : QString sub_domain(int part) const;
121 : snap_string_list const & sub_domains_list() const;
122 :
123 : // port handling
124 : void set_port(QString const & port);
125 : void set_port(int port);
126 : int get_port() const;
127 :
128 : // path handling
129 : void set_path(QString uri_path);
130 : QString path(bool encoded = true) const;
131 : int path_count() const;
132 : QString path_folder_name(int part) const;
133 : snap_string_list const & path_list() const;
134 :
135 : // option handling
136 : void set_option(QString const & name, QString const & value);
137 : void unset_option(QString const & name);
138 : QString option(QString const & name) const;
139 : int option_count() const;
140 : QString option(int part, QString & name) const;
141 : snap_uri_options_t const & options_list() const;
142 :
143 : // query string handling
144 : void set_query_option(QString const & name, QString const & value);
145 : void unset_query_option(QString const & name);
146 : void set_query_string(QString const & uri_query_string);
147 : QString query_string() const;
148 : bool has_query_option(QString const & name) const;
149 : void clear_query_options();
150 : QString query_option(QString const & name) const;
151 : int query_option_count() const;
152 : QString query_option(int part, QString & name) const;
153 : snap_uri_options_t const & query_string_list() const;
154 :
155 : // anchor handling (note: "#!" is not considered an anchor)
156 : void set_anchor(QString const & uri_anchor);
157 : QString const & anchor() const;
158 :
159 : // operators
160 : bool operator == (snap_uri const & rhs) const;
161 : bool operator != (snap_uri const & rhs) const;
162 : bool operator < (snap_uri const & rhs) const;
163 : bool operator <= (snap_uri const & rhs) const;
164 : bool operator > (snap_uri const & rhs) const;
165 : bool operator >= (snap_uri const & rhs) const;
166 :
167 : static QString urlencode(QString const & uri, char const * accepted = "");
168 : static QString urldecode(QString const & uri, bool relax = false);
169 : static int protocol_to_port(QString const & uri_protocol);
170 :
171 : private:
172 : bool process_domain(QString const & full_domain_name, snap_string_list & sub_domain_names, QString & domain_name, QString & tld);
173 :
174 : // f_original is the unchanged source (from constructor or
175 : // last set_uri() call)
176 : QString f_original = QString();
177 : QString f_protocol = QString("http");
178 : QString f_username = QString();
179 : QString f_password = QString();
180 : int f_port = 80;
181 : QString f_domain = QString();
182 : QString f_top_level_domain = QString();
183 : snap_string_list f_sub_domains = snap_string_list();
184 : snap_string_list f_path = snap_string_list();
185 : snap_uri_options_t f_options = snap_uri_options_t();
186 : snap_uri_options_t f_query_strings = snap_uri_options_t();
187 : QString f_anchor = QString();
188 : };
189 :
190 :
191 :
192 :
193 : // The following is used to compile rules as defined for the domains
194 : // and websites; the result is a set of regular expressions we can
195 : // use to parse the URI when we receive a hit
196 : //
197 : // See https://snapwebsites.org/implementation/basic-concept-url-website/url-test
198 : class snap_uri_rules
199 : {
200 : public:
201 : // handling of rule scripts
202 : bool parse_domain_rules(QString const & script, QByteArray & result);
203 : bool parse_website_rules(QString const & script, QByteArray & result);
204 :
205 : // processing of URIs
206 : //QString process_uri(snap_uri & uri);
207 :
208 : QString const & errmsg() const { return f_errmsg; }
209 :
210 : private:
211 : QString f_errmsg = QString();
212 : };
213 :
214 :
215 : /** \brief Domain variables
216 : *
217 : * This class is used to hold the domain variable information.
218 : * Each variable has a type that defines how the variable is used
219 : * (standard, website, or flag, and when defined as a flag whether
220 : * a default was defined.)
221 : */
222 0 : class domain_variable : public parser::parser_user_data
223 : {
224 : public:
225 : /** \brief Define the type of this variable.
226 : *
227 : * This enumaration is used to define the exact type of the variable.
228 : * This is used to know how to use the variable later. That information
229 : * is actually saved in the resulting compiled data.
230 : *
231 : * \warning
232 : * The variable type is saved as is in the database (i.e. as a number)
233 : * which means that the order defined below CANNOT CHANGE. If we need
234 : * more types, add them afterward. If a type becomes obsolete, do not
235 : * delete it nor reuse its position.
236 : */
237 : typedef int domain_variable_type_t;
238 : // WARNING: saved as a number in the database
239 :
240 : /** \brief Standard variable type.
241 : *
242 : * The standard variable type is used as is to define a sub-domain
243 : * name. It is given a name and a regular expression. It may be
244 : * optional, but it does not otherwise required anything specific.
245 : *
246 : * The result is whatever the regular expression matches.
247 : */
248 : static domain_variable_type_t const DOMAIN_VARIABLE_TYPE_STANDARD = 0;
249 : // WARNING: saved as a number in the database DO NOT CHANGE
250 :
251 : /** \brief Website variable type.
252 : *
253 : * This type defines a value which is a regular expression, exactly
254 : * the same as the standard variable. However, the result is always
255 : * set to the default value (canonicalization.)
256 : */
257 : static domain_variable_type_t const DOMAIN_VARIABLE_TYPE_WEBSITE = 1;
258 : // WARNING: saved as a number in the database DO NOT CHANGE
259 :
260 : /** \brief Flag variable with a default value.
261 : *
262 : * This value is used whenever a sub-domain entry is an option which
263 : * means it does not participate to the website canonicalization. Any
264 : * matches are removed from the result.
265 : *
266 : * This flag defines a default. If there is no match, then use the
267 : * default instead.
268 : */
269 : static domain_variable_type_t const DOMAIN_VARIABLE_TYPE_FLAG_WITH_DEFAULT = 2;
270 : // WARNING: saved as a number in the database DO NOT CHANGE
271 :
272 : /** \brief Flag variable without a default value.
273 : *
274 : * This flag is similar to the DOMAIN_VARIABLE_TYPE_FLAG_WITH_DEFAULT
275 : * except that no default was defined. This means the flag is either
276 : * required, or completely ignored (when marked as optional.)
277 : *
278 : * In this case, the default value may be defined somewhere else. For
279 : * example, the language information is expected to be sent by the
280 : * client browser and can be accessed from there instead.
281 : */
282 : static domain_variable_type_t const DOMAIN_VARIABLE_TYPE_FLAG_NO_DEFAULT = 3;
283 : // WARNING: saved as a number in the database DO NOT CHANGE
284 :
285 : /** \brief Initialize a domain variable.
286 : *
287 : * This function initializes the domain variable with its type, name
288 : * and value. It is not possible to change the type or name of the
289 : * variable at a later time. The value can be changed with the
290 : * set_value() function.
291 : *
292 : * The default value is marked as undefined. It can be modified with
293 : * the set_default() function.
294 : *
295 : * Values and default values are always strings. Values are expected
296 : * to be regular expressions.
297 : *
298 : * The required flag is set to false (optional.) The set_required()
299 : * function can be used later to change that flag.
300 : *
301 : * \param[in] type The type of the new domain variable.
302 : * \param[in] name The name of the variable. The name can be qualified.
303 : * \param[in] value The value of the variable.
304 : *
305 : * \sa set_value()
306 : * \sa set_default()
307 : * \sa set_required()
308 : */
309 0 : domain_variable(domain_variable_type_t type, QString const & name, QString const & value)
310 0 : : f_type(type)
311 : , f_name(name)
312 0 : , f_value(value)
313 : //, f_default("") -- auto-init
314 : //, f_required(false) -- auto-init
315 : {
316 0 : switch(type)
317 : {
318 0 : case DOMAIN_VARIABLE_TYPE_STANDARD:
319 : case DOMAIN_VARIABLE_TYPE_WEBSITE:
320 : case DOMAIN_VARIABLE_TYPE_FLAG_WITH_DEFAULT:
321 : case DOMAIN_VARIABLE_TYPE_FLAG_NO_DEFAULT:
322 0 : break;
323 :
324 0 : default:
325 0 : throw std::runtime_error("unknown type specified in domain_variable constructor");
326 :
327 : }
328 0 : }
329 :
330 : /** \brief Retrieve the variable type.
331 : *
332 : * This function returns the type of the variable.
333 : *
334 : * \return The type of this variable.
335 : */
336 0 : domain_variable_type_t get_type() const
337 : {
338 0 : return f_type;
339 : }
340 :
341 : /** \brief Retrieve the variable name.
342 : *
343 : * This function returns the variable name. The name is read-only.
344 : *
345 : * The only way to set the name of a variable is to define it in
346 : * the constructor. It cannot be changed later. This function
347 : * returns the fully qualified name of the variable.
348 : *
349 : * \return The variable name in a QString.
350 : */
351 0 : QString const & get_name() const
352 : {
353 0 : return f_name;
354 : }
355 :
356 : /** \brief Get the value of the variable.
357 : *
358 : * The value of the domain variables is expected to be a valid
359 : * regular expression. The return value is read-only. To change
360 : * the value, use the set_value() function instead.
361 : *
362 : * \return The value of the variable in a QString.
363 : *
364 : * \sa set_value()
365 : */
366 0 : QString const & get_value() const
367 : {
368 0 : return f_value;
369 : }
370 :
371 : /** \brief Change the value of the variable.
372 : *
373 : * This function can be used to change the value of this variable.
374 : *
375 : * \param[in] value The new value to set this variable to.
376 : */
377 : void set_value(QString const & value)
378 : {
379 : f_value = value;
380 : }
381 :
382 : /** \brief Get the default value of the variable.
383 : *
384 : * This function can be used to read the default value of the
385 : * variable. Note that if the variable is not of a type that
386 : * supports a default, the return value is always an empty
387 : * string.
388 : *
389 : * The value returned by this function is read-only. To modify
390 : * the default value, use the set_default() function instead.
391 : *
392 : * \return The default value of this variable.
393 : */
394 0 : QString const & get_default() const
395 : {
396 0 : return f_default;
397 : }
398 :
399 : /** \brief Set the default value of the variable.
400 : *
401 : * This function is used to set the default value of this variable.
402 : * By default the default value is an empty string. At this time
403 : * there is no function one can use to know whether the default
404 : * value was defined, however, the flag uses a different type
405 : * when a default or no defaults are defined.
406 : *
407 : * When the type is DOMAIN_VARIABLE_TYPE_FLAG_NO_DEFAULT then the
408 : * default is expected to never be defined.
409 : *
410 : * \exception std::runtime_error
411 : * The runtime error is raised if the default is set when the type
412 : * of the variable doesn't allow it. This is an internal error since
413 : * the system should never have to raise this error.
414 : *
415 : * \param[in] default_value The new default value.
416 : */
417 0 : void set_default(QString const & default_value)
418 : {
419 0 : switch(f_type)
420 : {
421 0 : case DOMAIN_VARIABLE_TYPE_WEBSITE:
422 : case DOMAIN_VARIABLE_TYPE_FLAG_WITH_DEFAULT:
423 0 : f_default = default_value;
424 0 : break;
425 :
426 0 : default:
427 0 : throw std::runtime_error("cannot define a default value for this type of domain variable");
428 :
429 : }
430 0 : }
431 :
432 : /** \brief Get whether the required flag is true or false.
433 : *
434 : * This function is the representation of the REQUIRED (true) or
435 : * OPTIONAL (false) keywords used in front of variable names.
436 : *
437 : * \return true when the sub-domain is required.
438 : */
439 0 : bool get_required() const
440 : {
441 0 : return f_required;
442 : }
443 :
444 : /** \brief Set whether this variable was marked as required.
445 : *
446 : * The sub-domain rule defines whether this entry is required or not.
447 : * This function is used to reflect this information in this variable.
448 : *
449 : * \param[in] required Set whether the variable was marked as required (true) or not (false).
450 : */
451 0 : void set_required(bool required = true)
452 : {
453 0 : f_required = required;
454 0 : }
455 :
456 : void read(QtSerialization::QReader & stream);
457 : void write(QtSerialization::QWriter & stream) const;
458 :
459 : private:
460 : /** \brief The domain variable type.
461 : *
462 : * This field defines the type of the domain variable. It cannot be
463 : * modified once a variable was created.
464 : *
465 : * \sa get_type()
466 : */
467 : domain_variable_type_t f_type = DOMAIN_VARIABLE_TYPE_STANDARD;
468 :
469 : /** \brief The domain variable name.
470 : *
471 : * This field represents the fully qualified name of the variable.
472 : * The name cannot be changed once the variable was created.
473 : *
474 : * Names are expected to be unique within one rule.
475 : *
476 : * \sa get_name()
477 : */
478 : QString f_name = QString();
479 :
480 : /** \brief The value of this variable.
481 : *
482 : * This is the value of the variable. It is expected to be a valid
483 : * regular expression. The value is generally set at the time the
484 : * variable is created. It can be changed later with the set_value()
485 : * function.
486 : *
487 : * \sa get_value()
488 : * \sa set_value()
489 : */
490 : QString f_value = QString();
491 :
492 : /** \brief The default value of the variable.
493 : *
494 : * This field holds the default value of the variable. This is used
495 : * for websites and flags with a default value. Other types do not
496 : * make use of a default value.
497 : *
498 : * The default value can be modified with the set_default()
499 : * function.
500 : *
501 : * \sa get_default()
502 : * \sa set_default()
503 : */
504 : QString f_default = QString();
505 :
506 : /** \brief Wether the value is required.
507 : *
508 : * This value represents one or more sub-domains. If those sub-domains
509 : * are required, then this value will be true.
510 : *
511 : * This value is set using the REQUIRED or OPTIONAL keywords in the
512 : * sub_domain rule.
513 : *
514 : * \sa get_required()
515 : * \sa set_required()
516 : */
517 : bool f_required = false;
518 : };
519 :
520 :
521 : /** \brief Define the information of a domain.
522 : *
523 : * This class holds a set of sub-domain variables which together
524 : * define a domain. The domain is also given a domain.
525 : */
526 0 : class domain_info : public parser::parser_user_data, public QtSerialization::QSerializationObject
527 : {
528 : public:
529 : /** \brief Add a domain variable to the domain info.
530 : *
531 : * This function adds a domain variable as defined by
532 : * the sub-domain rules to a domain information object.
533 : * The variable is expected to be valid, although at
534 : * this point the system doesn't check whether it is
535 : * unique or properly qualified. Those checks are done
536 : * afterward.
537 : *
538 : * \param[in] var The variable to add to this domain.
539 : */
540 0 : void add_var(QSharedPointer<domain_variable> & var)
541 : {
542 0 : f_vars.push_back(var);
543 0 : }
544 :
545 : /** \brief Retrieve the name of this domain.
546 : *
547 : * This function returns a read-only reference to the name of
548 : * this domain definition.
549 : *
550 : * To change the name, use the set_name() function.
551 : *
552 : * \return A reference to the name of this domain.
553 : *
554 : * \sa set_name()
555 : */
556 0 : QString const & get_name() const
557 : {
558 0 : return f_name;
559 : }
560 :
561 : /** \brief Set the name of the domain.
562 : *
563 : * This function is used to set the name of the domain.
564 : * The name is expected to be unique among all the domain
565 : * definitions found in a block (i.e. per domain.)
566 : *
567 : * \param[in] name The name of the domain.
568 : *
569 : * \sa get_name()
570 : */
571 0 : void set_name(QString const & name)
572 : {
573 0 : f_name = name;
574 0 : }
575 :
576 : /** \brief Retrieve the number of variables defined.
577 : *
578 : * This function returns the number of variables that were added
579 : * to this domain definition. The number may be zero if no variables
580 : * were added.
581 : *
582 : * \return The number of domain variables available in this object.
583 : */
584 0 : int size() const
585 : {
586 0 : return f_vars.size();
587 : }
588 :
589 : /** \brief Retrieve one of the domain variables.
590 : *
591 : * This function returns a domain variable shared pointer.
592 : *
593 : * The index is expected to be between 0 (inclusive) and size()
594 : * (exclusive.) If size() is zero, this function cannot be
595 : * used.
596 : *
597 : * \param[in] idx The index of the variable.
598 : *
599 : * \return A shared pointer to the domain variable information.
600 : */
601 0 : QSharedPointer<domain_variable> get_variable(int idx) const
602 : {
603 0 : return f_vars[idx];
604 : }
605 :
606 : /** \brief Retrieve one of the domain variables.
607 : *
608 : * This operator returns a domain variable shared pointer.
609 : *
610 : * The index is expected to be between 0 (inclusive) and size()
611 : * (exclusive.) If size() is zero, this operator cannot be
612 : * used.
613 : *
614 : * \param[in] idx The index of the variable.
615 : *
616 : * \return A shared pointer to the domain variable information.
617 : */
618 0 : QSharedPointer<domain_variable> operator [] (int idx) const
619 : {
620 0 : return f_vars[idx];
621 : }
622 :
623 : void read(QtSerialization::QReader & r);
624 : virtual void readTag(QString const & name, QtSerialization::QReader & r);
625 : void write(QtSerialization::QWriter & w) const;
626 :
627 : private:
628 : /** \brief The name of this domain definition.
629 : *
630 : * This field holds the name of the domain definition. The
631 : * name should be read-only, although it gets defined after
632 : * we create instances of domain_info...
633 : */
634 : QString f_name = QString();
635 :
636 : /** \brief The list of variables attached to this domain.
637 : *
638 : * This array lists all the variables accepted by this domain.
639 : * Note that the variables are saved in the order in which
640 : * they appear in the source string. It is very important since
641 : * they need to be used to parse input URLs in the exact order
642 : * they are specified here.
643 : */
644 : QVector<QSharedPointer<domain_variable> > f_vars = QVector<QSharedPointer<domain_variable> >();
645 : };
646 :
647 :
648 : /** \brief Set of rules defined in a domain declaration.
649 : *
650 : * This class holds an array of domain information.
651 : */
652 0 : class domain_rules : public parser::parser_user_data, public QtSerialization::QSerializationObject
653 : {
654 : public:
655 : /** \brief Add one domain information object.
656 : *
657 : * This function adds one domain information object to the
658 : * domain rules object. This is what the result is expected
659 : * to be.
660 : *
661 : * Note that the order is kept as is since the checks of the
662 : * domains is always done in order as specified by the user.
663 : * If a URL matches more than one domain, the first that matches
664 : * is used. The following will be ignored. In debug mode, URLs
665 : * may checked to all the domain information definitions in order
666 : * to determine whether there is a problem (i.e. a match that
667 : * should use Domain B instead of Domain A.) This can be done
668 : * on a backend system.
669 : *
670 : * \param[in] info The domain information to add to this object.
671 : */
672 0 : void add_info(QSharedPointer<domain_info> & info)
673 : {
674 0 : f_info.push_back(info);
675 0 : }
676 :
677 : /** \brief Retrieve the number of domain information object.
678 : *
679 : * This function returns the number of domain_info objects
680 : * that were added to this domain rules object.
681 : *
682 : * This function will return zero until one or more domain info
683 : * was added to the domain rules.
684 : *
685 : * \return The number of domain_info objects defined in this domain rules.
686 : *
687 : * \sa operator [] ()
688 : * \sa add_info()
689 : */
690 0 : int size() const
691 : {
692 0 : return f_info.size();
693 : }
694 :
695 : /** \brief This operator can be used to retrieve a domain info.
696 : *
697 : * This operator returns the specified domain information from this
698 : * domain rules.
699 : *
700 : * The index must be between 0 (inclusive) and size() (exclusive).
701 : *
702 : * \param[in] idx The index of the domain info to retrieve.
703 : *
704 : * \return A pointer to the specified domain_info object.
705 : *
706 : * \sa size()
707 : */
708 0 : QSharedPointer<domain_info> operator [] (int idx) const
709 : {
710 0 : return f_info[idx];
711 : }
712 :
713 : void read(QtSerialization::QReader & stream);
714 : virtual void readTag(QString const & name, QtSerialization::QReader & r);
715 : void write(QtSerialization::QWriter & stream) const;
716 :
717 : private:
718 : /** \brief The array holding all the domain_info objects.
719 : *
720 : * This vector holds the domain information that are stored
721 : * by this domain rules object. The order in which the
722 : * domain_info where added to the domain_rules object
723 : * is preserved.
724 : */
725 : QVector<QSharedPointer<domain_info> > f_info = QVector<QSharedPointer<domain_info> >();
726 : };
727 :
728 :
729 :
730 : // Websites data
731 0 : class website_variable : public parser::parser_user_data
732 : {
733 : public:
734 : // WARNING: saved as a number in the database -- DO NOT CHANGE #'s
735 : typedef int website_variable_type_t;
736 : static website_variable_type_t const WEBSITE_VARIABLE_TYPE_STANDARD = 0;
737 : static website_variable_type_t const WEBSITE_VARIABLE_TYPE_WEBSITE = 1;
738 : static website_variable_type_t const WEBSITE_VARIABLE_TYPE_FLAG_WITH_DEFAULT = 2;
739 : static website_variable_type_t const WEBSITE_VARIABLE_TYPE_FLAG_NO_DEFAULT = 3;
740 :
741 : // WARNING: saved as a number in the database -- DO NOT CHANGE #'s
742 : typedef int website_variable_part_t;
743 : static website_variable_part_t const WEBSITE_VARIABLE_PART_PATH = 0;
744 : static website_variable_part_t const WEBSITE_VARIABLE_PART_PORT = 1;
745 : static website_variable_part_t const WEBSITE_VARIABLE_PART_PROTOCOL = 2;
746 : static website_variable_part_t const WEBSITE_VARIABLE_PART_QUERY = 3;
747 :
748 0 : website_variable(website_variable_type_t type, QString const & name, QString const & value)
749 0 : : f_type(type)
750 : , f_part(WEBSITE_VARIABLE_PART_PATH) // this is the obvious default here, we could define an UNDEFINED = -1 too?
751 : , f_name(name)
752 0 : , f_value(value)
753 : //, f_default("") -- auto-init
754 : //, f_required(false) -- auto-init
755 : {
756 0 : switch(type)
757 : {
758 0 : case WEBSITE_VARIABLE_TYPE_STANDARD:
759 : case WEBSITE_VARIABLE_TYPE_WEBSITE:
760 : case WEBSITE_VARIABLE_TYPE_FLAG_WITH_DEFAULT:
761 : case WEBSITE_VARIABLE_TYPE_FLAG_NO_DEFAULT:
762 0 : break;
763 :
764 0 : default:
765 0 : throw std::runtime_error("unknown type specified in website_variable constructor");
766 :
767 : }
768 0 : }
769 :
770 0 : website_variable_type_t get_type() const
771 : {
772 0 : return f_type;
773 : }
774 :
775 0 : QString const & get_name() const
776 : {
777 0 : return f_name;
778 : }
779 :
780 0 : QString const & get_value() const
781 : {
782 0 : return f_value;
783 : }
784 :
785 : void set_value(QString const & value)
786 : {
787 : f_value = value;
788 : }
789 :
790 0 : QString const & get_default() const
791 : {
792 0 : return f_default;
793 : }
794 :
795 0 : void set_default(QString const & default_value)
796 : {
797 0 : switch(f_type)
798 : {
799 0 : case WEBSITE_VARIABLE_TYPE_WEBSITE:
800 : case WEBSITE_VARIABLE_TYPE_FLAG_WITH_DEFAULT:
801 0 : f_default = default_value;
802 0 : break;
803 :
804 0 : default:
805 0 : throw std::runtime_error("cannot define a default value for this type of website variable");
806 :
807 : }
808 0 : }
809 :
810 0 : bool get_required() const
811 : {
812 0 : return f_required;
813 : }
814 :
815 0 : void set_required(bool required = true)
816 : {
817 0 : f_required = required;
818 0 : }
819 :
820 0 : website_variable_part_t get_part() const
821 : {
822 0 : return f_part;
823 : }
824 :
825 0 : void set_part(website_variable_part_t part)
826 : {
827 0 : switch(part)
828 : {
829 0 : case WEBSITE_VARIABLE_PART_PATH:
830 : case WEBSITE_VARIABLE_PART_PORT:
831 : case WEBSITE_VARIABLE_PART_PROTOCOL:
832 : case WEBSITE_VARIABLE_PART_QUERY:
833 0 : break;
834 :
835 0 : default:
836 0 : throw std::runtime_error("unknown part specified in website_variable::set_part()");
837 :
838 : }
839 0 : f_part = part;
840 0 : }
841 :
842 : void read(QtSerialization::QReader & r);
843 : void write(QtSerialization::QWriter & w) const;
844 :
845 : private:
846 : website_variable_type_t f_type = website_variable_type_t();
847 : website_variable_part_t f_part = website_variable_part_t();
848 : QString f_name = QString();
849 : QString f_value = QString();
850 : QString f_default = QString();
851 : bool f_required = false;
852 : };
853 :
854 :
855 0 : class website_info : public parser::parser_user_data, public QtSerialization::QSerializationObject
856 : {
857 : public:
858 0 : void add_var(QSharedPointer<website_variable >& var)
859 : {
860 0 : f_vars.push_back(var);
861 0 : }
862 :
863 0 : QString const & get_name() const
864 : {
865 0 : return f_name;
866 : }
867 :
868 0 : void set_name(QString const & name)
869 : {
870 0 : f_name = name;
871 0 : }
872 :
873 0 : int size() const
874 : {
875 0 : return f_vars.size();
876 : }
877 :
878 0 : QSharedPointer<website_variable> get_variable(int idx) const
879 : {
880 0 : return f_vars[idx];
881 : }
882 :
883 0 : QSharedPointer<website_variable> operator [] (int idx) const
884 : {
885 0 : return f_vars[idx];
886 : }
887 :
888 : void read(QtSerialization::QReader & r);
889 : virtual void readTag(QString const & name, QtSerialization::QReader & r);
890 : void write(QtSerialization::QWriter & w) const;
891 :
892 : private:
893 : QString f_name = QString();
894 : QVector<QSharedPointer<website_variable> > f_vars = QVector<QSharedPointer<website_variable> >();
895 : };
896 :
897 :
898 0 : class website_rules : public parser::parser_user_data, public QtSerialization::QSerializationObject
899 : {
900 : public:
901 0 : void add_info(QSharedPointer<website_info> & info)
902 : {
903 0 : f_info.push_back(info);
904 0 : }
905 :
906 0 : int size() const
907 : {
908 0 : return f_info.size();
909 : }
910 :
911 0 : QSharedPointer<website_info> operator [] (int idx) const
912 : {
913 0 : return f_info[idx];
914 : }
915 :
916 : void read(QtSerialization::QReader & r);
917 : virtual void readTag(QString const & name, QtSerialization::QReader & r);
918 : void write(QtSerialization::QWriter & w) const;
919 :
920 : private:
921 : QVector<QSharedPointer<website_info> > f_info = QVector<QSharedPointer<website_info> >();
922 : };
923 :
924 :
925 : } // namespace snap
926 : // vim: ts=4 sw=4 et
|