PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/class_mailparse.php

http://trellis-desk-translate-russian.googlecode.com/
PHP | 1261 lines | 1222 code | 16 blank | 23 comment | 47 complexity | 90c1cd3eeedbc03f1595069635544277 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /*
  3. #======================================================
  4. | Trellis Desk
  5. | =====================================
  6. | By DJ Tarazona (dj@accord5.com)
  7. | (c) 2010 ACCORD5
  8. | http://www.trellisdesk.com/
  9. | =====================================
  10. | Email: sales@accord5.com
  11. #======================================================
  12. | @ Version: v1.0.4 Final Build 10440094
  13. | @ Version Int: 104.4.0.094
  14. | @ Version Num: 10440094
  15. | @ Build: 0094
  16. #======================================================
  17. | | Mail Parse Class
  18. #======================================================
  19. */
  20. class mailparse {
  21. #=======================================
  22. # @ Parse Email
  23. #=======================================
  24. function decode($raw_email)
  25. {
  26. require_once('Mail/mimeDecode.php');
  27. $params['include_bodies'] = true;
  28. $params['decode_bodies'] = true;
  29. $params['decode_headers'] = true;
  30. $params['input'] = $raw_email;
  31. $decoded = Mail_mimeDecode::decode($params);
  32. // Find Our Content
  33. $email_parse = array();
  34. $attachment = 0;
  35. $charset = 'utf-8';
  36. if ( strtolower( $decoded->ctype_primary ) == 'multipart' )
  37. {
  38. foreach( $decoded->parts as $part )
  39. {
  40. if ( ( $part->disposition == 'attachment' || $part->ctype_primary == 'image' ) && ! $attachment )
  41. {
  42. if ( $part->ctype_parameters['filename'] )
  43. {
  44. $email['attachment_name'] = $this->ifthd->sanitize_data( $part->ctype_parameters['filename'] );
  45. }
  46. elseif ( $part->ctype_parameters['name'] )
  47. {
  48. $email['attachment_name'] = $this->ifthd->sanitize_data( $part->ctype_parameters['name'] );
  49. }
  50. elseif ( $part->ctype_parameters['d_parameters']['name'] )
  51. {
  52. $email['attachment_name'] = $this->ifthd->sanitize_data( $part->ctype_parameters['d_parameters']['name'] );
  53. }
  54. $email['attachment_type'] = $part->ctype_primary .'/'. $part->ctype_secondary;
  55. $email['attachment_content'] = trim( $part->body );
  56. $attachment = 1;
  57. }
  58. elseif ( $part->ctype_primary == 'text' )
  59. {
  60. if ( $part->ctype_secondary == 'plain' )
  61. {
  62. if ( $part->ctype_parameters['charset'] )
  63. {
  64. $email_parse['message']['plain'] = iconv( $part->ctype_parameters['charset'], 'utf-8', $part->body );
  65. }
  66. else
  67. {
  68. $email_parse['message']['plain'] = $part->body;
  69. }
  70. }
  71. elseif ( $part->ctype_secondary == 'html' )
  72. {
  73. if ( $part->ctype_parameters['charset'] )
  74. {
  75. $email_parse['message']['html'] = iconv( $part->ctype_parameters['charset'], 'utf-8', $part->body );
  76. }
  77. else
  78. {
  79. $email_parse['message']['html'] = $part->body;
  80. }
  81. }
  82. if ( $part->ctype_parameters['charset'] && strtolower( $part->ctype_parameters['charset'] ) != $charset )
  83. {
  84. $charset = strtolower( $part->ctype_parameters['charset'] );
  85. }
  86. }
  87. elseif ( strtolower( $part->ctype_primary ) == 'multipart' )
  88. {
  89. foreach( $part->parts as $apart )
  90. {
  91. if ( ( $apart->disposition == 'attachment' || $apart->ctype_primary == 'image' ) && ! $attachment )
  92. {
  93. if ( $apart->ctype_parameters['filename'] )
  94. {
  95. $email['attachment_name'] = $this->ifthd->sanitize_data( $apart->ctype_parameters['filename'] );
  96. }
  97. elseif ( $apart->ctype_parameters['name'] )
  98. {
  99. $email['attachment_name'] = $this->ifthd->sanitize_data( $apart->ctype_parameters['name'] );
  100. }
  101. elseif ( $apart->ctype_parameters['d_parameters']['name'] )
  102. {
  103. $email['attachment_name'] = $this->ifthd->sanitize_data( $apart->ctype_parameters['d_parameters']['name'] );
  104. }
  105. $email['attachment_type'] = $apart->ctype_primary .'/'. $apart->ctype_secondary;
  106. $email['attachment_content'] = trim( $apart->body );
  107. $attachment = 1;
  108. }
  109. elseif ( $apart->ctype_primary == 'text' )
  110. {
  111. if ( $apart->ctype_secondary == 'plain' )
  112. {
  113. if ( strtolower( $apart->ctype_parameters['charset'] ) != 'utf-8' )
  114. {
  115. $email_parse['message']['plain'] = iconv( $part->ctype_parameters['charset'], 'utf-8', $apart->body );
  116. }
  117. else
  118. {
  119. $email_parse['message']['plain'] = $apart->body;
  120. }
  121. }
  122. elseif ( $apart->ctype_secondary == 'html' )
  123. {
  124. if ( strtolower( $apart->ctype_parameters['charset'] ) != 'utf-8' )
  125. {
  126. $email_parse['message']['html'] = iconv( $apart->ctype_parameters['charset'], 'utf-8', $apart->body );
  127. }
  128. else
  129. {
  130. $email_parse['message']['html'] = $apart->body;
  131. }
  132. }
  133. if ( $apart->ctype_parameters['charset'] && strtolower( $apart->ctype_parameters['charset'] ) != $charset )
  134. {
  135. $charset = strtolower( $apart->ctype_parameters['charset'] );
  136. }
  137. }
  138. }
  139. }
  140. }
  141. }
  142. else
  143. {
  144. if ( $decoded->ctype_primary == 'text' )
  145. {
  146. if ( $decoded->ctype_secondary == 'plain' )
  147. {
  148. if ( strtolower( $decoded->ctype_parameters['charset'] ) != 'utf-8' )
  149. {
  150. $email_parse['message']['plain'] = iconv( $decoded->ctype_parameters['charset'], 'utf-8', $decoded->body );
  151. }
  152. else
  153. {
  154. $email_parse['message']['plain'] = $decoded->body;
  155. }
  156. }
  157. elseif ( $decoded->ctype_secondary == 'html' )
  158. {
  159. if ( strtolower( $decoded->ctype_parameters['charset'] ) != 'utf-8' )
  160. {
  161. $email_parse['message']['html'] = iconv( $decoded->ctype_parameters['charset'], 'utf-8', $decoded->body );
  162. }
  163. else
  164. {
  165. $email_parse['message']['html'] = $decoded->body;
  166. }
  167. }
  168. }
  169. }
  170. // From
  171. if ( strpos( $decoded->headers['from'], '<' ) !== false )
  172. {
  173. if ( preg_match( "/(.*?)<(.*)>/", $decoded->headers['from'], $matches ) )
  174. {
  175. $email['nickname'] = $matches[1];
  176. $email['from'] = $matches[2];
  177. if ( preg_match( "/\"([^\"]*)\"/", $email['nickname'], $matches ) )
  178. {
  179. $email['nickname'] = $matches[1];
  180. }
  181. }
  182. else
  183. {
  184. $email['from'] = $decoded->headers['from'];
  185. }
  186. }
  187. elseif ( preg_match( "/([0-9,a-z,A-Z,+]+)([0-9,a-z,A-Z,.,_,-,+]+)[@]([0-9,a-z,A-Z]+)([0-9,a-z,A-Z,.,_,-]+)[.]([0-9,a-z,A-Z]{2})([0-9,a-z,A-Z]*)[\s](.+)/", $decoded->headers['from'], $matches ) )
  188. {
  189. $email['nickname'] = $matches[7];
  190. $email['from'] = $matches[1] . $matches[2] . '@' . $matches[3] . $matches[4] .'.' . $matches[5] . $matches[6];
  191. }
  192. else
  193. {
  194. $email['from'] = $decoded->headers['from'];
  195. }
  196. // To
  197. if ( strpos( $decoded->headers['to'], '<' ) !== false )
  198. {
  199. if ( preg_match( "/<(.*)>/", $decoded->headers['to'], $matches ) )
  200. {
  201. $email['to'] = $matches[1];
  202. }
  203. }
  204. elseif ( preg_match( "/([0-9,a-z,A-Z,+]+)([0-9,a-z,A-Z,.,_,-,+]+)[@]([0-9,a-z,A-Z]+)([0-9,a-z,A-Z,.,_,-]+)[.]([0-9,a-z,A-Z]{2})([0-9,a-z,A-Z]*)[\s](.+)/", $decoded->headers['to'], $matches ) )
  205. {
  206. $email['to'] = $matches[1] . $matches[2] . '@' . $matches[3] . $matches[4] .'.' . $matches[5] . $matches[6];
  207. }
  208. else
  209. {
  210. $email['to'] = $decoded->headers['to'];
  211. }
  212. // Finally, Sanitize
  213. $email['from'] = $this->ifthd->sanitize_data( $email['from'] );
  214. $email['nickname'] = $this->ifthd->sanitize_data( $email['nickname'] );
  215. $email['to'] = $this->ifthd->sanitize_data( $email['to'] );
  216. $email['date'] = strtotime( $decoded->headers['date'] );
  217. $email['subject'] = $this->ifthd->sanitize_data( iconv( $charset, 'utf-8', $decoded->headers['subject'] ) );
  218. $email['message']['plain'] = $this->ifthd->sanitize_data( $email_parse['message']['plain'] );
  219. $email['message']['html'] = $this->ifthd->sanitize_data( $email_parse['message']['html'] );
  220. return $email;
  221. }
  222. #=======================================
  223. # @ Process Email
  224. #=======================================
  225. function process($email)
  226. {
  227. if ( ! $email['nickname'] ) $email['nickname'] = $email['from'];
  228. if ( ! $email['from'] || ! $email['to'] || ! $email['subject'] )
  229. {
  230. $this->ifthd->log( 'error', "Email ??????????? ??????????" );
  231. return false;
  232. }
  233. if ( ! $this->ifthd->validate_email( $email['from'] ) )
  234. {
  235. $this->ifthd->log( 'error', "???????????? ????? Email" );
  236. return false;
  237. }
  238. #=============================
  239. # Flood Check
  240. #=============================
  241. if ( $this->ifthd->core->cache['config']['email_flood'] )
  242. {
  243. $this->ifthd->core->db->construct( array(
  244. 'insert' => 'in_email_log',
  245. 'set' => array( 'email' => $email['from'], 'date' => time() ),
  246. ) );
  247. $this->ifthd->core->db->execute();
  248. $time_cutoff = 60 * 3; // 3 Min
  249. $this->ifthd->core->db->construct( array(
  250. 'select' => array( 'id' ),
  251. 'from' => 'in_email_log',
  252. 'where' => array( array( 'email', '=', $email['from'] ), array( 'date', '>=', ( time() - $time_cutoff ), 'and' ) ),
  253. 'limit' => array( 0, 6 ),
  254. ) );
  255. $this->ifthd->core->db->execute();
  256. if ( $this->ifthd->core->db->get_num_rows() > 5 )
  257. {
  258. $this->ifthd->log( 'security', "Email ????? ?????: ". $email['from'] );
  259. return false;
  260. }
  261. }
  262. #=============================
  263. # Find Department
  264. #=============================
  265. $this->ifthd->core->db->construct( array(
  266. 'select' => 'all',
  267. 'from' => 'departments',
  268. 'where' => array( 'incoming_email', '=', $email['to'], 'and' ),
  269. 'limit' => array( 0, 1 ),
  270. ) );
  271. $this->ifthd->core->db->execute();
  272. if ( ! $this->ifthd->core->db->get_num_rows() )
  273. {
  274. $this->ifthd->log( 'error', "????? ?? ?????? Email: ". $email['to'] );
  275. return false;
  276. }
  277. $d = $this->ifthd->core->db->fetch_row();
  278. #=============================
  279. # Find Member
  280. #=============================
  281. $this->ifthd->core->db->construct( array(
  282. 'select' => array( 'm' => array( 'id', 'name', 'time_zone', 'dst_active', 'open_tickets' ), 'g' => array( 'g_upload_size_max', 'g_m_depart_perm', 'g_depart_perm', 'g_acp_access' ) ),
  283. 'from' => array( 'm' => 'members' ),
  284. 'join' => array( array( 'from' => array( 'g' => 'groups' ), 'where' => array( 'g' => 'g_id', '=', 'm' => 'mgroup' ) ) ),
  285. 'where' => array( array( 'm' => 'email' ), '=', $email['from'] ),
  286. 'limit' => array( 0, 1 ),
  287. ) );
  288. $this->ifthd->core->db->execute();
  289. if ( $this->ifthd->core->db->get_num_rows() )
  290. {
  291. $m = $this->ifthd->core->db->fetch_row();
  292. }
  293. else
  294. {
  295. if ( ! $d['guest_pipe'] )
  296. {
  297. $replace = array(); // Initialize for Security
  298. if ( $m['id'] )
  299. {
  300. $this->ifthd->send_email( $m['id'], 'ticket_pipe_rejected', $replace, array( 'from_email' => $d['incoming_email'] ) );
  301. }
  302. else
  303. {
  304. $replace['MEM_NAME'] = $email['nickname'];
  305. $this->ifthd->send_guest_email( $email['from'], 'ticket_pipe_rejected', $replace, array( 'from_email' => $d['incoming_email'] ) );
  306. }
  307. $this->ifthd->log( 'security', "Guest Piping Not Allowed: ". $d['name'] );
  308. return false;
  309. }
  310. $this->ifthd->core->db->construct( array(
  311. 'select' => array( 'g_upload_size_max', 'g_m_depart_perm' ),
  312. 'from' => 'groups',
  313. 'where' => array( 'g_id', '=', 2 ),
  314. 'limit' => array( 0, 1 ),
  315. ) );
  316. $this->ifthd->core->db->execute();
  317. $m = $this->ifthd->core->db->fetch_row();
  318. }
  319. #=============================
  320. # Detect Type
  321. #=============================
  322. $ticket_found = 0;
  323. if ( preg_match_all( $this->ifthd->convert_html( $this->ifthd->core->cache['config']['email_subject_regex'] ), $email['subject'], $matches, PREG_PATTERN_ORDER ) )
  324. {
  325. while( list( , $ptid ) = each( $matches[1] ) )
  326. {
  327. $this->ifthd->core->db->construct( array(
  328. 'select' => 'all',
  329. 'from' => 'tickets',
  330. 'where' => array( 'id', '=', intval( $ptid ) ),
  331. 'limit' => array( 0, 1 ),
  332. ) );
  333. $this->ifthd->core->db->execute();
  334. if ( $this->ifthd->core->db->get_num_rows() )
  335. {
  336. $ticket_found = 1;
  337. $t = $this->ifthd->core->db->fetch_row();
  338. break;
  339. }
  340. }
  341. }
  342. $message_html = 0;
  343. if ( $m['g_acp_access'] && $ticket_found )
  344. {
  345. if ( $email['message']['html'] )
  346. {
  347. if ( $this->ifthd->core->cache['config']['enable_ticket_rte'] )
  348. {
  349. $message = $email['message']['html'];
  350. $message_html = 1;
  351. }
  352. else
  353. {
  354. if ( $email['message']['plain'] )
  355. {
  356. $message = $email['message']['plain'];
  357. }
  358. else
  359. {
  360. $message = $this->ifthd->remove_html_s( $email['message']['html'] );
  361. }
  362. }
  363. }
  364. elseif ( $email['message']['plain'] )
  365. {
  366. $message = $email['message']['plain'];
  367. }
  368. }
  369. else
  370. {
  371. if ( $email['message']['plain'] )
  372. {
  373. $message = $email['message']['plain'];
  374. }
  375. elseif ( $email['message']['html'] )
  376. {
  377. $message = $this->ifthd->remove_html_s( $email['message']['html'] );
  378. }
  379. }
  380. // Get The Good Message
  381. if ( $this->ifthd->core->cache['config']['email_use_rline'] )
  382. {
  383. $final_message = "";
  384. $message_on = "";
  385. $found_on = 0;
  386. $on_line = 0;
  387. $end_line = 0;
  388. $msg_lines = split( "\n", $message );
  389. foreach( $msg_lines as $num => $mline )
  390. {
  391. if ( preg_match( '/^On[\s]/i', $mline ) )
  392. {
  393. $on_line = $num;
  394. $found_on = 1;
  395. }
  396. if ( strpos( $mline, $this->ifthd->core->cache['config']['email_reply_line'] ) !== false )
  397. {
  398. $end_line = $num;
  399. break;
  400. }
  401. if ( $found_on )
  402. {
  403. $message_on .= $mline ."\n";
  404. }
  405. else
  406. {
  407. $final_message .= $mline ."\n";
  408. }
  409. }
  410. if ( ( ( $end_line - $on_line ) > 2 ) || ! $end_line ) $final_message .= $message_on;
  411. $message = trim( $final_message );
  412. if ( $message_html ) $message = $this->closetags( $message );
  413. }
  414. if ( ! $message )
  415. {
  416. $this->ifthd->log( 'error', "??????????? ????????? ??????????? ?????" );
  417. return false;
  418. }
  419. #=============================
  420. # Process
  421. #=============================
  422. if ( $ticket_found )
  423. {
  424. if ( $m['g_acp_access'] )
  425. {
  426. if ( $t['mid'] )
  427. {
  428. $this->ifthd->core->db->construct( array(
  429. 'select' => array( 'email_notify', 'email_ticket_reply', 'time_zone', 'dst_active', 'open_tickets' ),
  430. 'from' => 'members',
  431. 'where' => array( 'id', '=', $t['mid'] ),
  432. ) );
  433. $this->ifthd->core->db->execute();
  434. $mem = $this->ifthd->core->db->fetch_row();
  435. }
  436. if ( $perms = is_array( unserialize( $m['g_depart_perm'] ) ) )
  437. {
  438. if ( ! $perms[ $t['did'] ] )
  439. {
  440. $this->ifthd->log( 'security', "????????? ????????? ???????? Email: ". $t['subject'] );
  441. return false;
  442. }
  443. }
  444. }
  445. else
  446. {
  447. if ( $t['mid'] )
  448. {
  449. if ( $m['id'] != $t['mid'] )
  450. {
  451. $this->ifthd->log( 'security', "????????? ????????????? ???????? Email: ". $t['subject'] );
  452. return false;
  453. }
  454. }
  455. else
  456. {
  457. if ( $email['from'] != $t['email'] )
  458. {
  459. $this->ifthd->log( 'security', "????????? ?????? ???????? Email: ". $t['subject'] );
  460. return false;
  461. }
  462. }
  463. }
  464. if ( $t['status'] == 6 )
  465. {
  466. if ( $m['g_acp_access'] || $d['ticket_own_reopen'] )
  467. {
  468. $this->ifthd->core->db->construct( array(
  469. 'update' => 'tickets',
  470. 'set' => array( 'close_reason' => "", 'status' => 1 ),
  471. 'where' => array( 'id', '=', $t['id'] ),
  472. ) );
  473. $this->ifthd->core->db->execute();
  474. $this->ifthd->log( 'ticket', "?????? ?????? ???????? &#039;". $t['subject'] ."&#039;", 1, $t['id'] );
  475. if ( $m['g_acp_access'] )
  476. {
  477. if ( $t['mid'] )
  478. {
  479. $this->ifthd->core->db->construct( array(
  480. 'update' => 'members',
  481. 'set' => array( 'open_tickets' => $mem['open_tickets'] + 1 ),
  482. 'where' => array( 'id', '=', $t['mid'] ),
  483. ) );
  484. $this->ifthd->core->db->next_shutdown();
  485. $this->ifthd->core->db->execute();
  486. }
  487. }
  488. else
  489. {
  490. $this->ifthd->core->db->construct( array(
  491. 'update' => 'members',
  492. 'set' => array( 'open_tickets' => $m['open_tickets'] + 1 ),
  493. 'where' => array( 'id', '=', $t['mid'] ),
  494. ) );
  495. $this->ifthd->core->db->next_shutdown();
  496. $this->ifthd->core->db->execute();
  497. }
  498. }
  499. else
  500. {
  501. $replace['TICKET_ID'] = $t['id'];
  502. $replace['SUBJECT'] = $t['subject'];
  503. if ( $m['id'] )
  504. {
  505. $this->ifthd->send_email( $m['id'], 'reply_pipe_closed', $replace, array( 'from_email' => $d['incoming_email'] ) );
  506. }
  507. else
  508. {
  509. $replace['MEM_NAME'] = $email['nickname'];
  510. $this->ifthd->send_guest_email( $email['from'], 'reply_pipe_closed', $replace, array( 'from_email' => $d['incoming_email'] ) );
  511. }
  512. $this->ifthd->log( 'error', "????? ????????, ?????? ?????? &#039;". $t['subject'] ."&#039;", 1, $t['id'] );
  513. return false;
  514. }
  515. }
  516. #=============================
  517. # Attachment
  518. #=============================
  519. if ( $d['can_attach'] && $email['attachment_name'] )
  520. {
  521. $allowed_exts = explode( "|", $this->ifthd->core->cache['config']['upload_exts'] );
  522. $file_ext = strrchr( $email['attachment_name'], "." );
  523. if ( in_array( $file_ext, $allowed_exts ) )
  524. {
  525. if ( ( strlen( $email['attachment_content'] ) / 1024 ) <= $m['g_upload_size_max'] || ! $m['g_upload_size_max'] )
  526. {
  527. $file_safe_name = $this->sanitize_name( $email['attachment_name'] );
  528. $attachment_name = md5( 'a'. uniqid( rand(), true ) ) . $file_ext;
  529. $attachment_loc = $this->ifthd->core->cache['config']['upload_dir'] .'/'. $attachment_name;
  530. if ( @ $fp = fopen( $attachment_loc, 'a' ) )
  531. {
  532. if ( @ fwrite( $fp, $email['attachment_content'] ) )
  533. {
  534. @ fclose( $fp );
  535. $db_array = array(
  536. 'tid' => $t['id'],
  537. 'real_name' => $attachment_name,
  538. 'original_name' => $file_safe_name,
  539. 'mid' => $m['id'],
  540. 'mname' => $m['name'],
  541. 'size' => strlen( $email['attachment_content'] ),
  542. 'mime' => $email['attachment_type'],
  543. 'date' => time(),
  544. );
  545. $this->ifthd->core->db->construct( array(
  546. 'insert' => 'attachments',
  547. 'set' => $db_array,
  548. ) );
  549. $this->ifthd->core->db->execute();
  550. $attachment_id = $this->ifthd->core->db->get_insert_id();
  551. $this->ifthd->log( 'ticket', "????????? ???????? #". $attachment_id, 1, $t['id'] );
  552. $this->ifthd->log( 'member', "????????? ???????? #". $attachment_id, 1, $attachment_id );
  553. }
  554. }
  555. }
  556. }
  557. }
  558. #=============================
  559. # Add Reply
  560. #=============================
  561. $db_array = array(
  562. 'tid' => $t['id'],
  563. 'mid' => $m['id'],
  564. 'mname' => $m['name'],
  565. 'attach_id' => $attachment_id,
  566. 'message' => $message,
  567. 'date' => time(),
  568. 'ipadd' => $this->ifthd->input['ip_address'],
  569. );
  570. if ( ! $m['id'] )
  571. {
  572. $db_array['mname'] = $email['nickname'];
  573. $db_array['guest'] = 1;
  574. }
  575. elseif ( $m['g_acp_access'] )
  576. {
  577. $db_array['staff'] = 1;
  578. if ( $message_html ) $db_array['rte'] = 1;
  579. }
  580. $this->ifthd->core->db->construct( array(
  581. 'insert' => 'replies',
  582. 'set' => $db_array,
  583. ) );
  584. $this->ifthd->core->db->execute();
  585. $reply_id = $this->ifthd->core->db->get_insert_id();
  586. $this->ifthd->log( 'member', "?????? ????? &#039;". $t['subject'] ."&#039;", 1, $reply_id );
  587. $this->ifthd->log( 'ticket', "?????? ????? &#039;". $t['subject'] ."&#039;", 1, $t['id'] );
  588. #=============================
  589. # Email
  590. #=============================
  591. if ( $m['g_acp_access'] )
  592. {
  593. if ( ( $mem['email_ticket_reply'] && $mem['email_notify'] ) || ( $this->ifthd->core->cache['config']['guest_ticket_emails'] && $t['guest_email'] ) )
  594. {
  595. $mem_offset = ( $mem['time_zone'] * 60 * 60 ) + ( $mem['dst_active'] * 60 * 60 );
  596. $replace = ""; // Initialize for Security
  597. $replace['TICKET_ID'] = $t['id'];
  598. $replace['SUBJECT'] = $t['subject'];
  599. $replace['DEPARTMENT'] = $t['dname'];
  600. $replace['PRIORITY'] = $this->ifthd->get_priority( $t['priority'] );
  601. $replace['SUB_DATE'] = $this->ifthd->ift_date( $t['date'], '', '', 0, 1, $mem_offset, 1 );
  602. $replace['REPLY'] = $message;
  603. $replace['MESSAGE'] = $t['message'];
  604. if ( $mem['email_ticket_reply'] )
  605. {
  606. $replace['TICKET_LINK'] = $this->ifthd->core->cache['config']['hd_url'] ."/index.php?act=tickets&code=view&id=". $t['id'];
  607. $this->ifthd->send_email( $t['mid'], 'ticket_reply', $replace, array( 'from_email' => $this->ifthd->core->cache['depart'][ $t['did'] ]['incoming_email'] ), 1 );
  608. }
  609. elseif ( ! $t['mid'] && $this->ifthd->core->cache['config']['guest_ticket_emails'] && $t['guest_email'] )
  610. {
  611. $replace['MEM_NAME'] = $t['mname'];
  612. $replace['TICKET_KEY'] = $t['tkey'];
  613. $replace['TICKET_LINK'] = $this->ifthd->core->cache['config']['hd_url'] ."/index.php?act=tickets&code=view&id=". $t['id'] ."&email=". urlencode( $t['email'] ) ."&key=". $t['tkey'];
  614. $this->ifthd->send_guest_email( $t['email'], 'ticket_reply_guest', $replace, array( 'from_email' => $this->ifthd->core->cache['depart'][ $t['did'] ]['incoming_email'] ), 1 );
  615. }
  616. }
  617. }
  618. else
  619. {
  620. $this->ifthd->core->db->construct( array(
  621. 'select' => array( 'm' => array( 'id', 'mgroup', 'email_notify', 'email_staff_ticket_reply', 'time_zone', 'dst_active' ),
  622. 'g' => array( 'g_depart_perm' ),
  623. ),
  624. 'from' => array( 'm' => 'members' ),
  625. 'join' => array( array( 'from' => array( 'g' => 'groups' ), 'where' => array( 'g' => 'g_id', '=', 'm' => 'mgroup' ) ) ),
  626. 'where' => array( array( 'g' => 'g_acp_access' ), '=', 1 ),
  627. ) );
  628. $staff_sql = $this->ifthd->core->db->execute();
  629. if ( $this->ifthd->core->db->get_num_rows($staff_sql) )
  630. {
  631. while( $sm = $this->ifthd->core->db->fetch_row($staff_sql) )
  632. {
  633. // Check Departments
  634. if ( is_array( unserialize( $sm['g_depart_perm'] ) ) )
  635. {
  636. $my_departs = "";
  637. $my_departs = unserialize( $sm['g_depart_perm'] );
  638. if ( $my_departs[ $d['id'] ] )
  639. {
  640. if ( $sm['email_staff_ticket_reply'] && $sm['email_notify'] )
  641. {
  642. $s_email_staff = 1;
  643. }
  644. $do_feeds[ $sm['id'] ] = 1;
  645. }
  646. }
  647. else
  648. {
  649. if ( $sm['email_staff_ticket_reply'] && $sm['email_notify'] )
  650. {
  651. $s_email_staff = 1;
  652. }
  653. $do_feeds[ $sm['id'] ] = 1;
  654. }
  655. if ( $s_email_staff )
  656. {
  657. $mem_offset = ( $sm['time_zone'] * 60 * 60 ) + ( $sm['dst_active'] * 60 * 60 );
  658. $replace = array(); // Initialize for Security
  659. $replace['TICKET_ID'] = $t['id'];
  660. $replace['SUBJECT'] = $t['subject'];
  661. $replace['DEPARTMENT'] = $t['dname'];
  662. $replace['PRIORITY'] = $this->ifthd->get_priority( $t['priority'] );
  663. $replace['SUB_DATE'] = $this->ifthd->ift_date( $t['date'], '', 0, 0, 1, $mem_offset, 1 );
  664. $replace['REPLY'] = $message;
  665. $replace['TICKET_LINK'] = $this->ifthd->core->cache['config']['hd_url'] ."/admin.php?section=manage&act=tickets&code=view&id=". $t['id'];
  666. $replace['MESSAGE'] = $t['message'];
  667. if ( $m['id'] )
  668. {
  669. $replace['MEMBER'] = $m['name'];
  670. }
  671. else
  672. {
  673. $replace['MEMBER'] = $email['nickname'];
  674. }
  675. $this->ifthd->send_email( $sm['id'], 'staff_reply_ticket', $replace, array( 'from_email' => $this->ifthd->core->cache['depart'][ $t['did'] ]['incoming_email'] ), 1 );
  676. }
  677. $s_email_staff = 0; // Reset
  678. }
  679. if ( is_array( $do_feeds ) )
  680. {
  681. require_once HD_SRC .'feed.php';
  682. $feed = new feed();
  683. $feed->ifthd =& $this->ifthd;
  684. while( list( $smid, ) = each( $do_feeds ) )
  685. {
  686. $feed->show_feed( 'stickets', $smid, 1 );
  687. }
  688. }
  689. }
  690. }
  691. #=============================
  692. # Update Ticket
  693. #=============================
  694. $db_array = array( 'last_reply' => time(), 'last_mid' => $m['id'], 'replies' => ( $t['replies'] + 1 ) );
  695. if ( $m['g_acp_access'] )
  696. {
  697. $db_array['last_reply_staff'] = time();
  698. $db_array['last_mname'] = $m['name'];
  699. if ( $t['status'] != 5 )
  700. {
  701. $db_array['status'] = 4;
  702. }
  703. }
  704. else
  705. {
  706. if ( $m['id'] )
  707. {
  708. $db_array['last_mname'] = $m['name'];
  709. }
  710. else
  711. {
  712. $db_array['last_mname'] = $email['nickname'];
  713. }
  714. if ( $t['status'] == 4 )
  715. {
  716. $db_array['status'] = 1;
  717. }
  718. }
  719. $this->ifthd->core->db->construct( array(
  720. 'update' => 'tickets',
  721. 'set' => $db_array,
  722. 'where' => array( 'id', '=', $t['id'] ),
  723. 'limit' => array( 1 ),
  724. ) );
  725. $this->ifthd->core->db->next_shutdown();
  726. $this->ifthd->core->db->execute();
  727. }
  728. else
  729. {
  730. #=============================
  731. # Department Security
  732. #=============================
  733. $d_allow = unserialize( $m['g_m_depart_perm'] );
  734. if ( ! $d_allow[ $d['id'] ] )
  735. {
  736. $replace = array(); // Initialize for Security
  737. if ( $m['id'] )
  738. {
  739. $this->ifthd->send_email( $m['id'], 'ticket_pipe_rejected', $replace, array( 'from_email' => $d['incoming_email'] ) );
  740. }
  741. else
  742. {
  743. $replace['MEM_NAME'] = $email['nickname'];
  744. $this->ifthd->send_guest_email( $email['from'], 'ticket_pipe_rejected', $replace, array( 'from_email' => $d['incoming_email'] ) );
  745. }
  746. $this->ifthd->log( 'security', "????? ?????? &#039;". $d['name'] ."&#039; ?????? ????????", 1, $d['id'] );
  747. return false;
  748. }
  749. #=============================
  750. # Attachment
  751. #=============================
  752. if ( $d['can_attach'] && $email['attachment_name'] )
  753. {
  754. $allowed_exts = explode( "|", $this->ifthd->core->cache['config']['upload_exts'] );
  755. $file_ext = strrchr( $email['attachment_name'], "." );
  756. if ( in_array( $file_ext, $allowed_exts ) )
  757. {
  758. if ( ( strlen( $email['attachment_content'] ) / 1024 ) <= $m['g_upload_size_max'] || ! $m['g_upload_size_max'] )
  759. {
  760. $file_safe_name = $this->sanitize_name( $email['attachment_name'] );
  761. $attachment_name = md5( 'a'. uniqid( rand(), true ) ) . $file_ext;
  762. $attachment_loc = $this->ifthd->core->cache['config']['upload_dir'] .'/'. $attachment_name;
  763. if ( @ $fp = fopen( $attachment_loc, 'a' ) )
  764. {
  765. if ( @ fwrite( $fp, $email['attachment_content'] ) )
  766. {
  767. @ fclose( $fp );
  768. $db_array = array(
  769. 'tid' => 0,
  770. 'real_name' => $attachment_name,
  771. 'original_name' => $file_safe_name,
  772. 'mid' => $m['id'],
  773. 'mname' => $m['name'],
  774. 'size' => strlen( $email['attachment_content'] ),
  775. 'mime' => $email['attachment_type'],
  776. 'date' => time(),
  777. );
  778. $this->ifthd->core->db->construct( array(
  779. 'insert' => 'attachments',
  780. 'set' => $db_array,
  781. ) );
  782. $this->ifthd->core->db->execute();
  783. $attachment_id = $this->ifthd->core->db->get_insert_id();
  784. $this->ifthd->log( 'member', "????????? ???????? #". $attachment_id, 1, $attachment_id );
  785. }
  786. }
  787. }
  788. }
  789. }
  790. #=============================
  791. # Create Ticket
  792. #=============================
  793. $db_array = array(
  794. 'did' => $d['id'],
  795. 'dname' => $d['name'],
  796. 'mid' => $m['id'],
  797. 'mname' => $m['name'],
  798. 'email' => $email['from'],
  799. 'subject' => $email['subject'],
  800. 'priority' => 2,
  801. 'message' => $message,
  802. 'date' => time(),
  803. 'last_reply' => time(),
  804. 'last_mid' => $m['id'],
  805. 'last_mname' => $m['name'],
  806. 'ipadd' => $this->ifthd->input['ip_address'],
  807. 'status' => 1,
  808. 'attach_id' => $attachment_id,
  809. );
  810. if ( ! $m['id'] )
  811. {
  812. $db_array['tkey'] = substr( md5( 'tk' . uniqid( rand(), true ) . time() ), 0, 11 );
  813. $db_array['mname'] = $email['nickname'];
  814. $db_array['last_mname'] = $email['nickname'];
  815. $db_array['guest'] = 1;
  816. $db_array['guest_email'] = 1;
  817. }
  818. if ( $d['auto_assign'] )
  819. {
  820. $db_array['amid'] = $d['auto_assign'];
  821. $db_array['amname'] = $this->ifthd->core->cache['staff'][ $d['auto_assign'] ]['name'];
  822. }
  823. $this->ifthd->core->db->construct( array(
  824. 'insert' => 'tickets',
  825. 'set' => $db_array,
  826. ) );
  827. $this->ifthd->core->db->execute();
  828. $ticket_id = $this->ifthd->core->db->get_insert_id();
  829. $this->ifthd->log( 'member', "?????? ?????? &#039;". $email['subject'] ."&#039;", 1, $ticket_id );
  830. $this->ifthd->log( 'ticket', "?????? ?????? &#039;". $email['subject'] ."&#039;", 1, $ticket_id );
  831. #=============================
  832. # Update Attachment
  833. #=============================
  834. if ( $attachment_id )
  835. {
  836. $this->ifthd->core->db->construct( array(
  837. 'update' => 'attachments',
  838. 'set' => array( 'tid' => $ticket_id ),
  839. 'where' => array( 'id', '=', $attachment_id ),
  840. 'limit' => array( 1 ),
  841. ) );
  842. $this->ifthd->core->db->next_shutdown();
  843. $this->ifthd->core->db->execute();
  844. $this->ifthd->log( 'ticket', "????????? ???????? #". $attachment_id, 1, $ticket_id );
  845. }
  846. #=============================
  847. # Update Member
  848. #=============================
  849. if ( $m['id'] )
  850. {
  851. $this->ifthd->core->db->next_no_quotes('set');
  852. $this->ifthd->core->db->construct( array(
  853. 'update' => 'members',
  854. 'set' => array( 'open_tickets' => 'open_tickets+1', 'tickets' => 'tickets+1' ),
  855. 'where' => array( 'id', '=', $m['id'] ),
  856. 'limit' => array( 1 ),
  857. ) );
  858. $this->ifthd->core->db->next_shutdown();
  859. $this->ifthd->core->db->execute();
  860. }
  861. #=============================
  862. # Update Department
  863. #=============================
  864. $this->ifthd->core->db->next_no_quotes('set');
  865. $this->ifthd->core->db->construct( array(
  866. 'update' => 'departments',
  867. 'set' => array( 'tickets' => 'tickets+1' ),
  868. 'where' => array( 'id', '=', $d['id'] ),
  869. 'limit' => array( 1 ),
  870. ) );
  871. $this->ifthd->core->db->next_shutdown();
  872. $this->ifthd->core->db->execute();
  873. #=============================
  874. # Send Email
  875. #=============================
  876. if ( $m['id'] )
  877. {
  878. $mem_offset = ( $m['time_zone'] * 60 * 60 ) + ( $m['dst_active'] * 60 * 60 );
  879. $replace = array(); // Initialize for Security
  880. $replace['TICKET_ID'] = $ticket_id;
  881. $replace['SUBJECT'] = $email['subject'];
  882. $replace['DEPARTMENT'] = $d['name'];
  883. $replace['PRIORITY'] = $this->ifthd->get_priority( 2 );
  884. $replace['SUB_DATE'] = $this->ifthd->ift_date( time(), '', 0, 0, 1, $mem_offset, 1 );
  885. $replace['TICKET_LINK'] = $this->ifthd->core->cache['config']['hd_url'] ."/index.php?act=tickets&code=view&id=". $ticket_id;
  886. $replace['MESSAGE'] = $message;
  887. $this->ifthd->send_email( $m['id'], 'new_ticket', $replace, array( 'from_email' => $d['incoming_email'] ), 1 );
  888. }
  889. #=============================
  890. # Send Guest Email
  891. #=============================
  892. if ( ! $m['id'] && $this->ifthd->core->cache['config']['guest_ticket_emails'] )
  893. {
  894. $replace = array(); // Initialize for Security
  895. $replace['TICKET_ID'] = $ticket_id;
  896. $replace['SUBJECT'] = $email['subject'];
  897. $replace['DEPARTMENT'] = $d['name'];
  898. $replace['PRIORITY'] = $this->ifthd->get_priority( 2 );
  899. $replace['SUB_DATE'] = $this->ifthd->ift_date( time() );
  900. $replace['TICKET_LINK'] = $this->ifthd->core->cache['config']['hd_url'] ."/index.php?act=tickets&code=view&id=". $ticket_id ."&email=". urlencode( $db_array['email'] ) ."&key=". $db_array['tkey'];
  901. $replace['MEM_NAME'] = $email['nickname'];
  902. $replace['TICKET_KEY'] = $db_array['tkey'];
  903. $replace['MESSAGE'] = $message;
  904. $this->ifthd->send_guest_email( $email['from'], 'new_guest_ticket', $replace, array( 'from_email' => $d['incoming_email'] ), 1 );
  905. }
  906. #=============================
  907. # Email Staff
  908. #=============================
  909. $this->ifthd->core->db->construct( array(
  910. 'select' => array( 'm' => array( 'id', 'mgroup', 'email_notify', 'email_staff_new_ticket', 'time_zone', 'dst_active' ),
  911. 'g' => array( 'g_depart_perm' ),
  912. ),
  913. 'from' => array( 'm' => 'members' ),
  914. 'join' => array( array( 'from' => array( 'g' => 'groups' ), 'where' => array( 'g' => 'g_id', '=', 'm' => 'mgroup' ) ) ),
  915. 'where' => array( array( 'g' => 'g_acp_access' ), '=', 1 ),
  916. ) );
  917. $staff_sql = $this->ifthd->core->db->execute();
  918. if ( $this->ifthd->core->db->get_num_rows($staff_sql) )
  919. {
  920. while( $sm = $this->ifthd->core->db->fetch_row($staff_sql) )
  921. {
  922. // Check Departments
  923. if ( is_array( unserialize( $sm['g_depart_perm'] ) ) )
  924. {
  925. $my_departs = "";
  926. $my_departs = unserialize( $sm['g_depart_perm'] );
  927. if ( $my_departs[ $d['id'] ] )
  928. {
  929. if ( $sm['email_staff_new_ticket'] && $sm['email_notify'] )
  930. {
  931. $s_email_staff = 1;
  932. }
  933. $do_feeds[ $sm['id'] ] = 1;
  934. }
  935. }
  936. else
  937. {
  938. if ( $sm['email_staff_new_ticket'] && $sm['email_notify'] )
  939. {
  940. $s_email_staff = 1;
  941. }
  942. $do_feeds[ $sm['id'] ] = 1;
  943. }
  944. if ( $s_email_staff )
  945. {
  946. $mem_offset = ( $sm['time_zone'] * 60 * 60 ) + ( $sm['dst_active'] * 60 * 60 );
  947. $replace = array(); // Initialize for Security
  948. $replace['TICKET_ID'] = $ticket_id;
  949. $replace['SUBJECT'] = $email['subject'];
  950. $replace['DEPARTMENT'] = $d['name'];
  951. $replace['PRIORITY'] = $this->ifthd->get_priority( 2 );
  952. $replace['SUB_DATE'] = $this->ifthd->ift_date( time(), '', 0, 0, 1, $mem_offset, 1 );
  953. $replace['MESSAGE'] = $message;
  954. $replace['TICKET_LINK'] = $this->ifthd->core->cache['config']['hd_url'] ."/admin.php?section=manage&act=tickets&code=view&id=". $ticket_id;
  955. if ( $m['id'] )
  956. {
  957. $replace['MEMBER'] = $m['name'];
  958. $this->ifthd->send_email( $sm['id'], 'staff_new_ticket', $replace, array( 'from_email' => $d['incoming_email'] ), 1 );
  959. }
  960. else
  961. {
  962. $replace['MEMBER'] = $email['nickname'];
  963. $this->ifthd->send_email( $sm['id'], 'staff_new_guest_ticket', $replace, array( 'from_email' => $d['incoming_email'] ), 1 );
  964. }
  965. }
  966. $s_email_staff = 0; // Reset
  967. }
  968. }
  969. if ( is_array( $do_feeds ) )
  970. {
  971. require_once HD_SRC .'feed.php';
  972. $feed = new feed();
  973. $feed->ifthd =& $this->ifthd;
  974. while( list( $smid, ) = each( $do_feeds ) )
  975. {
  976. $feed->show_feed( 'stickets', $smid, 1 );
  977. }
  978. }
  979. if ( $d['auto_assign'] )
  980. {
  981. $this->ifthd->core->db->construct( array(
  982. 'update' => 'members',
  983. 'set' => array( 'assigned' => ( $this->ifthd->core->cache['staff'][ $d['auto_assign'] ]['assigned'] + 1 ) ),
  984. 'where' => array( 'id', '=', $d['auto_assign'] ),
  985. ) );
  986. $this->ifthd->core->db->execute();
  987. $this->ifthd->rebuild_staff_cache();
  988. }
  989. }
  990. #=============================
  991. # Update Stats
  992. #=============================
  993. $this->ifthd->r_ticket_stats(1);
  994. }
  995. #=============================
  996. # Sanitize Name
  997. #=============================
  998. function sanitize_name($name)
  999. {
  1000. $name = str_replace( " ", "_", $name );
  1001. return ereg_replace( "[^A-Za-z0-9_\.]", "", $name );
  1002. }
  1003. #=============================
  1004. # Close Tags
  1005. #=============================
  1006. function closetags($html)
  1007. {
  1008. $html = $this->ifthd->convert_html( $html );
  1009. # Strip any mangled tags off the end
  1010. $html=preg_replace("#]*$#", " ", $html);
  1011. #put all opened tags into an array
  1012. preg_match_all ( "#<([a-z]+)( .*)?(?!/)>#iU", $html, $result );
  1013. $openedtags = $result[1];
  1014. $openedtags = array_diff($openedtags, array("img", "hr", "br"));
  1015. $openedtags = array_values($openedtags);
  1016. #put all closed tags into an array
  1017. preg_match_all ( "#</([a-z]+)>#iU", $html, $result );
  1018. $closedtags = $result[1];
  1019. $len_opened = count ( $openedtags );
  1020. # all tags are closed
  1021. if( count ( $closedtags ) == $len_opened )
  1022. {
  1023. return $html;
  1024. }
  1025. $openedtags = array_reverse ( $openedtags );
  1026. # close tags
  1027. for( $i = 0; $i < $len_opened; $i++ )
  1028. {
  1029. if ( !in_array ( $openedtags[$i], $closedtags ) )
  1030. {
  1031. $html .= "</" . $openedtags[$i] . ">";
  1032. }
  1033. else
  1034. {
  1035. unset ( $closedtags[array_search ( $openedtags[$i], $closedtags)] );
  1036. }
  1037. }
  1038. return $this->ifthd->sanitize_data( $html );
  1039. }
  1040. }
  1041. ?>