/**
  * Perform some command line options for the BinField page
  * @param array $args
  * @param array $request_remainder
  */
 public function actionCommandLine($args, $request_remainder)
 {
     $action = array_shift($request_remainder);
     switch ($action) {
         case "migrate":
             $config = I2CE::getConfig()->traverse('/modules/BinField/store');
             $config_top = I2CE::getConfig();
             $mech = 'db';
             $config->setIfIsSet($mech, 'mechanism');
             if ($mech != 'file') {
                 echo "This migration only works when you've set your binary file storage to file.\n";
                 return;
             }
             $migrated = 0;
             $config->setIfIsSet($migrated, 'migrated_to_file');
             if ($migrated) {
                 echo "The migration has already occurred.\n";
                 return;
             }
             $db = MDB2::singleton();
             $get_field_info = $db->prepare("SELECT ff.id as ff_id,ff.field as field_id,field.name as field,field.type AS type,ff.form as form_id,form.name as form FROM form_field ff JOIN field ON field.id = ff.field JOIN form ON form.id = ff.form WHERE ff.id = ?", array('integer'), array('integer', 'integer', 'text', 'text', 'integer', 'text'));
             if (I2CE::pearError($get_field_info, "Unable to prepare statement for field info lookup: ")) {
                 die;
             }
             $find_string_field = $db->prepare("SELECT id from field WHERE name = ? AND type = 'string'", array('text'), array('integer'));
             if (I2CE::pearError($find_string_field, "Unable to prepare statement for new field lookup: ")) {
                 die;
             }
             $update_ff = $db->prepare("UPDATE form_field SET field = ? WHERE id = ?", array('integer', 'integer'));
             if (I2CE::pearError($update_ff, "Unable to prepare statement for updating form field: ")) {
                 die;
             }
             $updates = array();
             $updates['last_entry'] = $db->prepare("UPDATE last_entry SET blob_value = null, string_value = ? WHERE record = ? AND form_field = ?", array('text', 'integer', 'integer'));
             if (I2CE::pearError($updates['last_entry'], "Unable to prepare statement for updating last_entry")) {
                 die;
             }
             $updates['entry'] = $db->prepare("UPDATE entry SET blob_value = null, string_value = ? WHERE record = ? AND form_field = ? AND UNIX_TIMESTAMP(date) = ?", array('text', 'integer', 'integer', 'integer'));
             if (I2CE::pearError($updates['entry'], "Unable to prepare statement for updating entry")) {
                 die;
             }
             $updates['config_alt'] = $db->prepare("UPDATE config_alt SET value = ? WHERE parent = ? AND name = ?", array('text', 'text', 'text'));
             if (I2CE::pearError($updates['config_alt'], "Unable to prepare statement for updating entry")) {
                 die;
             }
             $db->beginTransaction();
             require_once 'classDef/I2CE_FormField_STORE_BINARY_FILE.file.php';
             $tables = array('last_entry' => "SELECT *,UNIX_TIMESTAMP(date) AS unixtime FROM last_entry WHERE blob_value IS NOT NULL LIMIT 1", 'entry' => "SELECT *,UNIX_TIMESTAMP(date) AS unixtime FROM entry  WHERE blob_value IS NOT NULL LIMIT 1", 'config_alt' => "SELECT * , RIGHT( parent, INSTR( REVERSE( parent ) ,  '/' ) -1 ) AS field_name, LEFT( parent, LENGTH( parent ) - INSTR( REVERSE( parent ) ,  '/' ) ) AS ppath, LEFT( parent, LENGTH( parent ) - INSTR( REVERSE( parent ) ,  '/' ) -7 ) AS top, ( SELECT UNIX_TIMESTAMP( value ) FROM config_alt WHERE name =  'last_modified' AND parent = top) AS unixtime, ( SELECT value FROM config_alt WHERE name = field_name AND parent = ppath) AS blob_value, ( SELECT RIGHT( top, INSTR( REVERSE( top ) ,  '/' ) -1 )) AS record, SUBSTR( parent, 23, LOCATE(  '/', parent, 23 ) -23 ) AS form FROM  `config_alt` WHERE name =  '=A:binary' AND parent LIKE  '/I2CE/formsData/forms/%/fields/%' LIMIT 1");
             $processed_ffs = array();
             foreach ($tables as $table => $query) {
                 while (true) {
                     $data = $db->queryRow($query);
                     if (I2CE::pearError($data, "Unable to find blob values in DB.")) {
                         $db->rollback();
                         die;
                     }
                     if (!$data) {
                         break;
                     }
                     $form = "form";
                     $field = "field";
                     if ($table == 'config_alt') {
                         $data->blob_value = base64_decode($data->blob_value);
                         $form = $data->form;
                         $field = $data->field_name;
                     }
                     list($meta, $value) = self::processBlob($data->blob_value);
                     if ($table != 'config_alt') {
                         if (sizeof($meta) == 0) {
                             // Just do nothing with this one. It doesn't appear to be a BINARY FILE
                             continue;
                         }
                         $info_res = $get_field_info->execute($data->form_field);
                         if (I2CE::pearError($info_res, "Unable to get details: ")) {
                             $db->rollback();
                             die;
                         }
                         $field_info = $info_res->fetchRow();
                         if (!$field_info) {
                             echo "Unable to get and process field info!";
                             $db->rollback();
                             die;
                         }
                         if (!array_key_exists($data->form_field, $processed_ffs)) {
                             if ($field_info->type == 'blob') {
                                 $new_field_res = $find_string_field->execute($field_info->field);
                                 if (I2CE::pearError($new_field_res, "Unable to lookup existing field: ")) {
                                     $db->rollback();
                                     die;
                                 }
                                 $existing_field = $new_field_res->fetchOne();
                                 if (!$existing_field) {
                                     $existing_field = $db->getBeforeID('field', 'id', true, true);
                                     if (!I2CE::pearError($existing_field, "Error getting field id:")) {
                                         $field_values = array('id' => $existing_field, 'name' => $field_info->field, 'type' => 'string');
                                         $add_res = $db->autoExecute("field", $field_values, MDB2_AUTOQUERY_INSERT, null, array('integer', 'text', 'text'));
                                         $existing_field = $db->getAfterID($existing_field, 'field', 'id');
                                         if (I2CE::pearError($add_res, "Unable to add new field to entry storage: ")) {
                                             $db->rollback();
                                             die;
                                         }
                                     } else {
                                         $db->rollback();
                                         die;
                                     }
                                 }
                                 echo "Got new field {$existing_field} to use\n";
                                 $update_res = $update_ff->execute(array($existing_field, $data->form_field));
                                 if (I2CE::pearError($update_res, "Unable to update form field to new string field: ")) {
                                     $db->rollback();
                                     die;
                                 }
                                 echo 'Updated ' . $data->form_field . ' to use ' . $existing_field . "\n";
                             }
                             $processed_ffs[$data->form_field] = true;
                         }
                         $form = $field_info->form;
                         $field = $field_info->field;
                     }
                     if (!array_key_exists('fmod-time', $meta)) {
                         $meta['fmod-time'] = $data->unixtime;
                     }
                     if (!array_key_exists('file-name', $meta)) {
                         $meta['file-name'] = 'unknown';
                     }
                     $file = I2CE_FormField_STORE_BINARY_FILE::setupStorageFile($data->record, $form, $field, $meta['fmod-time'], $meta['file-name']);
                     echo "File will be {$file}\n";
                     $nH = fopen($file, 'w');
                     if (!$nH) {
                         $db->rollback();
                         die("Unable to open {$file}");
                     }
                     fwrite($nH, $value);
                     fclose($nH);
                     $meta_string = '';
                     foreach ($meta as $key => $val) {
                         $meta_string .= "{$key}<{$val}>";
                     }
                     if ($table == 'entry') {
                         $update_res = $updates['entry']->execute(array($meta_string, $data->record, $data->form_field, $data->unixtime));
                         if (I2CE::pearError($update_res, "Unable to update blob to string value: ")) {
                             $db->rollback();
                             die;
                         }
                     } elseif ($table == 'last_entry') {
                         $update_res = $updates['last_entry']->execute(array($meta_string, $data->record, $data->form_field));
                         if (I2CE::pearError($update_res, "Unable to update blob to string value: ")) {
                             $db->rollback();
                             die;
                         }
                         echo "Updating same row in entry table.\n";
                         $update_res = $updates['entry']->execute(array($meta_string, $data->record, $data->form_field, $data->unixtime));
                         if (I2CE::pearError($update_res, "Unable to update blob to string value: ")) {
                             $db->rollback();
                             die;
                         }
                     } elseif ($table == 'config_alt') {
                         $update_res = $updates['config_alt']->execute(array($meta_string, $data->ppath, $field));
                         if (I2CE::pearError($update_res, "Unable to update blob to string value: ")) {
                             $db->rollback();
                             die;
                         }
                         $md_field = $config_top->traverse($data->parent, false, false);
                         if (!$md_field instanceof I2CE_MagicDataNode) {
                             I2CE::raiseError("Can't update MD attributes for " . $data->ppath);
                             $db->rollback();
                             die;
                         }
                         $md_field->removeAttribute("binary");
                         $md_field->removeAttribute("encoding");
                     }
                 }
             }
             $db->commit();
             $config->migrated_to_file = 1;
             $path = '/var/lib/iHRIS/file_storage';
             $config->setIfIsSet($path, 'path');
             echo "Migration has finished.  You MUST make sure the file storage path ({$path}) is\nreadable and writeable by www-data (or your web server)!\n";
             break;
         default:
             I2CE::raiseError("Unknown command line page for bin field: {$action}\n");
             break;
     }
 }
 /**
  * Gets the length of the conten
  * @returns int
  */
 public function getContentLength()
 {
     return parent::getContentLength() + (int) $this->null_term;
 }
 /**
  * Load this value from the temporary upload table
  * @param $key;
  */
 public function storeInTemporaryTable()
 {
     if (!$this->tmp_key) {
         return false;
     }
     if (!self::$storeStmt) {
         $db = MDB2::singleton();
         $stmt = $db->prepare("REPLACE INTO `temp_upload` (`key`,`value`) VALUES (?,?)", array('text', 'blob'), MDB2_PREPARE_MANIP);
         if (I2CE::pearError($stmt, "Error creating store stement")) {
             return false;
         }
         self::$storeStmt = $stmt;
     }
     $res = self::$storeStmt->execute(array($this->tmp_key, $this->getDBValue()));
     if (I2CE::pearError($res, "Could not store into temp_upload")) {
         return false;
     }
 }