Mercurial > hg > orthanc
changeset 1065:921532f67770
Lua scripts can invoke system commands, with CallSystem()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 25 Jul 2014 16:59:33 +0200 |
parents | cd20e2568fc2 |
children | bb82e5e818e9 |
files | CMakeLists.txt Core/Uuid.h NEWS OrthancServer/Scheduler/CallSystemCommand.cpp OrthancServer/Scheduler/CallSystemCommand.h OrthancServer/ServerContext.cpp Resources/Samples/Lua/CallDcm2Xml.lua Resources/Toolbox.lua |
diffstat | 8 files changed, 210 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Fri Jul 25 16:13:36 2014 +0200 +++ b/CMakeLists.txt Fri Jul 25 16:59:33 2014 +0200 @@ -173,6 +173,7 @@ OrthancServer/Scheduler/ServerScheduler.cpp OrthancServer/Scheduler/StorePeerCommand.cpp OrthancServer/Scheduler/StoreScuCommand.cpp + OrthancServer/Scheduler/CallSystemCommand.cpp )
--- a/Core/Uuid.h Fri Jul 25 16:13:36 2014 +0200 +++ b/Core/Uuid.h Fri Jul 25 16:59:33 2014 +0200 @@ -43,6 +43,8 @@ * http://stackoverflow.com/questions/246930/is-there-any-difference-between-a-guid-and-a-uuid **/ +#include "Toolbox.h" + namespace Orthanc { namespace Toolbox @@ -69,6 +71,16 @@ { return path_; } + + void Write(const std::string& content) + { + Toolbox::WriteFile(content, path_); + } + + void Read(std::string& content) const + { + Toolbox::ReadFile(content, path_); + } }; } }
--- a/NEWS Fri Jul 25 16:13:36 2014 +0200 +++ b/NEWS Fri Jul 25 16:59:33 2014 +0200 @@ -8,7 +8,12 @@ * Access patient module at the study level to cope with PatientID collisions * On-the-fly conversion of JSON to XML according to the HTTP Accept header * C-Echo SCU in the REST API + +Lua scripts +----------- + * Lua scripts can do HTTP requests, and thus can call Web services +* Lua scripts can invoke system commands, with CallSystem() Plugins -------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Scheduler/CallSystemCommand.cpp Fri Jul 25 16:59:33 2014 +0200 @@ -0,0 +1,72 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "CallSystemCommand.h" + +#include <glog/logging.h> +#include "../../Core/Toolbox.h" +#include "../../Core/Uuid.h" + +namespace Orthanc +{ + CallSystemCommand::CallSystemCommand(ServerContext& context, + const std::string& command, + const std::vector<std::string>& arguments) : + context_(context), + command_(command), + arguments_(arguments) + { + } + + bool CallSystemCommand::Apply(ListOfStrings& outputs, + const ListOfStrings& inputs) + { + for (ListOfStrings::const_iterator + it = inputs.begin(); it != inputs.end(); ++it) + { + LOG(INFO) << "Calling system command " << command_ << " on instance " << *it; + + std::string dicom; + context_.ReadFile(dicom, *it, FileContentType_Dicom); + + Toolbox::TemporaryFile tmp; + tmp.Write(dicom); + + std::vector<std::string> args = arguments_; + args.push_back(tmp.GetPath()); + + Toolbox::ExecuteSystemCommand(command_, args); + } + + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/Scheduler/CallSystemCommand.h Fri Jul 25 16:59:33 2014 +0200 @@ -0,0 +1,55 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, + * Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IServerCommand.h" +#include "../ServerContext.h" + +namespace Orthanc +{ + class CallSystemCommand : public IServerCommand + { + private: + ServerContext& context_; + std::string command_; + std::vector<std::string> arguments_; + + public: + CallSystemCommand(ServerContext& context, + const std::string& command, + const std::vector<std::string>& arguments); + + virtual bool Apply(ListOfStrings& outputs, + const ListOfStrings& inputs); + }; +}
--- a/OrthancServer/ServerContext.cpp Fri Jul 25 16:13:36 2014 +0200 +++ b/OrthancServer/ServerContext.cpp Fri Jul 25 16:59:33 2014 +0200 @@ -44,6 +44,7 @@ #include <dcmtk/dcmdata/dcfilefo.h> +#include "Scheduler/CallSystemCommand.h" #include "Scheduler/DeleteInstanceCommand.h" #include "Scheduler/ModifyInstanceCommand.h" #include "Scheduler/StoreScuCommand.h" @@ -160,6 +161,47 @@ return command.release(); } + if (operation == "call-system") + { + LOG(INFO) << "Lua script to call system command on " << parameters["Instance"].asString(); + + const Json::Value& argsIn = parameters["Arguments"]; + if (argsIn.type() != Json::arrayValue) + { + throw OrthancException(ErrorCode_BadParameterType); + } + + std::vector<std::string> args; + args.reserve(argsIn.size()); + for (Json::Value::ArrayIndex i = 0; i < argsIn.size(); ++i) + { + // http://jsoncpp.sourceforge.net/namespace_json.html#7d654b75c16a57007925868e38212b4e + switch (argsIn[i].type()) + { + case Json::stringValue: + args.push_back(argsIn[i].asString()); + break; + + case Json::intValue: + args.push_back(boost::lexical_cast<std::string>(argsIn[i].asInt())); + break; + + case Json::uintValue: + args.push_back(boost::lexical_cast<std::string>(argsIn[i].asUInt())); + break; + + case Json::realValue: + args.push_back(boost::lexical_cast<std::string>(argsIn[i].asFloat())); + break; + + default: + throw OrthancException(ErrorCode_BadParameterType); + } + } + + return new CallSystemCommand(context, parameters["Command"].asString(), args); + } + throw OrthancException(ErrorCode_ParameterOutOfRange); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Samples/Lua/CallDcm2Xml.lua Fri Jul 25 16:59:33 2014 +0200 @@ -0,0 +1,8 @@ +function OnStoredInstance(instanceId, tags, metadata) + -- Assume Latin1 encoding in dcm2xml + local args = {} + table.insert(args, '+Ca') + table.insert(args, 'latin-1') + + Delete(CallSystem(instanceId, 'dcm2xml', args)) +end
--- a/Resources/Toolbox.lua Fri Jul 25 16:13:36 2014 +0200 +++ b/Resources/Toolbox.lua Fri Jul 25 16:59:33 2014 +0200 @@ -93,5 +93,20 @@ end +function CallSystem(instanceId, command, args) + if instanceId == nil then + error('Cannot modify a nonexistent instance') + end + + table.insert(_job, { + Operation = 'call-system', + Instance = instanceId, + Command = command, + Arguments = args + }) + + return instanceId +end + print('Lua toolbox installed')