~ubuntu-branches/ubuntu/edgy/lurker/edgy

« back to all changes in this revision

Viewing changes to index/search.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Meurer
  • Date: 2004-09-26 16:27:51 UTC
  • Revision ID: james.westby@ubuntu.com-20040926162751-z1ohcjltv7ojtg6z
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Id: search.cpp,v 1.5 2004/08/27 18:11:59 terpstra Exp $
 
2
 *  
 
3
 *  search.cpp - Search for messages in lurker database (optionally delete)
 
4
 *  
 
5
 *  Copyright (C) 2004 - Wesley W. Terpstra
 
6
 *  
 
7
 *  License: GPL
 
8
 *  
 
9
 *  Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
 
10
 *  
 
11
 *    This program is free software; you can redistribute it and/or modify
 
12
 *    it under the terms of the GNU General Public License as published by
 
13
 *    the Free Software Foundation; version 2.
 
14
 *    
 
15
 *    This program is distributed in the hope that it will be useful,
 
16
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *    GNU General Public License for more details.
 
19
 *    
 
20
 *    You should have received a copy of the GNU General Public License
 
21
 *    along with this program; if not, write to the Free Software
 
22
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
 */
 
24
 
 
25
#define _XOPEN_SOURCE 500
 
26
#define _FILE_OFFSET_BITS 64
 
27
 
 
28
#include <Search.h>
 
29
#include <Keys.h>
 
30
 
 
31
#include <iostream>
 
32
#include <assert.h>
 
33
#include <stdio.h>
 
34
 
 
35
using namespace std;
 
36
 
 
37
void help(const char* name)
 
38
{
 
39
        cerr << "Lurker-search (v" << VERSION << ") searches for messages in a lurker database.\n";
 
40
        cerr << "\n";
 
41
        cerr << "Usage: " << name << " -c <config-file> -k <keyword> [ -d -f -v -q ] <terms>*\n";
 
42
        cerr << "\n";
 
43
        cerr << "\t-c <config-file> Use this config file for lurker settings\n";
 
44
        cerr << "\t-k <keyword>     Add the specified keyword tag to hits\n";
 
45
        cerr << "\t-d               Delete matching messages\n";
 
46
        cerr << "\t-f               Don't prompt before deleting\n";
 
47
        cerr << "\t-v               Output message summaries\n";
 
48
        cerr << "\t-q               Don't output message ids or status\n";
 
49
        cerr << "\n";
 
50
        cerr << "Execute a keyword search to find messages.\n";
 
51
        cerr << "The following search terms are supported (all must match):\n";
 
52
        cerr << " -xxx   - select messages which do NOT match this term\n";
 
53
        cerr << " id:xxx - select a message by the Message-ID field\n";
 
54
        cerr << " rt:xxx - select messages which reply to the chosen Message-ID\n";
 
55
        cerr << " th:xxx - select messages included in this thread\n";
 
56
        cerr << " ml:xxx - select messages in this mailing list\n";
 
57
        cerr << " gr:xxx - select messages in this mailing list group\n";
 
58
        cerr << " au:xxx - select messages with this term in the author fields\n";
 
59
        cerr << " sb:xxx - select messages with this word in the subject\n";
 
60
        cerr << " lang:xx - select messages in this language\n";
 
61
        cerr << "\n";
 
62
}
 
63
 
 
64
int main(int argc, char** argv)
 
65
{
 
66
        int c;
 
67
        
 
68
        const char* config = 0;
 
69
        bool erase = false;
 
70
        bool force = false;
 
71
        bool verbose = false;
 
72
        bool quiet = false;
 
73
        string keyword;
 
74
        
 
75
        while ((c = getopt(argc, (char*const*)argv, "c:k:dvfq?")) != -1)
 
76
        {
 
77
                switch ((char)c)
 
78
                {
 
79
                case 'c':
 
80
                        config = optarg;
 
81
                        break;
 
82
                case 'k':
 
83
                        keyword = optarg;
 
84
                        break;
 
85
                case 'd':
 
86
                        erase = true;
 
87
                        break;
 
88
                case 'f':
 
89
                        force = true;
 
90
                        break;
 
91
                case 'v':
 
92
                        verbose = true;
 
93
                        break;
 
94
                case 'q':
 
95
                        quiet = true;
 
96
                        break;
 
97
                default:
 
98
                        help(argv[0]);
 
99
                        return 1;
 
100
                }
 
101
        }
 
102
        
 
103
        if (!config || optind >= argc)
 
104
        {
 
105
                help(argv[0]);
 
106
                return 1;
 
107
        }
 
108
        
 
109
        Config cfg;
 
110
        if (cfg.load(config) != 0)
 
111
        {
 
112
                cerr << cfg.getError() << flush;
 
113
                return 1;
 
114
        }
 
115
        
 
116
        ESort::Writer* db;
 
117
        auto_ptr<ESort::Reader> dbr;
 
118
        
 
119
        if (erase || keyword != "")
 
120
        {
 
121
                if (verbose) cerr << "opening " << cfg.dbdir << "/db read-write" << endl;
 
122
                // Work around g++ 2.95 bug
 
123
                auto_ptr<ESort::Writer> w
 
124
                        (ESort::Writer::opendb(cfg.dbdir + "/db"));
 
125
                db = w.get();
 
126
                dbr = w;
 
127
        }
 
128
        else
 
129
        {
 
130
                if (verbose) cerr << "opening " << cfg.dbdir << "/db read-only" << endl;
 
131
                auto_ptr<ESort::Reader> r
 
132
                        (ESort::Reader::opendb(cfg.dbdir + "/db"));
 
133
                dbr = r;
 
134
        }
 
135
 
 
136
        if (!dbr.get())
 
137
        {
 
138
                perror("opening database");
 
139
                return 1;
 
140
        }
 
141
        
 
142
        Search s(cfg, dbr.get(), ESort::Forward);
 
143
        
 
144
        while (optind < argc) s.keyword(argv[optind++]);
 
145
        
 
146
        vector<Summary> result;
 
147
        vector<Summary>::size_type sz = 0;
 
148
        while (s.pull(1, result) && result.size() == sz+1)
 
149
        {
 
150
                sz = result.size();
 
151
                
 
152
                if (!quiet)
 
153
                        cout << "id: " << result.back().id().serialize() << "\n";
 
154
                if (verbose)
 
155
                {
 
156
                        string ok;
 
157
                        if ((ok = result.back().load(dbr.get(), cfg)) != "")
 
158
                        {
 
159
                                cerr << "Failed to load: " << ok << "\n";
 
160
                                return 1;
 
161
                        }
 
162
                        cout << "sb: " << result.back().subject() << "\n";
 
163
                        cout << "au: \"" << result.back().author_name() << "\" <"
 
164
                             << result.back().author_email() << ">\n";
 
165
                }
 
166
        }
 
167
        
 
168
        if (result.empty()) return 0;
 
169
        
 
170
        if (erase && !force)
 
171
        {
 
172
                cout << flush;
 
173
                cerr << "Are you certain you want to delete these messages? (yes/no) [no] " << flush;
 
174
                string ok;
 
175
                std::getline(cin, ok);
 
176
                if (ok != "yes")
 
177
                {
 
178
                        cerr << "aborted!\n";
 
179
                        return 1;
 
180
                }
 
181
        }
 
182
        
 
183
        if (keyword != "")
 
184
        {
 
185
                if (!quiet) cerr << "Tagging messages with keyword" << endl;
 
186
                for (vector<Summary>::iterator i = result.begin(); 
 
187
                     i != result.end();
 
188
                     ++i)
 
189
                {
 
190
                        if (db->insert(
 
191
                                LU_KEYWORD +
 
192
                                keyword +
 
193
                                '\0' +
 
194
                                i->id().raw()) != 0)
 
195
                        {
 
196
                                perror("insert");
 
197
                                cerr << "Tagging with keyword failed; operation aborted.\n";
 
198
                                return 1; 
 
199
                        }
 
200
                }
 
201
        }
 
202
        
 
203
        if (erase)
 
204
        {
 
205
                if (!quiet) cerr << "Marking messages as deleted" << endl;
 
206
                for (vector<Summary>::iterator i = result.begin(); 
 
207
                     i != result.end();
 
208
                     ++i)
 
209
                {
 
210
                        if (db->insert(
 
211
                                LU_KEYWORD +
 
212
                                string(LU_KEYWORD_DELETED) +
 
213
                                '\0' +
 
214
                                i->id().raw()) != 0)
 
215
                        {
 
216
                                perror("insert");
 
217
                                cerr << "Delete keyword failed; operation aborted.\n";
 
218
                                return 1; 
 
219
                        }
 
220
                        
 
221
                        if (db->insert(
 
222
                                LU_SUMMARY +
 
223
                                i->id().raw() + 
 
224
                                LU_MESSAGE_DELETED) != 0)
 
225
                        {
 
226
                                perror("insert");
 
227
                                cerr << "Delete summary failed; operation aborted.\n";
 
228
                                return 1;
 
229
                        }
 
230
                }
 
231
        }
 
232
        
 
233
        if (erase || keyword != "")
 
234
        {
 
235
                if (!quiet) cerr << "Committing changes to disk" << endl;
 
236
                if (db->commit() != 0)
 
237
                {
 
238
                        perror("commit");
 
239
                        cerr << "Commit failed; operation aborted.\n";
 
240
                        return 1;
 
241
                }
 
242
                
 
243
                if (!quiet)
 
244
                {
 
245
                        cerr << "\n";
 
246
                        cerr << "Database modified -- cache is now invalid.\n";
 
247
                        cerr << "Re-run lurker-prune with the '-p' option.\n";
 
248
                }
 
249
        }
 
250
        
 
251
        return 0;
 
252
}