00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #define ULXR_NEED_EXPORTS
00033 #include <ulxmlrpcpp/ulxmlrpcpp.h>
00034
00035 #include <cstdio>
00036 #include <cctype>
00037
00038 #include <ulxmlrpcpp/ulxr_htmlform_handler.h>
00039 #include <ulxmlrpcpp/ulxr_http_protocol.h>
00040 #include <ulxmlrpcpp/ulxr_except.h>
00041
00042
00043 namespace ulxr {
00044
00045
00046 namespace hidden {
00047
00048
00049 ULXR_API_IMPL0 SubResourceBase::SubResourceBase(const CppString &in_name, const CppString &in_descr)
00050 : name(in_name)
00051 , descr(in_descr)
00052 {
00053 }
00054
00055
00056 ULXR_API_IMPL0 SubResourceBase::~SubResourceBase()
00057 {
00058 }
00059
00060
00061 ULXR_API_IMPL(CppString) SubResourceBase::getName() const
00062 {
00063 return name;
00064 }
00065
00066
00067 ULXR_API_IMPL(CppString) SubResourceBase::getDescription() const
00068 {
00069 return descr;
00070 }
00071
00072
00073 }
00074
00075
00077
00078
00079 ULXR_API_IMPL0 HtmlFormHandler::HtmlFormHandler(const CppString &in_resource)
00080 : masterResource(in_resource)
00081 {
00082 addSubResource(getCssName(), this, &HtmlFormHandler::handle_css_file, ULXR_PCHAR("Common style sheet"));
00083
00084 }
00085
00086
00087 ULXR_API_IMPL(CppString) HtmlFormHandler::getMasterResource() const
00088 {
00089 return masterResource;
00090 }
00091
00092
00093 ULXR_API_IMPL0 HtmlFormHandler::~HtmlFormHandler()
00094 {
00095 for (unsigned i = 0; i < subResources.size(); ++i)
00096 delete subResources[i];
00097
00098 subResources.clear();
00099 }
00100
00101
00102 ULXR_API_IMPL(bool) HtmlFormHandler::handler(HttpProtocol *prot,
00103 const CppString &method,
00104 const CppString &resource,
00105 const Cpp8BitString &conn_data)
00106 {
00107 ULXR_TRACE(ULXR_PCHAR("HtmlFormHandler::handler ")
00108 << method << ULXR_PCHAR(" ")
00109 << resource << std::endl);
00110
00111 CppString target;
00112 if (resourceSplit(method, resource, getMasterResource(), target))
00113 {
00114
00115 HtmlFormData formdata;
00116 formdata = extractFormElements(prot, method, target, conn_data);
00117
00118 for (unsigned i = 0; i < subResources.size(); ++i)
00119 {
00120 if (subResources[i]->getName() == target)
00121 {
00122 CppString mimetype = ULXR_PCHAR("text/html");
00123 std::string resp = encodeForHtml(subResources[i]->call(formdata, mimetype));
00124 prot->sendResponseHeader(200, ULXR_PCHAR("OK"), mimetype, resp.length());
00125 prot->writeRaw(resp.data(), resp.length());
00126 return true;
00127 }
00128 }
00129 return false;
00130 }
00131 else
00132 return false;
00133 }
00134
00135
00136 ULXR_API_IMPL(std::string) HtmlFormHandler::encodeForHtml(const CppString &data)
00137 {
00138 #ifdef ULXR_UNICODE
00139 return unicodeToUtf8(data);
00140 #else
00141 return data;
00142 #endif
00143 }
00144
00145
00146 ULXR_API_IMPL(CppString) HtmlFormHandler::encodeFromHtml(const std::string &data)
00147 {
00148 #ifdef ULXR_UNICODE
00149 return utf8ToUnicode(data);
00150 #else
00151 return data;
00152 #endif
00153 }
00154
00155
00156 ULXR_API_IMPL(bool) HtmlFormHandler::resourceSplit(const CppString &method,
00157 const CppString &resource,
00158 const CppString &rsc_start,
00159 CppString &target)
00160 {
00161 if (resource.substr(0, rsc_start.length()) == rsc_start)
00162 {
00163 target = resource.substr(rsc_start.length());
00164 if (method == ULXR_PCHAR("GET"))
00165 {
00166 std::size_t pos = target.find('?');
00167 if (pos != CppString::npos)
00168 target.erase(0, pos);
00169 }
00170
00171 return true;
00172 }
00173 else
00174 {
00175 target = ULXR_PCHAR("");
00176 return false;
00177 }
00178 }
00179
00180
00181 ULXR_API_IMPL(HtmlFormData) HtmlFormHandler::extractFormElements(HttpProtocol *prot,
00182 const CppString &method,
00183 const CppString &resource,
00184 const Cpp8BitString &conn_data)
00185 {
00186 ULXR_TRACE(ULXR_PCHAR("HtmlFormHandler::extractFormElements")) ;
00187 HtmlFormData formdata;
00188 std::string post_data = conn_data;
00189
00190 if (method == ULXR_PCHAR("POST"))
00191 {
00192 char conn_buffer [ULXR_RECV_BUFFER_SIZE];
00193 long conn_readed;
00194 bool done = false;
00195 while (!done && ((conn_readed = prot->readRaw(conn_buffer, sizeof(conn_buffer))) > 0) )
00196 {
00197 if (!prot->hasBytesToRead())
00198 done = true;
00199 post_data.append(conn_buffer, conn_readed);
00200 }
00201 }
00202 else
00203 {
00204 std::size_t pos = resource.find(ULXR_CHAR('?'));
00205 if (pos != CppString::npos)
00206 post_data = getLatin1(resource.substr(pos+1));
00207 }
00208
00209 while (post_data.length() != 0)
00210 {
00211 ULXR_TRACE(ULXR_PCHAR("formdata ") << ULXR_GET_STRING(post_data));
00212 std::size_t pos = 0;
00213 std::string element;
00214 if ( (pos = post_data.find(ULXR_CHAR('&'))) != CppString::npos)
00215 {
00216 element = post_data.substr(0, pos);
00217 post_data.erase(0, pos+1);
00218 }
00219 else
00220 {
00221 element = post_data.substr(0, pos);
00222 post_data = "";
00223 }
00224
00225 ULXR_TRACE(ULXR_PCHAR("element ") << ULXR_GET_STRING(element));
00226
00227 if ( (pos = element.find(ULXR_CHAR('='))) != CppString::npos)
00228 {
00229 std::string name = element.substr(0, pos);
00230 std::string value = element.substr(pos+1);
00231 formdata.addElement(encodeFromHtml(formDecode(name)), encodeFromHtml(formDecode(value)));
00232 }
00233 else
00234 {
00235
00236 }
00237 }
00238
00239 return formdata;
00240 }
00241
00242
00243 ULXR_API_IMPL(std::string) HtmlFormHandler::formDecode(std::string &value)
00244 {
00245 ULXR_TRACE(ULXR_PCHAR("formDecode 1 ") << ULXR_GET_STRING(value));
00246
00247 std::size_t pos = 0;
00248 while ((pos = value.find('+')) != std::string::npos)
00249 value.replace(pos, 1, 1, ' ');
00250
00251 ULXR_TRACE(ULXR_PCHAR("formDecode 2 ") << ULXR_GET_STRING(value));
00252
00253 pos = 0;
00254 while ((pos = value.find('%', pos)) != std::string::npos)
00255 {
00256 if (value.length() >= pos+3)
00257 {
00258 int c1 = ulxr_toupper(value[pos+1]) - '0';
00259 if (c1 > 9)
00260 c1 += '0' - 'A' + 0x0A;
00261
00262 int c2 = ulxr_toupper(value[pos+2]) - '0';
00263 if (c2 > 9)
00264 c2 += '0' - 'A' + 0x0A;
00265
00266 ULXR_TRACE(ULXR_PCHAR("formDecode 3 ")
00267 << (unsigned int) value[pos+1] << ULXR_PCHAR(" ")
00268 << (unsigned int) c1 << ULXR_PCHAR(" ")
00269 << (unsigned int) c2 );
00270
00271 if ( c1 >= 0 && c1 <= 0x0F
00272 && c2 >= 0 && c2 <= 0x0F)
00273 {
00274 unsigned char x = c1 << 4 | c2;
00275 if (x !=0)
00276 value.replace(pos, 3, 1, x);
00277 }
00278 pos++;
00279 }
00280 ULXR_TRACE(ULXR_PCHAR("formDecode 4 ") << ULXR_GET_STRING(value));
00281 }
00282 return value;
00283 }
00284
00285
00286 ULXR_API_IMPL(CppString) HtmlFormHandler::handle_subresource_list(const HtmlFormData &, CppString &mimetype)
00287 {
00288 mimetype = ULXR_PCHAR("text/html");
00289 CppString resp;
00290 resp += ULXR_PCHAR("<table border=\"3\">\n")
00291 ULXR_PCHAR("<tr><td>Resource</td>")
00292 ULXR_PCHAR("<td>Description</td></tr>");
00293
00294 for (unsigned i = 0; i < subResources.size(); ++i)
00295 {
00296 CppString s = applyTags(makeAnchor(subResources[i]->getName(), subResources[i]->getName()),
00297 ULXR_PCHAR("td"))
00298 + applyTags(subResources[i]->getDescription(), ULXR_PCHAR("td"));
00299 resp += applyTags(s, ULXR_PCHAR("tr"));
00300 }
00301
00302 return resp;
00303 }
00304
00305
00306 ULXR_API_IMPL(CppString) HtmlFormHandler::handle_css_file(const HtmlFormData &, CppString &mimetype)
00307 {
00308 mimetype = ULXR_PCHAR("text/css");
00309 return ULXR_PCHAR("// No css data set\n");
00310 }
00311
00312
00313 ULXR_API_IMPL(CppString) HtmlFormHandler::getCssName() const
00314 {
00315 return ULXR_PCHAR("ulxr.css");
00316 }
00317
00318
00319 ULXR_API_IMPL(CppString) HtmlFormHandler::getHeader(const CppString &title) const
00320 {
00321 return ULXR_PCHAR("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n")
00322 ULXR_PCHAR("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=")
00323 + getEncoding()
00324 + ULXR_PCHAR("\">\n<title>")
00325 + title
00326 + ULXR_PCHAR("</title>\n<link href=\"")
00327 + getCssName()
00328 + ULXR_PCHAR("\" rel=\"stylesheet\" type=\"text/css\"></head><body>\n");
00329 }
00330
00331
00332 ULXR_API_IMPL(CppString) HtmlFormHandler::getTail() const
00333 {
00334 return ULXR_PCHAR("\n</body></html>\n");
00335 }
00336
00337
00338 ULXR_API_IMPL(CppString) HtmlFormHandler::makeAnchor(const CppString &url, const CppString &descr)
00339 {
00340 return ULXR_PCHAR("<a href=\"") + url + ULXR_PCHAR("\">")
00341 + descr + ULXR_PCHAR("</a>");
00342 }
00343
00344
00345 ULXR_API_IMPL(CppString) HtmlFormHandler::makeIdent(const CppString &name, unsigned index)
00346 {
00347 return name + makeNumber(index);
00348 }
00349
00350
00351 ULXR_API_IMPL(CppString) HtmlFormHandler::openForm(const CppString &name, const CppString &method)
00352 {
00353 return ULXR_PCHAR("<form name=\"")
00354 + name
00355 + ULXR_PCHAR("\" accept-charset=\"")
00356 + getEncoding()
00357 + ULXR_PCHAR("\" method=\"")
00358 + method
00359 + ULXR_PCHAR("\">\n");
00360 }
00361
00362
00363 ULXR_API_IMPL(CppString) HtmlFormHandler::closeForm()
00364 {
00365 return ULXR_PCHAR("</form>\n");
00366 }
00367
00368
00369 ULXR_API_IMPL(CppString) HtmlFormHandler::applyTags(const CppString &data,
00370 const CppString &tag,
00371 bool newline)
00372 {
00373 std::size_t pos = 0;
00374 CppString end_tag = tag;
00375 if ( (pos = tag.find(ULXR_CHAR(' '))) != CppString::npos)
00376 end_tag = tag.substr(0, pos-1);
00377
00378 CppString resp = ULXR_PCHAR("<") + tag + ULXR_PCHAR(">")
00379 + data
00380 + ULXR_PCHAR("</") + end_tag + ULXR_PCHAR(">\n");
00381
00382 if (newline)
00383 resp += ULXR_PCHAR("\n");
00384
00385 return resp;
00386
00387 }
00388
00389
00390 ULXR_API_IMPL(CppString) HtmlFormHandler::makeLineBreak()
00391 {
00392 return ULXR_PCHAR("<br />");
00393 }
00394
00395
00396 ULXR_API_IMPL(CppString) HtmlFormHandler::makeCheckBox(const CppString &name,
00397 const CppString &value,
00398 bool checked)
00399 {
00400 CppString chkd;
00401 if (checked)
00402 chkd = ULXR_PCHAR(" checked=\"checked\"");
00403
00404 return ULXR_PCHAR("<input type=\"checkbox\" name=\"")
00405 + name
00406 + ULXR_PCHAR("\" value=\"")
00407 + value
00408 + ULXR_PCHAR("\"")
00409 + chkd
00410 + ULXR_PCHAR("></input>\n");
00411 }
00412
00413
00414 ULXR_API_IMPL(CppString) HtmlFormHandler::openSelect(const CppString &name,
00415 int size,
00416 bool multi)
00417 {
00418 CppString ret = ULXR_PCHAR("<select name=\"")
00419 + name
00420 + ULXR_PCHAR("\"");
00421 if (size >= 0)
00422 ret += ULXR_PCHAR(" size=\"")
00423 + makeNumber(size)
00424 + ULXR_PCHAR("\"");
00425
00426 if (multi)
00427 ret += ULXR_PCHAR(" multiple=\"multiple\"");
00428
00429 return ret + ULXR_PCHAR(">\n");
00430 }
00431
00432
00433 ULXR_API_IMPL(CppString) HtmlFormHandler::makeOption(const CppString &data,
00434 const CppString &value,
00435 bool selected)
00436 {
00437 CppString ret = ULXR_PCHAR("<option");
00438
00439 if (value.length() != 0)
00440 ret += ULXR_PCHAR(" value=\"")
00441 + value
00442 + ULXR_PCHAR("\"");
00443
00444 if (selected)
00445 ret += ULXR_PCHAR(" selected=\"selected\"");
00446
00447 return ret + ULXR_PCHAR(">") + data + ULXR_PCHAR("</option>\n");
00448 }
00449
00450
00451 ULXR_API_IMPL(CppString) HtmlFormHandler::closeSelect()
00452 {
00453 return ULXR_PCHAR("</select>\n");
00454 }
00455
00456
00457 ULXR_API_IMPL(CppString) HtmlFormHandler::makeTextArea(const CppString &name,
00458 const CppString &value,
00459 int cols, int rows)
00460 {
00461 CppString ret = ULXR_PCHAR("<textarea name=\"")
00462 + name
00463 + ULXR_PCHAR("\"");
00464
00465 if (cols >= 0)
00466 ret += ULXR_PCHAR(" cols=\"")
00467 + makeNumber(cols)
00468 + ULXR_PCHAR("\"");
00469
00470 if (rows >= 0)
00471 ret += ULXR_PCHAR(" rows=\"")
00472 + makeNumber(rows)
00473 + ULXR_PCHAR("\"");
00474
00475 return ret + ULXR_PCHAR(">") + value + ULXR_PCHAR("</textarea>");
00476 }
00477
00478
00479 ULXR_API_IMPL(CppString) HtmlFormHandler::makeTextField(const CppString &name,
00480 const CppString &value)
00481 {
00482 return ULXR_PCHAR("<input type=\"text\" name=\"")
00483 + name
00484 + ULXR_PCHAR("\" value=\"")
00485 + value
00486 + ULXR_PCHAR("\"></input>\n");
00487 }
00488
00489
00490 ULXR_API_IMPL(CppString) HtmlFormHandler::makeRadioButton(const CppString &name,
00491 const CppString &value,
00492 bool checked)
00493 {
00494 CppString chkd;
00495 if (checked)
00496 chkd = ULXR_PCHAR(" checked=\"checked\"");
00497
00498 return ULXR_PCHAR("<input type=\"radio\" name=\"")
00499 + name
00500 + ULXR_PCHAR("\" value=\"")
00501 + value
00502 + ULXR_PCHAR("\"")
00503 + chkd
00504 + ULXR_PCHAR("></input>\n");
00505 }
00506
00507
00508 ULXR_API_IMPL(CppString) HtmlFormHandler::makeSubmitButton(const CppString &name,
00509 const CppString &value)
00510 {
00511 return ULXR_PCHAR("<input type=\"submit\" name=\"")
00512 + name
00513 + ULXR_PCHAR("\" value=\"")
00514 + value
00515 + ULXR_PCHAR("\"></input>\n");
00516 }
00517
00518
00519 ULXR_API_IMPL(CppString) HtmlFormHandler::makeResetButton(const CppString &name,
00520 const CppString &value)
00521 {
00522 return ULXR_PCHAR("<input type=\"reset\" name=\"")
00523 + name
00524 + ULXR_PCHAR("\" value=\"")
00525 + value
00526 + ULXR_PCHAR("\"></input>\n");
00527 }
00528
00529
00530 ULXR_API_IMPL(CppString) HtmlFormHandler::makeText(const CppString &name)
00531 {
00532 return xmlEscape(name);
00533 }
00534
00535
00536 ULXR_API_IMPL(CppString) HtmlFormHandler::makeNumber(unsigned index)
00537 {
00538 #ifndef ULXR_UNICODE
00539 char cb[40];
00540 ulxr_sprintf(cb, "%d", index);
00541 #else
00542 wchar_t cb[40];
00543 # if defined(__BORLANDC__) || defined(_MSC_VER)
00544 ulxr_swprintf(cb, L"%d", index);
00545 # else
00546 ulxr_swprintf(cb, sizeof(cb), L"%d", index);
00547 # endif
00548 #endif
00549 return CppString(cb);
00550 }
00551
00552
00553 ULXR_API_IMPL(CppString) HtmlFormHandler::makeHexNumber(unsigned index)
00554 {
00555 #ifndef ULXR_UNICODE
00556 char cb[40];
00557 if (index <= 0x0F)
00558 ulxr_sprintf(cb, "0x0%x", index);
00559 else
00560 ulxr_sprintf(cb, "0x%x", index);
00561 #else
00562 wchar_t cb[40];
00563 # if defined(__BORLANDC__) || defined(_MSC_VER)
00564 if (index <= 0x0F)
00565 ulxr_swprintf(cb, L"0x0%x", index);
00566 else
00567 ulxr_swprintf(cb, L"0x%x", index);
00568 # else
00569 if (index <= 0x0F)
00570 ulxr_swprintf(cb, sizeof(cb), L"0x0%x", index);
00571 else
00572 ulxr_swprintf(cb, sizeof(cb), L"0x%x", index);
00573 # endif
00574 #endif
00575 return CppString(cb);
00576 }
00577
00578
00579 ULXR_API_IMPL(long) HtmlFormHandler::getLong(const CppString &num)
00580 {
00581 #ifndef ULXR_UNICODE
00582 return ulxr_atoi(num.c_str());
00583 #else
00584 std::string asc = getLatin1(num);
00585 return ulxr_atoi(asc.c_str());
00586 #endif
00587 }
00588
00589
00590 ULXR_API_IMPL(CppString) HtmlFormHandler::getEncoding() const
00591 {
00592 #ifdef ULXR_UNICODE
00593 return ULXR_PCHAR("UTF-8");
00594 #else
00595 return ULXR_PCHAR("ISO-8859-1");
00596 #endif
00597 }
00598
00599
00601
00602
00603 ULXR_API_IMPL(unsigned) HtmlFormData::size() const
00604 {
00605 return elements.size();
00606 }
00607
00608
00609 ULXR_API_IMPL(void) HtmlFormData::addElement( const CppString &name, const CppString &value)
00610 {
00611 elements[name].push_back(value);
00612 }
00613
00614
00615 ULXR_API_IMPL(std::vector<CppString>) HtmlFormData::getElement(const CppString &name) const
00616 {
00617 Elements::const_iterator it;
00618 if ((it = elements.find(name)) == elements.end())
00619 throw RuntimeException(ApplicationError, ulxr_i18n(ULXR_PCHAR("Index out out range for HtmlFormData::getElement() call")));
00620 else
00621 return (*it).second;
00622 }
00623
00624
00625 ULXR_API_IMPL(std::vector<CppString>) HtmlFormData::getElement(const CppString &base_name, unsigned index) const
00626 {
00627 return getElement(base_name + HtmlFormHandler::makeNumber(index));
00628 }
00629
00630
00631 ULXR_API_IMPL(bool) HtmlFormData::hasElement(const CppString &name) const
00632 {
00633 return elements.find(name) != elements.end();
00634 }
00635
00636
00637 ULXR_API_IMPL(bool) HtmlFormData::hasElement(const CppString &base_name, unsigned index) const
00638 {
00639 return hasElement(base_name + HtmlFormHandler::makeNumber(index));
00640 }
00641
00642
00643 }
00644