564 lines
17 KiB
C++
564 lines
17 KiB
C++
|
|
// Copyright (c) 2013, IOnU Security, Inc.
|
||
|
|
// Copyright (c) 2016, Sequence Logic, Inc. All rights reserved.
|
||
|
|
|
||
|
|
#include "vanaccess.h"
|
||
|
|
|
||
|
|
#include "eyeinterface.h"
|
||
|
|
|
||
|
|
#include "../cppcoreobjects//cloudguardurn.h"
|
||
|
|
#include "../component/slfile.h"
|
||
|
|
#include "../internal.h"
|
||
|
|
#include "jsonobject.h"
|
||
|
|
|
||
|
|
#include <algorithm>
|
||
|
|
#include <sys/types.h>
|
||
|
|
#include <sys/stat.h>
|
||
|
|
#include <sstream>
|
||
|
|
#include <cstdio>
|
||
|
|
#include <set>
|
||
|
|
#ifdef WIN32
|
||
|
|
#include <io.h>
|
||
|
|
#include <direct.h>
|
||
|
|
#else
|
||
|
|
#include <dirent.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
using namespace sequencelogic;
|
||
|
|
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
void listFilesDeep(const File &rootDir, std::vector<File> &files);
|
||
|
|
void removeFiles(const std::string &dir);
|
||
|
|
void removeDirsDeep(const File &rootDir);
|
||
|
|
};
|
||
|
|
|
||
|
|
namespace sequencelogic
|
||
|
|
{
|
||
|
|
class VanAccessData
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
VanAccessData() {}
|
||
|
|
~VanAccessData() {}
|
||
|
|
|
||
|
|
std::string _VANRootDir;
|
||
|
|
std::string _VANIntDir;
|
||
|
|
std::string _curVAN;
|
||
|
|
std::string _devURN;
|
||
|
|
|
||
|
|
// Check VAN id...
|
||
|
|
bool isValidVANid(const std::string &van) const
|
||
|
|
{
|
||
|
|
CloudGuardURN vanURN(van);
|
||
|
|
return (vanURN.getType() != CloudGuardURN::URN_TYPE::INVALID);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if a directory exists. If not, create it. If we can't, return false.
|
||
|
|
bool checkAndCreateDir(std::string dir) const
|
||
|
|
{
|
||
|
|
if (dir == "")
|
||
|
|
return false;
|
||
|
|
|
||
|
|
if (*dir.rbegin() != File::DIR_SEP)
|
||
|
|
dir += File::DIR_SEP;
|
||
|
|
|
||
|
|
bool bRetVal = true;
|
||
|
|
// Create the full path.
|
||
|
|
File tmpFile (dir);
|
||
|
|
|
||
|
|
bRetVal = tmpFile.mkdirs();
|
||
|
|
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
const char VanAccess::VAN_CONFIG_JSON[] = "van-config.json"; // VAN config filename
|
||
|
|
const char VanAccess::LAST_ACTIVE_USER[] = "last_active_user.json"; // The last "active" user filename. This is stored at the internal directory root.
|
||
|
|
|
||
|
|
VanAccess::VanAccess() : _pData(new VanAccessData())
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
VanAccess::~VanAccess()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set a VAN's data root directory.
|
||
|
|
*
|
||
|
|
* @param rootDir The root directory to set.
|
||
|
|
*/
|
||
|
|
bool VanAccess::setVANDataRootDirectory(const std::string &rootDir)
|
||
|
|
{
|
||
|
|
bool bRetVal = false;
|
||
|
|
|
||
|
|
// Just store the VAN id string in our cache. Use the CloudGuardURN class to verify it!
|
||
|
|
if (_pData->checkAndCreateDir(rootDir))
|
||
|
|
{
|
||
|
|
// Check that the directory exists. Now sure if this should actually be an error condition,
|
||
|
|
// initially provisioned devices
|
||
|
|
_pData->_VANRootDir = rootDir;
|
||
|
|
if (*_pData->_VANRootDir.rbegin() != File::DIR_SEP)
|
||
|
|
_pData->_VANRootDir += File::DIR_SEP;
|
||
|
|
bRetVal = true;
|
||
|
|
}
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get a VAN's data root directory.
|
||
|
|
*
|
||
|
|
* @returns The data root, or an empty string if there is no VAN found. If the root directory is indeed the root
|
||
|
|
* of a filesystem, the client should set this as "/" in the function above.
|
||
|
|
*/
|
||
|
|
std::string VanAccess::getVANDataRootDirectory() const
|
||
|
|
{
|
||
|
|
return _pData->_VANRootDir;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set a VAN's internal directory. This is for private storage for this class.
|
||
|
|
*
|
||
|
|
* @param rootDir The internal directory to set.
|
||
|
|
*/
|
||
|
|
bool VanAccess::setVANInternalDirectory(const std::string &intDir)
|
||
|
|
{
|
||
|
|
bool bRetVal = false;
|
||
|
|
|
||
|
|
// Just store the VAN id string in our cache. Use the CloudGuardURN class to verify it!
|
||
|
|
if (_pData->checkAndCreateDir(intDir))
|
||
|
|
{
|
||
|
|
// Check that the directory exists. Now sure if this should actually be an error condition,
|
||
|
|
// initially provisioned devices
|
||
|
|
_pData->_VANIntDir = intDir;
|
||
|
|
if (*_pData->_VANIntDir.rbegin() != File::DIR_SEP)
|
||
|
|
_pData->_VANIntDir += File::DIR_SEP;
|
||
|
|
bRetVal = true;
|
||
|
|
|
||
|
|
// See if there is a 'last active user' file...
|
||
|
|
std::string lastActiveUser = _pData->_VANIntDir;
|
||
|
|
lastActiveUser += LAST_ACTIVE_USER;
|
||
|
|
JSONObject lastUser;
|
||
|
|
if (lastUser.LoadFromFile(lastActiveUser) && (lastUser.getJSONString("lastActiveID") != ""))
|
||
|
|
{
|
||
|
|
_pData->_devURN = lastUser.getJSONString("lastActiveID");
|
||
|
|
setCurrentVan(lastUser.getJSONObject("lastActiveVAN").toString());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get a VAN's internal directory.
|
||
|
|
*
|
||
|
|
* @returns The internal directory, or an empty string if there is no VAN found. If the root directory is indeed the root
|
||
|
|
* of a filesystem, the client should set this as "/" in the function above.
|
||
|
|
*/
|
||
|
|
std::string VanAccess::getVANInternalDirectory() const
|
||
|
|
{
|
||
|
|
return _pData->_VANIntDir;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set the current VAN being used by the client.
|
||
|
|
*
|
||
|
|
* @param vanObj The current VAN, JSON, containing the VAN ID and alias: "{ "_id":"urn:sl:000000:::", "alias":"TEST SERVER" }"
|
||
|
|
* @returns True, if VAN ID is valid, and set.
|
||
|
|
*/
|
||
|
|
bool VanAccess::setCurrentVan(const std::string &vanObj)
|
||
|
|
{
|
||
|
|
bool bRetVal = true;
|
||
|
|
std::lock_guard<std::mutex> lock(_protectData);
|
||
|
|
JSONObject van(vanObj);
|
||
|
|
// Use the internal directory area. If it's not set, fail.
|
||
|
|
if ((_pData->_VANIntDir != "") &&
|
||
|
|
!van.empty() && _pData->isValidVANid(van.getJSONString("_id")))
|
||
|
|
{
|
||
|
|
ionu_policy_uninstall();
|
||
|
|
|
||
|
|
CloudGuardURN vanURN(van.getJSONString("_id"));
|
||
|
|
std::stringstream tmpFilename;
|
||
|
|
tmpFilename << _pData->_VANIntDir <<
|
||
|
|
van.getJSONString("alias", "xxx") << File::DIR_SEP <<
|
||
|
|
vanURN.getVANID() << File::DIR_SEP <<
|
||
|
|
VAN_CONFIG_JSON;
|
||
|
|
File vanCfgFile (tmpFilename.str());
|
||
|
|
if (!vanCfgFile.exists())
|
||
|
|
installVAN(vanObj);
|
||
|
|
_pData->_curVAN = vanObj;
|
||
|
|
|
||
|
|
ionu_policy_install(_pData->_curVAN.c_str());
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_pData->_curVAN = "";
|
||
|
|
bRetVal = false;
|
||
|
|
}
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the current VAN being used by the client.
|
||
|
|
*
|
||
|
|
* @returns The current VAN in use, empty string if no current VAN is in use.
|
||
|
|
*/
|
||
|
|
std::string VanAccess::getCurrentVan() const
|
||
|
|
{
|
||
|
|
std::lock_guard<std::mutex> lock(_protectData);
|
||
|
|
return _pData->_curVAN;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all provisioned VANs on the client. Searches the data root.
|
||
|
|
*
|
||
|
|
* @returns A shared pointer to a vector of strings of the provisioned VAN ids.
|
||
|
|
*/
|
||
|
|
std::string VanAccess::getProvisionedVANs() const
|
||
|
|
{
|
||
|
|
JSONArray retVal;
|
||
|
|
|
||
|
|
// See if we have a root directory!
|
||
|
|
if (_pData->_VANIntDir != "")
|
||
|
|
{
|
||
|
|
// Look for all the VAN directories. They better be proper VAN id's!
|
||
|
|
std::string tmpPath = _pData->_VANIntDir;
|
||
|
|
if (tmpPath[tmpPath.length()-1] != File::DIR_SEP)
|
||
|
|
tmpPath += File::DIR_SEP;
|
||
|
|
|
||
|
|
File tmpDirFile (tmpPath);
|
||
|
|
std::vector<File> aliasList;
|
||
|
|
tmpDirFile.listFiles(aliasList);
|
||
|
|
|
||
|
|
// Now, check all the returned directories for proper VAN id...
|
||
|
|
std::vector<File> vanList;
|
||
|
|
for (unsigned int i = 0; i < aliasList.size(); ++i)
|
||
|
|
{
|
||
|
|
if (!aliasList[i].isDirectory())
|
||
|
|
continue;
|
||
|
|
|
||
|
|
// Now, get all the VANs in the list of returned aliases...
|
||
|
|
vanList.clear();
|
||
|
|
aliasList[i].listFiles(vanList);
|
||
|
|
for (unsigned int j = 0; j < vanList.size(); ++j)
|
||
|
|
{
|
||
|
|
std::string tmpVANID = vanList[j].getDirectory();
|
||
|
|
if (tmpVANID[tmpVANID.size()-1] == File::DIR_SEP) {
|
||
|
|
// Workaround for Android's lack of 'pop_back'...
|
||
|
|
//tmpVANID.pop_back();
|
||
|
|
std::string::reverse_iterator rIter = tmpVANID.rbegin();
|
||
|
|
++rIter;
|
||
|
|
tmpVANID.erase(rIter.base());
|
||
|
|
}
|
||
|
|
tmpVANID.erase(0, tmpVANID.rfind(File::DIR_SEP)+1);
|
||
|
|
|
||
|
|
sequencelogic::CloudGuardURN tmpURN(tmpVANID, "");
|
||
|
|
if (tmpURN.getType() != sequencelogic::CloudGuardURN::URN_TYPE::INVALID)
|
||
|
|
{
|
||
|
|
File vanCfgFile(vanList[j], VAN_CONFIG_JSON);
|
||
|
|
if (vanCfgFile.exists())
|
||
|
|
{
|
||
|
|
JSONObject tmpVAN;
|
||
|
|
if (tmpVAN.LoadFromFile(vanCfgFile.getAbsolutePath()))
|
||
|
|
retVal.addElement(tmpVAN);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return retVal.toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* For a specific VAN, get a JSON array of provisioned users, on this device.
|
||
|
|
*
|
||
|
|
* @param vanObj VAN object, as JSON
|
||
|
|
* @returns A JSON array with all provisioned users
|
||
|
|
*/
|
||
|
|
std::string VanAccess::getProvisionedUsers(const std::string &vanObj) const
|
||
|
|
{
|
||
|
|
JSONArray retVal;
|
||
|
|
if (vanObj != "")
|
||
|
|
{
|
||
|
|
JSONObject van(vanObj);
|
||
|
|
CloudGuardURN vanURN(van.getJSONString("_id"));
|
||
|
|
std::stringstream tmpDirName;
|
||
|
|
|
||
|
|
std::string dir = getVANInternalDirectory(); // This was getVANDataRootDirectory() which is wrong!
|
||
|
|
|
||
|
|
tmpDirName << dir << File::DIR_SEP <<
|
||
|
|
van.getJSONString("alias") << File::DIR_SEP <<
|
||
|
|
vanURN.getVANID() << File::DIR_SEP;
|
||
|
|
File vanFile(tmpDirName.str());
|
||
|
|
if (vanFile.exists())
|
||
|
|
{
|
||
|
|
std::vector<File> userList;
|
||
|
|
vanFile.listFiles(userList);
|
||
|
|
for (unsigned int i = 0; i < userList.size(); ++i)
|
||
|
|
{
|
||
|
|
if (userList[i].isDirectory())
|
||
|
|
{
|
||
|
|
File userFile(userList[i].getAbsolutePath(), "sl-keyring.iks.public");
|
||
|
|
JSONObject userObj;
|
||
|
|
if (userFile.exists() && userObj.LoadFromFile(userFile.getAbsolutePath()))
|
||
|
|
retVal.addElement(userObj);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return retVal.toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* For a specific VAN, see if this user is already provisioned.
|
||
|
|
*
|
||
|
|
* @param vanObj The VAN to check, as JSON
|
||
|
|
* @param user User to look for
|
||
|
|
* @return "" if user is not provisioned, JSON with user props if provisioned.
|
||
|
|
*/
|
||
|
|
std::string VanAccess::isProvisionedUser(const std::string &vanObj, const std::string &user) const
|
||
|
|
{
|
||
|
|
std::string retVal;
|
||
|
|
JSONArray provisionedUsers (getProvisionedUsers(vanObj));
|
||
|
|
for (int i = 0; (retVal == "") && (i < provisionedUsers.getnumelements()); ++i)
|
||
|
|
{
|
||
|
|
const JSONObject &userObj = reinterpret_cast<const JSONObject &>(provisionedUsers[i]);
|
||
|
|
if (userObj.getJSONString("user") == user
|
||
|
|
|| userObj.getJSONObject("email").getJSONString("primary") == user
|
||
|
|
){
|
||
|
|
retVal = userObj.toString();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return retVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Wipe out the specified office, in the current van.
|
||
|
|
*/
|
||
|
|
void VanAccess::wipeOffice(const std::string &devUrn)
|
||
|
|
{
|
||
|
|
JSONObject curVanObj(getCurrentVan());
|
||
|
|
if (!curVanObj.empty())
|
||
|
|
{
|
||
|
|
CloudGuardURN vanURN(curVanObj.getJSONString("_id"));
|
||
|
|
CloudGuardURN devURN(devUrn);
|
||
|
|
std::stringstream tmpDir;
|
||
|
|
tmpDir << getVANInternalDirectory() << curVanObj.getJSONString("alias") <<
|
||
|
|
File::DIR_SEP << vanURN.getVANID() <<
|
||
|
|
File::DIR_SEP << devURN.getPMOID() << File::DIR_SEP;
|
||
|
|
|
||
|
|
removeFiles(tmpDir.str());
|
||
|
|
|
||
|
|
tmpDir.str("");
|
||
|
|
tmpDir << getVANDataRootDirectory() << curVanObj.getJSONString("alias") <<
|
||
|
|
File::DIR_SEP << vanURN.getVANID() <<
|
||
|
|
File::DIR_SEP << devURN.getPMOID() << File::DIR_SEP;
|
||
|
|
|
||
|
|
removeFiles(tmpDir.str());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Wipe out the current VAN (wipes ALL offices)
|
||
|
|
*/
|
||
|
|
void VanAccess::wipeCurrentVAN()
|
||
|
|
{
|
||
|
|
JSONObject curVanObj(getCurrentVan());
|
||
|
|
if (!curVanObj.empty())
|
||
|
|
{
|
||
|
|
JSONArray provisionedUsers (getProvisionedUsers(curVanObj.toString()));
|
||
|
|
for (int i = 0; i < provisionedUsers.getnumelements(); ++i)
|
||
|
|
{
|
||
|
|
const JSONObject &user = reinterpret_cast<const JSONObject &>(provisionedUsers[i]);
|
||
|
|
wipeOffice(user.getJSONString("urn"));
|
||
|
|
}
|
||
|
|
std::stringstream tmpDir;
|
||
|
|
tmpDir << getVANInternalDirectory() << curVanObj.getJSONString("alias") <<
|
||
|
|
File::DIR_SEP << CloudGuardURN(curVanObj.getJSONString("_id")).getVANID() << File::DIR_SEP;
|
||
|
|
removeFiles(tmpDir.str());
|
||
|
|
tmpDir.str("");
|
||
|
|
tmpDir << getVANDataRootDirectory() << curVanObj.getJSONString("alias") <<
|
||
|
|
File::DIR_SEP << CloudGuardURN(curVanObj.getJSONString("_id")).getVANID() << File::DIR_SEP;
|
||
|
|
removeFiles(tmpDir.str());
|
||
|
|
}
|
||
|
|
std::string lastActiveUser = _pData->_VANIntDir;
|
||
|
|
lastActiveUser += LAST_ACTIVE_USER;
|
||
|
|
std::remove(lastActiveUser.c_str());
|
||
|
|
setCurrentVan("");
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Wipe out ALL VANs!
|
||
|
|
*/
|
||
|
|
void VanAccess::wipe()
|
||
|
|
{
|
||
|
|
std::set<std::string> serverPaths;
|
||
|
|
JSONArray vans (getProvisionedVANs());
|
||
|
|
for (int i = 0; i < vans.getnumelements(); ++i)
|
||
|
|
{
|
||
|
|
const JSONObject &van = reinterpret_cast<const JSONObject &>(vans[i]);
|
||
|
|
setCurrentVan(van.toString());
|
||
|
|
wipeCurrentVAN();
|
||
|
|
std::stringstream tmpDir;
|
||
|
|
tmpDir << getVANInternalDirectory() << van.getJSONString("alias");
|
||
|
|
serverPaths.insert(tmpDir.str());
|
||
|
|
tmpDir.str("");
|
||
|
|
tmpDir << getVANDataRootDirectory() << van.getJSONString("alias");
|
||
|
|
serverPaths.insert(tmpDir.str());
|
||
|
|
}
|
||
|
|
|
||
|
|
for (std::set<std::string>::iterator iter = serverPaths.begin(); iter != serverPaths.end(); ++iter)
|
||
|
|
{
|
||
|
|
|
||
|
|
#ifdef WIN32
|
||
|
|
::_rmdir(iter->c_str());
|
||
|
|
#else
|
||
|
|
::rmdir(iter->c_str());
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Install a VAN.
|
||
|
|
*
|
||
|
|
* @param vanObj The current VAN, JSON, containing the VAN ID and alias: "{ "_id":"urn:sl:000000:::", "alias":"TEST SERVER" }"
|
||
|
|
* @returns True, if VAN ID is valid, and installed.
|
||
|
|
*/
|
||
|
|
bool VanAccess::installVAN (const std::string &vanObj)
|
||
|
|
{
|
||
|
|
bool bRetVal = false;
|
||
|
|
JSONObject van(vanObj);
|
||
|
|
// Use the internal directory area. If it's not set, fail.
|
||
|
|
if ((_pData->_VANIntDir != "") &&
|
||
|
|
!van.empty() && _pData->isValidVANid(van.getJSONString("_id")))
|
||
|
|
{
|
||
|
|
CloudGuardURN vanURN(van.getJSONString("_id"));
|
||
|
|
std::stringstream tmpFilename;
|
||
|
|
|
||
|
|
tmpFilename << _pData->_VANIntDir <<
|
||
|
|
van.getJSONString("alias", "xxx") << File::DIR_SEP <<
|
||
|
|
vanURN.getVANID() << File::DIR_SEP <<
|
||
|
|
VAN_CONFIG_JSON;
|
||
|
|
File vanCfgFile (tmpFilename.str());
|
||
|
|
|
||
|
|
vanCfgFile.getParentFile().mkdirs();
|
||
|
|
|
||
|
|
bRetVal = van.SaveToFile(vanCfgFile.getAbsolutePath());
|
||
|
|
}
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set the current device ID. This is the ID of the (soon to be) logged in user device.
|
||
|
|
*
|
||
|
|
* @param devURN The current device URN.
|
||
|
|
* @returns true if the URN is valid, and set.
|
||
|
|
*/
|
||
|
|
bool VanAccess::setDeviceURN (const std::string &devURN)
|
||
|
|
{
|
||
|
|
bool bRetVal = false;
|
||
|
|
|
||
|
|
if (_pData->_curVAN != "")
|
||
|
|
{
|
||
|
|
CloudGuardURN tmpURN(devURN);
|
||
|
|
if (tmpURN.getType() != CloudGuardURN::URN_TYPE::INVALID)
|
||
|
|
{
|
||
|
|
bRetVal = true;
|
||
|
|
std::lock_guard<std::mutex> lock(_protectData);
|
||
|
|
_pData->_devURN = devURN;
|
||
|
|
JSONObject lastActiveJSON;
|
||
|
|
lastActiveJSON.setJSONValue("lastActiveID", devURN.c_str());
|
||
|
|
lastActiveJSON.setJSONValue("lastActiveVAN", JSONObject(_pData->_curVAN));
|
||
|
|
std::string fileName = _pData->_VANIntDir;
|
||
|
|
fileName += LAST_ACTIVE_USER;
|
||
|
|
lastActiveJSON.SaveToFile(fileName);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::lock_guard<std::mutex> lock(_protectData);
|
||
|
|
_pData->_devURN = "";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the current device URN.
|
||
|
|
*
|
||
|
|
* @return The currently set device URN.
|
||
|
|
*/
|
||
|
|
std::string VanAccess::getDeviceURN() const
|
||
|
|
{
|
||
|
|
return _pData->_devURN;
|
||
|
|
}
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
void listFilesDeep(const File &rootDir, std::vector<File> &files)
|
||
|
|
{
|
||
|
|
std::vector<File> tmpList;
|
||
|
|
rootDir.listFiles(tmpList);
|
||
|
|
for (unsigned int i = 0; i < tmpList.size(); ++i)
|
||
|
|
{
|
||
|
|
if (tmpList[i].isFile())
|
||
|
|
files.push_back(tmpList[i]);
|
||
|
|
else if (tmpList[i].isDirectory())
|
||
|
|
listFilesDeep(tmpList[i], files);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void removeFiles(const std::string &dir)
|
||
|
|
{
|
||
|
|
if ((dir != "") &&
|
||
|
|
#ifdef WIN32
|
||
|
|
(dir.length() > 3) // Don't remove starting from "c:\"
|
||
|
|
#else
|
||
|
|
(dir.length() > 1) // Don't remove starting from "/"
|
||
|
|
#endif
|
||
|
|
)
|
||
|
|
{
|
||
|
|
std::vector<File> files;
|
||
|
|
listFilesDeep(dir, files);
|
||
|
|
for (unsigned int i = 0; i < files.size(); ++i)
|
||
|
|
files[i].deleteFile();
|
||
|
|
removeDirsDeep(dir);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void removeDirsDeep(const File &rootDir)
|
||
|
|
{
|
||
|
|
std::vector<File> tmpList;
|
||
|
|
rootDir.listFiles(tmpList);
|
||
|
|
for (unsigned int i = 0; i < tmpList.size(); ++i)
|
||
|
|
{
|
||
|
|
if (tmpList[i].isDirectory())
|
||
|
|
{
|
||
|
|
removeDirsDeep(tmpList[i]);
|
||
|
|
std::string dirName = tmpList[i].getAbsolutePath();
|
||
|
|
if (*dirName.rbegin() == File::DIR_SEP)
|
||
|
|
{
|
||
|
|
// Workaround for Android's lack of pop_back
|
||
|
|
//dirName.pop_back();
|
||
|
|
std::string::reverse_iterator rIter = dirName.rbegin();
|
||
|
|
++rIter;
|
||
|
|
dirName.erase(rIter.base());
|
||
|
|
}
|
||
|
|
#ifdef WIN32
|
||
|
|
::_rmdir(dirName.c_str());
|
||
|
|
#else
|
||
|
|
::rmdir(dirName.c_str());
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#ifdef WIN32
|
||
|
|
::_rmdir(rootDir.getAbsolutePath().c_str());
|
||
|
|
#else
|
||
|
|
::rmdir(rootDir.getAbsolutePath().c_str());
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|