Array f_hphp_get_status() { std::string out; ServerStats::ReportStatus(out, ServerStats::Format::JSON); return HHVM_FN(json_decode)(String(out)).toArray(); }
void XDebugServer::parseInput(folly::StringPiece in, String& cmd, Array& args) { // Always start with a blank array args = Array::Create(); // Find the first space in the command. Everything before is assumed to be the // command string auto ptr = strchr(const_cast<char*>(in.data()), ' '); if (ptr != nullptr) { size_t size = ptr - in.data(); cmd = String::attach(StringData::Make(in.data(), size, CopyString)); } else if (in[0] != '\0') { // There are no spaces, the entire string is the command cmd = String::attach(StringData::Make(in.data(), CopyString)); return; } else { throw_exn(Error::Parse); } // Loop starting after the space until the end of the string char opt; bool escaped = false; char* value = nullptr; ParseState state = ParseState::NORMAL; do { ptr++; switch (state) { // A new option which is prefixed with "-" is expected case ParseState::NORMAL: if (*ptr != '-') { throw_exn(Error::Parse); } else { state = ParseState::OPT_FOLLOWS; } break; // The option key follows case ParseState::OPT_FOLLOWS: opt = *ptr; state = ParseState::SEP_FOLLOWS; break; // Expect a " " separator to follow case ParseState::SEP_FOLLOWS: if (*ptr != ' ') { throw_exn(Error::Parse); } else { state = ParseState::VALUE_FOLLOWS_FIRST_CHAR; value = ptr + 1; } break; // Expect the option value's first character to follow. This character // could be either '"'or '-' case ParseState::VALUE_FOLLOWS_FIRST_CHAR: if (*ptr == '"' && opt != '-') { value = ptr + 1; state = ParseState::QUOTED; } else { state = ParseState::VALUE_FOLLOWS; } break; // The option's value should follow case ParseState::VALUE_FOLLOWS: if ((*ptr == ' ' && opt != '-') || *ptr == '\0') { if (args[opt].isNull()) { size_t size = ptr - value; StringData* val_data = StringData::Make(value, size, CopyString); args.set(opt, String::attach(val_data)); state = ParseState::NORMAL; } else { throw_exn(Error::DupArg); } } break; // State when we are within a quoted string case ParseState::QUOTED: // if the quote is escaped, remain in ParseState::QUOTED. This // will also handle other escaped chars, or an instance of // an escaped slash followed by a quote: \\" if (*ptr == '\\') { escaped = !escaped; break; } else if (*ptr != '"') { break; } else if (escaped) { escaped = false; break; } // Need to strip slashes before adding option if (args[opt].isNull()) { size_t size = ptr - value; StringData* val_data = StringData::Make(value, size, CopyString); args.set(opt, HHVM_FN(stripcslashes)(String::attach(val_data))); state = ParseState::SKIP_CHAR; } else { throw_exn(Error::DupArg); } break; // Do nothing case ParseState::SKIP_CHAR: state = ParseState::NORMAL; break; } } while (*ptr != '\0'); }
void HHVM_FUNCTION(header, const String& str, bool replace /* = true */, int http_response_code /* = 0 */) { if (HHVM_FN(headers_sent)()) { raise_warning("Cannot modify header information - headers already sent"); } String header = f_rtrim(str); // new line safety check // NOTE: PHP actually allows "\n " and "\n\t" to fall through. Is that bad // for security? if (header.find('\n') >= 0 || header.find('\r') >= 0) { raise_warning("Header may not contain more than a single header, " "new line detected"); return; } Transport *transport = g_context->getTransport(); if (transport && header.size()) { const char *header_line = header.data(); // handle single line of status code if (header.size() >= 5 && strncasecmp(header_line, "HTTP/", 5) == 0) { int code = 200; const char *reason = nullptr; for (const char *ptr = header_line; *ptr; ptr++) { if (*ptr == ' ' && *(ptr + 1) != ' ') { code = atoi(ptr + 1); for (ptr++; *ptr; ptr++) { if (*ptr == ' ' && *(ptr + 1) != ' ') { reason = ptr + 1; break; } } break; } } if (code) { transport->setResponse(code, reason); } return; } const char *colon_offset = strchr(header_line, ':'); String newHeader; if (colon_offset) { if (!strncasecmp(header_line, "Content-Type", colon_offset - header_line)) { const char *ptr = colon_offset+1, *mimetype = NULL; while (*ptr == ' ') ptr++; mimetype = ptr; if (strncmp(mimetype, "text/", 5) == 0 && strstr(mimetype, "charset=") == NULL) { newHeader = header + ";charset=utf-8"; } } } if (replace) { transport->replaceHeader(newHeader.empty() ? header : newHeader); } else { transport->addHeader(newHeader.empty() ? header : newHeader); } if (http_response_code) { transport->setResponse(http_response_code, "explicit_header_response_code"); } } }
int64_t HHVM_FUNCTION(connection_aborted) { return HHVM_FN(connection_status)() == k_CONNECTION_ABORTED; }
void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, const Variant& value, const Array& fieldspec) { // At this point the typeID (and field num, if applicable) should've already // been written to the output so all we need to do is write the payload. switch (thrift_typeID) { case T_STOP: case T_VOID: return; case T_STRUCT: { if (!value.is(KindOfObject)) { throw_tprotocolexception("Attempt to send non-object " "type as a T_STRUCT", INVALID_DATA); } binary_serialize_spec(value.toObject(), transport, HHVM_FN(hphp_get_static_property)(value.toObject()-> getClassName(), s_TSPEC, false).toArray()); } return; case T_BOOL: transport.writeI8(value.toBoolean() ? 1 : 0); return; case T_BYTE: transport.writeI8(value.toByte()); return; case T_I16: transport.writeI16(value.toInt16()); return; case T_I32: transport.writeI32(value.toInt32()); return; case T_I64: case T_U64: transport.writeI64(value.toInt64()); return; case T_DOUBLE: { union { int64_t c; double d; } a; a.d = value.toDouble(); transport.writeI64(a.c); } return; case T_FLOAT: { union { int32_t c; float d; } a; a.d = (float)value.toDouble(); transport.writeI32(a.c); } return; //case T_UTF7: case T_UTF8: case T_UTF16: case T_STRING: { String sv = value.toString(); transport.writeString(sv.data(), sv.size()); } return; case T_MAP: { Array ht = value.toArray(); uint8_t keytype = fieldspec.rvalAt(PHPTransport::s_ktype, AccessFlags::Error_Key).toByte(); transport.writeI8(keytype); uint8_t valtype = fieldspec.rvalAt(PHPTransport::s_vtype, AccessFlags::Error_Key).toByte(); transport.writeI8(valtype); Array valspec = fieldspec.rvalAt(PHPTransport::s_val, AccessFlags::Error_Key).toArray(); transport.writeI32(ht.size()); for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) { binary_serialize_hashtable_key(keytype, transport, key_ptr.first()); binary_serialize(valtype, transport, key_ptr.second(), valspec); } } return; case T_LIST: { Array ht = value.toArray(); Variant val; uint8_t valtype = fieldspec.rvalAt(PHPTransport::s_etype, AccessFlags::Error_Key).toInt64(); transport.writeI8(valtype); Array valspec = fieldspec.rvalAt(PHPTransport::s_elem, AccessFlags::Error_Key).toArray(); transport.writeI32(ht.size()); for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) { binary_serialize(valtype, transport, key_ptr.second(), valspec); } } return; case T_SET: { Array ht = value.toArray(); uint8_t keytype = fieldspec.rvalAt(PHPTransport::s_etype, AccessFlags::Error_Key).toByte(); transport.writeI8(keytype); transport.writeI32(ht.size()); for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) { binary_serialize_hashtable_key(keytype, transport, key_ptr.first()); } } return; }; char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA); }
bool HHVM_FUNCTION(bzclose, const Resource& bz) { return HHVM_FN(fclose)(bz); }
Variant HHVM_FUNCTION(bzwrite, const Resource& bz, const String& data, int length /* = 0 */) { return HHVM_FN(fwrite)(bz, data, length); }
bool PDOSqliteStatement::paramHook(PDOBoundParam* param, PDOParamEvent event_type) { switch (event_type) { case PDO_PARAM_EVT_EXEC_PRE: if (executed && !m_done) { sqlite3_reset(m_stmt); m_done = 1; } if (param->is_param) { if (param->paramno == -1) { param->paramno = sqlite3_bind_parameter_index(m_stmt, param->name.c_str()) - 1; } switch (PDO_PARAM_TYPE(param->param_type)) { case PDO_PARAM_STMT: return false; case PDO_PARAM_NULL: if (sqlite3_bind_null(m_stmt, param->paramno + 1) == SQLITE_OK) { return true; } handleError(__FILE__, __LINE__); return false; case PDO_PARAM_INT: case PDO_PARAM_BOOL: if (param->parameter.isNull()) { if (sqlite3_bind_null(m_stmt, param->paramno + 1) == SQLITE_OK) { return true; } } else { if (SQLITE_OK == sqlite3_bind_int(m_stmt, param->paramno + 1, param->parameter.toInt64())) { return true; } } handleError(__FILE__, __LINE__); return false; case PDO_PARAM_LOB: if (param->parameter.isResource()) { Variant buf = HHVM_FN(stream_get_contents)( param->parameter.toResource()); if (!same(buf, false)) { param->parameter = buf; } else { pdo_raise_impl_error(dbh, this, "HY105", "Expected a stream resource"); return false; } } else if (param->parameter.isNull()) { if (sqlite3_bind_null(m_stmt, param->paramno + 1) == SQLITE_OK) { return true; } handleError(__FILE__, __LINE__); return false; } { String sparam = param->parameter.toString(); if (SQLITE_OK == sqlite3_bind_blob(m_stmt, param->paramno + 1, sparam.data(), sparam.size(), SQLITE_STATIC)) { return true; } } handleError(__FILE__, __LINE__); return false; case PDO_PARAM_STR: default: if (param->parameter.isNull()) { if (sqlite3_bind_null(m_stmt, param->paramno + 1) == SQLITE_OK) { return true; } } else { String sparam = param->parameter.toString(); if (SQLITE_OK == sqlite3_bind_text(m_stmt, param->paramno + 1, sparam.data(), sparam.size(), SQLITE_STATIC)) { return true; } } handleError(__FILE__, __LINE__); return false; } } break; default:; } return true; }
static void url_encode_array(StringBuffer &ret, const Variant& varr, std::set<void*> &seen_arrs, const String& num_prefix, const String& key_prefix, const String& key_suffix, const String& arg_sep, bool encode_plus = true) { void *id = varr.isArray() ? (void*)varr.getArrayData() : (void*)varr.getObjectData(); if (!seen_arrs.insert(id).second) { return; // recursive } // Allow multiple non-recursive references to the same array/object SCOPE_EXIT { seen_arrs.erase(id); }; Array arr; if (varr.is(KindOfObject)) { Object o = varr.toObject(); arr = o->isCollection() ? varr.toArray() : HHVM_FN(get_object_vars(o)); } else { arr = varr.toArray(); } for (ArrayIter iter(arr); iter; ++iter) { Variant data = iter.second(); if (data.isNull() || data.isResource()) continue; String key = iter.first(); bool numeric = key.isNumeric(); if (data.isArray() || data.is(KindOfObject)) { String encoded; if (numeric) { encoded = key; } else { encoded = StringUtil::UrlEncode(key, encode_plus); } StringBuffer new_prefix(key_prefix.size() + num_prefix.size() + encoded.size() + key_suffix.size() + 4); new_prefix.append(key_prefix); if (numeric) new_prefix.append(num_prefix); new_prefix.append(encoded); new_prefix.append(key_suffix); new_prefix.append("%5B"); url_encode_array(ret, data, seen_arrs, String(), new_prefix.detach(), String("%5D", CopyString), arg_sep); } else { if (!ret.empty()) { ret.append(arg_sep); } ret.append(key_prefix); if (numeric) { ret.append(num_prefix); ret.append(key); } else { ret.append(StringUtil::UrlEncode(key, encode_plus)); } ret.append(key_suffix); ret.append("="); if (data.isInteger() || data.is(KindOfBoolean)) { ret.append(String(data.toInt64())); } else if (data.is(KindOfDouble)) { ret.append(String(data.toDouble())); } else { ret.append(StringUtil::UrlEncode(data.toString(), encode_plus)); } } } }
TypedValue HHVM_FUNCTION(json_decode, const String& json, bool assoc, int64_t depth, int64_t options) { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); if (json.empty()) { return make_tv<KindOfNull>(); } const int64_t supported_options = k_JSON_FB_LOOSE | k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS | k_JSON_BIGINT_AS_STRING | k_JSON_FB_HACK_ARRAYS; int64_t parser_options = options & supported_options; Variant z; const auto ok = JSON_parser(z, json.data(), json.size(), assoc, depth, parser_options); if (UNLIKELY(StructuredLog::coinflip(RuntimeOption::EvalSerDesSampleRate))) { StructuredLog::logSerDes("json", "des", json, z); } if (ok) { return tvReturn(std::move(z)); } String trimmed = HHVM_FN(trim)(json, "\t\n\r "); if (trimmed.size() == 4) { if (!strcasecmp(trimmed.data(), "null")) { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); return make_tv<KindOfNull>(); } if (!strcasecmp(trimmed.data(), "true")) { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); return make_tv<KindOfBoolean>(true); } } else if (trimmed.size() == 5 && !strcasecmp(trimmed.data(), "false")) { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); return make_tv<KindOfBoolean>(false); } int64_t p; double d; DataType type = json.get()->isNumericWithVal(p, d, 0); if (type == KindOfInt64) { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); return make_tv<KindOfInt64>(p); } else if (type == KindOfDouble) { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); if ((options & k_JSON_BIGINT_AS_STRING) && (json.toInt64() == LLONG_MAX || json.toInt64() == LLONG_MIN) && errno == ERANGE) { // Overflow bool is_float = false; for (int i = (trimmed[0] == '-' ? 1 : 0); i < trimmed.size(); ++i) { if (trimmed[i] < '0' || trimmed[i] > '9') { is_float = true; break; } } if (!is_float) { return tvReturn(trimmed); } } return make_tv<KindOfDouble>(d); } char ch0 = json.charAt(0); if (json.size() > 1 && ch0 == '"' && json.charAt(json.size() - 1) == '"') { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); // Wrap the string in an array to allow the JSON_parser to handle // things like unicode escape sequences, then unwrap to get result String wrapped("["); wrapped += json + "]"; // Stick to a normal hhvm array for the wrapper const int64_t mask = ~(k_JSON_FB_COLLECTIONS | k_JSON_FB_STABLE_MAPS); if (JSON_parser(z, wrapped.data(), wrapped.size(), false, depth, parser_options & mask) && z.isArray()) { Array arr = z.toArray(); if ((arr.size() == 1) && arr.exists(0)) { return tvReturn(arr[0]); } // The input string could be something like: "foo","bar" // Which will parse inside the [] wrapper, but be invalid json_set_last_error_code(json_error_codes::JSON_ERROR_SYNTAX); } } if ((options & k_JSON_FB_LOOSE) && json.size() > 1 && ch0 == '\'' && json.charAt(json.size() - 1) == '\'') { json_set_last_error_code(json_error_codes::JSON_ERROR_NONE); return tvReturn(json.substr(1, json.size() - 2)); } assert(json_get_last_error_code() != json_error_codes::JSON_ERROR_NONE); return make_tv<KindOfNull>(); }
static Variant eval_for_assert(ActRec* const curFP, const String& codeStr) { String prefixedCode = concat3("<?php return ", codeStr, ";"); auto const oldErrorLevel = s_option_data->assertQuietEval ? HHVM_FN(error_reporting)(Variant(0)) : 0; SCOPE_EXIT { if (s_option_data->assertQuietEval) HHVM_FN(error_reporting)(oldErrorLevel); }; auto const unit = g_context->compileEvalString(prefixedCode.get()); if (unit == nullptr) { raise_recoverable_error("Syntax error in assert()"); // Failure to compile the eval string doesn't count as an // assertion failure. return Variant(true); } if (!(curFP->func()->attrs() & AttrMayUseVV)) { throw_not_supported("assert()", "assert called from non-varenv function"); } if (!curFP->hasVarEnv()) { curFP->setVarEnv(VarEnv::createLocal(curFP)); } auto varEnv = curFP->getVarEnv(); if (curFP != vmfp()) { // If we aren't using FCallBuiltin, the stack frame of the call to assert // will be in middle of the code we are about to eval and our caller, whose // varEnv we want to use. The invokeFunc below will get very confused if // this is the case, since it will be using a varEnv that belongs to the // wrong function on the stack. So, we rebind it here, to match what // invokeFunc will expect. assert(!vmfp()->hasVarEnv()); vmfp()->setVarEnv(varEnv); varEnv->enterFP(curFP, vmfp()); } ObjectData* thiz = nullptr; Class* cls = nullptr; Class* ctx = curFP->func()->cls(); if (ctx) { if (curFP->hasThis()) { thiz = curFP->getThis(); cls = thiz->getVMClass(); } else { cls = curFP->getClass(); } } auto const func = unit->getMain(ctx); return Variant::attach( g_context->invokeFunc( func, init_null_variant, thiz, cls, varEnv, nullptr, ExecutionContext::InvokePseudoMain ) ); }
// Grab the ip address and port of the client that is connected to this proxy. bool DebuggerProxy::getClientConnectionInfo(VRefParam address, VRefParam port) { Resource s(m_thrift.getSocket().get()); return HHVM_FN(socket_getpeername)(s, address, port); }
bool HHVM_FUNCTION(trigger_error, const String& error_msg, int error_type /* = k_E_USER_NOTICE */) { std::string msg = error_msg.data(); // not toCppString() if (UNLIKELY(g_context->getThrowAllErrors())) { throw Exception(folly::sformat("throwAllErrors: {}", error_type)); } if (error_type == k_E_USER_ERROR) { g_context->handleError(msg, error_type, true, ExecutionContext::ErrorThrowMode::IfUnhandled, "\nFatal error: "); return true; } if (error_type == k_E_USER_WARNING) { g_context->handleError(msg, error_type, true, ExecutionContext::ErrorThrowMode::Never, "\nWarning: "); return true; } if (error_type == k_E_USER_NOTICE) { g_context->handleError(msg, error_type, true, ExecutionContext::ErrorThrowMode::Never, "\nNotice: "); return true; } if (error_type == k_E_USER_DEPRECATED) { g_context->handleError(msg, error_type, true, ExecutionContext::ErrorThrowMode::Never, "\nDeprecated: "); return true; } if (error_type == k_E_STRICT) { // So that we can raise strict warnings for mismatched // params in FCallBuiltin raise_strict_warning(msg); return true; } ActRec* fp = g_context->getStackFrame(); if (fp->m_func->isNative() && fp->m_func->nativeFuncPtr() == (BuiltinFunction)HHVM_FN(trigger_error)) { fp = g_context->getOuterVMFrame(fp); } if (fp && fp->m_func->isBuiltin()) { if (error_type == k_E_ERROR) { raise_error_without_first_frame(msg); return true; } if (error_type == k_E_WARNING) { raise_warning_without_first_frame(msg); return true; } if (error_type == k_E_NOTICE) { raise_notice_without_first_frame(msg); return true; } if (error_type == k_E_DEPRECATED) { raise_deprecated_without_first_frame(msg); return true; } if (error_type == k_E_RECOVERABLE_ERROR) { raise_recoverable_error_without_first_frame(msg); return true; } } raise_warning("Invalid error type specified"); return false; }
bool TestCppBase::TestString() { // constructors { VS(String(15).c_str(), "15"); VS(String(-15).c_str(), "-15"); VS(String(int64_t(12345678912345678LL)).c_str(), "12345678912345678"); VS(String(int64_t(-12345678912345678LL)).c_str(), "-12345678912345678"); VS(String(5.603).c_str(), "5.603"); VS(String("test").c_str(), "test"); VS(String(String("test")).c_str(), "test"); } // informational { VERIFY(String().isNull()); VERIFY(!String("").isNull()); VERIFY(String().empty()); VERIFY(String("").empty()); VERIFY(!String("test").empty()); VERIFY(String().size() == 0); VERIFY(String().length() == 0); VERIFY(String("").size() == 0); VERIFY(String("").length() == 0); VERIFY(String("test").size() == 4); VERIFY(String("test").length() == 4); VERIFY(!String("2test").isNumeric()); VERIFY(!String("2test").isInteger()); VERIFY(!String("test").isNumeric()); VERIFY(!String("test").isInteger()); VERIFY(String("23").isNumeric()); VERIFY(String("23").isInteger()); VERIFY(String("23.3").isNumeric()); VERIFY(!String("23.3").isInteger()); } // operators { String s; s = "test1"; VS(s.c_str(), "test1"); s = String("test2"); VS(s.c_str(), "test2"); s = Variant("test3"); VS(s.c_str(), "test3"); s = String("a") + "b"; VS(s.c_str(), "ab"); s = String("c") + String("d"); VS(s.c_str(), "cd"); s += "efg"; VS(s.c_str(), "cdefg"); s += String("hij"); VS(s.c_str(), "cdefghij"); } // manipulations { String s = HHVM_FN(strtolower)("Test"); VS(s.c_str(), "test"); } // conversions { VERIFY(!String().toBoolean()); VERIFY(String("123").toBoolean()); VERIFY(String("123").toByte() == 123); VERIFY(String("32767").toInt16() == 32767); VERIFY(String("1234567890").toInt32() == 1234567890); VERIFY(String("123456789012345678").toInt64() == 123456789012345678LL); VERIFY(String("123.45").toDouble() == 123.45); } return Count(true); }
bool TestExtCurl::test_curl_multi_getcontent() { Resource mh = HHVM_FN(curl_multi_init)(); Variant c1 = HHVM_FN(curl_init)(String(get_request_uri())); Variant c2 = HHVM_FN(curl_init)(String(get_request_uri())); HHVM_FN(curl_setopt)(c1.toResource(), k_CURLOPT_RETURNTRANSFER, true); HHVM_FN(curl_setopt)(c2.toResource(), k_CURLOPT_RETURNTRANSFER, true); HHVM_FN(curl_multi_add_handle)(mh, c1.toResource()); HHVM_FN(curl_multi_add_handle)(mh, c2.toResource()); Variant still_running; do { HHVM_FN(curl_multi_exec)(mh, ref(still_running)); } while (more(still_running, 0)); VS(HHVM_FN(curl_multi_getcontent)(c1.toResource()), "OK"); VS(HHVM_FN(curl_multi_getcontent)(c1.toResource()), "OK"); VS(HHVM_FN(curl_multi_getcontent)(c2.toResource()), "OK"); VS(HHVM_FN(curl_multi_getcontent)(c2.toResource()), "OK"); return Count(true); }
static void xslt_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) { XSLTProcessorData *intern = nullptr; int error = 0; xsltTransformContextPtr tctxt = xsltXPathGetTransformContext (ctxt); if (tctxt == nullptr) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the transformation context\n" ); error = 1; } else { intern = (XSLTProcessorData*)tctxt->_private; if (intern == nullptr) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: failed to get the internal object\n" ); error = 1; } else { if (intern->m_registerPhpFunctions == 0) { xsltGenericError(xsltGenericErrorContext, "xsltExtFunctionTest: PHP Object did not register PHP functions\n" ); error = 1; } } } xmlXPathObjectPtr obj; if (error == 1) { for (int i = nargs - 1; i >= 0; i--) { obj = valuePop(ctxt); xmlXPathFreeObject(obj); } return; } Array args; // Reverse order to pop values off ctxt stack for (int i = nargs - 2; i >= 0; i--) { Variant arg; obj = valuePop(ctxt); switch (obj->type) { case XPATH_STRING: arg = String((char*)obj->stringval, CopyString); break; case XPATH_BOOLEAN: arg = (bool)obj->boolval; break; case XPATH_NUMBER: arg = (double)obj->floatval; break; case XPATH_NODESET: if (type == 1) { char *str = (char*)xmlXPathCastToString(obj); arg = String(str, CopyString); xmlFree(str); } else if (type == 2) { arg = Array::Create(); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { for (int j = 0; j < obj->nodesetval->nodeNr; j++) { // TODO: not sure this is the right thing to do. xmlNodePtr node = obj->nodesetval->nodeTab[j]; if (node->type == XML_ELEMENT_NODE) { Object element = newNode(s_DOMElement, xmlCopyNode(node, /*extended*/ 1)); arg.toArrRef().append(element); } else if (node->type == XML_ATTRIBUTE_NODE) { Object attribute = newNode(s_DOMAttr, (xmlNodePtr)xmlCopyProp(nullptr, (xmlAttrPtr)node)); arg.toArrRef().append(attribute); } else if (node->type == XML_TEXT_NODE) { Object text = newNode(s_DOMText, (xmlNodePtr)xmlNewText(xmlNodeGetContent(node))); arg.toArrRef().append(text); } else { raise_warning("Unhandled node type '%d'", node->type); // Use a generic DOMNode as fallback for now. Object nodeobj = newNode(s_DOMNode, xmlCopyNode(node, /*extended*/ 1)); arg.toArrRef().append(nodeobj); } } } } break; default: arg = String((char*)xmlXPathCastToString(obj), CopyString); } xmlXPathFreeObject(obj); args.prepend(arg); } obj = valuePop(ctxt); if (obj->stringval == nullptr) { raise_warning("Handler name must be a string"); xmlXPathFreeObject(obj); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); return; } String handler((char*)obj->stringval, CopyString); xmlXPathFreeObject(obj); if (!HHVM_FN(is_callable)(handler)) { raise_warning("Unable to call handler %s()", handler.data()); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else if (intern->m_registerPhpFunctions == 2 && !intern->m_registered_phpfunctions.exists(handler)) { raise_warning("Not allowed to call handler '%s()'", handler.data()); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else { Variant retval = vm_call_user_func(handler, args); if (retval.isObject() && retval.getObjectData()->instanceof(s_DOMNode)) { ObjectData *retval_data = retval.asCObjRef().get(); xmlNode* nodep = Native::data<DOMNode>(retval_data)->nodep(); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); intern->m_usedElements.prepend(retval); } else if (retval.is(KindOfBoolean)) { valuePush(ctxt, xmlXPathNewBoolean(retval.toBoolean())); } else if (retval.isObject()) { raise_warning("A PHP Object cannot be converted to an XPath-string"); // Push an empty string to get an xslt result. valuePush(ctxt, xmlXPathNewString((xmlChar*)"")); } else { String sretval = retval.toString(); valuePush(ctxt, xmlXPathNewString((xmlChar*)sretval.data())); } } }
bool HHVM_FUNCTION(user_error, const String& error_msg, int error_type /* = k_E_USER_NOTICE */) { return HHVM_FN(trigger_error)(error_msg, error_type); }
static Variant new_socket_connect(const HostURL &hosturl, double timeout, Variant &errnum, Variant &errstr) { int domain = AF_UNSPEC; int type = SOCK_STREAM; auto const& scheme = hosturl.getScheme(); SmartPtr<Socket> sock; SmartPtr<SSLSocket> sslsock; std::string sockerr; int error; if (scheme == "udp" || scheme == "udg") { type = SOCK_DGRAM; } else if (scheme == "unix") { domain = AF_UNIX; } int fd = -1; if (domain == AF_UNIX) { sockaddr_storage sa_storage; struct sockaddr *sa_ptr; size_t sa_size; fd = socket(domain, type, 0); sock = makeSmartPtr<Socket>( fd, domain, hosturl.getHost().c_str(), hosturl.getPort()); if (!set_sockaddr(sa_storage, sock, hosturl.getHost().c_str(), hosturl.getPort(), sa_ptr, sa_size)) { // set_sockaddr raises its own warning on failure return false; } if (connect_with_timeout(fd, sa_ptr, sa_size, timeout, hosturl, sockerr, error) != 0) { SOCKET_ERROR(sock, sockerr.c_str(), error); errnum = sock->getLastError(); errstr = HHVM_FN(socket_strerror)(sock->getLastError()); return false; } } else { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = domain; hints.ai_socktype = type; auto port = folly::to<std::string>(hosturl.getPort()); auto host = hosturl.getHost(); struct addrinfo *aiHead; int errcode = getaddrinfo(host.c_str(), port.c_str(), &hints, &aiHead); if (errcode != 0) { errstr = String(gai_strerror(errcode), CopyString); return false; } SCOPE_EXIT { freeaddrinfo(aiHead); }; for (struct addrinfo *ai = aiHead; ai != nullptr; ai = ai->ai_next) { domain = ai->ai_family; fd = socket(domain, ai->ai_socktype, ai->ai_protocol); if (fd == -1) { continue; } if (connect_with_timeout(fd, ai->ai_addr, ai->ai_addrlen, timeout, hosturl, sockerr, error) == 0) { break; } close(fd); fd = -1; } sslsock = SSLSocket::Create(fd, domain, hosturl, timeout); if (sslsock) { sock = sslsock; } else { sock = makeSmartPtr<Socket>(fd, domain, hosturl.getHost().c_str(), hosturl.getPort()); } } if (!sock->valid()) { SOCKET_ERROR(sock, sockerr.empty() ? "unable to create socket" : sockerr.c_str(), error); errnum = sock->getLastError(); errstr = HHVM_FN(socket_strerror)(sock->getLastError()); return false; } if (sslsock && !sslsock->onConnect()) { raise_warning("Failed to enable crypto"); return false; } return Variant(std::move(sock)); }
Variant HHVM_FUNCTION(bzread, const Resource& bz, int length /* = 1024 */) { return HHVM_FN(fread)(bz, length); }
Variant HHVM_FUNCTION(ob_get_contents) { if (HHVM_FN(ob_get_level)() == 0) { return false; } return g_context->obCopyContents(); }
void StandardExtension::initMisc() { HHVM_FALIAS(HH\\server_warmup_status, server_warmup_status); HHVM_FE(connection_aborted); HHVM_FE(connection_status); HHVM_FE(connection_timeout); HHVM_FE(constant); HHVM_FE(define); HHVM_FE(defined); HHVM_FE(ignore_user_abort); HHVM_FE(pack); HHVM_FE(sleep); HHVM_FE(usleep); HHVM_FE(time_nanosleep); HHVM_FE(time_sleep_until); HHVM_FE(uniqid); HHVM_FE(unpack); HHVM_FE(sys_getloadavg); HHVM_FE(token_get_all); HHVM_FE(token_name); HHVM_FE(hphp_to_string); HHVM_FALIAS(__SystemLib\\max2, SystemLib_max2); HHVM_FALIAS(__SystemLib\\min2, SystemLib_min2); HHVM_RC_INT(PHP_MAXPATHLEN, PATH_MAX); Native::registerConstant<KindOfBoolean>(makeStaticString("PHP_DEBUG"), #if DEBUG true #else false #endif ); bindTokenConstants(); HHVM_RC_INT(T_PAAMAYIM_NEKUDOTAYIM, get_user_token_id(T_DOUBLE_COLON)); HHVM_RC_INT(UPLOAD_ERR_OK, 0); HHVM_RC_INT(UPLOAD_ERR_INI_SIZE, 1); HHVM_RC_INT(UPLOAD_ERR_FORM_SIZE, 2); HHVM_RC_INT(UPLOAD_ERR_PARTIAL, 3); HHVM_RC_INT(UPLOAD_ERR_NO_FILE, 4); HHVM_RC_INT(UPLOAD_ERR_NO_TMP_DIR, 6); HHVM_RC_INT(UPLOAD_ERR_CANT_WRITE, 7); HHVM_RC_INT(UPLOAD_ERR_EXTENSION, 8); HHVM_RC_INT(CREDITS_GROUP, 1 << 0); HHVM_RC_INT(CREDITS_GENERAL, 1 << 1); HHVM_RC_INT(CREDITS_SAPI, 1 << 2); HHVM_RC_INT(CREDITS_MODULES, 1 << 3); HHVM_RC_INT(CREDITS_DOCS, 1 << 4); HHVM_RC_INT(CREDITS_FULLPAGE, 1 << 5); HHVM_RC_INT(CREDITS_QA, 1 << 6); HHVM_RC_INT(CREDITS_ALL, 0xFFFFFFFF); HHVM_RC_INT(INI_SYSTEM, IniSetting::PHP_INI_SYSTEM); HHVM_RC_INT(INI_PERDIR, IniSetting::PHP_INI_PERDIR); HHVM_RC_INT(INI_USER, IniSetting::PHP_INI_USER); HHVM_RC_INT(INI_ALL, IniSetting::PHP_INI_SYSTEM | IniSetting::PHP_INI_PERDIR | IniSetting::PHP_INI_USER); HHVM_RC_STR(PHP_BINARY, current_executable_path()); HHVM_RC_STR(PHP_BINDIR, current_executable_directory()); HHVM_RC_STR(PHP_OS, HHVM_FN(php_uname)("s").toString().toCppString()); HHVM_RC_STR(PHP_SAPI, RuntimeOption::ExecutionMode); HHVM_RC_INT(PHP_INT_SIZE, sizeof(int64_t)); HHVM_RC_INT(PHP_INT_MIN, k_PHP_INT_MIN); HHVM_RC_INT(PHP_INT_MAX, k_PHP_INT_MAX); HHVM_RC_INT_SAME(PHP_MAJOR_VERSION); HHVM_RC_INT_SAME(PHP_MINOR_VERSION); HHVM_RC_INT_SAME(PHP_RELEASE_VERSION); HHVM_RC_STR_SAME(PHP_EXTRA_VERSION); HHVM_RC_STR_SAME(PHP_VERSION); HHVM_RC_INT_SAME(PHP_VERSION_ID); // FIXME: These values are hardcoded from their previous IDL values // Grab their correct values from the system as appropriate HHVM_RC_STR(PHP_EOL, "\n"); HHVM_RC_STR(PHP_CONFIG_FILE_PATH, ""); HHVM_RC_STR(PHP_CONFIG_FILE_SCAN_DIR, ""); HHVM_RC_STR(PHP_DATADIR, ""); HHVM_RC_STR(PHP_EXTENSION_DIR, ""); HHVM_RC_STR(PHP_LIBDIR, ""); HHVM_RC_STR(PHP_LOCALSTATEDIR, ""); HHVM_RC_STR(PHP_PREFIX, ""); HHVM_RC_STR(PHP_SHLIB_SUFFIX, "so"); HHVM_RC_STR(PHP_SYSCONFDIR, ""); HHVM_RC_STR(PEAR_EXTENSION_DIR, ""); HHVM_RC_STR(PEAR_INSTALL_DIR, ""); loadSystemlib("std_misc"); }
Array HHVM_FUNCTION(hphp_get_status) { std::string out; ServerStats::ReportStatus(out, Writer::Format::JSON); return Variant::attach(HHVM_FN(json_decode)(String(out))).toArray(); }
int64_t HHVM_FUNCTION(connection_timeout) { return HHVM_FN(connection_status)() == k_CONNECTION_TIMEOUT; }
bool TestExtCurl::test_curl_init() { Variant c = HHVM_FN(curl_init)(); VS(HHVM_FN(curl_errno)(c.toResource()), 0); VS(HHVM_FN(curl_error)(c.toResource()), ""); return Count(true); }
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(); }
bool TestExtCurl::test_curl_version() { Variant ret = HHVM_FN(curl_version)(); VERIFY(!ret.toArray()[s_protocols].toArray().empty()); return Count(true); }
virtual void moduleInit() { HHVM_NAMED_FE(HH\\autoload_set_paths, HHVM_FN(autoload_set_paths)); HHVM_NAMED_FE(HH\\could_include, HHVM_FN(could_include)); loadSystemlib(); }
bool TestExtCurl::test_curl_multi_init() { HHVM_FN(curl_multi_init)(); return Count(true); }
size_t check_request_surprise() { auto& info = TI(); auto& p = info.m_reqInjectionData; auto const flags = fetchAndClearSurpriseFlags(); auto const do_timedout = (flags & TimedOutFlag) && !p.getDebuggerAttached(); auto const do_memExceeded = flags & MemExceededFlag; auto const do_memThreshold = flags & MemThresholdFlag; auto const do_signaled = flags & SignaledFlag; auto const do_cpuTimedOut = (flags & CPUTimedOutFlag) && !p.getDebuggerAttached(); auto const do_GC = flags & PendingGCFlag; // Start with any pending exception that might be on the thread. auto pendingException = info.m_pendingException; info.m_pendingException = nullptr; if (do_timedout) { p.setCPUTimeout(0); // Stop CPU timer so we won't time out twice. if (pendingException) { setSurpriseFlag(TimedOutFlag); } else { pendingException = generate_request_timeout_exception(); } } // Don't bother with the CPU timeout if we're already handling a wall timeout. if (do_cpuTimedOut && !do_timedout) { p.setTimeout(0); // Stop wall timer so we won't time out twice. if (pendingException) { setSurpriseFlag(CPUTimedOutFlag); } else { pendingException = generate_request_cpu_timeout_exception(); } } if (do_memExceeded) { if (pendingException) { setSurpriseFlag(MemExceededFlag); } else { pendingException = generate_memory_exceeded_exception(); } } if (do_memThreshold) { clearSurpriseFlag(MemThresholdFlag); if (!g_context->m_memThresholdCallback.isNull()) { VMRegAnchor _; try { vm_call_user_func(g_context->m_memThresholdCallback, empty_array()); } catch (Object& ex) { raise_error("Uncaught exception escaping mem Threshold callback: %s", ex.toString().data()); } } } if (do_GC) { VMRegAnchor _; if (RuntimeOption::EvalEnableGC) { MM().collect("surprise"); } else { MM().checkHeap("surprise"); } } if (do_signaled) { HHVM_FN(pcntl_signal_dispatch)(); } if (pendingException) { pendingException->throwException(); } return flags; }
void StandardExtension::initMisc() { HHVM_FALIAS(HH\\server_warmup_status, server_warmup_status); HHVM_FE(connection_aborted); HHVM_FE(connection_status); HHVM_FE(connection_timeout); HHVM_FE(constant); HHVM_FE(define); HHVM_FE(defined); HHVM_FE(ignore_user_abort); HHVM_FE(pack); HHVM_FE(sleep); HHVM_FE(usleep); HHVM_FE(time_nanosleep); HHVM_FE(time_sleep_until); HHVM_FE(uniqid); HHVM_FE(unpack); HHVM_FE(sys_getloadavg); HHVM_FE(token_get_all); HHVM_FE(token_name); HHVM_FE(hphp_to_string); HHVM_FALIAS(__SystemLib\\max2, SystemLib_max2); HHVM_FALIAS(__SystemLib\\min2, SystemLib_min2); Native::registerConstant<KindOfDouble>(makeStaticString("INF"), k_INF); Native::registerConstant<KindOfDouble>(makeStaticString("NAN"), k_NAN); Native::registerConstant<KindOfInt64>( makeStaticString("PHP_MAXPATHLEN"), MAXPATHLEN); Native::registerConstant<KindOfBoolean>(makeStaticString("PHP_DEBUG"), #if DEBUG true #else false #endif ); bindTokenConstants(); Native::registerConstant<KindOfInt64>(s_T_PAAMAYIM_NEKUDOTAYIM.get(), get_user_token_id(T_DOUBLE_COLON)); HHVM_RC_STR(PHP_BINARY, current_executable_path()); HHVM_RC_STR(PHP_BINDIR, current_executable_directory()); HHVM_RC_STR(PHP_OS, HHVM_FN(php_uname)("s").toString().toCppString()); HHVM_RC_STR(PHP_SAPI, RuntimeOption::ExecutionMode); HHVM_RC_INT(PHP_INT_SIZE, sizeof(int64_t)); HHVM_RC_INT(PHP_INT_MIN, k_PHP_INT_MIN); HHVM_RC_INT(PHP_INT_MAX, k_PHP_INT_MAX); HHVM_RC_INT_SAME(PHP_MAJOR_VERSION); HHVM_RC_INT_SAME(PHP_MINOR_VERSION); HHVM_RC_INT_SAME(PHP_RELEASE_VERSION); HHVM_RC_STR_SAME(PHP_EXTRA_VERSION); HHVM_RC_STR_SAME(PHP_VERSION); HHVM_RC_INT_SAME(PHP_VERSION_ID); // FIXME: These values are hardcoded from their previous IDL values // Grab their correct values from the system as appropriate HHVM_RC_STR(PHP_EOL, "\n"); HHVM_RC_STR(PHP_CONFIG_FILE_PATH, ""); HHVM_RC_STR(PHP_CONFIG_FILE_SCAN_DIR, ""); HHVM_RC_STR(PHP_DATADIR, ""); HHVM_RC_STR(PHP_EXTENSION_DIR, ""); HHVM_RC_STR(PHP_LIBDIR, ""); HHVM_RC_STR(PHP_LOCALSTATEDIR, ""); HHVM_RC_STR(PHP_PREFIX, ""); HHVM_RC_STR(PHP_SHLIB_SUFFIX, "so"); HHVM_RC_STR(PHP_SYSCONFDIR, ""); HHVM_RC_STR(PEAR_EXTENSION_DIR, ""); HHVM_RC_STR(PEAR_INSTALL_DIR, ""); loadSystemlib("std_misc"); }