Variant f_class_uses(CVarRef obj, bool autoload /* = true */) { String clsname; if (obj.isString()) { clsname = obj.toString(); } else if (obj.isObject()) { clsname = obj.toObject()->o_getClassName(); } else { return false; } const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname); if (!info) { if (!autoload) return false; AutoloadHandler::s_instance->invokeHandler(clsname); return f_class_uses(clsname, false); } Array ret(Array::Create()); const ClassInfo::TraitVec &traits = info->getTraitsVec(); for (unsigned int i = 0; i < traits.size(); i++) { ret.set(traits[i], traits[i]); } return ret; }
bool ArrayData::hasInternalReference(PointerSet &vars) const { if (supportValueRef()) { for (ArrayIter iter(this); iter; ++iter) { CVarRef var = iter.secondRef(); if (var.isReferenced()) { Variant *pvar = var.getVariantData(); if (vars.find(pvar) != vars.end()) { return true; } vars.insert(pvar); } if (var.isObject()) { ObjectData *pobj = var.getObjectData(); if (vars.find(pobj) != vars.end()) { return true; } vars.insert(pobj); if (pobj->o_toArray().get()->hasInternalReference(vars)) { return true; } } else if (var.isArray() && var.getArrayData()->hasInternalReference(vars)) { return true; } } } return false; }
bool ArrayData::hasInternalReference(PointerSet &vars, bool ds /* = false */) const { if (isSharedMap()) return false; for (ArrayIter iter(this); iter; ++iter) { CVarRef var = iter.secondRef(); if (var.isReferenced()) { Variant *pvar = var.getRefData(); if (vars.find(pvar) != vars.end()) { return true; } vars.insert(pvar); } if (var.isObject()) { ObjectData *pobj = var.getObjectData(); if (vars.find(pobj) != vars.end()) { return true; } vars.insert(pobj); if (ds && pobj->o_instanceof("Serializable")) { return true; } if (pobj->hasInternalReference(vars, ds)) { return true; } } else if (var.isArray() && var.getArrayData()->hasInternalReference(vars, ds)) { return true; } } return false; }
Variant f_get_object_vars(CVarRef object) { if (object.isObject()) { return object.toObject()->o_toIterArray(ctxClassName()); } raise_warning("get_object_vars() expects parameter 1 to be object"); return Variant(Variant::nullInit); }
Object Certificate::Get(CVarRef var) { if (var.isResource()) { return var.toObject(); } if (var.isString() || var.isObject()) { bool file; BIO *in = ReadData(var, &file); if (in == nullptr) return Object(); X509 *cert; /* if (file) { cert = PEM_read_bio_X509(in, NULL, NULL, NULL); } else { cert = (X509 *)PEM_ASN1_read_bio ((char *(*)())d2i_X509, PEM_STRING_X509, in, NULL, NULL, NULL); } */ cert = PEM_read_bio_X509(in, nullptr, nullptr, nullptr); BIO_free(in); if (cert) { return Object(new Certificate(cert)); } } return Object(); }
Variant f_class_implements(CVarRef obj, bool autoload /* = true */) { String clsname; if (obj.isString()) { clsname = obj.toString(); } else if (obj.isObject()) { clsname = obj.toObject()->o_getClassName(); } else { return false; } const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname); if (info == NULL) { if (!autoload) return false; AutoloadHandler::s_instance->invokeHandler(clsname); return f_class_implements(clsname, false); } Array ret(Array::Create()); ClassInfo::InterfaceVec ifs; info->getAllInterfacesVec(ifs); for (unsigned int i = 0; i < ifs.size(); i++) { ret.set(ifs[i], ifs[i]); } return ret; }
Variant f_property_exists(CVarRef class_or_object, const String& property) { if (class_or_object.isObject()) { const String& context = ctxClassName(); return (bool)class_or_object.toObject()->o_realProp( property, ObjectData::RealPropExist, context); } if (!class_or_object.isString()) { raise_warning( "First parameter must either be an object" " or the name of an existing class" ); return Variant(Variant::NullInit()); } Class* cls = Unit::lookupClass(get_classname(class_or_object).get()); if (!cls) { return false; } bool accessible; auto propInd = cls->getDeclPropIndex(cls, property.get(), accessible); if (propInd != kInvalidSlot) { return true; } propInd = cls->lookupSProp(property.get()); return (propInd != kInvalidSlot); }
Variant f_get_parent_class(CVarRef object /* = null_variant */) { if (!object.isInitialized()) { CallerFrame cf; Class* cls = arGetContextClass(cf()); if (cls && cls->parent()) { return String(cls->parentRef()); } return false; } Variant class_name; if (object.isObject()) { class_name = f_get_class(object); } else if (object.isString()) { class_name = object; } else { return false; } const Class* cls = Unit::lookupClass(class_name.toString().get()); if (cls) { auto& parentClass = *(const String*)(&cls->parentRef()); if (!parentClass.empty()) { return parentClass; } } return false; }
Variant f_hphp_invoke_method(CVarRef obj, CStrRef cls, CStrRef name, CArrRef params) { if (!obj.isObject()) { return invoke_static_method(cls.data(), name.data(), params); } return obj.toObject()->o_invoke(name.data(), params, -1); }
Variant f_get_parent_class(CVarRef object /* = null_variant */) { if (hhvm) { if (!object.isInitialized()) { CallerFrame cf; HPHP::VM::Class* cls = arGetContextClass(cf()); if (cls && cls->parent()) { return CStrRef(cls->parentRef()); } return false; } } Variant class_name; if (object.isObject()) { class_name = f_get_class(object); } else if (object.isString()) { class_name = object; } else { return false; } const ClassInfo *classInfo = ClassInfo::FindClass(class_name.toString()); if (classInfo) { CStrRef parentClass = classInfo->getParentClass(); if (!parentClass.empty()) { return parentClass; } } return false; }
void f_var_dump(CVarRef v) { VariableSerializer vs(VariableSerializer::VarDump, 0, 2); // manipulate maxCount to match PHP behavior if (!v.isObject()) { vs.incMaxCount(); } vs.serialize(v, false); }
Variant f_hphp_invoke_method(CVarRef obj, CStrRef cls, CStrRef name, CArrRef params) { if (!obj.isObject()) { return invoke_static_method(cls, name, params); } ObjectData *o = obj.toCObjRef().get(); return o->o_invoke(name, params); }
void VariableSerializer::write(CVarRef v, bool isArrayKey /* = false */) { if (!isArrayKey && v.isObject()) { write(v.toObject()); return; } setReferenced(v.isReferenced()); setRefCount(v.getRefCount()); v.serialize(this, isArrayKey); }
bool same(CVarRef v1, CObjRef v2) { bool null1 = v1.isNull(); bool null2 = v2.isNull(); if (null1 && null2) return true; if (null1 || null2) return false; if (!v1.isObject()) return false; auto const od = v1.getObjectData(); return od == v2.get(); }
Variant invoke_failed(CVarRef func, CArrRef params, bool fatal /* = true */) { if (func.isObject()) { return o_invoke_failed( func.objectForCall()->o_getClassName().c_str(), "__invoke", fatal); } else { return invoke_failed(func.toString().c_str(), params, fatal); } }
Variant ObjectStringPropertyExpression::eval(VariableEnvironment &env) const { CVarRef obj = m_obj->eval(env); SET_LINE; if (!g_context->getDebuggerBypassCheck()) { return obj.o_get(m_name); } Variant v = obj.o_get(m_name, false); if (!v.isNull()) return v; CStrRef context = obj.isObject() ? obj.getObjectData()->o_getClassName() : null_string; return obj.o_get(m_name, false, context); }
bool f_property_exists(CVarRef class_or_object, CStrRef property) { if (class_or_object.isObject()) { // Call o_exists for objects, to include dynamic properties. return class_or_object.toObject()->o_propExists(property); } const ClassInfo *classInfo = ClassInfo::FindClass(get_classname(class_or_object)); while (classInfo) { if (classInfo->hasProperty(property)) { return true; } else { classInfo = classInfo->getParentClassInfo(); } } return false; }
static Variant collator_convert_object_to_string(CVarRef obj) { if (!obj.isObject()) return obj; String str; try { str = obj.toString(); } catch (Exception &e) { return obj; } UErrorCode status; String ustr = intl_convert_str_utf8_to_utf16(str, &status); if (U_FAILURE(status)) { raise_warning("Error casting object to string in " "collator_convert_object_to_string()"); return uninit_null(); } return ustr; }
static Variant HHVM_STATIC_METHOD(IntlTimeZone, createEnumeration, CVarRef countryRawOffset) { icu::StringEnumeration *se = nullptr; if (countryRawOffset.isNull()) { se = icu::TimeZone::createEnumeration(); } else if (countryRawOffset.isNumeric(true)) { se = icu::TimeZone::createEnumeration((int32_t)countryRawOffset.toInt64()); } else if (countryRawOffset.isString() || countryRawOffset.isObject()) { se = icu::TimeZone::createEnumeration(countryRawOffset.toString().c_str()); } else { s_intl_error->set(U_ILLEGAL_ARGUMENT_ERROR, "intltz_create_enumeration: invalid argument type"); return false; } return IntlIterator::newInstance(se); }
Variant f_get_parent_class(CVarRef object /* = null_variant */) { Variant class_name; if (object.isObject()) { class_name = f_get_class(object); } else if (object.isString()) { class_name = object; } else { return false; } const ClassInfo *classInfo = ClassInfo::FindClass(class_name.toString()); if (classInfo) { CStrRef parentClass = classInfo->getParentClass(); if (!parentClass.empty()) { return parentClass; } } return false; }
Variant f_class_uses(CVarRef obj, bool autoload /* = true */) { Class* cls; if (obj.isString()) { cls = Unit::getClass(obj.getStringData(), autoload); if (!cls) { return false; } } else if (obj.isObject()) { cls = obj.getObjectData()->getVMClass(); } else { return false; } Array ret(Array::Create()); for (auto const& traitName : cls->preClass()->usedTraits()) { const String& nameRef = *(String*)(&traitName); ret.set(nameRef, nameRef); } return ret; }
Variant f_get_class(CVarRef object /* = null_variant */) { if (object.isNull()) { // No arg passed. String ret; CallerFrame cf; Class* cls = arGetContextClassImpl<true>(cf()); if (cls) { ret = String(cls->nameRef()); } if (ret.empty()) { raise_warning("get_class() called without object from outside a class"); return false; } return ret; } if (!object.isObject()) return false; return object.toObject()->o_getClassName(); }
Variant f_class_parents(CVarRef obj, bool autoload /* = true */) { Class* cls; if (obj.isString()) { cls = Unit::getClass(obj.getStringData(), autoload); if (!cls) { return false; } } else if (obj.isObject()) { cls = obj.getObjectData()->getVMClass(); } else { return false; } Array ret(Array::Create()); for (cls = cls->parent(); cls; cls = cls->parent()) { auto& clsName = cls->nameRef(); ret.set(clsName, clsName); } return ret; }
Variant f_class_implements(CVarRef obj, bool autoload /* = true */) { Class* cls; if (obj.isString()) { cls = Unit::getClass(obj.getStringData(), autoload); if (!cls) { return false; } } else if (obj.isObject()) { cls = obj.getObjectData()->getVMClass(); } else { return false; } Array ret(Array::Create()); const Class::InterfaceMap& ifaces = cls->allInterfaces(); for (int i = 0, size = ifaces.size(); i < size; i++) { ret.set(ifaces[i]->nameRef(), ifaces[i]->nameRef()); } return ret; }
Variant f_class_uses(CVarRef obj, bool autoload /* = true */) { Class* cls; if (obj.isString()) { cls = Unit::getClass(obj.getStringData(), autoload); if (!cls) { return false; } } else if (obj.isObject()) { cls = obj.getObjectData()->getVMClass(); } else { return false; } Array ret(Array::Create()); for (auto& elem : cls->usedTraits()) { auto& traitName = elem->nameRef(); ret.set(traitName, traitName); } return ret; }
bool ArrayData::hasInternalReference(PointerSet &vars, bool ds /* = false */) const { if (isSharedMap()) return false; for (ArrayIter iter(this); iter; ++iter) { CVarRef var = iter.secondRef(); if (var.isReferenced()) { Variant *pvar = var.getVariantData(); if (vars.find(pvar) != vars.end()) { return true; } vars.insert(pvar); } if (var.isObject()) { ObjectData *pobj = var.getObjectData(); if (vars.find(pobj) != vars.end()) { return true; } vars.insert(pobj); if (pobj->o_instanceof("Serializable")) { if (ds) { // We want to detect Serializable object as well return true; } else { // Serializable object does not have internal reference issue return false; } } if (pobj->o_toArray().get()->hasInternalReference(vars, ds)) { return true; } } else if (var.isArray() && var.getArrayData()->hasInternalReference(vars, ds)) { return true; } } return false; }
Variant f_class_parents(CVarRef obj, bool autoload /* = true */) { String clsname; if (obj.isString()) { clsname = obj.toString(); } else if (obj.isObject()) { clsname = obj.toObject()->o_getClassName(); } else { return false; } const ClassInfo *info = ClassInfo::FindClass(clsname); if (info == NULL) { return false; } Array ret(Array::Create()); ClassInfo::ClassVec parents; info->getAllParentsVec(parents); for (unsigned int i = 0; i < parents.size(); i++) { ret.set(parents[i], parents[i]); } return ret; }
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) { if (Loaded) return true; Loaded = true; // load extension functions first, so system/classes may call them ParseExtFunctions(ar, ExtensionFunctions, false); AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult()); s_variables = VariableTablePtr(new VariableTable(*ar2.get())); s_constants = ConstantTablePtr(new ConstantTable(*ar2.get())); // parse all PHP files under system/classes if (!extOnly) { ar = AnalysisResultPtr(new AnalysisResult()); ar->loadBuiltinFunctions(); string slib = systemlib_path(); if (slib.empty()) { for (const char **cls = SystemClasses; *cls; cls++) { string phpBaseName = "/system/classes/"; phpBaseName += *cls; phpBaseName += ".php"; Parse(ar, phpBaseName, Option::GetSystemRoot() + phpBaseName); } } else { Parse(ar, slib, slib); } ar->analyzeProgram(true); ar->inferTypes(); const StringToFileScopePtrMap &files = ar->getAllFiles(); for (StringToFileScopePtrMap::const_iterator iterFile = files.begin(); iterFile != files.end(); iterFile++) { const StringToClassScopePtrVecMap &classes = iterFile->second->getClasses(); for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin(); iter != classes.end(); ++iter) { assert(iter->second.size() == 1); iter->second[0]->setSystem(); assert(!s_classes[iter->first]); s_classes[iter->first] = iter->second[0]; } } } else { NoSuperGlobals = true; } // load extension constants, classes and dynamics ParseExtConsts(ar, ExtensionConsts, false); ParseExtClasses(ar, ExtensionClasses, false); for (unsigned int i = 0; i < Option::SepExtensions.size(); i++) { Option::SepExtensionOptions &options = Option::SepExtensions[i]; string soname = options.soname; if (soname.empty()) { soname = string("lib") + options.name + ".so"; } if (!options.lib_path.empty()) { soname = options.lib_path + "/" + soname; } if (!LoadSepExtensionSymbols(ar, options.name, soname)) { return false; } } if (!extOnly) { Array constants = ClassInfo::GetSystemConstants(); LocationPtr loc(new Location); for (ArrayIter it = constants.begin(); it; ++it) { CVarRef key = it.first(); if (!key.isString()) continue; std::string name = key.toCStrRef().data(); if (s_constants->getSymbol(name)) continue; if (name == "true" || name == "false" || name == "null") continue; CVarRef value = it.secondRef(); if (!value.isInitialized() || value.isObject()) continue; ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value); TypePtr t = value.isNull() ? Type::Null : value.isBoolean() ? Type::Boolean : value.isInteger() ? Type::Int64 : value.isDouble() ? Type::Double : value.isArray() ? Type::Array : Type::Variant; s_constants->add(key.toCStrRef().data(), t, e, ar2, e); } s_variables = ar2->getVariables(); for (int i = 0, n = NumGlobalNames(); i < n; ++i) { s_variables->add(GlobalNames[i], Type::Variant, false, ar, ConstructPtr(), ModifierExpressionPtr()); } } s_constants->setDynamic(ar, "SID", true); return true; }
bool BuiltinSymbols::Load(AnalysisResultPtr ar) { if (Loaded) return true; Loaded = true; if (g_context.isNull()) init_thread_locals(); ClassInfo::Load(); // load extension functions first, so system/php may call them ImportExtFunctions(ar, ClassInfo::GetSystem()); ConstantTablePtr cns = ar->getConstants(); // load extension constants, classes and dynamics ImportNativeConstants(ar, cns); ImportExtConstants(ar, cns, ClassInfo::GetSystem()); ImportExtClasses(ar); Array constants = ClassInfo::GetSystemConstants(); LocationPtr loc(new Location); for (ArrayIter it = constants.begin(); it; ++it) { CVarRef key = it.first(); if (!key.isString()) continue; std::string name = key.toCStrRef().data(); if (cns->getSymbol(name)) continue; if (name == "true" || name == "false" || name == "null") continue; CVarRef value = it.secondRef(); if (!value.isInitialized() || value.isObject()) continue; ExpressionPtr e = Expression::MakeScalarExpression(ar, ar, loc, value); TypePtr t = value.isNull() ? Type::Null : value.isBoolean() ? Type::Boolean : value.isInteger() ? Type::Int64 : value.isDouble() ? Type::Double : value.isArray() ? Type::Array : Type::Variant; cns->add(key.toCStrRef().data(), t, e, ar, e); } for (int i = 0, n = NumGlobalNames(); i < n; ++i) { ar->getVariables()->add(GlobalNames[i], Type::Variant, false, ar, ConstructPtr(), ModifierExpressionPtr()); } cns->setDynamic(ar, "PHP_BINARY", true); cns->setDynamic(ar, "PHP_BINDIR", true); cns->setDynamic(ar, "PHP_OS", true); cns->setDynamic(ar, "PHP_SAPI", true); cns->setDynamic(ar, "SID", true); // Systemlib files were all parsed by hphp_process_init const StringToFileScopePtrMap &files = ar->getAllFiles(); for (const auto& file : files) { file.second->setSystem(); const auto& classes = file.second->getClasses(); for (const auto& clsVec : classes) { assert(clsVec.second.size() == 1); auto cls = clsVec.second[0]; cls->setSystem(); ar->addSystemClass(cls); for (const auto& func : cls->getFunctions()) { FunctionScope::RecordFunctionInfo(func.first, func.second); } } const auto& functions = file.second->getFunctions(); for (const auto& func : functions) { func.second->setSystem(); ar->addSystemFunction(func.second); FunctionScope::RecordFunctionInfo(func.first, func.second); } } return true; }
Variant f_get_object_vars(CVarRef object) { if (object.isObject()) { return object.toObject()->o_toIterArray(FrameInjection::GetClassName(true)); } return false; }