Пример #1
0
Variant f_qlzuncompress(CStrRef data, int level /* = 1 */) {
#ifndef HAVE_QUICKLZ
  throw NotSupportedException(__func__, "QuickLZ library cannot be found");
#else
  if (level < 1 || level > 3) {
    throw_invalid_argument("level: %d", level);
    return false;
  }

  if (data.size() < 9) {
    raise_notice("passing invalid data to qlzuncompress()");
    return false;
  }

  size_t size = QuickLZ1::qlz_size_decompressed(data.data());
  if ((int64)size < 0 ||
      (RuntimeOption::SerializationSizeLimit > 0 &&
       (int64)size > RuntimeOption::SerializationSizeLimit)) {
    raise_notice("invalid size in compressed header: %zd", size);
    return false;
  }

  String s = String(size, ReserveString);
  char *decompressed = s.mutableSlice().ptr;
  size_t dsize = 0;

  switch (level) {
    case 1: {
      QuickLZ1::qlz_state_decompress state;
      memset(&state, 0, sizeof(state));
      dsize = QuickLZ1::qlz_decompress(data.data(), decompressed, &state);
      break;
    }
    case 2: {
      QuickLZ2::qlz_state_decompress state;
      memset(&state, 0, sizeof(state));
      dsize = QuickLZ2::qlz_decompress(data.data(), decompressed, &state);
      break;
    }
    case 3: {
      QuickLZ3::qlz_state_decompress *state =
        new QuickLZ3::qlz_state_decompress();
      memset(state, 0, sizeof(*state));
      dsize = QuickLZ3::qlz_decompress(data.data(), decompressed, state);
      delete state;
      break;
    }
  }

  assert(dsize == size);
  return s.setSize(dsize);
#endif
}
Пример #2
0
Variant HHVM_FUNCTION(snuncompress, const String& data) {
  size_t dsize;

  snappy::GetUncompressedLength(data.data(), data.size(), &dsize);
  String s = String(dsize, ReserveString);
  char *uncompressed = s.bufferSlice().ptr;

  if (!snappy::RawUncompress(data.data(), data.size(), uncompressed)) {
    return false;
  }
  return s.setSize(dsize);
}
Пример #3
0
Variant HHVM_FUNCTION(qlzuncompress, const String& data, int level /* = 1 */) {
  if (level < 1 || level > 3) {
    throw_invalid_argument("level: %d", level);
    return false;
  }

  if (data.size() < 9) {
    raise_notice("passing invalid data to qlzuncompress()");
    return false;
  }

  size_t size = QuickLZ1::qlz_size_decompressed(data.data());
  if ((int64_t)size < 0 ||
      (RuntimeOption::SerializationSizeLimit > 0 &&
       (int64_t)size > RuntimeOption::SerializationSizeLimit)) {
    raise_notice("invalid size in compressed header: %zd", size);
    return false;
  }

  String s = String(size, ReserveString);
  char *decompressed = s.bufferSlice().ptr;
  size_t dsize = 0;

  switch (level) {
    case 1: {
      QuickLZ1::qlz_state_decompress state;
      memset(&state, 0, sizeof(state));
      dsize = QuickLZ1::qlz_decompress(data.data(), decompressed, &state);
      break;
    }
    case 2: {
      QuickLZ2::qlz_state_decompress state;
      memset(&state, 0, sizeof(state));
      dsize = QuickLZ2::qlz_decompress(data.data(), decompressed, &state);
      break;
    }
    case 3: {
      QuickLZ3::qlz_state_decompress *state =
        new QuickLZ3::qlz_state_decompress();
      memset(state, 0, sizeof(*state));
      dsize = QuickLZ3::qlz_decompress(data.data(), decompressed, state);
      delete state;
      break;
    }
  }

  if (dsize != size) {
    return false;
  }
  return s.setSize(dsize);
}
Пример #4
0
Variant HHVM_FUNCTION(lz4uncompress, const String& compressed) {
  const char* compressed_ptr = compressed.data();
  int dsize = VarintDecode(&compressed_ptr, compressed.size());
  if (dsize < 0) {
    return false;
  }

  String s = String(dsize, ReserveString);
  char *uncompressed = s.bufferSlice().ptr;
  int ret = LZ4_uncompress(compressed_ptr, uncompressed, dsize);

  if (ret <= 0) {
    return false;
  }
  return s.setSize(dsize);
}
Пример #5
0
Variant f_snuncompress(CStrRef data) {
#ifndef HAVE_SNAPPY
  throw NotSupportedException(__func__, "Snappy library cannot be found");
#else
  size_t dsize;

  snappy::GetUncompressedLength(data.data(), data.size(), &dsize);
  String s = String(dsize, ReserveString);
  char *uncompressed = s.mutableSlice().ptr;

  if (!snappy::RawUncompress(data.data(), data.size(), uncompressed)) {
    return false;
  }
  return s.setSize(dsize);
#endif
}
Пример #6
0
Variant f_lz4uncompress(CStrRef compressed) {
  const char* compressed_ptr = compressed.data();
  int dsize = VarintDecode(&compressed_ptr, compressed.size());
  if (dsize < 0) {
    return false;
  }

  String s = String(dsize, ReserveString);
  char *uncompressed = s.mutableSlice().ptr;
  int ret = LZ4_uncompress(compressed_ptr, uncompressed, dsize);

  if (ret <= 0) {
    return false;
  }
  return s.setSize(dsize);
}
Пример #7
0
Файл: icu.cpp Проект: fdbzn/hhvm
String u16(const char *u8, int32_t u8_len, UErrorCode &error) {
  error = U_ZERO_ERROR;
  int32_t outlen = ucnv_toUChars(s_intl_request->utf8(),
                                 nullptr, 0, u8, u8_len, &error);
  if (error != U_BUFFER_OVERFLOW_ERROR) {
    return uninit_null();
  }
  String ret = String(sizeof(UChar) * (outlen + 1), ReserveString);
  UChar *out = (UChar*)ret->mutableData();
  error = U_ZERO_ERROR;
  outlen = ucnv_toUChars(s_intl_request->utf8(),
                         out, outlen + 1, u8, u8_len, &error);
  if (U_FAILURE(error)) {
    return uninit_null();
  }
  ret.setSize(outlen * sizeof(UChar));
  return ret;
}
Пример #8
0
static Variant php_hash_do_hash_hmac(CStrRef algo, CStrRef data,
                                     bool isfilename, CStrRef key,
                                     bool raw_output /* = false */) {
  HashEnginePtr ops = php_hash_fetch_ops(algo);
  if (!ops) {
    raise_warning("Unknown hashing algorithm: %s", algo.data());
    return false;
  }
  Variant f;
  if (isfilename) {
    f = f_fopen(data, "rb");
    if (same(f, false)) {
      return false;
    }
  }

  void *context = malloc(ops->context_size);
  ops->hash_init(context);

  char *K = prepare_hmac_key(ops, context, key);

  if (isfilename) {
    for (Variant chunk = f_fread(f, 1024); !is_empty_string(chunk);
         chunk = f_fread(f, 1024)) {
      String schunk = chunk.toString();
      ops->hash_update(context, (unsigned char *)schunk.data(), schunk.size());
    }
  } else {
    ops->hash_update(context, (unsigned char *)data.data(), data.size());
  }

  String raw = String(ops->digest_size, ReserveString);
  char *digest = raw.mutableSlice().ptr;
  ops->hash_final((unsigned char *)digest, context);
  finalize_hmac_key(K, ops, context, digest);
  free(context);

  raw.setSize(ops->digest_size);
  if (raw_output) {
    return raw;
  }
  return StringUtil::HexEncode(raw);
}
Пример #9
0
String f_hash_final(CObjRef context, bool raw_output /* = false */) {
  HashContext *hash = context.getTyped<HashContext>();

  String raw = String(hash->ops->digest_size, ReserveString);
  char *digest = raw.mutableSlice().ptr;
  hash->ops->hash_final((unsigned char *)digest, hash->context);
  if (hash->options & k_HASH_HMAC) {
    finalize_hmac_key(hash->key, hash->ops, hash->context, digest);
    hash->key = NULL;
  }
  free(hash->context);
  hash->context = NULL;

  raw.setSize(hash->ops->digest_size);
  if (raw_output) {
    return raw;
  }
  return StringUtil::HexEncode(raw);
}
Пример #10
0
String File::read(int64 length) {
  if (length <= 0) {
    raise_notice("Invalid length %lld", length);
    return "";
  }

  String s = String(length, ReserveString);
  char *ret = s.mutableSlice().ptr;
  int64 copied = 0;
  int64 avail = m_writepos - m_readpos;

  while (avail < length && !eof()) {
    if (m_buffer == NULL) {
      m_buffer = (char *)malloc(CHUNK_SIZE);
    }

    if (avail > 0) {
      memcpy(ret + copied, m_buffer + m_readpos, avail);
      copied += avail;
      length -= avail;
    }

    m_writepos = readImpl(m_buffer, CHUNK_SIZE);
    m_readpos = 0;
    avail = m_writepos - m_readpos;

    if (avail == 0 || m_nonblocking) {
      // For nonblocking mode, temporary out of data.
      break;
    }
  }

  avail = m_writepos - m_readpos;
  if (avail > 0) {
    int64 n = length < avail ? length : avail;
    memcpy(ret + copied, m_buffer + m_readpos, n);
    m_readpos += n;
    copied += n;
  }

  m_position += copied;
  return s.setSize(copied);
}
Пример #11
0
static Variant php_hash_do_hash(const String& algo, const String& data,
                                bool isfilename,
                                bool raw_output) {
  HashEnginePtr ops = php_hash_fetch_ops(algo);
  if (!ops) {
    raise_warning("Unknown hashing algorithm: %s", algo.data());
    return false;
  }
  Variant f;
  if (isfilename) {
    f = HHVM_FN(fopen)(data, "rb");
    if (same(f, false)) {
      return false;
    }
  }

  void *context = malloc(ops->context_size);
  ops->hash_init(context);

  if (isfilename) {
    for (Variant chunk = HHVM_FN(fread)(f.toResource(), 1024);
         !is_empty_string(chunk);
         chunk = HHVM_FN(fread)(f.toResource(), 1024)) {
      String schunk = chunk.toString();
      ops->hash_update(context, (unsigned char *)schunk.data(), schunk.size());
    }
  } else {
    ops->hash_update(context, (unsigned char *)data.data(), data.size());
  }

  String raw = String(ops->digest_size, ReserveString);
  char *digest = raw.mutableData();
  ops->hash_final((unsigned char *)digest, context);
  free(context);

  raw.setSize(ops->digest_size);
  if (raw_output) {
    return raw;
  }
  return HHVM_FN(bin2hex)(raw);
}
Пример #12
0
String StringUtil::Implode(const Variant& items, const String& delim) {
  if (!isContainer(items)) {
    throw_param_is_not_container();
  }
  int size = getContainerSize(items);
  if (size == 0) return "";

  String* sitems = (String*)smart_malloc(size * sizeof(String));
  int len = 0;
  int lenDelim = delim.size();
  int i = 0;
  for (ArrayIter iter(items); iter; ++iter) {
    new (&sitems[i]) String(iter.second().toString());
    len += sitems[i].size() + lenDelim;
    i++;
  }
  len -= lenDelim; // always one delimiter less than count of items
  assert(i == size);

  String s = String(len, ReserveString);
  char *buffer = s.bufferSlice().ptr;
  const char *sdelim = delim.data();
  char *p = buffer;
  for (int i = 0; i < size; i++) {
    String &item = sitems[i];
    if (i && lenDelim) {
      memcpy(p, sdelim, lenDelim);
      p += lenDelim;
    }
    int lenItem = item.size();
    if (lenItem) {
      memcpy(p, item.data(), lenItem);
      p += lenItem;
    }
    sitems[i].~String();
  }
  smart_free(sitems);
  assert(p - buffer == len);
  s.setSize(len);
  return s;
}
Пример #13
0
Variant f_lz4compress(CStrRef uncompressed) {
  int bufsize = LZ4_compressBound(uncompressed.size());
  if (bufsize < 0) {
    return false;
  }
  int headerSize = VarintSize(uncompressed.size());
  bufsize += headerSize;  // for the header
  String s = String(bufsize, ReserveString);
  char *compressed = s.mutableSlice().ptr;

  VarintEncode(uncompressed.size(), &compressed);  // write the header

  int csize = LZ4_compress(uncompressed.data(), compressed,
      uncompressed.size());
  if (csize < 0) {
    return false;
  }
  bufsize = csize + headerSize;
  s.shrink(bufsize);
  return s.setSize(bufsize);
}
Пример #14
0
bool FileRepository::readActualFile(const StringData *name,
                                    const struct stat &s,
                                    FileInfo &fileInfo) {
  if (s.st_size > StringData::MaxSize) {
    throw FatalErrorException(0, "file %s is too big", name->data());
  }
  int fileSize = s.st_size;
  int fd = open(name->data(), O_RDONLY);
  if (!fd) return false; // ignore file open exception
  String str = String(fileSize, ReserveString);
  char *input = str.bufferSlice().ptr;
  if (!input) return false;
  int nbytes = read(fd, input, fileSize);
  close(fd);
  str.setSize(fileSize);
  fileInfo.m_inputString = str;
  if (nbytes != fileSize) return false;

  computeMd5(name, fileInfo);
  return true;
}
Пример #15
0
Variant f_stream_get_contents(CResRef handle, int maxlen /* = -1 */,
                              int offset /* = -1 */) {
  if (maxlen < -1) {
    throw_invalid_argument("maxlen: %d", maxlen);
    return false;
  }

  if (maxlen == 0) {
    return String();
  }

  File *file = handle.getTyped<File>(false /* nullOkay */,
                                     true /* badTypeOkay */);
  if (!file) {
    throw_invalid_argument(
      "stream_get_contents() expects parameter 1 to be a resource");
    return false;
  }

  if (offset >= 0 && !file->seek(offset, SEEK_SET) ) {
    raise_warning("Failed to seek to position %d in the stream", offset);
    return false;
  }

  String ret;
  if (maxlen != -1) {
    ret = String(maxlen, ReserveString);
    char *buf = ret.bufferSlice().ptr;
    maxlen = file->readImpl(buf, maxlen);
    if (maxlen < 0) {
      return false;
    }
    ret.setSize(maxlen);
  } else {
    StringBuffer sb;
    sb.read(file);
    ret = sb.detach();
  }
  return ret;
}
Пример #16
0
String f_utf8_decode(CStrRef data) {
  String str = String(data.size(), ReserveString);
  char *newbuf = str.mutableSlice().ptr;
  int newlen = 0;
  const char *s = data.data();
  for (int pos = data.size(); pos > 0; ) {
    unsigned short c = (unsigned char)(*s);
    if (c >= 0xf0) { /* four bytes encoded, 21 bits */
      if (pos-4 >= 0) {
        c = ((s[0]&7)<<18) | ((s[1]&63)<<12) | ((s[2]&63)<<6) | (s[3]&63);
      } else {
        c = '?';
      }
      s += 4;
      pos -= 4;
    } else if (c >= 0xe0) { /* three bytes encoded, 16 bits */
      if (pos-3 >= 0) {
        c = ((s[0]&63)<<12) | ((s[1]&63)<<6) | (s[2]&63);
      } else {
        c = '?';
      }
      s += 3;
      pos -= 3;
    } else if (c >= 0xc0) { /* two bytes encoded, 11 bits */
      if (pos-2 >= 0) {
        c = ((s[0]&63)<<6) | (s[1]&63);
      } else {
        c = '?';
      }
      s += 2;
      pos -= 2;
    } else {
      s++;
      pos--;
    }
    newbuf[newlen] = (char)(c > 0xff ? '?' : c);
    ++newlen;
  }
  return str.setSize(newlen);
}
Пример #17
0
String StringUtil::Implode(const Variant& items, const String& delim,
                           const bool checkIsContainer /* = true */) {
  if (checkIsContainer && !isContainer(items)) {
    throw_param_is_not_container();
  }
  int size = getContainerSize(items);
  if (size == 0) return empty_string();

  req::vector<String> sitems;
  sitems.reserve(size);
  size_t len = 0;
  size_t lenDelim = delim.size();
  for (ArrayIter iter(items); iter; ++iter) {
    sitems.emplace_back(iter.second().toString());
    len += sitems.back().size() + lenDelim;
  }
  len -= lenDelim; // always one delimiter less than count of items
  assert(sitems.size() == size);

  String s = String(len, ReserveString);
  char *buffer = s.mutableData();
  const char *sdelim = delim.data();
  char *p = buffer;
  String &init_str = sitems[0];
  int init_len = init_str.size();
  memcpy(p, init_str.data(), init_len);
  p += init_len;
  for (int i = 1; i < size; i++) {
    String &item = sitems[i];
    memcpy(p, sdelim, lenDelim);
    p += lenDelim;
    int lenItem = item.size();
    memcpy(p, item.data(), lenItem);
    p += lenItem;
  }
  assert(p - buffer == len);
  s.setSize(len);
  return s;
}
Пример #18
0
static Variant mcrypt_generic(const Resource& td, const String& data,
                              bool dencrypt) {
  auto pm = cast<MCrypt>(td);
  if (!pm->m_init) {
    raise_warning("Operation disallowed prior to mcrypt_generic_init().");
    return false;
  }

  if (data.empty()) {
    raise_warning("An empty string was passed");
    return false;
  }

  String s;
  unsigned char* data_s;
  int block_size, data_size;
  /* Check blocksize */
  if (mcrypt_enc_is_block_mode(pm->m_td) == 1) { /* It's a block algorithm */
    block_size = mcrypt_enc_get_block_size(pm->m_td);
    data_size = (((data.size() - 1) / block_size) + 1) * block_size;
    s = String(data_size, ReserveString);
    data_s = (unsigned char *)s.mutableData();
    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 = (unsigned char *)s.mutableData();
    memcpy(data_s, data.data(), data.size());
  }

  if (dencrypt) {
    mdecrypt_generic(pm->m_td, data_s, data_size);
  } else {
    mcrypt_generic(pm->m_td, data_s, data_size);
  }
  s.setSize(data_size);
  return s;
}
Пример #19
0
Variant HHVM_FUNCTION(hash_final, const Resource& context,
                                 bool raw_output /* = false */) {
  auto hash = get_valid_hash_context_resource(context, __FUNCTION__);
  if (!hash) {
    return false;
  }

  String raw = String(hash->ops->digest_size, ReserveString);
  char *digest = raw.mutableData();
  hash->ops->hash_final((unsigned char *)digest, hash->context);
  if (hash->options & k_HASH_HMAC) {
    finalize_hmac_key(hash->key, hash->ops, hash->context, digest);
    hash->key = NULL;
  }
  free(hash->context);
  hash->context = NULL;

  raw.setSize(hash->ops->digest_size);
  if (raw_output) {
    return raw;
  }
  return HHVM_FN(bin2hex)(raw);
}
Пример #20
0
static unsigned char *php_parserr(unsigned char *cp, unsigned char* end,
                                  querybuf *answer,
                                  int type_to_fetch, bool store,
                                  Array &subarray) {
    unsigned short type, cls ATTRIBUTE_UNUSED, dlen;
    unsigned long ttl;
    int64_t n, i;
    unsigned short s;
    unsigned char *tp, *p;
    char name[MAXHOSTNAMELEN];
    int have_v6_break = 0, in_v6_break = 0;

    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
    if (n < 0) {
        return NULL;
    }
    cp += n;

    CHECKCP(10);
    GETSHORT(type, cp);
    GETSHORT(cls, cp);
    GETLONG(ttl, cp);
    GETSHORT(dlen, cp);
    CHECKCP(dlen);
    if (type_to_fetch != T_ANY && type != type_to_fetch) {
        cp += dlen;
        return cp;
    }

    if (!store) {
        cp += dlen;
        return cp;
    }

    subarray.set(s_host, String(name, CopyString));
    switch (type) {
    case DNS_T_A:
        CHECKCP(4);
        subarray.set(s_type, s_A);
        snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
        subarray.set(s_ip, String(name, CopyString));
        cp += dlen;
        break;
    case DNS_T_MX:
        CHECKCP(2);
        subarray.set(s_type, s_MX);
        GETSHORT(n, cp);
        subarray.set(s_pri, n);
    /* no break; */
    case DNS_T_CNAME:
        if (type == DNS_T_CNAME) {
            subarray.set(s_type, s_CNAME);
        }
    /* no break; */
    case DNS_T_NS:
        if (type == DNS_T_NS) {
            subarray.set(s_type, s_NS);
        }
    /* no break; */
    case DNS_T_PTR:
        if (type == DNS_T_PTR) {
            subarray.set(s_type, s_PTR);
        }
        n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_target, String(name, CopyString));
        break;
    case DNS_T_HINFO:
        /* See RFC 1010 for values */
        subarray.set(s_type, s_HINFO);
        CHECKCP(1);
        n = *cp & 0xFF;
        cp++;
        CHECKCP(n);
        subarray.set(s_cpu, String((const char *)cp, n, CopyString));
        cp += n;
        CHECKCP(1);
        n = *cp & 0xFF;
        cp++;
        CHECKCP(n);
        subarray.set(s_os, String((const char *)cp, n, CopyString));
        cp += n;
        break;
    case DNS_T_TXT: {
        int l1 = 0, l2 = 0;

        String s = String(dlen, ReserveString);
        tp = (unsigned char *)s.bufferSlice().ptr;

        while (l1 < dlen) {
            n = cp[l1];
            if ((n + l1) > dlen) {
                // bad record, don't set anything
                break;
            }
            memcpy(tp + l1 , cp + l1 + 1, n);
            l1 = l1 + n + 1;
            l2 = l2 + n;
        }
        s.setSize(l2);
        cp += dlen;

        subarray.set(s_type, s_TXT);
        subarray.set(s_txt, s);
        break;
    }
    case DNS_T_SOA:
        subarray.set(s_type, s_SOA);
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_mname, String(name, CopyString));
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_rname, String(name, CopyString));
        CHECKCP(5*4);
        GETLONG(n, cp);
        subarray.set(s_serial, n);
        GETLONG(n, cp);
        subarray.set(s_refresh, n);
        GETLONG(n, cp);
        subarray.set(s_retry, n);
        GETLONG(n, cp);
        subarray.set(s_expire, n);
        GETLONG(n, cp);
        subarray.set(s_minimum_ttl, n);
        break;
    case DNS_T_AAAA:
        tp = (unsigned char *)name;
        CHECKCP(8*2);
        for (i = 0; i < 8; i++) {
            GETSHORT(s, cp);
            if (s != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                tp += sprintf((char *)tp, "%x", s);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
        }
        if (have_v6_break && in_v6_break) {
            tp[0] = ':';
            tp++;
        }
        tp[0] = '\0';
        subarray.set(s_type, s_AAAA);
        subarray.set(s_ipv6, String(name, CopyString));
        break;
    case DNS_T_A6:
        p = cp;
        subarray.set(s_type, s_A6);
        CHECKCP(1);
        n = ((int)cp[0]) & 0xFF;
        cp++;
        subarray.set(s_masklen, n);
        tp = (unsigned char *)name;
        if (n > 15) {
            have_v6_break = 1;
            in_v6_break = 1;
            tp[0] = ':';
            tp++;
        }
        if (n % 16 > 8) {
            /* Partial short */
            if (cp[0] != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                sprintf((char *)tp, "%x", cp[0] & 0xFF);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
            cp++;
        }
        for (i = (n + 8)/16; i < 8; i++) {
            CHECKCP(2);
            GETSHORT(s, cp);
            if (s != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                tp += sprintf((char*)tp,"%x",s);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
        }
        if (have_v6_break && in_v6_break) {
            tp[0] = ':';
            tp++;
        }
        tp[0] = '\0';
        subarray.set(s_ipv6, String(name, CopyString));
        if (cp < p + dlen) {
            n = dn_expand(answer->qb2, end, cp, name,
                          (sizeof name) - 2);
            if (n < 0) {
                return NULL;
            }
            cp += n;
            subarray.set(s_chain, String(name, CopyString));
        }
        break;
    case DNS_T_SRV:
        CHECKCP(3*2);
        subarray.set(s_type, s_SRV);
        GETSHORT(n, cp);
        subarray.set(s_pri, n);
        GETSHORT(n, cp);
        subarray.set(s_weight, n);
        GETSHORT(n, cp);
        subarray.set(s_port, n);
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_target, String(name, CopyString));
        break;
    case DNS_T_NAPTR:
        CHECKCP(2*2);
        subarray.set(s_type, s_NAPTR);
        GETSHORT(n, cp);
        subarray.set(s_order, n);
        GETSHORT(n, cp);
        subarray.set(s_pref, n);

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_flags, String((const char *)cp, n, CopyString));
        cp += n;

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_services, String((const char *)cp, n, CopyString));
        cp += n;

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_regex, String((const char *)cp, n, CopyString));
        cp += n;

        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_replacement, String(name, CopyString));
        break;
    default:
        cp += dlen;
    }

    subarray.set(s_class, s_IN);
    subarray.set(s_ttl, (int)ttl);
    return cp;
}
Пример #21
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);
}
Пример #22
0
static unsigned char *php_parserr(unsigned char *cp, querybuf *answer,
                                  int type_to_fetch, bool store,
                                  Array &subarray) {
  unsigned short type, cls ATTRIBUTE_UNUSED, dlen;
  unsigned long ttl;
  int64_t n, i;
  unsigned short s;
  unsigned char *tp, *p;
  char name[MAXHOSTNAMELEN];
  int have_v6_break = 0, in_v6_break = 0;

  n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
  if (n < 0) {
    return NULL;
  }
  cp += n;

  GETSHORT(type, cp);
  GETSHORT(cls, cp);
  GETLONG(ttl, cp);
  GETSHORT(dlen, cp);
  if (type_to_fetch != T_ANY && type != type_to_fetch) {
    cp += dlen;
    return cp;
  }

  if (!store) {
    cp += dlen;
    return cp;
  }

  subarray.set("host", String(name, CopyString));
  switch (type) {
  case DNS_T_A:
    subarray.set("type", "A");
    snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
    subarray.set("ip", String(name, CopyString));
    cp += dlen;
    break;
  case DNS_T_MX:
    subarray.set("type", "MX");
    GETSHORT(n, cp);
    subarray.set("pri", n);
    /* no break; */
  case DNS_T_CNAME:
    if (type == DNS_T_CNAME) {
      subarray.set("type", "CNAME");
    }
    /* no break; */
  case DNS_T_NS:
    if (type == DNS_T_NS) {
      subarray.set("type", "NS");
    }
    /* no break; */
  case DNS_T_PTR:
    if (type == DNS_T_PTR) {
      subarray.set("type", "PTR");
    }
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set("target", String(name, CopyString));
    break;
  case DNS_T_HINFO:
    /* See RFC 1010 for values */
    subarray.set("type", "HINFO");
    n = *cp & 0xFF;
    cp++;
    subarray.set("cpu", String((const char *)cp, n, CopyString));
    cp += n;
    n = *cp & 0xFF;
    cp++;
    subarray.set("os", String((const char *)cp, n, CopyString));
    cp += n;
    break;
  case DNS_T_TXT: {
    int ll = 0;

    subarray.set("type", "TXT");
    String s = String(dlen, ReserveString);
    tp = (unsigned char *)s.mutableSlice().ptr;

    while (ll < dlen) {
      n = cp[ll];
      memcpy(tp + ll , cp + ll + 1, n);
      ll = ll + n + 1;
    }
    s.setSize(dlen);
    cp += dlen;

    subarray.set("txt", s);
    break;
  }
  case DNS_T_SOA:
    subarray.set("type", "SOA");
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set("mname", String(name, CopyString));
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set("rname", String(name, CopyString));
    GETLONG(n, cp);
    subarray.set("serial", n);
    GETLONG(n, cp);
    subarray.set("refresh", n);
    GETLONG(n, cp);
    subarray.set("retry", n);
    GETLONG(n, cp);
    subarray.set("expire", n);
    GETLONG(n, cp);
    subarray.set("minimum-ttl", n);
    break;
  case DNS_T_AAAA:
    tp = (unsigned char *)name;
    for (i = 0; i < 8; i++) {
      GETSHORT(s, cp);
      if (s != 0) {
        if (tp > (u_char *)name) {
          in_v6_break = 0;
          tp[0] = ':';
          tp++;
        }
        tp += sprintf((char *)tp, "%x", s);
      } else {
        if (!have_v6_break) {
          have_v6_break = 1;
          in_v6_break = 1;
          tp[0] = ':';
          tp++;
        } else if (!in_v6_break) {
          tp[0] = ':';
          tp++;
          tp[0] = '0';
          tp++;
        }
      }
    }
    if (have_v6_break && in_v6_break) {
      tp[0] = ':';
      tp++;
    }
    tp[0] = '\0';
    subarray.set("type", "AAAA");
    subarray.set("ipv6", String(name, CopyString));
    break;
  case DNS_T_A6:
    p = cp;
    subarray.set("type", "A6");
    n = ((int)cp[0]) & 0xFF;
    cp++;
    subarray.set("masklen", n);
    tp = (unsigned char *)name;
    if (n > 15) {
      have_v6_break = 1;
      in_v6_break = 1;
      tp[0] = ':';
      tp++;
    }
    if (n % 16 > 8) {
      /* Partial short */
      if (cp[0] != 0) {
        if (tp > (u_char *)name) {
          in_v6_break = 0;
          tp[0] = ':';
          tp++;
        }
        sprintf((char *)tp, "%x", cp[0] & 0xFF);
      } else {
        if (!have_v6_break) {
          have_v6_break = 1;
          in_v6_break = 1;
          tp[0] = ':';
          tp++;
        } else if (!in_v6_break) {
          tp[0] = ':';
          tp++;
          tp[0] = '0';
          tp++;
        }
      }
      cp++;
    }
    for (i = (n + 8)/16; i < 8; i++) {
      GETSHORT(s, cp);
      if (s != 0) {
        if (tp > (u_char *)name) {
          in_v6_break = 0;
          tp[0] = ':';
          tp++;
        }
        tp += sprintf((char*)tp,"%x",s);
      } else {
        if (!have_v6_break) {
          have_v6_break = 1;
          in_v6_break = 1;
          tp[0] = ':';
          tp++;
        } else if (!in_v6_break) {
          tp[0] = ':';
          tp++;
          tp[0] = '0';
          tp++;
        }
      }
    }
    if (have_v6_break && in_v6_break) {
      tp[0] = ':';
      tp++;
    }
    tp[0] = '\0';
    subarray.set("ipv6", String(name, CopyString));
    if (cp < p + dlen) {
      n = dn_expand(answer->qb2, answer->qb2+65536, cp, name,
                    (sizeof name) - 2);
      if (n < 0) {
        return NULL;
      }
      cp += n;
      subarray.set("chain", String(name, CopyString));
    }
    break;
  case DNS_T_SRV:
    subarray.set("type", "SRV");
    GETSHORT(n, cp);
    subarray.set("pri", n);
    GETSHORT(n, cp);
    subarray.set("weight", n);
    GETSHORT(n, cp);
    subarray.set("port", n);
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set("target", String(name, CopyString));
    break;
  case DNS_T_NAPTR:
    subarray.set("type", "NAPTR");
    GETSHORT(n, cp);
    subarray.set("order", n);
    GETSHORT(n, cp);
    subarray.set("pref", n);
    n = (cp[0] & 0xFF);
    subarray.set("flags", String((const char *)(++cp), n, CopyString));
    cp += n;
    n = (cp[0] & 0xFF);
    subarray.set("services", String((const char *)(++cp), n, CopyString));
    cp += n;
    n = (cp[0] & 0xFF);
    subarray.set("regex", String((const char *)(++cp), n, CopyString));
    cp += n;
    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
    if (n < 0) {
      return NULL;
    }
    cp += n;
    subarray.set("replacement", String(name, CopyString));
    break;
  default:
    cp += dlen;
  }

  subarray.set("class", "IN");
  subarray.set("ttl", (int)ttl);
  return cp;
}
Пример #23
0
Variant binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport,
                           CArrRef fieldspec) {
  Variant ret;
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return uninit_null();
    case T_STRUCT: {
      Variant val;
      if ((val = fieldspec.rvalAt(PHPTransport::s_class)).isNull()) {
        throw_tprotocolexception("no class type in spec", INVALID_DATA);
        skip_element(T_STRUCT, transport);
        return uninit_null();
      }
      String structType = val.toString();
      ret = createObject(structType);
      if (ret.isNull()) {
        // unable to create class entry
        skip_element(T_STRUCT, transport);
        return uninit_null();
      }
      Variant spec = f_hphp_get_static_property(structType, s_TSPEC, false);
      if (!spec.is(KindOfArray)) {
        char errbuf[128];
        snprintf(errbuf, 128, "spec for %s is wrong type: %d\n",
                 structType.data(), ret.getType());
        throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
        return uninit_null();
      }
      binary_deserialize_spec(ret.toObject(), transport, spec.toArray());
      return ret;
    } break;
    case T_BOOL: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return c != 0;
    }
  //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return Variant((int8_t)c);
    }
    case T_I16: {
      uint16_t c;
      transport.readBytes(&c, 2);
      return Variant((int16_t)ntohs(c));
    }
    case T_I32: {
      uint32_t c;
      transport.readBytes(&c, 4);
      return Variant((int32_t)ntohl(c));
    }
    case T_U64:
    case T_I64: {
      uint64_t c;
      transport.readBytes(&c, 8);
      return Variant((int64_t)ntohll(c));
    }
    case T_DOUBLE: {
      union {
        uint64_t c;
        double d;
      } a;
      transport.readBytes(&(a.c), 8);
      a.c = ntohll(a.c);
      return a.d;
    }
    case T_FLOAT: {
      union {
        uint32_t c;
        float d;
      } a;
      transport.readBytes(&(a.c), 4);
      a.c = ntohl(a.c);
      return a.d;
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t size = transport.readU32();
      if (size && (size + 1)) {
        String s = String(size, ReserveString);
        char* strbuf = s.bufferSlice().ptr;
        transport.readBytes(strbuf, size);
        return s.setSize(size);
      } else {
        return "";
      }
    }
    case T_MAP: { // array of key -> value
      uint8_t types[2];
      transport.readBytes(types, 2);
      uint32_t size = transport.readU32();

      Array keyspec = fieldspec.rvalAt(PHPTransport::s_key,
                                       AccessFlags::Error_Key).toArray();
      Array valspec = fieldspec.rvalAt(PHPTransport::s_val,
                                       AccessFlags::Error_Key).toArray();
      ret = Array::Create();

      for (uint32_t s = 0; s < size; ++s) {
        Variant key = binary_deserialize(types[0], transport, keyspec);
        Variant value = binary_deserialize(types[1], transport, valspec);
        ret.set(key, value);
      }
      return ret; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
      int8_t type = transport.readI8();
      uint32_t size = transport.readU32();
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      ret = Array::Create();

      for (uint32_t s = 0; s < size; ++s) {
        Variant value = binary_deserialize(type, transport, elemspec);
        ret.append(value);
      }
      return ret;
    }
    case T_SET: { // array of key -> TRUE
      uint8_t type;
      uint32_t size;
      transport.readBytes(&type, 1);
      transport.readBytes(&size, 4);
      size = ntohl(size);
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      ret = Array::Create();

      for (uint32_t s = 0; s < size; ++s) {
        Variant key = binary_deserialize(type, transport, elemspec);

        if (key.isInteger()) {
          ret.set(key, true);
        } else {
          ret.set(key.toString(), true);
        }
      }
      return ret;
    }
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
  return uninit_null();
}
Пример #24
0
String f_posix_ctermid() {
  String s = String(L_ctermid, ReserveString);
  char *buffer = s.mutableSlice().ptr;
  ctermid(buffer);
  return s.setSize(strlen(buffer));
}
Пример #25
0
Variant binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport,
                           const Array& fieldspec) {
  Variant ret;
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return init_null();
    case T_STRUCT: {
      Variant val;
      if ((val = fieldspec.rvalAt(PHPTransport::s_class)).isNull()) {
        throw_tprotocolexception("no class type in spec", INVALID_DATA);
        skip_element(T_STRUCT, transport);
        return init_null();
      }
      String structType = val.toString();
      ret = createObject(structType);
      if (ret.isNull()) {
        // unable to create class entry
        skip_element(T_STRUCT, transport);
        return init_null();
      }
      Variant spec = HHVM_FN(hphp_get_static_property)(structType, s_TSPEC,
                                                                   false);
      if (!spec.is(KindOfArray)) {
        char errbuf[128];
        snprintf(errbuf, 128, "spec for %s is wrong type: %d\n",
                 structType.data(), ret.getType());
        throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
        return init_null();
      }
      binary_deserialize_spec(ret.toObject(), transport, spec.toArray());
      return ret;
    } break;
    case T_BOOL: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return c != 0;
    }
  //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return Variant((int8_t)c);
    }
    case T_I16: {
      uint16_t c;
      transport.readBytes(&c, 2);
      return Variant((int16_t)ntohs(c));
    }
    case T_I32: {
      uint32_t c;
      transport.readBytes(&c, 4);
      return Variant((int32_t)ntohl(c));
    }
    case T_U64:
    case T_I64: {
      uint64_t c;
      transport.readBytes(&c, 8);
      return Variant((int64_t)ntohll(c));
    }
    case T_DOUBLE: {
      union {
        uint64_t c;
        double d;
      } a;
      transport.readBytes(&(a.c), 8);
      a.c = ntohll(a.c);
      return a.d;
    }
    case T_FLOAT: {
      union {
        uint32_t c;
        float d;
      } a;
      transport.readBytes(&(a.c), 4);
      a.c = ntohl(a.c);
      return a.d;
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t size = transport.readU32();
      if (size && (size + 1)) {
        String s = String(size, ReserveString);
        char* strbuf = s.mutableData();
        transport.readBytes(strbuf, size);
        s.setSize(size);
        return s;
      } else {
        return empty_string_variant();
      }
    }
    case T_MAP: { // array of key -> value
      uint8_t types[2];
      transport.readBytes(types, 2);
      uint32_t size = transport.readU32();

      Array keyspec = fieldspec.rvalAt(PHPTransport::s_key,
                                       AccessFlags::Error_Key).toArray();
      Array valspec = fieldspec.rvalAt(PHPTransport::s_val,
                                       AccessFlags::Error_Key).toArray();
      String format = fieldspec.rvalAt(PHPTransport::s_format,
                                       AccessFlags::None).toString();
      if (format.equal(PHPTransport::s_collection)) {
        ret = newobj<c_Map>();
        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(types[0], transport, keyspec);
          Variant value = binary_deserialize(types[1], transport, valspec);
          collectionSet(ret.getObjectData(), key.asCell(), value.asCell());
        }
      } else {
        ret = Array::Create();
        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(types[0], transport, keyspec);
          Variant value = binary_deserialize(types[1], transport, valspec);
          ret.toArrRef().set(key, value);
        }
      }
      return ret; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
      int8_t type = transport.readI8();
      uint32_t size = transport.readU32();
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      String format = fieldspec.rvalAt(PHPTransport::s_format,
                                       AccessFlags::None).toString();

      if (format.equal(PHPTransport::s_collection)) {
        auto const pvec = newobj<c_Vector>();
        ret = pvec;
        for (uint32_t s = 0; s < size; ++s) {
          Variant value = binary_deserialize(type, transport, elemspec);
          pvec->t_add(value);
        }
      } else {
        PackedArrayInit pai(size);
        for (auto s = uint32_t{0}; s < size; ++s) {
          pai.append(binary_deserialize(type, transport, elemspec));
        }
        ret = pai.toArray();
      }

      return ret;
    }
    case T_SET: { // array of key -> TRUE
      uint8_t type;
      uint32_t size;
      transport.readBytes(&type, 1);
      transport.readBytes(&size, 4);
      size = ntohl(size);
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      String format = fieldspec.rvalAt(PHPTransport::s_format,
                                       AccessFlags::None).toString();
      if (format.equal(PHPTransport::s_collection)) {
        auto set_ret = makeSmartPtr<c_Set>();

        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(type, transport, elemspec);

          if (key.isInteger()) {
            set_ret->t_add(key);
          } else {
            set_ret->t_add(key.toString());
          }
        }

        ret = Variant(std::move(set_ret));
      } else {
        ArrayInit init(size, ArrayInit::Mixed{});
        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(type, transport, elemspec);
          if (key.isInteger()) {
            init.set(key, true);
          } else {
            init.setKeyUnconverted(key, true);
          }
        }
        ret = init.toArray();
      }
      return ret;
    }
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
  return init_null();
}
Пример #26
0
String File::readRecord(CStrRef delimiter, int64 maxlen /* = 0 */) {
  if (eof() && m_writepos == m_readpos) {
    return empty_string;
  }

  if (maxlen <= 0 || maxlen > CHUNK_SIZE) {
    maxlen = CHUNK_SIZE;
  }

  int64 avail = m_writepos - m_readpos;
  if (m_buffer == NULL) {
    m_buffer = (char *)malloc(CHUNK_SIZE * 3);
  }
  if (avail < maxlen && !eof()) {
    assert(m_writepos + maxlen - avail <= CHUNK_SIZE * 3);
    m_writepos += readImpl(m_buffer + m_writepos, maxlen - avail);
    maxlen = m_writepos - m_readpos;
  }
  if (m_readpos >= CHUNK_SIZE) {
    memcpy(m_buffer, m_buffer + m_readpos, m_writepos - m_readpos);
    m_writepos -= m_readpos;
    m_readpos = 0;
  }

  int64 toread;
  const char *e;
  bool skip = false;
  if (delimiter.empty()) {
    toread = maxlen;
  } else {
    if (delimiter.size() == 1) {
      e = (const char *)memchr(m_buffer + m_readpos, delimiter.charAt(0),
                               m_writepos - m_readpos);
    } else {
      int64 pos = string_find(m_buffer + m_readpos, m_writepos - m_readpos,
                              delimiter.data(), delimiter.size(), 0, true);
      if (pos >= 0) {
        e = m_buffer + m_readpos + pos;
      } else {
        e = NULL;
      }
    }

    if (!e) {
      toread = maxlen;
    } else {
      toread = e - m_buffer - m_readpos;
      skip = true;
    }
  }

  if (toread > maxlen && maxlen > 0) {
    toread = maxlen;
  }

  if (toread >= 0) {
    String s = String(toread, ReserveString);
    char *buf = s.mutableSlice().ptr;
    if (toread) {
      memcpy(buf, m_buffer + m_readpos, toread);
    }

    m_readpos += toread;
    if (skip) {
      m_readpos += delimiter.size();
      m_position += delimiter.size();
    }
    return s.setSize(toread);
  }

  return empty_string;
}
Пример #27
0
Variant ZendPack::pack(const String& fmt, const Array& argv) {
  /* Preprocess format into formatcodes and formatargs */
  req::TinyVector<char, 64> formatcodes; // up to 64 codes on the stack
  req::TinyVector<int, 64> formatargs;
  int argc = argv.size();

  const char *format = fmt.c_str();
  int formatlen = fmt.size();
  int currentarg = 0;
  for (int i = 0; i < formatlen; ) {
    char code = format[i++];
    int arg = 1;

    /* Handle format arguments if any */
    if (i < formatlen) {
      char c = format[i];

      if (c == '*') {
        arg = -1;
        i++;
      }
      else if (c >= '0' && c <= '9') {
        arg = atoi(&format[i]);

        while (format[i] >= '0' && format[i] <= '9' && i < formatlen) {
          i++;
        }
      }
    }

    /* Handle special arg '*' for all codes and check argv overflows */
    switch ((int) code) {
      /* Never uses any args */
    case 'x':
    case 'X':
    case '@':
      if (arg < 0) {
        throw_invalid_argument("Type %c: '*' ignored", code);
        arg = 1;
      }
      break;

      /* Always uses one arg */
    case 'a':
    case 'A':
    case 'h':
    case 'H':
    case 'Z':
      if (currentarg >= argc) {
        throw_invalid_argument("Type %c: not enough arguments", code);
        return false;
      }

      if (arg < 0) {
        arg = argv[currentarg].toString().size();
        //add one, because Z is always NUL-terminated
        if (code == 'Z') {
          arg++;
        }
      }

      currentarg++;
      break;

      /* Use as many args as specified */
    case 'q':
    case 'Q':
    case 'J':
    case 'P':
    case 'c':
    case 'C':
    case 's':
    case 'S':
    case 'i':
    case 'I':
    case 'l':
    case 'L':
    case 'n':
    case 'N':
    case 'v':
    case 'V':
    case 'f':
    case 'd':
      if (arg < 0) {
        arg = argc - currentarg;
      }

      currentarg += arg;

      if (currentarg > argc) {
        throw_invalid_argument("Type %c: too few arguments", code);
        return false;
      }
      break;

    default:
      throw_invalid_argument("Type %c: unknown format code", code);
      return false;
    }

    formatcodes.push_back(code);
    formatargs.push_back(arg);
  }

  if (currentarg < argc) {
    throw_invalid_argument("%d arguments unused", (argc - currentarg));
  }

  int outputpos = 0, outputsize = 0;
  /* Calculate output length and upper bound while processing*/
  for (int i = 0; i < (int)formatcodes.size(); i++) {
    int code = (int) formatcodes[i];
    int arg = formatargs[i];

    switch ((int) code) {
    case 'h':
    case 'H':
      INC_OUTPUTPOS((arg + (arg % 2)) / 2,1);  /* 4 bit per arg */
      break;

    case 'a':
    case 'A':
    case 'c':
    case 'C':
    case 'x':
    case 'Z':
      INC_OUTPUTPOS(arg,1);    /* 8 bit per arg */
      break;

    case 's':
    case 'S':
    case 'n':
    case 'v':
      INC_OUTPUTPOS(arg,2);    /* 16 bit per arg */
      break;

    case 'i':
    case 'I':
      INC_OUTPUTPOS(arg,sizeof(int));
      break;

    case 'l':
    case 'L':
    case 'N':
    case 'V':
      INC_OUTPUTPOS(arg,4);    /* 32 bit per arg */
      break;
    case 'q':
    case 'Q':
    case 'J':
    case 'P':
      INC_OUTPUTPOS(arg,8);    /* 64 bit per arg */
      break;

    case 'f':
      INC_OUTPUTPOS(arg,sizeof(float));
      break;

    case 'd':
      INC_OUTPUTPOS(arg,sizeof(double));
      break;

    case 'X':
      outputpos -= arg;

      if (outputpos < 0) {
        throw_invalid_argument("Type %c: outside of string", code);
        outputpos = 0;
      }
      break;

    case '@':
      outputpos = arg;
      break;
    }

    if (outputsize < outputpos) {
      outputsize = outputpos;
    }
  }

  String str = String(outputsize, ReserveString);
  char *output = str.mutableData();
  outputpos = 0;
  currentarg = 0;

  /* Do actual packing */
  for (int i = 0; i < (int)formatcodes.size(); i++) {
    int code = (int) formatcodes[i];
    int arg = formatargs[i];
    String val;
    const char *s;
    int slen;

    switch ((int) code) {
    case 'a':
    case 'A':
    case 'Z': {
      int arg_cp = (code != 'Z') ? arg : std::max(0, arg - 1);
      memset(&output[outputpos], (code != 'A') ? '\0' : ' ', arg);
      val = argv[currentarg++].toString();
      s = val.c_str();
      slen = val.size();
      memcpy(&output[outputpos], s, (slen < arg_cp) ? slen : arg_cp);
      outputpos += arg;
    }
    break;

    case 'h':
    case 'H': {
      int nibbleshift = (code == 'h') ? 0 : 4;
      int first = 1;
      const char *v;

      val = argv[currentarg++].toString();
      v = val.data();
      slen = val.size();
      outputpos--;
      if (arg > slen) {
        throw_invalid_argument
          ("Type %c: not enough characters in string", code);
        arg = slen;
      }

      while (arg-- > 0) {
        char n = *v++;

        if (n >= '0' && n <= '9') {
          n -= '0';
        } else if (n >= 'A' && n <= 'F') {
          n -= ('A' - 10);
        } else if (n >= 'a' && n <= 'f') {
          n -= ('a' - 10);
        } else {
          throw_invalid_argument("Type %c: illegal hex digit %c", code, n);
          n = 0;
        }

        if (first--) {
          output[++outputpos] = 0;
        } else {
          first = 1;
        }

        output[outputpos] |= (n << nibbleshift);
        nibbleshift = (nibbleshift + 4) & 7;
      }

      outputpos++;
      break;
    }

    case 'c':
    case 'C':
      while (arg-- > 0) {
        pack(argv[currentarg++], 1, byte_map, &output[outputpos]);
        outputpos++;
      }
      break;

    case 's':
    case 'S':
    case 'n':
    case 'v': {
      int64_t *map = machine_endian_short_map;

      if (code == 'n') {
        map = big_endian_short_map;
      } else if (code == 'v') {
        map = little_endian_short_map;
      }

      while (arg-- > 0) {
        pack(argv[currentarg++], 2, map, &output[outputpos]);
        outputpos += 2;
      }
      break;
    }

    case 'i':
    case 'I':
      while (arg-- > 0) {
        pack(argv[currentarg++], sizeof(int), int_map, &output[outputpos]);
        outputpos += sizeof(int);
      }
      break;

    case 'l':
    case 'L':
    case 'N':
    case 'V': {
      int64_t *map = machine_endian_int32_map;

      if (code == 'N') {
        map = big_endian_int32_map;
      } else if (code == 'V') {
        map = little_endian_int32_map;
      }

      while (arg-- > 0) {
        pack(argv[currentarg++], 4, map, &output[outputpos]);
        outputpos += 4;
      }
      break;
    }

    case 'q':
    case 'Q':
    case 'J':
    case 'P': {
      int64_t *map = machine_endian_int64_map;
      if (code == 'J') {
        map = big_endian_int64_map;
      } else if (code == 'P') {
        map = little_endian_int64_map;
      }

      while (arg-- > 0) {
        pack(argv[currentarg++], 8, map, &output[outputpos]);
        outputpos += 8;
      }
      break;
    }

    case 'f': {
      float v;

      while (arg-- > 0) {
        v = argv[currentarg++].toDouble();
        memcpy(&output[outputpos], &v, sizeof(v));
        outputpos += sizeof(v);
      }
      break;
    }

    case 'd': {
      double v;

      while (arg-- > 0) {
        v = argv[currentarg++].toDouble();
        memcpy(&output[outputpos], &v, sizeof(v));
        outputpos += sizeof(v);
      }
      break;
    }

    case 'x':
      memset(&output[outputpos], '\0', arg);
      outputpos += arg;
      break;

    case 'X':
      outputpos -= arg;

      if (outputpos < 0) {
        outputpos = 0;
      }
      break;

    case '@':
      if (arg > outputpos) {
        memset(&output[outputpos], '\0', arg - outputpos);
      }
      outputpos = arg;
      break;
    }
  }

  str.setSize(outputpos);
  return str;
}
Пример #28
0
Variant ZendPack::unpack(const String& fmt, const String& data) {
  const char *format = fmt.c_str();
  int formatlen = fmt.size();
  const char *input = data.c_str();
  int inputlen = data.size();
  int inputpos = 0;

  Array ret = Array::Create();
  while (formatlen-- > 0) {
    char type = *(format++);
    int arg = 1, argb;
    const char *name;
    int namelen;
    int size=0;

    /* Handle format arguments if any */
    if (formatlen > 0) {
      char c = *format;

      if (c >= '0' && c <= '9') {
        arg = atoi(format);

        while (formatlen > 0 && *format >= '0' && *format <= '9') {
          format++;
          formatlen--;
        }
      } else if (c == '*') {
        arg = -1;
        format++;
        formatlen--;
      }
    }

    /* Get of new value in array */
    name = format;
    argb = arg;

    while (formatlen > 0 && *format != '/') {
      formatlen--;
      format++;
    }

    namelen = format - name;

    if (namelen > 200)
      namelen = 200;

    switch ((int) type) {
      /* Never use any input */
    case 'X':
      size = -1;
      break;

    case '@':
      size = 0;
      break;

    case 'a':
    case 'A':
    case 'Z':
      size = arg;
      arg = 1;
      break;

    case 'h':
    case 'H':
      size = (arg > 0) ? (arg + (arg % 2)) / 2 : arg;
      arg = 1;
      break;

      /* Use 1 byte of input */
    case 'c':
    case 'C':
    case 'x':
      size = 1;
      break;

      /* Use 2 bytes of input */
    case 's':
    case 'S':
    case 'n':
    case 'v':
      size = 2;
      break;

      /* Use machine dependent bytes of input */
    case 'i':
    case 'I':
      size = sizeof(int);
      break;

      /* Use 4 bytes of input */
    case 'l':
    case 'L':
    case 'N':
    case 'V':
      size = 4;
      break;

      /* Use 8 bytes of input */
    case 'q':
    case 'Q':
    case 'J':
    case 'P':
      size = 8;
      break;
      /* Use sizeof(float) bytes of input */
    case 'f':
      size = sizeof(float);
      break;

      /* Use sizeof(double) bytes of input */
    case 'd':
      size = sizeof(double);
      break;

    default:
      throw_invalid_argument("Invalid format type %c", type);
      return false;
    }

    /* Do actual unpacking */
    for (int i = 0; i != arg; i++ ) {
      /* Space for name + number, safe as namelen is ensured <= 200 */
      char n[256];

      if (arg != 1 || namelen == 0) {
        /* Need to add element number to name */
        snprintf(n, sizeof(n), "%.*s%d", namelen, name, i + 1);
      } else {
        /* Truncate name to next format code or end of string */
        snprintf(n, sizeof(n), "%.*s", namelen, name);
      }

      if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) {
        throw_invalid_argument("Type %c: integer overflow", type);
        inputpos = 0;
      }

      if ((inputpos + size) <= inputlen) {
        switch ((int) type) {
        case 'a':
        case 'A':
        case 'Z': {
          int len = inputlen - inputpos; /* Remaining string */

          /* If size was given take minimum of len and size */
          if ((size >= 0) && (len > size)) {
            len = size;
          }

          size = len;

          /* A will strip any trailing whitespace */
          if (type == 'A')
          {
            char padn = '\0'; char pads = ' '; char padt = '\t';
            char padc = '\r'; char padl = '\n';
            while (--len >= 0) {
               if (input[inputpos + len] != padn
                   && input[inputpos + len] != pads
                   && input[inputpos + len] != padt
                   && input[inputpos + len] != padc
                   && input[inputpos + len] != padl
               )
                       break;
            }
          }
          /* Remove everything after the first null */
          if (type=='Z') {
            int s;
            for (s=0 ; s < len ; s++) {
                     if (input[inputpos + s] == '\0')
                             break;
            }
            len = s;
          }

          /*only A is \0 terminated*/
          if (type=='A')
            len++;

          ret.set(String(n, CopyString),
                  String(input + inputpos, len, CopyString));
          break;
        }

        case 'h':
        case 'H': {
          int len = (inputlen - inputpos) * 2;  /* Remaining */
          int nibbleshift = (type == 'h') ? 0 : 4;
          int first = 1;
          char *buf;
          int ipos, opos;

          /* If size was given take minimum of len and size */
          if (size >= 0 && len > (size * 2)) {
            len = size * 2;
          }

          if (argb > 0) {
            len -= argb % 2;
          }

          String s = String(len, ReserveString);
          buf = s.mutableData();

          for (ipos = opos = 0; opos < len; opos++) {
            char c = (input[inputpos + ipos] >> nibbleshift) & 0xf;

            if (c < 10) {
              c += '0';
            } else {
              c += 'a' - 10;
            }

            buf[opos] = c;
            nibbleshift = (nibbleshift + 4) & 7;

            if (first-- == 0) {
              ipos++;
              first = 1;
            }
          }

          s.setSize(len);
          ret.set(String(n, CopyString), s);
          break;
        }

        case 'c':
        case 'C': {
          int issigned = (type == 'c') ? (input[inputpos] & 0x80) : 0;
          ret.set(String(n, CopyString),
                  unpack(&input[inputpos], 1, issigned, byte_map));
          break;
        }

        case 's':
        case 'S':
        case 'n':
        case 'v': {
          int issigned = 0;
          int64_t *map = machine_endian_short_map;

          if (type == 's') {
            issigned = input[inputpos + (machine_little_endian ? 1 : 0)] &
              0x80;
          } else if (type == 'n') {
            map = big_endian_short_map;
          } else if (type == 'v') {
            map = little_endian_short_map;
          }

          ret.set(String(n, CopyString),
                  unpack(&input[inputpos], 2, issigned, map));
          break;
        }

        case 'i':
        case 'I': {
          int32_t v = 0;
          int issigned = 0;

          if (type == 'i') {
            issigned = input[inputpos + (machine_little_endian ?
                                         (sizeof(int) - 1) : 0)] & 0x80;
          } else if (sizeof(int32_t) > 4 &&
                     (input[inputpos + machine_endian_int32_map[3]]
                      & 0x80) == 0x80) {
            v = ~INT_MAX;
          }

          v |= unpack(&input[inputpos], sizeof(int), issigned, int_map);
          if (type == 'i') {
            ret.set(String(n, CopyString), v);
          } else {
            uint64_t u64 = uint32_t(v);
            ret.set(String(n, CopyString), u64);
          }
          break;
        }

        case 'l':
        case 'L':
        case 'N':
        case 'V': {
          int issigned = 0;
          int64_t *map = machine_endian_int32_map;
          int64_t v = 0;

          if (type == 'l' || type == 'L') {
            issigned = input[inputpos + (machine_little_endian ? 3 : 0)]
              & 0x80;
          } else if (type == 'N') {
            issigned = input[inputpos] & 0x80;
            map = big_endian_int32_map;
          } else if (type == 'V') {
            issigned = input[inputpos + 3] & 0x80;
            map = little_endian_int32_map;
          }

          if (sizeof(int32_t) > 4 && issigned) {
            v = ~INT_MAX;
          }

          v |= unpack(&input[inputpos], 4, issigned, map);
          if (type == 'l') {
            ret.set(String(n, CopyString), v);
          } else {
            uint64_t u64 = uint32_t(v);
            ret.set(String(n, CopyString), u64);
          }
          break;
        }

        case 'q':
        case 'Q':
        case 'J':
        case 'P': {
          int issigned = 0;
          int64_t *map = machine_endian_int64_map;
          int64_t v = 0;
          if (type == 'q' || type == 'Q') {
            issigned = input[inputpos + (machine_little_endian ? 7 : 0)] & 0x80;
          } else if (type == 'J') {
            issigned = input[inputpos] & 0x80;
            map = big_endian_int64_map;
          } else if (type == 'P') {
            issigned = input[inputpos + 7] & 0x80;
            map = little_endian_int64_map;
          }

          v = unpack(&input[inputpos], 8, issigned, map);

          if (type == 'q') {
            ret.set(String(n, CopyString), v);
          } else {
            uint64_t u64 = uint64_t(v);
            ret.set(String(n, CopyString), u64);
          }

          break;
        }

        case 'f': {
          float v;

          memcpy(&v, &input[inputpos], sizeof(float));
          ret.set(String(n, CopyString), (double)v);
          break;
        }

        case 'd': {
          double v;

          memcpy(&v, &input[inputpos], sizeof(double));
          ret.set(String(n, CopyString), v);
          break;
        }

        case 'x':
          /* Do nothing with input, just skip it */
          break;

        case 'X':
          if (inputpos < size) {
            inputpos = -size;
            i = arg - 1;    /* Break out of for loop */

            if (arg >= 0) {
              throw_invalid_argument("Type %c: outside of string", type);
            }
          }
          break;

        case '@':
          if (arg <= inputlen) {
            inputpos = arg;
          } else {
            throw_invalid_argument("Type %c: outside of string", type);
          }

          i = arg - 1;  /* Done, break out of for loop */
          break;
        }

        inputpos += size;
        if (inputpos < 0) {
          if (size != -1) { /* only print warning if not working with * */
            throw_invalid_argument("Type %c: outside of string", type);
          }
          inputpos = 0;
        }
      } else if (arg < 0) {
        /* Reached end of input for '*' repeater */
        break;
      } else {
        throw_invalid_argument
          ("Type %c: not enough input, need %d, have %d",
           type, size, inputlen - inputpos);
        return false;
      }
    }

    formatlen--; /* Skip '/' separator, does no harm if inputlen == 0 */
    format++;
  }