diff --git a/DataObjects/Auth.php b/DataObjects/Auth.php new file mode 100644 index 0000000000000000000000000000000000000000..cb95f56cbe57fc038e691a38f4e44852e4188118 --- /dev/null +++ b/DataObjects/Auth.php @@ -0,0 +1,21 @@ +<?php +/** + * Table Definition for auth + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Auth extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'auth'; // table name + public $username; // string(50) not_null primary_key + public $password; // string(32) not_null multiple_key + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Auth',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/DataObjects/Cap_areas.php b/DataObjects/Cap_areas.php new file mode 100644 index 0000000000000000000000000000000000000000..57e7e2aca24665ea9d9f96fb1b8b2199e0923139 --- /dev/null +++ b/DataObjects/Cap_areas.php @@ -0,0 +1,21 @@ +<?php +/** + * Table Definition for cap_areas + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_areas extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_areas'; // table name + public $key; // int(6) not_null primary_key + public $areaDesc; // string(255) not_null + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_areas',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/DataObjects/Cap_category.php b/DataObjects/Cap_category.php new file mode 100644 index 0000000000000000000000000000000000000000..f3804c2dc355bbd3d77b70b9d86f0a35bce596c4 --- /dev/null +++ b/DataObjects/Cap_category.php @@ -0,0 +1,24 @@ +<?php +/** + * Table Definition for cap_category + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_category extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_category'; // table name + public $key; // int(11) not_null primary_key auto_increment + public $value; // string(100) not_null + public $name; // string(100) + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_category',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + var $fb_linkDisplayFields = array('name'); +} diff --git a/DataObjects/Cap_certainty.php b/DataObjects/Cap_certainty.php new file mode 100644 index 0000000000000000000000000000000000000000..c6578bd2b492e11c0f36917e8968ffe056d64713 --- /dev/null +++ b/DataObjects/Cap_certainty.php @@ -0,0 +1,23 @@ +<?php +/** + * Table Definition for cap_certainty + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_certainty extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_certainty'; // table name + public $key; // int(11) not_null primary_key auto_increment + public $value; // string(30) not_null + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_certainty',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + var $fb_linkOrderFields = array('cap_certainty.key'); +} diff --git a/DataObjects/Cap_info.php b/DataObjects/Cap_info.php new file mode 100644 index 0000000000000000000000000000000000000000..68ac2f433cba7fdf0c95b5b6b2870e31865b303f --- /dev/null +++ b/DataObjects/Cap_info.php @@ -0,0 +1,100 @@ +<?php +/** + * Table Definition for cap_info + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_info extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_info'; // table name + public $category; // string(255) not_null + public $event; // string(255) + public $urgency; // string(255) not_null + public $severity; // string(255) not_null + public $certainty; // string(255) not_null + public $audience; // string(255) + public $effective; // datetime(19) not_null binary + public $onset; // datetime(19) binary + public $expires; // datetime(19) not_null binary + public $senderName; // string(255) + public $headline; // string(255) not_null + public $description; // string(255) + public $instruction; // string(255) + public $web; // string(255) + public $contact; // string(255) + public $created; // datetime(19) binary + public $recKey; // int(11) not_null primary_key + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_info',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + var $fb_dateTimeElementFormat = 'F-d-Y &\nb\sp;\<\stron\g>T\i\me:</\stron\g> h:i a'; + var $fb_formHeaderText = 'UNL CAP Alert Info System'; + var $fb_enumFields = array('audience'); + var $fb_enumOptions = array('audience'=>array('ALL'=>'ALL','Students'=>'Students','Faculty/Staff'=>'Faculty/Staff')); + var $fb_textFields = array('description','instruction'); + + function expire() + { + if ($this->expires > date('Y-m-d H:i:s')) { + $this->expires = date('Y-m-d H:i:00', strtotime('last minute')); + return $this->update(); + } else { + return true; + } + } + + function preGenerateForm(&$fb) { + $this->fb_preDefElements['created'] = HTML_QuickForm::createElement('hidden','created'); + $this->fb_preDefElements['onset'] = HTML_QuickForm::createElement('hidden','onset'); + $this->fb_preDefElements['event'] = HTML_QuickForm::createElement('hidden','event','University of Nebraska-Lincoln Alert'); + } + + function postGenerateForm(&$form,&$fb) { + foreach($this->fb_textFields as $field) { + $el =& $form->getElement($field); + $el->setCols(60); + $el->setRows(5); + } + + foreach(array('headline','web') as $field) { + $el =& $form->getElement($field); + $el->setSize(50); + } + + $form->insertElementBefore(HTML_QuickForm::createElement('static','head',NULL,' <div class="sevlegend"><div class="Extreme"></div><div> - Extreme severity will alert users with audio and a large ALERT scrollbar.</div></div> + <div class="sevlegend"><div class="Severe"></div><div> - Severe</div></div> + <div class="sevlegend"><div class="Moderate"></div><div> - Moderate</div></div> + <div class="sevlegend"><div class="Minor"></div> + <div> - Minor</div></div> + <div class="sevlegend"><div class="Unknown"></div> + <div> - Unknown</div></div> + '),'certainty'); + $el =& $form->getElement('urgency'); + $el->setValue('Immediate'); + $el->freeze(); + $el =& $form->getElement('severity'); + $el->setValue('Extreme'); + $el->freeze(); + $el =& $form->getElement('certainty'); + $el->setValue('Likely'); + $el->freeze(); + $el =& $form->getElement('audience'); + $el->setValue('ALL'); + $el->freeze(); + $el =& $form->getElement('web'); + $el->setValue('http://www.unl.edu/'); + + $el =& $form->getElement('senderName'); + $el->setValue('UNL Police Department'); + + $form->setDefaults(array('expires'=>time()+60*15,'category'=>'Safety')); + + } +} diff --git a/DataObjects/Cap_info_seq.php b/DataObjects/Cap_info_seq.php new file mode 100644 index 0000000000000000000000000000000000000000..1b69c0b5ccd1bec0a2550dee32f89b8706342b29 --- /dev/null +++ b/DataObjects/Cap_info_seq.php @@ -0,0 +1,20 @@ +<?php +/** + * Table Definition for cap_info_seq + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_info_seq extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_info_seq'; // table name + public $id; // int(10) not_null primary_key unsigned auto_increment + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_info_seq',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/DataObjects/Cap_severity.php b/DataObjects/Cap_severity.php new file mode 100644 index 0000000000000000000000000000000000000000..4311644e7ff30802ef44ed3730ea070bc9650f62 --- /dev/null +++ b/DataObjects/Cap_severity.php @@ -0,0 +1,23 @@ +<?php +/** + * Table Definition for cap_severity + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_severity extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_severity'; // table name + public $key; // int(11) not_null primary_key auto_increment + public $value; // string(30) not_null + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_severity',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + var $fb_linkOrderFields = array('cap_severity.key'); +} diff --git a/DataObjects/Cap_urgency.php b/DataObjects/Cap_urgency.php new file mode 100644 index 0000000000000000000000000000000000000000..ae8d1b321c9f05badfb5ee6372c0c488e116a8a8 --- /dev/null +++ b/DataObjects/Cap_urgency.php @@ -0,0 +1,23 @@ +<?php +/** + * Table Definition for cap_urgency + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Cap_urgency extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'cap_urgency'; // table name + public $key; // int(11) not_null primary_key auto_increment + public $value; // string(30) not_null + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Cap_urgency',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + var $fb_linkOrderFields = array('cap_urgency.key'); +} diff --git a/DataObjects/Users.php b/DataObjects/Users.php new file mode 100644 index 0000000000000000000000000000000000000000..4240b1ffdf7b58cda57b40b9070c5729b4ecc147 --- /dev/null +++ b/DataObjects/Users.php @@ -0,0 +1,24 @@ +<?php +/** + * Table Definition for users + */ +require_once 'DB/DataObject.php'; + +class DataObjects_Users extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'users'; // table name + public $id; // int(11) not_null primary_key auto_increment + public $ip; // string(15) not_null + public $first_load; // datetime(19) not_null binary + public $last_load; // datetime(19) not_null binary + public $version; // string(5) not_null + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObjects_Users',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/DataObjects/alerts.ini b/DataObjects/alerts.ini new file mode 100644 index 0000000000000000000000000000000000000000..68b6188a167f0af8127ca9990c9402305c436613 --- /dev/null +++ b/DataObjects/alerts.ini @@ -0,0 +1,81 @@ + +[auth] +username = 130 +password = 130 + +[auth__keys] +username = K + +[cap_areas] +key = 129 +areaDesc = 130 + +[cap_areas__keys] +key = K + +[cap_category] +key = 129 +value = 130 +name = 2 + +[cap_category__keys] +key = N + +[cap_certainty] +key = 129 +value = 130 + +[cap_certainty__keys] +key = N + +[cap_info] +category = 130 +event = 2 +urgency = 130 +severity = 130 +certainty = 130 +audience = 2 +effective = 142 +onset = 14 +expires = 142 +senderName = 2 +headline = 130 +description = 2 +instruction = 2 +web = 2 +contact = 2 +created = 14 +recKey = 129 + +[cap_info__keys] +recKey = K + +[cap_info_seq] +id = 129 + +[cap_info_seq__keys] +id = N + +[cap_severity] +key = 129 +value = 130 + +[cap_severity__keys] +key = N + +[cap_urgency] +key = 129 +value = 130 + +[cap_urgency__keys] +key = N + +[users] +id = 129 +ip = 130 +first_load = 142 +last_load = 142 +version = 130 + +[users__keys] +id = N diff --git a/DataObjects/alerts.links.ini b/DataObjects/alerts.links.ini new file mode 100644 index 0000000000000000000000000000000000000000..8e8c592b0de01499828d8d117d9edcdfef7b6d28 --- /dev/null +++ b/DataObjects/alerts.links.ini @@ -0,0 +1,5 @@ +[cap_info] +category = cap_category:value +certainty = cap_certainty:value +severity = cap_severity:value +urgency = cap_urgency:value \ No newline at end of file diff --git a/DataObjects/uptodate.ini b/DataObjects/uptodate.ini new file mode 100644 index 0000000000000000000000000000000000000000..76ff883eaaf2d1d5939068bb51ac5def24afb1a1 --- /dev/null +++ b/DataObjects/uptodate.ini @@ -0,0 +1,71 @@ + +[auth] +username = 130 +password = 130 + +[auth__keys] +username = K + +[cap_areas] +key = 129 +areaDesc = 130 + +[cap_areas__keys] +key = K + +[cap_category] +key = 129 +value = 130 + +[cap_category__keys] +key = N + +[cap_certainty] +key = 129 +value = 130 + +[cap_certainty__keys] +key = N + +[cap_info] +category = 2 +event = 2 +urgency = 2 +severity = 2 +certainty = 2 +audience = 2 +effective = 14 +onset = 14 +expires = 14 +senderName = 2 +headline = 2 +description = 2 +instruction = 2 +web = 2 +contact = 2 +Submit = 2 +created = 14 +recKey = 129 + +[cap_info__keys] +recKey = K + +[cap_info_seq] +id = 129 + +[cap_info_seq__keys] +id = N + +[cap_severity] +key = 129 +value = 130 + +[cap_severity__keys] +key = N + +[cap_urgency] +key = 129 +value = 130 + +[cap_urgency__keys] +key = N diff --git a/DataObjects/uptodate.links.ini b/DataObjects/uptodate.links.ini new file mode 100644 index 0000000000000000000000000000000000000000..8e8c592b0de01499828d8d117d9edcdfef7b6d28 --- /dev/null +++ b/DataObjects/uptodate.links.ini @@ -0,0 +1,5 @@ +[cap_info] +category = cap_category:value +certainty = cap_certainty:value +severity = cap_severity:value +urgency = cap_urgency:value \ No newline at end of file diff --git a/NotesLDAP.php b/NotesLDAP.php new file mode 100644 index 0000000000000000000000000000000000000000..c590966fa656357384245024eaa8df2203a3af16 --- /dev/null +++ b/NotesLDAP.php @@ -0,0 +1,55 @@ +<?php +/** + * Modified by Brett Bieber: + * changed PEAR_ERROR_DIE to PEAR_ERROR_RETURN for graceful exits on bind errors + */ +class NotesLDAP extends Auth_Container_LDAP +{ + /** + * Connect to the LDAP server using the global options + * + * @access private + * @return object Returns a PEAR error object if an error occurs. + */ + function _connect() + { + // connect + if (isset($this->options['url']) && $this->options['url'] != '') { + $this->_debug('Connecting with URL', __LINE__); + $conn_params = array($this->options['url']); + } else { + $this->_debug('Connecting with host:port', __LINE__); + $conn_params = array($this->options['host'], $this->options['port']); + } + + if(($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) { + return PEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41, PEAR_ERROR_DIE); + } + $this->_debug('Successfully connected to server', __LINE__); + + // try switchig to LDAPv3 + $ver = 0; + if(@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver >= 2) { + $this->_debug('Switching to LDAPv3', __LINE__); + @ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, 3); + } + + // bind with credentials or anonymously + if($this->options['binddn'] && $this->options['bindpw']) { + $this->_debug('Binding with credentials', __LINE__); + $bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']); + } else { + $this->_debug('Binding anonymously', __LINE__); + $bind_params = array($this->conn_id); + } + + // bind for searching + if ((@call_user_func_array('ldap_bind', $bind_params)) == false) { + $this->_debug(); + $this->_disconnect(); + return PEAR::raiseError('Auth_Container_LDAP: Could not bind to LDAP server.', 41, PEAR_ERROR_RETURN); + } + $this->_debug('Binding was successful', __LINE__); + } +} + diff --git a/admin_auth.php b/admin_auth.php new file mode 100644 index 0000000000000000000000000000000000000000..1310d93a30cf24885a518c777c143917c1c7e44b --- /dev/null +++ b/admin_auth.php @@ -0,0 +1,24 @@ +<?php + +require_once 'DB/DataObject.php'; +require_once 'UNL/Auth.php'; +require_once 'config.inc.php'; + +$a = UNL_Auth::factory('SimpleCAS'); +$a->login(); + +if (@$_GET['action'] == 'logout') { + $a->logout(); +} + +if ($a->isLoggedIn()) { + $validuser = DB_DataObject::factory('auth'); + $validuser->username = $a->getUser(); + if ($validuser->find()!=1) { + $a->logout(); + echo 'invalid username'; + exit(); + } +} else { + exit(); +} diff --git a/cap.css b/cap.css new file mode 100644 index 0000000000000000000000000000000000000000..1ca888599142ccc564a96eff13facad8533b3c03 --- /dev/null +++ b/cap.css @@ -0,0 +1,67 @@ +/* CSS Document */ +#title ul { + margin-right:20px; +} +.cap_alert { +margin:0 0 10px 0; +} +.cap_info { +border:2px solid; +padding:2px; +margin-top:4px; +padding-bottom:1.5em; +position:relative; +} +.cap_info a { + position:absolute; + margin:0 5px; + top:0px; + right:0px; +} +.cap_preamble { +} +.Extreme, .extreme { +border-color:#FF0000; +} +.Severe, .severe { +border-color:#FF9900; +} +.Moderate, .moderate { +border-color:#FFFF99; +} +.Minor, .minor { +border-color:#CCCCCC; +} +.Unknown, .unknown { + +} +.cap_headline { + font-weight:bold; +} +.cap_onset { +float:left; +} +.cap_expires { +float:right; +} + +form .sevlegend { +width:100%; +float:left; +clear:left; +} + +form .Extreme, form .Severe, form .Moderate, form .Minor, form .Unknown { +width:1.2em;height:1.4em; +border-left:1px solid black; +border-right:1px solid black; +} +form .sevlegend div { +float:left; +} + +form .Extreme {background-color:#CC0000;border-top:1px solid black;} +form .Severe {background-color:#FF9900;} +form .Moderate {background-color:#FFFF99;} +form .Minor {background-color:#CCCCCC;} +form .Unknown {border-bottom:1px solid black;} diff --git a/configsample.inc.php b/configsample.inc.php new file mode 100644 index 0000000000000000000000000000000000000000..9cfe4ddf890975ea8c7cb2af97e8668983fea045 --- /dev/null +++ b/configsample.inc.php @@ -0,0 +1,21 @@ +<?php + +// To rebuild dataobjects: /usr/local/php/bin/php /usr/local/php/lib/php/DB/DataObject/createTables.php ~/uptodate_DB_DataObject.ini +require_once('DB/DataObject/FormBuilder.php'); +require_once('displayAlerts.php'); + +$GLOBALS['database'] = 'alerts'; +$GLOBALS['username'] = 'alerts'; +$GLOBALS['password'] = 'alerts'; +$GLOBALS['dbhost'] = 'localhost'; +$dsn='mysqli://'.$GLOBALS['username'].':'.$GLOBALS['password'].'@'.$GLOBALS['dbhost'].'/'.$GLOBALS['database']; + +$options = &PEAR::getStaticProperty('DB_DataObject','options'); +$options = array( + 'database' => $dsn, + 'schema_location' => '/var/www/html/DataObjects', + 'class_location' => '/var/www/html/DataObjects', + 'require_prefix' => 'DataObjects/', + 'class_prefix' => 'DataObjects_', + 'backend' => 'mdb2' +); diff --git a/dataobject.ini b/dataobject.ini new file mode 100644 index 0000000000000000000000000000000000000000..4666b0523a565f77d54ca07b572a904968eee3cc --- /dev/null +++ b/dataobject.ini @@ -0,0 +1,6 @@ +[DB_DataObject] +database = mysql://alerts:alerts@localhost/alerts +schema_location = /home/bbieber/workspace/UNL_Alert/DataObjects +class_location = /home/bbieber/workspace/UNL_Alert/DataObjects +require_prefix = DataObjects/ +class_prefix = DataObjects_ diff --git a/displayAlerts.php b/displayAlerts.php new file mode 100644 index 0000000000000000000000000000000000000000..676749fb46b5ce5012d44d6fe58cb4ecdb25bd59 --- /dev/null +++ b/displayAlerts.php @@ -0,0 +1,42 @@ +<?php +function displayAlerts($db, $a) { + $sql = "SELECT recKey, category, event, urgency, severity, effective, onset, expires, certainty, audience, senderName, headline, description, instruction, web, contact ". + "FROM cap_info ". + "WHERE effective<='".date('Y-m-d H:i')."' AND expires>'".date('Y-m-d H:i')."'"; + $alerts =&$db->query($sql); + $content = ''; + if ($alerts->numRows()>0) { + ob_start(); + ?> + <div class="cap_alert"><h1>Current UNL Alerts:</h1> + <?php + while ($infoRec =&$alerts->fetchRow(MDB2_FETCHMODE_ASSOC)) { ?> + <div class="cap_preamble"> + At <?php echo $infoRec['effective']; ?>, the University of Nebraska-Lincoln issued a <?php echo $infoRec['severity']; ?> + <?php echo $infoRec['category']; ?> alert for <?php echo $infoRec['audience']; ?>: + </div> + <div class="cap_info <?php echo $infoRec['severity']; ?>"> + <div class="cap_headline"> + <?php echo $infoRec['headline']; ?> + </div> + <?php if (isset($infoRec['description'])) { ?> + <div class="cap_description"> + <?php echo $infoRec['description']; ?> and <?php echo $infoRec['audience']; ?> are advised to <?php echo $infoRec['instruction']; ?> + </div> + <?php } ?> + <?php if (isset($infoRec['onset'])) { ?> + <div class="cap_onset">Onset: <?php echo $infoRec['onset']; ?></div> + <?php } ?> + <div class="cap_expires">Expires: <?php echo date('Y-m-d g:i a',strtotime($infoRec['expires'])); ?></div> + <a href="?expire=<?php echo $infoRec['reckey']; ?>" onclick="return confirm('Are you sure you want to expire the alert immediately?');">Delete (Expire Immediately)</a> + </div> + <?php + } + ?> + </div> + <?php + $content = ob_get_contents(); + ob_end_clean(); + } + return $content; +} ?> \ No newline at end of file diff --git a/exportCAPAlert.php b/exportCAPAlert.php new file mode 100644 index 0000000000000000000000000000000000000000..e053c8dd949b62427a72cd9cb8254925cbfd977c --- /dev/null +++ b/exportCAPAlert.php @@ -0,0 +1,57 @@ +<?php +require_once 'config.inc.php'; + +function exportCAPAlert(){ + $output = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n". + "<alert xmlns:cap='http://www.incident.com/cap/1.0'>\n". + "<identifier>University of Nebraska-Lincoln ".date('Y-m-d\TH:i:sO')."</identifier>\n". + "<sender>police.unl.edu</sender>\n". + "<sent>".date('Y-m-d\TH:i:sO')."</sent>\n". + "<status>Actual</status>\n". + "<msgType>Alert</msgType>\n". + "<scope>Public</scope>\n". + "<note>\n". + "Current Watches, Warnings and Advisories for UNL Issued by University Police". + "</note>\n". + "<references>\n". + "http://www.unl.edu/". + "</references>\n"; + $link = mysql_connect($GLOBALS['dbhost'],$GLOBALS['username'],$GLOBALS['password']); + mysql_select_db($GLOBALS['database'],$link); + $sql = "SELECT recKey, category, event, urgency, severity, effective, onset, expires, certainty, audience, senderName, headline, description, instruction, web, contact ". + "FROM cap_info ". + "WHERE effective<='".date('Y-m-d H:i')."' AND expires>'".date('Y-m-d H:i')."' ". + "ORDER BY recKey DESC"; + $result = mysql_query($sql); + while($info = mysql_fetch_assoc($result)) { + foreach ($info as $key=>$val) { + $info[$key] = trim($val); + } + $output .= "<info>\n". + "<category>{$info['category']}</category>\n". + "<event>{$info['event']}</event>\n". + "<urgency>{$info['urgency']}</urgency>\n". + "<severity>{$info['severity']}</severity>\n". + "<certainty>{$info['certainty']}</certainty>\n". + "<headline>{$info['headline']}</headline>\n". + "<description>{$info['description']}</description>\n". + "<instruction>{$info['instruction']}</instruction>\n". + "<web>{$info['web']}</web>\n". + "<parameter>\n". + "<valueName>id</valueName>\n". + "<value>{$info['recKey']}</value>\n". + "</parameter>\n". + "<area>\n". + "<areaDesc>Lincoln (Nebraska)</areaDesc>\n". + "<geocode>031111</geocode>\n". + "</area>\n". + "</info>\n"; + } + $output .= "</alert>\n"; + mysql_close($link); + return $output; +} +$xmlCAP = exportCAPAlert(); + +file_put_contents(dirname(__FILE__).'/xml/unlcap.xml', $xmlCAP); + diff --git a/exportJSONAlert.php b/exportJSONAlert.php new file mode 100644 index 0000000000000000000000000000000000000000..89585d8fabf2c3d016ad820571ccc05cc9334cbc --- /dev/null +++ b/exportJSONAlert.php @@ -0,0 +1,23 @@ +<?php + +ini_set('display_errors',false); +require_once 'xml2json/xml2json.php'; + +$file = dirname(__FILE__).'/xml/unlcap.xml'; + +//Read the XML alert info from the file. +file_exists($file) or die('Could not find file '); +$xmlStringContents = file_get_contents($file); +$jsonContents = ''; +$nl = "\n"; +// Convert it to JSON now. +// xml2json simply takes a String containing XML contents as input. +$jsonContents = xml2json::transformXmlStringToJson($xmlStringContents); + +$jsonContents = 'unlAlerts.data = '.$jsonContents.$nl; + +$jsonContents .= 'try { +unlAlerts.server.init(); +} catch(e) {}'.$nl; + +file_put_contents(dirname(__FILE__).'/json/unlcap.js', $jsonContents); diff --git a/index.php b/index.php new file mode 100644 index 0000000000000000000000000000000000000000..35731e4671d41da5be6ae5ed043b75712100ea30 --- /dev/null +++ b/index.php @@ -0,0 +1,97 @@ +<?php + +ini_set('display_errors', false); + +if ($_SERVER['SERVER_NAME'] != 'ucommbieber.unl.edu' + && $_SERVER['SERVER_PORT'] != 443) { + $url = 'https://'. $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; + header('Location: '.$url); + exit(); +} + +require_once 'UNL/Templates.php'; +require_once 'MDB2.php'; +require_once 'admin_auth.php'; + + + +UNL_Templates::$options['version'] = 3; +$p = UNL_Templates::factory('Secure'); + +$p->doctitle = '<title>UNL | Up To Date Alerts</title>'; +$p->head .= '<link rel="stylesheet" type="text/css" href="cap.css" />'; +$p->breadcrumbs = <<<BC +<ul> + <li><a href="http://www.unl.edu/">UNL</a></li> + <li>ALERTS at UNL </li> +</ul> +BC; +$p->titlegraphic = '<h1>UNL Alerts</h1>'; +$p->maincontentarea = ''; + +$db =& MDB2::factory($dsn); +if (MDB2::isError($db)) { + die($db->getMessage()); +} + +$p->navlinks = ' +<ul> + <li class="first"><a href="http://alert1.unl.edu/">UNL Alert Server 1</a> + <!-- s1 --> + </li> + <li><a href="http://alert2.unl.edu/">UNL Alert Server 2</a> + <!-- s2 --> + </li> + <li><a href="'.$_SERVER['PHP_SELF'].'?action=logout" title="Logout">Logout '.$a->getUser().'</a></li> +</ul>'; + +if (isset($_GET['expire'])) { + $del = &DB_DataObject::factory('cap_info'); + if ($del->get($_GET['expire'])) { + if($del->expire()) { + $p->maincontentarea .= '<h3>The alert has expired as of '.$del->expires.'</h3>'; + } + } + unset($del); +} + +$p->navlinks = str_replace('<!-- s1 -->','<ul><li><a href="./">Create New Alert</a></li></ul>', $p->navlinks); +$p->navlinks = str_replace('<!-- s2 -->','<ul><li><a href="http://alert2.unl.edu/">Create New Alert</a></li></ul>', $p->navlinks); + +$cap =& DB_DataObject::factory('cap_info'); +if (isset($_GET['detail'])) { + $cap->get($_GET['detail']); +} +$fb =& DB_DataObject_FormBuilder::create($cap); +$form =& $fb->getForm(); +$form->setDefaults(array('contact'=>$a->getUser())); +if ($form->validate()) { + $result = $form->process(array(&$fb, 'processForm'), false); + if ($result==1) { + $p->maincontentarea .= "<span class='sserifstoryhead'>The alert was successfully added.</span>"; + // Update file on both servers. + file_get_contents('http://alert1.unl.edu/exportCAPAlert.php'); + file_get_contents('http://alert2.unl.edu/exportCAPAlert.php'); + // Old way + //include('exportCAPAlert.php'); + header('Location: ./?detail='.$cap->recKey); + exit(); + } +} + +if (isset($cap->recKey)) { + $form->removeElement('__submit__'); + $form->freeze(); + $content = $form->toHtml(); + $content .= '<h4 style="float:right;"><a href="./">New Alert</a></h4>'; +} else { + $content = $form->toHtml(); +} + +$p->maincontentarea .= displayAlerts($db, $a); +$p->maincontentarea .= $content; +$p->footercontent = '© '.date('Y').' University of Nebraska–Lincoln'; + +echo $p; + +$db->disconnect(); diff --git a/json/unlcap.js b/json/unlcap.js new file mode 100644 index 0000000000000000000000000000000000000000..81615c24da6764606ecced53e1e747c524c1fd26 --- /dev/null +++ b/json/unlcap.js @@ -0,0 +1,2 @@ +unlAlerts.data = {"alert":{"identifier":"University of Nebraska-Lincoln 2007-04-26T09:46:23-0500","sender":"bbieber@unlnotes.unl.edu","sent":"2007-04-26T09:46:23-0500","status":"Actual","msgType":"Alert","scope":"Public","note":"Current Watches, Warnings and Advisories for UNL Issued by University Communications","references":"http:\/\/www.unl.edu\/","info":{"category":"Safety","event":"University of Nebraska-Lincoln Alert","urgency":"Immediate","severity":"Extreme","certainty":"Likely","headline":"Thursday 4\/26\/07 Test","description":"TEST - Flash Flood - Broken pipe in 17R Parking Garage - TEST","instruction":"Test - Avoid the area - Test","web":"http:\/\/www.unl.edu\/","parameter":{"valueName":"id","value":"103"},"area":{"areaDesc":"Lincoln (Nebraska)","geocode":"031111"}}}} +try { unlAlerts.server.init(); } catch(e) {} \ No newline at end of file diff --git a/pref/pref.txt b/pref/pref.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ca038dd2aac677e4cb395046834203ec8e2150c --- /dev/null +++ b/pref/pref.txt @@ -0,0 +1 @@ +http://newmedia2.unl.edu/pref.txt http://alert1.unl.edu/xml/unlcap.xml 60 5 6 \ No newline at end of file diff --git a/xml/.cvsignore b/xml/.cvsignore new file mode 100644 index 0000000000000000000000000000000000000000..8d6cae386905ce4891c797be7b1feac5b1dd1a38 --- /dev/null +++ b/xml/.cvsignore @@ -0,0 +1 @@ +unlcap.xml diff --git a/xml/unlcap.xml b/xml/unlcap.xml new file mode 100644 index 0000000000000000000000000000000000000000..bec206cec040cde3fd5191fca93924f6f325c107 --- /dev/null +++ b/xml/unlcap.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alert xmlns:cap="http://www.incident.com/cap/1.0"> +<identifier>University of Nebraska-Lincoln 2007-04-26T09:46:23-0500</identifier> +<sender>bbieber@unlnotes.unl.edu</sender> +<sent>2007-04-26T09:46:23-0500</sent> +<status>Actual</status> +<msgType>Alert</msgType> +<scope>Public</scope> +<note> +Current Watches, Warnings and Advisories for UNL Issued by University Communications</note> +<references> +http://www.unl.edu/</references> +<info> +<category>Safety</category> +<event>University of Nebraska-Lincoln Alert</event> +<urgency>Immediate</urgency> +<severity>Extreme</severity> +<certainty>Likely</certainty> +<headline>Thursday 4/26/07 Test</headline> +<description>TEST - Flash Flood - Broken pipe in 17R Parking Garage - TEST</description> +<instruction>Test - Avoid the area - Test</instruction> +<web>http://www.unl.edu/</web> +<parameter> +<valueName>id</valueName> +<value>103</value> +</parameter> +<area> +<areaDesc>Lincoln (Nebraska)</areaDesc> +<geocode>031111</geocode> +</area> +</info> +</alert> \ No newline at end of file diff --git a/xml2json/json/JSON.php b/xml2json/json/JSON.php new file mode 100755 index 0000000000000000000000000000000000000000..63c58edbb6bc55fafc754d84609978ec609dcc08 --- /dev/null +++ b/xml2json/json/JSON.php @@ -0,0 +1,805 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ + +/** + * Converts to and from JSON format. + * + * JSON (JavaScript Object Notation) is a lightweight data-interchange + * format. It is easy for humans to read and write. It is easy for machines + * to parse and generate. It is based on a subset of the JavaScript + * Programming Language, Standard ECMA-262 3rd Edition - December 1999. + * This feature can also be found in Python. JSON is a text format that is + * completely language independent but uses conventions that are familiar + * to programmers of the C-family of languages, including C, C++, C#, Java, + * JavaScript, Perl, TCL, and many others. These properties make JSON an + * ideal data-interchange language. + * + * This package provides a simple encoder and decoder for JSON notation. It + * is intended for use with client-side Javascript applications that make + * use of HTTPRequest to perform server communication functions - data can + * be encoded into JSON notation for use in a client-side javascript, or + * decoded from incoming Javascript requests. JSON format is native to + * Javascript, and can be directly eval()'ed with no further parsing + * overhead + * + * All strings should be in ASCII or UTF-8 format! + * + * LICENSE: Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: Redistributions of source code must retain the + * above copyright notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * @category + * @package Services_JSON + * @author Michal Migurski <mike-json@teczno.com> + * @author Matt Knapp <mdknapp[at]gmail[dot]com> + * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> + * @copyright 2005 Michal Migurski + * @version CVS: $Id$ + * @license http://www.opensource.org/licenses/bsd-license.php + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 + */ + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_SLICE', 1); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_STR', 2); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_ARR', 3); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_OBJ', 4); + +/** + * Marker constant for Services_JSON::decode(), used to flag stack state + */ +define('SERVICES_JSON_IN_CMT', 5); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_LOOSE_TYPE', 16); + +/** + * Behavior switch for Services_JSON::decode() + */ +define('SERVICES_JSON_SUPPRESS_ERRORS', 32); + +/** + * Converts to and from JSON format. + * + * Brief example of use: + * + * <code> + * // create a new instance of Services_JSON + * $json = new Services_JSON(); + * + * // convert a complexe value to JSON notation, and send it to the browser + * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); + * $output = $json->encode($value); + * + * print($output); + * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] + * + * // accept incoming POST data, assumed to be in JSON notation + * $input = file_get_contents('php://input', 1000000); + * $value = $json->decode($input); + * </code> + */ +class Services_JSON +{ + /** + * constructs a new JSON instance + * + * @param int $use object behavior flags; combine with boolean-OR + * + * possible values: + * - SERVICES_JSON_LOOSE_TYPE: loose typing. + * "{...}" syntax creates associative arrays + * instead of objects in decode(). + * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. + * Values which can't be encoded (e.g. resources) + * appear as NULL instead of throwing errors. + * By default, a deeply-nested resource will + * bubble up with an error, so all return values + * from encode() should be checked with isError() + */ + function Services_JSON($use = 0) + { + $this->use = $use; + } + + /** + * convert a string from one UTF-16 char to one UTF-8 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf16 UTF-16 character + * @return string UTF-8 character + * @access private + */ + function utf162utf8($utf16) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); + } + + $bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); + + switch(true) { + case ((0x7F & $bytes) == $bytes): + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x7F & $bytes); + + case (0x07FF & $bytes) == $bytes: + // return a 2-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xC0 | (($bytes >> 6) & 0x1F)) + . chr(0x80 | ($bytes & 0x3F)); + + case (0xFFFF & $bytes) == $bytes: + // return a 3-byte UTF-8 character + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0xE0 | (($bytes >> 12) & 0x0F)) + . chr(0x80 | (($bytes >> 6) & 0x3F)) + . chr(0x80 | ($bytes & 0x3F)); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * convert a string from one UTF-8 char to one UTF-16 char + * + * Normally should be handled by mb_convert_encoding, but + * provides a slower PHP-only method for installations + * that lack the multibye string extension. + * + * @param string $utf8 UTF-8 character + * @return string UTF-16 character + * @access private + */ + function utf82utf16($utf8) + { + // oh please oh please oh please oh please oh please + if(function_exists('mb_convert_encoding')) { + return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); + } + + switch(strlen($utf8)) { + case 1: + // this case should never be reached, because we are in ASCII range + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return $utf8; + + case 2: + // return a UTF-16 character from a 2-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr(0x07 & (ord($utf8{0}) >> 2)) + . chr((0xC0 & (ord($utf8{0}) << 6)) + | (0x3F & ord($utf8{1}))); + + case 3: + // return a UTF-16 character from a 3-byte UTF-8 char + // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + return chr((0xF0 & (ord($utf8{0}) << 4)) + | (0x0F & (ord($utf8{1}) >> 2))) + . chr((0xC0 & (ord($utf8{1}) << 6)) + | (0x7F & ord($utf8{2}))); + } + + // ignoring UTF-32 for now, sorry + return ''; + } + + /** + * encodes an arbitrary variable into JSON format + * + * @param mixed $var any number, boolean, string, array, or object to be encoded. + * see argument 1 to Services_JSON() above for array-parsing behavior. + * if var is a strng, note that encode() always expects it + * to be in ASCII or UTF-8 format! + * + * @return mixed JSON string representation of input var or an error if a problem occurs + * @access public + */ + function encode($var) + { + switch (gettype($var)) { + case 'boolean': + return $var ? 'true' : 'false'; + + case 'NULL': + return 'null'; + + case 'integer': + return (int) $var; + + case 'double': + case 'float': + return (float) $var; + + case 'string': + // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT + $ascii = ''; + $strlen_var = strlen($var); + + /* + * Iterate over every character in the string, + * escaping with a slash or encoding to UTF-8 where necessary + */ + for ($c = 0; $c < $strlen_var; ++$c) { + + $ord_var_c = ord($var{$c}); + + switch (true) { + case $ord_var_c == 0x08: + $ascii .= '\b'; + break; + case $ord_var_c == 0x09: + $ascii .= '\t'; + break; + case $ord_var_c == 0x0A: + $ascii .= '\n'; + break; + case $ord_var_c == 0x0C: + $ascii .= '\f'; + break; + case $ord_var_c == 0x0D: + $ascii .= '\r'; + break; + + case $ord_var_c == 0x22: + case $ord_var_c == 0x2F: + case $ord_var_c == 0x5C: + // double quote, slash, slosh + $ascii .= '\\'.$var{$c}; + break; + + case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): + // characters U-00000000 - U-0000007F (same as ASCII) + $ascii .= $var{$c}; + break; + + case (($ord_var_c & 0xE0) == 0xC0): + // characters U-00000080 - U-000007FF, mask 110XXXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, ord($var{$c + 1})); + $c += 1; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF0) == 0xE0): + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2})); + $c += 2; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xF8) == 0xF0): + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3})); + $c += 3; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFC) == 0xF8): + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4})); + $c += 4; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + + case (($ord_var_c & 0xFE) == 0xFC): + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $char = pack('C*', $ord_var_c, + ord($var{$c + 1}), + ord($var{$c + 2}), + ord($var{$c + 3}), + ord($var{$c + 4}), + ord($var{$c + 5})); + $c += 5; + $utf16 = $this->utf82utf16($char); + $ascii .= sprintf('\u%04s', bin2hex($utf16)); + break; + } + } + + return '"'.$ascii.'"'; + + case 'array': + /* + * As per JSON spec if any array key is not an integer + * we must treat the the whole array as an object. We + * also try to catch a sparsely populated associative + * array with numeric keys here because some JS engines + * will create an array with empty indexes up to + * max_index which can cause memory issues and because + * the keys, which may be relevant, will be remapped + * otherwise. + * + * As per the ECMA and JSON specification an object may + * have any string as a property. Unfortunately due to + * a hole in the ECMA specification if the key is a + * ECMA reserved word or starts with a digit the + * parameter is only accessible using ECMAScript's + * bracket notation. + */ + + // treat as a JSON object + if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { + $properties = array_map(array($this, 'name_value'), + array_keys($var), + array_values($var)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + } + + // treat it like a regular array + $elements = array_map(array($this, 'encode'), $var); + + foreach($elements as $element) { + if(Services_JSON::isError($element)) { + return $element; + } + } + + return '[' . join(',', $elements) . ']'; + + case 'object': + $vars = get_object_vars($var); + + $properties = array_map(array($this, 'name_value'), + array_keys($vars), + array_values($vars)); + + foreach($properties as $property) { + if(Services_JSON::isError($property)) { + return $property; + } + } + + return '{' . join(',', $properties) . '}'; + + default: + return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) + ? 'null' + : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); + } + } + + /** + * array-walking function for use in generating JSON-formatted name-value pairs + * + * @param string $name name of key to use + * @param mixed $value reference to an array element to be encoded + * + * @return string JSON-formatted name-value pair, like '"name":value' + * @access private + */ + function name_value($name, $value) + { + $encoded_value = $this->encode($value); + + if(Services_JSON::isError($encoded_value)) { + return $encoded_value; + } + + return $this->encode(strval($name)) . ':' . $encoded_value; + } + + /** + * reduce a string by removing leading and trailing comments and whitespace + * + * @param $str string string value to strip of comments and whitespace + * + * @return string string value stripped of comments and whitespace + * @access private + */ + function reduce_string($str) + { + $str = preg_replace(array( + + // eliminate single line comments in '// ...' form + '#^\s*//(.+)$#m', + + // eliminate multi-line comments in '/* ... */' form, at start of string + '#^\s*/\*(.+)\*/#Us', + + // eliminate multi-line comments in '/* ... */' form, at end of string + '#/\*(.+)\*/\s*$#Us' + + ), '', $str); + + // eliminate extraneous space + return trim($str); + } + + /** + * decodes a JSON string into appropriate variable + * + * @param string $str JSON-formatted string + * + * @return mixed number, boolean, string, array, or object + * corresponding to given JSON input string. + * See argument 1 to Services_JSON() above for object-output behavior. + * Note that decode() always returns strings + * in ASCII or UTF-8 format! + * @access public + */ + function decode($str) + { + $str = $this->reduce_string($str); + + switch (strtolower($str)) { + case 'true': + return true; + + case 'false': + return false; + + case 'null': + return null; + + default: + $m = array(); + + if (is_numeric($str)) { + // Lookie-loo, it's a number + + // This would work on its own, but I'm trying to be + // good about returning integers where appropriate: + // return (float)$str; + + // Return float or int, as appropriate + return ((float)$str == (integer)$str) + ? (integer)$str + : (float)$str; + + } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { + // STRINGS RETURNED IN UTF-8 FORMAT + $delim = substr($str, 0, 1); + $chrs = substr($str, 1, -1); + $utf8 = ''; + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c < $strlen_chrs; ++$c) { + + $substr_chrs_c_2 = substr($chrs, $c, 2); + $ord_chrs_c = ord($chrs{$c}); + + switch (true) { + case $substr_chrs_c_2 == '\b': + $utf8 .= chr(0x08); + ++$c; + break; + case $substr_chrs_c_2 == '\t': + $utf8 .= chr(0x09); + ++$c; + break; + case $substr_chrs_c_2 == '\n': + $utf8 .= chr(0x0A); + ++$c; + break; + case $substr_chrs_c_2 == '\f': + $utf8 .= chr(0x0C); + ++$c; + break; + case $substr_chrs_c_2 == '\r': + $utf8 .= chr(0x0D); + ++$c; + break; + + case $substr_chrs_c_2 == '\\"': + case $substr_chrs_c_2 == '\\\'': + case $substr_chrs_c_2 == '\\\\': + case $substr_chrs_c_2 == '\\/': + if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || + ($delim == "'" && $substr_chrs_c_2 != '\\"')) { + $utf8 .= $chrs{++$c}; + } + break; + + case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): + // single, escaped unicode character + $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) + . chr(hexdec(substr($chrs, ($c + 4), 2))); + $utf8 .= $this->utf162utf8($utf16); + $c += 5; + break; + + case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): + $utf8 .= $chrs{$c}; + break; + + case ($ord_chrs_c & 0xE0) == 0xC0: + // characters U-00000080 - U-000007FF, mask 110XXXXX + //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 2); + ++$c; + break; + + case ($ord_chrs_c & 0xF0) == 0xE0: + // characters U-00000800 - U-0000FFFF, mask 1110XXXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 3); + $c += 2; + break; + + case ($ord_chrs_c & 0xF8) == 0xF0: + // characters U-00010000 - U-001FFFFF, mask 11110XXX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 4); + $c += 3; + break; + + case ($ord_chrs_c & 0xFC) == 0xF8: + // characters U-00200000 - U-03FFFFFF, mask 111110XX + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 5); + $c += 4; + break; + + case ($ord_chrs_c & 0xFE) == 0xFC: + // characters U-04000000 - U-7FFFFFFF, mask 1111110X + // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + $utf8 .= substr($chrs, $c, 6); + $c += 5; + break; + + } + + } + + return $utf8; + + } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { + // array, or object notation + + if ($str{0} == '[') { + $stk = array(SERVICES_JSON_IN_ARR); + $arr = array(); + } else { + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = array(); + } else { + $stk = array(SERVICES_JSON_IN_OBJ); + $obj = new stdClass(); + } + } + + array_push($stk, array('what' => SERVICES_JSON_SLICE, + 'where' => 0, + 'delim' => false)); + + $chrs = substr($str, 1, -1); + $chrs = $this->reduce_string($chrs); + + if ($chrs == '') { + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } else { + return $obj; + + } + } + + //print("\nparsing {$chrs}\n"); + + $strlen_chrs = strlen($chrs); + + for ($c = 0; $c <= $strlen_chrs; ++$c) { + + $top = end($stk); + $substr_chrs_c_2 = substr($chrs, $c, 2); + + if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { + // found a comma that is not inside a string, array, etc., + // OR we've reached the end of the character list + $slice = substr($chrs, $top['where'], ($c - $top['where'])); + array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); + //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + // we are in an array, so just push an element onto the stack + array_push($arr, $this->decode($slice)); + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + // we are in an object, so figure + // out the property name and set an + // element in an associative array, + // for now + $parts = array(); + + if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // "name":value pair + $key = $this->decode($parts[1]); + $val = $this->decode($parts[2]); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { + // name:value pair, where name is unquoted + $key = $parts[1]; + $val = $this->decode($parts[2]); + + if ($this->use & SERVICES_JSON_LOOSE_TYPE) { + $obj[$key] = $val; + } else { + $obj->$key = $val; + } + } + + } + + } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { + // found a quote, and we are not inside a string + array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); + //print("Found start of string at {$c}\n"); + + } elseif (($chrs{$c} == $top['delim']) && + ($top['what'] == SERVICES_JSON_IN_STR) && + (($chrs{$c - 1} != '\\') || + ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) { + // found a quote, we're in a string, and it's not escaped + array_pop($stk); + //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '[') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-bracket, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); + //print("Found start of array at {$c}\n"); + + } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { + // found a right-bracket, and we're in an array + array_pop($stk); + //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($chrs{$c} == '{') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a left-brace, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); + //print("Found start of object at {$c}\n"); + + } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { + // found a right-brace, and we're in an object + array_pop($stk); + //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } elseif (($substr_chrs_c_2 == '/*') && + in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { + // found a comment start, and we are in an array, object, or slice + array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); + $c++; + //print("Found start of comment at {$c}\n"); + + } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { + // found a comment end, and we're in one now + array_pop($stk); + $c++; + + for ($i = $top['where']; $i <= $c; ++$i) + $chrs = substr_replace($chrs, ' ', $i, 1); + + //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); + + } + + } + + if (reset($stk) == SERVICES_JSON_IN_ARR) { + return $arr; + + } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { + return $obj; + + } + + } + } + } + + /** + * @todo Ultimately, this should just call PEAR::isError() + */ + function isError($data, $code = null) + { + if (class_exists('pear')) { + return PEAR::isError($data, $code); + } elseif (is_object($data) && (get_class($data) == 'services_json_error' || + is_subclass_of($data, 'services_json_error'))) { + return true; + } + + return false; + } +} + +if (class_exists('PEAR_Error')) { + + class Services_JSON_Error extends PEAR_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + parent::PEAR_Error($message, $code, $mode, $options, $userinfo); + } + } + +} else { + + /** + * @todo Ultimately, this class shall be descended from PEAR_Error + */ + class Services_JSON_Error + { + function Services_JSON_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + + } + } + +} + +?> diff --git a/xml2json/json/LICENSE b/xml2json/json/LICENSE new file mode 100755 index 0000000000000000000000000000000000000000..4ae6bef55df28180491b7cbcb45fa4ecacbc2624 --- /dev/null +++ b/xml2json/json/LICENSE @@ -0,0 +1,21 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/xml2json/xml2json.php b/xml2json/xml2json.php new file mode 100755 index 0000000000000000000000000000000000000000..0ac83cd9e43c906d9d1952c571fe79d0b9288588 --- /dev/null +++ b/xml2json/xml2json.php @@ -0,0 +1,235 @@ +<?php +/* +============================================================================================ +Filename: +--------- +xml2json.php + +Description: +------------ +This PHP class converts XML-based data into JSON formatted data. +This program makes use of several open source PHP utility classes and functions. + +License: +-------- +This code is made available free of charge with the rights to use, copy, modify, +merge, publish and distribute. This Software shall be used for Good, not Evil. + +First Created on: +----------------- +Oct/04/2006 + +Last Modified on: +----------------- +Oct/07/2006 +============================================================================================ +*/ +require_once 'json/JSON.php'; + +// Internal program-specific Debug option. +define ("DEBUG", false); +// Maximum Recursion Depth that we can allow. +define ("MAX_RECURSION_DEPTH_ALLOWED", 25); +// An empty string +define ("EMPTY_STR", ""); +// SimpleXMLElement object property name for attributes +define ("SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES", "@attributes"); +// SimpleXMLElement object name. +define ("SIMPLE_XML_ELEMENT_PHP_CLASS", "SimpleXMLElement"); + +class xml2json { + + /* + ============================================================================= + Function name: + --------------- + transformXmlStringToJson + + Function Parameters: + --------------------- + 1) XML data string. + + Description: + ------------ + This function transforms the XML based String data into JSON format. If the input XML + string is in table format, the resulting JSON output will also be in table format. + Conversely, if the input XML string is in tree format, the resulting JSON output will + also be in tree format. + + Function Return Value: + ---------------------- + 1) If everything is successful, it returns a string containing JSON table/tree formatted data. + Otherwise, it returns an empty string. + + First Created on: + ----------------- + Oct/04/2006 + + Last Modified on: + ----------------- + Oct/07/2006 + ============================================================================= + */ + public static function transformXmlStringToJson($xmlStringContents) { + /* + Get the SimpleXMLElement representation of the function input + parameter that contains XML string. Convert the XML string + contents to SimpleXMLElement type. SimpleXMLElement type is + nothing but an object that can be processed with normal property + selectors and (associative) array iterators. + simplexml_load_string returns a SimpleXMLElement object which + contains an instance variable which itself is an associative array of + several SimpleXMLElement objects. + */ + $simpleXmlElementObject = simplexml_load_string($xmlStringContents); + + if ($simpleXmlElementObject == null) { + return(EMPTY_STR); + } + + $simpleXmlRootElementName = $simpleXmlElementObject->getName(); + // Uncomment this line to see the inner details of the SimpleXMLElement object. + if (DEBUG) { + // var_dump($simpleXmlRootElementName); + // var_dump($simpleXmlElementObject); + } + + $jsonOutput = EMPTY_STR; + // Let us convert the XML structure into PHP array structure. + $array1 = xml2json::convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject); + + if (($array1 != null) && (sizeof($array1) > 0)) { + //create a new instance of Services_JSON + $json = new Services_JSON(); + $jsonOutput = $json->encode($array1); + + if (DEBUG) { + // var_dump($array1); + // var_dump($jsonOutput); + } + } // End of if (($array1 != null) && (sizeof($array1) > 0)) + + return($jsonOutput); + } // End of function transformXmlStringToJson + + /* + ============================================================================= + Function name: + --------------- + convertSimpleXmlElementObjectIntoArray + + Function Parameters: + --------------------- + 1) Simple XML Element Object + + (The following function argument needs to be passed only when this function is + called recursively. It can be omitted when this function is called from another + function.) + 2) Recursion Depth + + Description: + ------------ + This function accepts a SimpleXmlElementObject as a single argument. + This function converts the XML object into a PHP associative array. + If the input XML is in table format (i.e. non-nested), the resulting associative + array will also be in a table format. Conversely, if the input XML is in + tree (i.e. nested) format, this function will return an associative array + (tree/nested) representation of that XML. + + There are so many ways to turn an XML document into a PHP array. Out of all + those options, the recursive logic here uses a method that is very nicely + documented by the PHP open source community in the SimpleXMLElement section of + the PHP manual available at www.php.net. Credit goes to all those kind + PHP (People Helping People!!!) souls. + + Function Return Value: + ---------------------- + 1) If everything is successful, it returns an associate array containing + the data collected from the XML format. Otherwise, it returns null. + + Caution and Remarks: + --------------------- + IT IS A RECURSIVE FUNCTION. + + First Created on: + ----------------- + Oct/04/2006 + + Last Modified on: + ----------------- + Oct/07/2006 + ============================================================================= + */ + public static function convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject, &$recursionDepth=0) { + // Keep an eye on how deeply we are involved in recursion. + if ($recursionDepth > MAX_RECURSION_DEPTH_ALLOWED) { + // Fatal error. Exit now. + return(null); + } + + if ($recursionDepth == 0) { + if (get_class($simpleXmlElementObject) != SIMPLE_XML_ELEMENT_PHP_CLASS) { + // If the external caller doesn't call this function initially + // with a SimpleXMLElement object, return now. + return(null); + } else { + // Store the original SimpleXmlElementObject sent by the caller. + // We will need it at the very end when we return from here for good. + $callerProvidedSimpleXmlElementObject = $simpleXmlElementObject; + } + } // End of if ($recursionDepth == 0) { + + if (get_class($simpleXmlElementObject) == SIMPLE_XML_ELEMENT_PHP_CLASS) { + // Get a copy of the simpleXmlElementObject + $copyOfsimpleXmlElementObject = $simpleXmlElementObject; + // Get the object variables in the SimpleXmlElement object for us to iterate. + $simpleXmlElementObject = get_object_vars($simpleXmlElementObject); + } + + // It needs to be an array of object variables. + if (is_array($simpleXmlElementObject)) { + // Is the array size 0? Then, we reached the rare CDATA text if any. + if (count($simpleXmlElementObject) <= 0) { + // Let us return the lonely CDATA. It could even be whitespaces. + return (trim(strval($copyOfsimpleXmlElementObject))); + } + + // Let us walk through the child elements now. + foreach($simpleXmlElementObject as $key=>$value) { + // When this block of code is commented, XML attributes will be + // added to the result array. + // Uncomment the following block of code if XML attributes are + // NOT required to be returned as part of the result array. + /* + if($key == SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES) { + continue; + } + */ + // Let us recursively process the current element we just visited. + // Increase the recursion depth by one. + $recursionDepth++; + $resultArray[$key] = xml2json::convertSimpleXmlElementObjectIntoArray($value, $recursionDepth); + // Decrease the recursion depth by one. + $recursionDepth--; + } // End of foreach($simpleXmlElementObject as $key=>$value) { + + if ($recursionDepth == 0) { + // That is it. We are heading to the exit now. + // Set the XML root element name as the root [top-level] key of + // the associative array that we are going to return to the caller of this + // recursive function. + $tempArray = $resultArray; + $resultArray = array(); + $resultArray[$callerProvidedSimpleXmlElementObject->getName()] = $tempArray; + } + + return ($resultArray); + } else { + // We are now looking at either the XML attribute text or + // the text between the XML tags. + return (trim(strval($simpleXmlElementObject))); + } // End of else + } // End of function convertSimpleXmlElementObjectIntoArray. + +} // End of class xml2json +?> \ No newline at end of file diff --git a/xml2json/xml2json.sh b/xml2json/xml2json.sh new file mode 100755 index 0000000000000000000000000000000000000000..d3b17e97be36392ea85d3d79cc70e01d430dea7c --- /dev/null +++ b/xml2json/xml2json.sh @@ -0,0 +1,57 @@ +#!/usr/bin/php + +<?php +/* +============================================================================================ +Filename: +--------- +xml2json.sh + +Description: +------------ +The code in this PHP program is just a test driver that exercises the XML to JSON converter +class. This PHP program reads the contents of a filename passed in the command line and +converts the XML contents in that file to JSON formatted data. + +This program takes a XML filename as a command line argument as shown below: +php -f xml2json_test.php test1.xml + +License: +-------- +This code is made available free of charge with the rights to use, copy, modify, +merge, publish and distribute. This Software shall be used for Good, not Evil. + +First Created on: +----------------- +Oct/04/2006 + +Last Modified on: +----------------- +Oct/07/2006 +============================================================================================ +*/ +require_once("xml2json.php"); + +// Filename from where XML contents are to be read. +$testXmlFile = ""; + +// Read the filename from the command line. +if ($argc <= 1) { + print("Please provide the XML filename as a command-line argument:\n"); + print("\tphp -f xml2json_test.php test1.xml\n"); + return; +} else { + $testXmlFile = $argv[1]; +} + +//Read the XML contents from the input file. +file_exists($testXmlFile) or die('Could not find file ' . $testXmlFile); +$xmlStringContents = file_get_contents($testXmlFile); +$jsonContents = ""; + +// Convert it to JSON now. +// xml2json simply takes a String containing XML contents as input. +$jsonContents = xml2json::transformXmlStringToJson($xmlStringContents); + +echo($jsonContents); +?> \ No newline at end of file