static File* phpStreamOpenFilter(const char* sFilter,
                                 const String& modestr,
                                 int options, const Variant& context) {
  const char *mode = modestr.c_str();
  int rwMode = 0;
  if (strchr(mode, 'r') || strchr(mode, '+')) {
    rwMode |= k_STREAM_FILTER_READ;
  }
  if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
    rwMode |= k_STREAM_FILTER_WRITE;
  }

  String duppath(sFilter, CopyString);
  char *path = duppath.bufferSlice().ptr;
  char *p = strstr(path, "/resource=");
  if (!p) {
    raise_recoverable_error("No URL resource specified");
    return nullptr;
  }
  Resource fpres = File::Open(String(p + sizeof("/resource=") - 1, CopyString),
                              modestr, options, context);
  if (fpres.isNull()) {
    return nullptr;
  }
  *p = 0;
  char *token = nullptr;
  p = strtok_r(path + 1, "/", &token);
  while (p) {
    if (!strncasecmp(p, "read=", sizeof("read=") - 1)) {
      phpStreamApplyFilterList(fpres, p + sizeof("read=") - 1,
                               k_STREAM_FILTER_READ);
    } else if (!strncasecmp(p, "write=", sizeof("write=") - 1)) {
      phpStreamApplyFilterList(fpres, p + sizeof("write=") - 1,
                               k_STREAM_FILTER_WRITE);
    } else {
      phpStreamApplyFilterList(fpres, p, rwMode);
    }
    p = strtok_r(nullptr, "/", &token);
  }
  return dynamic_cast<File*>(fpres.detach());
}