/* Function to populate TSK Blackboard exif related attributes */ void extractExifData(ExifData * exifData, TskFile * pFile) { std::map<ExifTag, TSK_ATTRIBUTE_TYPE>::iterator it; std::vector<TskBlackboardAttribute> attrs; std::string datetime = ""; int timezone = 0; for (it = tagMap.begin(); it != tagMap.end(); ++it) { ExifEntry * exifEntry = exif_data_get_entry(exifData, it->first); char tag_data[256]; if (exifEntry == NULL) continue; if (it->first == EXIF_TAG_GPS_LATITUDE || it->first == EXIF_TAG_GPS_LONGITUDE) { // Check for the EXIF_IFD_GPS image file directory to avoid interoperability value ExifIfd ifd = exif_entry_get_ifd(exifEntry); if (ifd != EXIF_IFD_GPS) continue; exif_entry_get_value(exifEntry, tag_data, 256); float decDegrees = getDecimalDegrees(tag_data); char refValue[2]; if (it->first == EXIF_TAG_GPS_LATITUDE) { // Get the latitude reference value; used to determine if positive or negative decimal value ExifEntry * latitudeRef = exif_data_get_entry(exifData, it->first); exif_entry_get_value(latitudeRef, refValue,2); if (strcmp(refValue, "S") == 0) decDegrees *= -1; } else { // Get the longitude reference value; used to determine if positive or negative decimal value ExifEntry * longitudeRef = exif_data_get_entry(exifData, it->first); exif_entry_get_value(longitudeRef, refValue,2); if (strcmp(refValue, "W") == 0) decDegrees *= -1; } TskBlackboardAttribute attr(it->second, name(), "", decDegrees); attrs.push_back(attr); } else if (it->first == EXIF_TAG_GPS_SPEED) { // Check for the EXIF_IFD_GPS image file directory to avoid interoperability value ExifIfd ifd = exif_entry_get_ifd(exifEntry); if (ifd != EXIF_IFD_GPS) continue; //Get the GPS speed value exif_entry_get_value(exifEntry, tag_data, 256); float speed = getGPSSpeed(tag_data); char refValue[2]; //Get the GPS speed reference value ExifEntry * speedRef = exif_data_get_entry(exifData, it->first); exif_entry_get_value(speedRef, refValue,2); //Convert Kilometers per hour to meters per second if (strcmp(refValue, "K") == 0) { speed *= 0.277778; } //Convert Miles per hour to meters per second if (strcmp(refValue, "M") == 0) { speed *= 0.44704; } //Convert Knots to meters per second if (strcmp(refValue, "N") == 0) { speed *= 0.514444; } TskBlackboardAttribute attr(it->second, name(), "", speed); attrs.push_back(attr); } else if (it->first == EXIF_TAG_DATE_TIME_ORIGINAL) { exif_entry_get_value(exifEntry, tag_data, 256); datetime = std::string(tag_data); } else if(it->first == EXIF_TAG_TIME_ZONE_OFFSET){ exif_entry_get_value(exifEntry, tag_data, 256); timezone = atoi(tag_data); } else { // Get the tag's data exif_entry_get_value(exifEntry, tag_data, 256); // Add tag data to blackboard TskBlackboardAttribute attr(it->second, name(), "", tag_data); attrs.push_back(attr); } } if(!datetime.empty()){ Poco::DateTime parsedDT; int tzd; Poco::DateTimeParser::tryParse(datetime, parsedDT, tzd); if(timezone) parsedDT.makeUTC(timezone); else parsedDT.makeUTC(tzd); TskBlackboardAttribute attr(TSK_DATETIME, name(), "", (uint64_t)parsedDT.utcTime()); attrs.push_back(attr); } if(attrs.size() > 0){ TskBlackboardArtifact art = pFile->createArtifact(TSK_METADATA_EXIF); for(size_t i = 0; i < attrs.size(); i++){ art.addAttribute(attrs[i]); } } }
void FileServerRequestHandler::handleRequest(const HTTPRequest& request, Poco::MemoryInputStream& message, const std::shared_ptr<StreamSocket>& socket) { try { bool noCache = false; #if ENABLE_DEBUG noCache = true; #endif Poco::Net::HTTPResponse response; Poco::URI requestUri(request.getURI()); LOG_TRC("Fileserver request: " << requestUri.toString()); requestUri.normalize(); // avoid .'s and ..'s std::string path(requestUri.getPath()); if (path.find("loleaflet/" LOOLWSD_VERSION_HASH "/") == std::string::npos) { LOG_WRN("client - server version mismatch, disabling browser cache."); noCache = true; } std::vector<std::string> requestSegments; requestUri.getPathSegments(requestSegments); const std::string relPath = getRequestPathname(request); // Is this a file we read at startup - if not; its not for serving. if (requestSegments.size() < 1 || FileHash.find(relPath) == FileHash.end()) throw Poco::FileNotFoundException("Invalid URI request: [" + requestUri.toString() + "]."); const auto& config = Application::instance().config(); const std::string loleafletHtml = config.getString("loleaflet_html", "loleaflet.html"); const std::string endPoint = requestSegments[requestSegments.size() - 1]; if (endPoint == loleafletHtml) { preprocessFile(request, message, socket); return; } if (request.getMethod() == HTTPRequest::HTTP_GET) { if (endPoint == "admin.html" || endPoint == "adminSettings.html" || endPoint == "adminHistory.html" || endPoint == "adminAnalytics.html") { preprocessAdminFile(request, socket); return; } if (endPoint == "admin-bundle.js" || endPoint == "admin-localizations.js") { noCache = true; if (!LOOLWSD::AdminEnabled) throw Poco::FileAccessDeniedException("Admin console disabled"); if (!FileServerRequestHandler::isAdminLoggedIn(request, response)) throw Poco::Net::NotAuthenticatedException("Invalid admin login"); // Ask UAs to block if they detect any XSS attempt response.add("X-XSS-Protection", "1; mode=block"); // No referrer-policy response.add("Referrer-Policy", "no-referrer"); } // Do we have an extension. const std::size_t extPoint = endPoint.find_last_of('.'); if (extPoint == std::string::npos) throw Poco::FileNotFoundException("Invalid file."); const std::string fileType = endPoint.substr(extPoint + 1); std::string mimeType; if (fileType == "js") mimeType = "application/javascript"; else if (fileType == "css") mimeType = "text/css"; else if (fileType == "html") mimeType = "text/html"; else if (fileType == "png") mimeType = "image/png"; else if (fileType == "svg") mimeType = "image/svg+xml"; else mimeType = "text/plain"; auto it = request.find("If-None-Match"); if (it != request.end()) { // if ETags match avoid re-sending the file. if (!noCache && it->second == "\"" LOOLWSD_VERSION_HASH "\"") { // TESTME: harder ... - do we even want ETag support ? std::ostringstream oss; Poco::DateTime now; Poco::DateTime later(now.utcTime(), int64_t(1000)*1000 * 60 * 60 * 24 * 128); oss << "HTTP/1.1 304 Not Modified\r\n" << "Date: " << Poco::DateTimeFormatter::format( now, Poco::DateTimeFormat::HTTP_FORMAT) << "\r\n" << "Expires: " << Poco::DateTimeFormatter::format( later, Poco::DateTimeFormat::HTTP_FORMAT) << "\r\n" << "User-Agent: " << WOPI_AGENT_STRING << "\r\n" << "Cache-Control: max-age=11059200\r\n" << "\r\n"; socket->send(oss.str()); socket->shutdown(); return; } } response.set("User-Agent", HTTP_AGENT_STRING); response.set("Date", Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT)); bool gzip = request.hasToken("Accept-Encoding", "gzip"); const std::string *content; #if ENABLE_DEBUG if (std::getenv("LOOL_SERVE_FROM_FS")) { // Useful to not serve from memory sometimes especially during loleaflet development // Avoids having to restart loolwsd everytime you make a change in loleaflet const std::string filePath = Poco::Path(LOOLWSD::FileServerRoot, relPath).absolute().toString(); HttpHelper::sendFile(socket, filePath, mimeType, response, noCache); return; } #endif if (gzip) { response.set("Content-Encoding", "gzip"); content = getCompressedFile(relPath); } else content = getUncompressedFile(relPath); if (!noCache) { // 60 * 60 * 24 * 128 (days) = 11059200 response.set("Cache-Control", "max-age=11059200"); response.set("ETag", "\"" LOOLWSD_VERSION_HASH "\""); } response.setContentType(mimeType); response.add("X-Content-Type-Options", "nosniff"); std::ostringstream oss; response.write(oss); const std::string header = oss.str(); LOG_TRC("#" << socket->getFD() << ": Sending " << (!gzip ? "un":"") << "compressed : file [" << relPath << "]: " << header); socket->send(header); socket->send(*content); } } catch (const Poco::Net::NotAuthenticatedException& exc) { LOG_ERR("FileServerRequestHandler::NotAuthenticated: " << exc.displayText()); sendError(401, request, socket, "", "", "WWW-authenticate: Basic realm=\"online\"\r\n"); } catch (const Poco::FileAccessDeniedException& exc) { LOG_ERR("FileServerRequestHandler: " << exc.displayText()); sendError(403, request, socket, "403 - Access denied!", "You are unable to access"); } catch (const Poco::FileNotFoundException& exc) { LOG_WRN("FileServerRequestHandler: " << exc.displayText()); sendError(404, request, socket, "404 - file not found!", "There seems to be a problem locating"); } }