DABC (Data Acquisition Backbone Core)  2.9.9
Url.cxx
Go to the documentation of this file.
1 // $Id: Url.cxx 3862 2018-05-11 10:06:18Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "dabc/Url.h"
17 
18 #include "dabc/logging.h"
19 #include "dabc/ConfigBase.h"
20 
22 {
23  SetUrl(std::string());
24 }
25 
26 dabc::Url::Url(const char* url)
27 {
28  SetUrl(std::string(url ? url : ""));
29 }
30 
31 dabc::Url::Url(const std::string &url)
32 {
33  SetUrl(url);
34 }
35 
37 {
38 }
39 
41 {
42  SetUrl("", false);
43 }
44 
45 
46 bool dabc::Url::SetUrl(const std::string &url, bool showerr)
47 {
48  fValid = false;
49  fUrl.clear();
50  fProtocol.clear();
51  fHostName.clear();
52  fPort = 0;
53  fFileName.clear();
54  fOptions.clear();
55 
56  if (url.length()==0) return false;
57 
58  fUrl = url;
59  fValid = true;
60 
61  std::string s = fUrl;
62  std::size_t pos = s.find("://");
63 
64  if (pos != std::string::npos) {
65  fProtocol = s.substr(0, pos);
66  s.erase(0, pos + 3);
67  }
68 
69  if (s.length() == 0) return fValid;
70 
71  // first question in url is position for options,
72  pos = s.find("?");
73  if (pos != std::string::npos) {
74  SetOptions(s.substr(pos+1));
75  s.erase(pos);
76  }
77 
78  pos = s.find("/");
79 
80  if (pos==0) {
81  fFileName = s;
82  } else
83  if (pos != std::string::npos) {
84  fHostName = s.substr(0, pos);
85  fFileName = s.substr(pos+1);
86  } else {
87  fHostName = s;
88  }
89 
90  pos = fHostName.find(":");
91  if (pos != std::string::npos) {
92  if (!dabc::str_to_int(fHostName.c_str()+pos+1, &fPort)) {
93  if (showerr) EOUT("Invalid URL format:%s - wrong port number", fHostName.c_str());
94  fValid = false;
95  }
96  fHostName.erase(pos);
97  }
98 
99  return fValid;
100 }
101 
102 void dabc::Url::SetOptions(const std::string &opt)
103 {
104  fOptions = opt;
105 
106  ReplaceSpecialSymbols(fOptions);
107 }
108 
109 void dabc::Url::ReplaceSpecialSymbols(std::string& opt)
110 {
111  // replace special symbols which could appear in the options string
112 
113  std::size_t pos = 0;
114  while ((pos = opt.find("%27")) != std::string::npos) opt.replace(pos, 3, "\'");
115  while ((pos = opt.find("%22")) != std::string::npos) opt.replace(pos, 3, "\"");
116  while ((pos = opt.find("%20")) != std::string::npos) opt.replace(pos, 3, " ");
117  while ((pos = opt.find("%3E")) != std::string::npos) opt.replace(pos, 3, ">");
118  while ((pos = opt.find("%3C")) != std::string::npos) opt.replace(pos, 3, "<");
119  while ((pos = opt.find("%5B")) != std::string::npos) opt.replace(pos, 3, "[");
120  while ((pos = opt.find("%5D")) != std::string::npos) opt.replace(pos, 3, "]");
121 }
122 
123 
124 std::string dabc::Url::GetFullName() const
125 {
126  if (fFileName.length()==0) return fHostName;
127  if (fHostName.length()==0) return fFileName;
128 
129  return dabc::format("%s/%s", fHostName.c_str(), fFileName.c_str());
130 }
131 
132 std::string dabc::Url::GetPortStr() const
133 {
134  if (fPort<=0) return std::string();
135 
136  return dabc::format("%d", fPort);
137 }
138 
139 std::string dabc::Url::GetHostNameWithPort(int dfltport) const
140 {
141  int port = fPort;
142  if (port <= 0) port = dfltport;
143 
144  return (port>0) ? fHostName + dabc::format(":%d", port) : fHostName;
145 }
146 
147 std::string dabc::Url::ComposeItemName(int nodeid, const std::string &itemname)
148 {
149  if (nodeid<0) return std::string();
150 
151  return dabc::format("dabc://node%d/%s", nodeid, itemname.length() > 0 ? itemname.c_str() : "");
152 }
153 
154 std::string dabc::Url::ComposePortName(int nodeid, const std::string &fullportname, int portid)
155 {
156  std::string sbuf;
157  if ((nodeid<0) || fullportname.empty()) return sbuf;
158 
159  sbuf = ComposeItemName(nodeid, fullportname);
160 
161  if (portid>=0)
162  sbuf += dabc::format("%d", portid);
163 
164  return sbuf;
165 }
166 
167 bool dabc::Url::DecomposeItemName(const std::string &name, int& nodeid, std::string& fullportname)
168 {
169  Url url;
170 
171 // DOUT0("Url %s valid %d protocol %s host %s file %s", name, url.IsValid(), url.GetProtocol().c_str(), url.GetHostName().c_str(), url.GetFileName().c_str());
172 
173  if (!url.SetUrl(name, false)) return false;
174 
175  if (url.GetProtocol().length()==0) {
176  fullportname = url.GetFullName();
177  nodeid = -1;
178  return true;
179  }
180 
181  if (url.GetProtocol().compare("dabc")!=0) return false;
182 
183  std::string node = url.GetHostName();
184  if (node.compare(0, 4, "node")!=0) return false;
185  node.erase(0,4);
186 
187  nodeid = -1;
188  if (!str_to_int(node.c_str(), &nodeid)) return false;
189  if (nodeid<0) return false;
190 
191  fullportname = url.GetFileName();
192  return true;
193 }
194 
195 std::string dabc::Url::GetOptionsPart(int number) const
196 {
197  std::string res;
198  GetOption("", number, &res);
199  return res;
200 }
201 
202 
203 bool dabc::Url::GetOption(const std::string &optname, int optionnumber, std::string* value) const
204 {
205  if (value) value->clear();
206 
207  if (fOptions.empty()) return false;
208  if ((optionnumber<0) && optname.empty()) return false;
209 
210  int cnt = 0;
211  size_t p = 0;
212 
213  while (p < fOptions.length()) {
214 
215  // instead of simple search we should analyze different quotes, ignoring symbols inside quotes
216  // size_t separ = fOptions.find("&", p);
217  // if (separ==std::string::npos) separ = fOptions.length();
218 
219 
220  bool q1(false), q2(false), special(false);
221 
222  size_t separ = p, posequal = std::string::npos;
223  for(;separ<fOptions.length();separ++) {
224 
225  if (q1 || q2) {
226  if (fOptions[separ] == '\\') { special = !special; continue; }
227  else special = false;
228  }
229 
230  if (!q2 && (fOptions[separ]=='\'') && !special) { q1 = !q1; continue; }
231  if (!q1 && (fOptions[separ]=='\"') && !special) { q2 = !q2; continue; }
232 
233  if (!q1 && !q2) {
234  if (fOptions[separ] == '&') break;
235  if ((fOptions[separ] == '=') && (posequal = std::string::npos)) posequal = separ;
236  }
237  }
238 
239 
240 // printf("Search for option %s fullstr %s p=%d separ=%d\n", optname.c_str(), fOptions.c_str(), p, separ);
241 
242  if (optionnumber>=0) {
243  if (cnt==optionnumber) {
244  if (value) *value = fOptions.substr(p, separ-p);
245  return true;
246  }
247  cnt++;
248  } else
249  if (separ-p >= optname.length()) {
250  bool find = fOptions.compare(p, optname.length(), optname)==0;
251  if (find) {
252 
253  p+=optname.length();
254 
255  // this is just option name, nothing else - value is empty http://host?option
256  if (p==separ) return true;
257 
258  if (fOptions[p]=='=') {
259  // also empty option possible, but with syntax http://host?option=
260  p++;
261  if ((p<separ) && value) {
262  *value = fOptions.substr(p, separ-p);
263  // check if surrounded by quotes or double quotes and remove them
264  if ((value->length()>1) && ((value->at(0)=='\'') || (value->at(0)=='\"'))
265  && (value->at(0) == value->at(value->length()-1))) {
266  value->erase(0,1);
267  value->resize(value->length()-1);
268  }
269  }
270  return true;
271  }
272  }
273  }
274 
275  p = separ + 1; // +1 while we should skip & from search, no matter at the end of the string
276  }
277 
278  return false;
279 }
280 
281 std::string dabc::Url::GetOptionStr(const std::string &optname, const std::string &dflt) const
282 {
283  std::string res;
284 
285  if (GetOption(optname, -1, &res)) return res;
286 
287  return dflt;
288 }
289 
290 int dabc::Url::GetOptionInt(const std::string &optname, int dflt) const
291 {
292  std::string res = GetOptionStr(optname);
293 
294  if (res.empty()) return dflt;
295 
296  int resi(0);
297  if (str_to_int(res.c_str(), &resi)) return resi;
298 
299  return dflt;
300 }
301 
302 double dabc::Url::GetOptionDouble(const std::string &optname, double dflt) const
303 {
304  std::string res = GetOptionStr(optname);
305 
306  if (res.empty()) return dflt;
307 
308  double resd(0.);
309  if (str_to_double(res.c_str(), &resd)) return resd;
310 
311  return dflt;
312 }
313 
314 bool dabc::Url::GetOptionBool(const std::string &optname, bool dflt) const
315 {
316  std::string res = GetOptionStr(optname);
317 
318  if (res.empty()) return dflt;
319 
320  if (res == xmlTrueValue) return true;
321  if (res == xmlFalseValue) return false;
322 
323  return dflt;
324 }
325 
Uniform Resource Locator interpreter.
Definition: Url.h:33
std::string GetOptionsPart(int number=0) const
Definition: Url.cxx:195
std::string GetOptionStr(const std::string &optname, const std::string &dflt="") const
Definition: Url.cxx:281
bool SetUrl(const std::string &url, bool showerr=true)
Definition: Url.cxx:46
std::string GetFullName() const
Definition: Url.cxx:124
bool GetOptionBool(const std::string &optname, bool dflt=false) const
Definition: Url.cxx:314
std::string GetFileName() const
Definition: Url.h:62
int GetOptionInt(const std::string &optname, int dflt=0) const
Definition: Url.cxx:290
std::string GetHostName() const
Definition: Url.h:58
std::string GetProtocol() const
Definition: Url.h:57
Url()
Definition: Url.cxx:21
std::string GetPortStr() const
Definition: Url.cxx:132
void Reset()
Definition: Url.cxx:40
static void ReplaceSpecialSymbols(std::string &opt)
!
Definition: Url.cxx:109
std::string GetHostNameWithPort(int dfltport=0) const
Definition: Url.cxx:139
static bool DecomposeItemName(const std::string &url, int &nodeid, std::string &itemtname)
Method decompose from url nodeid and full item name, which includes all parents.
Definition: Url.cxx:167
virtual ~Url()
Definition: Url.cxx:36
double GetOptionDouble(const std::string &optname, double dflt=0.) const
Definition: Url.cxx:302
void SetOptions(const std::string &opt)
Method allows to set URL options directly to be able use all Get methods.
Definition: Url.cxx:102
bool GetOption(const std::string &optname, int optionnumber=-1, std::string *value=nullptr) const
Definition: Url.cxx:203
static std::string ComposeItemName(int nodeid, const std::string &itemname="")
!
Definition: Url.cxx:147
static std::string ComposePortName(int nodeid, const std::string &fullportname, int portid=-1)
! Method creates url string with port address, which includes nodeid and full portname If optional pa...
Definition: Url.cxx:154
#define EOUT(args ...)
Definition: logging.h:150
bool str_to_double(const char *val, double *res)
Convert string to double value.
Definition: string.cxx:216
std::string format(const char *fmt,...)
Definition: string.cxx:49
const char * xmlTrueValue
Definition: ConfigBase.cxx:90
const char * xmlFalseValue
Definition: ConfigBase.cxx:91
bool str_to_int(const char *val, int *res)
Convert string to integer value.
Definition: string.cxx:142