ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

190 lines
3.6 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef CPPCMS_IMPL_DIR_H
  9. #define CPPCMS_IMPL_DIR_H
  10. #if defined(__sun)
  11. #define _POSIX_PTHREAD_SEMANTICS
  12. #endif
  13. #include <cppcms/defs.h>
  14. #ifdef CPPCMS_WIN_NATIVE
  15. # include <booster/locale/encoding.h>
  16. # ifndef NOMINMAX
  17. # define NOMINMAX
  18. # endif
  19. # include <windows.h>
  20. #else
  21. # include <stdlib.h>
  22. # include <sys/types.h>
  23. # include <dirent.h>
  24. # include <unistd.h>
  25. #endif
  26. #include <booster/noncopyable.h>
  27. #include <string>
  28. #include <assert.h>
  29. namespace cppcms {
  30. namespace impl {
  31. class directory : public booster::noncopyable {
  32. public:
  33. directory();
  34. ~directory();
  35. bool open(std::string const &dir_name);
  36. void close();
  37. bool next();
  38. char const *name();
  39. private:
  40. #ifdef CPPCMS_WIN_NATIVE
  41. HANDLE dir_;
  42. _WIN32_FIND_DATAW entry_;
  43. std::string utf_name_;
  44. #else // POSIX
  45. DIR *dir_;
  46. #if defined(__linux) || defined(__FreeBSD__) || defined(__APPLE__)
  47. struct dirent de_;
  48. #else
  49. #define CPPCMS_DIR_ALLOCATE_DE
  50. struct dirent *de_;
  51. #endif
  52. struct dirent *entry_p_;
  53. #endif
  54. };
  55. inline directory::~directory()
  56. {
  57. close();
  58. }
  59. #ifdef CPPCMS_WIN_NATIVE
  60. inline directory::directory() : dir_(INVALID_HANDLE_VALUE)
  61. {
  62. }
  63. inline void directory::close()
  64. {
  65. if(dir_!=INVALID_HANDLE_VALUE) {
  66. FindClose(dir_);
  67. dir_ = INVALID_HANDLE_VALUE;
  68. }
  69. }
  70. inline bool directory::open(std::string const &name)
  71. {
  72. std::wstring search = booster::locale::conv::utf_to_utf<wchar_t>(name.c_str()) +L"/*";
  73. dir_ = FindFirstFileW(search.c_str(),&entry_);
  74. if(dir_ == INVALID_HANDLE_VALUE) {
  75. if(GetLastError() == ERROR_FILE_NOT_FOUND)
  76. return true;
  77. else
  78. return false;
  79. }
  80. return true;
  81. }
  82. inline bool directory::next()
  83. {
  84. if(dir_ == INVALID_HANDLE_VALUE)
  85. return false;
  86. utf_name_ = booster::locale::conv::utf_to_utf<char>(entry_.cFileName);
  87. if(!FindNextFileW(dir_,&entry_)) {
  88. close();
  89. }
  90. return true;
  91. }
  92. inline char const *directory::name()
  93. {
  94. return utf_name_.c_str();
  95. }
  96. #else // POSIX
  97. inline directory::directory() : dir_(0), entry_p_(0)
  98. {
  99. #ifdef CPPCMS_DIR_ALLOCATE_DE
  100. de_ = 0;
  101. #endif
  102. }
  103. inline bool directory::open(std::string const &dir_name)
  104. {
  105. close();
  106. dir_ = opendir(dir_name.c_str());
  107. if(!dir_)
  108. return false;
  109. #ifdef CPPCMS_DIR_ALLOCATE_DE
  110. //
  111. // This pathconf/opendir exploit can be used with only file systems
  112. // with small file names like fat... So we require
  113. // at least 4K so it would be impossible to exploit
  114. // this
  115. //
  116. int name_len = pathconf(dir_name.c_str(),_PC_NAME_MAX);
  117. if(name_len < 4096) // -1 or small value
  118. name_len = 4096; // guess
  119. #ifdef NAME_MAX
  120. if(name_len < NAME_MAX)
  121. name_len = NAME_MAX;
  122. #endif
  123. de_ = static_cast<struct dirent*>(malloc(sizeof(struct dirent) + name_len + 1 - sizeof(de_->d_name)));
  124. if(!de_)
  125. throw std::bad_alloc();
  126. #endif // alloc de
  127. return true;
  128. }
  129. inline void directory::close()
  130. {
  131. #ifdef CPPCMS_DIR_ALLOCATE_DE
  132. if(de_) {
  133. free(de_);
  134. de_ = 0;
  135. }
  136. #endif
  137. entry_p_ = 0;
  138. if(dir_) {
  139. closedir(dir_);
  140. dir_=0;
  141. }
  142. }
  143. inline bool directory::next()
  144. {
  145. assert(dir_);
  146. #ifdef CPPCMS_DIR_ALLOCATE_DE
  147. struct dirent *d = de_;
  148. #else
  149. struct dirent *d = &de_;
  150. #endif
  151. return readdir_r(dir_,d,&entry_p_) == 0 && entry_p_ != 0;
  152. }
  153. inline char const *directory::name()
  154. {
  155. assert(entry_p_);
  156. return entry_p_->d_name;
  157. }
  158. #endif // POSIX
  159. } // impl
  160. } // cppcms
  161. #endif