PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/include/attach/attach_func.php

https://github.com/Dratone/EveBB
PHP | 338 lines | 233 code | 49 blank | 56 comment | 56 complexity | b87fd280e41d96b9fce61fa80fae842d MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /* Functions in this file
  3. working:
  4. bool attach_rules(int rules, int check)
  5. bool attach_allow_upload(int rules, int max_file_size, string allowed_file_ext, int uploaded_size, string uploaded_file_name)
  6. string attach_icon(string extension)
  7. string attach_generate_pathname(string storagepath)
  8. string attach_generate_filename(string storagepath, int messagelenght, int filesize)
  9. string attach_create_mime(string extension)
  10. string attach_get_extension(string filename)
  11. bool attach_check_extension(string filename, string allowed)
  12. void attach_fix_icon_array(void)
  13. bool attach_delete_attachment(int item)
  14. bool attach_create_subfolder(string subfolder)
  15. int attach_create_attachment(string filename, string mime, int filesize, string tmp_name, int post id, int messagelenght)
  16. void attach_delete_thread(int threadid)
  17. void attach_delete_post(int postid)
  18. todo:
  19. */
  20. function attach_rules($rules=0, $check=1){ //binary check if check is in rules
  21. if($rules & $check && $rules != 0)return true;
  22. else return false;
  23. }
  24. function attach_allow_upload($rules=0,$max_size=0,$file_ext='',$upload_size=10,$upload_name=''){
  25. global $pun_user,$pun_config;
  26. $attach_allowed = false;
  27. //check so that the user is allowed to upload
  28. if(attach_rules($rules,ATTACH_UPLOAD)||$pun_user['g_id']==PUN_ADMIN)
  29. $attach_allowed=true;
  30. else
  31. $attach_allowed=false;
  32. // check for file extension
  33. if(($attach_allowed && attach_check_extension($upload_name,$file_ext))||$pun_user['g_id']==PUN_ADMIN)
  34. $attach_allowed=true;
  35. else
  36. $attach_allowed=false;
  37. // check for filesize (the only thing Administrators cannot override, so it needs to be last)
  38. if((($attach_allowed && $upload_size <= $max_size)||($pun_user['g_id']==PUN_ADMIN)) && $upload_size <= $pun_config['attach_max_size'])
  39. $attach_allowed=true;
  40. else
  41. $attach_allowed=false;
  42. return $attach_allowed;
  43. }
  44. function attach_icon($extension){
  45. global $pun_config, $attach_icons, $pun_user; //fetch some global stuff needed
  46. if(count($attach_icons) == 0 && strlen($pun_config['attach_icon_extension']) != 0)attach_fix_icon_array();
  47. $icon_url = $pun_config['attach_icon_folder'].'unknown.png'; // default icon, if none found in the attachment icon list
  48. if($pun_user['show_img'] == 0||$pun_config['attach_use_icon']== 0)return ''; // user doesn't want to see images.
  49. if(array_key_exists($extension,$attach_icons))$icon_url = $pun_config['attach_icon_folder'].$attach_icons[$extension]; // if extension exist, assign that one to the url instead of the default
  50. return '<img src="'.$icon_url.'" width="15" height="15" alt="'.pun_htmlspecialchars($extension).'" />'; // return the image stuff...
  51. }
  52. function attach_fix_icon_array(){
  53. global $pun_config, $attach_icons;
  54. $icon_extension = explode('"',$pun_config['attach_icon_extension']);
  55. $icon_name = explode('"',$pun_config['attach_icon_name']);
  56. for($i = 0; $i < count($icon_extension); $i++){
  57. $attach_icons[$icon_extension[$i]]=$icon_name[$i];
  58. }
  59. }
  60. function attach_generate_pathname($storagepath=''){
  61. if(strlen($storagepath)!=0){
  62. //we have to check so that path doesn't exist already...
  63. $not_unique=true;
  64. while($not_unique){
  65. $newdir = attach_generate_pathname();
  66. if(!is_dir($storagepath.$newdir))return $newdir;
  67. }
  68. }else
  69. return substr(md5(time().'Salt keyword, replace if you want to'),0,32);
  70. }
  71. function attach_generate_filename($storagepath, $messagelenght=0, $filesize=0){
  72. $not_unique=true;
  73. while($not_unique){
  74. $newfile = md5(attach_generate_pathname().$messagelenght.$filesize.'Some more salt keyworbs, change if you want to').'.attach';
  75. if(!is_file($storagepath.$newfile))return $newfile;
  76. }
  77. }
  78. function attach_create_attachment($name='', $mime='', $size=0, $tmp_name='', $post_id=0, $messagelenght=0){
  79. global $db, $pun_user, $pun_config;
  80. // fetch an unique name for the file
  81. $unique_name = attach_generate_filename($pun_config['attach_basefolder'].$pun_config['attach_subfolder'].'/',$messagelenght,$size);
  82. // move the uploaded file from temp to the attachment folder and rename the file to the unique name
  83. if(!move_uploaded_file($tmp_name,$pun_config['attach_basefolder'].$pun_config['attach_subfolder'].'/'.$unique_name))
  84. error('Unable to move file from: '.$tmp_name.' to '.$pun_config['attach_basefolder'].$pun_config['attach_subfolder'].'/'.$unique_name.'',__FILE__,__LINE__);
  85. //return false;
  86. if(strlen($mime)==0)
  87. $mime = attach_create_mime(attach_find_extention($name));
  88. // update the database with this info
  89. $result = $db->query('INSERT INTO '.$db->prefix.'attach_2_files (owner,post_id,filename,extension,mime,location,size) VALUES ('.$pun_user['id'].', '.$post_id.', \''.$db->escape($name).'\', \''.$db->escape(attach_get_extension($name)).'\', \''.$db->escape($mime).'\', \''.$db->escape($pun_config['attach_subfolder'].'/'.$unique_name).'\', '.$size.')')or error('Unable to insert attachment record into database.',__FILE__,__LINE__,$db->error());
  90. return true;
  91. }
  92. function attach_create_subfolder($newfolder=''){
  93. global $db,$pun_config,$pun_user;
  94. if(strlen($newfolder)==0||$pun_user['g_id']!=PUN_ADMIN)
  95. return false;
  96. // check to see if that folder is there already, then just update the config ...
  97. if(!is_dir($pun_config['attach_basefolder'].$newfolder)){
  98. // if the folder doesn't excist, try to create it
  99. if(!mkdir($pun_config['attach_basefolder'].$newfolder,0755))
  100. error('Unable to create new subfolder with name \''.$pun_config['attach_basefolder'].$newfolder.'\' with mode 0755',__FILE__,__LINE__);
  101. // create a .htaccess and index.html file in the new subfolder
  102. if(!copy($pun_config['attach_basefolder'].'.htaccess', $pun_config['attach_basefolder'].$newfolder.'/.htaccess'))
  103. error('Unable to copy .htaccess file to new subfolder with name \''.$pun_config['attach_basefolder'].$newfolder.'\'',__FILE__,__LINE__);
  104. if(!copy($pun_config['attach_basefolder'].'index.html', $pun_config['attach_basefolder'].$newfolder.'/index.html'))
  105. error('Unable to copy index.html file to new subfolder with name \''.$pun_config['attach_basefolder'].$newfolder.'\'',__FILE__,__LINE__);
  106. // if the folder was created continue
  107. }
  108. $form = array ('subfolder' => $newfolder);
  109. // update the config, if the subfolder has changed
  110. while (list($key, $input) = @each($form))
  111. {
  112. // Only update values that have changed
  113. if ($pun_config['attach_'.$key] != $input)
  114. {
  115. if ($input != '' || is_int($input))
  116. $value = '\''.$db->escape($input).'\'';
  117. else
  118. $value = 'NULL';
  119. $db->query('UPDATE '.$db->prefix.'config SET conf_value='.$value.' WHERE conf_name=\'attach_'.$key.'\'') or error('Unable to update attachment mod config', __FILE__, __LINE__, $db->error());
  120. }
  121. }
  122. require_once PUN_ROOT.'include/cache.php';
  123. generate_config_cache();
  124. // return true if everything has gone as planned, return false if the new folder could not be created (rights etc?)
  125. return true;
  126. }
  127. function attach_create_mime($extension=''){
  128. $mimecodes = array ( // mimes taken from microsoft ... those that don't need external programs to work
  129. // abit unsure on some file extentions, but they aren't used so much anyhow :P
  130. //fileext. mimetype
  131. 'diff' => 'text/x-diff',
  132. 'patch' => 'text/x-diff',
  133. 'rtf' => 'text/richtext',
  134. 'html' => 'text/html',
  135. 'htm' => 'text/html',
  136. 'aiff' => 'audio/x-aiff',
  137. 'iff' => 'audio/x-aiff',
  138. 'basic' => 'audio/basic', // no idea about extention
  139. 'wav' => 'audio/wav',
  140. 'gif' => 'image/gif',
  141. 'jpg' => 'image/jpeg',
  142. 'jpeg' => 'image/pjpeg',
  143. 'tif' => 'image/tiff',
  144. 'png' => 'image/x-png',
  145. 'xbm' => 'image/x-xbitmap', // no idea about extention
  146. 'bmp' => 'image/bmp',
  147. 'xjg' => 'image/x-jg', // no idea about extention
  148. 'emf' => 'image/x-emf', // no idea about extention
  149. 'wmf' => 'image/x-wmf', // no idea about extention
  150. 'avi' => 'video/avi',
  151. 'mpg' => 'video/mpeg',
  152. 'mpeg' => 'video/mpeg',
  153. 'ps' => 'application/postscript',
  154. 'b64' => 'application/base64', // no idea about extention
  155. 'macbinhex' => 'application/macbinhex40', // no idea about extention
  156. 'pdf' => 'application/pdf',
  157. 'xzip' => 'application/x-compressed', // no idea about extention
  158. 'zip' => 'application/x-zip-compressed',
  159. 'gzip' => 'application/x-gzip-compressed',
  160. 'java' => 'application/java',
  161. 'msdownload' => 'application/x-msdownload' // no idea about extention
  162. );
  163. foreach ($mimecodes as $type => $mime ){
  164. if($extention==$type)
  165. return $mime;
  166. }
  167. return 'application/octet-stream'; // default, if not defined above...
  168. }
  169. function attach_get_extension($filename=''){
  170. if(strlen($filename)==0)return '';
  171. return strtolower(ltrim(strrchr($filename,"."),"."));
  172. }
  173. function attach_check_extension($filename='', $allowed_extensions=''){
  174. global $pun_config;
  175. $cur_file_extension = attach_get_extension($filename);
  176. $allowed_extensions = (strlen($allowed_extensions)!=0)?explode('"',$allowed_extensions):array();
  177. $denied_extensions = (strlen($pun_config['attach_always_deny'])!=0)?explode('"',$pun_config['attach_always_deny']):array();
  178. //if it's denied, return false
  179. foreach($denied_extensions AS $key => $value){
  180. //if the extension is there, return false
  181. if($value==$cur_file_extension)return false;
  182. }
  183. //if it's not there, check against the allowed, if there are any entered...
  184. if(count($allowed_extensions)!=0){
  185. foreach($allowed_extensions AS $key => $value){
  186. //if the extension is there, return true
  187. if($value==$cur_file_extension)return true;
  188. }
  189. return false;
  190. }
  191. //ok, nothing there...so then it's ok to take it on...
  192. return true;
  193. }
  194. function attach_delete_attachment($item=0){
  195. global $db, $pun_user, $pun_config;
  196. // check if the user may delete it ... can be overridden, but that's only if create orphans are off...
  197. $attach_allowed_delete = false;
  198. if($pun_user['g_id']==PUN_ADMIN)
  199. $attach_allowed_delete = true;
  200. else{
  201. // make a database query to check if the user is allowed to delete it, and if the user is the owner.
  202. $result = $db->query('SELECT af.owner, ar.rules FROM '.$db->prefix.'attach_2_files AS af, '.$db->prefix.'attach_2_rules AS ar, '.$db->prefix.'posts AS p, '.$db->prefix.'topics AS t WHERE af.id = \''.$item.'\' AND p.id = af.post_id AND t.id=p.topic_id AND ar.forum_id = t.forum_id AND ar.group_id='.$pun_user['g_id'].' LIMIT 1')or error('Unable to fetch owner and attachment rules',__FILE__,__LINE__,$db->error());
  203. if($db->num_rows($result)==1){
  204. list($attach_owner, $attach_rules) = $db->fetch_row($result);
  205. // depending on if the user doing this is the owner or another (moderator?) ,different rulechecks...
  206. $attach_rule_to_check = ($attach_owner == $pun_user['id']) ? ATTACH_OWNER_DELETE : ATTACH_DELETE;
  207. $attach_allowed_delete = attach_rules($attach_rules,$attach_rule_to_check);
  208. }
  209. if($pun_config['attach_create_orphans']=='0' && (basename($_SERVER['SCRIPT_NAME'])=='delete.php'||basename($_SERVER['SCRIPT_NAME'])=='moderate.php')){
  210. $attach_allowed_delete = true;
  211. // this thing overrides if no orphans should be created, and thus the user must always be able to delete all attachments in threads or posts when using delete.php or moderate.php
  212. }
  213. }
  214. if($attach_allowed_delete){
  215. // fetch the info for the file
  216. $result = $db->query('SELECT af.location FROM '.$db->prefix.'attach_2_files AS af WHERE af.id='.intval($item).' LIMIT 1')or error('Unable to load file info',__FILE__,__LINE__,$db->error());
  217. if($db->num_rows($result)==1)
  218. list($attach_location) = $db->fetch_row($result);
  219. // first empty the file
  220. $fp = fopen($pun_config['attach_basefolder'].$attach_location,'wb'); //wb = write, reset file to 0 bytes if existing, and b is just for windows, to tell it's binary mode...is ignored on other OS:es
  221. if (!$fp)
  222. error('Error creating filepointer for file to delete/reset size, for attachment with id: "'.$item.'"',__FILE__,__LINE__);
  223. fclose($fp); // file should now be 0 bytes, 'w' will place the pointer at start, and trunate the file... and I don't put anything in there...
  224. // if successful, remove the database entry
  225. $result = $db->query('DELETE FROM '.$db->prefix.'attach_2_files WHERE id='.intval($item).' LIMIT 1')or error('Unable to delete attachment record in database',__FILE__,__LINE__,$db->error());
  226. return true;
  227. }else
  228. error('Error deleting attachment, not allowed to delete attachment (item_id=\''.$item.'\')',__FILE__,__LINE__);
  229. }
  230. function attach_delete_thread($id=0){
  231. global $db,$pun_config;
  232. $ok=true;
  233. // check if orphans should be made or not
  234. if($pun_config['attach_create_orphans']!=1){
  235. //if delete, fetch all post id's of the posts in this thread
  236. $result_attach = $db->query('SELECT af.id FROM '.$db->prefix.'attach_2_files AS af, '.$db->prefix.'posts AS p WHERE af.post_id=p.id AND p.topic_id='.intval($id)) or error('Error when searching for all attachments in this thread',__FILE__,__LINE__);
  237. if($db->num_rows($result_attach)>0){
  238. //fetch all attachment id's
  239. while((list($attach_id)=$db->fetch_row($result_attach))&&$ok){
  240. // loop though and delete attachment after attachment (this can take a loooong time)
  241. $ok = attach_delete_attachment($attach_id);
  242. // break if attachment failed (then rest will become orphans, but better than a zillion of errors...
  243. }
  244. }
  245. }
  246. }
  247. function attach_delete_post($id=0){
  248. global $db;
  249. $ok =true;
  250. // check for all attachments,
  251. $result = $db->query('SELECT af.id FROM '.$db->prefix.'attach_2_files AS af WHERE af.post_id='.intval($id)) or error('Error when searching for all attachments in this post',__FILE__,__LINE__);
  252. if($db->num_rows($result)>0){
  253. // try to delete each post (I'm using the 'override check' in attach_delete_attachment, so nothing is needed here...)
  254. while((list($attach_id) = $db->fetch_row($result))&&$ok){
  255. $ok = attach_delete_attachment($attach_id); // if one fails, let the other be ... or chanses are that they will fail aswell causing lot of trouble, they becomes orphans instead...
  256. }
  257. }
  258. }
  259. function file_upload_error_message($error_code)
  260. {
  261. switch ($error_code)
  262. {
  263. case UPLOAD_ERR_INI_SIZE:
  264. return 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
  265. case UPLOAD_ERR_FORM_SIZE:
  266. return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
  267. case UPLOAD_ERR_PARTIAL:
  268. return 'The uploaded file was only partially uploaded';
  269. case UPLOAD_ERR_NO_FILE:
  270. return 'No file was uploaded';
  271. case UPLOAD_ERR_NO_TMP_DIR:
  272. return 'Missing a temporary folder';
  273. case UPLOAD_ERR_CANT_WRITE:
  274. return 'Failed to write file to disk';
  275. case UPLOAD_ERR_EXTENSION:
  276. return 'File upload stopped by extension';
  277. default:
  278. return 'Unknown upload error';
  279. }
  280. }
  281. function format_bytes($size)
  282. {
  283. $units = array('B', 'KB', 'MB', 'GB', 'TB');
  284. for ($i = 0; $size >= 1024 && $i < 4; $i++)
  285. $size /= 1024;
  286. return round($size, 1).' '.$units[$i];
  287. }