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