1 /* doscan - Denial Of Service Capable Auditing of Networks       -*- C++ -*-
2  * Copyright (C) 2003 Florian Weimer
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 "config.h"
20 #include "rx.h"
21 
22 #include <string>
23 
24 // rx
25 
rx(const char * pattern,int options)26 rx::rx(const char* pattern, int options) throw (error)
27 {
28   const char *err;
29   int offset;
30 
31   regexp = pcre_compile(pattern, options, &err, &offset, 0);
32   if (regexp == 0) {
33     throw error(err, offset);
34   }
35 
36   pcre_fullinfo(regexp, 0, PCRE_INFO_CAPTURECOUNT, &capture_count);
37 }
38 
~rx()39 rx::~rx()
40 {
41   free(regexp);
42 }
43 
44 bool
exec(const std::string & data,unsigned offset,int options) const45 rx::exec(const std::string& data, unsigned offset, int options) const
46 {
47   // pcre_exec() might need to store the matches for backreferences in
48   // the pattern, so we always pass the ovector array of the suitable
49   // length.
50 
51   int ovecsize = (capture_count + 1) * 3;
52   int ovector[ovecsize];
53   int result = pcre_exec(regexp, 0, data.data(), data.size(), offset, options,
54                          ovector, ovecsize);
55 
56   if (result >= 0) {
57     return true;
58   } else if (result == PCRE_ERROR_NOMATCH) {
59     return false;
60   } else {
61     throw match_error(result);
62   }
63 }
64 
65 bool
exec(const std::string & data,match & m,unsigned offset,int options) const66 rx::exec(const std::string& data, match& m, unsigned offset, int options) const
67 {
68   // pcre_exec() might need to store the matches for backreferences in
69   // the pattern, so we always pass the ovector array of the suitable
70   // length.
71 
72   int ovecsize = (capture_count + 1) * 3;
73   int ovector[ovecsize];
74   int result = pcre_exec(regexp, 0, data.data(), data.size(), offset, options,
75                          ovector, ovecsize);
76 
77   if (result > 0) {
78     m.first = data.begin() + ovector[0];
79     m.last = data.begin() + ovector[1];
80     return true;
81   } else if (result == 0 || result == PCRE_ERROR_NOMATCH) {
82     m.first = m.last = data.begin();
83     return false;
84   } else {
85     throw match_error(result);
86   }
87 }
88 
89 bool
exec(const std::string & data,matches & m,unsigned offset,int options) const90 rx::exec(const std::string& data, matches& m,
91          unsigned offset, int options) const
92 {
93   // pcre_exec() might need to store the matches for backreferences in
94   // the pattern, so we always pass the ovector array of the suitable
95   // length.
96 
97   int ovecsize = (capture_count + 1) * 3;
98   int ovector[ovecsize];
99   int result = pcre_exec(regexp, 0, data.data(), data.size(), offset, options,
100                          ovector, ovecsize);
101 
102   if (result >= 0) {
103     m.set(data, ovector, ovecsize);
104     return true;
105   } else if (result == PCRE_ERROR_NOMATCH) {
106     m.clear();
107     return false;
108   } else {
109     throw match_error(result);
110   }
111 }
112 
113 // matches
114 
115 void
set(const std::string & data,int * ovector,int ovecsize)116 rx::matches::set(const std::string& data, int *ovector, int ovecsize)
117 {
118   unsigned count = ovecsize / 3;
119   const std::string::const_iterator begin = data.begin();
120 
121   array.resize(count);
122 
123   for (unsigned j = 0; j < count; j++) {
124     array[j].first = begin + ovector[2 * j];
125     array[j].last = begin + ovector[2 * j + 1];
126   }
127 }
128