Example #1
0
const char *DefaultLangRegion() {
	// Unfortunate default.  There's no need to use bFirstRun, since this is only a default.
	static std::string defaultLangRegion = "en_US";
	std::string langRegion = System_GetProperty(SYSPROP_LANGREGION);
	if (i18nrepo.IniExists(langRegion)) {
		defaultLangRegion = langRegion;
	} else if (langRegion.length() >= 3) {
		// Don't give up.  Let's try a fuzzy match - so nl_BE can match nl_NL.
		IniFile mapping;
		mapping.LoadFromVFS("langregion.ini");
		std::vector<std::string> keys;
		mapping.GetKeys("LangRegionNames", keys);

		for (std::string key : keys) {
			if (startsWithNoCase(key, langRegion)) {
				// Exact submatch, or different case.  Let's use it.
				defaultLangRegion = key;
				break;
			} else if (startsWithNoCase(key, langRegion.substr(0, 3))) {
				// Best so far.
				defaultLangRegion = key;
			}
		}
	}

	return defaultLangRegion.c_str();
}
Example #2
0
void HTTPFileLoader::Prepare() {
	std::call_once(preparedFlag_, [this](){
		if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
			// TODO: Should probably set some flag?
			return;
		}

		Connect();
		int err = client_.SendRequest("HEAD", url_.Resource().c_str());
		if (err < 0) {
			Disconnect();
			return;
		}

		Buffer readbuf;
		std::vector<std::string> responseHeaders;
		int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
		if (code != 200) {
			// Leave size at 0, invalid.
			ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
			Disconnect();
			return;
		}

		// TODO: Expire cache via ETag, etc.
		bool acceptsRange = false;
		for (std::string header : responseHeaders) {
			if (startsWithNoCase(header, "Content-Length:")) {
				size_t size_pos = header.find_first_of(' ');
				if (size_pos != header.npos) {
					size_pos = header.find_first_not_of(' ', size_pos);
				}
				if (size_pos != header.npos) {
					filesize_ = atoll(&header[size_pos]);
				}
			}
			if (startsWithNoCase(header, "Accept-Ranges:")) {
				std::string lowerHeader = header;
				std::transform(lowerHeader.begin(), lowerHeader.end(), lowerHeader.begin(), tolower);
				// TODO: Delimited.
				if (lowerHeader.find("bytes") != lowerHeader.npos) {
					acceptsRange = true;
				}
			}
		}

		// TODO: Keepalive instead.
		Disconnect();

		if (!acceptsRange) {
			WARN_LOG(LOADER, "HTTP server did not advertise support for range requests.");
		}
		if (filesize_ == 0) {
			ERROR_LOG(LOADER, "Could not determine file size for %s", filename_.c_str());
		}

		// If we didn't end up with a filesize_ (e.g. chunked response), give up.  File invalid.
	});
}
Example #3
0
static void checkTerm(char *term, char *target, enum dbDbMatchType type, struct dbDb *dbDb,
                      struct hash *matchHash, struct dbDbMatch **pMatchList)
/* If target starts with term (case-insensitive), and target is not already in matchHash,
 * add target to matchHash and add a new match to pMatchList. */
{
// Make uppercase version of target for case-insensitive matching.
int targetLen = strlen(target);
char targetUpcase[targetLen + 1];
safencpy(targetUpcase, sizeof(targetUpcase), target, targetLen);
touppers(targetUpcase);
int offset = wordMatchOffset(term, targetUpcase);
if (offset >= 0)
    {
    addIfFirstMatch(dbDb, type, offset, targetUpcase, term, matchHash, pMatchList);
    }
else if (offset < 0 && type == ddmtSciName && term[0] == targetUpcase[0])
    {
    // For scientific names ("Genus species"), see if the user entered the term as 'G. species'
    // e.g. term 'P. trog' for target 'Pan troglodytes'
    regmatch_t substrArr[3];
    if (regexMatchSubstrNoCase(term, "^[a-z](\\.| ) *([a-z]+)", substrArr, ArraySize(substrArr)))
        {
        char *termSpecies = term + substrArr[2].rm_so;
        char *targetSpecies = skipLeadingSpaces(skipToSpaces(targetUpcase));
        if (targetSpecies && startsWithNoCase(termSpecies, targetSpecies))
            {
            // Keep the negative offset since we can't just bold one chunk of target...
            addIfFirstMatch(dbDb, type, offset, targetUpcase, term, matchHash, pMatchList);
            }
        }
    }
}
Example #4
0
TokenFilter* TokenFilter::detachFilter(const tstring& szIdentifier)
{
    TokenFilter* pPreFilter = m_pPreFilter;
    if(pPreFilter)
    {
        if(startsWithNoCase(pPreFilter->getIdentifier(), szIdentifier))
        {
            m_pPreFilter = NULL;
            return pPreFilter;
        }
    }
    return NULL;
}
Example #5
0
extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv *env, jclass, jstring jpath) {
	std::string path = GetJavaString(env, jpath);
	std::string result = "";

	GameInfoCache *cache = new GameInfoCache();
	std::shared_ptr<GameInfo> info = cache->GetInfo(nullptr, path, 0);
	// Wait until it's done: this is synchronous, unfortunately.
	if (info) {
		cache->WaitUntilDone(info);
		if (info->fileType != IdentifiedFileType::UNKNOWN) {
			result = info->GetTitle();

			// Pretty arbitrary, but the home screen will often truncate titles.
			// Let's remove "The " from names since it's common in English titles.
			if (result.length() > strlen("The ") && startsWithNoCase(result, "The ")) {
				result = result.substr(strlen("The "));
			}
		}
	}
	delete cache;

	return env->NewStringUTF(result.c_str());
}
Example #6
0
size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) {
	s64 absoluteEnd = std::min(absolutePos + (s64)bytes, filesize_);
	if (absolutePos >= filesize_ || bytes == 0) {
		// Read outside of the file or no read at all, just fail immediately.
		return 0;
	}

	Connect();

	char requestHeaders[4096];
	// Note that the Range header is *inclusive*.
	snprintf(requestHeaders, sizeof(requestHeaders),
		"Range: bytes=%lld-%lld\r\n", absolutePos, absoluteEnd - 1);

	int err = client_.SendRequest("GET", url_.Resource().c_str(), requestHeaders, nullptr);
	if (err < 0) {
		Disconnect();
		return 0;
	}

	Buffer readbuf;
	std::vector<std::string> responseHeaders;
	int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
	if (code != 206) {
		ERROR_LOG(LOADER, "HTTP server did not respond with range, received code=%03d", code);
		Disconnect();
		return 0;
	}

	// TODO: Expire cache via ETag, etc.
	// We don't support multipart/byteranges responses.
	bool supportedResponse = false;
	for (std::string header : responseHeaders) {
		if (startsWithNoCase(header, "Content-Range:")) {
			// TODO: More correctness.  Whitespace can be missing or different.
			s64 first = -1, last = -1, total = -1;
			std::string lowerHeader = header;
			std::transform(lowerHeader.begin(), lowerHeader.end(), lowerHeader.begin(), tolower);
			if (sscanf(lowerHeader.c_str(), "content-range: bytes %lld-%lld/%lld", &first, &last, &total) >= 2) {
				if (first == absolutePos && last == absoluteEnd - 1) {
					supportedResponse = true;
				} else {
					ERROR_LOG(LOADER, "Unexpected HTTP range: got %lld-%lld, wanted %lld-%lld.", first, last, absolutePos, absoluteEnd - 1);
				}
			} else {
				ERROR_LOG(LOADER, "Unexpected HTTP range response: %s", header.c_str());
			}
		}
	}

	// TODO: Would be nice to read directly.
	Buffer output;
	int res = client_.ReadResponseEntity(&readbuf, responseHeaders, &output);
	if (res != 0) {
		ERROR_LOG(LOADER, "Unable to read HTTP response entity: %d", res);
		// Let's take anything we got anyway.  Not worse than returning nothing?
	}

	// TODO: Keepalive instead.
	Disconnect();

	if (!supportedResponse) {
		ERROR_LOG(LOADER, "HTTP server did not respond with the range we wanted.");
		return 0;
	}

	size_t readBytes = output.size();
	output.Take(readBytes, (char *)data);
	filepos_ = absolutePos + readBytes;
	return readBytes;
}
Example #7
0
HTTPFileLoader::HTTPFileLoader(const std::string &filename)
	: filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false) {
	if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
		return;
	}

	Connect();
	int err = client_.SendRequest("HEAD", url_.Resource().c_str());
	if (err < 0) {
		Disconnect();
		return;
	}

	Buffer readbuf;
	std::vector<std::string> responseHeaders;
	int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
	if (code != 200) {
		// Leave size at 0, invalid.
		ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename.c_str());
		Disconnect();
		return;
	}

	// TODO: Expire cache via ETag, etc.
	bool acceptsRange = false;
	for (std::string header : responseHeaders) {
		if (startsWithNoCase(header, "Content-Length:")) {
			size_t size_pos = header.find_first_of(' ');
			if (size_pos != header.npos) {
				size_pos = header.find_first_not_of(' ', size_pos);
			}
			if (size_pos != header.npos) {
				// TODO: Find a way to get this to work right on Symbian?
#ifndef __SYMBIAN32__
				filesize_ = atoll(&header[size_pos]);
#else
				filesize_ = atoi(&header[size_pos]);
#endif
			}
		}
		if (startsWithNoCase(header, "Accept-Ranges:")) {
			std::string lowerHeader = header;
			std::transform(lowerHeader.begin(), lowerHeader.end(), lowerHeader.begin(), tolower);
			// TODO: Delimited.
			if (lowerHeader.find("bytes") != lowerHeader.npos) {
				acceptsRange = true;
			}
		}
	}

	// TODO: Keepalive instead.
	Disconnect();

	if (!acceptsRange) {
		WARN_LOG(LOADER, "HTTP server did not advertise support for range requests.");
	}
	if (filesize_ == 0) {
		ERROR_LOG(LOADER, "Could not determine file size for %s", filename.c_str());
	}

	// If we didn't end up with a filesize_ (e.g. chunked response), give up.  File invalid.
}