1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
23 #include "OCUtilities.h"
25 #include <boost/algorithm/string.hpp>
32 #include <uri.h> // libcoap
33 #include <option.h> // libcoap
38 // Helper function to escape special character.
39 std::string escapeString(const std::string& value)
41 std::ostringstream stringStream;
42 for (const char& c : value)
46 case '\\': stringStream << "\\\\";
48 case '"': stringStream << "\\\"";
50 case '/': stringStream << "\\/";
52 case '\b': stringStream << "\\b";
54 case '\f': stringStream << "\\f";
56 case '\n': stringStream << "\\n";
58 case '\r': stringStream << "\\r";
60 case '\t': stringStream << "\\t";
62 default: stringStream << c;
66 return stringStream.str();
69 // [TODO] remove this function
70 // it seems that the C stack is parsing and giving out the query separately.
71 // the entire URI need not be parsed
72 static OC::Utilities::QueryParamsKeyVal tempPatch(const std::string& _uri)
74 OC::Utilities::QueryParamsKeyVal qp;
80 std::vector<std::string> queryparams;
81 boost::split(queryparams, _uri, boost::is_any_of("&"));
83 for(std::string& it: queryparams)
85 std::vector<std::string> keyval;
86 boost::split(keyval, it, boost::is_any_of("="));
87 if(2 == keyval.size())
89 qp[keyval.at(0)] = keyval.at(1);
96 // implementation can be split into two functions if needed
97 // uses do{}while(0) to avoid returning from multiple locations
98 OC::Utilities::QueryParamsKeyVal OC::Utilities::getQueryParams(const std::string& _uri)
101 // this is a temporary fix. [TODO] remove this after permanent fix
102 return tempPatch(_uri);
104 OC::Utilities::QueryParamsKeyVal qp;
105 unsigned char *bufptr = nullptr; // don't delete via bufptr
106 unsigned char *bufptrToDelete = nullptr; // bufptr may be incremented. need this one to keep track.
114 coap_uri_t coapuri = {{0}};
115 unsigned char* uristr = reinterpret_cast<unsigned char*>(const_cast<char*>(_uri.c_str()));
117 if(coap_split_uri(uristr, _uri.length(), &coapuri) < 0)
122 size_t buflen = 2048; // this is big enough buffer. [TODO] may want to downsize it. I have seen that the size may have to be greater than coap.query.length, which is counterintuitve but there may be a bug in coap uri parser.
123 bufptrToDelete = bufptr = new (std::nothrow) unsigned char[buflen](); // why heap? will need it for incrementing the pointer in the logic below
131 if((segments = coap_split_query(coapuri.query.s, coapuri.query.length, bufptr, &buflen)) < 0)
136 // coap uri parser has weird api. its not straighforward to understand what the coap function calls below do.
137 // coap uri parser lacks ability to split the key value pair in query params. that will be done in getQueryParams() function
138 std::vector<std::string> queryparams;
141 queryparams.push_back(std::string (reinterpret_cast<char*>(coap_opt_value(bufptr)), coap_opt_length(bufptr)));
142 bufptr += coap_opt_size(bufptr);
145 if(queryparams.empty())
151 for(std::string& it : queryparams)
153 std::vector<std::string> keyval;
154 boost::split(keyval, it, boost::is_any_of("="));
155 if(2 == keyval.size())
157 qp[keyval.at(0)] = keyval.at(1);
165 delete [] bufptrToDelete;
172 OCStackResult result_guard(const OCStackResult r)
174 std::ostringstream os;
179 os << "result_guard(): unhandled exception: " << OCException::reason(r);
180 throw OCException(os.str(), r);
182 /* Exceptional conditions: */
183 case OC_STACK_NO_MEMORY:
184 case OC_STACK_COMM_ERROR:
185 case OC_STACK_NOTIMPL:
186 case OC_STACK_INVALID_URI:
187 case OC_STACK_INVALID_QUERY:
188 case OC_STACK_INVALID_IP:
189 case OC_STACK_INVALID_PORT:
190 case OC_STACK_INVALID_CALLBACK:
191 case OC_STACK_INVALID_METHOD:
192 case OC_STACK_INVALID_PARAM:
193 case OC_STACK_INVALID_OBSERVE_PARAM:
194 os << "result_guard(): " << r << ": " << OCException::reason(r);
195 throw OCException(os.str(), r);
197 /* Non-exceptional failures or success: */
199 case OC_STACK_NO_RESOURCE:
200 case OC_STACK_RESOURCE_ERROR:
201 case OC_STACK_SLOW_RESOURCE:
202 case OC_STACK_NO_OBSERVERS:
203 case OC_STACK_OBSERVER_NOT_FOUND:
204 case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
206 case OC_STACK_PRESENCE_STOPPED:
207 case OC_STACK_PRESENCE_TIMEOUT:
208 case OC_STACK_PRESENCE_DO_NOT_HANDLE: