/** * parse a server response. it parses a xml response sent by a server and returns the value or * error it contains. * @param s the received data * @return the value described by data * @see ParseMethodCall() */ Value XmlRpcParser::ParseMethodResponse(String s){ XmlParser p(s); Value v; String error; try{ while(!p.Tag("methodResponse")) p.Skip(); if(p.Tag("fault")) { ValueMap vm(Parse(p)); error << vm["faultString"] <<" ("<<vm["faultCode"]<<")"; p.PassEnd(); //fault p.PassEnd(); //methodResponse return ErrorValue(error); } p.PassTag("params"); p.PassTag("param"); v=Parse(p); p.PassEnd(); //param p.PassEnd(); //params p.PassEnd(); //methodResponse } catch(Exc e) { return ErrorValue(NFormat("EXCEPTION: %s",e)); } return Value(v); }
Value StrDblValue(const char *s) { if(s && *s) { const char *p; double q = ScanDouble(s, &p); if(!IsNull(q)) while(*p) { if((byte)*p > ' ') return ErrorValue(t_("Invalid number !")); p++; } return IsNull(q) ? ErrorValue(t_("Invalid number !")) : Value(q); } return (double)Null; }
Value StrIntValue(const char *s) { if(s && *s) { const char *p; int64 q = ScanInt64(s, &p); if(!IsNull(q)) while(*p) { if((byte)*p > ' ') return ErrorValue(t_("Invalid number !")); p++; } return IsNull(q) ? ErrorValue(t_("Invalid number !")) : Value(q); } return (int)Null; }
Value ConvertDate::Scan(const Value& text) const { Value v = UPP::Scan(DATE_V, text, defaultval); if(IsError(v)) return v; if(IsNull(v)) return notnull ? NotNullError() : v; Date m = v; if(m >= minval && m <= maxval) return v; return ErrorValue(t_("Date must be between ") + UPP::Format(minval) + t_("range\v and ") + UPP::Format(maxval) + "."); }
Value SqlStatement::Fetch(Sql& cursor) const { ASSERT(text.GetCount()); if(!Execute(cursor)) return ErrorValue(SqlExc(cursor.GetSession())); if(!cursor.Fetch()) return Null; return cursor[0]; }
const Value Slot::change_link(unsigned char operation, const Value &val) { if (val.is_string()) { // update a link (create/destroy) Object * target = root_->object_at(val.str()); if (!target) return ErrorValue(NOT_FOUND_ERROR, val.str()); if (!target->kind_of(Slot)) { target = target->child("in"); if (target) target = target->first_child(); // target/out/... if (!target) { return ErrorValue(NOT_FOUND_ERROR, val.str()).append(": slot not found"); } } if (kind_of(Outlet)) { // other should be an Inlet target = (Slot*)TYPE_CAST(Inlet, target); } else { // other should be an Outlet target = (Slot*)TYPE_CAST(Outlet,target); } if (!target) { return ErrorValue(BAD_REQUEST_ERROR, "Could not update link with ").append(val.to_json()).append(": incompatible)."); } if (operation == 'c') { // create link if (connect((Slot*)target)) { //std::cout << "LINKED: " << url() << " with " << val << std::endl; return Value(url()).push_back("=>").push_back(target->url()); } else { return ErrorValue(BAD_REQUEST_ERROR, "Could not make the connection with (").append(val.to_json()).append(")."); } } else { // disconnect disconnect((Slot*)target); return Value(url()).push_back("||").push_back(target->url()); } } else { return Value(info()); } }
Value ParseJSON(const char *s) { try { CParser p(s); return ParseJSON(p); } catch(CParser::Error e) { return ErrorValue(e); } }
Value Sql::Select0(const String& s) { SetStatement(s); if(!Run()) return ErrorValue(GetLastError()); if(!Fetch()) return Null; Value v; cn->GetColumn(0, v); return v; }
Value ConvertInt::Scan(const Value& text) const { Value v = UPP::Scan(INT_V, text); if(IsError(v)) return v; if(IsNull(v)) return notnull ? NotNullError() : v; int64 m = v; if(m >= minval && m <= maxval) { if(m >= INT_MIN && m <= INT_MAX) return (int)m; else return v; } return ErrorValue(UPP::Format(t_("Number must be between %d and %d."), minval, maxval)); }
Value ConvertString::Scan(const Value& text) const { if(IsError(text)) return text; if(IsNull(text)) return notnull ? NotNullError() : Value(text); if(text.GetType() == STRING_V && String(text).GetLength() <= maxlen || text.GetType() == WSTRING_V && WString(text).GetLength() <= maxlen) { String s = text; if(trimleft) s = Upp::TrimLeft(s); if(trimright) s = Upp::TrimRight(s); return s; } return ErrorValue(UPP::Format(t_("Please enter no more than %d characters."), maxlen)); }
Value ConvertDouble::Scan(const Value& txt) const { String text = txt; if(pattern.GetCount() && pattern != "%.10g") { // Fix text with patterns like "%2.!n EUR" (e.g. 1.2 EUR) text = UPP::Filter(text, CharFilterDouble); while(ToUpper(*text.Last()) == 'E') text.Trim(text.GetCount() - 1); } Value v = UPP::Scan(DOUBLE_V, text); if(IsError(v)) return v; if(IsNull(v)) return notnull ? NotNullError() : v; double m = v; if(m >= minval && m <= maxval) return v; return ErrorValue(UPP::Format(t_("Number must be between %g and %g."), minval, maxval)); }
Value ConvertTime::Scan(const Value& text) const { bool hastime; Value v = UPP::Scan(TIME_V, text, defaultval, &hastime); if(IsError(v)) return v; if(IsNull(v)) return notnull ? NotNullError() : v; Time m = v; if(!hastime && dayend) { m.hour = 23; m.minute = 59; m.second = 59; v = m; } if(m >= minval && m <= maxval) return v; return ErrorValue(t_("Time must be between ") + UPP::Format(minval) + t_("range\v and ") + UPP::Format(maxval) + "."); }
/** * parse a method call. it parses a xml message sent by a client and returns the method name and * the parameter it contains. * @param s the received data * @return the value, which includes an ValueArray with first element beeing the method name * @see ParseMethodResponse() */ Value XmlRpcParser::ParseMethodCall(String s){ XmlParser p(s); ValueArray va; try { while(!p.Tag("methodCall")) p.Skip(); p.PassTag("methodName"); va.Add(Value(p.ReadText())); p.PassEnd(); //methodName p.PassTag("params"); while(p.Tag("param")) { va.Add(Parse(p)); p.PassEnd(); //param } p.PassEnd(); //params p.PassEnd(); //methodCall LOG("request parsed"); } catch(Exc e) { return ErrorValue(NFormat("EXCEPTION: %s",e)); } return Value(va); }
static struct gl_list_t *FindNextNameElementPath(CONST struct Name *n, struct gl_list_t *list, enum find_errors *errval) { unsigned long pos,c,len; struct InstanceName rec; CONST struct Instance *current,*child; struct value_t setvalue,oldvalue; CONST struct Set *sptr; struct gl_list_t *result; PAN *p, *p2; struct Name *n2; *errval = correct_instance; if (NameId(n)){ result = gl_create(NAMELISTSIZE); SetInstanceNameType(rec,StrName); SetInstanceNameStrPtr(rec,NameIdPtr(n)); len = gl_length(list); for (c=1; c<=len; c++){ p = (PAN *)gl_fetch(list,c); current = p->i; pos = ChildSearch(current,&rec); if (pos!=0){ child = InstanceChild(current,pos); if (child!=NULL){ n2 = CopyAppendNameNode(p->n, n); p2 = CreatePAN(child, n2); gl_append_ptr(result,(VOIDPTR)p2); } else{ *errval = unmade_instance; DestroyPANList(&result); return NULL; } } else{ *errval = unmade_instance; /* it would seem this ought to be undefined_instance, * but maybe refinement causes insanity. -- in which case * it should be a caller policy to wait, rather than our * job to anticipate policy and short circuit things here. */ DestroyPANList(&result); return NULL; } } return result; } else { sptr = NameSetPtr(n); setvalue = EvaluateSet(sptr,InstanceEvaluateName); switch(ValueKind(setvalue)){ case integer_value: case symbol_value: case list_value: oldvalue = setvalue; if (ListMode) { setvalue = CreateOrderedSetFromList(oldvalue); } else { setvalue = CreateSetFromList(oldvalue); } DestroyValue(&oldvalue); /* intended to fall through to next case */ case set_value: result = FindArrayChildrenPath(list,SetValue(setvalue),errval); DestroyValue(&setvalue); return result; case error_value: switch(ErrorValue(setvalue)){ case illegal_set_use: *errval = impossible_instance; break; default: *errval = undefined_instance; break; /* more needs to be added here */ } DestroyValue(&setvalue); return NULL; default: ASC_PANIC("Need to add to FindNextNameElementPath.\n"); exit(2);/* Needed to keep gcc from whining */ } } }
RpcGet RpcRequest::Execute() { if(!shouldExecute) return RpcGet(); shouldExecute = false; String request; if(json) { ContentType("application/json"); static Atomic id; Json json; json("jsonrpc", "2.0") ("method", method); if(data.out.GetCount()) { JsonArray a; for(int i = 0; i < data.out.GetCount(); i++) { const Value& v = data.out[i]; if(v.Is<RawJsonText>()) a.CatRaw(v.To<RawJsonText>().json); else a << JsonRpcData(v); } json("params", a); } else if(data.out_map.GetCount()) { Json m; for(int i = 0; i < data.out_map.GetCount(); i++) { const Value& v = data.out_map.GetValue(i); String key = (String)data.out_map.GetKey(i); if(v.Is<RawJsonText>()) m.CatRaw(key, v.To<RawJsonText>().json); else m(key, JsonRpcData(v)); } json("params", m); } json("id", id); AtomicInc(id); request = ~json; } else { ContentType("text/xml"); request = XmlHeader(); request << XmlTag("methodCall")(XmlTag("methodName")(method) + FormatXmlRpcParams(data.out)); } if(sLogRpcCalls) { if(sLogRpcCallsCompress) RLOG("=== XmlRpc call request:\n" << CompressLog(request)); else RLOG("=== XmlRpc call request:\n" << request); } String response; New(); if(shorted) response = RpcExecuteShorted(request); else response = Post(request).Execute(); if(sLogRpcCalls) { if(sLogRpcCallsCompress) RLOG("=== XmlRpc call response:\n" << CompressLog(response)); else RLOG("=== XmlRpc call response:\n" << response); } RpcGet h; if(IsNull(response)) { faultCode = RPC_CLIENT_HTTP_ERROR; faultString = GetErrorDesc(); error = "Http request failed: " + faultString; LLOG(error); h.v = ErrorValue(error); return h; } if(json) { try { Value r = ParseJSON(response); if(IsValueMap(r)) { ValueMap m = r; Value result = m["result"]; if(!result.IsVoid()) { data.in.Clear(); data.in.Add(result); data.ii = 0; h.v = result; return h; } Value e = m["error"]; if(IsValueMap(e)) { Value c = e["code"]; Value m = e["message"]; if(IsNumber(c) && IsString(m)) { faultCode = e["code"]; faultString = e["message"]; error.Clear(); error << "Failed '" << faultString << "' (" << faultCode << ')'; LLOG(s); h.v = ErrorValue(error); return h; } } } String s; faultString = "Invalid response"; faultCode = RPC_CLIENT_RESPONSE_ERROR; error = faultString; LLOG(error); h.v = ErrorValue(error); return h; } catch(CParser::Error e) { String s; faultString = e; faultCode = RPC_CLIENT_JSON_ERROR; error.Clear(); error << "JSON Error: " << faultString; LLOG(error); h.v = ErrorValue(error); return h; } } else { XmlParser p(response); try { p.ReadPI(); p.PassTag("methodResponse"); if(p.Tag("fault")) { Value m = ParseXmlRpcValue(p); if(IsValueMap(m)) { ValueMap mm = m; faultString = mm["faultString"]; faultCode = mm["faultCode"]; error.Clear(); error << "Failed '" << faultString << "' (" << faultCode << ')'; LLOG(s); h.v = ErrorValue(error); return h; } } else { data.in = ParseXmlRpcParams(p); data.ii = 0; p.PassEnd(); } } catch(XmlError e) { String s; faultString = e; faultCode = RPC_CLIENT_XML_ERROR; error.Clear(); error << "XML Error: " << faultString; LLOG(error << ": " << p.GetPtr()); h.v = ErrorValue(error); return h; } h.v = data.in.GetCount() ? data.in[0] : Null; return h; } }
Value Socket::Data::GetInfo(String info) const { return ErrorValue(info); }
const Value& ValueMap::Data::Get(const Value& k) const { int q = key.Find(k); return q >= 0 ? value[q] : ErrorValue(); }
Value ErrorConvertClass::Scan(const Value& v) const { return ErrorValue(); }
Value ValueMap::GetAndClear(const Value& key) { Data& d = Clone(); int q = d.key.Find(key); return q < 0 ? ErrorValue() : d.value.GetAndClear(q); }
Value Scan(dword qtype, const String& text, const Value& def, bool *hastime) { Date date; const char *s; if(hastime) *hastime = false; switch(qtype) { case INT64_V: case INT_V: case BOOL_V: return StrIntValue(text); case DATE_V: if(text.IsEmpty()) return (Date) Null; s = StrToDate(date, text, (Date)def); if(s) for(;;) { if(IsDigit(*s)) break; if(*s == '\0') return date; s++; } return ErrorValue(t_("Invalid date !")); case TIME_V: { if(text.IsEmpty()) return (Time) Null; s = StrToDate(date, text, (Date)def); if(s) try { CParser p(s); Time tm = ToTime(date); Time d = (Time)def; tm.hour = d.hour; tm.minute = d.minute; tm.second = d.second; if(p.IsEof()) return tm; if(hastime) *hastime = true; int q = p.ReadInt(); if(q < 0 || q > 23) throw CParser::Error(""); tm.hour = q; if(p.IsEof()) return tm; p.PassChar(':'); q = p.ReadInt(); if(q < 0 || q > 59) throw CParser::Error(""); tm.minute = q; if(p.IsEof()) return tm; p.PassChar(':'); q = p.ReadInt(); if(q < 0 || q > 59) throw CParser::Error(""); tm.second = q; if(p.IsEof()) return tm; } catch(CParser::Error) {} return ErrorValue(t_("Invalid time !")); } case STRING_V: case WSTRING_V: return text; case DOUBLE_V: return StrDblValue(text); default: ASSERT(0); break; } return Null; }
Value NotNullError() { return ErrorValue(t_("Null value not allowed.")); }