示例#1
0
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 appendOrPrependFilter(const Resource& stream,
                 const String& filtername,
                 const Variant& readwrite,
                 const Variant& params,
                 bool append) {
    const char* func_name =
      append ? "stream_filter_append()" : "stream_filter_prepend()";

    if (!m_registeredFilters.exists(filtername)) {
      raise_warning("%s: unable to locate filter \"%s\"",
                    func_name,
                    filtername.data());
      return false;
    }

    auto file = cast<File>(stream);
    int mode = readwrite.toInt32();
    if (!mode) {
      auto str = file->getMode();
      /* The documentation says a read filter is only created for 'r' and '+'
       * modes, but the implementation will always create one unless
       * STREAM_FILTER_WRITE is passed.
       *
       * This branch is only executed if no STREAM_FILTER* args were passed,
       * so we always create a READ filter.
       */
      mode = k_STREAM_FILTER_READ;
      if (str.find('+') != -1 || str.find('w') != -1 || str.find('a') != -1) {
        mode |= k_STREAM_FILTER_WRITE;
      }
    }
    if (!(mode & k_STREAM_FILTER_ALL)) {
      return false;
    }

    // If it's ALL we create two resources, but only return one - this
    // matches Zend, and is the documented behavior.
    req::ptr<StreamFilter> ret;
    if (mode & k_STREAM_FILTER_READ) {
      auto resource = createInstance(func_name,
                                     file,
                                     filtername,
                                     params);
      if (!resource) {
        return false;
      }
      ret = resource;
      if (append) {
        file->appendReadFilter(resource);
      } else {
        file->prependReadFilter(resource);
      }
    }
    if (mode & k_STREAM_FILTER_WRITE) {
      auto resource = createInstance(func_name,
                                     file,
                                     filtername,
                                     params);
      if (!resource) {
        return false;
      }
      ret = resource;
      if (append) {
        file->appendWriteFilter(resource);
      } else {
        file->prependWriteFilter(resource);
      }
    }
    return Variant(std::move(ret));
  }
示例#3
0
static Variant warn_non_object() {
    raise_warning("Cannot access property on non-object");
    return null;
}
示例#4
0
bool HttpProtocol::ProxyRequest(Transport *transport, bool force,
                                const std::string &url,
                                int &code, std::string &error,
                                StringBuffer &response,
                                HeaderMap *extraHeaders /* = NULL */) {
  ASSERT(transport);
  if (transport->headersSent()) {
    raise_warning("Cannot proxy request - headers already sent");
    return false;
  }

  HeaderMap requestHeaders;
  transport->getHeaders(requestHeaders);
  if (extraHeaders) {
    for (HeaderMap::const_iterator iter = extraHeaders->begin();
         iter != extraHeaders->end(); ++iter) {
      vector<string> &values = requestHeaders[iter->first];
      values.insert(values.end(), iter->second.begin(), iter->second.end());
    }
  }

  int size = 0;
  const char *data = NULL;
  if (transport->getMethod() == Transport::POST) {
    data = (const char *)transport->getPostData(size);
  }

  code = 0; // HTTP status of curl or 0 for "no server response code"
  vector<String> responseHeaders;
  HttpClient http;
  if (data && size) {
    code = http.post(url.c_str(), data, size, response, &requestHeaders,
                     &responseHeaders);
  } else {
    code = http.get(url.c_str(), response, &requestHeaders, &responseHeaders);
  }
  if (code == 0) {
    if (!force) return false; // so we can retry
    Logger::Error("Unable to proxy %s: %s", url.c_str(),
                  http.getLastError().c_str());
    error = http.getLastError();
    return true;
  }

  for (unsigned int i = 0; i < responseHeaders.size(); i++) {
    String &header = responseHeaders[i];
    if (header.find(":") != String::npos &&
        header.find("Content-Length: ") != 0 &&
        header.find("Client-Transfer-Encoding: ") != 0 &&
        header.find("Transfer-Encoding: ") != 0 &&
        header.find("Connection: ") != 0) {
      transport->addHeader(header.data());
    }
  }
  const char* respData = response.data();
  if (!respData) {
    respData = "";
  }
  Logger::Verbose("Response code was %d when proxying %s", code, url.c_str());
  return true;
}
示例#5
0
static void HHVM_FUNCTION(gc_enable) {
  if (RuntimeOption::EnableHipHopSyntax) {
    raise_warning("HipHop currently does not support circular reference "
                  "collection");
  }
}
示例#6
0
bool SSLSocket::handleError(int64_t nr_bytes, bool is_init) {
  char esbuf[512];
  std::string ebuf;
  unsigned long ecode;

  bool retry = true;
  int err = SSL_get_error(m_data->m_handle, nr_bytes);
  switch (err) {
  case SSL_ERROR_ZERO_RETURN:
    /* SSL terminated (but socket may still be active) */
    retry = false;
    break;
  case SSL_ERROR_WANT_READ:
  case SSL_ERROR_WANT_WRITE:
    /* re-negotiation, or perhaps the SSL layer needs more
     * packets: retry in next iteration */
    errno = EAGAIN;
    retry = (is_init || m_data->m_is_blocked);
    break;
  case SSL_ERROR_SYSCALL:
    if (ERR_peek_error() == 0) {
      if (nr_bytes == 0) {
        if (ERR_get_error()) {
          raise_warning("SSL: fatal protocol error");
        }
        SSL_set_shutdown(m_data->m_handle,
                         SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
        setEof(true);
        retry = false;
      } else {
        raise_warning("SSL: %s", folly::errnoStr(errno).c_str());
        retry = false;
      }
      break;
    }
    /* fall through */
  default:
    /* some other error */
    ecode = ERR_get_error();
    switch (ERR_GET_REASON(ecode)) {
    case SSL_R_NO_SHARED_CIPHER:
      raise_warning("SSL_R_NO_SHARED_CIPHER: no suitable shared cipher "
                    "could be used.  This could be because the server is "
                    "missing an SSL certificate (local_cert context "
                    "option)");
      retry = false;
      break;

    default:
      do {
        // NULL is automatically added
        ERR_error_string_n(ecode, esbuf, sizeof(esbuf));
        if (!ebuf.empty()) {
          ebuf += '\n';
        }
        ebuf += esbuf;
      } while ((ecode = ERR_get_error()) != 0);

      raise_warning("SSL operation failed with code %d. %s%s",
                    err, !ebuf.empty() ? "OpenSSL Error messages:\n" : "",
                    !ebuf.empty() ? ebuf.c_str() : "");
    }

    retry = false;
    errno = 0;
  }

  return retry;
}
示例#7
0
bool SSLSocket::applyVerificationPolicy(X509 *peer) {
  /* verification is turned off */
  if (!m_context[s_verify_peer].toBoolean()) {
    return true;
  }

  if (peer == nullptr) {
    raise_warning("Could not get peer certificate");
    return false;
  }

  int err = SSL_get_verify_result(m_data->m_handle);
  switch (err) {
  case X509_V_OK:
    /* fine */
    break;
  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
    if (m_context[s_allow_self_signed].toBoolean()) {
      /* allowed */
      break;
    }
    /* not allowed, so fall through */
  default:
    raise_warning("Could not verify peer: code:%d %s", err,
                  X509_verify_cert_error_string(err));
    return false;
  }

  /* if the cert passed the usual checks, apply our own local policies now */

  /* Does the common name match ? (used primarily for https://) */
  String cnmatch = m_context[s_CN_match].toString();
  if (!cnmatch.empty()) {
    X509_NAME *name = X509_get_subject_name(peer);
    char buf[1024];
    int name_len = X509_NAME_get_text_by_NID(name, NID_commonName, buf,
                                             sizeof(buf));

    if (name_len < 0) {
      raise_warning("Unable to locate peer certificate CN");
      return false;
    } else if (name_len != (int)strlen(buf)) {
      raise_warning("Peer certificate CN=`%.*s' is malformed", name_len, buf);
      return false;
    }

    bool match = (strcmp(cnmatch.c_str(), buf) == 0);
    if (!match && strlen(buf) > 3 && buf[0] == '*' && buf[1] == '.') {
      /* Try wildcard */
      if (strchr(buf+2, '.')) {
        const char* cnmatch_str = cnmatch.c_str();
        const char *tmp = strstr(cnmatch_str, buf+1);
        match = tmp && strcmp(tmp, buf+2) && tmp == strchr(cnmatch_str, '.');
      }
    }

    if (!match) {
      /* didn't match */
      raise_warning("Peer certificate CN=`%.*s' did not match expected CN=`%s'",
                    name_len, buf, cnmatch.c_str());
      return false;
    }
  }

  return true;
}
示例#8
0
void f_hphp_thread_set_warmup_enabled() {
  raise_warning("hphp_thread_set_warmup_enabled is deprecated, to enable "
                "the RequestInitFunction and RequestInitDocument features "
                "please set Server.EnableMemoryManager=true in your HipHop "
                "config");
}
示例#9
0
static bool yaf_route_map_route(const Object& o, const Object& request)
{
    auto ptr_uri = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_URI, 
            ObjectData::RealPropUnchecked, "Yaf_Request_Abstract");

    auto ptr_base_uri = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_BASE, 
            ObjectData::RealPropUnchecked, "Yaf_Request_Abstract");

    auto ptr_ctl_prefer = o->o_realProp(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER, 
             ObjectData::RealPropUnchecked, "Yaf_Route_Map");

    auto ptr_delim = o->o_realProp(YAF_ROUTE_MAP_VAR_NAME_DELIMETER, 
             ObjectData::RealPropUnchecked, "Yaf_Route_Map");

    if (ptr_uri == NULL) {
        raise_warning("invalid uri:%p", ptr_uri);
        return false;
    }

    std::string req_uri;
    if (ptr_uri && ptr_uri->isString() && 
        ptr_base_uri && 
        ptr_base_uri->isString()&&
        strncasecmp(ptr_uri->toString().c_str(), 
            ptr_base_uri->toString().c_str(), ptr_base_uri->toString().length()) == 0) {
        req_uri = std::string(ptr_uri->toString().c_str() + ptr_base_uri->toString().length()); 
    } else {
        req_uri = std::string(ptr_uri->toString().c_str());
    }

    if (req_uri.length() == 0) {
        return false;
    }

    std::string str_query_str;
    if (ptr_delim->isString() && ptr_delim->toString().length()) {
        const char* str_delim = ptr_delim->toString().c_str();
        char* tmp_req_uri = strdup(req_uri.c_str());
        char* query_str = strstr(tmp_req_uri, str_delim);
        if (query_str && *(query_str - 1) == '/') {
            char* rest = query_str + strlen(str_delim);
            if (*rest == '\0') {
                req_uri = std::string(req_uri, query_str - tmp_req_uri);
                query_str = NULL;
            } else if(*rest == '/') {
                req_uri = std::string(req_uri, query_str - tmp_req_uri);
                str_query_str  = std::string(rest);
            } else {
                query_str = NULL;
            }
        }
        
        free(tmp_req_uri);
    }

    std::string route_result;
    char* save_ptr = NULL;
    char* tmp = strdup(req_uri.c_str());
    char* seg = strtok_r(tmp, YAF_ROUTER_URL_DELIMIETER, &save_ptr);
    while (seg) {
        int seg_len = strlen(seg);
        if (seg_len) {
            route_result += seg;
        }

        route_result += "_";
        seg = strtok_r(NULL, YAF_ROUTER_URL_DELIMIETER, &save_ptr);
    }

    free(tmp);
    if (route_result.length()) {
        if (route_result[route_result.length() - 1] == '_') {
            route_result.pop_back();
        }

        if (ptr_ctl_prefer->toBoolean()) {
            auto ptr_controller = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_CONTROLLER, 
                        ObjectData::RealPropUnchecked, "Yaf_Request_Abstract");
            *ptr_controller = String(route_result);
        } else {
            auto ptr_action = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_ACTION, 
                        ObjectData::RealPropUnchecked, "Yaf_Request_Abstract");
            *ptr_action = String(route_result);
        }
    }

    if (str_query_str.length()) {
        Array arr = yaf_router_parse_parameters(str_query_str.c_str()); 
        yaf_request_set_params_multi(&request, arr);
    }

    return true;
}
示例#10
0
void _xml_characterDataHandler(void *userData, const XML_Char *s, int len) {
  auto parser = getParserFromToken(userData);

  if (parser) {
    Variant retval;
    Array args = Array::Create();

    if (parser->characterDataHandler.toBoolean()) {
      args.append(Variant(parser));
      args.append(_xml_xmlchar_zval(s, len, parser->target_encoding));
      xml_call_handler(parser, parser->characterDataHandler, args);
    }

    if (!parser->data.isNull()) {
      int i;
      int doprint = 0;

      String decoded_value;
      int decoded_len;
      decoded_value = xml_utf8_decode(s,len,
                                          parser->target_encoding);
      decoded_len = decoded_value.size();
      for (i = 0; i < decoded_len; i++) {
        switch (decoded_value[i]) {
        case ' ':
        case '\t':
        case '\n':
        default:
          doprint = 1;
          break;
        }
        if (doprint) {
          break;
        }
      }
      if (doprint || (! parser->skipwhite)) {
        if (parser->lastwasopen) {
          String myval;
          // check if value exists, if yes append to that
          if (parser->ctag.toArrRef().exists(s_value)) {
            myval = tvCastToString(parser->ctag.toArray().rvalAt(s_value).tv());
            myval += decoded_value;
            parser->ctag.toArrRef().set(s_value, myval);
          } else {
            parser->ctag.toArrRef().set(
              s_value,
              decoded_value
            );
          }
        } else {
          Array tag;
          String myval;
          String mytype;

          auto curtag = parser->data.toArrRef().pop();
          SCOPE_EXIT {
            try {
              parser->data.toArrRef().append(curtag);
            } catch (...) {}
          };

          if (curtag.toArrRef().exists(s_type)) {
            mytype = tvCastToString(curtag.toArrRef().rvalAt(s_type).tv());
            if (!strcmp(mytype.data(), "cdata") &&
                curtag.toArrRef().exists(s_value)) {
              myval = tvCastToString(curtag.toArrRef().rvalAt(s_value).tv());
              myval += decoded_value;
              curtag.toArrRef().set(s_value, myval);
              return;
            }
          }
          if (parser->level <= XML_MAXLEVEL && parser->level > 0) {
            tag = Array::Create();
            _xml_add_to_info(parser, parser->ltags[parser->level-1] +
                             parser->toffset);
            tag.set(s_tag, String(parser->ltags[parser->level-1] +
                                  parser->toffset, CopyString));
            tag.set(s_value, decoded_value);
            tag.set(s_type, s_cdata);
            tag.set(s_level, parser->level);
            parser->data.toArrRef().append(tag);
          } else if (parser->level == (XML_MAXLEVEL + 1)) {
            raise_warning("Maximum depth exceeded - Results truncated");
          }
        }
      }
    }
  }
示例#11
0
void raiseWarning(const StringData* sd) {
  raise_warning("%s", sd->data());
}
示例#12
0
void Variant::unserialize(VariableUnserializer *uns,
                          Uns::Mode mode /* = Uns::Mode::Value */) {

  // NOTE: If you make changes to how serialization and unserialization work,
  // make sure to update the reserialize() method in "runtime/ext/ext_apc.cpp"
  // and to update test_apc_reserialize() in "test/ext/test_ext_apc.cpp".

  char type, sep;
  type = uns->readChar();
  sep = uns->readChar();

  if (type != 'R') {
    uns->add(this, mode);
  }

  if (type == 'N') {
    if (sep != ';') throw Exception("Expected ';' but got '%c'", sep);
    setNull(); // NULL *IS* the value, without we get undefined warnings
    return;
  }
  if (sep != ':') {
    throw Exception("Expected ':' but got '%c'", sep);
  }

  switch (type) {
  case 'r':
    {
      int64_t id = uns->readInt();
      Variant *v = uns->getByVal(id);
      if (v == nullptr) {
        throw Exception("Id %" PRId64 " out of range", id);
      }
      operator=(*v);
    }
    break;
  case 'R':
    {
      int64_t id = uns->readInt();
      Variant *v = uns->getByRef(id);
      if (v == nullptr) {
        throw Exception("Id %" PRId64 " out of range", id);
      }
      assignRef(*v);
    }
    break;
  case 'b': { int64_t v = uns->readInt(); operator=((bool)v); } break;
  case 'i': { int64_t v = uns->readInt(); operator=(v);       } break;
  case 'd':
    {
      double v;
      char ch = uns->peek();
      bool negative = false;
      char buf[4];
      if (ch == '-') {
        negative = true;
        ch = uns->readChar();
        ch = uns->peek();
      }
      if (ch == 'I') {
        uns->read(buf, 3); buf[3] = '\0';
        if (strcmp(buf, "INF")) {
          throw Exception("Expected 'INF' but got '%s'", buf);
        }
        v = atof("inf");
      } else if (ch == 'N') {
        uns->read(buf, 3); buf[3] = '\0';
        if (strcmp(buf, "NAN")) {
          throw Exception("Expected 'NAN' but got '%s'", buf);
        }
        v = atof("nan");
      } else {
        v = uns->readDouble();
      }
      operator=(negative ? -v : v);
    }
    break;
  case 's':
    {
      String v;
      v.unserialize(uns);
      operator=(v);
    }
    break;
  case 'S':
    if (uns->getType() == VariableUnserializer::Type::APCSerialize) {
      union {
        char buf[8];
        StringData *sd;
      } u;
      uns->read(u.buf, 8);
      operator=(u.sd);
    } else {
      throw Exception("Unknown type '%c'", type);
    }
    break;
  case 'a':
    {
      Array v = Array::Create();
      v.unserialize(uns);
      operator=(v);
      return; // array has '}' terminating
    }
    break;
  case 'L':
    {
      int64_t id = uns->readInt();
      sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      String rsrcName;
      rsrcName.unserialize(uns);
      sep = uns->readChar();
      if (sep != '{') {
        throw Exception("Expected '{' but got '%c'", sep);
      }
      sep = uns->readChar();
      if (sep != '}') {
        throw Exception("Expected '}' but got '%c'", sep);
      }
      DummyResource* rsrc = NEWOBJ(DummyResource);
      rsrc->o_setResourceId(id);
      rsrc->m_class_name = rsrcName;
      operator=(rsrc);
      return; // resource has '}' terminating
    }
    break;
  case 'O':
  case 'V':
  case 'K':
    {
      String clsName;
      clsName.unserialize(uns);

      sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      int64_t size = uns->readInt();
      char sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      sep = uns->readChar();
      if (sep != '{') {
        throw Exception("Expected '{' but got '%c'", sep);
      }

      const bool allowObjectFormatForCollections = true;

      Class* cls;
      // If we are potentially dealing with a collection, we need to try to
      // load the collection class under an alternate name so that we can
      // deserialize data that was serialized before the migration of
      // collections to the HH namespace.

      if (type != 'O') {
        // Collections are CPP builtins; don't attempt to autoload
        cls = Unit::getClass(clsName.get(), /* autoload */ false);
        if (!cls) {
          cls = tryAlternateCollectionClass(clsName.get());
        }
      } else if (allowObjectFormatForCollections) {
        // In order to support the legacy {O|V}:{Set|Vector|Map}
        // serialization, we defer autoloading until we know that there's
        // no alternate (builtin) collection class.
        cls = Unit::getClass(clsName.get(), /* autoload */ false);
        if (!cls) {
          cls = tryAlternateCollectionClass(clsName.get());
        }
        if (!cls) {
          cls = Unit::loadClass(clsName.get()); // with autoloading
        }
      } else {
        cls = Unit::loadClass(clsName.get()); // with autoloading
      }

      Object obj;
      if (RuntimeOption::UnserializationWhitelistCheck &&
          (type == 'O') &&
          !uns->isWhitelistedClass(clsName)) {
        const char* err_msg =
          "The object being unserialized with class name '%s' "
          "is not in the given whitelist. "
          "See http://fburl.com/SafeSerializable for more detail";
        if (RuntimeOption::UnserializationWhitelistCheckWarningOnly) {
          raise_warning(err_msg, clsName.c_str());
        } else {
          raise_error(err_msg, clsName.c_str());
        }
      }
      if (cls) {
        // Only unserialize CPP extension types which can actually
        // support it. Otherwise, we risk creating a CPP object
        // without having it initialized completely.
        if (cls->instanceCtor() && !cls->isCppSerializable()) {
          obj = ObjectData::newInstance(
            SystemLib::s___PHP_Unserializable_ClassClass);
          obj->o_set(s_PHP_Unserializable_Class_Name, clsName);
        } else {
          obj = ObjectData::newInstance(cls);
          if (UNLIKELY(cls == c_Pair::classof() && size != 2)) {
            throw Exception("Pair objects must have exactly 2 elements");
          }
        }
      } else {
        obj = ObjectData::newInstance(
          SystemLib::s___PHP_Incomplete_ClassClass);
        obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
      }
      operator=(obj);

      if (size > 0) {
        if (type == 'O') {
          // Collections are not allowed
          if (obj->isCollection()) {
            if (size > 0) {
              throw Exception("%s does not support the 'O' serialization "
                              "format", clsName.data());
            }
            // Be lax and tolerate the 'O' serialization format for collection
            // classes if there are 0 properties.
            raise_warning("%s does not support the 'O' serialization "
                          "format", clsName.data());
          }
          /*
            Count backwards so that i is the number of properties
            remaining (to be used as an estimate for the total number
            of dynamic properties when we see the first dynamic prop).
            see getVariantPtr
          */
          for (int64_t i = size; i--; ) {
            String key = uns->unserializeKey().toString();
            int ksize = key.size();
            const char *kdata = key.data();
            int subLen = 0;
            if (kdata[0] == '\0') {
              if (UNLIKELY(!ksize)) {
                throw EmptyObjectPropertyException();
              }
              // private or protected
              subLen = strlen(kdata + 1) + 2;
              if (UNLIKELY(subLen >= ksize)) {
                if (subLen == ksize) {
                  throw EmptyObjectPropertyException();
                } else {
                  throw Exception("Mangled private object property");
                }
              }
              String k(kdata + subLen, ksize - subLen, CopyString);
              Class* ctx = (Class*)-1;
              if (kdata[1] != '*') {
                ctx = Unit::lookupClass(
                  String(kdata + 1, subLen - 2, CopyString).get());
              }
              unserializeProp(uns, obj.get(), k, ctx, key, i + 1);
            } else {
              unserializeProp(uns, obj.get(), key, nullptr, key, i + 1);
            }
          }
        } else {
          assert(type == 'V' || type == 'K');
          if (!obj->isCollection()) {
            throw Exception("%s is not a collection class", clsName.data());
          }
          collectionUnserialize(obj.get(), uns, size, type);
        }
      }
      sep = uns->readChar();
      if (sep != '}') {
        throw Exception("Expected '}' but got '%c'", sep);
      }

      obj->invokeWakeup();
      return; // object has '}' terminating
    }
    break;
  case 'C':
    {
      String clsName;
      clsName.unserialize(uns);

      sep = uns->readChar();
      if (sep != ':') {
        throw Exception("Expected ':' but got '%c'", sep);
      }
      String serialized;
      serialized.unserialize(uns, '{', '}');

      Object obj;
      try {
        obj = create_object_only(clsName);
      } catch (ClassNotFoundException &e) {
        if (!uns->allowUnknownSerializableClass()) {
          throw;
        }
        obj = create_object_only(s_PHP_Incomplete_Class);
        obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
        obj->o_set("serialized", serialized);
      }

      if (!obj->instanceof(SystemLib::s_SerializableClass)) {
        raise_warning("Class %s has no unserializer",
                      obj->o_getClassName().data());
      } else {
        obj->o_invoke_few_args(s_unserialize, 1, serialized);
        obj.get()->clearNoDestruct();
      }

      operator=(obj);
      return; // object has '}' terminating
    }
    break;
  default:
    throw Exception("Unknown type '%c'", type);
  }
  sep = uns->readChar();
  if (sep != ';') {
    throw Exception("Expected ';' but got '%c'", sep);
  }
}
示例#13
0
Variant HHVM_FUNCTION(socket_select,
                      VRefParam read,
                      VRefParam write,
                      VRefParam except,
                      const Variant& vtv_sec,
                      int tv_usec /* = 0 */) {
  int count = 0;
  if (!read.isNull()) {
    count += read.toArray().size();
  }
  if (!write.isNull()) {
    count += write.toArray().size();
  }
  if (!except.isNull()) {
    count += except.toArray().size();
  }
  if (!count) {
    return false;
  }

  struct pollfd *fds = (struct pollfd *)calloc(count, sizeof(struct pollfd));
  count = 0;
  if (!read.isNull()) {
    sock_array_to_fd_set(read.toArray(), fds, count, POLLIN);
  }
  if (!write.isNull()) {
    sock_array_to_fd_set(write.toArray(), fds, count, POLLOUT);
  }
  if (!except.isNull()) {
    sock_array_to_fd_set(except.toArray(), fds, count, POLLPRI);
  }
  if (!count) {
    raise_warning("no resource arrays were passed to select");
    free(fds);
    return false;
  }

  IOStatusHelper io("socket_select");
  int timeout_ms = -1;
  if (!vtv_sec.isNull()) {
    timeout_ms = vtv_sec.toInt32() * 1000 + tv_usec / 1000;
  }

  /* slight hack to support buffered data; if there is data sitting in the
   * read buffer of any of the streams in the read array, let's pretend
   * that we selected, but return only the readable sockets */
  if (!read.isNull()) {
    auto hasData = Array::Create();
    for (ArrayIter iter(read.toArray()); iter; ++iter) {
      auto file = cast<File>(iter.second());
      if (file->bufferedLen() > 0) {
        hasData.append(iter.second());
      }
    }
    if (hasData.size() > 0) {
      if (!write.isNull()) {
        write = empty_array();
      }
      if (!except.isNull()) {
        except = empty_array();
      }
      read = hasData;
      free(fds);
      return hasData.size();
    }
  }

  int retval = poll(fds, count, timeout_ms);
  if (retval == -1) {
    raise_warning("unable to select [%d]: %s", errno,
                  folly::errnoStr(errno).c_str());
    free(fds);
    return false;
  }

  count = 0;
  int nfds = 0;
  if (!read.isNull()) {
    sock_array_from_fd_set(read, fds, nfds, count, POLLIN|POLLERR|POLLHUP);
  }
  if (!write.isNull()) {
    sock_array_from_fd_set(write, fds, nfds, count, POLLOUT|POLLERR);
  }
  if (!except.isNull()) {
    sock_array_from_fd_set(except, fds, nfds, count, POLLPRI|POLLERR);
  }

  free(fds);
  return count;
}
示例#14
0
bool HHVM_FUNCTION(socket_set_option,
                   const Resource& socket,
                   int level,
                   int optname,
                   const Variant& optval) {
  auto sock = cast<Socket>(socket);

  struct linger lv;
  struct timeval tv;
  int ov;
  int optlen;
  void *opt_ptr;

  switch (optname) {
  case SO_LINGER:
    {
      Array value = optval.toArray();
      if (!value.exists(s_l_onoff)) {
        raise_warning("no key \"l_onoff\" passed in optval");
        return false;
      }
      if (!value.exists(s_l_linger)) {
        raise_warning("no key \"l_linger\" passed in optval");
        return false;
      }

      lv.l_onoff = (unsigned short)value[s_l_onoff].toInt32();
      lv.l_linger = (unsigned short)value[s_l_linger].toInt32();
      optlen = sizeof(lv);
      opt_ptr = &lv;
    }
    break;

  case SO_RCVTIMEO:
  case SO_SNDTIMEO:
    {
      Array value = optval.toArray();
      if (!value.exists(s_sec)) {
        raise_warning("no key \"sec\" passed in optval");
        return false;
      }
      if (!value.exists(s_usec)) {
        raise_warning("no key \"usec\" passed in optval");
        return false;
      }

      tv.tv_sec = value[s_sec].toInt32();
      tv.tv_usec = value[s_usec].toInt32();
      if (tv.tv_usec >= 1000000) {
        tv.tv_sec += tv.tv_usec / 1000000;
        tv.tv_usec %= 1000000;
      }
      if (tv.tv_sec < 0) {
        tv.tv_sec = ThreadInfo::s_threadInfo.getNoCheck()->
        m_reqInjectionData.getSocketDefaultTimeout();
      }
      optlen = sizeof(tv);
      opt_ptr = &tv;
      sock->setTimeout(tv);
    }
    break;

  default:
    ov = optval.toInt32();
    optlen = sizeof(ov);
    opt_ptr = &ov;
    break;
  }

  if (setsockopt(sock->fd(), level, optname, opt_ptr, optlen) != 0) {
    SOCKET_ERROR(sock, "unable to set socket option", errno);
    return false;
  }
  return true;
}
示例#15
0
static Variant php_mcrypt_do_crypt(CStrRef cipher, CStrRef key, CStrRef data,
                                   CStrRef mode, CStrRef iv, bool dencrypt) {
  MCRYPT td = mcrypt_module_open((char*)cipher.data(),
                                 (char*)MCG(algorithms_dir).data(),
                                 (char*)mode.data(),
                                 (char*)MCG(modes_dir).data());
  if (td == MCRYPT_FAILED) {
    raise_warning(MCRYPT_OPEN_MODULE_FAILED);
    return false;
  }

  /* Checking for key-length */
  int max_key_length = mcrypt_enc_get_key_size(td);
  if (key.size() > max_key_length) {
    raise_warning("Size of key is too large for this algorithm");
  }
  int count;
  int *key_length_sizes = mcrypt_enc_get_supported_key_sizes(td, &count);
  int use_key_length;
  char *key_s = NULL;
  if (count == 0 && key_length_sizes == NULL) { // all lengths 1 - k_l_s = OK
    use_key_length = key.size();
    key_s = (char*)malloc(use_key_length);
    memcpy(key_s, key.data(), use_key_length);
  } else if (count == 1) {  /* only m_k_l = OK */
    key_s = (char*)malloc(key_length_sizes[0]);
    memset(key_s, 0, key_length_sizes[0]);
    memcpy(key_s, key.data(), MIN(key.size(), key_length_sizes[0]));
    use_key_length = key_length_sizes[0];
  } else { /* dertermine smallest supported key > length of requested key */
    use_key_length = max_key_length; /* start with max key length */
    for (int i = 0; i < count; i++) {
      if (key_length_sizes[i] >= key.size() &&
          key_length_sizes[i] < use_key_length) {
        use_key_length = key_length_sizes[i];
      }
    }
    key_s = (char*)malloc(use_key_length);
    memset(key_s, 0, use_key_length);
    memcpy(key_s, key.data(), MIN(key.size(), use_key_length));
  }
  mcrypt_free(key_length_sizes);

  /* Check IV */
  char *iv_s = NULL;
  int iv_size = mcrypt_enc_get_iv_size(td);

  /* IV is required */
  if (mcrypt_enc_mode_has_iv(td) == 1) {
    if (!iv.empty()) {
      if (iv_size != iv.size()) {
        raise_warning("The IV parameter must be as long as the blocksize");
      } else {
        iv_s = (char*)malloc(iv_size + 1);
        memcpy(iv_s, iv.data(), iv_size);
      }
    } else {
      raise_warning("Attempt to use an empty IV, which is NOT recommended");
      iv_s = (char*)malloc(iv_size + 1);
      memset(iv_s, 0, iv_size + 1);
    }
  }

  int block_size;
  unsigned long int data_size;
  String s;
  char *data_s;
  /* Check blocksize */
  if (mcrypt_enc_is_block_mode(td) == 1) { /* It's a block algorithm */
    block_size = mcrypt_enc_get_block_size(td);
    data_size = (((data.size() - 1) / block_size) + 1) * block_size;
    s = String(data_size, ReserveString);
    data_s = (char*)s.mutableSlice().ptr;
    memset(data_s, 0, data_size);
    memcpy(data_s, data.data(), data.size());
  } else { /* It's not a block algorithm */
    data_size = data.size();
    s = String(data_size, ReserveString);
    data_s = (char*)s.mutableSlice().ptr;
    memcpy(data_s, data.data(), data.size());
  }

  if (mcrypt_generic_init(td, key_s, use_key_length, iv_s) < 0) {
    raise_warning("Mcrypt initialisation failed");
    return false;
  }
  if (dencrypt) {
    mdecrypt_generic(td, data_s, data_size);
  } else {
    mcrypt_generic(td, data_s, data_size);
  }

  /* freeing vars */
  mcrypt_generic_end(td);
  if (key_s != NULL) {
    free(key_s);
  }
  if (iv_s != NULL) {
    free(iv_s);
  }
  return s.setSize(data_size);
}
示例#16
0
void f_gc_disable() {
  raise_warning("HipHop currently does not support circular reference "
                "collection");
}
示例#17
0
SSL *SSLSocket::createSSL(SSL_CTX *ctx) {
  ERR_clear_error();

  /* look at options in the stream and set appropriate verification flags */
  if (m_context[s_verify_peer].toBoolean()) {
    /* turn on verification callback */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verifyCallback);

    /* CA stuff */
    String cafile = m_context[s_cafile].toString();
    String capath = m_context[s_capath].toString();

    if (!cafile.empty() || !capath.empty()) {
      if (!SSL_CTX_load_verify_locations(ctx, cafile.data(), capath.data())) {
        raise_warning("Unable to set verify locations `%s' `%s'",
                      cafile.data(), capath.data());
        return nullptr;
      }
    }

    int64_t depth = m_context[s_verify_depth].toInt64();
    if (depth) {
      SSL_CTX_set_verify_depth(ctx, depth);
    }
  } else {
    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
  }

  /* callback for the passphrase (for localcert) */
  if (!m_context[s_passphrase].toString().empty()) {
    SSL_CTX_set_default_passwd_cb_userdata(ctx, this);
    SSL_CTX_set_default_passwd_cb(ctx, passwdCallback);
  }

  String cipherlist = m_context[s_ciphers].toString();
  if (cipherlist.empty()) {
    cipherlist = "DEFAULT";
  }
  SSL_CTX_set_cipher_list(ctx, cipherlist.data());

  String certfile = m_context[s_local_cert].toString();
  if (!certfile.empty()) {
    String resolved_path_buff = File::TranslatePath(certfile);
    if (!resolved_path_buff.empty()) {
      /* a certificate to use for authentication */
      if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data())
          != 1) {
        raise_warning("Unable to set local cert chain file `%s'; Check "
                      "that your cafile/capath settings include details of "
                      "your certificate and its issuer", certfile.data());
        return nullptr;
      }

      if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(),
                                      SSL_FILETYPE_PEM) != 1) {
        raise_warning("Unable to set private key file `%s'",
                      resolved_path_buff.data());
        return nullptr;
      }

      SSL *tmpssl = SSL_new(ctx);
      X509 *cert = SSL_get_certificate(tmpssl);
      if (cert) {
        EVP_PKEY *key = X509_get_pubkey(cert);
        EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
        EVP_PKEY_free(key);
      }
      SSL_free(tmpssl);

      if (!SSL_CTX_check_private_key(ctx)) {
        raise_warning("Private key does not match certificate!");
      }
    }
  }

  SSL *ssl = SSL_new(ctx);
  if (ssl) {
    SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */
  }
  return ssl;
}
示例#18
0
int64_t f_gc_collect_cycles() {
  raise_warning("HipHop currently does not support circular reference "
                "collection");
  return 0;
}
示例#19
0
bool SSLSocket::setupCrypto(SSLSocket *session /* = NULL */) {
  if (m_data->m_handle) {
    raise_warning("SSL/TLS already set-up for this stream");
    return false;
  }

  /* need to do slightly different things, based on client/server method,
   * so lets remember which method was selected */
#if OPENSSL_VERSION_NUMBER < 0x00909000L
  SSL_METHOD *smethod;
#else
  const SSL_METHOD *smethod;
#endif
  switch (m_data->m_method) {
  case CryptoMethod::ClientSSLv23:
    m_data->m_client = true;
    smethod = SSLv23_client_method();
    break;
  case CryptoMethod::ClientSSLv3:
    m_data->m_client = true;
    smethod = SSLv3_client_method();
    break;
  case CryptoMethod::ClientTLS:
    m_data->m_client = true;
    smethod = TLSv1_client_method();
    break;
  case CryptoMethod::ServerSSLv23:
    m_data->m_client = false;
    smethod = SSLv23_server_method();
    break;
  case CryptoMethod::ServerSSLv3:
    m_data->m_client = false;
    smethod = SSLv3_server_method();
    break;

  /* SSLv2 protocol might be disabled in the OpenSSL library */
#ifndef OPENSSL_NO_SSL2
  case CryptoMethod::ClientSSLv2:
    m_data->m_client = true;
    smethod = SSLv2_client_method();
    break;
  case CryptoMethod::ServerSSLv2:
    m_data->m_client = false;
    smethod = SSLv2_server_method();
    break;
#else
  case CryptoMethod::ClientSSLv2:
  case CryptoMethod::ServerSSLv2:
    raise_warning("OpenSSL library does not support SSL2 protocol");
    return false;
  break;
#endif

  case CryptoMethod::ServerTLS:
    m_data->m_client = false;
    smethod = TLSv1_server_method();
    break;
  default:
    return false;
  }

  SSL_CTX *ctx = SSL_CTX_new(smethod);
  if (ctx == nullptr) {
    raise_warning("failed to create an SSL context");
    return false;
  }

  SSL_CTX_set_options(ctx, SSL_OP_ALL);
  m_data->m_handle = createSSL(ctx);
  if (m_data->m_handle == nullptr) {
    raise_warning("failed to create an SSL handle");
    SSL_CTX_free(ctx);
    return false;
  }

  if (!SSL_set_fd(m_data->m_handle, getFd())) {
    handleError(0, true);
  }
  if (session) {
    SSL_copy_session_id(m_data->m_handle, session->m_data->m_handle);
  }
  return true;
}
示例#20
0
文件: ext_bz2.cpp 项目: hmic/hhvm
Variant HHVM_FUNCTION(bzopen, const Variant& filename, const String& mode) {
  if (mode != s_r && mode != s_w) {
    raise_warning(
      "'%s' is not a valid mode for bzopen(). "
      "Only 'w' and 'r' are supported.",
      mode.data()
    );
    return false;
  }

  BZ2File *bz;
  if (filename.isString()) {
    if (filename.asCStrRef().empty()) {
      raise_warning("filename cannot be empty");
      return false;
    }
    bz = newres<BZ2File>();
    bool ret = bz->open(File::TranslatePath(filename.toString()), mode);
    if (!ret) {
      raise_warning("%s", folly::errnoStr(errno).c_str());
      return false;
    }
  } else {
    if (!filename.isResource()) {
      raise_warning("first parameter has to be string or file-resource");
      return false;
    }
    PlainFile* f = filename.toResource().getTyped<PlainFile>();
    if (!f) {
      return false;
    }

    std::string stream_mode = f->getMode();
    int stream_mode_len = stream_mode.length();

    if (stream_mode_len != 1 &&
        !(stream_mode_len == 2 &&
          stream_mode.find('b') != std::string::npos)) {
      raise_warning("cannot use stream opened in mode '%s'",
                    stream_mode.c_str());
      return false;
    } else if (stream_mode_len == 1 &&
        stream_mode[0] != 'r' && stream_mode[0] != 'w' &&
        stream_mode[0] != 'a' && stream_mode[0] != 'x') {
      raise_warning("cannot use stream opened in mode '%s'",
                    stream_mode.c_str());
      return false;
    }

    const char rw_mode = stream_mode[0];
    if (mode == s_r && rw_mode != 'r') {
      raise_warning("cannot write to a stream opened in read only mode");
      return false;
    } else if (mode == s_w && rw_mode != 'w' && rw_mode != 'a' &&
               rw_mode != 'x') {
      raise_warning("cannot read from a stream opened in write only mode");
      return false;
    }

    bz = newres<BZ2File>(f);
  }
  Resource handle(bz);
  return handle;
}
示例#21
0
bool SSLSocket::enableCrypto(bool activate /* = true */) {
  if (activate && !m_data->m_ssl_active) {
    double timeout = m_data->m_connect_timeout;
    bool blocked = m_data->m_is_blocked;
    if (!m_data->m_state_set) {
      if (m_data->m_client) {
        SSL_set_connect_state(m_data->m_handle);
      } else {
        SSL_set_accept_state(m_data->m_handle);
      }
      m_data->m_state_set = true;
    }

    if (m_data->m_client && setBlocking(false)) {
      m_data->m_is_blocked = false;
    }

    int n;
    bool retry = true;
    do {
      if (m_data->m_client) {
        struct timeval tvs, tve;
        struct timezone tz;

        gettimeofday(&tvs, &tz);
        n = SSL_connect(m_data->m_handle);
        gettimeofday(&tve, &tz);

        timeout -= (tve.tv_sec + (double) tve.tv_usec / 1000000) -
          (tvs.tv_sec + (double) tvs.tv_usec / 1000000);
        if (timeout < 0) {
          raise_warning("SSL: connection timeout");
          return -1;
        }
      } else {
        n = SSL_accept(m_data->m_handle);
      }

      if (n <= 0) {
        retry = handleError(n, true);
      } else {
        break;
      }
    } while (retry);

    if (m_data->m_client &&
        m_data->m_is_blocked != blocked &&
        setBlocking(blocked)) {
      m_data->m_is_blocked = blocked;
    }

    if (n == 1) {
      X509 *peer_cert = SSL_get_peer_certificate(m_data->m_handle);
      if (!applyVerificationPolicy(peer_cert)) {
        SSL_shutdown(m_data->m_handle);
      } else {
        m_data->m_ssl_active = true;

        /* allow the script to capture the peer cert
         * and/or the certificate chain */
        if (m_context[s_capture_peer_cert].toBoolean()) {
          m_context.set(s_peer_certificate,
                        Variant(makeSmartPtr<Certificate>(peer_cert)));
          peer_cert = nullptr;
        }

        if (m_context[s_capture_peer_cert_chain].toBoolean()) {
          Array arr;
          STACK_OF(X509) *chain = SSL_get_peer_cert_chain(m_data->m_handle);
          if (chain) {
            for (int i = 0; i < sk_X509_num(chain); i++) {
              X509 *mycert = X509_dup(sk_X509_value(chain, i));
              arr.append(Variant(makeSmartPtr<Certificate>(mycert)));
            }
          }
          m_context.set(s_peer_certificate_chain, arr);
        }
      }

      if (peer_cert) {
        X509_free(peer_cert);
      }
    } else  {
      n = errno == EAGAIN ? 0 : -1;
    }

    return n >= 0;

  } else if (!activate && m_data->m_ssl_active) {
    /* deactivate - common for server/client */
    SSL_shutdown(m_data->m_handle);
    m_data->m_ssl_active = false;
  }
  return true;
}
示例#22
0
bool Transport::setCookie(CStrRef name, CStrRef value, int64_t expire /* = 0 */,
                          CStrRef path /* = "" */, CStrRef domain /* = "" */,
                          bool secure /* = false */,
                          bool httponly /* = false */,
                          bool encode_url /* = true */) {
  if (!name.empty() && strpbrk(name.data(), "=,; \t\r\n\013\014")) {
    Logger::Warning("Cookie names can not contain any of the following "
                    "'=,; \\t\\r\\n\\013\\014'");
    return false;
  }

  if (!encode_url &&
      !value.empty() && strpbrk(value.data(), ",; \t\r\n\013\014")) {
    Logger::Warning("Cookie values can not contain any of the following "
                    "',; \\t\\r\\n\\013\\014'");
    return false;
  }

  char *encoded_value = nullptr;
  int len = 0;
  if (!value.empty() && encode_url) {
    int encoded_value_len = value.size();
    encoded_value = url_encode(value.data(), encoded_value_len);
    len += encoded_value_len;
  } else if (!value.empty()) {
    encoded_value = strdup(value.data());
    len += value.size();
  }
  len += path.size();
  len += domain.size();

  std::string cookie;
  cookie.reserve(len + 100);
  if (value.empty()) {
    /*
     * MSIE doesn't delete a cookie when you set it to a null value
     * so in order to force cookies to be deleted, even on MSIE, we
     * pick an expiry date in the past
     */
    String sdt = DateTime(1, true).toString(DateTime::DateFormat::Cookie);
    cookie += name.data();
    cookie += "=deleted; expires=";
    cookie += sdt.data();
  } else {
    cookie += name.data();
    cookie += "=";
    cookie += encoded_value ? encoded_value : "";
    if (expire > 0) {
      if (expire > 253402300799LL) {
        raise_warning("Expiry date cannot have a year greater then 9999");
        return false;
      }
      cookie += "; expires=";
      String sdt =
        DateTime(expire, true).toString(DateTime::DateFormat::Cookie);
      cookie += sdt.data();
    }
  }

  if (encoded_value) {
    free(encoded_value);
  }

  if (!path.empty()) {
    cookie += "; path=";
    cookie += path.data();
  }
  if (!domain.empty()) {
    cookie += "; domain=";
    cookie += domain.data();
  }
  if (secure) {
    cookie += "; secure";
  }
  if (httponly) {
    cookie += "; httponly";
  }

  m_responseCookies[name.data()] = cookie;
  return true;
}
示例#23
0
req::ptr<File>
HttpStreamWrapper::open(const String& filename,
                        const String& mode,
                        int options,
                        const req::ptr<StreamContext>& context) {
  if (RuntimeOption::ServerHttpSafeMode && !is_cli_mode()) {
    return nullptr;
  }

  if (strncmp(filename.data(), "http://",  sizeof("http://")  - 1) &&
      strncmp(filename.data(), "https://", sizeof("https://") - 1)) {
    return nullptr;
  }

  Array headers;
  String method = s_GET;
  String post_data = null_string;
  String proxy_host;
  String proxy_user;
  String proxy_pass;
  int proxy_port = -1;
  int max_redirs = 20;
  int timeout = -1;
  bool ignore_errors = false;

  if (context && !context->getOptions().isNull() &&
      !context->getOptions()[s_http].isNull()) {
    Array opts = context->getOptions()[s_http].toArray();
    if (opts.exists(s_method)) {
      method = opts[s_method].toString();
    }
    if (opts.exists(s_header)) {
      Array lines;
      if (opts[s_header].isString()) {
        lines = StringUtil::Explode(
          opts[s_header].toString(), "\r\n").toArray();
      } else if (opts[s_header].isArray()) {
        lines = opts[s_header];
      }

      for (ArrayIter it(lines); it; ++it) {
        Array parts = StringUtil::Explode(
          it.second().toString(), ":", 2).toArray();
        headers.set(parts.rvalAt(0), parts.rvalAt(1));
      }
    }
    if (opts.exists(s_user_agent) && !headers.exists(s_User_Agent)) {
      headers.set(s_User_Agent, opts[s_user_agent]);
    }
    if (opts.exists(s_max_redirects)) {
      max_redirs = opts[s_max_redirects].toInt64();
    }
    if (opts.exists(s_timeout)) {
      timeout = opts[s_timeout].toInt64();
    }
    if (opts.exists(s_ignore_errors)) {
      ignore_errors = opts[s_ignore_errors].toBoolean();
    }
    if (opts.exists(s_proxy)) {
      Variant host = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_HOST);
      Variant port = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_PORT);
      if (!same(host, false) && !same(port, false)) {
        proxy_host = host.toString();
        proxy_port = port.toInt64();
        Variant user = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_USER);
        Variant pass = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_PASS);
        if (!same(user, false) && !same(pass, false)) {
          proxy_user = user.toString();
          proxy_pass = pass.toString();
        }
      }
    }
    post_data = opts[s_content].toString();
  }

  if (!headers.exists(s_User_Agent)) {
    auto default_user_agent = ThreadInfo::s_threadInfo.getNoCheck()
      ->m_reqInjectionData.getUserAgent();
    if (!default_user_agent.empty()) {
      headers.set(s_User_Agent, default_user_agent);
    }
  }
  auto file = req::make<UrlFile>(method.data(), headers,
                                    post_data, max_redirs,
                                    timeout, ignore_errors);
  file->setStreamContext(context);
  file->setProxy(proxy_host, proxy_port, proxy_user, proxy_pass);
  bool ret = file->open(filename, mode);
  if (!ret) {
    raise_warning("Failed to open %s (%s)", filename.data(),
                  file->getLastError().c_str());
    return nullptr;
  }
  return file;
}
示例#24
0
void Transport::prepareHeaders(bool compressed, bool chunked,
    const String &response, const String& orig_response) {
  for (HeaderMap::const_iterator iter = m_responseHeaders.begin();
       iter != m_responseHeaders.end(); ++iter) {
    const vector<string> &values = iter->second;
    for (unsigned int i = 0; i < values.size(); i++) {
      addHeaderImpl(iter->first.c_str(), values[i].c_str());
    }
  }

  for (CookieMap::const_iterator iter = m_responseCookies.begin();
       iter != m_responseCookies.end(); ++iter) {
    addHeaderImpl("Set-Cookie", iter->second.c_str());
  }

  if (compressed) {
    addHeaderImpl("Content-Encoding", "gzip");
    removeHeaderImpl("Content-Length");
    // Remove the Content-MD5 header coming from PHP if we compressed the data,
    // as the checksum is going to be invalid.
    auto it = m_responseHeaders.find("Content-MD5");
    if (it != m_responseHeaders.end()) {
      removeHeaderImpl("Content-MD5");
      // Re-add it back unless this is a chunked response. We'd have to buffer
      // the response completely to compute the MD5, which defeats the purpose
      // of chunking.
      if (chunked) {
        raise_warning("Cannot use chunked HTTP response and Content-MD5 header "
          "at the same time. Dropping Content-MD5.");
      } else {
        string cur_md5 = it->second[0];
        String expected_md5 = StringUtil::Base64Encode(StringUtil::MD5(
          orig_response, true));
        // Can never trust these PHP people...
        if (expected_md5.c_str() != cur_md5) {
          raise_warning("Content-MD5 mismatch. Expected: %s, Got: %s",
            expected_md5.c_str(), cur_md5.c_str());
        }
        addHeaderImpl("Content-MD5", StringUtil::Base64Encode(StringUtil::MD5(
          response, true)).c_str());
      }
    }
  }

  if (m_responseHeaders.find("Content-Type") == m_responseHeaders.end() &&
      m_responseCode != 304) {
    string contentType = "text/html; charset="
                         + RuntimeOption::DefaultCharsetName;
    addHeaderImpl("Content-Type", contentType.c_str());
  }

  if (RuntimeOption::ExposeHPHP) {
    addHeaderImpl("X-Powered-By", "HPHP");
  }

  if ((RuntimeOption::ExposeXFBServer || RuntimeOption::ExposeXFBDebug) &&
      !RuntimeOption::XFBDebugSSLKey.empty() &&
      m_responseHeaders.find("X-FB-Debug") == m_responseHeaders.end()) {
    String ip = RuntimeOption::ServerPrimaryIP;
    String key = RuntimeOption::XFBDebugSSLKey;
    String cipher("AES-256-CBC");
    int iv_len = f_openssl_cipher_iv_length(cipher).toInt32();
    String iv = f_openssl_random_pseudo_bytes(iv_len);
    String encrypted =
      f_openssl_encrypt(ip, cipher, key, k_OPENSSL_RAW_DATA, iv);
    String output = StringUtil::Base64Encode(iv + encrypted);
    if (debug) {
      String decrypted =
        f_openssl_decrypt(encrypted, cipher, key, k_OPENSSL_RAW_DATA, iv);
      assert(decrypted->same(ip.get()));
    }
    addHeaderImpl("X-FB-Debug", output.c_str());
  }

  // shutting down servers, so need to terminate all Keep-Alive connections
  if (!RuntimeOption::EnableKeepAlive || isServerStopping()) {
    addHeaderImpl("Connection", "close");
    removeHeaderImpl("Keep-Alive");

    // so lower level transports can ignore incoming "Connection: keep-alive"
    removeRequestHeaderImpl("Connection");
  }
}
示例#25
0
  bool setOption(long option, CVarRef value) {
    if (m_cp == NULL) {
      return false;
    }
    m_error_no = CURLE_OK;

    switch (option) {
    case CURLOPT_INFILESIZE:
    case CURLOPT_VERBOSE:
    case CURLOPT_HEADER:
    case CURLOPT_NOPROGRESS:
    case CURLOPT_NOBODY:
    case CURLOPT_FAILONERROR:
    case CURLOPT_UPLOAD:
    case CURLOPT_POST:
    case CURLOPT_FTPLISTONLY:
    case CURLOPT_FTPAPPEND:
    case CURLOPT_NETRC:
    case CURLOPT_PUT:
    case CURLOPT_TIMEOUT:
#if LIBCURL_VERSION_NUM >= 0x071002
    case CURLOPT_TIMEOUT_MS:
#endif
    case CURLOPT_FTP_USE_EPSV:
    case CURLOPT_LOW_SPEED_LIMIT:
    case CURLOPT_SSLVERSION:
    case CURLOPT_LOW_SPEED_TIME:
    case CURLOPT_RESUME_FROM:
    case CURLOPT_TIMEVALUE:
    case CURLOPT_TIMECONDITION:
    case CURLOPT_TRANSFERTEXT:
    case CURLOPT_HTTPPROXYTUNNEL:
    case CURLOPT_FILETIME:
    case CURLOPT_MAXREDIRS:
    case CURLOPT_MAXCONNECTS:
    case CURLOPT_CLOSEPOLICY:
    case CURLOPT_FRESH_CONNECT:
    case CURLOPT_FORBID_REUSE:
    case CURLOPT_CONNECTTIMEOUT:
#if LIBCURL_VERSION_NUM >= 0x071002
    case CURLOPT_CONNECTTIMEOUT_MS:
#endif
    case CURLOPT_SSL_VERIFYHOST:
    case CURLOPT_SSL_VERIFYPEER:
      //case CURLOPT_DNS_USE_GLOBAL_CACHE: not thread-safe when set to true
    case CURLOPT_NOSIGNAL:
    case CURLOPT_PROXYTYPE:
    case CURLOPT_BUFFERSIZE:
    case CURLOPT_HTTPGET:
    case CURLOPT_HTTP_VERSION:
    case CURLOPT_CRLF:
    case CURLOPT_DNS_CACHE_TIMEOUT:
    case CURLOPT_PROXYPORT:
    case CURLOPT_FTP_USE_EPRT:
    case CURLOPT_HTTPAUTH:
    case CURLOPT_PROXYAUTH:
    case CURLOPT_FTP_CREATE_MISSING_DIRS:
    case CURLOPT_FTPSSLAUTH:
    case CURLOPT_FTP_SSL:
    case CURLOPT_UNRESTRICTED_AUTH:
    case CURLOPT_PORT:
    case CURLOPT_AUTOREFERER:
    case CURLOPT_COOKIESESSION:
    case CURLOPT_TCP_NODELAY:
    case CURLOPT_IPRESOLVE:
    case CURLOPT_FOLLOWLOCATION:
      m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, value.toInt64());
      break;
    case CURLOPT_RETURNTRANSFER:
      m_write.method = value.toBoolean() ? PHP_CURL_RETURN : PHP_CURL_STDOUT;
      break;
    case CURLOPT_BINARYTRANSFER:
      m_write.type = value.toBoolean() ? PHP_CURL_BINARY : PHP_CURL_ASCII;
      break;
    case CURLOPT_PRIVATE:
    case CURLOPT_URL:
    case CURLOPT_PROXY:
    case CURLOPT_USERPWD:
    case CURLOPT_PROXYUSERPWD:
    case CURLOPT_RANGE:
    case CURLOPT_CUSTOMREQUEST:
    case CURLOPT_USERAGENT:
    case CURLOPT_FTPPORT:
    case CURLOPT_COOKIE:
    case CURLOPT_REFERER:
    case CURLOPT_INTERFACE:
    case CURLOPT_KRB4LEVEL:
    case CURLOPT_EGDSOCKET:
    case CURLOPT_CAINFO:
    case CURLOPT_CAPATH:
    case CURLOPT_SSL_CIPHER_LIST:
    case CURLOPT_SSLKEY:
    case CURLOPT_SSLKEYTYPE:
    case CURLOPT_SSLKEYPASSWD:
    case CURLOPT_SSLENGINE:
    case CURLOPT_SSLENGINE_DEFAULT:
    case CURLOPT_SSLCERTTYPE:
    case CURLOPT_ENCODING:
    case CURLOPT_COOKIEJAR:
    case CURLOPT_SSLCERT:
    case CURLOPT_RANDOM_FILE:
    case CURLOPT_COOKIEFILE:
      {
        String svalue = value.toString();
#if LIBCURL_VERSION_NUM >= 0x071100
        /* Strings passed to libcurl as 'char *' arguments, are copied
           by the library... NOTE: before 7.17.0 strings were not copied. */
        m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, svalue.c_str());
#else
        char *copystr = strndup(svalue.data(), svalue.size());
        m_to_free->str.push_back(copystr);
        m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, copystr);
#endif
        if (option == CURLOPT_URL) m_url = value;
      }
      break;
    case CURLOPT_FILE:
    case CURLOPT_INFILE:
    case CURLOPT_WRITEHEADER:
    case CURLOPT_STDERR:
      {
        if (!value.is(KindOfObject)) {
          return false;
        }

        Object obj = value.toObject();
        if (obj.isNull() || obj.getTyped<File>(true) == NULL) {
          return false;
        }

        switch (option) {
          case CURLOPT_FILE:
            m_write.fp = obj;
            m_write.method = PHP_CURL_FILE;
            break;
          case CURLOPT_WRITEHEADER:
            m_write_header.fp = obj;
            m_write_header.method = PHP_CURL_FILE;
            break;
          case CURLOPT_INFILE:
            m_read.fp = obj;
            m_emptyPost = false;
            break;
          default: {
            if (obj.getTyped<PlainFile>(true) == NULL) {
              return false;
            }
            FILE *fp = obj.getTyped<PlainFile>()->getStream();
            if (!fp) {
              return false;
            }
            m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, fp);
            break;
          }
        }
      }
      break;
    case CURLOPT_WRITEFUNCTION:
      m_write.callback = value;
      m_write.method = PHP_CURL_USER;
      break;
    case CURLOPT_READFUNCTION:
      m_read.callback = value;
      m_read.method = PHP_CURL_USER;
      m_emptyPost = false;
      break;
    case CURLOPT_HEADERFUNCTION:
      m_write_header.callback = value;
      m_write_header.method = PHP_CURL_USER;
      break;
    case CURLOPT_POSTFIELDS:
      m_emptyPost = false;
      if (value.is(KindOfArray) || value.is(KindOfObject)) {
        Array arr = value.toArray();
        curl_httppost *first = NULL;
        curl_httppost *last  = NULL;
        for (ArrayIter iter(arr); iter; ++iter) {
          String key = iter.first().toString();
          String val = iter.second().toString();
          const char *postval = val.data();

          /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
           * must be explicitly cast to long in curl_formadd
           * use since curl needs a long not an int. */
          if (*postval == '@') {
            ++postval;
            m_error_no = (CURLcode)curl_formadd
              (&first, &last,
               CURLFORM_COPYNAME, key.data(),
               CURLFORM_NAMELENGTH, (long)key.size(),
               CURLFORM_FILE, postval,
               CURLFORM_END);
          } else {
            m_error_no = (CURLcode)curl_formadd
              (&first, &last,
               CURLFORM_COPYNAME, key.data(),
               CURLFORM_NAMELENGTH, (long)key.size(),
               CURLFORM_COPYCONTENTS, postval,
               CURLFORM_CONTENTSLENGTH,(long)val.size(),
               CURLFORM_END);
          }
        }

        if (m_error_no != CURLE_OK) {
          return false;
        }

        m_to_free->post.push_back(first);
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_HTTPPOST, first);

      } else {
        String svalue = value.toString();
#if LIBCURL_VERSION_NUM >= 0x071100
        /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS,
           but we have to provide size before */
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_POSTFIELDSIZE,
                                      svalue.size());
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_COPYPOSTFIELDS,
                                      svalue.c_str());
#else
        char *post = strndup(svalue.data(), svalue.size());
        m_to_free->str.push_back(post);

        m_error_no = curl_easy_setopt(m_cp, CURLOPT_POSTFIELDS, post);
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_POSTFIELDSIZE,
                                      svalue.size());
#endif
      }
      break;
    case CURLOPT_HTTPHEADER:
    case CURLOPT_QUOTE:
    case CURLOPT_HTTP200ALIASES:
    case CURLOPT_POSTQUOTE:
      if (value.is(KindOfArray) || value.is(KindOfObject)) {
        Array arr = value.toArray();
        curl_slist *slist = NULL;
        for (ArrayIter iter(arr); iter; ++iter) {
          String key = iter.first().toString();
          String val = iter.second().toString();

          slist = curl_slist_append(slist, val.c_str());
          if (!slist) {
            raise_warning("Could not build curl_slist");
            return false;
          }
        }

        m_to_free->slist.push_back(slist);
        m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, slist);

      } else {
        raise_warning("You must pass either an object or an array with "
                      "the CURLOPT_HTTPHEADER, CURLOPT_QUOTE, "
                      "CURLOPT_HTTP200ALIASES and CURLOPT_POSTQUOTE "
                      "arguments");
        return false;
      }
      break;

    case CURLINFO_HEADER_OUT:
      if (value.toInt64() == 1) {
        curl_easy_setopt(m_cp, CURLOPT_DEBUGFUNCTION, curl_debug);
        curl_easy_setopt(m_cp, CURLOPT_DEBUGDATA, (void *)this);
        curl_easy_setopt(m_cp, CURLOPT_VERBOSE, 1);
      } else {
        curl_easy_setopt(m_cp, CURLOPT_DEBUGFUNCTION, NULL);
        curl_easy_setopt(m_cp, CURLOPT_DEBUGDATA, NULL);
        curl_easy_setopt(m_cp, CURLOPT_VERBOSE, 0);
      }
      break;

    default:
      m_error_no = CURLE_FAILED_INIT;
      throw_invalid_argument("option: %d", option);
      break;
    }

    m_opts.set(int64(option), value);

    return m_error_no == CURLE_OK;
  }
示例#26
0
Variant HHVM_FUNCTION(dns_get_record, const String& hostname, int type /*= -1*/,
                      VRefParam authnsRef /* = null */,
                      VRefParam addtlRef /* = null */) {
    IOStatusHelper io("dns_get_record", hostname.data(), type);
    if (type < 0) type = PHP_DNS_ALL;
    if (type & ~PHP_DNS_ALL && type != PHP_DNS_ANY) {
        raise_warning("Type '%d' not supported", type);
        return false;
    }

    unsigned char *cp = NULL, *end = NULL;
    int qd, an, ns = 0, ar = 0;
    querybuf answer;

    /* - We emulate an or'ed type mask by querying type by type.
     *   (Steps 0 - NUMTYPES-1 )
     *   If additional info is wanted we check again with DNS_T_ANY
     *   (step NUMTYPES / NUMTYPES+1 )
     *   store_results is used to skip storing the results retrieved in step
     *   NUMTYPES+1 when results were already fetched.
     * - In case of PHP_DNS_ANY we use the directly fetch DNS_T_ANY.
     *   (step NUMTYPES+1 )
     */
    Array ret;
    bool first_query = true;
    bool store_results = true;
    for (int t = (type == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
            t < PHP_DNS_NUM_TYPES + 2 || first_query; t++) {
        first_query = false;
        int type_to_fetch;
        switch (t) {
        case 0:
            type_to_fetch = type & PHP_DNS_A     ? DNS_T_A     : 0;
            break;
        case 1:
            type_to_fetch = type & PHP_DNS_NS    ? DNS_T_NS    : 0;
            break;
        case 2:
            type_to_fetch = type & PHP_DNS_CNAME ? DNS_T_CNAME : 0;
            break;
        case 3:
            type_to_fetch = type & PHP_DNS_SOA   ? DNS_T_SOA   : 0;
            break;
        case 4:
            type_to_fetch = type & PHP_DNS_PTR   ? DNS_T_PTR   : 0;
            break;
        case 5:
            type_to_fetch = type & PHP_DNS_HINFO ? DNS_T_HINFO : 0;
            break;
        case 6:
            type_to_fetch = type & PHP_DNS_MX    ? DNS_T_MX    : 0;
            break;
        case 7:
            type_to_fetch = type & PHP_DNS_TXT   ? DNS_T_TXT   : 0;
            break;
        case 8:
            type_to_fetch = type & PHP_DNS_AAAA  ? DNS_T_AAAA  : 0;
            break;
        case 9:
            type_to_fetch = type & PHP_DNS_SRV   ? DNS_T_SRV   : 0;
            break;
        case 10:
            type_to_fetch = type & PHP_DNS_NAPTR ? DNS_T_NAPTR : 0;
            break;
        case 11:
            type_to_fetch = type & PHP_DNS_A6    ? DNS_T_A6    : 0;
            break;
        case PHP_DNS_NUM_TYPES:
            store_results = false;
            continue;
        default:
        case (PHP_DNS_NUM_TYPES + 1):
            type_to_fetch = DNS_T_ANY;
            break;
        }
        if (!type_to_fetch) continue;

        struct __res_state *res;
        res = ResolverInit::s_res.get()->getResolver();
        if (res == NULL) {
            return false;
        }

        int n = res_nsearch(res, hostname.data(), C_IN, type_to_fetch,
                            answer.qb2, sizeof answer);
        if (n < 0) {
            res_nclose(res);
            php_dns_free_res(res);
            continue;
        }

        HEADER *hp;
        cp = answer.qb2 + HFIXEDSZ;
        end = answer.qb2 + n;
        hp = (HEADER *)&answer;
        qd = ntohs(hp->qdcount);
        an = ntohs(hp->ancount);
        ns = ntohs(hp->nscount);
        ar = ntohs(hp->arcount);

        /* Skip QD entries, they're only used by dn_expand later on */
        while (qd-- > 0) {
            n = dn_skipname(cp, end);
            if (n < 0) {
                raise_warning("Unable to parse DNS data received");
                res_nclose(res);
                php_dns_free_res(res);
                return false;
            }
            cp += n + QFIXEDSZ;
        }

        /* YAY! Our real answers! */
        while (an-- && cp && cp < end) {
            Array retval;
            cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, retval);
            if (!retval.empty() && store_results) {
                ret.append(retval);
            }
        }
        res_nclose(res);
        php_dns_free_res(res);
    }

    Array authns;
    Array addtl;

    /* List of Authoritative Name Servers */
    while (ns-- > 0 && cp && cp < end) {
        Array retval;
        cp = php_parserr(cp, end, &answer, DNS_T_ANY, true, retval);
        if (!retval.empty()) {
            authns.append(retval);
        }
    }

    /* Additional records associated with authoritative name servers */
    while (ar-- > 0 && cp && cp < end) {
        Array retval;
        cp = php_parserr(cp, end, &answer, DNS_T_ANY, true, retval);
        if (!retval.empty()) {
            addtl.append(retval);
        }
    }

    authnsRef = authns;
    addtlRef = addtl;
    return ret;
}
示例#27
0
ArrayData* GlobalsArray::EscalateForSort(ArrayData* ad, SortFunction sf) {
  raise_warning("Sorting the $GLOBALS array is not supported");
  return ad;
}
示例#28
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 = HHVM_FN(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) ||
                (header.size() >= 7 && strncasecmp(header_line, "Status:", 7) == 0)) {
            int code = 200;
            const char *reason = nullptr;
            for (const char *ptr = header_line + 5; *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);
        }
    }
}
示例#29
0
void Object::setToDefaultObject() {
    raise_warning(Strings::CREATING_DEFAULT_OBJECT);
    operator=(SystemLib::AllocStdClassObject());
}
示例#30
0
Variant HHVM_FUNCTION(getaddrinfo,
                      const String& host,
                      const String& port,
                      int family /* = 0 */,
                      int socktype /* = 0 */,
                      int protocol /* = 0 */,
                      int flags /* = 0 */) {
  const char *hptr = NULL, *pptr = NULL;
  if (!host.empty()) {
    hptr = host.c_str();
  }
  if (!port.empty()) {
    pptr = port.c_str();
  }

  struct addrinfo hints, *res;
  struct addrinfo *res0 = NULL;
  int error;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = family;
  hints.ai_socktype = socktype;
  hints.ai_protocol = protocol;
  hints.ai_flags = flags;
  error = getaddrinfo(hptr, pptr, &hints, &res0);

  if (error) {
    raise_warning("%s", gai_strerror(error));

    if (res0) {
      freeaddrinfo(res0);
    }
    return false;
  }

  Array ret = Array::Create();

  for (res = res0; res; res = res->ai_next) {
    Array data = make_map_array(
      s_family, res->ai_family,
      s_socktype, res->ai_socktype,
      s_protocol, res->ai_protocol
    );

    switch (res->ai_addr->sa_family) {
      case AF_INET:
      {
        struct sockaddr_in *a;
        String buffer = ipaddr_convert(res->ai_addr, sizeof(*a));
        if (!buffer.empty()) {
          a = (struct sockaddr_in *)res->ai_addr;
          data.set(
            s_sockaddr,
            make_map_array(
              s_address, buffer,
              s_port, ntohs(a->sin_port)
            )
          );
        }
        break;
      }
      case AF_INET6:
      {
        struct sockaddr_in6 *a;
        String buffer = ipaddr_convert(res->ai_addr, sizeof(*a));
        if (!buffer.empty()) {
          a = (struct sockaddr_in6 *)res->ai_addr;
          data.set(
            s_sockaddr,
            make_map_array(
              s_address, buffer,
              s_port, ntohs(a->sin6_port),
              s_flow_info, (int32_t)a->sin6_flowinfo,
              s_scope_id, (int32_t)a->sin6_scope_id
            )
          );
        }
        break;
      }
      default:
        data.set(s_sockaddr, empty_array());
        break;
    }

    ret.append(data);
  }

  if (res0) {
    freeaddrinfo(res0);
  }

  return ret;
}