예제 #1
0
파일: NSRootDir.cpp 프로젝트: fsfod/ns2_IO
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);
}
예제 #2
0
파일: NSRootDir.cpp 프로젝트: fsfod/ns2_IO
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));
}
예제 #3
0
파일: NSRootDir.cpp 프로젝트: fsfod/ns2_IO
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;
}
예제 #4
0
파일: NSRootDir.cpp 프로젝트: fsfod/ns2_IO
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;
}
예제 #5
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, &currentVersion))
		{
			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;
}
예제 #6
0
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;
}