Beispiel #1
0
bool HHVM_FUNCTION(pcntl_signal,
                   int signo,
                   const Variant& handler,
                   bool restart_syscalls /* = true */) {
  /* Special long value case for SIG_DFL and SIG_IGN */
  if (handler.isInteger()) {
    int64_t handle = handler.toInt64();
    if (handle != (long)SIG_DFL && handle != (long)SIG_IGN) {
      raise_warning("Invalid value for handle argument specified");
    }
    if (php_signal(signo, (Sigfunc *)handle, restart_syscalls) == SIG_ERR) {
      raise_warning("Error assigning signal");
      return false;
    }
    return true;
  }

  if (!is_callable(handler)) {
    raise_warning("%s is not a callable function name error",
                    handler.toString().data());
    return false;
  }

  s_signal_handlers->handlers.set(signo, handler);

  if (php_signal(signo, pcntl_signal_handler, restart_syscalls) == SIG_ERR) {
    raise_warning("Error assigning signal");
    return false;
  }
  return true;
}
Beispiel #2
0
bool PDOSqliteResource::createFunction(const String& name,
                                       const Variant& callback,
                                       int argcount) {
  if (!is_callable(callback)) {
    raise_warning("function '%s' is not callable", callback.toString().data());
    return false;
  }

  auto udf = req::make_unique<UDF>();

  udf->func = callback;
  udf->argc = argcount;
  udf->name = name.toCppString();

  auto stat = sqlite3_create_function(
    conn()->m_db,
    udf->name.c_str(),
    argcount,
    SQLITE_UTF8,
    static_cast<SQLite3::UserDefinedFunc*>(udf.get()),
    php_sqlite3_callback_func,
    nullptr,
    nullptr
  );

  if (stat != SQLITE_OK) {
    return false;
  }
  m_udfs.emplace_back(std::move(udf));

  return true;
}
Beispiel #3
0
	T* try_convert() const {
		if(!is_callable()) {
			return NULL;
		}

		return dynamic_cast<T*>(mutable_callable());
	}
Beispiel #4
0
void HHVM_METHOD(ZMQSocket, __construct, const Object& context, int64_t type, const Variant& persistentId, const Variant& newSocketCallback) {
  auto sock = Native::data<ZMQSocket>(this_);
  auto ctx = Native::data<ZMQContext>(context);
  bool isNew = false;
  auto data = ZMQSocketData::get(ctx->context, type, persistentId, isNew);

  if (!data) {
    throwExceptionClassZMQErr(s_ZMQSocketExceptionClass, "Error creating socket: {}", errno);
  }

  sock->socket = data;
  if (!ctx->context->is_persistent) {
    sock->context_obj = context;
  }

  if (isNew) {
    if (!newSocketCallback.isNull()) {
      if (!is_callable(newSocketCallback)) {
        throwExceptionClass(s_ZMQSocketExceptionClass, "Invalid callback", PHP_ZMQ_INTERNAL_ERROR);
      }
      vm_call_user_func(newSocketCallback, make_packed_array(Object(this_), persistentId));
    }
  }

  if (data->is_persistent) {
    sock->persistent_id = persistentId;
    ZMQSocketData::set(data, type, persistentId);
  }
}
Beispiel #5
0
bool PDOSqliteConnection::createFunction(const String& name,
                                         const Variant& callback,
                                         int argcount) {
  if (!is_callable(callback)) {
    raise_warning("function '%s' is not callable", callback.toString().data());
    return false;
  }

  auto udf = std::make_shared<UDF>();

  udf->func = callback;
  udf->argc = argcount;
  udf->name = name.toCppString();

  auto stat = sqlite3_create_function(m_db, udf->name.c_str(), argcount,
                                      SQLITE_UTF8, udf.get(),
                                      php_sqlite3_callback_func,
                                      nullptr, nullptr);
  if (stat != SQLITE_OK) {
    return false;
  }
  m_udfs.push_back(udf);

  return true;
}
Beispiel #6
0
bool HHVM_METHOD(SQLite3, createfunction,
                 const String& name,
                 const Variant& callback,
                 int64_t argcount /* = -1 */) {
  auto *data = Native::data<SQLite3>(this_);
  data->validate();
  if (name.empty()) {
    return false;
  }
  if (!is_callable(callback)) {
    raise_warning("Not a valid callback function %s",
                  callback.toString().data());
    return false;
  }

  auto udf = std::make_shared<SQLite3::UserDefinedFunc>();
  if (sqlite3_create_function(data->m_raw_db, name.data(), argcount,
                              SQLITE_UTF8, udf.get(), php_sqlite3_callback_func,
                              nullptr, nullptr) == SQLITE_OK) {
    udf->func = callback;
    udf->argc = argcount;
    data->m_udfs.push_back(udf);
    return true;
  }
  return false;
}
variant variant::get_member(const std::string& str) const
{
	if(is_callable()) {
		return callable_->query_value(str);
	}

	if(str == "self") {
		return *this;
	} else {
		return variant();
	}
}
Beispiel #8
0
static bool HHVM_FUNCTION(
    readline_completion_function,
    const Variant& function) {
  if (!is_callable(function)) {
    raise_warning(
        "readline_completion_function(): %s is not callable",
        function.toString().data());
    return false;
  }
  s_readline->completion = function;
  rl_attempted_completion_function = readline_completion_cb;
  return true;
}
Beispiel #9
0
Variant HHVM_FUNCTION(preg_replace_callback,
                      const Variant& pattern,
                      const Variant& callback,
                      const Variant& subject,
                      int limit /* = -1 */,
                      VRefParam count /* = null */) {
  if (!is_callable(callback)) {
    raise_warning("Not a valid callback function %s",
                  callback.toString().data());
    return empty_string_variant();
  }
  return preg_replace_impl(pattern, callback, subject,
                           limit, count.getVariantOrNull(), true, false);
}
Beispiel #10
0
bool TypeConstraint::checkTypeAliasNonObj(const TypedValue* tv) const {
  assert(tv->m_type != KindOfObject);
  assert(isObject());

  auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName);
  auto td = p.first;
  auto c = p.second;

  // Common case is that we actually find the alias:
  if (td) {
    if (td->nullable && tv->m_type == KindOfNull) return true;
    auto result = annotCompat(tv->m_type, td->type,
      td->klass ? td->klass->name() : nullptr);
    switch (result) {
      case AnnotAction::Pass: return true;
      case AnnotAction::Fail: return false;
      case AnnotAction::CallableCheck:
        return is_callable(tvAsCVarRef(tv));
      case AnnotAction::DictCheck:
        return tv->m_data.parr->isDict();
      case AnnotAction::VecCheck:
        return tv->m_data.parr->isVecArray();
      case AnnotAction::ObjectCheck: break;
    }
    assert(result == AnnotAction::ObjectCheck);
    assert(td->type == AnnotType::Object);
    // Fall through to the check below, since this could be a type
    // alias to an enum type
    c = td->klass;
  }

  // Otherwise, this isn't a proper type alias, but it *might* be a
  // first-class enum. Check if the type is an enum and check the
  // constraint if it is. We only need to do this when the underlying
  // type is not an object, since only int and string can be enums.
  if (c && isEnum(c)) {
    auto dt = c->enumBaseTy();
    // For an enum, if the underlying type is mixed, we still require
    // it is either an int or a string!
    if (dt) {
      return equivDataTypes(*dt, tv->m_type);
    } else {
      return isIntType(tv->m_type) || isStringType(tv->m_type);
    }
  }
  return false;
}
Beispiel #11
0
Variant HHVM_FUNCTION(header_register_callback, const Variant& callback) {
  if (!is_callable(callback)) {
    raise_warning("First argument is expected to be a valid callback");
    return init_null();
  }

  auto transport = g_context->getTransport();
  if (!transport) {
    // fail if there is no transport
    return false;
  }
  if (transport->headersSent()) {
    // fail if headers have already been sent
    return false;
  }
  return g_context->setHeaderCallback(callback);
}
Beispiel #12
0
Variant HHVM_FUNCTION(preg_replace_callback_array,
                      const Variant& patterns_and_callbacks,
                      const Variant& subject,
                      int limit /* = -1 */,
                      VRefParam count /* = uninit_null() */) {
  if (!patterns_and_callbacks.isArray()) {
    raise_warning(
      "%s() expects parameter 1 to be an array, %s given",
      __FUNCTION__+2 /* +2 removes the "f_" prefix */,
      getDataTypeString(patterns_and_callbacks.getType()).c_str()
    );
    return init_null();
  }

  // Now see if we need to raise any warnings because of not having a
  // valid callback function
  for (ArrayIter iter(patterns_and_callbacks.toArray()); iter; ++iter) {
    if (!is_callable(iter.second())) {
      raise_warning("Not a valid callback function %s",
                    iter.second().toString().data());
      return subject.isString() ? empty_string_variant()
                                : Variant(empty_array());
    }
  }

  if (subject.isString()) {
    Array subject_arr = Array::Create();
    subject_arr.add(0, subject.toString());
    Variant ret = preg_replace_callback_array_impl(
      patterns_and_callbacks, subject_arr, limit, count
    );
    // ret[0] could be an empty string
    return ret.isArray() ? ret.toArray()[0] : init_null();
  } else if (subject.isArray()) {
    return preg_replace_callback_array_impl(
      patterns_and_callbacks, subject.toArray(), limit, count
    );
  } else {
    // No warning is given here, just return null
    return init_null();
  }
}
Beispiel #13
0
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();
}
Beispiel #14
0
/* ECMA-262 5.1 Edition    15.12.3 (abstract operation Str) */
static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val)
{
    jsval_t value;
    HRESULT hres;

    if(is_object_instance(val) && get_object(val)) {
        jsdisp_t *obj;
        DISPID id;

        obj = iface_to_jsdisp((IUnknown*)get_object(val));
        if(!obj)
            return S_FALSE;

        hres = jsdisp_get_id(obj, toJSONW, 0, &id);
        jsdisp_release(obj);
        if(hres == S_OK)
            FIXME("Use toJSON.\n");
    }

    /* FIXME: Support replacer replacer. */

    hres = maybe_to_primitive(ctx->ctx, val, &value);
    if(FAILED(hres))
        return hres;

    switch(jsval_type(value)) {
    case JSV_NULL:
        if(!append_string(ctx, nullW))
            hres = E_OUTOFMEMORY;
        break;
    case JSV_BOOL:
        if(!append_string(ctx, get_bool(value) ? trueW : falseW))
            hres = E_OUTOFMEMORY;
        break;
    case JSV_STRING: {
        jsstr_t *str = get_string(value);
        const WCHAR *ptr = jsstr_flatten(str);
        if(ptr)
            hres = json_quote(ctx, ptr, jsstr_length(str));
        else
            hres = E_OUTOFMEMORY;
        break;
    }
    case JSV_NUMBER: {
        double n = get_number(value);
        if(is_finite(n)) {
            const WCHAR *ptr;
            jsstr_t *str;

            /* FIXME: Optimize. There is no need for jsstr_t here. */
            hres = double_to_string(n, &str);
            if(FAILED(hres))
                break;

            ptr = jsstr_flatten(str);
            assert(ptr != NULL);
            hres = ptr && !append_string_len(ctx, ptr, jsstr_length(str)) ? E_OUTOFMEMORY : S_OK;
            jsstr_release(str);
        }else {
            if(!append_string(ctx, nullW))
                hres = E_OUTOFMEMORY;
        }
        break;
    }
    case JSV_OBJECT: {
        jsdisp_t *obj;

        obj = iface_to_jsdisp((IUnknown*)get_object(value));
        if(!obj) {
            hres = S_FALSE;
            break;
        }

        if(!is_callable(obj))
            hres = is_class(obj, JSCLASS_ARRAY) ? stringify_array(ctx, obj) : stringify_object(ctx, obj);
        else
            hres = S_FALSE;

        jsdisp_release(obj);
        break;
    }
    case JSV_UNDEFINED:
        hres = S_FALSE;
        break;
    case JSV_VARIANT:
        FIXME("VARIANT\n");
        hres = E_NOTIMPL;
        break;
    }

    jsval_release(value);
    return hres;
}
Beispiel #15
0
bool TypeConstraint::check(TypedValue* tv, const Func* func) const {
  assert(hasConstraint() && !isTypeVar() && !isMixed() && !isTypeConstant());

  // This is part of the interpreter runtime; perf matters.
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }

  if (isNullable() && tv->m_type == KindOfNull) {
    return true;
  }

  if (tv->m_type == KindOfObject) {
    // Perfect match seems common enough to be worth skipping the hash
    // table lookup.
    const Class *c = nullptr;
    if (isObject()) {
      if (m_typeName->isame(tv->m_data.pobj->getVMClass()->name())) {
        if (isProfileRequest()) InstanceBits::profile(m_typeName);
        return true;
      }
      // We can't save the Class* since it moves around from request
      // to request.
      assert(m_namedEntity);
      c = Unit::lookupClass(m_namedEntity);
    } else {
      switch (metaType()) {
        case MetaType::Self:
          selfToClass(func, &c);
          break;
        case MetaType::Parent:
          parentToClass(func, &c);
          break;
        case MetaType::Callable:
          return is_callable(tvAsCVarRef(tv));
        case MetaType::Precise:
        case MetaType::Number:
        case MetaType::ArrayKey:
        case MetaType::Dict:
        case MetaType::Vec:
          return false;
        case MetaType::Mixed:
          // We assert'd at the top of this function that the
          // metatype cannot be Mixed
          not_reached();
      }
    }
    if (isProfileRequest() && c) {
      InstanceBits::profile(c->preClass()->name());
    }
    if (c && tv->m_data.pobj->instanceof(c)) {
      return true;
    }
    return isObject() && checkTypeAliasObj(tv->m_data.pobj->getVMClass());
  }

  auto const result = annotCompat(tv->m_type, m_type, m_typeName);
  switch (result) {
    case AnnotAction::Pass: return true;
    case AnnotAction::Fail: return false;
    case AnnotAction::CallableCheck:
      return is_callable(tvAsCVarRef(tv));
    case AnnotAction::DictCheck:
      return tv->m_data.parr->isDict();
    case AnnotAction::VecCheck:
      return tv->m_data.parr->isVecArray();
    case AnnotAction::ObjectCheck:
      assert(isObject());
      return checkTypeAliasNonObj(tv);
  }
  not_reached();
}
Beispiel #16
0
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 (!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()));
    }
  }
}