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