1 /*
2 * Copyright 2007-2021 Fabrice Colin
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include <getopt.h>
20 #include <stdlib.h>
21 #include <iostream>
22 #include <string>
23 #include <set>
24 #include <giomm/init.h>
25 #include <glibmm/init.h>
26
27 #include "config.h"
28 #include "StringManip.h"
29 #include "MIMEScanner.h"
30 #include "Url.h"
31 #include "DBusIndex.h"
32
33 using namespace std;
34
35 static struct option g_longOptions[] = {
36 {"get", 0, 0, 'g'},
37 {"help", 0, 0, 'h'},
38 {"list", 0, 0, 'l'},
39 {"reload", 0, 0, 'r'},
40 {"set", 1, 0, 's'},
41 {"version", 0, 0, 'v'},
42 {0, 0, 0, 0}
43 };
44
45
printLabels(const set<string> & labels,const string & fileName)46 static void printLabels(const set<string> &labels, const string &fileName)
47 {
48 if (fileName.empty() == false)
49 {
50 clog << fileName << endl;
51 }
52 clog << "Labels: ";
53
54 for (set<string>::const_iterator labelIter = labels.begin();
55 labelIter != labels.end(); ++labelIter)
56 {
57 if (labelIter->substr(0, 2) == "X-")
58 {
59 continue;
60 }
61 clog << "[" << Url::escapeUrl(*labelIter) << "]";
62 }
63 clog << endl;
64 }
65
printHelp(void)66 static void printHelp(void)
67 {
68 // Help
69 clog << "pinot-label - Label files from the command-line\n\n"
70 << "Usage: pinot-label [OPTIONS] [FILES]\n\n"
71 << "Options:\n"
72 << " -g, --get get the labels list for the given file\n"
73 << " -h, --help display this help and exit\n"
74 << " -l, --list list known labels\n"
75 << " -r, --reload get the daemon to reload the configuration\n"
76 << " -s, --set set labels on the given file\n"
77 << " -v, --version output version information and exit\n\n";
78 clog << "Examples:\n"
79 << "pinot-label --get /home/fabrice/Documents/Bozo.txt\n\n"
80 << "pinot-label --list\n\n"
81 << "pinot-label --set \"[Clowns][Fun][My Hero]\" /home/fabrice/Documents/Bozo.txt\n\n"
82 << "Report bugs to " << PACKAGE_BUGREPORT << endl;
83 }
84
main(int argc,char ** argv)85 int main(int argc, char **argv)
86 {
87 set<string> labels;
88 string labelsString;
89 int longOptionIndex = 0;
90 unsigned int docId = 0;
91 int minArgNum = 1;
92 bool getLabels = false, getDocumentLabels = false, reloadIndex = false, setDocumentLabels = false, success = false;
93
94 // Look at the options
95 int optionChar = getopt_long(argc, argv, "ghlrs:v", g_longOptions, &longOptionIndex);
96 while (optionChar != -1)
97 {
98 set<string> engines;
99
100 switch (optionChar)
101 {
102 case 'g':
103 getDocumentLabels = true;
104 break;
105 case 'h':
106 printHelp();
107 return EXIT_SUCCESS;
108 case 'l':
109 minArgNum = 0;
110 getLabels = true;
111 break;
112 case 'r':
113 minArgNum = 0;
114 reloadIndex = true;
115 break;
116 case 's':
117 setDocumentLabels = true;
118 if (optarg != NULL)
119 {
120 labelsString = optarg;
121 }
122 break;
123 case 'v':
124 clog << "pinot-label - " << PACKAGE_STRING << "\n\n"
125 << "This is free software. You may redistribute copies of it under the terms of\n"
126 << "the GNU General Public License <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>.\n"
127 << "There is NO WARRANTY, to the extent permitted by law." << endl;
128 return EXIT_SUCCESS;
129 default:
130 return EXIT_FAILURE;
131 }
132
133 // Next option
134 optionChar = getopt_long(argc, argv, "ghls:v", g_longOptions, &longOptionIndex);
135 }
136
137 if (argc == 1)
138 {
139 printHelp();
140 return EXIT_SUCCESS;
141 }
142
143 if ((argc < 2) ||
144 (argc - optind < minArgNum))
145 {
146 clog << "Not enough parameters" << endl;
147 return EXIT_FAILURE;
148 }
149
150 if ((setDocumentLabels == true) &&
151 (labelsString.empty() == true))
152 {
153 clog << "Incorrect parameters" << endl;
154 return EXIT_FAILURE;
155 }
156
157 Glib::init();
158 Gio::init();
159 // Initialize GType
160 #if !GLIB_CHECK_VERSION(2,35,0)
161 g_type_init();
162 #endif
163
164 MIMEScanner::initialize("", "");
165
166 // We need a pure DBusIndex object
167 DBusIndex index(NULL);
168
169 if (getLabels == true)
170 {
171 if (index.getLabels(labels) == true)
172 {
173 printLabels(labels, "");
174
175 success = true;
176 }
177 }
178
179 while (optind < argc)
180 {
181 string fileParam(argv[optind]);
182 Url thisUrl(fileParam, "");
183
184 // Rewrite it as a local URL
185 string urlParam(thisUrl.getProtocol());
186 urlParam += "://";
187 urlParam += thisUrl.getLocation();
188 if (thisUrl.getFile().empty() == false)
189 {
190 urlParam += "/";
191 urlParam += thisUrl.getFile();
192 }
193 #ifdef DEBUG
194 clog << "URL rewritten to " << urlParam << endl;
195 #endif
196
197 if ((getDocumentLabels == true) ||
198 (setDocumentLabels == true))
199 {
200 docId = index.hasDocument(urlParam);
201 if (docId == 0)
202 {
203 clog << fileParam << " is not indexed" << endl;
204 success = false;
205
206 // Next
207 ++optind;
208 continue;
209 }
210 }
211
212 if (getDocumentLabels == true)
213 {
214 labels.clear();
215
216 if (index.getDocumentLabels(docId, labels) == true)
217 {
218 printLabels(labels, fileParam);
219
220 success = true;
221 }
222 }
223
224 if (setDocumentLabels == true)
225 {
226 string::size_type endPos = 0;
227 string label(StringManip::extractField(labelsString, "[", "]", endPos));
228
229 labels.clear();
230
231 // Parse labels
232 while (label.empty() == false)
233 {
234 labels.insert(Url::unescapeUrl(label));
235
236 if (endPos == string::npos)
237 {
238 break;
239 }
240 label = StringManip::extractField(labelsString, "[", "]", endPos);
241 }
242
243 #ifdef DEBUG
244 printLabels(labels, fileParam);
245 #endif
246 success = index.setDocumentLabels(docId, labels);
247 }
248
249 // Next
250 ++optind;
251 }
252
253 if (reloadIndex == true)
254 {
255 index.reload();
256 }
257
258 MIMEScanner::shutdown();
259
260 // Did whatever operation we carried out succeed ?
261 if (success == true)
262 {
263 return EXIT_SUCCESS;
264 }
265
266 return EXIT_FAILURE;
267 }
268