/**
  * Static function to refresh src_org_cache from src_org
  *
  * @param Source|src_id|src_uuid $source
  * @return int number of rows cached
  */
 public static function refresh_cache($source)
 {
     $conn = AIR2_DBManager::get_master_connection();
     // get the src_id
     $src_id;
     if (is_numeric($source)) {
         $src_id = $source;
     } elseif (is_string($source)) {
         $q = 'select src_id from source where src_uuid = ?';
         $src_id = $conn->fetchOne($q, array($source), 0);
     } elseif (is_object($source)) {
         $src_id = $source->src_id;
     }
     // sanity!
     if (!$src_id) {
         Carper::carp("Source !exists");
         return;
     }
     // delete all src_org_cache recs for this source
     $conn->execute("delete from src_org_cache where soc_src_id = {$src_id}");
     // array of org_id => status
     $org_status = Source::get_authz_status($src_id);
     // bulk-insert
     $vals = array();
     foreach ($org_status as $org_id => $status) {
         $vals[] = "({$src_id},{$org_id},'{$status}')";
     }
     if (count($vals)) {
         $vals = implode(',', $vals);
         $stmt = "insert into src_org_cache (soc_src_id, soc_org_id, soc_status)";
         $conn->execute("{$stmt} values {$vals}");
     }
     return count($vals);
 }
 /**
  * initialize security for this controller
  *
  * This function determines what (if any) security the user has and
  * encapsulates it in the $AIR2User class variable.  Will return a
  * login page and exit if the user cannot be authenticated.
  *
  * @access private
  * @return void
  */
 public function init_security()
 {
     // load required libraries
     $this->authuser = new $this->auth_user_class();
     // check if the credentials were good
     if (!$this->authuser->has_valid_tkt() || !$this->authuser->get_user()) {
         // user not authenticated
         $this_uri = current_url() . '?' . $this->input->server('QUERY_STRING');
         Carper::carp("Permission denied for {$this_uri}");
         $uri = $this->uri_for('login', array('back' => $this_uri));
         //echo "Location: $uri\n";
         redirect($uri);
         exit(0);
     }
     // authn ok
     return true;
 }
 /**
  * Calls confess() and exit(1);
  *
  * @param unknown $message
  */
 public static function croak($message)
 {
     Carper::confess($message);
     exit(1);
 }
 /**
  * Loads login view and authenticate users
  *
  * we do explicit load->view calls here because the login screen is
  * independent of the rest of the View architecture.
  */
 public function index()
 {
     // redirect to original request, or home page
     $back = $this->input->get_post('back');
     if (!isset($back) || !strlen($back)) {
         $back = site_url('');
     }
     // admin allows overriding PIN SSO
     $admin = false;
     if (isset($this->input_all['admin']) && $this->input_all['admin']) {
         $admin = true;
     }
     if (isset($_GET['admin']) && $_GET['admin']) {
         $admin = true;
     }
     // create stash
     $stash = array('static_url' => site_url(), 'back' => $back, 'c' => $this, 'admin' => $admin);
     // GET requests show a login form
     if ($this->method == 'GET') {
         // special case.
         // if we are configured to trust the PIN SSO tkt (auth_tkt)
         // then check for it and use its "sso" data value
         // as the AIR2 username
         if (AIR2_PIN_SSO_TRUST && !$admin) {
             $tkt = $this->input->cookie(AIR2_PIN_SSO_TKT);
             if (!$tkt) {
                 $tkt = $this->input->get_post(AIR2_PIN_SSO_TKT);
             }
             if ($tkt) {
                 $at = new Apache_AuthTkt(array('conf' => AIR2_PIN_SSO_CONFIG, 'encrypt_data' => false));
                 //Carper::carp("got auth_tkt for trust pin sso");
                 if ($at->validate_ticket($tkt)) {
                     $tkt_info = $at->parse_ticket($tkt);
                     $tkt_data = json_decode($tkt_info['data'], true);
                     if (isset($tkt_data['sso'])) {
                         $username = $tkt_data['sso'];
                         $user = $this->_fetch_user($username);
                         if ($user) {
                             // trust prior authentication. create the AIR2 tkt.
                             $this->airuser->create_tkt($user, true, true);
                             $user->user_login_dtim = air2_date();
                             $user->save();
                             //echo "Location: $back\n";
                             redirect($back);
                         } else {
                             Carper::carp("Invalid user in tkt");
                             redirect(AIR2_PIN_SSO_URL . '?back=' . $back);
                         }
                     } else {
                         Carper::carp("Missing sso param in tkt");
                         redirect(AIR2_PIN_SSO_URL . '?back=' . $back);
                     }
                 } else {
                     Carper::carp("Invalid tkt");
                     redirect(AIR2_PIN_SSO_URL . '?back=' . $back);
                 }
             } else {
                 // no PIN tkt; redirect to PIN login
                 Carper::carp("No PIN SSO tkt");
                 redirect(AIR2_PIN_SSO_URL . '?back=' . $back);
             }
         }
         // print form
         $this->load->view('login', $stash);
     } elseif ($this->method == 'POST') {
         header('Access-Control-Allow-Origin: *');
         // allow external
         $uname = isset($this->input_all['username']) ? $this->input_all['username'] : null;
         // #9505 - xss-filter messes up passwords, so get raw input
         $pwd = isset($_POST['password']) ? $_POST['password'] : null;
         // didn't enter username or password
         if (!$uname || !$pwd || strlen($uname) < 1 || strlen($pwd) < 1) {
             if ($this->view == "json") {
                 header('X-AIR2: authentication failed', false, 400);
                 $resp = array('success' => false, 'message' => 'invalid request');
                 print json_encode($resp);
             } elseif ($this->view == "xml") {
                 header('X-AIR2: authentication failed', false, 400);
                 // TODO use 'xml' view
                 print "<air2><success>false</success><message>invalid request</message></air2>";
             } else {
                 $stash['errormsg'] = 'You must enter both a username and password';
                 $this->load->view('login', $stash);
             }
             return;
         }
         // bad username
         $user = $this->_fetch_user($uname);
         if (!$user || !$user->exists()) {
             if ($this->view == "json") {
                 header('X-AIR2: authentication failed', false, 401);
                 $resp = array('success' => false, 'message' => 'authentication failed');
                 print json_encode($resp);
                 return;
             } elseif ($this->view == "xml") {
                 header('X-AIR2: authentication failed', false, 401);
                 // TODO use 'xml' view
                 print "<air2><success>false</success><message>authentication failed</message></air2>";
                 return;
             } else {
                 $stash['errormsg'] = 'The information you entered does not match an active account';
                 $this->load->view('login', $stash);
                 return;
             }
         }
         // delegate to PIN SSO?
         $pw_ok = false;
         // the !$admin means we avoid infinite loop with the SSO service,
         // which just points back here.
         if (AIR2_PIN_SSO_TRUST && !$admin) {
             $pw_ok = $this->check_pin_sso($uname, $pwd);
         } else {
             $pw_ok = $user->check_password($pwd);
         }
         // bad password
         if (!$pw_ok) {
             if ($this->view == "json") {
                 header('X-AIR2: authentication failed', false, 401);
                 $resp = array('success' => false, 'message' => 'authentication failed');
                 print json_encode($resp);
                 return;
             } elseif ($this->view == "xml") {
                 header('X-AIR2: authentication failed', false, 401);
                 // TODO use 'xml' view
                 print "<air2><success>false</success><message>authentication failed</message></air2>";
                 return;
             } else {
                 $stash['errormsg'] = 'The information you entered does not match an active account';
                 $this->load->view('login', $stash);
                 //TODO -- form error msg
                 return;
             }
         }
         // authenticated ok. create the tkt.
         $tkt = $this->airuser->create_tkt($user, true, true);
         $user->user_login_dtim = air2_date();
         $user->save();
         // non-html response does not redirect
         if ($this->view == "json") {
             $tkt['success'] = true;
             print json_encode($tkt);
             return;
         } elseif ($this->view == "xml") {
             header('X-AIR2: authentication failed', false, 401);
             // TODO use 'xml' view
             print "<air2><success>true</success><air2_tkt>" . $tkt['air2_tkt'] . "</air2_tkt></air2>";
             return;
         } else {
             redirect($back);
         }
     }
 }
 /**
  * Fix the question sequence numbers for this query, given the question
  * that has changed, and its new sequence number.
  *
  * @param Question $ques
  * @param int     $seq
  */
 protected function _fix_sequence(Question $ques = null, $seq = null)
 {
     if ($ques) {
         if (!is_int($seq) || $seq < 1) {
             throw new Rframe_Exception(Rframe::BAD_DATA, "Invalid sequence '{$seq}'");
         }
         $ques->ques_dis_seq = $seq;
     }
     // get all existing questions
     $q = Doctrine_Query::create()->from('Question q');
     //         $q->setConnection(AIR2_DBManager::get_master_connection());
     $q->where('q.ques_inq_id = ?', $this->parent_rec->inq_id);
     if ($ques && $ques->ques_id) {
         $q->addWhere('q.ques_id != ?', $ques->ques_id);
     }
     $q->orderBy('q.ques_dis_seq asc');
     $rs = $q->execute();
     $current_seq_num = 1;
     foreach ($rs as $idx => $rec) {
         if ($current_seq_num == $seq) {
             $current_seq_num++;
         }
         // update and save
         $rec->ques_dis_seq = $current_seq_num;
         // compensate for doctrines agressive caching
         if ($rec->exists()) {
             $rec->save();
         } else {
             Carper::carp("tried to reorder a non-existant question " . "ques_uuid:{$rec->ques_uuid} ques_id:{$rec->ques_id} " . "ques_value:{$rec->ques_value} of inquery {$rec->ques_inq_id}");
         }
         $current_seq_num++;
     }
 }
 /**
  * Create all the normalized sizes for the Image. Called by postSave().
  */
 public function make_sizes()
 {
     if (!isset($this->_set_image)) {
         Carper::croak("image not set for " . $this->img_uuid);
     }
     $dir = self::get_directory($this->img_ref_type, $this->img_uuid);
     $ext = self::$CONFIG[$this->img_ref_type]['convert_to'];
     $name = self::$CONFIG[$this->img_ref_type]['filename'];
     // remove old files, and copy a new one
     array_map("unlink", glob("{$dir}/*"));
     $fname = $this->img_file_name;
     copy($this->_set_image, "{$dir}{$fname}");
     // convert at full resolution
     $p = new phMagick($this->_set_image, "{$dir}{$name}.{$ext}");
     $p->convert();
     // resized versions
     foreach (self::$CONFIG[$this->img_ref_type]['sizes'] as $size => $dim) {
         $p = new phMagick($this->_set_image, "{$dir}{$name}_{$size}.{$ext}");
         if ($dim[0] == 0 || $dim[1] == 0) {
             $p->resize($dim[0], $dim[1]);
         } elseif (is_a($this, 'ImageOrgLogo')) {
             $p->resize($dim[0], $dim[1]);
         } else {
             $p->resizeExactly($dim[0], $dim[1]);
         }
     }
     $this->_set_image = false;
 }
 /**
  * DO THE RIGHT THING with an Exception, depending on what environment
  * we're running in.
  *
  * @param Exception $e
  */
 function show_exception(Exception $e)
 {
     $msg = 'There was an error';
     if (defined('AIR2_ENVIRONMENT') && AIR2_ENVIRONMENT != 'prod') {
         $msg = $e->__toString();
     } else {
         Carper::carp($e->__toString());
     }
     $this->show_error('An error was encountered', $msg);
 }
 /**
  *
  *
  * @return array $locked
  */
 public static function get_locked()
 {
     Carper::croak("rewrite get_locked to use AIR2_Query dql");
     $proto = new JobQueue();
     $jobs = $proto->fetchAll("where jq_start_dtim is not null and jq_complete_dtim is null");
     $locked = array();
     while ($job = $jobs->next()) {
         $locked[] = $job;
     }
     return $locked;
 }
 /**
  * initialize security for this controller
  *
  * This function determines what (if any) security the user has and
  * encapsulates it in the $AIR2User class variable.  Will return a
  * login page and exit if the user cannot be authenticated.
  *
  * @access private
  * @return void
  */
 private function _init_security()
 {
     // check if the credentials were good
     if (!$this->airuser->has_valid_tkt() || !$this->airuser->get_user()) {
         // user not authenticated
         $this_uri = current_url() . '?' . $this->input->server('QUERY_STRING');
         //Carper::carp("Permission denied for $this_uri");
         $uri = $this->uri_for('login', array('back' => $this_uri));
         //echo "Location: $uri\n";
         redirect($uri);
         exit(0);
     }
     // ok credentials. does the user have min authz?
     $air2_user = $this->airuser->get_user();
     // skip authz check if SYSTEM or TEST user
     // TODO the TEST type really ought to be tested here as well
     // but that will require audit of existing unit tests.
     if ($air2_user['user_type'] != 'S' && $air2_user['user_type'] != 'T') {
         $cum_authz = 0;
         foreach ($air2_user->get_authz() as $org_id => $bitmask) {
             $cum_authz += $bitmask;
         }
         if ($cum_authz == 0) {
             Carper::carp("authn ok for " . $air2_user->user_username . " type=" . $air2_user['user_type'] . " but no authz");
             show_error('Insufficient authz', 403);
         }
     }
     //set global remote user ID and TYPE (for upd/cre user stamps)
     define('AIR2_REMOTE_USER_ID', $this->airuser->get_id());
     define('AIR2_REMOTE_USER_TYPE', $air2_user['user_type']);
     // enable activity logging
     // TODO: where else can this go? Would it be better to default to true?
     AIR2Logger::$ENABLE_LOGGING = true;
     // authn ok
     return true;
 }