String f_exec(CStrRef command, Variant output /* = null */, Variant return_var /* = null */) { ShellExecContext ctx; FILE *fp = ctx.exec(command); if (!fp) return ""; StringBuffer sbuf; sbuf.read(fp); Array lines = StringUtil::Explode(sbuf.detach(), "\n"); return_var = ctx.exit(); int count = lines.size(); if (count > 0 && lines[count - 1].toString().empty()) { count--; // remove explode()'s last empty line } if (!output.is(KindOfArray)) { output = Array(ArrayData::Create()); } for (int i = 0; i < count; i++) { output.append(lines[i]); } if (!count || lines.empty()) { return String(); } return StringUtil::Trim(lines[count - 1], StringUtil::TrimRight); }
bool TestCppBase::TestVariant() { // operators { Variant v(15); v += 20; VERIFY(v.isNumeric()); VERIFY(v.is(KindOfInt64)); VERIFY(v == Variant(35)); } // conversions { Variant v("123"); VERIFY(v.toInt32() == 123); } // offset { Variant v = "test"; VS(v.rvalAt(0), "t"); } { Variant v; v.lvalAt(0) = String("v0"); v.lvalAt(1) = String("v1"); VERIFY(v[0] == "v0"); VERIFY(v[1] == "v1"); } { Variant v; v.lvalAt() = String("test"); VS(v, CREATE_VECTOR1("test")); } { Variant v; v.lvalAt(1) = String("test"); VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v[s_1], "test"); VS(v[Variant("1")], "test"); } { Variant v; v.lvalAt(Variant(1.5)) = String("test"); VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v[s_1], "test"); VS(v[Variant("1")], "test"); } { Variant v; v.lvalAt(s_1) = String("test"); VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v[s_1], "test"); VS(v[Variant("1")], "test"); } { Variant v; v.lvalAt(Variant("1")) = String("test"); VS(v[1], "test"); VS(v[1.5], "test"); VS(v[Variant(1.5)], "test"); VS(v[s_1], "test"); VS(v[Variant("1")], "test"); } // membership { Variant v; v.lvalAt(s_n0) = String("v0"); v.lvalAt(s_n1) = String("v1"); v.remove(s_n1); VS(v, CREATE_MAP1(s_n0, "v0")); v.append("v2"); VS(v, CREATE_MAP2(s_n0, "v0", 0, "v2")); } { Variant v; v.lvalAt(s_n0) = String("v0"); v.lvalAt(1) = String("v1"); v.remove(Variant(1.5)); VS(v, CREATE_MAP1("n0", "v0")); } { Variant v; v.lvalAt(s_n0) = String("v0"); v.lvalAt(1) = String("v1"); v.remove(Variant("1")); VS(v, CREATE_MAP1("n0", "v0")); } { Variant v; v.lvalAt(s_n0) = String("v0"); v.lvalAt(1) = String("v1"); v.remove(String("1")); VS(v, CREATE_MAP1("n0", "v0")); } { Variant v; v.lvalAt(s_n0) = String("v0"); v.lvalAt(empty_string) = String("v1"); v.remove(Variant()); VS(v, CREATE_MAP1("n0", "v0")); } // references { Variant v1("original"); Variant v2 = v1; v2 = String("changed"); VERIFY(v1 == "original"); } { Variant v1("original"); Variant v2 = strongBind(v1); v2 = String("changed"); VERIFY(v1 == "changed"); } { Variant v1 = 10; Variant v2 = Array(ArrayInit(1).setRef(v1).create()); v1 = 20; VS(v2[0], 20); } { Variant v1 = 10; Variant v2; v2.lvalAt() = ref(v1); v1 = 20; VS(v2[0], 20); } { Variant v1 = 10; Variant v2 = CREATE_VECTOR1(5); v2.lvalAt() = ref(v1); v1 = 20; VS(v2[1], 20); } { Variant v1 = 10; Variant v2 = strongBind(v1); v2++; VS(v2, 11); VS(v1, 11); } { Variant arr = CREATE_VECTOR2(1, 2); Variant v; for (MutableArrayIter iter = arr.begin(nullptr, v); iter.advance();) { v++; } VS(arr, CREATE_VECTOR2(2, 3)); } // array escalation { Variant arr; lval(arr.lvalAt(0)).lvalAt(0) = 1.2; VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Variant arr; lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create(); lval(arr.lvalAt(0)).lvalAt(0) = 1.2; VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create(); lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create("test"); arr.lvalAt(0) = CREATE_VECTOR1(1.2); VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2))); } { Variant arr = Array::Create("test"); lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2; VS(arr, CREATE_MAP2(0, "test", s_name, CREATE_VECTOR1(1.2))); } return Count(true); }
/* SOAP client calls this function to parse response from SOAP server */ bool parse_packet_soap(c_SoapClient *obj, const char *buffer, int buffer_size, sdlFunctionPtr fn, const char *fn_name, Variant &return_value, Variant &soap_headers) { char* envelope_ns = NULL; xmlNodePtr trav, env, head, body, resp, cur, fault; xmlAttrPtr attr; int param_count = 0; int soap_version = SOAP_1_1; sdlSoapBindingFunctionHeaderMap *hdrs = NULL; return_value.reset(); /* Response for one-way opearation */ if (buffer_size == 0) { return true; } /* Parse XML packet */ xmlDocPtr response = soap_xmlParseMemory(buffer, buffer_size); if (!response) { add_soap_fault(obj, "Client", "looks like we got no XML document"); return false; } if (xmlGetIntSubset(response) != NULL) { add_soap_fault(obj, "Client", "DTD are not supported by SOAP"); xmlFreeDoc(response); return false; } /* Get <Envelope> element */ env = NULL; trav = response->children; while (trav != NULL) { if (trav->type == XML_ELEMENT_NODE) { if (!env && node_is_equal_ex(trav,"Envelope", SOAP_1_1_ENV_NAMESPACE)) { env = trav; envelope_ns = SOAP_1_1_ENV_NAMESPACE; soap_version = SOAP_1_1; } else if (!env && node_is_equal_ex(trav, "Envelope", SOAP_1_2_ENV_NAMESPACE)) { env = trav; envelope_ns = SOAP_1_2_ENV_NAMESPACE; soap_version = SOAP_1_2; } else { add_soap_fault(obj, "VersionMismatch", "Wrong Version"); xmlFreeDoc(response); return false; } } trav = trav->next; } if (env == NULL) { add_soap_fault(obj, "Client", "looks like we got XML without \"Envelope\" element"); xmlFreeDoc(response); return false; } attr = env->properties; while (attr != NULL) { if (attr->ns == NULL) { add_soap_fault(obj, "Client", "A SOAP Envelope element cannot have non Namespace " "qualified attributes"); xmlFreeDoc(response); return false; } if (attr_is_equal_ex(attr, "encodingStyle", SOAP_1_2_ENV_NAMESPACE)) { if (soap_version == SOAP_1_2) { add_soap_fault(obj, "Client", "encodingStyle cannot be specified on the Envelope"); xmlFreeDoc(response); return false; } if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE)) { add_soap_fault(obj, "Client", "Unknown data encoding style"); xmlFreeDoc(response); return false; } } attr = attr->next; } /* Get <Header> element */ head = NULL; trav = env->children; while (trav != NULL && trav->type != XML_ELEMENT_NODE) { trav = trav->next; } if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) { head = trav; trav = trav->next; } /* Get <Body> element */ body = NULL; while (trav != NULL && trav->type != XML_ELEMENT_NODE) { trav = trav->next; } if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) { body = trav; trav = trav->next; } while (trav != NULL && trav->type != XML_ELEMENT_NODE) { trav = trav->next; } if (body == NULL) { add_soap_fault(obj, "Client", "Body must be present in a SOAP envelope"); xmlFreeDoc(response); return false; } attr = body->properties; while (attr != NULL) { if (attr->ns == NULL) { if (soap_version == SOAP_1_2) { add_soap_fault(obj, "Client", "A SOAP Body element cannot have non Namespace " "qualified attributes"); xmlFreeDoc(response); return false; } } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) { if (soap_version == SOAP_1_2) { add_soap_fault(obj, "Client", "encodingStyle cannot be specified on the Body"); xmlFreeDoc(response); return false; } if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE)) { add_soap_fault(obj, "Client", "Unknown data encoding style"); xmlFreeDoc(response); return false; } } attr = attr->next; } if (trav != NULL && soap_version == SOAP_1_2) { add_soap_fault(obj, "Client", "A SOAP 1.2 envelope can contain only Header and Body"); xmlFreeDoc(response); return false; } if (head != NULL) { attr = head->properties; while (attr != NULL) { if (attr->ns == NULL) { add_soap_fault(obj, "Client", "A SOAP Header element cannot have non Namespace " "qualified attributes"); xmlFreeDoc(response); return false; } if (attr_is_equal_ex(attr, "encodingStyle", SOAP_1_2_ENV_NAMESPACE)) { if (soap_version == SOAP_1_2) { add_soap_fault(obj, "Client", "encodingStyle cannot be specified on the Header"); xmlFreeDoc(response); return false; } if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE)) { add_soap_fault(obj, "Client", "Unknown data encoding style"); xmlFreeDoc(response); return false; } } attr = attr->next; } } /* Check if <Body> contains <Fault> element */ fault = get_node_ex(body->children,"Fault",envelope_ns); if (fault != NULL) { char *faultcode = NULL; String faultstring, faultactor; Variant details; xmlNodePtr tmp; if (soap_version == SOAP_1_1) { tmp = get_node(fault->children, "faultcode"); if (tmp != NULL && tmp->children != NULL) { faultcode = (char*)tmp->children->content; } tmp = get_node(fault->children, "faultstring"); if (tmp != NULL && tmp->children != NULL) { Variant zv = master_to_zval(get_conversion(KindOfString), tmp); faultstring = zv.toString(); } tmp = get_node(fault->children, "faultactor"); if (tmp != NULL && tmp->children != NULL) { Variant zv = master_to_zval(get_conversion(KindOfString), tmp); faultactor = zv.toString(); } tmp = get_node(fault->children, "detail"); if (tmp != NULL) { details = master_to_zval(encodePtr(), tmp); } } else { tmp = get_node(fault->children, "Code"); if (tmp != NULL && tmp->children != NULL) { tmp = get_node(tmp->children, "Value"); if (tmp != NULL && tmp->children != NULL) { faultcode = (char*)tmp->children->content; } } tmp = get_node(fault->children,"Reason"); if (tmp != NULL && tmp->children != NULL) { /* TODO: lang attribute */ tmp = get_node(tmp->children,"Text"); if (tmp != NULL && tmp->children != NULL) { Variant zv = master_to_zval(get_conversion(KindOfString), tmp); faultstring = zv.toString(); } } tmp = get_node(fault->children,"Detail"); if (tmp != NULL) { details = master_to_zval(encodePtr(), tmp); } } obj->m_soap_fault = Object(SystemLib::AllocSoapFaultObject(String(faultcode, CopyString), faultstring, faultactor, details)); xmlFreeDoc(response); return false; } /* Parse content of <Body> element */ return_value = Array::Create(); resp = body->children; while (resp != NULL && resp->type != XML_ELEMENT_NODE) { resp = resp->next; } if (resp != NULL) { if (fn && fn->binding && fn->binding->bindingType == BINDING_SOAP) { /* Function has WSDL description */ sdlParamPtr h_param, param; xmlNodePtr val = NULL; const char *name, *ns = NULL; Variant tmp; sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes; int res_count; hdrs = &fnb->output.headers; if (!fn->responseParameters.empty()) { res_count = fn->responseParameters.size(); for (unsigned int i = 0; i < fn->responseParameters.size(); i++) { h_param = fn->responseParameters[i]; param = h_param; if (fnb->style == SOAP_DOCUMENT) { if (param->element) { name = param->element->name.c_str(); ns = param->element->namens.c_str(); /* name = param->encode->details.type_str; ns = param->encode->details.ns; */ } else { name = param->paramName.c_str(); } } else { name = fn->responseName.c_str(); /* ns = ? */ } /* Get value of parameter */ cur = get_node_ex(resp, (char*)name, (char*)ns); if (!cur) { cur = get_node(resp, (char*)name); /* TODO: produce warning invalid ns */ } if (!cur && fnb->style == SOAP_RPC) { cur = resp; } if (cur) { if (fnb->style == SOAP_DOCUMENT) { val = cur; } else { val = get_node(cur->children, (char*)param->paramName.c_str()); if (res_count == 1) { if (val == NULL) { val = get_node(cur->children, "return"); } if (val == NULL) { val = get_node(cur->children, "result"); } if (val == NULL && cur->children && !cur->children->next) { val = cur->children; } } } } if (!val) { /* TODO: may be "nil" is not OK? */ tmp.reset(); /* add_soap_fault(obj, "Client", "Can't find response data"); xmlFreeDoc(response); return false; */ } else { /* Decoding value of parameter */ if (param != NULL) { tmp = master_to_zval(param->encode, val); } else { tmp = master_to_zval(encodePtr(), val); } } return_value.set(String(param->paramName), tmp); param_count++; } } } else { /* Function hasn't WSDL description */ xmlNodePtr val; val = resp->children; while (val != NULL) { while (val && val->type != XML_ELEMENT_NODE) { val = val->next; } if (val != NULL) { if (!node_is_equal_ex(val,"result",RPC_SOAP12_NAMESPACE)) { Variant tmp = master_to_zval(encodePtr(), val); if (val->name) { String key((char*)val->name, CopyString); if (return_value.toArray().exists(key)) { return_value.lvalAt(key).append(tmp); } else if (val->next && get_node(val->next, (char*)val->name)) { Array arr = Array::Create(); arr.append(tmp); return_value.set(key, arr); } else { return_value.set(key, tmp); } } else { return_value.append(tmp); } ++param_count; } val = val->next; } } } } if (return_value.isArray()) { if (param_count == 0) { return_value.reset(); } else if (param_count == 1) { Array arr = return_value.toArray(); ArrayIter iter(arr); return_value = iter.second(); } } if (head) { trav = head->children; while (trav) { if (trav->type == XML_ELEMENT_NODE) { encodePtr enc; if (hdrs && !hdrs->empty()) { string key; if (trav->ns) { key += (char*)trav->ns->href; key += ':'; } key += (char*)trav->name; sdlSoapBindingFunctionHeaderMap::const_iterator iter = hdrs->find(key); if (iter != hdrs->end()) { enc = iter->second->encode; } } soap_headers.set(String((char*)trav->name, CopyString), master_to_zval(enc, trav)); } trav = trav->next; } } xmlFreeDoc(response); return true; }
Variant binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, CArrRef fieldspec) { Variant ret; switch (thrift_typeID) { case T_STOP: case T_VOID: return uninit_null(); case T_STRUCT: { Variant val; if ((val = fieldspec.rvalAt(PHPTransport::s_class)).isNull()) { throw_tprotocolexception("no class type in spec", INVALID_DATA); skip_element(T_STRUCT, transport); return uninit_null(); } String structType = val.toString(); ret = createObject(structType); if (ret.isNull()) { // unable to create class entry skip_element(T_STRUCT, transport); return uninit_null(); } Variant spec = f_hphp_get_static_property(structType, s_TSPEC, false); if (!spec.is(KindOfArray)) { char errbuf[128]; snprintf(errbuf, 128, "spec for %s is wrong type: %d\n", structType.data(), ret.getType()); throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA); return uninit_null(); } binary_deserialize_spec(ret.toObject(), transport, spec.toArray()); return ret; } break; case T_BOOL: { uint8_t c; transport.readBytes(&c, 1); return c != 0; } //case T_I08: // same numeric value as T_BYTE case T_BYTE: { uint8_t c; transport.readBytes(&c, 1); return Variant((int8_t)c); } case T_I16: { uint16_t c; transport.readBytes(&c, 2); return Variant((int16_t)ntohs(c)); } case T_I32: { uint32_t c; transport.readBytes(&c, 4); return Variant((int32_t)ntohl(c)); } case T_U64: case T_I64: { uint64_t c; transport.readBytes(&c, 8); return Variant((int64_t)ntohll(c)); } case T_DOUBLE: { union { uint64_t c; double d; } a; transport.readBytes(&(a.c), 8); a.c = ntohll(a.c); return a.d; } case T_FLOAT: { union { uint32_t c; float d; } a; transport.readBytes(&(a.c), 4); a.c = ntohl(a.c); return a.d; } //case T_UTF7: // aliases T_STRING case T_UTF8: case T_UTF16: case T_STRING: { uint32_t size = transport.readU32(); if (size && (size + 1)) { String s = String(size, ReserveString); char* strbuf = s.bufferSlice().ptr; transport.readBytes(strbuf, size); return s.setSize(size); } else { return ""; } } case T_MAP: { // array of key -> value uint8_t types[2]; transport.readBytes(types, 2); uint32_t size = transport.readU32(); Array keyspec = fieldspec.rvalAt(PHPTransport::s_key, AccessFlags::Error_Key).toArray(); Array valspec = fieldspec.rvalAt(PHPTransport::s_val, AccessFlags::Error_Key).toArray(); ret = Array::Create(); for (uint32_t s = 0; s < size; ++s) { Variant key = binary_deserialize(types[0], transport, keyspec); Variant value = binary_deserialize(types[1], transport, valspec); ret.set(key, value); } return ret; // return_value already populated } case T_LIST: { // array with autogenerated numeric keys int8_t type = transport.readI8(); uint32_t size = transport.readU32(); Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem, AccessFlags::Error_Key); Array elemspec = elemvar.toArray(); ret = Array::Create(); for (uint32_t s = 0; s < size; ++s) { Variant value = binary_deserialize(type, transport, elemspec); ret.append(value); } return ret; } case T_SET: { // array of key -> TRUE uint8_t type; uint32_t size; transport.readBytes(&type, 1); transport.readBytes(&size, 4); size = ntohl(size); Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem, AccessFlags::Error_Key); Array elemspec = elemvar.toArray(); ret = Array::Create(); for (uint32_t s = 0; s < size; ++s) { Variant key = binary_deserialize(type, transport, elemspec); if (key.isInteger()) { ret.set(key, true); } else { ret.set(key.toString(), true); } } return ret; } }; char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA); return uninit_null(); }