Line data Source code
1 : /* TLD library -- TLD validation command line tools
2 : * Copyright (c) 2011-2022 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 227 : void check_uri(char const * uri)
71 : {
72 : tld_result result;
73 227 : 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 223 : struct tld_info info;
81 223 : char const * s(user_schemes == nullptr ? schemes : user_schemes);
82 223 : result = tld_check_uri(uri, &info, s, 0);
83 :
84 223 : 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 : && info.f_country[0] != '\0') // LCOV_EXCL_LINE
91 : {
92 : std::cout << "Country: " << info.f_country << std::endl; // LCOV_EXCL_LINE
93 : }
94 0 : if(info.f_tld != nullptr)
95 : {
96 : // port or path may follow this TLD
97 : //
98 0 : char const * e(strchr(info.f_tld, ':'));
99 0 : if(e == nullptr)
100 : {
101 0 : e = strchr(info.f_tld, '/');
102 : }
103 0 : if(e == nullptr)
104 : {
105 : std::cout << "TLD: " << info.f_tld << std::endl; // LCOV_EXCL_LINE
106 : }
107 : else
108 : {
109 : std::cout << "TLD: " << std::string(info.f_tld, e - info.f_tld) << std::endl; // LCOV_EXCL_LINE
110 : }
111 : std::cout << "Offset: " << info.f_offset << std::endl; // LCOV_EXCL_LINE
112 : }
113 : }
114 : }
115 227 : if(result != TLD_RESULT_SUCCESS)
116 : {
117 7 : std::cerr << "error: URI \"" << uri << "\" is not considered valid." << std::endl;
118 7 : ++err_count;
119 : }
120 227 : }
121 :
122 : /** \brief List the default schemes accepted.
123 : *
124 : * This function lists all the schemes defined in the \p schemes variable.
125 : */
126 2 : void list()
127 : {
128 736 : for(const char *s(schemes); *s != '\0'; ++s)
129 : {
130 734 : if(*s == ',')
131 : {
132 122 : printf("\n");
133 : }
134 : else
135 : {
136 612 : printf("%c", *s);
137 : }
138 : }
139 2 : printf("\n");
140 2 : exit(1);
141 : }
142 :
143 : /** \brief Print out the help of the tld tool.
144 : *
145 : * This function prints out the help information about the validate_tld tool.
146 : * The function does not return.
147 : */
148 2 : void usage()
149 : {
150 2 : printf("Usage: validate_tld [-<opts>] <uri> | <email>\n");
151 2 : printf("Where <uri> or <email> are URIs starting with a valid scheme.\n");
152 2 : printf("The <email> scheme is mailto:.\n");
153 2 : printf("Where -<opts> are:\n");
154 2 : printf(" -h | --help print out this help screen\n");
155 2 : printf(" -l | --list print the default list of schemes\n");
156 2 : printf(" -s | --schemes <list> set the list of schemes with user's defined schemes\n");
157 2 : printf(" the list is a comma separate set of scheme names\n");
158 2 : printf(" -v | --verbose request some verbosity of the tool's work\n");
159 2 : exit(1);
160 : }
161 :
162 : /** \brief The validate tools.
163 : *
164 : * The parameters can include any number of URIs and emails. The system
165 : * must be told what's what using a protocol. For emails, use the name
166 : * "mail".
167 : *
168 : * \param[in] argc Number of command line arguments passed in.
169 : * \param[in] argv The arguments passed in.
170 : *
171 : * \return The tool returns 0 on success meaning that all the URIs and emails are valid, 1 otherwise.
172 : */
173 235 : int main(int argc, char *argv[])
174 : {
175 : try
176 : {
177 235 : bool uri(false);
178 :
179 468 : for(int i(1); i < argc; ++i)
180 : {
181 239 : if(argv[i][0] == '-')
182 : {
183 12 : if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
184 : {
185 2 : usage();
186 : /*NOTREACHED*/
187 : }
188 10 : else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--list") == 0)
189 : {
190 2 : list();
191 : /*NOTREACHED*/
192 : }
193 8 : else if(strcmp(argv[i], "--version") == 0)
194 : {
195 2 : printf("%s\n", LIBTLD_VERSION);
196 2 : if(verbose)
197 : {
198 1 : printf("libtld v%s\n", tld_version());
199 : }
200 2 : exit(1);
201 : }
202 6 : else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--schemes") == 0)
203 : {
204 3 : ++i;
205 3 : if(i >= argc)
206 : {
207 1 : fprintf(stderr, "error: the --schemes option requires a list of comma separated schemes.\n");
208 : }
209 3 : user_schemes = argv[i];
210 : }
211 3 : else if(strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
212 : {
213 3 : verbose = 1;
214 : }
215 : }
216 : else
217 : {
218 227 : uri = true;
219 227 : check_uri(argv[i]);
220 : }
221 : }
222 :
223 229 : if(!uri)
224 : {
225 2 : fprintf(stderr, "error: no URI was specified on the command line.\n");
226 2 : ++err_count;
227 : }
228 :
229 229 : return err_count > 0 ? 1 : 0;
230 : }
231 : catch(std::exception const& e) // LCOV_EXCL_LINE
232 : {
233 : // an exception occurred, print out the message and exit with an error
234 : //
235 : // note that this tool is not expecting any exception
236 : // because we only access the C interface which does
237 : // not throw
238 : //
239 : std::cerr << "exception: " << e.what() << std::endl; // LCOV_EXCL_LINE
240 : exit(1); // LCOV_EXCL_LINE
241 : }
242 705 : }
243 :
244 : // vim: ts=4 sw=4 et
|