xapian-core  2.0.0
databasehelpers.h
Go to the documentation of this file.
1 
4 /* Copyright 2002-2024 Olly Betts
5  * Copyright 2008 Lemur Consulting Ltd
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see
19  * <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef XAPIAN_INCLUDED_DATABASEHELPERS_H
23 #define XAPIAN_INCLUDED_DATABASEHELPERS_H
24 
25 #include <cerrno>
26 #include <fstream>
27 #include <string>
28 #include <string_view>
29 
30 #include "fileutils.h"
31 #include "parseint.h"
32 #include "safesysstat.h"
33 #include "safeunistd.h"
34 #include "str.h"
35 #include "xapian/error.h"
36 
49 int
51 
64 int
65 test_if_single_file_db(const struct stat& sb,
66  const std::string& path,
67  int* fd_ptr);
68 
73 template<typename A1,
74  typename A2,
75  typename A3,
76  typename A4,
77  typename A5,
78  typename A6>
79 void
80 read_stub_file(std::string_view file,
81  A1 action_auto,
82  A2 action_glass,
83  A3 action_honey,
84  A4 action_remote_prog,
85  A5 action_remote_tcp,
86  A6 action_inmemory)
87 {
88  // A stub database is a text file with one or more lines of this format:
89  // <dbtype> <serialised db object>
90  //
91  // Lines which start with a "#" character are ignored.
92  //
93  // Any paths specified in stub database files which are relative will be
94  // considered to be relative to the directory containing the stub database.
95  std::ifstream stub(std::string{file});
96  if (!stub) {
97  std::string msg = "Couldn't open stub database file: ";
98  msg += file;
99  throw Xapian::DatabaseNotFoundError(msg, errno);
100  }
101  std::string line;
102  unsigned int line_no = 0;
103  while (std::getline(stub, line)) {
104  ++line_no;
105  if (line.empty() || line[0] == '#')
106  continue;
107  std::string::size_type space = line.find(' ');
108  if (space == std::string::npos) space = line.size();
109 
110  std::string type(line, 0, space);
111  line.erase(0, space + 1);
112 
113  if (type == "auto") {
114  resolve_relative_path(line, file);
115  action_auto(line);
116  continue;
117  }
118 
119  if (type == "glass") {
120 #ifdef XAPIAN_HAS_GLASS_BACKEND
121  resolve_relative_path(line, file);
122  action_glass(line);
123  continue;
124 #else
125  (void)action_glass;
126  throw Xapian::FeatureUnavailableError("Glass backend disabled");
127 #endif
128  }
129 
130  if (type == "honey") {
131 #ifdef XAPIAN_HAS_HONEY_BACKEND
132  resolve_relative_path(line, file);
133  action_honey(line);
134  continue;
135 #else
136  (void)action_honey;
137  throw Xapian::FeatureUnavailableError("Honey backend disabled");
138 #endif
139  }
140 
141  if (type == "remote" && !line.empty()) {
142 #ifdef XAPIAN_HAS_REMOTE_BACKEND
143  if (line[0] == ':') {
144  // prog
145  // FIXME: timeouts
146  space = line.find(' ');
147  std::string args;
148  if (space == std::string::npos) {
149  action_remote_prog(std::string_view(line).substr(1),
150  std::string_view());
151  continue;
152  }
153  action_remote_prog(std::string_view(&line[1], space - 1),
154  std::string_view(line).substr(space + 1));
155  continue;
156  }
157  std::string::size_type colon = line.rfind(':');
158  if (colon != std::string::npos) {
159  // tcp
160  // FIXME: timeouts
161  // Avoid misparsing an IPv6 address without a port number. The
162  // port number is required, so just leave that case to the
163  // error handling further below.
164  if (!(line[0] == '[' && line.back() == ']')) {
165  unsigned int port;
166  if (parse_unsigned(line.c_str() + colon + 1, port)) {
167  std::string_view host{line};
168  host = host.substr(0, colon);
169  if (host[0] == '[' && host.back() == ']') {
170  host = host.substr(1, host.size() - 2);
171  }
172  action_remote_tcp(host, port);
173  continue;
174  }
175  }
176  }
177 #else
178  (void)action_remote_prog;
179  (void)action_remote_tcp;
180  throw Xapian::FeatureUnavailableError("Remote backend disabled");
181 #endif
182  }
183 
184  if (type == "inmemory" && line.empty()) {
185 #ifdef XAPIAN_HAS_INMEMORY_BACKEND
186  action_inmemory();
187  continue;
188 #else
189  (void)action_inmemory;
190  throw Xapian::FeatureUnavailableError("Inmemory backend disabled");
191 #endif
192  }
193 
194  if (type == "chert") {
195  auto msg = "Chert backend no longer supported";
197  }
198 
199  if (type == "flint") {
200  auto msg = "Flint backend no longer supported";
202  }
203 
204  // Don't include the line itself - that might help an attacker
205  // by revealing part of a sensitive file's contents if they can
206  // arrange for it to be read as a stub database via infelicities in
207  // an application which uses Xapian. The line number is enough
208  // information to identify the problem line.
209  std::string msg{file};
210  msg += ':';
211  msg += str(line_no);
212  msg += ": Bad line";
213  throw Xapian::DatabaseOpeningError(msg);
214  }
215 }
216 
217 #endif
Indicates an attempt to access a database not present.
Definition: error.h:1043
DatabaseOpeningError indicates failure to open a database.
Definition: error.h:569
Indicates an attempt to use a feature which is unavailable.
Definition: error.h:707
int test_if_single_file_db(int fd)
Probe if a file descriptor is a single-file database.
void read_stub_file(std::string_view file, A1 action_auto, A2 action_glass, A3 action_honey, A4 action_remote_prog, A5 action_remote_tcp, A6 action_inmemory)
Open, read and process a stub database file.
Hierarchy of classes which Xapian can throw as exceptions.
void resolve_relative_path(string &path, string_view base)
Resolve path relative to base.
Definition: fileutils.cc:105
File and path manipulation routines.
string str(int value)
Convert int to std::string.
Definition: str.cc:91
Parse signed and unsigned type from string and check for trailing characters.
bool parse_unsigned(const char *p, T &res)
Definition: parseint.h:29
include <sys/stat.h> with portability enhancements
<unistd.h>, but with compat.
Convert types to std::string.