Line data Source code
1 : /* TLD library -- TLD validation command line tools
2 : * Copyright (c) 2011-2021 Made to Order Software Corp. All Rights Reserved
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the
6 : * "Software"), to deal in the Software without restriction, including
7 : * without limitation the rights to use, copy, modify, merge, publish,
8 : * distribute, sublicense, and/or sell copies of the Software, and to
9 : * permit persons to whom the Software is furnished to do so, subject to
10 : * the following conditions:
11 : *
12 : * The above copyright notice and this permission notice shall be included
13 : * in all copies or substantial portions of the Software.
14 : *
15 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 : */
23 :
24 : /** \file
25 : * \brief Command line tool to validate TLDs.
26 : *
27 : * This tool is used to verify URIs and emails on the command line and
28 : * in scripts.
29 : */
30 :
31 : #include "libtld/tld.h"
32 : #include <stdio.h>
33 : #include <stdlib.h>
34 : #include <string.h>
35 : #include <iostream>
36 :
37 : /// Number of errors so we know whether to exit with 0 or 1
38 : int err_count = 0;
39 :
40 : /// Whether the user asked for verbosity, false by default.
41 : int verbose = 0;
42 :
43 : /** \brief List of schemes that we more or less support (some schemes have extensions using the semi-colon that we do not support yet.)
44 : *
45 : * This list of schemes comes from http://en.wikipedia.org/wiki/URI_scheme and is
46 : * likely not 100% valid, but it should cover a pretty large number of schemes
47 : * expected to work with our system.
48 : *
49 : * \note
50 : * The documentation does not show you all the schemes. Check out the
51 : * source to see all the schemes currently included.
52 : */
53 : const char *schemes = "afp,adiumxtra,aw,beshare,bolo,cap,coap,crid,dns,feed,file,"
54 : "finger,fish,ftp,ftps,git,gopher,http,https,icap,imap,"
55 : "ipp,irc,irc6,ircs,mumble,mupdate,mysql,nfs,nntp,"
56 : "opaquelocktoken,pop,psql,psyc,rmi,rsync,rtmp,rtsp,rtspu,"
57 : "sftp,shttp,sieve,smb,snmp,soap.beep,soap.beeps,soldat,"
58 : "ssh,teamspeak,telnet,tftp,tip,udp,unreal,ut2004,vemmi,"
59 : "ventrilo,wais,webcal,wyciwyg,z39.50r,z39.50s";
60 :
61 : /// Hold a list of schemes as defined by the end user.
62 : char const * user_schemes = nullptr;
63 :
64 : /** \brief Check the parameter as a URI.
65 : *
66 : * This function verifies that the URI is valid.
67 : *
68 : * \param[in] uri The URI to be checked.
69 : */
70 222 : void check_uri(char const * uri)
71 : {
72 : tld_result result;
73 222 : if(strncasecmp(uri, "mailto:", 7) == 0)
74 : {
75 8 : tld_email_list mail;
76 4 : result = mail.parse(uri + 7, 0);
77 : }
78 : else
79 : {
80 : struct tld_info info;
81 218 : char const * s(user_schemes == nullptr ? schemes : user_schemes);
82 218 : result = tld_check_uri(uri, &info, s, 0);
83 :
84 218 : if(verbose)
85 : {
86 : std::cout << "URI: " << uri << std::endl; // LCOV_EXCL_LINE
87 : std::cout << "Category: " << static_cast<int>(info.f_category) << std::endl; // LCOV_EXCL_LINE
88 : std::cout << "Status: " << static_cast<int>(info.f_status) << std::endl; // LCOV_EXCL_LINE
89 : if(info.f_country != nullptr) // LCOV_EXCL_LINE
90 : {
91 : std::cout << "Country: " << info.f_country << std::endl; // LCOV_EXCL_LINE
92 : }
93 : std::cout << "TLD: " << info.f_tld << std::endl; // LCOV_EXCL_LINE
94 : std::cout << "Offset: " << info.f_offset << std::endl; // LCOV_EXCL_LINE
95 : }
96 : }
97 222 : if(result != TLD_RESULT_SUCCESS)
98 : {
99 4 : fprintf(stderr, "error: URI \"%s\" is not considered valid.\n", uri);
100 4 : ++err_count;
101 : }
102 222 : }
103 :
104 : /** \brief List the default schemes accepted.
105 : *
106 : * This function lists all the schemes defined in the \p schemes variable.
107 : */
108 2 : void list()
109 : {
110 736 : for(const char *s(schemes); *s != '\0'; ++s)
111 : {
112 734 : if(*s == ',')
113 : {
114 122 : printf("\n");
115 : }
116 : else
117 : {
118 612 : printf("%c", *s);
119 : }
120 : }
121 2 : printf("\n");
122 2 : exit(1);
123 : }
124 :
125 : /** \brief Print out the help of the tld tool.
126 : *
127 : * This function prints out the help information about the validate_tld tool.
128 : * The function does not return.
129 : */
130 2 : void usage()
131 : {
132 2 : printf("Usage: validate_tld [-<opts>] <uri> | <email>\n");
133 2 : printf("Where <uri> or <email> are URIs starting with a valid scheme.\n");
134 2 : printf("The <email> scheme is mailto:.\n");
135 2 : printf("Where -<opts> are:\n");
136 2 : printf(" -h | --help print out this help screen\n");
137 2 : printf(" -l | --list print the default list of schemes\n");
138 2 : printf(" -s | --schemes <list> set the list of schemes with user's defined schemes\n");
139 2 : printf(" the list is a comma separate set of scheme names\n");
140 2 : printf(" -v | --verbose request some verbosity of the tool's work\n");
141 2 : exit(1);
142 : }
143 :
144 : /** \brief The validate tools.
145 : *
146 : * The parameters can include any number of URIs and emails. The system
147 : * must be told what's what using a protocol. For emails, use the name
148 : * "mail".
149 : *
150 : * \param[in] argc Number of command line arguments passed in.
151 : * \param[in] argv The arguments passed in.
152 : *
153 : * \return The tool returns 0 on success meaning that all the URIs and emails are valid, 1 otherwise.
154 : */
155 229 : int main(int argc, char *argv[])
156 : {
157 : try
158 : {
159 229 : bool uri(false);
160 :
161 457 : for(int i(1); i < argc; ++i)
162 : {
163 233 : if(argv[i][0] == '-')
164 : {
165 11 : if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
166 : {
167 2 : usage();
168 : /*NOTREACHED*/
169 : }
170 9 : else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--list") == 0)
171 : {
172 2 : list();
173 : /*NOTREACHED*/
174 : }
175 7 : else if(strcmp(argv[i], "--version") == 0)
176 : {
177 1 : printf("%s\n", LIBTLD_VERSION);
178 1 : if(verbose)
179 : {
180 1 : printf("libtld v%s\n", tld_version());
181 : }
182 1 : exit(1);
183 : }
184 6 : else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--schemes") == 0)
185 : {
186 3 : ++i;
187 3 : if(i >= argc)
188 : {
189 1 : fprintf(stderr, "error: the --schemes option requires a list of comma separated schemes.\n");
190 : }
191 3 : user_schemes = argv[i];
192 : }
193 3 : else if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
194 : {
195 3 : verbose = 1;
196 : }
197 : }
198 : else
199 : {
200 222 : uri = true;
201 222 : check_uri(argv[i]);
202 : }
203 : }
204 :
205 224 : if(!uri)
206 : {
207 2 : fprintf(stderr, "error: no URI were specified on the command line.\n");
208 2 : ++err_count;
209 : }
210 :
211 224 : return err_count > 0 ? 1 : 0;
212 : }
213 : catch(std::exception const& e) // LCOV_EXCL_LINE
214 : {
215 : // an exception occurred, print out the message and exit with an error
216 : //
217 : // note that this tool is not expecting any exception
218 : // because we only access the C interface which does
219 : // not throw
220 : //
221 : std::cerr << "exception: " << e.what() << std::endl; // LCOV_EXCL_LINE
222 : exit(1); // LCOV_EXCL_LINE
223 : }
224 687 : }
225 :
226 : // vim: ts=4 sw=4 et
|