void DirectoryFileSource::MountFiles(const PathStringArg& BasePath, const PathStringArg& DestinationPath){ ConvertAndValidatePath(BasePath); string NormBasePath = BasePath.GetNormalizedPath(); NormBasePath.push_back('/'); PlatformPath CurrentPath = BasePath.CreatePath(RealPath); string CurrentDestPath = DestinationPath.GetNormalizedPath(); if(!CurrentDestPath.empty() && CurrentDestPath.back() != '/'){ CurrentDestPath.push_back('/'); } std::wstring& CurrentPathS = const_cast<std::wstring&>(CurrentPath.native()); CurrentPathS.reserve(255); int pathOffset = RealPath.native().size(); std::function<void(const FileInfo&)> foreachFunc = [&](const FileInfo& file) mutable ->void { if(file.IsDirectory()){ int namesize = CurrentPathS.size(); string dirname = file.GetNormlizedNameWithSlash(); NormBasePath.append(dirname); CurrentDestPath.append(dirname); CurrentPath /= file.cFileName; //lambda recursion fun times ForEachFile(CurrentPath.c_str()+pathOffset, foreachFunc); //shrink the path back down one directory CurrentPathS.resize(namesize); CurrentDestPath.resize(CurrentDestPath.size()-dirname.size()); NormBasePath.resize(NormBasePath.size()-dirname.size()); }else{ //CurrentDestPath string FileName = file.GetNormlizedName(); string MountedPath = CurrentDestPath+FileName; SourceManager::MountFile(MountedPath, MountedFile(this, CurrentPath/file.cFileName, false)); MountedFiles.insert(std::make_pair(NormBasePath+FileName, std::move(MountedPath))); } }; ForEachFile(BasePath.ToString(), foreachFunc); }
void DirectoryFileSource::MountFile( const PathStringArg& FilePath, const PathStringArg& DestinationPath ){ ConvertAndValidatePath(FilePath); PlatformPath path = FilePath.CreatePath(RealPath); if(!boostfs::exists(path)){ throw std::exception("Cannot mount a file that does not exist"); } MountedFiles.insert(std::make_pair(FilePath.GetNormalizedPath(), DestinationPath.GetNormalizedPath())); SourceManager::MountFile(DestinationPath.GetNormalizedPath(), MountedFile(this, path, true)); }
int DirectoryFileSource::LoadLuaFile( lua_State* L, const PathStringArg& FilePath ) { auto path = RealPath/ConvertAndValidatePath(FilePath); if(FilePath.GetExtension() != luaExt){ throw std::runtime_error(FilePath.ToString() + " is not a lua file"); } string chunkpath = path.string(); // boost::replace(chunkpath, '/', '\\'); int result = LuaModule::LoadLuaFile(L, path, ('@'+chunkpath).c_str() ); //loadfile should of pushed either a function or an error message on to the stack leave it there as the return value return result; }
int DirectoryFileSource::RelativeRequire(lua_State* L, const PathStringArg& ModuleName ){ auto SearchPath = RealPath/ConvertAndValidatePath(ModuleName)/"?.dll"; auto package = luabind::globals(L)["package"]; //relative try{ string OriginalCPath = luabind::object_cast<string>(package["cpath"]); string OriginalPath = luabind::object_cast<string>(package["path"]); package["cpath"] = SearchPath.string(); package["cpath"] = OriginalCPath; package["path"] = OriginalPath; }catch(luabind::cast_failed e){ } return 0; }
/* * Handles the HTTP GET command from soap, only the client update install may be downloaded. * * This function can only be called when client_update_enabled is set to yes. * * @note This function is only use for backward compatibility */ int HandleClientUpdate(struct soap *soap) { std::string strPath; int nRet = 404; // default return file not found to soap char *szClientUpdatePath = NULL; char *szCurrentVersion = NULL; char *szReq = NULL; char *szReqEnd = NULL; std::string strLicenseRequest; std::string strLicenseResponse; ECLicenseClient *lpLicenseClient = NULL; unsigned int ulLicenseResponse = 0; unsigned char *lpLicenseResponse = NULL; ECRESULT er = erSuccess; ClientVersion currentVersion = {0}; ClientVersion latestVersion = {0}; std::string strClientMSIName; FILE *fd = NULL; // Get the server.cfg setting szClientUpdatePath = g_lpConfig->GetSetting("client_update_path"); if (!szClientUpdatePath || szClientUpdatePath[0] == 0) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: The configuration field 'client_update_path' is empty."); goto exit; } // if the version comes as "/autoupdate/6.20.1.1234?licreq", we need to pass the license request szReq = strrchr(soap->path, '?'); if (szReq != NULL) { // since we have the ?, that's good enough szReq = strstr(soap->buf, "X-License: "); if (szReq == NULL) { g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Client update: Invalid license request, header not found."); goto exit; } szReq += strlen("X-License: "); szReqEnd = strstr(szReq, "\r\n"); // TODO: can be be split over multiple lines? if (szReqEnd == NULL) { g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Client update: Invalid license request, end of header not found."); goto exit; } strLicenseRequest = base64_decode(std::string(szReq, szReqEnd - szReq)); lpLicenseClient = new ECLicenseClient(g_lpConfig->GetSetting("license_socket"), atoui(g_lpConfig->GetSetting("license_timeout"))); er = lpLicenseClient->Auth((unsigned char*)strLicenseRequest.c_str(), strLicenseRequest.length(), &lpLicenseResponse, &ulLicenseResponse); if (er != erSuccess) { g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Client update: Invalid license request, error: 0x%08X.", er); goto exit; } strLicenseResponse = base64_encode(lpLicenseResponse, ulLicenseResponse); soap->http_content = "binary"; soap_response(soap, SOAP_FILE); nRet = soap_send_raw(soap, strLicenseResponse.c_str(), strLicenseResponse.length()); g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Client update: Processing license request."); goto exit; } // the version comes as "/autoupdate/6.20.1.1234", convert it to "6.20.1.1234" szCurrentVersion = soap->path + strlen("/autoupdate"); if (szCurrentVersion[0] == '/') szCurrentVersion++; if (szCurrentVersion[0] != '\0') { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: The current client version is %s.", szCurrentVersion); if (!GetVersionFromString(szCurrentVersion, ¤tVersion)) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: Failed in getting version from input data."); goto exit; } } if (!GetLatestVersionAtServer(szClientUpdatePath, 0, &latestVersion)) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: No updates found on server."); goto exit; } if (szCurrentVersion[0] != '\0') { int res = CompareVersions(currentVersion, latestVersion); if (res == 0) { g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Client update: Client already has latest version."); goto exit; } else if (res > 0) { g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Client update: Client has newer version than server."); goto exit; } } if (!GetClientMSINameFromVersion(latestVersion, &strClientMSIName)) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: No suitable version available."); goto exit; } if (ConvertAndValidatePath(szClientUpdatePath, strClientMSIName, &strPath) != true) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: Error in path conversion and validation."); goto exit; } fd = fopen(strPath.c_str(), "rb"); if (!fd) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: Path not found %s.", strPath.c_str()); goto exit; } g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: Sending client %s new installer %s", PrettyIP(soap->ip).c_str(), strClientMSIName.c_str()); // application/msi-installer ? soap->http_content = "binary"; soap_response(soap, SOAP_FILE); while (true) { // FIXME: tmpbuf is only 1K, good enough? size_t nSize = fread(soap->tmpbuf, 1, sizeof(soap->tmpbuf), fd); if (!nSize) break; if (soap_send_raw(soap, soap->tmpbuf, nSize)) { g_lpLogger->Log(EC_LOGLEVEL_FATAL, "Client update: Error while sending client new installer"); goto exit; } } nRet = SOAP_OK; exit: if (lpLicenseResponse) delete [] lpLicenseResponse; if (lpLicenseClient) delete lpLicenseClient; if (fd) fclose(fd); return nRet; }
int ns__getClientUpdate(struct soap *soap, struct clientUpdateInfoRequest sClientUpdateInfo, struct clientUpdateResponse* lpsResponse) { unsigned int er = erSuccess; ClientVersion sCurrentVersion = {0}; ClientVersion sLatestVersion; unsigned int ulLicenseResponse = 0; unsigned char *lpLicenseResponse = NULL; ECLicenseClient *lpLicenseClient = NULL; std::string strClientMSIName; std::string strPath; FILE *fd = NULL; int res; unsigned int ulUserID = 0; ECSession *lpecSession = NULL; ECDatabase *lpDatabase = NULL; std::string strCurVersion; std::string strLatestVersion; std::string strQuery; time_t tNow = 0; char *lpszClientUpdatePath = g_lpConfig->GetSetting("client_update_path"); unsigned int ulLogLevel = atoui(g_lpConfig->GetSetting("client_update_log_level")); if (!parseBool(g_lpConfig->GetSetting("client_update_enabled"))) { // do not set on high loglevel, since by default the client updater is installed, and this will be quite often in your log g_lpLogger->Log(EC_LOGLEVEL_NOTICE, "Client update: trackid: 0x%08X, Config option 'client_update_enabled' has disabled this feature.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_SUPPORT; goto exit; } // setup soap soap_set_imode(soap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING | SOAP_ENC_ZLIB | SOAP_ENC_MTOM); soap_set_omode(soap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING | SOAP_ENC_ZLIB | SOAP_ENC_MTOM | SOAP_IO_CHUNK); if (!lpszClientUpdatePath || lpszClientUpdatePath[0] == 0) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, The configuration field 'client_update_path' is empty.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } er = g_lpSessionManager->CreateSessionInternal(&lpecSession); if(er != erSuccess) goto exit; // Lock the session lpecSession->Lock(); er = lpecSession->GetDatabase(&lpDatabase); if (er != erSuccess) goto exit; //@TODO change loglevel? g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, computername: %s, username: %s, clientversion: %s, windowsversion: %s, iplist: %s, soapip: %s", sClientUpdateInfo.ulTrackId, (sClientUpdateInfo.szComputerName) ? sClientUpdateInfo.szComputerName : "-", (sClientUpdateInfo.szUsername) ? sClientUpdateInfo.szUsername : "******", (sClientUpdateInfo.szClientVersion) ? sClientUpdateInfo.szClientVersion : "-", (sClientUpdateInfo.szWindowsVersion) ? sClientUpdateInfo.szWindowsVersion : "-", (sClientUpdateInfo.szClientIPList) ? sClientUpdateInfo.szClientIPList : "-", PrettyIP(soap->ip).c_str() ); if (!sClientUpdateInfo.szComputerName) sClientUpdateInfo.szComputerName = ""; //Client has no name? if(!sClientUpdateInfo.szUsername) { er = ZARAFA_E_NO_ACCESS; g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Client did not send a username", sClientUpdateInfo.ulTrackId); } // validate user name er = lpecSession->GetUserManagement()->SearchObjectAndSync(sClientUpdateInfo.szUsername, 0x01/*EMS_AB_ADDRESS_LOOKUP*/, &ulUserID); if (er != erSuccess) { er = ZARAFA_E_NO_ACCESS; g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, unknown username '%s'", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername); } if(lpecSession->GetUserManagement()->IsInternalObject(ulUserID)) { er = ZARAFA_E_NO_ACCESS; g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Wrong user data. User name '%s' is a reserved user", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername); goto exit; } // Check if the user connect to the right server, else redirect if (lpecSession->GetSessionManager()->IsDistributedSupported() ) { objectdetails_t sUserDetails; er = lpecSession->GetUserManagement()->GetObjectDetails(ulUserID, &sUserDetails); if (er != erSuccess) goto exit; /* Check if this is the correct server */ string strServerName = sUserDetails.GetPropString(OB_PROP_S_SERVERNAME); if (strServerName.empty()) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, User '%s' has no default server", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername); er = ZARAFA_E_NO_ACCESS; goto exit; } if (stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) { string strServerPath; er = GetBestServerPath(soap, lpecSession, strServerName, &strServerPath); if (er != erSuccess) goto exit; lpsResponse->lpszServerPath = s_strcpy(soap, strServerPath.c_str());// Server Path must always utf8 (also in 6.40.x) g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, User '%s' is redirected to '%s'", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername, lpsResponse->lpszServerPath); g_lpStatsCollector->Increment(SCN_REDIRECT_COUNT, 1); er = ZARAFA_E_UNABLE_TO_COMPLETE; goto exit; } } lpLicenseClient = new ECLicenseClient(g_lpConfig->GetSetting("license_socket"), atoui(g_lpConfig->GetSetting("license_timeout"))); er = lpLicenseClient->Auth(sClientUpdateInfo.sLicenseReq.__ptr, sClientUpdateInfo.sLicenseReq.__size, &lpLicenseResponse, &ulLicenseResponse); if (er != erSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Invalid license request, error: 0x%08X.", sClientUpdateInfo.ulTrackId, er); goto exit; } if (sClientUpdateInfo.szClientVersion == NULL || sClientUpdateInfo.szClientVersion[0] == '\0') { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, The client did not sent the current version number.", sClientUpdateInfo.ulTrackId); } else if (!GetVersionFromString(sClientUpdateInfo.szClientVersion, &sCurrentVersion)) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Failed in getting version from input data.", sClientUpdateInfo.ulTrackId); goto exit; //@fixme can we give the latest? } if (!GetLatestVersionAtServer(lpszClientUpdatePath, sClientUpdateInfo.ulTrackId, &sLatestVersion)) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, No updates found on server.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } res = CompareVersions(sCurrentVersion, sLatestVersion); if (res == 0) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, Client already has the latest version.", sClientUpdateInfo.ulTrackId); goto ok; } else if (res > 0) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, Client has newer version than server.", sClientUpdateInfo.ulTrackId); goto ok; } if (!GetClientMSINameFromVersion(sLatestVersion, &strClientMSIName)) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, No suitable version available.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } if (ConvertAndValidatePath(lpszClientUpdatePath, strClientMSIName, &strPath) != true) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Error in path conversion and validation.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } fd = fopen(strPath.c_str(), "rb"); if (!fd) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Path not found %s.", sClientUpdateInfo.ulTrackId, strPath.c_str()); er = ZARAFA_E_NO_ACCESS; goto exit; } // Update auto update client status VersionToString(sCurrentVersion, &strCurVersion); VersionToString(sLatestVersion, &strLatestVersion); tNow = time(NULL); // Get current time strQuery = "REPLACE INTO clientupdatestatus(userid, trackid, updatetime, currentversion, latestversion, computername, status) VALUES ("+ stringify(ulUserID)+", "+stringify(sClientUpdateInfo.ulTrackId)+", FROM_UNIXTIME("+ stringify(tNow) + "), \"" + strCurVersion + "\", \"" + strLatestVersion + "\", \"" + lpDatabase->Escape(sClientUpdateInfo.szComputerName).c_str()+"\", "+ stringify(UPDATE_STATUS_PENDING) + ")"; // ignore error in database tracking, SQL error logged in server, still send new client lpDatabase->DoUpdate(strQuery); soap->fmimereadopen = &mime_file_read_open; soap->fmimeread = &mime_file_read; soap->fmimereadclose = &mime_file_read_close; // Setup the MTOM Attachments lpsResponse->sStreamData.xop__Include.__ptr = (unsigned char*)fd; lpsResponse->sStreamData.xop__Include.__size = 0; lpsResponse->sStreamData.xop__Include.type = s_strcpy(soap, "application/binary"); lpsResponse->sStreamData.xop__Include.id = s_strcpy(soap, "zarafaclient"); g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Sending new installer %s", sClientUpdateInfo.ulTrackId, strClientMSIName.c_str()); ok: // Client is already up to date lpsResponse->sLicenseResponse.__size = ulLicenseResponse; lpsResponse->sLicenseResponse.__ptr = (unsigned char *)s_memcpy(soap, (const char *)lpLicenseResponse, ulLicenseResponse); lpsResponse->ulLogLevel = ulLogLevel; // 0 = none, 1 = on errors, 2 = always exit: if(lpecSession) { lpecSession->Unlock(); g_lpSessionManager->RemoveSessionInternal(lpecSession); } lpsResponse->er = er; if (lpLicenseResponse) delete [] lpLicenseResponse; if (lpLicenseClient) delete lpLicenseClient; if (er && fd) fclose(fd); return SOAP_OK; }