diff --git a/uppsrc/CtrlLib/FileSel.cpp b/uppsrc/CtrlLib/FileSel.cpp index e5dec9841..bfbe3e258 100644 --- a/uppsrc/CtrlLib/FileSel.cpp +++ b/uppsrc/CtrlLib/FileSel.cpp @@ -1223,7 +1223,7 @@ bool FileSel::Execute(int _mode) { dir.Add(GetHomeDirectory()); #ifdef PLATFORM_POSIX Array root = filesystem->Find("/media/*"); - dir.Add(GetHomeDirFile("Desktop")); + dir.Add(GetDesktopFolder()); dir.Add("/"); for(i = 0; i < root.GetCount(); i++) { String ugly = root[i].filename; diff --git a/uppsrc/XmlRpc/Client.cpp b/uppsrc/XmlRpc/Client.cpp index e0a53143a..23df157cf 100644 --- a/uppsrc/XmlRpc/Client.cpp +++ b/uppsrc/XmlRpc/Client.cpp @@ -2,13 +2,36 @@ #define LLOG(x) // LOG(x) -XmlRpcCall::XmlRpcCall(const char *url) +XmlRpcCall& XmlRpcCall::URL(const char *url) { shorted = true; if(url && *url) { server.URL(url); shorted = false; } + shouldExecute = true; + return *this; +} + +XmlRpcCall& XmlRpcCall::Method(const char *name) +{ + shouldExecute = true; + method = name; + data.Reset(); + error.Clear(); + return *this; +} + +XmlRpcCall::XmlRpcCall(const char *url) +{ + URL(url); + server.ContentType("text/xml"); + timeout = 30000; +} + +XmlRpcCall::XmlRpcCall() +{ + URL(NULL); server.ContentType("text/xml"); timeout = 30000; } @@ -17,6 +40,9 @@ String XmlRpcExecute(const String& request, const char *group, const char *peera Value XmlRpcCall::Execute() { + if(!shouldExecute) + return Value(); + shouldExecute = false; String request = XmlHeader(); request << XmlTag("methodCall")(XmlTag("methodName")(method) + FormatXmlRpcParams(data.out)); String response; @@ -26,8 +52,11 @@ Value XmlRpcCall::Execute() response = server.Post(request).TimeoutMsecs(timeout).ExecuteRedirect(); LLOG("response: " << response); if(IsNull(response)) { - LLOG("ERROR: " << server.GetError()); - return ErrorValue("Http request failed: " + server.GetError()); + faultCode = XMLRPC_CLIENT_HTTP_ERROR; + faultString = server.GetError(); + error = "Http request failed: " + faultString; + LLOG(error); + return ErrorValue(error); } XmlParser p(response); try { @@ -37,11 +66,12 @@ Value XmlRpcCall::Execute() Value m = ParseXmlRpcValue(p); if(IsValueMap(m)) { ValueMap mm = m; - String s; - s << "Failed '" << mm["faultString"] << "' (" << mm["faultCode"] << ')'; - error = s; + faultString = mm["faultString"]; + faultCode = mm["faultCode"]; + error.Clear(); + error << "Failed '" << faultString << "' (" << faultCode << ')'; LLOG(s); - return ErrorValue(s); + return ErrorValue(error); } } else { @@ -52,18 +82,19 @@ Value XmlRpcCall::Execute() } catch(XmlError e) { String s; - s << "XmlError " << e << ": " << p.GetPtr(); - LLOG(s); - error = s; - return ErrorValue(s); + faultString = e; + faultCode = XMLRPC_CLIENT_XML_ERROR; + error.Clear(); + error << "XML Error: " << faultString; + LLOG(error << ": " << p.GetPtr()); + return ErrorValue(error); } return data.in.GetCount() ? data.in[0] : Null; } -Value XmlRpcCall::Ret() +void XmlRpcCall::ClearError() { - Value v; - if(*this >> v) - return v; - return Value(); + faultCode = 0; + faultString.Clear(); + error.Clear(); } diff --git a/uppsrc/XmlRpc/Server.cpp b/uppsrc/XmlRpc/Server.cpp index 70e2c9ad9..f56df54d2 100644 --- a/uppsrc/XmlRpc/Server.cpp +++ b/uppsrc/XmlRpc/Server.cpp @@ -14,6 +14,19 @@ void Register(const char *name, void (*method)(XmlRpcData&), const char *group) XmlRpcMap(group).Add(name, method); } +struct XmlRpcError { + int code; + String text; +}; + +void ThrowXmlRpcError(int code, const char *s) +{ + XmlRpcError e; + e.code = code; + e.text = s; + throw e; +} + String XmlRpcExecute(const String& request, const char *group, const char *peeraddr) { VectorMap< String, void (*)(XmlRpcData&) >& xmlrpcmap = XmlRpcMap(group); @@ -33,13 +46,13 @@ String XmlRpcExecute(const String& request, const char *group, const char *peera data.in = ParseXmlRpcParams(p); int q = xmlrpcmap.Find(methodname); if(q < 0) - return FormatXmlRpcError(4, methodname + " method is unknown"); + return FormatXmlRpcError(XMLRPC_UNKNOWN_METHOD_ERROR, "\'" + methodname + "\' method is unknown"); else { (*xmlrpcmap[q])(data); if(IsValueArray(data.out)) { if(IsError(data.out[0])) { LLOG("ProcessingError"); - return FormatXmlRpcError(3, methodname + " Processing error: " + GetErrorText(data.out[0])); + return FormatXmlRpcError(XMLRPC_SERVER_PROCESSING_ERROR, "Processing error: " + GetErrorText(data.out[0])); } r << FormatXmlRpcParams(data.out); } @@ -48,13 +61,17 @@ String XmlRpcExecute(const String& request, const char *group, const char *peera p.PassEnd(); return r; } + catch(XmlRpcError e) { + LLOG("Client error: " << e.text); + return FormatXmlRpcError(e.code, e.text); + } catch(XmlError e) { LLOG("XmlError " << e << ": " << p.GetPtr()); - return FormatXmlRpcError(1, methodname + " XML Error: " + e); + return FormatXmlRpcError(XMLRPC_SERVER_XML_ERROR, "XML Error: " + e); } catch(ValueTypeMismatch) { LLOG("ValueTypeMismatch at parameter " << data.ii); - return FormatXmlRpcError(2, methodname + " Value type mismatch at parameter " + AsString(data.ii)); + return FormatXmlRpcError(XMLRPC_SERVER_PARAM_ERROR, "Parameter mismatch at parameter " + AsString(data.ii)); } return Null; } diff --git a/uppsrc/XmlRpc/XmlRpc.h b/uppsrc/XmlRpc/XmlRpc.h index f6f68fd80..13ef0cde0 100644 --- a/uppsrc/XmlRpc/XmlRpc.h +++ b/uppsrc/XmlRpc/XmlRpc.h @@ -5,6 +5,16 @@ using namespace Upp; +enum { + XMLRPC_CLIENT_HTTP_ERROR = -1000000, + XMLRPC_CLIENT_XML_ERROR, + XMLRPC_CLIENT_RETTYPE_ERROR, + XMLRPC_SERVER_PARAM_ERROR, + XMLRPC_SERVER_XML_ERROR, + XMLRPC_SERVER_PROCESSING_ERROR, + XMLRPC_UNKNOWN_METHOD_ERROR, +}; + struct ValueTypeMismatch {}; void ValueCheck(bool b); @@ -123,16 +133,21 @@ void xmlrpc##x(XmlRpcData& rpc); \ INITBLOCK { Register(#x, xmlrpc##x, group); } \ void xmlrpc##x(XmlRpcData& rpc) +void ThrowXmlRpcError(int code, const char *s); + class XmlRpcCall { bool shorted; HttpClient server; XmlRpcData data; String method; String error; + String faultString; + int faultCode; int timeout; + bool shouldExecute; public: - XmlRpcCall& Method(const char *name) { method = name; data.Reset(); error.Clear(); return *this; } + XmlRpcCall& Method(const char *name); template XmlRpcCall& operator<<(const T& x) { data << x; return *this; } @@ -140,10 +155,8 @@ public: Value Execute(); template - bool operator>>(T& x) { if(IsError(Execute())) return false; try { data >> x; } catch(ValueTypeMismatch) { return false; } return true; } - - Value Ret(); - + bool operator>>(T& x) { if(IsError(Execute())) return false; + try { data >> x; } catch(ValueTypeMismatch) { return false; } return true; } XmlRpcCall& operator()(const char *method) { Method(method); return *this; } #define E__Templ(I) class COMBINE(T, I) @@ -164,10 +177,16 @@ public: #undef E__Param #undef E__Body + String GetFaultString() const { return faultString; } + int GetFaultCode() const { return faultCode; } String GetError() const { return error; } + void ClearError(); + XmlRpcCall& TimeOut(int msec) { timeout = msec; } + XmlRpcCall& URL(const char *url); XmlRpcCall(const char *url); + XmlRpcCall(); }; #endif