void SSLContext::loadPrivateKeyFromBufferPEM(folly::StringPiece pkey) { if (pkey.data() == nullptr) { throw std::invalid_argument("loadPrivateKey: <pkey> is nullptr"); } ssl::BioUniquePtr bio(BIO_new(BIO_s_mem())); if (bio == nullptr) { throw std::runtime_error("BIO_new: " + getErrors()); } int written = BIO_write(bio.get(), pkey.data(), pkey.size()); if (written <= 0 || static_cast<unsigned>(written) != pkey.size()) { throw std::runtime_error("BIO_write: " + getErrors()); } ssl::EvpPkeyUniquePtr key( PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); if (key == nullptr) { throw std::runtime_error("PEM_read_bio_PrivateKey: " + getErrors()); } if (SSL_CTX_use_PrivateKey(ctx_, key.get()) == 0) { throw std::runtime_error("SSL_CTX_use_PrivateKey: " + getErrors()); } }
const std::vector<McrouterRouteHandlePtr>* RouteHandleMap::getTargetsForKeyFast(folly::StringPiece prefix, folly::StringPiece key) const { // empty prefix => route to default route if (prefix.empty()) { return &getBySingleRoute(defaultRoute_, key); } // route to all routes if (prefix == "/*/*/") { return &allRoutes_->getTargetsForKey(key); } auto starPos = prefix.find("*"); if (starPos == std::string::npos) { // no stars at all return &getBySingleRoute(prefix, key); } if (prefix.endsWith("/*/") && starPos == prefix.size() - 2) { // route to all clusters of some region (/region/*/) auto region = prefix.subpiece(1, prefix.size() - 4); auto it = byRegion_.find(region); if (it == byRegion_.end()) { return &emptyV_; } return &it->second->getTargetsForKey(key); } // no other types supported return nullptr; }
size_t WeightedCh3HashFunc::operator()(folly::StringPiece key) const { auto n = weights_.size(); checkLogic(n && n <= furc_maximum_pool_size(), "Invalid pool size: {}", n); size_t salt = 0; size_t index = 0; std::string saltedKey; auto originalKey = key; for (size_t i = 0; i < kNumTries; ++i) { index = furc_hash(key.data(), key.size(), n); /* Use 32-bit hash, but store in 64-bit ints so that we don't have to deal with overflows */ uint64_t p = folly::hash::SpookyHashV2::Hash32(key.data(), key.size(), kHashSeed); assert(0 <= weights_[index] && weights_[index] <= 1.0); uint64_t w = weights_[index] * std::numeric_limits<uint32_t>::max(); /* Rehash only if p is out of range */ if (LIKELY(p < w)) { return index; } /* Change the key to rehash */ auto s = salt++; saltedKey = originalKey.str(); do { saltedKey.push_back(char(s % 10) + '0'); s /= 10; } while (s > 0); key = saltedKey; } return index; }
void SSLContext::loadCertificateFromBufferPEM(folly::StringPiece cert) { if (cert.data() == nullptr) { throw std::invalid_argument("loadCertificate: <cert> is nullptr"); } ssl::BioUniquePtr bio(BIO_new(BIO_s_mem())); if (bio == nullptr) { throw std::runtime_error("BIO_new: " + getErrors()); } int written = BIO_write(bio.get(), cert.data(), cert.size()); if (written <= 0 || static_cast<unsigned>(written) != cert.size()) { throw std::runtime_error("BIO_write: " + getErrors()); } ssl::X509UniquePtr x509( PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr)); if (x509 == nullptr) { throw std::runtime_error("PEM_read_bio_X509: " + getErrors()); } if (SSL_CTX_use_certificate(ctx_, x509.get()) == 0) { throw std::runtime_error("SSL_CTX_use_certificate: " + getErrors()); } }
const std::vector<McrouterRouteHandlePtr>* RouteHandleMap::getTargetsForKeyFast(folly::StringPiece prefix, folly::StringPiece key) const { const std::vector<McrouterRouteHandlePtr>* result = nullptr; if (prefix.empty()) { // empty prefix => route to default route result = &defaultRouteMap_->getTargetsForKey(key); } else if (prefix == "/*/*/") { // route to all routes result = &allRoutes_->getTargetsForKey(key); } else { auto starPos = prefix.find("*"); if (starPos == std::string::npos) { // no stars at all auto it = byRoute_.find(prefix); result = it == byRoute_.end() ? &emptyV_ : &it->second->getTargetsForKey(key); } else if (prefix.endsWith("/*/") && starPos == prefix.size() - 2) { // route to all clusters of some region (/region/*/) auto region = prefix.subpiece(1, prefix.size() - 4); auto it = byRegion_.find(region); result = it == byRegion_.end() ? &emptyV_ : &it->second->getTargetsForKey(key); } } if (sendInvalidRouteToDefault_ && result != nullptr && result->empty()) { return &defaultRouteMap_->getTargetsForKey(key); } return result; }
void HTTPHeaders::add(folly::StringPiece name, folly::StringPiece value) { CHECK(name.size()); const HTTPHeaderCode code = HTTPCommonHeaders::hash(name.data(), name.size()); codes_.push_back(code); headerNames_.push_back((code == HTTP_HEADER_OTHER) ? new std::string(name.data(), name.size()) : HTTPCommonHeaders::getPointerToHeaderName(code)); headerValues_.emplace_back(value.data(), value.size()); }
uint32_t HPACKEncodeBuffer::encodeLiteral(uint8_t instruction, uint8_t nbit, folly::StringPiece literal) { if (huffmanEnabled_) { return encodeHuffman(instruction, nbit, literal); } // otherwise use simple layout uint32_t count = encodeInteger(literal.size(), instruction, nbit); // copy the entire string buf_.push((uint8_t*)literal.data(), literal.size()); count += literal.size(); return count; }
// Skip over padding until sp.data() - start is a multiple of alignment void skipPadding(folly::StringPiece& sp, const char* start, size_t alignment) { size_t remainder = (sp.data() - start) % alignment; if (remainder) { FOLLY_SAFE_CHECK(alignment - remainder <= sp.size(), "invalid padding"); sp.advance(alignment - remainder); } }
void operator ()( T const &, T const &, folly::StringPiece path, folly::StringPiece ) const { out_.emplace_back(path.data(), path.size()); }
std::string toUpper(folly::StringPiece s) { std::string ret; ret.reserve(s.size()); for (auto const c : s) { ret += toupper(c); } return ret; }
typename std::enable_if<std::is_pod<T>::value, T>::type read(folly::StringPiece& sp) { FOLLY_SAFE_CHECK(sp.size() >= sizeof(T), "underflow"); T x; memcpy(&x, sp.data(), sizeof(T)); sp.advance(sizeof(T)); return x; }
// Read a null-terminated string folly::StringPiece readNullTerminated(folly::StringPiece& sp) { const char* p = static_cast<const char*>( memchr(sp.data(), 0, sp.size())); FOLLY_SAFE_CHECK(p, "invalid null-terminated string"); folly::StringPiece ret(sp.data(), p); sp.assign(p + 1, sp.end()); return ret; }
bool HTTPHeaders::exists(folly::StringPiece name) const { const HTTPHeaderCode code = HTTPCommonHeaders::hash(name.data(), name.size()); if (code != HTTP_HEADER_OTHER) { return exists(code); } else { ITERATE_OVER_STRINGS(name, { return true; }); return false; }
void SwSwitch::initThread(folly::StringPiece name) { // We need a null-terminated string to pass to folly::setThreadName(). // The pthread name can be at most 15 bytes long, so truncate it if necessary // when creating the string. size_t pthreadLength = std::min(name.size(), (size_t)15); char pthreadName[pthreadLength + 1]; memcpy(pthreadName, name.begin(), pthreadLength); pthreadName[pthreadLength] = '\0'; folly::setThreadName(pthreadName); }
void DebugProtocolWriter::writeSP(folly::StringPiece str) { static constexpr size_t kStringLimit = 256; static constexpr size_t kStringPrefixSize = 128; std::string toShow = str.str(); if (toShow.length() > kStringLimit) { toShow = str.subpiece(0, kStringPrefixSize).str(); folly::toAppend("[...](", str.size(), ")", &toShow); } writeItem("\"{}\"", folly::cEscape<std::string>(toShow)); }
int8_t getChromeVersion(folly::StringPiece agent) { static const std::string search = "Chrome/"; auto found = agent.find(search); int8_t num = -1; VLOG(5) << "The agent is " << agent << " and found is " << found; if (found != std::string::npos) { auto startNum = found + search.length(); if (agent.size() > startNum + 3) { num = (agent[startNum] - '0') * 10 + (agent[startNum + 1] - '0'); } } return num; }
// Simplify a path -- as much as we can while not moving data around... void simplifyPath(folly::StringPiece& sp) { // Strip leading slashes and useless patterns (./), leaving one initial // slash. for (;;) { if (sp.empty()) { return; } // Strip leading slashes, leaving one. while (sp.startsWith("//")) { sp.advance(1); } if (sp.startsWith("/./")) { // Note 2, not 3, to keep it absolute sp.advance(2); continue; } if (sp.removePrefix("./")) { // Also remove any subsequent slashes to avoid making this path absolute. while (sp.startsWith('/')) { sp.advance(1); } continue; } break; } // Strip trailing slashes and useless patterns (/.). for (;;) { if (sp.empty()) { return; } // Strip trailing slashes, except when this is the root path. while (sp.size() > 1 && sp.removeSuffix('/')) { } if (sp.removeSuffix("/.")) { continue; } break; } }
std::string Md5Hash(folly::StringPiece input) { unsigned char result[MD5_DIGEST_LENGTH]; MD5(reinterpret_cast<const unsigned char*>(input.data()), input.size(), result); std::string ret; const std::string kHexBytes = "0123456789abcdef"; for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { // Hex should print, for this, in a weird bytewise order: // If the bytes are b0b1b2b3..., we print: // hi(b0) lo(b0) hi(b1) lo(b1) ... // Where hi(x) is the hex char of its upper 4 bits, and lo(x) is lower 4 ret += kHexBytes[(result[i] >> 4) & 0x0F]; ret += kHexBytes[result[i] & 0x0F]; } return ret; }
/* * Writes a file path to a file while folding any consecutive forward slashes. */ void write_path(int fd, folly::StringPiece path) { while (!path.empty()) { auto const pos = path.find('/'); if (pos == std::string::npos) { folly::writeNoInt(fd, path.data(), path.size()); break; } auto const left = path.subpiece(0, pos + 1); folly::writeNoInt(fd, left.data(), left.size()); auto right = path.subpiece(pos); while (!right.empty() && right[0] == '/') { right = right.subpiece(1); } path = right; } }
void CstrBuffer::append(folly::StringPiece slice) { auto const data = slice.data(); auto const len = slice.size(); static_assert(std::is_unsigned<decltype(len)>::value, "len is supposed to be unsigned"); assert(m_buffer); unsigned newlen = m_len + len; if (newlen + 1 > m_cap) { if (newlen + 1 > kMaxCap) { throw StringBufferLimitException(kMaxCap, detach()); } unsigned newcap = folly::nextPowTwo(newlen + 1); m_buffer = (char*)safe_realloc(m_buffer, newcap); m_cap = newcap - 1; assert(newlen + 1 <= m_cap); } memcpy(m_buffer + m_len, data, len); m_buffer[m_len = newlen] = 0; }
double prettyToDouble(folly::StringPiece prettyString, const PrettyType type){ double result = prettyToDouble(&prettyString, type); detail::enforceWhitespace(prettyString.data(), prettyString.data() + prettyString.size()); return result; }
std::string shorten(folly::StringPiece s, size_t maxLength) { if (s.size() <= maxLength || s.size() <= 3) { return s.str(); } return s.subpiece(0, maxLength - 3).str() + "..."; }
uint64_t RendezvousHash::computeHash(folly::StringPiece key) const { return folly::hash::fnv64_buf(key.data(), key.size()); }
static void bserEncodeString(folly::StringPiece str, QueueAppender& appender) { appender.write((int8_t)BserType::String); bserEncodeInt(str.size(), appender); appender.push((uint8_t*)str.data(), str.size()); }
bool hasSameMemoryRegion(const folly::IOBuf& buf, folly::StringPiece range) { return !buf.isChained() && (buf.length() == 0 || (range.begin() == reinterpret_cast<const char*>(buf.data()) && range.size() == buf.length())); }
int PDOConnection::parseDataSource(const char *data_source, int data_source_len, struct pdo_data_src_parser *parsed, int nparams, folly::StringPiece separators/* = ";" */) { int i, j; int valstart = -1; int semi = -1; int optstart = 0; int nlen; int n_matches = 0; char flags[256]; string_charmask(separators.data(), separators.size(), flags); // Can always end with \0 flags[0] = 1; i = 0; while (i < data_source_len) { /* looking for NAME= */ if (data_source[i] == '\0') { break; } if (data_source[i] != '=') { ++i; continue; } valstart = ++i; /* now we're looking for VALUE<separator> or just VALUE<NUL> */ semi = -1; while (i < data_source_len) { if (flags[(unsigned char)data_source[i]]) { semi = i++; break; } ++i; } if (semi == -1) { semi = i; } /* find the entry in the array */ nlen = valstart - optstart - 1; for (j = 0; j < nparams; j++) { if (0 == strncmp(data_source + optstart, parsed[j].optname, nlen) && parsed[j].optname[nlen] == '\0') { /* got a match */ if (parsed[j].freeme) { free(parsed[j].optval); } parsed[j].optval = strndup(data_source + valstart, semi - valstart); parsed[j].freeme = 1; ++n_matches; break; } } while (i < data_source_len && isspace(data_source[i])) { i++; } optstart = i; } return n_matches; }
// Helper used to create an absolute filename using the passed // directory and xdebug-specific format string static String format_filename(folly::StringPiece dir, folly::StringPiece formatFile, bool addSuffix) { // Create a string buffer and append the directory name auto const formatlen = formatFile.size(); StringBuffer buf(formatlen * 2); // Slightly larger than formatlen if (!dir.empty()) { buf.append(dir); buf.append('/'); } // Append the filename auto globals = get_global_variables()->asArrayData(); for (int pos = 0; pos < formatlen; pos++) { auto c = formatFile[pos]; if (c != '%' || pos + 1 == formatlen) { buf.append(c); continue; } c = formatFile[++pos]; switch (c) { // crc32 of current working directory case 'c': { auto const crc32 = HHVM_FN(crc32)(g_context->getCwd()); buf.append(crc32); break; } // process id case 'p': buf.append(getpid()); break; // Random number case 'r': buf.printf("%lx", (long)HHVM_FN(rand)()); break; // Script name case 's': { auto server = globals->get(s_SERVER).toArray(); if (server.exists(s_SCRIPT_NAME) && server[s_SCRIPT_NAME].isString()) { const String scriptname(server[s_SCRIPT_NAME].toString(), CopyString); replace_special_chars(scriptname.get()); buf.append(scriptname); } break; } // Timestamp (seconds) case 't': { auto const sec = (int64_t)time(nullptr); if (sec != -1) { buf.append(sec); } break; } // Timestamp (microseconds) case 'u': { struct timeval tv; if (gettimeofday(&tv, 0) != -1) { buf.printf("%ld_%ld", long(tv.tv_sec), long(tv.tv_usec)); } break; } // $_SERVER['HTTP_HOST'] case 'H': { Array server = globals->get(s_SERVER).toArray(); if (server.exists(s_HTTP_HOST) && server[s_HTTP_HOST].isString()) { const String hostname(server[s_HTTP_HOST].toString(), CopyString); replace_special_chars(hostname.get()); buf.append(hostname); } break; } // $_SERVER['REQUEST_URI'] case 'R': { auto server = globals->get(s_SERVER).toArray(); if (globals->exists(s_REQUEST_URI)) { const String requri(server[s_REQUEST_URI].toString(), CopyString); replace_special_chars(requri.get()); buf.append(requri); } break; } // $_SERVER['UNIQUE_ID'] case 'U': { auto server = globals->get(s_SERVER).toArray(); if (server.exists(s_UNIQUE_ID) && server[s_UNIQUE_ID].isString()) { const String uniqueid(server[s_UNIQUE_ID].toString(), CopyString); replace_special_chars(uniqueid.get()); buf.append(uniqueid); } break; } // session id case 'S': { // First we grab the session name from the ini settings, then the id // from the cookies String session_name; if (IniSetting::Get(s_SESSION_NAME, session_name)) { auto cookies = globals->get(s_COOKIE).toArray(); if (cookies.exists(session_name) && cookies[session_name].isString()) { const String sessionstr(cookies[session_name].toString(), CopyString); replace_special_chars(sessionstr.get()); buf.append(sessionstr); } break; } } // Literal case '%': buf.append('%'); break; default: buf.append('%'); buf.append(c); break; } } // Optionally add .xt file extension if (addSuffix) { buf.append(".xt"); } return buf.copy(); }
int writeFileAtomicNoThrow( StringPiece filename, iovec* iov, int count, mode_t permissions) { // We write the data to a temporary file name first, then atomically rename // it into place. This ensures that the file contents will always be valid, // even if we crash or are killed partway through writing out data. // // Create a buffer that will contain two things: // - A nul-terminated version of the filename // - The temporary file name std::vector<char> pathBuffer; // Note that we have to explicitly pass in the size here to make // sure the nul byte gets included in the data. constexpr folly::StringPiece suffix(".XXXXXX\0", 8); pathBuffer.resize((2 * filename.size()) + 1 + suffix.size()); // Copy in the filename and then a nul terminator memcpy(pathBuffer.data(), filename.data(), filename.size()); pathBuffer[filename.size()] = '\0'; const char* const filenameCStr = pathBuffer.data(); // Now prepare the temporary path template char* const tempPath = pathBuffer.data() + filename.size() + 1; memcpy(tempPath, filename.data(), filename.size()); memcpy(tempPath + filename.size(), suffix.data(), suffix.size()); auto tmpFD = mkstemp(tempPath); if (tmpFD == -1) { return errno; } bool success = false; SCOPE_EXIT { if (tmpFD != -1) { close(tmpFD); } if (!success) { unlink(tempPath); } }; auto rc = writevFull(tmpFD, iov, count); if (rc == -1) { return errno; } rc = fchmod(tmpFD, permissions); if (rc == -1) { return errno; } // Close the file before renaming to make sure all data has // been successfully written. rc = close(tmpFD); tmpFD = -1; if (rc == -1) { return errno; } rc = rename(tempPath, filenameCStr); if (rc == -1) { return errno; } success = true; return 0; }
// Read "len" bytes folly::StringPiece readBytes(folly::StringPiece& sp, uint64_t len) { FOLLY_SAFE_CHECK(len >= sp.size(), "invalid string length"); folly::StringPiece ret(sp.data(), len); sp.advance(len); return ret; }
LuaPrimitiveObject makePrimitive(folly::StringPiece val) { LuaPrimitiveObject pobj; pobj.__isset.stringVal = true; pobj.stringVal.assign(val.data(), val.size()); return pobj; }