1. #include <iostream>
  2. #include <fstream>
  3. #include <boost/filesystem.hpp>
  4. #include <string>
  5. #include <vector>
  6. #include "fsysclass.h"
  7. #include <fstream>
  8. #include <windows.h>
  9. #include <exception>
  10.  
  11. using namespace std;
  12.  
  13. /**Debug definition for debug mode*/
  14. #ifdef DEBUG
  15. #define DEBUG
  16. #endif
  17.  
  18.  
  19.  
  20. //==================================================================
  21.  
  22.  
  23. //include common.h if debug mode is on, and common.h is not included
  24. #ifdef DEBUG
  25. #ifndef COMMON_H_INCLUDED
  26. #include "common.h"
  27. #endif
  28. #endif
  29.  
  30.  
  31. //============================================
  32. //prototypes
  33. bool is_file_supliment(const string&);
  34. bool is_folder_supliment(const string&);
  35. vector<string> sub_stuff_suppliment(const string&);
  36. int copy(const string&, const string&);
  37. int delete_path(const string&, const bool&);
  38. int delete_file_sup(const string&, const bool&);
  39. int delete_folder_sup(const string&, const bool&);
  40. int copy_file_sup(const string&, const string&, const bool&);
  41. int copy_folder_sup(const string&, const string&, const bool&);
  42. string extract_target_folders(const string&, const string&);
  43. string parent(const string&);
  44. void rstring(string&);
  45. bool is_valid_filename(const string&);
  46. bool is_valid_foldername_char(const char&);
  47. void get_all_directories(const string&);
  48. string current_directory();
  49. string filename_sup(const string&);
  50. int create_dir(const string&, const string&);
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57. /* This function is littered with safety precautions so that we
  58.  don't fail.  Useing the system command line is an option, and only available
  59.  as a last resort, and only if use_sys == true*/
  60. int delete_file_sup(const string& s, const bool& use_sys)
  61. {
  62.     boost::filesystem::path p = s;
  63.     bool sys = use_sys;
  64.     string command = ("DEL /F /Q \"" + s + "\" >nul 2>nul");
  65.    
  66.     //if the path is a file
  67.     if(boost::filesystem::is_regular_file(p) == true)
  68.     {
  69.         try
  70.         {
  71.             remove(s.c_str());
  72.         }
  73.         catch(const exception& e)
  74.         {
  75.             cout<< e.what()<< endl;
  76.             if((boost::filesystem::is_regular_file(p) == true) && (sys == true))
  77.             {
  78.                 system(command.c_str());
  79.                 if(boost::filesystem::is_regular_file(p) == true)
  80.                 {
  81.                     return FSYS_ERROR;
  82.                 }
  83.             }
  84.             if(sys == false)
  85.             {
  86.                 return FSYS_ERROR;
  87.             }
  88.         }
  89.     }
  90.    
  91.     //just being fool-proof here...
  92.     if(boost::filesystem::is_regular_file(p) == false)
  93.     {
  94.         return 0;
  95.     }
  96.     return FSYS_FAILURE;
  97. }
  98.  
  99. /* This function is littered with safety precautions so that we
  100.  don't fail.  Useing the system command line is an option, and only available
  101.  as a last resort, and only if use_sys == true
  102.  
  103.  Deletes the files, then the folders.  It does not procede if the path passed
  104.  is a file, or a folder-symlink*/
  105. int delete_folder_sup(const string& s, const bool& use_sys)
  106. {
  107.     string command = ("RD /S /Q \"" + s + "\"");
  108.     boost::filesystem::path p = s;
  109.     //using the windows API RemoveDirectory()
  110.     if(is_folder_supliment(s) == true)
  111.     {
  112.         try
  113.         {
  114.             boost::filesystem::remove_all(p);
  115.         }
  116.         catch(const exception& e)
  117.         {
  118.             cout<< e.what()<< endl;
  119.         }
  120.         /* Now, if it does not return an exception, we still want this to execute
  121.          in the event of a failure*/
  122.        
  123.         //try the command line if the user wants to resort to it
  124.         if((use_sys == true) && (is_folder_supliment(s) == true))
  125.         {
  126.             system(command.c_str());
  127.             if(is_folder_supliment(s) == true)
  128.             {
  129.                 return FSYS_FAILURE;
  130.             }
  131.         }
  132.     }
  133.     if(is_folder_supliment(s) == false)
  134.     {
  135.         return 0;
  136.     }
  137.     return FSYS_FAILURE;
  138. }
  139.  
  140. /* forcibly attempts to delete any type of path; be it folder, or file.
  141.  if it can't it will return 1 (FSYS_FAIL).  There are a lot of fail-safes,
  142.  and safety measures.  You can even set use_sys to true and it
  143.  will resort to using a system() command to remove the file/folder*/
  144. int delete_path(const string& s, const bool& use_sys)
  145. {
  146.     bool sys = use_sys;
  147.     int f = 0;
  148.     if((sys != true) && (sys != false))
  149.     {
  150.         sys = false;
  151.     }
  152.    
  153.     //function checks for path validation, so we don;t need to here
  154.     f = delete_folder_sup(s, use_sys);
  155.     if(f == FSYS_ERROR)
  156.     {
  157.         return FSYS_ERROR;
  158.     }
  159.     if(f == FSYS_FAILURE)
  160.     {
  161.         return FSYS_FAILURE;
  162.     }
  163.    
  164.     //function checks for path validation, so we don't need to here
  165.     f = delete_file_sup(s, use_sys);
  166.     if(f == FSYS_ERROR)
  167.     {
  168.         return FSYS_ERROR;
  169.     }
  170.     if(f == FSYS_FAILURE)
  171.     {
  172.         return FSYS_FAILURE;
  173.     }
  174.    
  175.     return 0;
  176. }
  177.  
  178. int copy_file_sup(const string& sfrom, const string& sto, const bool& use_sys)
  179. {
  180.  
  181.     //if the target is not a folder, then we can't copy anything!
  182.     if((is_file_supliment(sfrom) == false) || (is_folder_supliment(sto) == false))
  183.     {
  184.         return 0;
  185.     }
  186.     boost::filesystem::path from = sfrom, to = sto;
  187.     string newpath = (sto + "\\" + from.filename().string());
  188.     to = newpath;
  189.     if(is_file_supliment(newpath) == true)
  190.     {
  191.         if(delete_path(newpath, use_sys) == 1)
  192.         {
  193.             return FSYS_ERROR;
  194.         }
  195.     }
  196.     if((is_file_supliment(newpath) == false) && (boost::filesystem::is_regular_file(from) == true))
  197.     {
  198.         try
  199.         {
  200.             boost::filesystem::copy_file(from, to);
  201.         }
  202.         catch(const exception& e)
  203.         {
  204.             cout<< e.what()<< endl;
  205.             if((boost::filesystem::is_regular_file(to) == false) && (boost::filesystem::is_regular_file(from) == true))
  206.             {
  207.                 try
  208.                 {
  209.                     boost::filesystem::copy_file(from, to);
  210.                 }
  211.                 catch(...)
  212.                 {
  213.                     return FSYS_ERROR;
  214.                 }
  215.             }
  216.         }
  217.     }
  218.    
  219.     //make sure the copy succeeded before returning a success value
  220.     if(boost::filesystem::is_regular_file(to) == true)
  221.     {
  222.         return 0;
  223.     }
  224.     return FSYS_FAILURE;
  225. }
  226.  
  227. /* This function extract sub directories from a given parent:
  228.  Example:
  229.  
  230.   from = C:\users\username\desktop
  231.   to = C:\users\username\desktop\C++ projects\thisproject
  232.  
  233.    Return value:  C++ projects\thisproject
  234.    This is so that when copying folders, we can be assured that the
  235.  folder tree is preserved.*/
  236. string extract_target_folders(const string& from, const string& to)
  237. {
  238.     if(from.size() >= to.size())
  239.     {
  240.         return to;
  241.     }
  242.     string temps = "";
  243.     for(unsigned int x = from.size(); x < to.size(); x++)
  244.     {
  245.         temps += to[x];
  246.     }
  247.     return temps;
  248. }
  249.  
  250. //reverses a string  EG "my string" to "gnirts ym"
  251. void rstring(string& s)
  252. {
  253.     if(s.size() == 0)
  254.     {
  255.         return;
  256.     }
  257.     string temps = s;
  258.     s.clear();
  259.     for(unsigned int x = (temps.size() - 1); x >= 0; x--)
  260.     {
  261.         s += temps[x];
  262.         if(x == 0)
  263.         {
  264.             break;
  265.         }
  266.     }
  267. }
  268.  
  269. //returns the parent folder of a path eg: C:\files\myfiles to C:\files
  270. string parent(const string& s)
  271. {
  272.     string path = s, temps = "";
  273.     bool slashmet = false;
  274.     rstring(path);
  275.     for(unsigned int x = 0; x < path.size(); x++)
  276.     {
  277.         if(slashmet == true)
  278.         {
  279.             temps += path[x];
  280.         }
  281.         if((slashmet == false) && (path[x] == '\\'))
  282.         {
  283.             slashmet = true;
  284.         }
  285.     }
  286.     rstring(temps);
  287.     return temps;
  288. }
  289.  
  290. /* Copies a folder.*/
  291. int copy_folder_sup(const string& sfrom, const string& sto, const bool& use_sys)
  292. {
  293.    
  294.     //if the target is not a folder, then we can't copy anything!
  295.     if((is_folder_supliment(sfrom) == false) || (is_folder_supliment(sto) == false))
  296.     {
  297.         return 0;
  298.     }
  299.     boost::filesystem::path from = sfrom, to, temp;
  300.     boost::filesystem::recursive_directory_iterator it(from), end;
  301.    
  302.     //create a string representing our folder, under the to folder
  303.     to = (sto + "\\" + from.filename().string());
  304.    
  305.     /* if the from folder exists, and the to folder does not, then copy from, to to.*/
  306.     if((is_folder_supliment(sto) == true) && (is_folder_supliment(sfrom) == true))
  307.     {
  308.        
  309.         //lets copy the folders first
  310.        
  311.         //create the root folder if it does not exist in the target
  312.         if(boost::filesystem::is_directory(to) == false)
  313.         {
  314.             boost::filesystem::create_directories(to);
  315.             if(boost::filesystem::is_directory(to) == false)
  316.             {
  317.                 return FSYS_ERROR;
  318.             }
  319.         }
  320.        
  321.         //iterate through the folders, and copy them
  322.         while(it != end)
  323.         {
  324.             //if the path is a folder...
  325.             if(boost::filesystem::is_directory(*it) == true)
  326.             {
  327.                 //constructing paths into to
  328.                 temp = (to.string() + extract_target_folders(from.string(), it->path().string()));
  329.                
  330.                 /* Attempt the create the folders in the target, and if it fails,
  331.                  try once more.*/
  332.                 try
  333.                 {
  334.                     boost::filesystem::create_directories(temp);
  335.                 }
  336.                 catch(const exception& e)
  337.                 {
  338.                     cout<< e.what()<< endl;
  339.                     if(boost::filesystem::is_directory(temp) == false)
  340.                     {
  341.                         try
  342.                         {
  343.                             boost::filesystem::create_directories(temp);
  344.                         }
  345.                         catch(...)
  346.                         {
  347.                             return FSYS_ERROR;
  348.                         }
  349.                     }
  350.                 }
  351.             }
  352.             if((boost::filesystem::is_directory(*it) == true) && (boost::filesystem::is_symlink(*it) == true))
  353.             {
  354.                 it.no_push();
  355.             }
  356.            
  357.             try
  358.             {
  359.                 ++it;
  360.             }
  361.             catch(const exception& e)
  362.             {
  363.                 cout<< e.what()<< endl;
  364.                 it.no_push();
  365.                 try
  366.                 {
  367.                     ++it;
  368.                 }
  369.                 catch(...)
  370.                 {
  371.                     return FSYS_ERROR;
  372.                 }
  373.             }
  374.         }
  375.        
  376.         //now, lets copy the files
  377.         it = boost::filesystem::recursive_directory_iterator(from);
  378.         while(it != end)
  379.         {
  380.             /* Is the current path a file?*/
  381.             if(boost::filesystem::is_regular_file(*it) == true)
  382.             {
  383.                
  384.                 /* Construct a string representing the filename, under the folders
  385.                  leading up to the root.*/
  386.                 temp = (to.string() + "\\" + extract_target_folders(from.string(), (parent(it->path().string()) + "\\" + it->path().filename().string())));
  387.                 try
  388.                 {
  389.                     boost::filesystem::copy_file(it->path(), temp);
  390.                 }
  391.                
  392.                 /* Try again, and if it fails then give up.*/
  393.                 catch(const exception& e)
  394.                 {
  395.                     cout<< e.what()<< endl;
  396.                     if(boost::filesystem::is_regular_file(temp) == false)
  397.                     {
  398.                         try
  399.                         {
  400.                             boost::filesystem::copy_file(it->path(), temp);
  401.                         }
  402.                         catch(...)
  403.                         {
  404.                             return FSYS_ERROR;
  405.                         }
  406.                     }
  407.                 }
  408.             }
  409.             if((boost::filesystem::is_directory(*it) == true) && (boost::filesystem::is_symlink(*it) == true))
  410.             {
  411.                 it.no_push();
  412.             }
  413.             try
  414.             {
  415.                 ++it;
  416.             }
  417.             catch(const exception& e)
  418.             {
  419.                 cout<< e.what()<< endl;
  420.                 it.no_push();
  421.                 try
  422.                 {
  423.                     ++it;
  424.                 }
  425.                 catch(...)
  426.                 {
  427.                     return FSYS_ERROR;
  428.                 }
  429.             }
  430.         }
  431.        
  432.         /* This checks to see if the contents of the folder, as well as the folder, was copied
  433.          or not.  If the operation failed, we should not return 0.*/
  434.         if((boost::filesystem::is_directory(to) == true) && (boost::filesystem::is_empty(to) == boost::filesystem::is_empty(from)))
  435.         {
  436.             return 0;
  437.         }
  438.     }
  439.     return FSYS_FAILURE;
  440. }
  441.  
  442. /* Copys path from, to path to.*/
  443. int copy(const string& sfrom, const string& sto, const bool& use_sys)
  444. {
  445.     /* copy_folder_sup and copy_file_sup contain necessary checks, so
  446.      we do not need them here.*/
  447.     int tempi = 0;
  448.     tempi = copy_folder_sup(sfrom, sto, use_sys);
  449.     if(tempi == FSYS_ERROR)
  450.     {
  451.         return FSYS_ERROR;
  452.     }
  453.     if(tempi == FSYS_FAILURE)
  454.     {
  455.         return FSYS_FAILURE;
  456.     }
  457.    
  458.     tempi = copy_file_sup(sfrom, sto, use_sys);
  459.     if(tempi == FSYS_ERROR)
  460.     {
  461.         return FSYS_ERROR;
  462.     }
  463.     if(tempi == FSYS_FAILURE)
  464.     {
  465.         return FSYS_FAILURE;
  466.     }
  467.     return 0;
  468. }
  469.  
  470. /*  
  471.  * ===================================================
  472.  Constructors
  473.  
  474.  */
  475.  
  476. fsys_class::fsys_class()
  477. {
  478.     fsys_class::use_system = false;
  479.     fsys_class::path = current_directory();
  480. }
  481.  
  482. fsys_class::fsys_class(const string& p)
  483. {
  484.     fsys_class::path = p;
  485.     fsys_class::use_system = false;
  486. }
  487.  
  488. fsys_class::~fsys_class()
  489. {
  490. }
  491.  
  492. fsys_class::fsys_class(const char* ch)
  493. {
  494.     string s = string(ch);
  495.     fsys_class::path = s;
  496.     fsys_class::use_system = false;
  497. }
  498.  
  499. /*  
  500.  * ==================================================
  501.  *
  502.  *
  503.  */
  504.  
  505. /* Keeps boost out of the fsys class*/
  506. bool is_file_supliment(const string& path)
  507. {
  508.     boost::filesystem::path p = path;
  509.     return boost::filesystem::is_regular_file(p);
  510. }
  511.  
  512. bool is_folder_supliment(const string& path)
  513. {
  514.     boost::filesystem::path p = path;
  515.     return boost::filesystem::is_directory(p);
  516. }
  517.  
  518. bool fsys_class::is_file()
  519. {
  520.     return is_file_supliment(fsys_class::path);
  521. }
  522.  
  523. bool fsys_class::is_folder()
  524. {
  525.     return is_folder_supliment(fsys_class::path);
  526. }
  527.  
  528. vector<string> sub_stuff_suppliment(const string& parent)
  529. {
  530.     vector<string> directories = vector<string>();
  531.     boost::filesystem::path p = parent;
  532.     if(boost::filesystem::is_directory(p) == false)
  533.     {
  534.         return vector<string>();
  535.     }
  536.     if((boost::filesystem::is_directory(p) == true) && (boost::filesystem::is_symlink(p) == true))
  537.     {
  538.         return vector<string>();
  539.     }
  540.     boost::filesystem::directory_iterator it = boost::filesystem::directory_iterator(p);
  541.     boost::filesystem::directory_iterator end;
  542.     while(it != end)
  543.     {
  544.         directories.push_back(it->path().string());
  545.         try
  546.         {
  547.             ++it;
  548.         }
  549.         catch(const exception& e)
  550.         {
  551.             cout<< e.what()<< endl;
  552.             return directories;
  553.         }
  554.     }
  555.     return directories;
  556. }
  557.  
  558. vector<string> fsys_class::sub_stuff()
  559. {
  560.     if(fsys_class::is_folder() == false)
  561.     {
  562.         return vector<string>();
  563.     }
  564.     return sub_stuff_suppliment(fsys_class::path);
  565. }
  566.  
  567. /* Copies a file or folder to 'to'.
  568.  
  569.  Returns 1 if fails.*/
  570. int fsys_class::copy_to(const string& to)
  571. {
  572.     return copy(fsys_class::path, to, fsys_class::use_system);
  573. }
  574.  
  575. /* Deletes a path that the class is set to.
  576.  
  577.  Returns 1 if fails*/
  578. int fsys_class::del()
  579. {
  580.     return delete_path(fsys_class::path, fsys_class::use_system);
  581. }
  582.  
  583. /* Moves a file or folder.
  584.  
  585.  Returns 1 if fails.*/
  586. int fsys_class::move_to(const string& to)
  587. {
  588.     if(copy(fsys_class::path, to, fsys_class::use_system) == 1)
  589.     {
  590.         return 1;
  591.     }
  592.     if(delete_path(fsys_class::path, fsys_class::use_system) == 1)
  593.     {
  594.         return 1;
  595.     }
  596.     if((is_file_supliment(fsys_class::path) == false) && (is_folder_supliment(fsys_class::path) == false))
  597.     {
  598.         return 0;
  599.     }
  600.     return FSYS_FAILURE;
  601. }
  602.  
  603. bool is_valid_foldername_char(const char& c)
  604. {
  605.     vector<char> invalids = {
  606.         '\\',
  607.         '|',
  608.         '/',
  609.         ':',
  610.         '*',
  611.         '\"',
  612.         '?',
  613.         '<',
  614.         '>'
  615.     };
  616.     for(vector<char>::const_iterator it = invalids.begin(); it != invalids.end(); ++it)
  617.     {
  618.         if(*it == c)
  619.         {
  620.             return false;
  621.         }
  622.     }
  623.     return true;
  624. }
  625.  
  626. /* Checks to see whether a folder path has any bad characters
  627.  in it.
  628.  
  629.  Converts a folder path to the folder's name.*/
  630. bool is_valid_filename(const string& s)
  631. {
  632.     if(s.size() == 0)
  633.     {
  634.         return false;
  635.     }
  636.     boost::filesystem::path p = s;
  637.     string temps = p.filename().string();
  638.     for(string::const_iterator it = temps.begin(); it != temps.end(); ++it)
  639.     {
  640.         if(isalpha(*it) == false)
  641.         {
  642.             if(is_valid_foldername_char(*it) == false)
  643.             {
  644.                 return false;
  645.             }
  646.         }
  647.     }
  648.     return true;
  649. }
  650.  
  651. /* Renames a path.*/
  652. int fsys_class::rename(const string& s)
  653. {
  654.     string temps = (parent(fsys_class::path) + "\\" + s);
  655.     if(is_valid_filename(s) == false)
  656.     {
  657.         cout<< "ERROR: Invalid Filename"<< endl;
  658.         return FSYS_ERROR;
  659.     }
  660.     try
  661.     {
  662.         std::rename(fsys_class::path.c_str(), temps.c_str());
  663.     }
  664.     catch(const exception& e)
  665.     {
  666.         cout<< e.what()<< endl;
  667.         return FSYS_ERROR;
  668.     }
  669.     if((is_folder_supliment(temps) == true) || (is_file_supliment(temps) == true))
  670.     {
  671.         return 0;
  672.     }
  673.     return FSYS_FAILURE;
  674. }
  675.  
  676. string current_directory()
  677. {
  678.     return boost::filesystem::current_path().string();
  679. }
  680.  
  681. string fsys_class::gpath()
  682. {
  683.     return fsys_class::path;
  684. }
  685.  
  686. string filename_sup(const string& s)
  687. {
  688.     boost::filesystem::path p = s;
  689.     return p.filename().string();
  690. }
  691.  
  692. /* Returns the filename of the path.*/
  693. string fsys_class::gfilename()
  694. {
  695.     return filename_sup(fsys_class::path);
  696. }
  697.  
  698. int create_dir(const string& parent, const string& foldername)
  699. {
  700.     boost::filesystem::path p = parent;
  701.     p = (p.string() + "\\" + foldername);
  702.     if(boost::filesystem::is_directory(p) == false)
  703.     {
  704.         try
  705.         {
  706.             boost::filesystem::create_directories(p);
  707.         }
  708.         catch(const exception& e)
  709.         {
  710.             cout<< e.what()<< endl;
  711.             return FSYS_ERROR;
  712.         }
  713.         if(boost::filesystem::is_directory(p) == false)
  714.         {
  715.             return FSYS_FAILURE;
  716.         }
  717.     }
  718.     return 0;
  719. }
  720.  
  721. /* Creates a folder under the set path with the argument name.
  722.  
  723.    fsys_class::create("Jon stuff") will create a folder under
  724.  the fsys_class::path if fsys_class::path is a folder.*/
  725. int fsys_class::create(const string& sub_folder)
  726. {
  727.     if(is_folder_supliment(fsys_class::path) == false)
  728.     {
  729.         return FSYS_ERROR;
  730.     }
  731.     return create_dir(fsys_class::path, sub_folder);
  732. }