String f_posix_ctermid() { String s = String(L_ctermid, ReserveString); char *buffer = s.bufferSlice().ptr; ctermid(buffer); s.setSize(strlen(buffer)); return s; }
String xml_utf8_decode(const XML_Char *s, int len, const XML_Char *encoding) { int pos = len; String str = String(len, ReserveString); char *newbuf = str.bufferSlice().ptr; unsigned short c; char (*decoder)(unsigned short) = NULL; xml_encoding *enc = xml_get_encoding(encoding); int newlen = 0; if (enc) { decoder = enc->decoding_function; } if (decoder == NULL) { /* If the target encoding was unknown, or no decoder function * was specified, return the UTF-8-encoded data as-is. */ memcpy(newbuf, s, len); str.setSize(len); return str; } while (pos > 0) { 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] = decoder ? decoder(c) : c; ++newlen; } assert(newlen <= len); str.shrink(newlen); return str; }
String f_posix_getcwd() { String s = String(PATH_MAX, ReserveString); char *buffer = s.bufferSlice().ptr; if (getcwd(buffer, PATH_MAX) == NULL) { return "/"; } s.setSize(strlen(buffer)); return s; }
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_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; } } assert(dsize == size); return s.setSize(dsize); #endif }
static String oidAsString(MongoDBBsonObjectIDData* data) { String s; char *data_s; s = String(24, ReserveString); data_s = s.bufferSlice().data(); bson_oid_to_string(&data->m_oid, data_s); s.setSize(24); return s; }
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); }
String f_utf8_encode(const String& data) { String str = String(data.size() * 4, ReserveString); char *newbuf = str.bufferSlice().ptr; int newlen = 0; const char *s = data.data(); for (int pos = data.size(); pos > 0; pos--, s++) { unsigned int c = (unsigned char)(*s); if (c < 0x80) { newbuf[newlen++] = (char) c; } else if (c < 0x800) { newbuf[newlen++] = (0xc0 | (c >> 6)); newbuf[newlen++] = (0x80 | (c & 0x3f)); } else if (c < 0x10000) {
static Variant mcrypt_generic(const Resource& td, const String& data, bool dencrypt) { MCrypt *pm = td.getTyped<MCrypt>(); 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.bufferSlice().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 = (unsigned char *)s.bufferSlice().ptr; 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; }
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); }
String File::read(int64_t length) { if (length <= 0) { raise_notice("Invalid length %" PRId64, length); // XXX: Changing this to empty_string causes problems, something is // writing to this upstream but I'm not sure what and since it's // unlikely to provide significant gain alone I'm leaving it for now. return ""; } auto const allocSize = length; String s = String(allocSize, ReserveString); char *ret = s.bufferSlice().ptr; int64_t copied = 0; int64_t avail = bufferedLen(); while (avail < length && !eof()) { if (m_buffer == nullptr) { m_buffer = (char *)malloc(CHUNK_SIZE); m_bufferSize = CHUNK_SIZE; } if (avail > 0) { memcpy(ret + copied, m_buffer + m_readpos, avail); copied += avail; length -= avail; } m_writepos = filteredReadToBuffer(); m_readpos = 0; avail = bufferedLen(); if (avail == 0 || m_nonblocking) { // For nonblocking mode, temporary out of data. break; } } avail = bufferedLen(); if (avail > 0) { int64_t n = length < avail ? length : avail; memcpy(ret + copied, m_buffer + m_readpos, n); m_readpos += n; copied += n; } m_position += copied; assert(copied <= allocSize); s.shrink(copied); return s; }
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.bufferSlice().ptr; if (!snappy::RawUncompress(data.data(), data.size(), uncompressed)) { return false; } return s.setSize(dsize); #endif }
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); }
Variant HHVM_FUNCTION(lz4hccompress, const String& 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.bufferSlice().ptr; VarintEncode(uncompressed.size(), &compressed); // write the header int csize = LZ4_compressHC(uncompressed.data(), compressed, uncompressed.size()); if (csize < 0) { return false; } bufsize = csize + headerSize; return s.shrink(bufsize); }
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; }
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.bufferSlice().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); }
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; }
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; }
String f_utf8_decode(const String& data) { String str = String(data.size(), ReserveString); char *newbuf = str.bufferSlice().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); }
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; }
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(); }
static Variant php_mcrypt_do_crypt(const String& cipher, const String& key, const String& data, const String& mode, const String& 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.bufferSlice().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.bufferSlice().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); }
Variant ZendPack::pack(const String& fmt, CArrRef argv) { /* Preprocess format into formatcodes and formatargs */ std::vector<char> formatcodes; std::vector<int> 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': if (currentarg >= argc) { throw_invalid_argument("Type %c: not enough arguments", code); return false; } if (arg < 0) { arg = argv[currentarg].toString().size(); } currentarg++; break; /* Use as many args as specified */ 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': 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 '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 s = String(outputsize, ReserveString); char *output = s.bufferSlice().ptr; 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': memset(&output[outputpos], (code == 'a') ? '\0' : ' ', arg); val = argv[currentarg++].toString(); s = val.c_str(); slen = val.size(); memcpy(&output[outputpos], s, (slen < arg) ? slen : arg); 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': { int *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': { int *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 '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; } } return s.setSize(outputpos); }
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; while (formatlen-- > 0) { char type = *(format++); char c; int arg = 1, argb; const char *name; int namelen; int size=0; /* Handle format arguments if any */ if (formatlen > 0) { 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': 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 sizeof(int) 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 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': { char pad = (type == 'a') ? '\0' : ' '; 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; /* Remove padding chars from unpacked data */ while (--len >= 0) { if (input[inputpos + len] != pad) break; } ret.set(String(n, CopyString), String(input + inputpos, len + 1, 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.bufferSlice().ptr; 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; int *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; int *map = machine_endian_int32_map; int32_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 '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++; }
Variant File::readRecord(const String& delimiter, int64_t maxlen /* = 0 */) { if (eof() && m_writepos == m_readpos) { return false; } if (maxlen <= 0 || maxlen > CHUNK_SIZE) { maxlen = CHUNK_SIZE; } int64_t avail = bufferedLen(); if (m_buffer == nullptr) { 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 = bufferedLen(); } if (m_readpos >= CHUNK_SIZE) { memcpy(m_buffer, m_buffer + m_readpos, bufferedLen()); m_writepos -= m_readpos; m_readpos = 0; } int64_t 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), bufferedLen()); } else { int64_t pos = string_find(m_buffer + m_readpos, bufferedLen(), delimiter.data(), delimiter.size(), 0, true); if (pos >= 0) { e = m_buffer + m_readpos + pos; } else { e = nullptr; } } 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.bufferSlice().ptr; if (toread) { memcpy(buf, m_buffer + m_readpos, toread); } m_readpos += toread; if (skip) { m_readpos += delimiter.size(); m_position += delimiter.size(); } s.setSize(toread); return s; } return empty_string(); }