function register($invite_md5 = '')
 {
     //check if user logged in
     //session_start();  // this can't do, or the original session will b lost
     $log_info = 'in register, ip:' . $this->request->clientIp();
     $reg_refer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'not set';
     $log_info .= ', refer:' . $reg_refer;
     CakeLog::write('info', $log_info);
     $log_info = '';
     if ($this->Session->read('uid')) {
         $this->redirect(array("controller" => "users", "action" => "ucenter"));
     }
     $money = $this->Session->read('money');
     if ($money) {
         $this->set('remindInfo', '注册成功后¥' . $money . '将存入您的账户');
     }
     $inviting_user = array();
     if ($invite_md5 != '') {
         // user visit from shared inviting page
         // this code block writes log and insert db record,
         //      avoid attack !!!
         do {
             // check if invite_md5 correct
             $conditions = array('uniq_md5' => $invite_md5);
             $inviting_user = $this->User->find('first', array('conditions' => $conditions));
             // not exists
             if (empty($inviting_user)) {
                 $log_str = sprintf('ip[%s] invite_md5[%s] find ' . 'no inviting user', $this->request->clientIp(), $invite_md5);
                 Cakelog::write('warning', $log_str);
                 // reset invite_md5 to avoid following process
                 $invite_md5 = '';
                 break;
             }
             // if the distinct ip much more less than visit count,
             //  we regard it as an attack.
             //    i.e. visit_count / ip_count > threshold in a day,
             //          disable insert
             $time_start = date('Y-m-d 00:00:00', time());
             $select_cond = array('invite_md5' => $invite_md5, 'created >=' => $time_start);
             $this->loadModel('Ivisit');
             $visited_total = $this->Ivisit->find('count', array('conditions' => $select_cond));
             $distinct_ip_total = $this->Ivisit->find('count', array('fields' => 'distinct req_ip', 'conditions' => $select_cond));
             if ($distinct_ip_total > 0) {
                 $ratio = $visited_total / $distinct_ip_total;
                 $log_str = sprintf('daily visited/disctinct [%s], threshold[%s]', $ratio, $this->VISIT_RATIO_THRESHOLD);
                 CakeLog::write('debug', $log_str);
                 if ($ratio >= $this->VISIT_RATIO_THRESHOLD) {
                     break;
                 }
             }
             // record this visit
             $data_row = array('req_ip' => $this->request->clientIp(), 'invite_md5' => $invite_md5);
             $save_res = $this->Ivisit->save($data_row);
             $money = Configure::read('register_user_money') / 100;
             $this->Session->write('invite_md5', $invite_md5);
             $this->set('invite_info', '注册成功后¥' . $money . '将存入您的账户');
             $log_str = sprintf('ip[%s] invite_md5[%s] save to ivisit res[%s].', $this->request->clientIp(), $data_row['invite_md5'], $save_res['Ivisit']['id']);
             CakeLog::write('debug', $log_str);
         } while (0);
     }
     $this->set('title_for_layout', "User::register|倚天剑shadow - 提供shadowsocks科学上(翻)网(墙)账号!倚天剑shadow|shadowsocks账号|免费shadowsocks账号");
     //var_dump($this->request->data);
     $err = 0;
     // no error
     $msg = "";
     $isPost = $this->request->is('post');
     //var_dump(CakeSession::read('vcode'));
     //var_dump($_SESSION['vcode']);
     if ($isPost) {
         $rdata = $this->request->data;
         //verify check code
         if (empty($rdata['checkcode']) || 0 != strcasecmp($rdata['checkcode'], $this->Session->read('vcode'))) {
             $err = 4;
             $msg = '验证码错误!';
         }
         CakeSession::write('vcode', '');
         if ($rdata['password'] != $rdata['password2']) {
             $err = 1;
             $msg = "密码输入不一致!";
         }
         //$pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i";
         $pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,7}(\\.[a-z]{2})?)\$/i";
         // allow user register with both email and telephone
         $tel_pattern = '#1[\\d]{10}#';
         if (!preg_match($pattern, $rdata['email']) && !preg_match($tel_pattern, $rdata['email'])) {
             $err = 2;
             $msg = "邮箱格式或电话号码错误 !";
         }
         if ($err == 0) {
             $existEmail = $this->User->find('first', array('conditions' => array('email' => $rdata['email'])));
             //var_dump($existEmail);
             //var_dump($existEmail['User']['uid']);
             $datetime = date("Y-m-d H:i:s", time());
             //var_dump($datetime);
             if (count($existEmail) > 0) {
                 $err = 3;
                 $msg = "用户已注册!";
             }
         }
     }
     if ($isPost && $err == 0) {
         //data validated ok
         //insert into db, get user loged in
         $datetime = date("Y-m-d H:i:s", time());
         $data_row = array('email' => $rdata['email'], 'password' => md5($rdata['password']));
         if (Configure::read('open_invite') > 0) {
             $md5_field = sprintf('%d,%s,%s', rand(1000, 9999), $this->request->clientIp(), $rdata['email']);
             $data_row['uniq_md5'] = md5($md5_field);
             $data_row['reg_ip'] = $this->request->clientIp();
         }
         //save_res is the whole data_row
         $save_res = $this->User->save($data_row);
         //var_dump($save_res);
         //var_dump($data_row);
         if ($save_res) {
             //after save, cake return the id of the recored
             //table 'uid' while cake uses 'id' for prod env
             $uid = $save_res['User']['id'];
             if (empty($uid)) {
                 //Mac dev enviroment use uid
                 CakeLog::write('warning', 'get uid from save_res empty');
                 $uid = $save_res['User']['uid'];
             }
             //var_dump($uid); //null
             //var_dump($save_res['User']['uid']); //userid
             $this->Session->write('uid', $uid);
             $this->Session->write('username', $rdata['email']);
             //unset vcode to avoid attack
             $this->Session->write('vcode', '');
             //var_dump($this->Session->read('uid'));
             //var_dump($save_res);
             $this->log('register success,email=' . $rdata['email'], 'info');
             // register ok. process inviting related logic
             //      1. add a voucher to registered user
             //      2. add invite_num to inviting user in cake_users
             $invite_md5 = $this->Session->read('invite_md5');
             if (Configure::read('open_invite') > 0 && $invite_md5 != '') {
                 $this->loadModel('Voucher');
                 $conditions = array('uniq_md5' => $invite_md5);
                 $inviting_user = $this->User->find('first', array('conditions' => $conditions));
                 $inviting_uid = $inviting_user['User']['uid'];
                 $date_time_now = date('Y-m-d H:i:s', time());
                 $md5_source = sprintf('%d-%s-%s-%s', $uid, $rdata['email'], $date_time_now, $this->request->clientIp());
                 // for registering user
                 $expire_after_k_days = 7;
                 $expire_datetime = date('Y-m-d H:i:s', strtotime("+{$expire_after_k_days} day"));
                 $data_row = array('md5str' => md5($md5_source), 'uid' => $uid, 'from_uid' => $inviting_uid, 'get_from' => $this->VOUCHER_VIA_REGISTER, 'expire' => $expire_datetime, 'amount' => Configure::read('register_user_money'), 'is_valid' => $this->VOUCHER_VALID);
                 $save_res = $this->Voucher->save($data_row);
                 if (empty($save_res)) {
                     $log_str = sprintf('save voucher failed, user[%d]', $uid);
                     CakeLog::write('warning', $log_str);
                 }
                 // increase invite_num field.
                 //  the following code block doesn't work on 2t-vps[ubuntu]
                 //      while works on Mac dev env
                 //                    $this->User->id = $inviting_user['User']['uid'];
                 //                    $invite_num = $inviting_user['User']['invite_num'] + 1;
                 //                    $this->User->saveField('invite_num', $invite_num);
                 $update_fields = array('invite_num' => $inviting_user['User']['invite_num'] + 1);
                 $update_cond = array('uid' => $inviting_user['User']['uid']);
                 $up_res = $this->User->updateAll($update_fields, $update_cond);
                 $log_str = sprintf('invite success, new user[%d]' . ' update invite_num result[%s]', $uid, $up_res);
                 CakeLog::write('debug', $log_str);
             }
             $this->assign_money2user();
             return $this->redirect(array("controller" => "users", "action" => "ucenter"));
         } else {
             $err = 5;
             $msg = "系统忙,注册失败!";
         }
         //            return $this->redirect(
         //                array("controller" => "users", "action" => "ucenter")
         //            );
     }
     if ($err > 0) {
         $this->set('isError', $err);
         $this->set('errMsg', $msg);
         $this->log('in register, err:' . $err . ', msg:' . $msg, 'warn');
     }
 }
 /**
  * Wrapper of CakeEmail object creation and submission.
  * @param $emailData
  * @param string $templateName
  * @param string $to
  * @param string $subjectBlockName
  * @param string $tag
  * @param string $locale
  * @param bool $debug
  * @param array $emailOptions
  * @return string
  * @throws Exception
  */
 public static function sendEmail($emailData, $templateName = '', $to = '', $subjectBlockName = '', $tag = '', $locale = 'en-US', $debug = false, $emailOptions = array())
 {
     if (empty($templateName) || empty($to) || empty($subjectBlockName)) {
         CakeLog::error('CRITICAL EXEPTION: In email library.');
         CakeLog::error('Empty argument passed to email sender.');
         throw new BadMethodCallException('Empty argument passed to email sender.', 1);
         return false;
     }
     // Since getting the data from Drupal happens in-line we need to check
     // for errors by seeing if we only get log_info back and nothing else.
     if (!empty($tag)) {
         $drupalData = array();
         DruniqueAPIUtil::getData(['api_url' => 'email_text.json', 'params' => ['tag' => $tag], 'locale' => $locale], $drupalData);
         if (sizeof($drupalData) <= 1) {
             CakeLog::error('CRITICAL EXEPTION: In email library.');
             CakeLog::error('Unable to get view variables from CMS.');
             throw new Exception('Unable to get view variables from CMS.', 1);
             return false;
         }
         $emailData['email_text'] = $drupalData;
     }
     $email = new CakeEmail('default');
     $subject = DruniqueAPIUtil::content($subjectBlockName, $emailData['email_text']);
     $subject = preg_replace('/[\\pZ\\pC]/u', ' ', $subject);
     if ($debug) {
         $email->transport('Debug');
     }
     // Make sure format is set correctly based on existence of templates.
     $format = 'both';
     $htmlTemplateExists = is_readable(APP . "View/Emails/html/{$templateName}.ctp");
     $textTemplateExists = is_readable(APP . "View/Emails/text/{$templateName}.ctp");
     if (!$htmlTemplateExists && !$textTemplateExists) {
         CakeLog::error('CRITICAL ERROR: In email library.');
         CakeLog::error("Unable to find email template named {$templateName}.ctp");
         return false;
     } elseif (!$htmlTemplateExists && $textTemplateExists) {
         $format = 'text';
     } elseif ($htmlTemplateExists && !$textTemplateExists) {
         $format = 'html';
     }
     $email->template($templateName, 'default')->emailFormat($format)->to($to)->subject(html_entity_decode($subject, ENT_QUOTES))->viewVars($emailData);
     if (isset($emailOptions['bcc'])) {
         $email->bcc($emailOptions['bcc']);
     }
     if (isset($emailOptions['cc'])) {
         $email->cc($emailOptions['cc']);
     }
     try {
         $response = $email->send();
         if ($debug) {
             return $response;
         }
         if ($response) {
             $result = 'Email was sent successfully';
         } else {
             $result = 'Email failed to send without exceptions';
             CakeLog::error('CRITICAL ERROR: Email library failed to send an email without exception.');
             Cakelog::error(print_r($email, true));
         }
     } catch (Exception $e) {
         $result = 'Email failed with exception: ' . print_r($e->getMessage(), true);
         CakeLog::error('CRITICAL ERROR: In email library.');
         CakeLog::error($e->getMessage());
     }
     return $result;
 }