Variant APCHandle::toLocal() const { switch (m_kind) { case APCKind::Uninit: case APCKind::Null: return init_null(); // shortcut.. no point to forward case APCKind::Bool: return APCTypedValue::fromHandle(this)->getBoolean(); case APCKind::Int: return APCTypedValue::fromHandle(this)->getInt64(); case APCKind::Double: return APCTypedValue::fromHandle(this)->getDouble(); case APCKind::StaticString: case APCKind::UncountedString: return Variant{APCTypedValue::fromHandle(this)->getStringData(), Variant::PersistentStrInit{}}; case APCKind::SharedString: return Variant::attach( StringData::MakeProxy(APCString::fromHandle(this)) ); case APCKind::StaticArray: case APCKind::UncountedArray: return Variant{APCTypedValue::fromHandle(this)->getArrayData(), Variant::PersistentArrInit{}}; case APCKind::SerializedArray: { auto const serArr = APCString::fromHandle(this)->getStringData(); return apc_unserialize(serArr->data(), serArr->size()); } case APCKind::SharedArray: case APCKind::SharedPackedArray: return Variant::attach( APCLocalArray::Make(APCArray::fromHandle(this))->asArrayData() ); case APCKind::SerializedObject: { auto const serObj = APCString::fromHandle(this)->getStringData(); return apc_unserialize(serObj->data(), serObj->size()); } case APCKind::SharedCollection: return APCCollection::fromHandle(this)->createObject(); case APCKind::SharedObject: return APCObject::MakeLocalObject(this); } not_reached(); }
static Variant HHVM_FUNCTION(bcmod, const String& left, const String& right) { bc_num first, second, result; bc_init_num(&first); bc_init_num(&second); bc_init_num(&result); SCOPE_EXIT { bc_free_num(&first); bc_free_num(&second); bc_free_num(&result); }; php_str2num(&first, (char*)left.data()); php_str2num(&second, (char*)right.data()); if (bc_modulo(first, second, &result, 0) == -1) { raise_warning("Division by zero"); return init_null(); } String ret(bc_num2str(result), AttachString); return ret; }
static Variant HHVM_FUNCTION(assert, const Variant& assertion) { if (!s_option_data->assertActive) return true; CallerFrame cf; Offset callerOffset; auto const fp = cf(&callerOffset); auto const passed = [&]() -> bool { if (assertion.isString()) { if (RuntimeOption::EvalAuthoritativeMode) { // We could support this with compile-time string literals, // but it's not yet implemented. throw NotSupportedException(__func__, "assert with strings argument in RepoAuthoritative mode"); } return eval_for_assert(fp, assertion.toString()).toBoolean(); } return assertion.toBoolean(); }(); if (passed) return true; if (!s_option_data->assertCallback.isNull()) { auto const unit = fp->m_func->unit(); PackedArrayInit ai(3); ai.append(String(const_cast<StringData*>(unit->filepath()))); ai.append(Variant(unit->getLineNumber(callerOffset))); ai.append(assertion.isString() ? assertion : empty_string_variant_ref); f_call_user_func(1, s_option_data->assertCallback, ai.toArray()); } if (s_option_data->assertWarning) { auto const str = !assertion.isString() ? String("Assertion failed") : concat3("Assertion \"", assertion.toString(), "\" failed"); raise_warning("%s", str.data()); } if (s_option_data->assertBail) { throw Assertion(); } return init_null(); }
XDEBUG_NOTIMPLEMENTED static Variant HHVM_FUNCTION(xdebug_stop_trace) { if (!XDEBUG_GLOBAL(ProfilerAttached)) { return false; } auto profiler = xdebug_profiler(); if (!profiler->isTracing()) { return false; } // End with xdebug_stop_trace() profiler->endFrame(init_null().asTypedValue(), nullptr, false); auto filename = profiler->getTracingFilename(); profiler->disableTracing(); detach_xdebug_profiler_if_needed(); return filename; }
Variant HHVM_STATIC_METHOD(IntlChar, charName, const Variant& arg, int64_t choice) { GETCP(arg, cp); UErrorCode error = U_ZERO_ERROR; int32_t buffer_len = u_charName(cp, (UCharNameChoice)choice, nullptr, 0, &error); String buffer(buffer_len, ReserveString); error = U_ZERO_ERROR; buffer_len = u_charName(cp, (UCharNameChoice)choice, buffer.bufferSlice().ptr, buffer_len + 1, &error); if (U_FAILURE(error)) { s_intl_error->setError(error, "Failure getting character name"); return init_null(); } buffer.setSize(buffer_len); return buffer; }
static Variant preg_replace_callback_array_impl( const Variant& patterns_and_callbacks, const Array& subjects, int limit, VRefParam count) { Array ret = Array::Create(); auto key = 0; auto total_replacement_count = 0; for (ArrayIter s_iter(subjects); s_iter; ++s_iter) { assert(s_iter.second().isString()); auto subj = s_iter.second(); for (ArrayIter pc_iter(patterns_and_callbacks.toArray()); pc_iter; ++pc_iter) { Variant pattern(pc_iter.first()); assert(pattern.isString()); Variant callback(pc_iter.second()); subj = HHVM_FN(preg_replace_callback)(pattern, callback, subj, limit, count); // If we got an error on the replacement, the subject will be null, // and then we will return null. if (subj.isNull()) { return init_null(); } if (count.isReferenced()) { total_replacement_count += count.toInt64(); } } ret.add(key++, subj); } // If count was passed in as an explicit reference, we will assign it to our // total replacement count; otherwise, count will just remained unassigned count.assignIfRef(total_replacement_count); // If there were no replacements (i.e., matches) return original subject(s) if (ret.empty()) { return subjects; } return ret; }
Variant HHVM_FUNCTION(parse_url, const String& url, int64_t component /* = -1 */) { Url resource; if (!url_parse(resource, url.data(), url.size())) { return false; } if (component > -1) { switch (component) { case k_PHP_URL_SCHEME: RETURN_COMPONENT(scheme); break; case k_PHP_URL_HOST: RETURN_COMPONENT(host); break; case k_PHP_URL_USER: RETURN_COMPONENT(user); break; case k_PHP_URL_PASS: RETURN_COMPONENT(pass); break; case k_PHP_URL_PATH: RETURN_COMPONENT(path); break; case k_PHP_URL_QUERY: RETURN_COMPONENT(query); break; case k_PHP_URL_FRAGMENT: RETURN_COMPONENT(fragment); break; case k_PHP_URL_PORT: if (resource.port) { return resource.port; } break; default: raise_warning( "parse_url(): Invalid URL component identifier %" PRId64, component); return false; } return init_null(); } ArrayInit ret(resource.port ? 8 : 7, ArrayInit::Map{}); SET_COMPONENT(scheme); SET_COMPONENT(host); if (resource.port) { ret.set(s_port, (int64_t)resource.port); } SET_COMPONENT(user); SET_COMPONENT(pass); SET_COMPONENT(path); SET_COMPONENT(query); SET_COMPONENT(fragment); return ret.toVariant(); }
Variant c_XMLReader::string_func_string_arg(String value, xmlreader_read_one_char_t internal_function) { if (value.empty()) { raise_warning("Argument cannot be an empty string"); return false; } char *retchar = NULL; if (m_ptr) { retchar = (char *)internal_function(m_ptr, (const unsigned char *)value.data()); } if (retchar) { String ret((const char*)retchar, CopyString); xmlFree(retchar); return ret; } else { return init_null(); } }
Object APCObject::createObject() const { Object obj; const Class* klass; if (auto const c = m_cls.left()) { klass = c; } else { klass = Unit::loadClass(m_cls.right()); if (!klass) { Logger::Error("APCObject::getObject(): Cannot find class %s", m_cls.right()->data()); return obj; } } obj = ObjectData::newInstance(const_cast<Class*>(klass)); obj.get()->clearNoDestruct(); auto prop = props(); auto const propEnd = prop + m_propCount; for (; prop != propEnd; ++prop) { auto const key = prop->name; const Class* ctx = nullptr; if (prop->ctx.isNull()) { ctx = klass; } else { if (auto const cls = prop->ctx.left()) { ctx = cls; } else { ctx = Unit::lookupClass(prop->ctx.right()); if (!ctx) continue; } } auto val = prop->val ? prop->val->toLocal() : init_null(); obj->setProp(const_cast<Class*>(ctx), key, val.asTypedValue(), false); } obj->invokeWakeup(); return obj; }
static Variant xml_call_handler(const req::ptr<XmlParser>& parser, const Variant& handler, const Array& args) { if (parser && handler.toBoolean()) { Variant retval; if (handler.isString() && !name_contains_class(handler.toString())) { if (!parser->object.isObject()) { retval = invoke(handler.toString().c_str(), args, -1); } else { retval = parser->object.toObject()-> o_invoke(handler.toString(), args); } } else if (is_callable(handler)) { vm_call_user_func(handler, args); } else { raise_warning("Handler is invalid"); } return retval; } return init_null(); }
Variant c_XMLReader::t_getattributens(const String& name, const String& namespaceURI) { if (name.empty() || namespaceURI.empty()) { raise_warning("Attribute Name and Namespace URI cannot be empty"); return false; } char *retchar = NULL; if (m_ptr) { retchar = (char *)xmlTextReaderGetAttributeNs(m_ptr, (xmlChar *)name.data(), (xmlChar *)namespaceURI.data()); } if (retchar) { String ret((const char*)retchar, CopyString); xmlFree(retchar); return ret; } else { return init_null(); } }
static Variant HHVM_FUNCTION(bcdiv, const String& left, const String& right, int64_t scale /* = -1 */) { if (scale < 0) scale = BCG(bc_precision); bc_num first, second, result; bc_init_num(&first); bc_init_num(&second); bc_init_num(&result); SCOPE_EXIT { bc_free_num(&first); bc_free_num(&second); bc_free_num(&result); }; php_str2num(&first, (char*)left.data()); php_str2num(&second, (char*)right.data()); if (bc_divide(first, second, &result, scale) == -1) { raise_warning("Division by zero"); return init_null(); } String ret(bc_num2str(result), AttachString); return ret; }
Variant SSATmp::variantVal() const { switch (type().toDataType()) { case KindOfUninit: case KindOfNull: // Upon return both will converted to KindOfNull anyway. return init_null(); case KindOfBoolean: return boolVal(); case KindOfInt64: return intVal(); case KindOfDouble: return dblVal(); case KindOfString: case KindOfStaticString: return Variant(const_cast<StringData*>(strVal())); case KindOfArray: return const_cast<ArrayData*>(arrVal()); default: always_assert(false); } }
Variant SSATmp::getValVariant() const { switch (m_inst->typeParam().toDataType()) { case KindOfUninit: return uninit_null(); case KindOfNull: return init_null(); case KindOfBoolean: return getValBool(); case KindOfInt64: return getValInt(); case KindOfDouble: return getValDbl(); case KindOfString: case KindOfStaticString: return Variant(getValStr()); case KindOfArray: return const_cast<ArrayData*>(getValArr()); default: always_assert(false); } }
void XDebugServer::onRequestInit() { if (!XDEBUG_GLOBAL(RemoteEnable)) { return; } // TODO(#4489053) Enable this when debugger internals have been refactored // Need to turn on debugging regardless of the remote mode in order to // capture exceptions/errors // ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck(); // ti->m_reqInjectionData.setDebugger(true); // Grab $_GET, $_COOKIE, and the transport const ArrayData* globals = get_global_variables()->asArrayData(); Array get = globals->get(s_GET).toArray(); Array cookie = globals->get(s_COOKIE).toArray(); Transport* transport = g_context->getTransport(); // Need to check $_GET[XDEBUG_SESSION_STOP]. If set, delete the session // cookie const Variant sess_stop_var = get[s_SESSION_STOP]; if (!sess_stop_var.isNull()) { cookie.set(s_SESSION, init_null()); if (transport != nullptr) { transport->setCookie(s_SESSION, empty_string()); } } // Need to check $_GET[XDEBUG_SESSION_START]. If set, store the session // cookie with $_GET[XDEBUG_SESSION_START] as the value const Variant sess_start_var = get[s_SESSION_START]; if (sess_start_var.isString()) { String sess_start = sess_start_var.toString(); cookie.set(s_SESSION, sess_start); if (transport != nullptr) { transport->setCookie(s_SESSION, sess_start, XDEBUG_GLOBAL(RemoteCookieExpireTime)); } } }
Variant HHVM_METHOD(SQLite3, querysingle, const String& sql, bool entire_row /* = false */) { auto *data = Native::data<SQLite3>(this_); SYNC_VM_REGS_SCOPED(); data->validate(); if (!sql.empty()) { Variant stmt = HHVM_MN(SQLite3, prepare)(this_, sql); if (!same(stmt, false)) { Object obj_stmt = stmt.toObject(); assert(obj_stmt.instanceof(SQLite3Stmt::getClass())); sqlite3_stmt *pstmt = Native::data<SQLite3Stmt>(obj_stmt)->m_raw_stmt; switch (sqlite3_step(pstmt)) { case SQLITE_ROW: /* Valid Row */ if (entire_row) { Array ret = Array::Create(); for (int i = 0; i < sqlite3_data_count(pstmt); i++) { ret.set(String((char*)sqlite3_column_name(pstmt, i), CopyString), get_column_value(pstmt, i)); } return ret; } return get_column_value(pstmt, 0); case SQLITE_DONE: /* Valid but no results */ if (entire_row) { return empty_array(); } else { return init_null(); } default: raise_warning("Unable to execute statement: %s", sqlite3_errmsg(data->m_raw_db)); } } } return false; }
Variant ArrayUtil::RandomKeys(const Array& input, int num_req /* = 1 */) { int count = input.size(); if (num_req <= 0 || num_req > count) { raise_warning("Second argument has to be between 1 and the " "number of elements in the array"); return init_null(); } if (num_req == 1) { // Iterating through the counter is correct but a bit inefficient // compared to being able to access the right offset into array data, // but necessary for this code to be agnostic to the array's internal // representation. Assuming uniform distribution, we'll expect to // iterate through half of the array's data. ssize_t index = f_rand(0, count-1); ssize_t pos = input->iter_begin(); while (index--) { pos = input->iter_advance(pos); } return input->getKey(pos); } std::vector<ssize_t> indices; indices.reserve(count); auto pos_limit = input->iter_end(); for (ssize_t pos = input->iter_begin(); pos != pos_limit; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); PackedArrayInit ret(num_req); for (int i = 0; i < num_req; i++) { ssize_t pos = indices[i]; ret.append(input->getKey(pos)); } return ret.toVariant(); }
static Variant xml_call_handler(XmlParser *parser, const Variant& handler, const Array& args) { if (parser && handler.toBoolean()) { Variant retval; if (handler.isString()) { if (!parser->object.isObject()) { retval = invoke(handler.toString().c_str(), args, -1); } else { retval = parser->object.toObject()-> o_invoke(handler.toString(), args); } } else if (handler.isArray() && handler.getArrayData()->size() == 2 && (handler.toCArrRef()[0].isString() || handler.toCArrRef()[0].isObject()) && handler.toCArrRef()[1].isString()) { vm_call_user_func(handler, args); } else { raise_warning("Handler is invalid"); } return retval; } return init_null(); }
static Variant dynamic_to_variant(const folly::dynamic& v) { switch (v.type()) { case folly::dynamic::Type::NULLT: return init_null(); case folly::dynamic::Type::BOOL: return v.asBool(); case folly::dynamic::Type::DOUBLE: return v.asDouble(); case folly::dynamic::Type::INT64: return v.asInt(); case folly::dynamic::Type::STRING: return v.data(); case folly::dynamic::Type::ARRAY: case folly::dynamic::Type::OBJECT: ArrayInit ret(v.size(), ArrayInit::Mixed{}); for (auto& item : v.items()) { ret.add(dynamic_to_variant(item.first), dynamic_to_variant(item.second)); } return ret.toArray(); } not_reached(); }
Variant HHVM_FUNCTION(php_uname, const String& mode /*="" */) { struct utsname buf; if (uname((struct utsname *)&buf) == -1) { return init_null(); } if (mode == s_s) { return String(buf.sysname, CopyString); } else if (mode == s_r) { return String(buf.release, CopyString); } else if (mode == s_n) { return String(buf.nodename, CopyString); } else if (mode == s_v) { return String(buf.version, CopyString); } else if (mode == s_m) { return String(buf.machine, CopyString); } else { /* assume mode == "a" */ char tmp_uname[512]; snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %s %s %s", buf.sysname, buf.nodename, buf.release, buf.version, buf.machine); return String(tmp_uname, CopyString); } }
Variant c_Closure::t___unset(Variant name) { raise_recoverable_error("Closure object cannot have properties"); return init_null(); }
static const Variant get_breakpoint_message(const BreakInfo& bi) { // In php5 xdebug, only messages have a string. But this could be extended to // be more useful. return type == BreakType::EXCEPTION ? Variant(bi.message->data()) : init_null(); }
void DummySandbox::run() { TRACE(2, "DummySandbox::run\n"); RequestInfo *ti = RequestInfo::s_requestInfo.getNoCheck(); while (!m_stopped) { try { CLISession hphpSession; DSandboxInfo sandbox = m_proxy->getSandbox(); std::string msg; if (sandbox.valid()) { SourceRootInfo sri(sandbox.m_user, sandbox.m_name); if (sandbox.m_path.empty()) { sandbox.m_path = sri.path(); } if (!sri.sandboxOn()) { msg = "Invalid sandbox was specified. " "PHP files may not be loaded properly.\n"; } else { auto server = php_global_exchange(s__SERVER, init_null()); forceToArray(server); Array arr = server.toArrRef(); server.unset(); php_global_set(s__SERVER, sri.setServerVariables(std::move(arr))); } Debugger::RegisterSandbox(sandbox); g_context->setSandboxId(sandbox.id()); std::string doc = getStartupDoc(sandbox); if (!doc.empty()) { char cwd[PATH_MAX]; getcwd(cwd, sizeof(cwd)); Logger::Info("Start loading startup doc '%s', pwd = '%s'", doc.c_str(), cwd); bool error; std::string errorMsg; bool ret = hphp_invoke(g_context.getNoCheck(), doc, false, null_array, uninit_null(), "", "", error, errorMsg, true, false, true, RuntimeOption::EvalPreludePath); if (!ret || error) { msg += "Unable to pre-load " + doc; if (!errorMsg.empty()) { msg += ": " + errorMsg; } } Logger::Info("Startup doc " + doc + " loaded"); } } else { g_context->setSandboxId(m_proxy->getDummyInfo().id()); } if (!DebuggerHook::attach<HphpdHook>(ti)) { const char* fail = "Could not attach hphpd to request: another debugger" " is already attached."; Logger::Error("%s", fail); Debugger::InterruptSessionStarted(nullptr, fail); throw DebuggerClientAttachFailureException(); } { DebuggerDummyEnv dde; // This is really the entire point of having the dummy sandbox. This // fires the initial session started interrupt to the client after // it first attaches. Debugger::InterruptSessionStarted(nullptr, msg.c_str()); } // Blocking until Ctrl-C is issued by end user and DebuggerProxy cannot // find a real sandbox thread to handle it. { Lock lock(this); while (!m_stopped && m_signum != CmdSignal::SignalBreak) { wait(1); } if (m_stopped) { // stopped by worker thread break; } m_signum = CmdSignal::SignalNone; } } catch (const DebuggerClientExitException& e) { // stopped by the dummy sandbox thread itself break; } catch (const DebuggerException& e) { } } }
Variant binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, const Array& fieldspec) { Variant ret; switch (thrift_typeID) { case T_STOP: case T_VOID: return init_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 init_null(); } String structType = val.toString(); ret = createObject(structType); if (ret.isNull()) { // unable to create class entry skip_element(T_STRUCT, transport); return init_null(); } Variant spec = HHVM_FN(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 init_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.mutableData(); transport.readBytes(strbuf, size); s.setSize(size); return s; } else { return empty_string_variant(); } } 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(); String format = fieldspec.rvalAt(PHPTransport::s_format, AccessFlags::None).toString(); if (format.equal(PHPTransport::s_collection)) { ret = newobj<c_Map>(); for (uint32_t s = 0; s < size; ++s) { Variant key = binary_deserialize(types[0], transport, keyspec); Variant value = binary_deserialize(types[1], transport, valspec); collectionSet(ret.getObjectData(), key.asCell(), value.asCell()); } } else { 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.toArrRef().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(); String format = fieldspec.rvalAt(PHPTransport::s_format, AccessFlags::None).toString(); if (format.equal(PHPTransport::s_collection)) { auto const pvec = newobj<c_Vector>(); ret = pvec; for (uint32_t s = 0; s < size; ++s) { Variant value = binary_deserialize(type, transport, elemspec); pvec->t_add(value); } } else { PackedArrayInit pai(size); for (auto s = uint32_t{0}; s < size; ++s) { pai.append(binary_deserialize(type, transport, elemspec)); } ret = pai.toArray(); } 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(); String format = fieldspec.rvalAt(PHPTransport::s_format, AccessFlags::None).toString(); if (format.equal(PHPTransport::s_collection)) { auto set_ret = makeSmartPtr<c_Set>(); for (uint32_t s = 0; s < size; ++s) { Variant key = binary_deserialize(type, transport, elemspec); if (key.isInteger()) { set_ret->t_add(key); } else { set_ret->t_add(key.toString()); } } ret = Variant(std::move(set_ret)); } else { ArrayInit init(size, ArrayInit::Mixed{}); for (uint32_t s = 0; s < size; ++s) { Variant key = binary_deserialize(type, transport, elemspec); if (key.isInteger()) { init.set(key, true); } else { init.setKeyUnconverted(key, true); } } ret = init.toArray(); } return ret; } }; char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA); return init_null(); }
Variant HHVM_FUNCTION(php_uname, const String& mode /*="" */) { #ifdef _WIN32 if (mode == s_s) { return s_Windows_NT; } else if (mode == s_r) { DWORD dwVersion = GetVersion(); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); return folly::sformat("{}.{}", dwMajorVersion, dwMinorVersion); } else if (mode == s_n) { DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; GetComputerName(ComputerName, &dwSize); return String(ComputerName, dwSize, CopyString); } else if (mode == s_v) { DWORD dwVersion = GetVersion(); auto dwBuild = (DWORD)(HIWORD(dwVersion)); auto winVer = php_get_windows_name(); if (!winVer.hasValue()) { return folly::sformat("build {}", dwBuild); } return folly::sformat("build {} ({})", dwBuild, winVer.value()); } else if (mode == s_m) { return php_get_windows_cpu(); } else { auto winVer = php_get_windows_name(); DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; GetComputerName(ComputerName, &dwSize); DWORD dwVersion = GetVersion(); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwBuild = (DWORD)(HIWORD(dwVersion)); if (dwMajorVersion == 6 && dwMinorVersion == 2 && winVer.hasValue()) { if (strncmp(winVer.value().c_str(), "Windows 8.1", 11) == 0 || strncmp(winVer.value().c_str(), "Windows Server 2012 R2", 22) == 0) { dwMinorVersion = 3; } } return folly::sformat("Windows NT {} {}.{} build {} ({}) {}", ComputerName, dwMajorVersion, dwMinorVersion, dwBuild, winVer.hasValue() ? winVer.value().c_str() : "unknown", php_get_windows_cpu() ); } #else struct utsname buf; if (uname((struct utsname *)&buf) == -1) { return init_null(); } if (mode == s_s) { return String(buf.sysname, CopyString); } else if (mode == s_r) { return String(buf.release, CopyString); } else if (mode == s_n) { return String(buf.nodename, CopyString); } else if (mode == s_v) { return String(buf.version, CopyString); } else if (mode == s_m) { return String(buf.machine, CopyString); } else { /* assume mode == "a" */ char tmp_uname[512]; snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %s %s %s", buf.sysname, buf.nodename, buf.release, buf.version, buf.machine); return String(tmp_uname, CopyString); } #endif }
Variant c_Closure::t___set(Variant member, Variant value) { raise_recoverable_error("Closure object cannot have properties"); return init_null(); }
static Variant get_breakpoint_message(const BreakInfo& bi) { if (auto eb = boost::get<ExnBreak>(&bi)) return VarNR(eb->message); return init_null(); }
Variant APCHandle::toLocal() const { switch (m_kind) { case APCKind::Uninit: case APCKind::Null: return init_null(); // shortcut.. no point to forward case APCKind::Bool: return APCTypedValue::fromHandle(this)->getBoolean(); case APCKind::Int: return APCTypedValue::fromHandle(this)->getInt64(); case APCKind::Double: return APCTypedValue::fromHandle(this)->getDouble(); case APCKind::StaticString: case APCKind::UncountedString: return Variant{APCTypedValue::fromHandle(this)->getStringData(), Variant::PersistentStrInit{}}; case APCKind::SharedString: return Variant::attach( StringData::MakeProxy(APCString::fromHandle(this)) ); case APCKind::StaticArray: case APCKind::UncountedArray: return Variant{APCTypedValue::fromHandle(this)->getArrayData(), KindOfPersistentArray, Variant::PersistentArrInit{}}; case APCKind::StaticVec: case APCKind::UncountedVec: return Variant{APCTypedValue::fromHandle(this)->getVecData(), KindOfPersistentVec, Variant::PersistentArrInit{}}; case APCKind::StaticDict: case APCKind::UncountedDict: return Variant{APCTypedValue::fromHandle(this)->getDictData(), KindOfPersistentDict, Variant::PersistentArrInit{}}; case APCKind::StaticKeyset: case APCKind::UncountedKeyset: return Variant{APCTypedValue::fromHandle(this)->getKeysetData(), KindOfPersistentKeyset, Variant::PersistentArrInit{}}; case APCKind::SerializedArray: { auto const serArr = APCString::fromHandle(this)->getStringData(); auto const v = apc_unserialize(serArr->data(), serArr->size()); assert(v.isPHPArray()); return v; } case APCKind::SerializedVec: { auto const serVec = APCString::fromHandle(this)->getStringData(); auto const v = apc_unserialize(serVec->data(), serVec->size()); assert(v.isVecArray()); return v; } case APCKind::SerializedDict: { auto const serDict = APCString::fromHandle(this)->getStringData(); auto const v = apc_unserialize(serDict->data(), serDict->size()); assert(v.isDict()); return v; } case APCKind::SerializedKeyset: { auto const serKeyset = APCString::fromHandle(this)->getStringData(); auto const v = apc_unserialize(serKeyset->data(), serKeyset->size()); assert(v.isKeyset()); return v; } case APCKind::SharedArray: case APCKind::SharedPackedArray: return Variant::attach( APCLocalArray::Make(APCArray::fromHandle(this))->asArrayData() ); case APCKind::SharedVec: return Variant::attach( APCArray::fromHandle(this)->toLocalVec() ); case APCKind::SharedDict: return Variant::attach( APCArray::fromHandle(this)->toLocalDict() ); case APCKind::SharedKeyset: return Variant::attach( APCArray::fromHandle(this)->toLocalKeyset() ); case APCKind::SerializedObject: { auto const serObj = APCString::fromHandle(this)->getStringData(); return apc_unserialize(serObj->data(), serObj->size()); } case APCKind::SharedCollection: return APCCollection::fromHandle(this)->createObject(); case APCKind::SharedObject: return APCObject::MakeLocalObject(this); } not_reached(); }
Variant MySQLResult::getField(int64_t field) const { if (!m_localized || field < 0 || field >= (int64_t)m_current_row->size()) { return init_null(); } return (*m_current_row)[field]; }
/* SOAP client calls this function to parse response from SOAP server */ bool parse_packet_soap(SoapClient *obj, const char *buffer, int buffer_size, std::shared_ptr<sdlFunction> fn, const char *fn_name, Variant &return_value, Array& soap_headers) { char* envelope_ns = nullptr; xmlNodePtr trav, env, head, body, resp, cur, fault; xmlAttrPtr attr; int param_count = 0; int soap_version = SOAP_1_1; sdlSoapBindingFunctionHeaderMap *hdrs = nullptr; assert(return_value.asTypedValue()->m_type == KindOfUninit); return_value.asTypedValue()->m_type = KindOfNull; /* 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) != nullptr) { add_soap_fault(obj, "Client", "DTD are not supported by SOAP"); xmlFreeDoc(response); return false; } /* Get <Envelope> element */ env = nullptr; trav = response->children; while (trav != nullptr) { 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 == nullptr) { add_soap_fault(obj, "Client", "looks like we got XML without \"Envelope\" element"); xmlFreeDoc(response); return false; } attr = env->properties; while (attr != nullptr) { if (attr->ns == nullptr) { 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 = nullptr; trav = env->children; while (trav != nullptr && trav->type != XML_ELEMENT_NODE) { trav = trav->next; } if (trav != nullptr && node_is_equal_ex(trav,"Header",envelope_ns)) { head = trav; trav = trav->next; } /* Get <Body> element */ body = nullptr; while (trav != nullptr && trav->type != XML_ELEMENT_NODE) { trav = trav->next; } if (trav != nullptr && node_is_equal_ex(trav,"Body",envelope_ns)) { body = trav; trav = trav->next; } while (trav != nullptr && trav->type != XML_ELEMENT_NODE) { trav = trav->next; } if (body == nullptr) { add_soap_fault(obj, "Client", "Body must be present in a SOAP envelope"); xmlFreeDoc(response); return false; } attr = body->properties; while (attr != nullptr) { if (attr->ns == nullptr) { 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 != nullptr && 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 != nullptr) { attr = head->properties; while (attr != nullptr) { if (attr->ns == nullptr) { 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 != nullptr) { char *faultcode = nullptr; String faultstring, faultactor; Variant details; xmlNodePtr tmp; if (soap_version == SOAP_1_1) { tmp = get_node(fault->children, "faultcode"); if (tmp != nullptr && tmp->children != nullptr) { faultcode = (char*)tmp->children->content; } tmp = get_node(fault->children, "faultstring"); if (tmp != nullptr && tmp->children != nullptr) { Variant zv = master_to_zval(get_conversion(KindOfString), tmp); faultstring = zv.toString(); } tmp = get_node(fault->children, "faultactor"); if (tmp != nullptr && tmp->children != nullptr) { Variant zv = master_to_zval(get_conversion(KindOfString), tmp); faultactor = zv.toString(); } tmp = get_node(fault->children, "detail"); if (tmp != nullptr) { details = master_to_zval(encodePtr(), tmp); } } else { tmp = get_node(fault->children, "Code"); if (tmp != nullptr && tmp->children != nullptr) { tmp = get_node(tmp->children, "Value"); if (tmp != nullptr && tmp->children != nullptr) { faultcode = (char*)tmp->children->content; } } tmp = get_node(fault->children,"Reason"); if (tmp != nullptr && tmp->children != nullptr) { /* TODO: lang attribute */ tmp = get_node(tmp->children,"Text"); if (tmp != nullptr && tmp->children != nullptr) { Variant zv = master_to_zval(get_conversion(KindOfString), tmp); faultstring = zv.toString(); } } tmp = get_node(fault->children,"Detail"); if (tmp != nullptr) { details = master_to_zval(encodePtr(), tmp); } } obj->m_soap_fault = 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 != nullptr && resp->type != XML_ELEMENT_NODE) { resp = resp->next; } if (resp != nullptr) { if (fn && fn->binding && fn->binding->bindingType == BINDING_SOAP) { /* Function has WSDL description */ sdlParamPtr h_param, param; xmlNodePtr val = nullptr; const char *name, *ns = nullptr; Variant tmp(Variant::NullInit{}); 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 == nullptr) { val = get_node(cur->children, "return"); } if (val == nullptr) { val = get_node(cur->children, "result"); } if (val == nullptr && cur->children && !cur->children->next) { val = cur->children; } } } } if (!val) { /* TODO: may be "nil" is not OK? */ /* add_soap_fault(obj, "Client", "Can't find response data"); xmlFreeDoc(response); return false; */ } else { /* Decoding value of parameter */ if (param != nullptr) { tmp = master_to_zval(param->encode, val); } else { tmp = master_to_zval(encodePtr(), val); } } return_value.toArrRef().set(String(param->paramName), tmp); param_count++; } } } else { /* Function hasn't WSDL description */ xmlNodePtr val; val = resp->children; while (val != nullptr) { while (val && val->type != XML_ELEMENT_NODE) { val = val->next; } if (val != nullptr) { 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.toCArrRef().exists(key)) { auto& lval = return_value.toArrRef().lvalAt(key); if (!lval.isArray()) lval = lval.toArray(); lval.toArrRef().append(tmp); } else if (val->next && get_node(val->next, (char*)val->name)) { Array arr = Array::Create(); arr.append(tmp); return_value.toArrRef().set(key, arr); } else { return_value.toArrRef().set(key, tmp); } } else { return_value.toArrRef().append(tmp); } ++param_count; } val = val->next; } } } } if (return_value.isArray()) { if (param_count == 0) { return_value = init_null(); } 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()) { std::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; }