svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/WebAPI.cpp
Go to the documentation of this file.
00001 #include "WebAPI.h"
00002 
00003 #include <Poco/DateTime.h>
00004 #include <Poco/format.h>
00005 #include <Poco/Timezone.h>
00006 #include <Poco/DateTimeFormat.h>
00007 #include <Poco/DateTimeFormatter.h>
00008 #include <Poco/DateTimeParser.h>
00009 #include <Poco/NumberFormatter.h>
00010 #include <Poco/RegularExpression.h>
00011 #include <Poco/URI.h>
00012 
00013 #include "MainScene.h"
00014 #include "CaptureScene.h"
00015 #include "Utils.h"
00016 
00017 
00018 SwitchRequestHandlerFactory::SwitchRequestHandlerFactory(Renderer& renderer):
00019     _log(Poco::Logger::get("")), _renderer(renderer)
00020 {
00021     _log.information("create SwitchRequestHandlerFactory");
00022 }
00023 
00024 SwitchRequestHandlerFactory::‾SwitchRequestHandlerFactory() {
00025     _log.information("release SwitchRequestHandlerFactory");
00026 }
00027 
00028 HTTPRequestHandler* SwitchRequestHandlerFactory::createRequestHandler(const HTTPServerRequest& request) {
00029     return new SwitchRequestHandler(_renderer);
00030 }
00031 
00032 
00033 
00034 SwitchRequestHandler::SwitchRequestHandler(Renderer& renderer): BaseRequestHandler(),
00035     _renderer(renderer)
00036 {
00037     _log.debug("create SwitchRequestHandler");
00038 }
00039 
00040 SwitchRequestHandler::‾SwitchRequestHandler() {
00041     _log.debug("release SwitchRequestHandler");
00042 }
00043 
00044 
00045 void SwitchRequestHandler::doRequest() {
00046     //_log.information(Poco::format("request from %s", request().clientAddress().toString()));
00047     string encoded;
00048     Poco::URI::encode(request().getURI(), "/", encoded);
00049     Poco::URI uri(encoded);
00050     //_log.information(Poco::format("webAPI access uri [%s]", uri.getPath()));
00051     //vector<string> params;
00052     //svvitch::split(uri.getPath().substr(1), '?', params, 2);
00053     vector<string> urls;
00054     svvitch::split(uri.getPath().substr(1), '/', urls, 3);
00055     // for (vector<string>::iterator it = urls.begin(); it != urls.end(); it++) {
00056     //  _log.information(Poco::format("url %s", string(*it)));
00057     // }
00058     if (urls.size() > 1) {
00059         string displayID = urls[0];
00060         if        (urls[1] == "switch") {
00061             switchContent();
00062         } else if (urls[1] == "update") {
00063             updateWorkspace();
00064         } else if (urls[1] == "set") {
00065             if (urls.size() == 3) set(urls[2]);
00066         } else if (urls[1] == "get") {
00067             if (urls.size() == 3) get(urls[2]);
00068         } else if (urls[1] == "files") {
00069             files();
00070         } else if (urls[1] == "download") {
00071             download();
00072         } else if (urls[1] == "upload") {
00073             upload();
00074         } else if (urls[1] == "clear-stock") {
00075             clearStock();
00076         } else if (urls[1] == "copy") {
00077             copy();
00078 
00079         //} else if (urls[1] == "reboot") {
00080         //  svvitch::rebootWindows();
00081         //  sendResponse(HTTPResponse::HTTP_OK, "reboot now");
00082 
00083         } else if (urls[1] == "version") {
00084             version();
00085         }
00086 
00087     } else {
00088         _log.information(Poco::format("webAPI access uri [%s]", uri.getPath()));
00089         Path src("docs", uri.getPath().substr(1));
00090         File f(src);
00091         if (f.exists()) {
00092             if (f.isDirectory()) src = src.makeDirectory().append("index.html");
00093             sendFile(src);
00094         }
00095     }
00096 
00097     if (!response().sent()) {
00098         string s = Poco::format("<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL %s was not found on this server.</p><hr><address>switch %s</address></body></html>", request().getURI(), svvitch::version());
00099         sendResponse(HTTPResponse::HTTP_NOT_FOUND, s);
00100     }
00101 }
00102 
00103 void SwitchRequestHandler::switchContent() {
00104     try {
00105         MainScenePtr scene = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00106         if (scene) {
00107             map<string, string> params;
00108             params["switched"] = scene->switchContent()?"true":"false";
00109             sendJSONP(form().get("callback", ""), params);
00110         } else {
00111             sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, "scene not found");
00112         }
00113     } catch (...) {
00114     }
00115 }
00116 
00117 void SwitchRequestHandler::updateWorkspace() {
00118 
00119     try {
00120         MainScenePtr main = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00121         if (main) {
00122             bool result = main->flushStock() && main->updateWorkspace();
00123             map<string, string> params;
00124             params["update"] = result?"true":"false";
00125             sendJSONP(form().get("callback", ""), params);
00126         } else {
00127             sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, "scene not found");
00128         }
00129     } catch (...) {
00130     }
00131 }
00132 
00133 void SwitchRequestHandler::set(const string& command) {
00134     try {
00135         string message;
00136         MainScenePtr scene = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00137         if (scene) {
00138             if (command == "playlist") {
00139                 string playlistID = form().get("pl", "");
00140                 int playlistIndex = 0;
00141                 if (form().has("i")) Poco::NumberParser::tryParse(form().get("i"), playlistIndex);
00142                 _log.information(Poco::format("set playlist: [%s]-%d", playlistID, playlistIndex));
00143                 _log.information(Poco::format("playlist: %s", playlistID));
00144                 bool result = scene->stackPrepareContent(playlistID, playlistIndex);
00145                 map<string, string> params;
00146                 params["playlist"] = result?"true":"false";
00147                 if (result) {
00148                     //Workspace& workspace = scene->getWorkspace();
00149                     //PlayListPtr playlist = workspace.getPlaylist(playlistID);
00150                     //if (playlist) params["name"] = Poco::format("¥"%s¥"", playlist->name());
00151                     //params["playlist"] = Poco::format("¥"%s¥"", playlistID);
00152                     //params["index"] = Poco::format("%d", playlistIndex);
00153                 }
00154                 sendJSONP(form().get("callback", ""), params);
00155                 return;
00156             } else if (command == "text") {
00157                 string playlistID = form().get("pl", "");
00158                 string text = form().get("t", "");
00159                 map<string, string> params;
00160                 params["text"] = scene->setPlaylistText(playlistID, text)?"true":"false";
00161                 sendJSONP(form().get("callback", ""), params);
00162                 return;
00163 
00164             } else if (command == "brightness") {
00165                 int i = 0;
00166                 Poco::NumberParser::tryParse(form().get("v"), i);
00167                 scene->setBrightness(i);
00168                 map<string, string> params;
00169                 params["brightness"] = Poco::format("%d", i);
00170                 sendJSONP(form().get("callback", ""), params);
00171                 return;
00172 
00173             } else if (command == "action") {
00174                 string action = form().get("v");
00175                 scene->setAction(action);
00176                 map<string, string> params;
00177                 params["action"] = action;
00178                 sendJSONP(form().get("callback", ""), params);
00179                 return;
00180 
00181             } else if (command == "transition") {
00182                 string transition = form().get("v");
00183                 scene->setTransition(transition);
00184                 map<string, string> params;
00185                 params["transition"] = transition;
00186                 sendJSONP(form().get("callback", ""), params);
00187                 return;
00188 
00189             } else if (command == "status") {
00190                 bool result = false;
00191                 string name = form().get("n");
00192                 string value = form().get("v");
00193                 ScenePtr targetScene = scene;
00194                 string s = form().get("s", "");
00195                 if (!s.empty()) {
00196                     targetScene = _renderer.getScene(s);
00197                 }
00198                 if (!name.empty()) {
00199                     if (value.empty()) {
00200                         targetScene->removeStatus(name);
00201                     } else {
00202                         targetScene->setStatus(name, value);
00203                     }
00204                     result = true;
00205                 }
00206                 map<string, string> params;
00207                 params["status"] = result?"true":"false";
00208                 sendJSONP(form().get("callback", ""), params);
00209                 return;
00210 
00211             } else {
00212                 message = "property not found";
00213             }
00214         } else {
00215             message = "scene not found";
00216         }
00217         sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, message);
00218     } catch (...) {
00219         sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, Poco::format("failed set '%s'", command));
00220     }
00221 }
00222 
00223 void SwitchRequestHandler::get(const string& command) {
00224     try {
00225         string message;
00226         MainScenePtr scene = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00227         if (scene) {
00228             if (command == "snapshot") {
00229                 LPDIRECT3DTEXTURE9 texture = _renderer.getCaptureTexture();
00230                 if (texture) {
00231                     // capture-lock
00232                     LPD3DXBUFFER buf = NULL;
00233                     if SUCCEEDED(D3DXSaveTextureToFileInMemory(&buf, D3DXIFF_PNG, texture, NULL)) {
00234                         try {
00235                             response().setContentType("image/png");
00236                             response().sendBuffer(buf->GetBufferPointer(), buf->GetBufferSize());
00237                         } catch (Poco::Exception& ex) {
00238                         }
00239                         SAFE_RELEASE(buf);
00240                     } else {
00241                         _log.warning("failed snapshot image");
00242                     }
00243                 }
00244                 return;
00245 
00246             } else if (command == "camera") {
00247                 CaptureScenePtr capture = dynamic_cast<CaptureScenePtr>(_renderer.getScene("capture"));
00248                 if (capture) {
00249                     LPDIRECT3DTEXTURE9 texture = capture->getCameraImage();
00250                     if (texture) {
00251                         // capture-lock
00252                         LPD3DXBUFFER buf = NULL;
00253                         if SUCCEEDED(D3DXSaveTextureToFileInMemory(&buf, D3DXIFF_PNG, texture, NULL)) {
00254                             try {
00255                                 response().setContentType("image/png");
00256                                 response().sendBuffer(buf->GetBufferPointer(), buf->GetBufferSize());
00257                             } catch (Poco::Exception& ex) {
00258                             }
00259                             SAFE_RELEASE(buf);
00260                         } else {
00261                             _log.warning("failed snapshot image");
00262                         }
00263                     }
00264                 }
00265                 return;
00266 
00267             } else if (command == "fonts") {
00268                 vector<string> fonts;
00269                 scene->renderer().getPrivateFontFamilies(fonts);
00270                 //vector<string> arrays;
00271                 //for (vector<string>::iterator it = fonts.begin(); it != fonts.end(); it++) {
00272                 //}
00273 
00274                 map<string, string> params;
00275                 params["fonts"] = svvitch::formatJSONArray(fonts);
00276                 sendJSONP(form().get("callback", ""), params);
00277                 return;
00278 
00279             } else if (command == "text") {
00280                 string playlistID = form().get("pl", "");
00281                 string text = scene->getPlaylistText(playlistID);
00282                 Poco::RegularExpression re("¥¥r|¥¥n");
00283                 re.subst(text, "¥¥n", Poco::RegularExpression::RE_GLOBAL);
00284                 map<string, string> params;
00285                 params["text"] = "¥"" + text + "¥"";
00286                 sendJSONP(form().get("callback", ""), params);
00287                 return;
00288 
00289             } else if (command == "display-status") {
00290                 map<string, string> status = scene->getStatus();
00291                 map<string, string>::const_iterator it = status.find("remote-copy");
00292                 map<string, string> params;
00293                 if (it != status.end()) {
00294                     params[it->first] = Poco::format("¥"%s¥"", it->second);
00295                 }
00296                 sendJSONP(form().get("callback", ""), params);
00297                 return;
00298 
00299             } else if (command == "status") {
00300                 ScenePtr targetScene = dynamic_cast<MainScenePtr>(scene);
00301                 string s = form().get("s", "");
00302                 string name = form().get("n", "");
00303                 if (!s.empty()) {
00304                     targetScene = _renderer.getScene(s);
00305                     if (!targetScene) {
00306                         sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, "scene not found");
00307                         return;
00308                     }
00309                 }
00310                 map<string, string> status = targetScene->getStatus();
00311                 if (!name.empty()) {
00312                     map<string, string>::const_iterator it = status.find(name);
00313                     string value;
00314                     if (it != status.end()) value = it->second;
00315                     sendResponse(HTTPResponse::HTTP_OK, value);
00316                 } else {
00317                     map<string, string> params;
00318                     for (map<string, string>::const_iterator it = status.begin(); it != status.end(); it++) {
00319                         params[it->first] = svvitch::formatJSON(it->second);
00320                     }
00321                     sendJSONP(form().get("callback", ""), params);
00322                 }
00323                 return;
00324 
00325             } else {
00326                 message = "property not found";
00327             }
00328         } else {
00329             message = "scene not found";
00330         }
00331         sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, message);
00332     } catch (...) {
00333         sendResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, Poco::format("failed get '%s'", command));
00334     }
00335 }
00336 
00337 void SwitchRequestHandler::files() {
00338     string path = form().get("path", "");
00339     //_log.information(Poco::format("files: %s", path));
00340     if (path.at(0) == '/' || path.at(0) == '¥¥') path = path.substr(1);
00341     Path dir(config().dataRoot, Path(path).toString());
00342     //Path dir = config().dataRoot;
00343     try {
00344         //if (!path.empty()) dir = dir.append(path);
00345         map<string, string> result;
00346         result["count"] = Poco::format("%d", svvitch::fileCount(dir));
00347         result["path"] = "¥"" + path + "¥"";
00348         result["files"] = fileToJSON(dir);
00349         sendJSONP(form().get("callback", ""), result);
00350     } catch (Poco::FileException& ex) {
00351         _log.warning(ex.displayText());
00352         sendResponse(HTTPResponse::HTTP_NOT_FOUND, ex.displayText());
00353     } catch (Poco::PathSyntaxException& ex) {
00354         _log.warning(ex.displayText());
00355         sendResponse(HTTPResponse::HTTP_NOT_FOUND, ex.displayText());
00356     }
00357 }
00358 
00359 string SwitchRequestHandler::fileToJSON(const Path path) {
00360     string name = path.getFileName();
00361     if (name.length() > 1 && (name.at(0) == '.' || name.at(0) == '$')) return "";
00362 
00363     if (path.isDirectory()) {
00364         vector<string> files;
00365         vector<File> list;
00366         File(path).list(list);
00367         for (vector<File>::iterator it = list.begin(); it != list.end(); it++) {
00368 //          string json = fileToJSON(*it);
00369 //          files.push_back(json);
00370             File f = *it;
00371             string subName = Path(f.path()).getFileName();
00372             if (subName.length() > 1 && subName.at(0) != '.' && subName.at(0) != '$') {
00373                 if (f.isDirectory()) {
00374                     files.push_back(subName + "/");
00375                 } else {
00376                     files.push_back(subName);
00377                 }
00378             }
00379         }
00380         return svvitch::formatJSONArray(files);
00381     }
00382     map<string, string> params;
00383     params["name"] = svvitch::formatJSON(name);
00384     File f(path);
00385     Poco::DateTime modified(f.getLastModified());
00386     modified.makeLocal(Poco::Timezone::tzd());
00387     params["modified"] = "¥"" + Poco::DateTimeFormatter::format(modified, Poco::DateTimeFormat::SORTABLE_FORMAT) + "¥"";
00388     params["size"] = Poco::format("%Lu", f.getSize());
00389     //if (f.getSize() < 10485760) {
00390     //  // 10MB以下ならmd5を計算
00391     //  params["md5"] = "¥"" + svvitch::md5(path) + "¥"";
00392     //}
00393     return svvitch::formatJSON(params);
00394 }
00395 
00396 void SwitchRequestHandler::download() {
00397     try {
00398         string path = form().get("path", "");
00399         if (path.at(0) == '/' || path.at(0) == '¥¥') path = path.substr(1);
00400         Path src(config().dataRoot, Path(path).toString());
00401         _log.information(Poco::format("download: %s", src.toString()));
00402         sendFile(src);
00403     } catch (Poco::PathSyntaxException& ex) {
00404         _log.warning(ex.displayText());
00405         sendResponse(HTTPResponse::HTTP_NOT_FOUND, ex.displayText());
00406     }
00407 }
00408 
00409 void SwitchRequestHandler::upload() {
00410     string path = form().get("path", "");
00411     string modified = form().get("modified", "");
00412     if (!path.empty()) {
00413         form(); // フォームをパースしuploadsフォルダにアップロードファイルを取り込む
00414         if (path.at(0) == '/' || path.at(0) == '¥¥') path = path.substr(1);
00415         boolean result = true;
00416         MainScenePtr main = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00417         if (main) {
00418             vector<File> list;
00419             File("uploads").list(list);
00420             for (vector<File>::iterator it = list.begin(); it != list.end(); it++) {
00421                 File src = *it;
00422                 if (!modified.empty()) {
00423                     int tz = 0;
00424                     Poco::DateTime time;
00425                     Poco::DateTimeParser::parse(Poco::DateTimeFormat::SORTABLE_FORMAT, modified, time, tz);
00426                     src.setLastModified(time.timestamp());
00427                 }
00428                 result &= main->addStock(path, src);
00429             }
00430         }
00431         map<string, string> params;
00432         params["upload"] = result?"true":"false";
00433         sendJSONP(form().get("callback", ""), params);
00434     } else {
00435         sendResponse(HTTPResponse::HTTP_NOT_FOUND, "path not found");
00436     }
00437 }
00438 
00439 void SwitchRequestHandler::clearStock() {
00440     MainScenePtr main = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00441     if (main) {
00442         main->clearStock();
00443 
00444         map<string, string> params;
00445         params["clear"] = "true";
00446         sendJSONP(form().get("callback", ""), params);
00447     }
00448 }
00449 
00450 
00451 void SwitchRequestHandler::copy() {
00452     string remote = form().get("remote", "");
00453     if (!remote.empty()) {
00454         MainScenePtr scene = dynamic_cast<MainScenePtr>(_renderer.getScene("main"));
00455         if (scene) {
00456             scene->activeCopyRemote(remote);
00457 
00458             map<string, string> params;
00459             params["copy"] = "true";
00460             sendJSONP(form().get("callback", ""), params);
00461         }
00462     }
00463 }
00464 
00465 void SwitchRequestHandler::version() {
00466     map<string, string> params;
00467     params["version"] = svvitch::version();
00468     sendJSONP(form().get("callback", ""), params);
00469 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines