cs-webapplibs-commits Mailing List for CS Web Application Libraries (Page 5)
Status: Beta
Brought to you by:
crazedsanity
You can subscribe to this list here.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(47) |
Sep
(8) |
Oct
(1) |
Nov
(3) |
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(3) |
Jun
(14) |
Jul
(5) |
Aug
|
Sep
(5) |
Oct
(2) |
Nov
|
Dec
|
| 2011 |
Jan
(15) |
Feb
(7) |
Mar
(1) |
Apr
(1) |
May
(1) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(2) |
Nov
(3) |
Dec
(1) |
| 2012 |
Jan
(1) |
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <cra...@us...> - 2009-08-20 16:21:57
|
Revision: 122
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=122&view=rev
Author: crazedsanity
Date: 2009-08-20 16:21:45 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Moved cs_versionAbstract to cs-content, abstract class into abstract folder.
NOTE::: as stated in a recent commit to cs-content, moving cs_versionAbstract
into the cs-content project means the two projects are not inextricably
attached to one another, and that this project is truly an extension of
cs-content. Previously, since everything in cs-content required
cs_versionAbstract{}, this project would ALWAYS have to be available (which
wasn't a problem when cs_versionAbstract{} was in it's own project,
"cs-versionparse").
/cs_authToken.class.php:
* fix location of cs_webapplibsAbstract.
/cs_version.abstract.class.php [MOVED]:
* moved to cs-content/abstract/
/cs_webdblogger.class.php:
* fix location of cs_webapplibsAbstract.
/cs_webdbupgrade.class.php:
* fix location of cs_webapplibsAbstract.
/tests/testOfCSWebAppLibs.php:
* test_version_basics() [DELETED]
* test_check_higher() [DELETED]
* middleTestClass{} [DELETED]
/tests/files/version* [DELETED]:
* moved to cs-content for testing cs_versionAbstract
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/cs_webdblogger.class.php
trunk/0.3/cs_webdbupgrade.class.php
trunk/0.3/tests/testOfCSWebAppLibs.php
Added Paths:
-----------
trunk/0.3/abstract/
trunk/0.3/abstract/cs_webapplibs.abstract.class.php
Removed Paths:
-------------
trunk/0.3/cs_version.abstract.class.php
trunk/0.3/cs_webapplibs.abstract.class.php
trunk/0.3/tests/files/version1
trunk/0.3/tests/files/version2
trunk/0.3/tests/files/version3
Copied: trunk/0.3/abstract/cs_webapplibs.abstract.class.php (from rev 119, trunk/0.3/cs_webapplibs.abstract.class.php)
===================================================================
--- trunk/0.3/abstract/cs_webapplibs.abstract.class.php (rev 0)
+++ trunk/0.3/abstract/cs_webapplibs.abstract.class.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -0,0 +1,20 @@
+<?php
+/*
+ * Created on Aug 19, 2009
+ *
+ * SVN INFORMATION:::
+ * -------------------
+ * Last Author::::::::: $Author$
+ * Current Revision:::: $Revision$
+ * Repository Location: $HeadURL$
+ * Last Updated:::::::: $Date$
+ */
+
+require_once(constant('LIBDIR') .'/cs-content/abstract/cs_version.abstract.class.php');
+
+
+abstract class cs_webapplibsAbstract extends cs_versionAbstract {
+
+}
+
+?>
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/cs_authToken.class.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -11,7 +11,7 @@
*/
-require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
+require_once(dirname(__FILE__) .'/abstract/cs_webapplibs.abstract.class.php');
class cs_authToken extends cs_webapplibsAbstract {
Deleted: trunk/0.3/cs_version.abstract.class.php
===================================================================
--- trunk/0.3/cs_version.abstract.class.php 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/cs_version.abstract.class.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -1,398 +0,0 @@
-<?php
-/*
- * Created on January 01, 2009 by Dan Falconer
- *
- * SVN INFORMATION:::
- * -------------------
- * Last Author::::::::: $Author$
- * Current Revision:::: $Revision$
- * Repository Location: $HeadURL$
- * Last Updated:::::::: $Date$
- */
-
-abstract class cs_versionAbstract {
-
- public $isTest = FALSE;
-
-
-
- private $versionFileLocation=null;
- private $fullVersionString;
- private $suffixList = array(
- 'ALPHA', //very unstable
- 'BETA', //kinda unstable, but probably useable
- 'RC' //all known bugs fixed, searching for unknown ones
- );
-
-
-
- abstract public function __construct();
-
-
-
- //=========================================================================
- /**
- * Retrieve our version string from the VERSION file.
- */
- final public function get_version($asArray=false) {
- $retval = NULL;
-
- $this->auto_set_version_file();
-
- if(file_exists($this->versionFileLocation)) {
- $myMatches = array();
- $findIt = preg_match('/VERSION: (.+)/', file_get_contents($this->versionFileLocation), $matches);
-
- if($findIt == 1 && count($matches) == 2) {
- $fullVersionString = $matches[1];
- $versionInfo = $this->parse_version_string($fullVersionString);
- $this->fullVersionString = $this->build_full_version_string($versionInfo);
-
-
- if($asArray) {
- $retval = $versionInfo;
- $retval['version_string'] = $this->fullVersionString;
- }
- else {
- $retval = $this->build_full_version_string($versionInfo);
- }
- }
- else {
- throw new exception(__METHOD__ .": failed to retrieve version string in file " .
- "(". $this->versionFileLocation .")");
- }
- }
- else {
- throw new exception(__METHOD__ .": failed to retrieve version information, file " .
- "(". $this->versionFileLocation .") does not exist or was not set");
- }
-
- return($retval);
- }//end get_version()
- //=========================================================================
-
-
-
- //=========================================================================
- public function __get($var) {
- return($this->$var);
- }//end __get()
- //=========================================================================
-
-
-
- //=========================================================================
- final public function get_project() {
- $retval = NULL;
- $this->auto_set_version_file();
- if(file_exists($this->versionFileLocation)) {
- $myMatches = array();
- $findIt = preg_match('/PROJECT: (.+)/', file_get_contents($this->versionFileLocation), $matches);
-
- if($findIt == 1 && count($matches) == 2 && strlen($matches[1])) {
- $retval = $matches[1];
- }
- else {
- throw new exception(__METHOD__ .": failed to retrieve project string");
- }
- }
- else {
- throw new exception(__METHOD__ .": failed to retrieve project information");
- }
-
- return($retval);
- }//end get_project()
- //=========================================================================
-
-
-
- //=========================================================================
- public function set_version_file_location($location) {
- if(file_exists($location)) {
- $this->versionFileLocation = $location;
- }
- else {
- throw new exception(__METHOD__ .": invalid location of VERSION file (". $location .")");
- }
- }//end set_version_file_location()
- //=========================================================================
-
-
-
- //=========================================================================
- protected function auto_set_version_file() {
- if(!strlen($this->versionFileLocation)) {
- $bt = debug_backtrace();
- foreach($bt as $callNum=>$data) {
- if(strlen($data['class'])) {
- if($data['class'] != __CLASS__) {
- $dir = dirname($data['file']);
- if(preg_match('/tests$/', $dir)) {
- $dir = preg_replace('/\/tests$/', '', $dir);
- }
- elseif(preg_match('/test$/', $dir)) {
- $dir = preg_replace('/\/test$/', '', $dir);
- }
- break;
- }
- }
- else {
- throw new exception(__METHOD__ .": failed to locate the calling class in backtrace");
- }
- }
-
- if(file_exists($dir .'/VERSION')) {
- $this->set_version_file_location($dir .'/VERSION');
- }
- else {
- throw new exception(__METHOD__ .": failed to automatically set version file (tried ". $dir ."/VERSION)");
- }
- }
- }//end auto_set_version_file()
- //=========================================================================
-
-
-
- //=========================================================================
- /**
- *
- * TODO: add logic to split apart the suffix (i.e. "-ALPHA5" broken into "ALPHA" and "5").
- */
- public function parse_version_string($version) {
- if(is_string($version) && strlen($version) && preg_match('/\./', $version)) {
- $version = preg_replace('/ /', '', $version);
-
- $pieces = explode('.', $version);
- $retval = array(
- 'version_major' => $pieces[0],
- 'version_minor' => $pieces[1]
- );
- if(isset($pieces[2]) && strlen($pieces[2])) {
- $retval['version_maintenance'] = $pieces[2];
- }
- else {
- $retval['version_maintenance'] = 0;
- }
-
- if(preg_match('/-/', $retval['version_maintenance'])) {
- $bits = explode('-', $retval['version_maintenance']);
- $retval['version_maintenance'] = $bits[0];
- $suffix = $bits[1];
- }
- elseif(preg_match('/-/', $retval['version_minor'])) {
- $bits = explode('-', $retval['version_minor']);
- $retval['version_minor'] = $bits[0];
- $suffix = $bits[1];
- }
- else {
- $suffix = "";
- }
- $retval['version_suffix'] = $suffix;
- }
- else {
- throw new exception(__METHOD__ .": invalid version string passed (". $version .")");
- }
-
- return($retval);
- }//end parse_version_string()
- //=========================================================================
-
-
-
- //=========================================================================
- public function build_full_version_string(array $versionInfo) {
- $requiredIndexes = array(
- 'version_major', 'version_minor', 'version_maintenance', 'version_suffix'
- );
-
- $missing="";
- $count=0;
- foreach($requiredIndexes as $indexName) {
- if(isset($versionInfo[$indexName])) {
- $count++;
- }
- else {
- if(strlen($missing)) {
- $missing .= ", ". $indexName;
- }
- else {
- $missing = $indexName;
- }
- }
- }
-
- if($count == count($requiredIndexes) && !strlen($missing)) {
- $suffix = $versionInfo['version_suffix'];
- unset($versionInfo['version_suffix']);
-
- $retval = "";
- foreach($versionInfo as $name=>$value) {
- if(strlen($retval)) {
- $retval .= ".". $value;
- }
- else {
- $retval = $value;
- }
- }
- if(strlen($suffix)) {
- $retval .= "-". $suffix;
- }
- }
- else {
- throw new exception(__METHOD__ .": missing indexes in given array (". $missing .")");
- }
-
- return($retval);
-
- }//end build_full_version_string()
- //=========================================================================
-
-
-
- //=========================================================================
- public function is_higher_version($version, $checkIfHigher) {
- $retval = FALSE;
- $this->gfObj = new cs_globalFunctions;
- if(!is_string($version) || !is_string($checkIfHigher)) {
- throw new exception(__METHOD__ .": no valid version strings, version=(". $version ."), checkIfHigher=(". $checkIfHigher .")");
- }
- elseif($version == $checkIfHigher) {
- $retval = FALSE;
- }
- else {
- $curVersionArr = $this->parse_version_string($version);
- $checkVersionArr = $this->parse_version_string($checkIfHigher);
-
- unset($curVersionArr['version_string'], $checkVersionArr['version_string']);
-
-
- $curVersionSuffix = $curVersionArr['version_suffix'];
- $checkVersionSuffix = $checkVersionArr['version_suffix'];
-
-
- unset($curVersionArr['version_suffix']);
-
- foreach($curVersionArr as $index=>$versionNumber) {
- $checkThis = $checkVersionArr[$index];
-
- if(is_numeric($checkThis) && is_numeric($versionNumber)) {
- //set them as integers.
- settype($versionNumber, 'int');
- settype($checkThis, 'int');
-
- if($checkThis > $versionNumber) {
- $retval = TRUE;
- break;
- }
- elseif($checkThis == $versionNumber) {
- //they're equal...
- }
- else {
- //TODO: should there maybe be an option to throw an exception (freak out) here?
- }
- }
- else {
- throw new exception(__METHOD__ .": ". $index ." is not numeric in one of the strings " .
- "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")");
- }
- }
-
- //now deal with those damnable suffixes, but only if the versions are so far identical: if
- // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when
- // we already know there's a major, minor, or maintenance version that's also higher.
- if($retval === FALSE) {
- //EXAMPLE: $version="1.0.0-BETA3", $checkIfHigher="1.1.0"
- // Moving from a non-suffixed version to a suffixed version isn't supported, but the inverse is:
- // i.e. (1.0.0-BETA3 to 1.0.0) is okay, but (1.0.0 to 1.0.0-BETA3) is NOT.
- // Also: (1.0.0-BETA3 to 1.0.0-BETA4) is okay, but (1.0.0-BETA4 to 1.0.0-BETA3) is NOT.
- if(strlen($curVersionSuffix) && strlen($checkVersionSuffix) && $curVersionSuffix == $checkVersionSuffix) {
- //matching suffixes.
- }
- elseif(strlen($curVersionSuffix) || strlen($checkVersionSuffix)) {
- //we know the suffixes are there and DO match.
- if(strlen($curVersionSuffix) && strlen($checkVersionSuffix)) {
- //okay, here's where we do some crazy things...
- $curVersionData = $this->parse_suffix($curVersionSuffix);
- $checkVersionData = $this->parse_suffix($checkVersionSuffix);
-
- if($curVersionData['type'] == $checkVersionData['type']) {
- //got the same suffix type (like "BETA"), check the number.
- if($checkVersionData['number'] > $curVersionData['number']) {
- //new version's suffix number higher than current...
- $retval = TRUE;
- }
- elseif($checkVersionData['number'] == $curVersionData['number']) {
- //new version's suffix number is EQUAL TO current...
- $retval = FALSE;
- }
- else {
- //new version's suffix number is LESS THAN current...
- $retval = FALSE;
- }
- }
- else {
- //not the same suffix... see if the new one is higher.
- $suffixValues = array_flip($this->suffixList);
- if($suffixValues[$checkVersionData['type']] > $suffixValues[$curVersionData['type']]) {
- $retval = TRUE;
- }
- else {
- //current suffix type is higher...
- }
- }
-
- }
- elseif(strlen($curVersionSuffix) && !strlen($checkVersionSuffix)) {
- //i.e. "1.0.0-BETA1" to "1.0.0" --->>> OKAY!
- $retval = TRUE;
- }
- elseif(!strlen($curVersionSuffix) && strlen($checkVersionSuffix)) {
- //i.e. "1.0.0" to "1.0.0-BETA1" --->>> NOT ACCEPTABLE!
- }
- }
- else {
- //no suffix to care about
- }
- }
- }
-
- return($retval);
-
- }//end is_higher_version()
- //=========================================================================
-
-
-
- //=========================================================================
- protected function parse_suffix($suffix) {
- $retval = NULL;
- if(strlen($suffix)) {
- //determine what kind it is.
- foreach($this->suffixList as $type) {
- if(preg_match('/^'. $type .'/', $suffix)) {
- $checkThis = preg_replace('/^'. $type .'/', '', $suffix);
- if(strlen($checkThis) && is_numeric($checkThis)) {
- //oooh... it's something like "BETA3"
- $retval = array(
- 'type' => $type,
- 'number' => $checkThis
- );
- }
- else {
- throw new exception(__METHOD__ .": invalid suffix (". $suffix .")");
- }
- break;
- }
- }
- }
- else {
- throw new exception(__METHOD__ .": invalid suffix (". $suffix .")");
- }
-
- return($retval);
- }//end parse_suffix()
- //=========================================================================
-
-
-}
-?>
\ No newline at end of file
Deleted: trunk/0.3/cs_webapplibs.abstract.class.php
===================================================================
--- trunk/0.3/cs_webapplibs.abstract.class.php 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/cs_webapplibs.abstract.class.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -1,20 +0,0 @@
-<?php
-/*
- * Created on Aug 19, 2009
- *
- * SVN INFORMATION:::
- * -------------------
- * Last Author::::::::: $Author$
- * Current Revision:::: $Revision$
- * Repository Location: $HeadURL$
- * Last Updated:::::::: $Date$
- */
-
-require_once(dirname(__FILE__) .'/cs_version.abstract.class.php');
-
-
-abstract class cs_webapplibsAbstract extends cs_versionAbstract {
-
-}
-
-?>
Modified: trunk/0.3/cs_webdblogger.class.php
===================================================================
--- trunk/0.3/cs_webdblogger.class.php 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/cs_webdblogger.class.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -27,7 +27,7 @@
//NOTE::: this class **REQUIRES** cs-content for its "cs_phpDB" class.
-require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
+require_once(dirname(__FILE__) .'/abstract/cs_webapplibs.abstract.class.php');
require_once(dirname(__FILE__) .'/cs_webdbupgrade.class.php');
class cs_webdblogger extends cs_webapplibsAbstract {
Modified: trunk/0.3/cs_webdbupgrade.class.php
===================================================================
--- trunk/0.3/cs_webdbupgrade.class.php 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/cs_webdbupgrade.class.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -12,7 +12,7 @@
*
*/
-require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
+require_once(dirname(__FILE__) .'/abstract/cs_webapplibs.abstract.class.php');
require_once(dirname(__FILE__) .'/cs_webdblogger.class.php');
class cs_webdbupgrade extends cs_webapplibsAbstract {
Deleted: trunk/0.3/tests/files/version1
===================================================================
--- trunk/0.3/tests/files/version1 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/tests/files/version1 2009-08-20 16:21:45 UTC (rev 122)
@@ -1,3 +0,0 @@
-
-PROJECT: test1
-VERSION: 0.1.2-ALPHA8754
\ No newline at end of file
Deleted: trunk/0.3/tests/files/version2
===================================================================
--- trunk/0.3/tests/files/version2 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/tests/files/version2 2009-08-20 16:21:45 UTC (rev 122)
@@ -1,3 +0,0 @@
-
-PROJECT: test2
-VERSION: 5.4
\ No newline at end of file
Deleted: trunk/0.3/tests/files/version3
===================================================================
--- trunk/0.3/tests/files/version3 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/tests/files/version3 2009-08-20 16:21:45 UTC (rev 122)
@@ -1,3 +0,0 @@
-
-PROJECT: test3 stuff
-VERSION: 5.4.3-BETA5543
\ No newline at end of file
Modified: trunk/0.3/tests/testOfCSWebAppLibs.php
===================================================================
--- trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 15:52:11 UTC (rev 121)
+++ trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 16:21:45 UTC (rev 122)
@@ -11,7 +11,6 @@
* $LastChangedRevision$
*/
-require_once(dirname(__FILE__) .'/../cs_version.abstract.class.php');
require_once(dirname(__FILE__) .'/../cs_authToken.class.php');
class testOfCSWebAppLibs extends UnitTestCase {
@@ -24,108 +23,8 @@
//--------------------------------------------------------------------------
- //--------------------------------------------------------------------------
- function test_version_basics() {
-
- $tests = array(
- 'files/version1' => array(
- '0.1.2-ALPHA8754',
- 'test1',
- array(
- 'version_major' => 0,
- 'version_minor' => 1,
- 'version_maintenance' => 2,
- 'version_suffix' => 'ALPHA8754'
- )
- ),
- 'files/version2' => array(
- '5.4.0',
- 'test2',
- array(
- 'version_major' => 5,
- 'version_minor' => 4,
- 'version_maintenance' => 0,
- 'version_suffix' => null
- )
- ),
- 'files/version3' => array(
- '5.4.3-BETA5543',
- 'test3 stuff',
- array(
- 'version_major' => 5,
- 'version_minor' => 4,
- 'version_maintenance' => 3,
- 'version_suffix' => 'BETA5543'
- )
- )
- );
-
- foreach($tests as $fileName=>$expectedArr) {
- $ver = new middleTestClass();
- $ver->set_version_file_location(dirname(__FILE__) .'/'. $fileName);
-
- $this->assertEqual($expectedArr[0], $ver->get_version(), "Failed to match string from file (". $fileName .")");
- $this->assertEqual($expectedArr[1], $ver->get_project(), "Failed to match project from file (". $fileName .")");
-
- //now check that pulling the version as an array is the same...
- $checkItArr = $ver->get_version(true);
- $expectThis = $expectedArr[2];
- $expectThis['version_string'] = $expectedArr[0];
- }
- }//end test_version_basics()
- //--------------------------------------------------------------------------
-
-
//--------------------------------------------------------------------------
- function test_check_higher() {
-
- //NOTE: the first item should ALWAYS be higher.
- $tests = array(
- 'basic, no suffix' => array('1.0.1', '1.0.0'),
- 'basic + suffix' => array('1.0.0-ALPHA1', '1.0.0-ALPHA0'),
- 'basic w/o maint' => array('1.0.1', '1.0'),
- 'suffix check' => array('1.0.0-BETA1', '1.0.0-ALPHA1'),
- 'suffix check2' => array('1.0.0-ALPHA10', '1.0.0-ALPHA1'),
- 'suffix check3' => array('1.0.1', '1.0.0-RC1')
- );
-
- foreach($tests as $name=>$checkData) {
- $ver = new middleTestClass;
- $this->assertTrue($ver->is_higher_version($checkData[1], $checkData[0]));
- $this->assertFalse($ver->is_higher_version($checkData[0], $checkData[1]));
- }
-
- //now check to ensure there's no problem with parsing equivalent versions.
- $tests = array(
- 'no suffix' => array('1.0', '1.0.0'),
- 'no maint + suffix' => array('1.0-ALPHA1', '1.0.0-ALPHA1'),
- 'no maint + BETA' => array('1.0-BETA5555', '1.0.0-BETA5555'),
- 'no maint + RC' => array('1.0-RC33', '1.0.0-RC33'),
- 'maint with space' => array('1.0-RC 33', '1.0.0-RC33'),
- 'extra spaces' => array(' 1.0 ', '1.0.0')
- );
- foreach($tests as $name=>$checkData) {
- $ver = new middleTestClass;
-
- //rip apart & recreate first version to test against the expected...
- $derivedFullVersion = $ver->build_full_version_string($ver->parse_version_string($checkData[0]));
- $this->assertEqual($derivedFullVersion, $checkData[1], "TEST=(". $name ."): derived version " .
- "(". $derivedFullVersion .") doesn't match expected (". $checkData[1] .")");
-
- //now rip apart & recreate the expected version (second) and make sure it matches itself.
- $derivedFullVersion = $ver->build_full_version_string($ver->parse_version_string($checkData[1]));
- $this->assertEqual($derivedFullVersion, $checkData[1], "TEST=(". $name ."): derived version " .
- "(". $derivedFullVersion .") doesn't match expected (". $checkData[1] .")");
- }
-
-
- }//end test_check_higher()
- //--------------------------------------------------------------------------
-
-
-
- //--------------------------------------------------------------------------
private function create_dbconn() {
$dbParams = array(
'host' => constant('DB_PG_HOST'),
@@ -249,10 +148,6 @@
}
-class middleTestClass extends cs_versionAbstract {
- function __construct(){}
-}
-
class authTokenTester extends cs_authToken {
public $isTest=true;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 15:52:17
|
Revision: 121
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=121&view=rev
Author: crazedsanity
Date: 2009-08-20 15:52:11 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
More tests, add "last_updated" to tokens.
/cs_authToken.class.php:
* create_token():
-- call _generic_update() to do the update statement.
* update_token_uses():
-- call _generic_update() to do the update statement.
* get_token_data():
-- ARG CHANGE: NEW ARG: #2 ($onlyNonExpired=true)
-- add ability to get ANY token's data (for unit testing & eventually
for logging purposes).
* remove_expired_tokens() [NEW]:
-- destroys tokens that are expired (doesn't do any checking as far
as whether or not there are uses left).
* _generic_update() [NEW]:
-- besides the update string given, it also updates the (new)
"last_updated" column.
-- NOTE::: this was done so that the cs_sessionDB{} class from
cs-content could potentially just call methods in this class to
create & expire records... its just an idea for now.
/setup/schema.mysql.sql:
* cswal_auth_token_table:
-- added "last_updated" (timestamp) column.
-- NOTE::: didn't set the default as NOW() because MySQL won't allow
more than one timestamp field to have that as the default...?
/setup/schema.pgsql.sql:
* mirrored changes to mysql schema.
/tests/testOfCSWebAppLibs.php:
* test_token_basics():
-- removed duplicate code into a private method, "basic_token_tests()"
-- added test for creating an already-expired token.
-- TODO: retrieve the token's data before authenticating, then test
to see if it was removed afterward.
* basic_token_tests() [NEW]:
-- set of tests that are performed for pretty much every token
created, so code was moved here so it is more standardized.
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/setup/schema.mysql.sql
trunk/0.3/setup/schema.pgsql.sql
trunk/0.3/tests/testOfCSWebAppLibs.php
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-20 14:55:21 UTC (rev 120)
+++ trunk/0.3/cs_authToken.class.php 2009-08-20 15:52:11 UTC (rev 121)
@@ -105,9 +105,7 @@
//now that we have the ID, let's create the real has string.
$finalHash = $this->create_hash_string($tokenId, $uid, $checksum, $stringToHash);
- $this->db->run_update("UPDATE ". $this->table ." SET token='". $finalHash ."' WHERE " .
- "auth_token_id=". $tokenId);
-
+ $this->_generic_update($tokenId, "token='". $finalHash ."'");
$tokenInfo = array(
'id' => $tokenId,
'hash' => $finalHash
@@ -134,11 +132,8 @@
* @return (exception) FAIL: exception denotes problem
*/
protected function update_token_uses($tokenId) {
-
try {
- $sql = "UPDATE ". $this->table ." SET total_uses= total_uses+1 " .
- "WHERE auth_token_id=". $tokenId;
- $updateRes = $this->db->run_update($sql);
+ $updateRes = $this->_generic_update($tokenId, "total_uses= total_uses+1");
}
catch(exception $e) {
throw new exception(__METHOD__ .": failed to update usage count::: ". $e->getMessage());
@@ -260,10 +255,15 @@
* @return (array) PASS: contains data about the given ID
* @return (exception) FAIL: exception contains error details.
*/
- protected function get_token_data($tokenId) {
+ protected function get_token_data($tokenId, $onlyNonExpired=true) {
try {
- $data = $this->db->run_query("SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId
- ." AND expiration::date >= CURRENT_DATE", 'auth_token_id');
+ $sql = "SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId;
+ if($onlyNonExpired === true) {
+ $sql .= " AND expiration::date >= CURRENT_DATE";
+ }
+
+ $data = $this->db->run_query($sql, 'auth_token_id');
+
if(is_array($data) && count($data) == 1) {
$tokenData = $data;
}
@@ -281,5 +281,49 @@
}//end get_token_data();
//=========================================================================
+
+
+ //=========================================================================
+ /**
+ * Deletes any tokens that are past expiration (does not test for total vs.
+ * max uses; authenticate_token() does that).
+ *
+ * @param (null) (void)
+ */
+ public function remove_expired_tokens() {
+ $sql = "SELECT * FROM ". $this->table ." WHERE NOW() > expiration";
+
+ try {
+ $data = $this->db->run_query($sql, 'auth_token_id');
+
+ if(is_array($data)) {
+ foreach($data as $tokenId => $tokenData) {
+ //TODO: add logging here?
+ $this->destroy_token($tokenId);
+ }
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error encountered while expiring tokens::: ". $e->getMessage());
+ }
+ }//end remove_expired_tokens()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function _generic_update($tokenId, $updateString) {
+ try {
+ $sql = "UPDATE ". $this->table ." SET ". $updateString .", last_updated=NOW() " .
+ "WHERE auth_token_id=". $tokenId;
+ $updateRes = $this->db->run_update($sql);
+ }
+ catch(exception $e) {
+ throw new exception("failed to update token::: ". $e->getMessage());
+ }
+ return($updateRes);
+ }//end generic_update()
+ //=========================================================================
+
}
?>
Modified: trunk/0.3/setup/schema.mysql.sql
===================================================================
--- trunk/0.3/setup/schema.mysql.sql 2009-08-20 14:55:21 UTC (rev 120)
+++ trunk/0.3/setup/schema.mysql.sql 2009-08-20 15:52:11 UTC (rev 121)
@@ -156,5 +156,6 @@
max_uses integer DEFAULT NULL,
total_uses integer NOT NULL DEFAULT 0,
creation timestamp NOT NULL DEFAULT NOW(),
+ last_updated timestamp,
expiration timestamp NOT NULL
);
\ No newline at end of file
Modified: trunk/0.3/setup/schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/schema.pgsql.sql 2009-08-20 14:55:21 UTC (rev 120)
+++ trunk/0.3/setup/schema.pgsql.sql 2009-08-20 15:52:11 UTC (rev 121)
@@ -100,6 +100,7 @@
max_uses integer DEFAULT NULL,
total_uses integer NOT NULL DEFAULT 0,
creation timestamp NOT NULL DEFAULT NOW(),
+ last_updated timestamp,
expiration timestamp NOT NULL
);
Modified: trunk/0.3/tests/testOfCSWebAppLibs.php
===================================================================
--- trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 14:55:21 UTC (rev 120)
+++ trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 15:52:11 UTC (rev 121)
@@ -164,6 +164,7 @@
//--------------------------------------------------------------------------
+
//--------------------------------------------------------------------------
function test_token_basics() {
$db = $this->create_dbconn();
@@ -185,12 +186,7 @@
{
//Generic test to ensure we get the appropriate data back.
$tokenData = $tok->create_token(1, 'test', 'abc123', null, 1);
- $this->assertTrue(is_array($tokenData));
- $this->assertTrue((count($tokenData) == 2));
- $this->assertTrue(isset($tokenData['id']));
- $this->assertTrue(isset($tokenData['hash']));
- $this->assertTrue(($tokenData['id'] > 0));
- $this->assertTrue((strlen($tokenData['hash']) == 32));
+ $this->basic_token_tests($tokenData, 1, 'test');
if(!$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1)) {
$this->gfObj->debug_print($tok->tokenData($tokenData['id']),1);
@@ -205,12 +201,7 @@
{
//Generic test to ensure we get the appropriate data back.
$tokenData = $tok->create_token(1, 'test', 'abc123', '2 years');
- $this->assertTrue(is_array($tokenData));
- $this->assertTrue((count($tokenData) == 2));
- $this->assertTrue(isset($tokenData['id']));
- $this->assertTrue(isset($tokenData['hash']));
- $this->assertTrue(($tokenData['id'] > 0));
- $this->assertTrue((strlen($tokenData['hash']) == 32));
+ $this->basic_token_tests($tokenData, 1, 'test');
$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
}
@@ -218,17 +209,43 @@
//try to create a token with max_uses of 0.
{
$tokenData = $tok->create_token(2, 'test', 'xxxxyyyyyxxxx', null, 0);
+ $this->basic_token_tests($tokenData, 2, 'test');
$checkData = $tok->tokenData($tokenData['id']);
$checkData = $checkData[$tokenData['id']];
$this->assertTrue(is_array($checkData));
- if(!$this->assertEqual($tokenData['id'], $checkData['auth_token_id'])) {
- $this->gfObj->debug_print($checkData);
- }
+ $this->assertEqual($tokenData['id'], $checkData['auth_token_id']);
$this->assertEqual($checkData['max_uses'], null);
}
+
+ //try creating a token that is purposely expired, make sure it exists, then make sure authentication fails.
+ {
+ $tokenData = $tok->create_token(88, 'test', 'This is a big old TEST', '-3 days');
+ if($this->assertTrue(is_array($tokenData))) {
+ $this->basic_token_tests($tokenData, 88, 'This is a big old TEST');
+ $this->assertFalse($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']));
+ }
+ }
}//end test_token_basics()
//--------------------------------------------------------------------------
+
+
+
+ //--------------------------------------------------------------------------
+ private function basic_token_tests(array $tokenData, $uid, $checksum) {
+
+ if($this->assertTrue(is_array($tokenData)) && $this->assertTrue(is_numeric($uid)) && $this->assertTrue(strlen($checksum))) {
+
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
+ }
+
+ }//end basic_token_tests()
+ //--------------------------------------------------------------------------
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 14:55:30
|
Revision: 120
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=120&view=rev
Author: crazedsanity
Date: 2009-08-20 14:55:21 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Drop tables (instead of DB), extra tests.
/cs_authToken.class.php:
* __construct():
-- create an instance of cs_webdbupgrade{} to see if an upgrade needs
to be performed.
-- NOTE::: this can be removed simply by adding logging, as
cs_webdblogger::__construct() checks for upgrades.
/tests/testOfCSWebAppLibs.php:
* create_dbconn() RENAMED FROM create_db()
* remove_tables() [NEW]:
-- does a DROP ... CASCADE on all tables belonging to cs-webapplibs
* test_token_basics():
-- updated references to use create_dbconn()
-- move tests around slighly so I can view the database after & know
for sure that the record that had only 1 use is actually missing
(because there is a gap in auth_token_id's).
-- test for creating a token with 0 max uses (to see that the invalid
value for max_uses is ignored).
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/tests/testOfCSWebAppLibs.php
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-20 13:57:54 UTC (rev 119)
+++ trunk/0.3/cs_authToken.class.php 2009-08-20 14:55:21 UTC (rev 120)
@@ -41,6 +41,8 @@
}
$this->gfObj = new cs_globalFunctions();
+ $upg = new cs_webdbupgrade(dirname(__FILE__) .'/VERSION', dirname(__FILE__) .'/upgrades/upgrade.xml');
+ $upg->check_versions(true);
}//end __construct()
//=========================================================================
Modified: trunk/0.3/tests/testOfCSWebAppLibs.php
===================================================================
--- trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 13:57:54 UTC (rev 119)
+++ trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 14:55:21 UTC (rev 120)
@@ -126,7 +126,7 @@
//--------------------------------------------------------------------------
- private function create_db() {
+ private function create_dbconn() {
$dbParams = array(
'host' => constant('DB_PG_HOST'),
'dbname' => constant('DB_PG_DBNAME'),
@@ -141,9 +141,33 @@
//--------------------------------------------------------------------------
+
//--------------------------------------------------------------------------
+ private function remove_tables() {
+ $tableList = array(
+ 'cswal_auth_token_table', 'cswal_version_table', 'cswdbl_attribute_table',
+ 'cswdbl_category_table', 'cswdbl_class_table', 'cswdbl_event_table',
+ 'cswdbl_log_attribute_table', 'cswdbl_log_table',
+ );
+
+ $db = $this->create_dbconn();
+ foreach($tableList as $name) {
+ try {
+ $db->run_update("DROP TABLE ". $name ." CASCADE", true);
+ }
+ catch(exception $e) {
+ //force an error.
+ $this->assertTrue(false, "Error while dropping (". $name .")::: ". $e->getMessage());
+ }
+ }
+ }//end remove_tables()
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
function test_token_basics() {
- $db = $this->create_db();
+ $db = $this->create_dbconn();
+ $this->remove_tables();
$tok = new authTokenTester($db);
//Generic test to ensure we get the appropriate data back.
@@ -157,11 +181,10 @@
$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
-
- //now create a token with a maximum lifetime...
+ //create a token with only 1 available use and try to authenticate it twice.
{
//Generic test to ensure we get the appropriate data back.
- $tokenData = $tok->create_token(1, 'test', 'abc123', '2 years');
+ $tokenData = $tok->create_token(1, 'test', 'abc123', null, 1);
$this->assertTrue(is_array($tokenData));
$this->assertTrue((count($tokenData) == 2));
$this->assertTrue(isset($tokenData['id']));
@@ -169,13 +192,19 @@
$this->assertTrue(($tokenData['id'] > 0));
$this->assertTrue((strlen($tokenData['hash']) == 32));
- $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
+ if(!$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1)) {
+ $this->gfObj->debug_print($tok->tokenData($tokenData['id']),1);
+ }
+ if(!$this->assertTrue(($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']) === null), "Able to authenticate twice on a token with only 1 use")) {
+ $this->gfObj->debug_print($tok->tokenData($tokenData['id']));
+ }
}
- //create a token with only 1 available use and try to authenticate it twice.
+
+ //now create a token with a maximum lifetime...
{
//Generic test to ensure we get the appropriate data back.
- $tokenData = $tok->create_token(1, 'test', 'abc123', null, 1);
+ $tokenData = $tok->create_token(1, 'test', 'abc123', '2 years');
$this->assertTrue(is_array($tokenData));
$this->assertTrue((count($tokenData) == 2));
$this->assertTrue(isset($tokenData['id']));
@@ -183,12 +212,20 @@
$this->assertTrue(($tokenData['id'] > 0));
$this->assertTrue((strlen($tokenData['hash']) == 32));
- if(!$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1)) {
- $this->gfObj->debug_print($tok->tokenData($tokenData['id']),1);
+ $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
+ }
+
+ //try to create a token with max_uses of 0.
+ {
+ $tokenData = $tok->create_token(2, 'test', 'xxxxyyyyyxxxx', null, 0);
+ $checkData = $tok->tokenData($tokenData['id']);
+ $checkData = $checkData[$tokenData['id']];
+
+ $this->assertTrue(is_array($checkData));
+ if(!$this->assertEqual($tokenData['id'], $checkData['auth_token_id'])) {
+ $this->gfObj->debug_print($checkData);
}
- if(!$this->assertTrue(($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']) === null), "Able to authenticate twice on a token with only 1 use")) {
- $this->gfObj->debug_print($tok->tokenData($tokenData['id']));
- }
+ $this->assertEqual($checkData['max_uses'], null);
}
}//end test_token_basics()
//--------------------------------------------------------------------------
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 13:58:05
|
Revision: 119
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=119&view=rev
Author: crazedsanity
Date: 2009-08-20 13:57:54 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Combine tests into a single batch of tests: this allows for doing database changes without affecting other tests (and potentially rebuilding the db after every test).
Added Paths:
-----------
trunk/0.3/tests/testOfCSWebAppLibs.php
Removed Paths:
-------------
trunk/0.3/tests/testOfAuthToken.php
trunk/0.3/tests/testOfCSVersionParse.php
Deleted: trunk/0.3/tests/testOfAuthToken.php
===================================================================
--- trunk/0.3/tests/testOfAuthToken.php 2009-08-20 02:20:49 UTC (rev 118)
+++ trunk/0.3/tests/testOfAuthToken.php 2009-08-20 13:57:54 UTC (rev 119)
@@ -1,104 +0,0 @@
-<?php
-/*
- * Created on Jan 25, 2009
- *
- * FILE INFORMATION:
- *
- * $HeadURL$
- * $Id$
- * $LastChangedDate$
- * $LastChangedBy$
- * $LastChangedRevision$
- */
-
-require_once(dirname(__FILE__) .'/../cs_authToken.class.php');
-
-class testOfCSAuthToken extends UnitTestCase {
-
- //--------------------------------------------------------------------------
- function __construct() {
- $this->gfObj = new cs_globalFunctions;
- $this->gfObj->debugPrintOpt=1;
- }//end __construct()
- //--------------------------------------------------------------------------
-
-
-
- //--------------------------------------------------------------------------
- private function create_db() {
- $dbParams = array(
- 'host' => constant('DB_PG_HOST'),
- 'dbname' => constant('DB_PG_DBNAME'),
- 'user' => constant('DB_PG_DBUSER'),
- 'password' => constant('DB_PG_DBPASS'),
- 'port' => constant('DB_PG_PORT')
- );
- $db = new cs_phpDB(constant('DBTYPE'));
- $db->connect($dbParams);
- return($db);
- }//end create_db()
- //--------------------------------------------------------------------------
-
-
- //--------------------------------------------------------------------------
- function test_basics() {
- $db = $this->create_db();
- $tok = new authTokenTester($db);
-
- //Generic test to ensure we get the appropriate data back.
- $tokenData = $tok->create_token(1, 'test', 'abc123');
- $this->assertTrue(is_array($tokenData));
- $this->assertTrue((count($tokenData) == 2));
- $this->assertTrue(isset($tokenData['id']));
- $this->assertTrue(isset($tokenData['hash']));
- $this->assertTrue(($tokenData['id'] > 0));
- $this->assertTrue((strlen($tokenData['hash']) == 32));
-
- $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
-
-
- //now create a token with a maximum lifetime...
- {
- //Generic test to ensure we get the appropriate data back.
- $tokenData = $tok->create_token(1, 'test', 'abc123', '2 years');
- $this->assertTrue(is_array($tokenData));
- $this->assertTrue((count($tokenData) == 2));
- $this->assertTrue(isset($tokenData['id']));
- $this->assertTrue(isset($tokenData['hash']));
- $this->assertTrue(($tokenData['id'] > 0));
- $this->assertTrue((strlen($tokenData['hash']) == 32));
-
- $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
- }
-
- //create a token with only 1 available use and try to authenticate it twice.
- {
- //Generic test to ensure we get the appropriate data back.
- $tokenData = $tok->create_token(1, 'test', 'abc123', null, 1);
- $this->assertTrue(is_array($tokenData));
- $this->assertTrue((count($tokenData) == 2));
- $this->assertTrue(isset($tokenData['id']));
- $this->assertTrue(isset($tokenData['hash']));
- $this->assertTrue(($tokenData['id'] > 0));
- $this->assertTrue((strlen($tokenData['hash']) == 32));
-
- if(!$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1)) {
- $this->gfObj->debug_print($tok->tokenData($tokenData['id']),1);
- }
- if(!$this->assertTrue(($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']) === null), "Able to authenticate twice on a token with only 1 use")) {
- $this->gfObj->debug_print($tok->tokenData($tokenData['id']));
- }
- }
- }//end test_basics()
- //--------------------------------------------------------------------------
-}
-
-class authTokenTester extends cs_authToken {
- public $isTest=true;
-
- public function tokenData($id) {
- return($this->get_token_data($id));
- }
-}
-
-?>
Deleted: trunk/0.3/tests/testOfCSVersionParse.php
===================================================================
--- trunk/0.3/tests/testOfCSVersionParse.php 2009-08-20 02:20:49 UTC (rev 118)
+++ trunk/0.3/tests/testOfCSVersionParse.php 2009-08-20 13:57:54 UTC (rev 119)
@@ -1,127 +0,0 @@
-<?php
-/*
- * Created on Jan 25, 2009
- *
- * FILE INFORMATION:
- *
- * $HeadURL$
- * $Id$
- * $LastChangedDate$
- * $LastChangedBy$
- * $LastChangedRevision$
- */
-
-
-
-class testOfCSVersionParse extends UnitTestCase {
-
- function __construct() {
- $this->gfObj = new cs_globalFunctions;
- }//end __construct()
-
-
- //--------------------------------------------------------------------------
- function test_basics() {
-
- $tests = array(
- 'files/version1' => array(
- '0.1.2-ALPHA8754',
- 'test1',
- array(
- 'version_major' => 0,
- 'version_minor' => 1,
- 'version_maintenance' => 2,
- 'version_suffix' => 'ALPHA8754'
- )
- ),
- 'files/version2' => array(
- '5.4.0',
- 'test2',
- array(
- 'version_major' => 5,
- 'version_minor' => 4,
- 'version_maintenance' => 0,
- 'version_suffix' => null
- )
- ),
- 'files/version3' => array(
- '5.4.3-BETA5543',
- 'test3 stuff',
- array(
- 'version_major' => 5,
- 'version_minor' => 4,
- 'version_maintenance' => 3,
- 'version_suffix' => 'BETA5543'
- )
- )
- );
-
- foreach($tests as $fileName=>$expectedArr) {
- $ver = new middleTestClass();
- $ver->set_version_file_location(dirname(__FILE__) .'/'. $fileName);
-
- $this->assertEqual($expectedArr[0], $ver->get_version(), "Failed to match string from file (". $fileName .")");
- $this->assertEqual($expectedArr[1], $ver->get_project(), "Failed to match project from file (". $fileName .")");
-
- //now check that pulling the version as an array is the same...
- $checkItArr = $ver->get_version(true);
- $expectThis = $expectedArr[2];
- $expectThis['version_string'] = $expectedArr[0];
- }
- }//end test_basics()
- //--------------------------------------------------------------------------
-
-
-
- //--------------------------------------------------------------------------
- function test_check_higher() {
-
- //NOTE: the first item should ALWAYS be higher.
- $tests = array(
- 'basic, no suffix' => array('1.0.1', '1.0.0'),
- 'basic + suffix' => array('1.0.0-ALPHA1', '1.0.0-ALPHA0'),
- 'basic w/o maint' => array('1.0.1', '1.0'),
- 'suffix check' => array('1.0.0-BETA1', '1.0.0-ALPHA1'),
- 'suffix check2' => array('1.0.0-ALPHA10', '1.0.0-ALPHA1'),
- 'suffix check3' => array('1.0.1', '1.0.0-RC1')
- );
-
- foreach($tests as $name=>$checkData) {
- $ver = new middleTestClass;
- $this->assertTrue($ver->is_higher_version($checkData[1], $checkData[0]));
- $this->assertFalse($ver->is_higher_version($checkData[0], $checkData[1]));
- }
-
- //now check to ensure there's no problem with parsing equivalent versions.
- $tests = array(
- 'no suffix' => array('1.0', '1.0.0'),
- 'no maint + suffix' => array('1.0-ALPHA1', '1.0.0-ALPHA1'),
- 'no maint + BETA' => array('1.0-BETA5555', '1.0.0-BETA5555'),
- 'no maint + RC' => array('1.0-RC33', '1.0.0-RC33'),
- 'maint with space' => array('1.0-RC 33', '1.0.0-RC33'),
- 'extra spaces' => array(' 1.0 ', '1.0.0')
- );
- foreach($tests as $name=>$checkData) {
- $ver = new middleTestClass;
-
- //rip apart & recreate first version to test against the expected...
- $derivedFullVersion = $ver->build_full_version_string($ver->parse_version_string($checkData[0]));
- $this->assertEqual($derivedFullVersion, $checkData[1], "TEST=(". $name ."): derived version " .
- "(". $derivedFullVersion .") doesn't match expected (". $checkData[1] .")");
-
- //now rip apart & recreate the expected version (second) and make sure it matches itself.
- $derivedFullVersion = $ver->build_full_version_string($ver->parse_version_string($checkData[1]));
- $this->assertEqual($derivedFullVersion, $checkData[1], "TEST=(". $name ."): derived version " .
- "(". $derivedFullVersion .") doesn't match expected (". $checkData[1] .")");
- }
-
-
- }//end test_check_higher()
- //--------------------------------------------------------------------------
-}
-
-
-class middleTestClass extends cs_versionAbstract {
- function __construct(){}
-}
-?>
Copied: trunk/0.3/tests/testOfCSWebAppLibs.php (from rev 117, trunk/0.3/tests/testOfCSVersionParse.php)
===================================================================
--- trunk/0.3/tests/testOfCSWebAppLibs.php (rev 0)
+++ trunk/0.3/tests/testOfCSWebAppLibs.php 2009-08-20 13:57:54 UTC (rev 119)
@@ -0,0 +1,209 @@
+<?php
+/*
+ * Created on Jan 25, 2009
+ *
+ * FILE INFORMATION:
+ *
+ * $HeadURL$
+ * $Id$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ */
+
+require_once(dirname(__FILE__) .'/../cs_version.abstract.class.php');
+require_once(dirname(__FILE__) .'/../cs_authToken.class.php');
+
+class testOfCSWebAppLibs extends UnitTestCase {
+
+ //--------------------------------------------------------------------------
+ function __construct() {
+ $this->gfObj = new cs_globalFunctions;
+ $this->gfObj->debugPrintOpt=1;
+ }//end __construct()
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
+ function test_version_basics() {
+
+ $tests = array(
+ 'files/version1' => array(
+ '0.1.2-ALPHA8754',
+ 'test1',
+ array(
+ 'version_major' => 0,
+ 'version_minor' => 1,
+ 'version_maintenance' => 2,
+ 'version_suffix' => 'ALPHA8754'
+ )
+ ),
+ 'files/version2' => array(
+ '5.4.0',
+ 'test2',
+ array(
+ 'version_major' => 5,
+ 'version_minor' => 4,
+ 'version_maintenance' => 0,
+ 'version_suffix' => null
+ )
+ ),
+ 'files/version3' => array(
+ '5.4.3-BETA5543',
+ 'test3 stuff',
+ array(
+ 'version_major' => 5,
+ 'version_minor' => 4,
+ 'version_maintenance' => 3,
+ 'version_suffix' => 'BETA5543'
+ )
+ )
+ );
+
+ foreach($tests as $fileName=>$expectedArr) {
+ $ver = new middleTestClass();
+ $ver->set_version_file_location(dirname(__FILE__) .'/'. $fileName);
+
+ $this->assertEqual($expectedArr[0], $ver->get_version(), "Failed to match string from file (". $fileName .")");
+ $this->assertEqual($expectedArr[1], $ver->get_project(), "Failed to match project from file (". $fileName .")");
+
+ //now check that pulling the version as an array is the same...
+ $checkItArr = $ver->get_version(true);
+ $expectThis = $expectedArr[2];
+ $expectThis['version_string'] = $expectedArr[0];
+ }
+ }//end test_version_basics()
+ //--------------------------------------------------------------------------
+
+
+
+ //--------------------------------------------------------------------------
+ function test_check_higher() {
+
+ //NOTE: the first item should ALWAYS be higher.
+ $tests = array(
+ 'basic, no suffix' => array('1.0.1', '1.0.0'),
+ 'basic + suffix' => array('1.0.0-ALPHA1', '1.0.0-ALPHA0'),
+ 'basic w/o maint' => array('1.0.1', '1.0'),
+ 'suffix check' => array('1.0.0-BETA1', '1.0.0-ALPHA1'),
+ 'suffix check2' => array('1.0.0-ALPHA10', '1.0.0-ALPHA1'),
+ 'suffix check3' => array('1.0.1', '1.0.0-RC1')
+ );
+
+ foreach($tests as $name=>$checkData) {
+ $ver = new middleTestClass;
+ $this->assertTrue($ver->is_higher_version($checkData[1], $checkData[0]));
+ $this->assertFalse($ver->is_higher_version($checkData[0], $checkData[1]));
+ }
+
+ //now check to ensure there's no problem with parsing equivalent versions.
+ $tests = array(
+ 'no suffix' => array('1.0', '1.0.0'),
+ 'no maint + suffix' => array('1.0-ALPHA1', '1.0.0-ALPHA1'),
+ 'no maint + BETA' => array('1.0-BETA5555', '1.0.0-BETA5555'),
+ 'no maint + RC' => array('1.0-RC33', '1.0.0-RC33'),
+ 'maint with space' => array('1.0-RC 33', '1.0.0-RC33'),
+ 'extra spaces' => array(' 1.0 ', '1.0.0')
+ );
+ foreach($tests as $name=>$checkData) {
+ $ver = new middleTestClass;
+
+ //rip apart & recreate first version to test against the expected...
+ $derivedFullVersion = $ver->build_full_version_string($ver->parse_version_string($checkData[0]));
+ $this->assertEqual($derivedFullVersion, $checkData[1], "TEST=(". $name ."): derived version " .
+ "(". $derivedFullVersion .") doesn't match expected (". $checkData[1] .")");
+
+ //now rip apart & recreate the expected version (second) and make sure it matches itself.
+ $derivedFullVersion = $ver->build_full_version_string($ver->parse_version_string($checkData[1]));
+ $this->assertEqual($derivedFullVersion, $checkData[1], "TEST=(". $name ."): derived version " .
+ "(". $derivedFullVersion .") doesn't match expected (". $checkData[1] .")");
+ }
+
+
+ }//end test_check_higher()
+ //--------------------------------------------------------------------------
+
+
+
+ //--------------------------------------------------------------------------
+ private function create_db() {
+ $dbParams = array(
+ 'host' => constant('DB_PG_HOST'),
+ 'dbname' => constant('DB_PG_DBNAME'),
+ 'user' => constant('DB_PG_DBUSER'),
+ 'password' => constant('DB_PG_DBPASS'),
+ 'port' => constant('DB_PG_PORT')
+ );
+ $db = new cs_phpDB(constant('DBTYPE'));
+ $db->connect($dbParams);
+ return($db);
+ }//end create_db()
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
+ function test_token_basics() {
+ $db = $this->create_db();
+ $tok = new authTokenTester($db);
+
+ //Generic test to ensure we get the appropriate data back.
+ $tokenData = $tok->create_token(1, 'test', 'abc123');
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
+
+ $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
+
+
+ //now create a token with a maximum lifetime...
+ {
+ //Generic test to ensure we get the appropriate data back.
+ $tokenData = $tok->create_token(1, 'test', 'abc123', '2 years');
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
+
+ $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
+ }
+
+ //create a token with only 1 available use and try to authenticate it twice.
+ {
+ //Generic test to ensure we get the appropriate data back.
+ $tokenData = $tok->create_token(1, 'test', 'abc123', null, 1);
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
+
+ if(!$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1)) {
+ $this->gfObj->debug_print($tok->tokenData($tokenData['id']),1);
+ }
+ if(!$this->assertTrue(($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']) === null), "Able to authenticate twice on a token with only 1 use")) {
+ $this->gfObj->debug_print($tok->tokenData($tokenData['id']));
+ }
+ }
+ }//end test_token_basics()
+ //--------------------------------------------------------------------------
+}
+
+
+class middleTestClass extends cs_versionAbstract {
+ function __construct(){}
+}
+
+class authTokenTester extends cs_authToken {
+ public $isTest=true;
+
+ public function tokenData($id) {
+ return($this->get_token_data($id));
+ }
+}
+?>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 02:20:56
|
Revision: 118
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=118&view=rev
Author: crazedsanity
Date: 2009-08-20 02:20:49 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Add missing requirement for cs_webdbupgrade.
Modified Paths:
--------------
trunk/0.3/cs_webdblogger.class.php
Modified: trunk/0.3/cs_webdblogger.class.php
===================================================================
--- trunk/0.3/cs_webdblogger.class.php 2009-08-20 01:59:58 UTC (rev 117)
+++ trunk/0.3/cs_webdblogger.class.php 2009-08-20 02:20:49 UTC (rev 118)
@@ -28,6 +28,7 @@
//NOTE::: this class **REQUIRES** cs-content for its "cs_phpDB" class.
require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
+require_once(dirname(__FILE__) .'/cs_webdbupgrade.class.php');
class cs_webdblogger extends cs_webapplibsAbstract {
/** Database handle */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 02:00:08
|
Revision: 117
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=117&view=rev
Author: crazedsanity
Date: 2009-08-20 01:59:58 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Updated test to work (last commit removed wrong method).
Modified Paths:
--------------
trunk/0.3/tests/testOfAuthToken.php
Modified: trunk/0.3/tests/testOfAuthToken.php
===================================================================
--- trunk/0.3/tests/testOfAuthToken.php 2009-08-20 01:50:46 UTC (rev 116)
+++ trunk/0.3/tests/testOfAuthToken.php 2009-08-20 01:59:58 UTC (rev 117)
@@ -25,18 +25,21 @@
//--------------------------------------------------------------------------
- function setUp() {
- $tok = new cs_authToken($this->create_db());
- try {
- $tok->load_table();
- }
- catch(exception $e) {
- }
- }//end setUp()
+ private function create_db() {
+ $dbParams = array(
+ 'host' => constant('DB_PG_HOST'),
+ 'dbname' => constant('DB_PG_DBNAME'),
+ 'user' => constant('DB_PG_DBUSER'),
+ 'password' => constant('DB_PG_DBPASS'),
+ 'port' => constant('DB_PG_PORT')
+ );
+ $db = new cs_phpDB(constant('DBTYPE'));
+ $db->connect($dbParams);
+ return($db);
+ }//end create_db()
//--------------------------------------------------------------------------
-
//--------------------------------------------------------------------------
function test_basics() {
$db = $this->create_db();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 01:51:04
|
Revision: 116
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=116&view=rev
Author: crazedsanity
Date: 2009-08-20 01:50:46 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Incorporate upgrades from cs-webdblogger v0.2.0 into the main schema.
Modified Paths:
--------------
trunk/0.3/setup/schema.mysql.sql
trunk/0.3/setup/schema.pgsql.sql
trunk/0.3/upgrades/upgrade.xml
Removed Paths:
-------------
trunk/0.3/upgrades/sql/
trunk/0.3/upgrades/upgradeTo0.2.0.php
trunk/0.3/upgrades/upgradeTo0.2.1.php
Modified: trunk/0.3/setup/schema.mysql.sql
===================================================================
--- trunk/0.3/setup/schema.mysql.sql 2009-08-20 01:44:14 UTC (rev 115)
+++ trunk/0.3/setup/schema.mysql.sql 2009-08-20 01:50:46 UTC (rev 116)
@@ -92,6 +92,50 @@
--
ALTER TABLE `cswdbl_log_table`
ADD CONSTRAINT `cswdbl_log_table_event_id_fkey` FOREIGN KEY (`event_id`) REFERENCES `cswdbl_event_table` (`event_id`);
+
+
+
+--
+-- Table structure for table `cswdbl_log_attribute_table`
+--
+
+CREATE TABLE `cswdbl_log_attribute_table` (
+ `log_attribute_id` int(11) NOT NULL auto_increment,
+ `log_id` int(11) NOT NULL,
+ `attribute_id` int(11) NOT NULL,
+ `value_text` text NOT NULL,
+ PRIMARY KEY (`log_attribute_id`),
+ KEY `cswdbl_log_attribute_table_log_id_fkey` (`log_id`),
+ KEY `cswdbl_log_attribute_table_attribute_id_fkey` (`attribute_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `cswdbl_log_table`
+--
+
+CREATE TABLE `cswdbl_log_table` (
+ `log_id` int(11) NOT NULL auto_increment,
+ `creation` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `event_id` int(11) NOT NULL,
+ `uid` int(11) NOT NULL,
+ `affected_uid` int(11) NOT NULL,
+ `details` text NOT NULL,
+ PRIMARY KEY (`log_id`),
+ KEY `cswdbl_log_table_event_id_fkey` (`event_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
+
+
+
+--
+-- Constraints for table `cswdbl_log_attribute_table`
+--
+ALTER TABLE `cswdbl_log_attribute_table`
+ ADD CONSTRAINT `cswdbl_log_attribute_table_attribute_id_fkey` FOREIGN KEY (`attribute_id`) REFERENCES `cswdbl_attribute_table` (`attribute_id`),
+ ADD CONSTRAINT `cswdbl_log_attribute_table_log_id_fkey` FOREIGN KEY (`log_id`) REFERENCES `cswdbl_log_table` (`log_id`);
+
+
-- This table create statement MUST work in PostgreSQL v8.2.x+ AND MySQL v5.0.x+:
Modified: trunk/0.3/setup/schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/schema.pgsql.sql 2009-08-20 01:44:14 UTC (rev 115)
+++ trunk/0.3/setup/schema.pgsql.sql 2009-08-20 01:50:46 UTC (rev 116)
@@ -63,6 +63,25 @@
details text NOT NULL
);
+
+--
+-- List of distinct attribute names.
+--
+CREATE TABLE cswdbl_attribute_table (
+ attribute_id serial NOT NULL PRIMARY KEY,
+ attribute_name text NOT NULL UNIQUE
+);
+
+--
+-- Linkage for attributes to logs.
+--
+CREATE TABLE cswdbl_log_attribute_table (
+ log_attribute_id serial NOT NULL PRIMARY KEY,
+ log_id int NOT NULL REFERENCES cswdbl_log_table(log_id),
+ attribute_id int NOT NULL REFERENCES cswdbl_attribute_table(attribute_id),
+ value_text text
+);
+
-- This table create statement MUST work in PostgreSQL v8.2.x+ AND MySQL v5.0.x+:
-- otherwise separate schema files have to be created and the code will have to
-- do extra checking...
Modified: trunk/0.3/upgrades/upgrade.xml
===================================================================
--- trunk/0.3/upgrades/upgrade.xml 2009-08-20 01:44:14 UTC (rev 115)
+++ trunk/0.3/upgrades/upgrade.xml 2009-08-20 01:50:46 UTC (rev 116)
@@ -18,12 +18,5 @@
to get skipped, or an exception to be thrown, potentially leaving the system
in an unstable state. Unstable is bad, m'kay?</system_note>
- <matching>
- <v0.2.0>
- <target_version>0.2.1</target_version>
- <script_name>upgradeTo0.2.1.php</script_name>
- <class_name>upgrade_to_0_2_1</class_name>
- <call_method>run_upgrade</call_method>
- </v0.2.0>
- </matching>
+ <matching />
</upgrade>
Deleted: trunk/0.3/upgrades/upgradeTo0.2.0.php
===================================================================
--- trunk/0.3/upgrades/upgradeTo0.2.0.php 2009-08-20 01:44:14 UTC (rev 115)
+++ trunk/0.3/upgrades/upgradeTo0.2.0.php 2009-08-20 01:50:46 UTC (rev 116)
@@ -1,95 +0,0 @@
-<?php
-
-class upgrade_to_0_2_0 {
-
- //=========================================================================
- public function __construct(cs_phpDB &$db) {
- if(!$db->is_connected()) {
- throw new exception(__METHOD__ .": database is not connected");
- }
- $this->db = $db;
-
- $this->gfObj = new cs_globalFunctions;
- $this->gfObj->debugPrintOpt = 1;
-
- }//end __construct()
- //=========================================================================
-
-
-
- //=========================================================================
- public function run_upgrade() {
-
-
- $upgradeFilename = dirname(__FILE__) ."/sql/upgradeTo0_2_0.". $this->db->get_dbtype() .".sql";
- if(!file_exists($upgradeFilename)) {
- throw new exception(__METHOD__ .": missing upgrade filename (". $upgradeFilename ."), " .
- "probably due to unsupported database type (". $this->db->get_dbtype() .")");
- }
-
-
- $tables = array(
- 'cat' => array(
- 'cswdbl_category_table',
- 'log_category_table',
- 'category_id'
- ),
- 'class' => array(
- 'cswdbl_class_table',
- 'log_class_table',
- 'class_id'
- ),
- 'event' => array(
- 'cswdbl_event_table',
- 'log_event_table',
- 'event_id'
- ),
- 'log' => array(
- 'cswdbl_log_table',
- 'log_table',
- 'log_id'
- )
- );
-
- //run the SQL file.
- $file = dirname(__FILE__) .'/sql/upgradeTo0_2_0.'. $this->db->get_dbtype() .'.sql';
- $upgradeRes = false;
- if(file_exists($file)) {
- $this->db->run_update(file_get_contents($file),true);
- $totalToSync = count($tables);
- $totalSynced = 0;
-
- //now make sure there's the same amount of data in BOTH tables.
- foreach($tables as $key => $tables) {
- $c1 = $this->db->run_query("SELECT * FROM ". $tables[0]);
- $num1 = $this->db->numRows();
- $c2 = $this->db->run_query("SELECT * FROM ". $tables[1]);
- $num2 = $this->db->numRows();
-
- if($num1 === $num2) {
- $totalSynced++;
- $this->db->run_update("DROP TABLE ". $tables[1] ." CASCADE", true);
-
- if($this->db->get_dbtype() == 'pgsql') {
- //Update the sequence...
- $seq = $tables[0] .'_'. $tables[2] .'_seq';
- $this->db->run_update("SELECT setval('". $seq ."', (SELECT max(". $tables[2] .") FROM ". $tables[0] ."))",true);
- }
- }
- else {
- throw new exception(__METHOD__ .": failed to sync ". $tables[0] ." with ". $tables[1] ." (". $num1 ." != ". $num2 .")");
- }
- }
- $upgradeRes = true;
- }
- else {
- throw new exception(__METHOD__ .": missing upgrade SQL file (". $file .")");
- }
-
- return($upgradeRes);
-
- }//end run_upgrade()
- //=========================================================================
-}
-
-?>
Deleted: trunk/0.3/upgrades/upgradeTo0.2.1.php
===================================================================
--- trunk/0.3/upgrades/upgradeTo0.2.1.php 2009-08-20 01:44:14 UTC (rev 115)
+++ trunk/0.3/upgrades/upgradeTo0.2.1.php 2009-08-20 01:50:46 UTC (rev 116)
@@ -1,47 +0,0 @@
-<?php
-
-class upgrade_to_0_2_1 {
-
- //=========================================================================
- public function __construct(cs_phpDB &$db) {
- if(!$db->is_connected()) {
- throw new exception(__METHOD__ .": database is not connected");
- }
- $this->db = $db;
-
- $this->gfObj = new cs_globalFunctions;
- $this->gfObj->debugPrintOpt = 1;
-
- }//end __construct()
- //=========================================================================
-
-
-
- //=========================================================================
- public function run_upgrade() {
-
-
- $upgradeFilename = dirname(__FILE__) ."/sql/upgradeTo0_2_1.". $this->db->get_dbtype() .".sql";
- if(!file_exists($upgradeFilename)) {
- throw new exception(__METHOD__ .": missing upgrade filename (". $upgradeFilename ."), " .
- "probably due to unsupported database type (". $this->db->get_dbtype() .")");
- }
-
- //run the SQL file.
- $file = dirname(__FILE__) .'/sql/upgradeTo0_2_1.'. $this->db->get_dbtype() .'.sql';
- $upgradeRes = false;
- if(file_exists($file)) {
- $this->db->run_update(file_get_contents($file),true);
- $upgradeRes = true;
- }
- else {
- throw new exception(__METHOD__ .": missing upgrade SQL file (". $file .")");
- }
-
- return($upgradeRes);
-
- }//end run_upgrade()
- //=========================================================================
-}
-
-?>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-20 01:44:23
|
Revision: 115
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=115&view=rev
Author: crazedsanity
Date: 2009-08-20 01:44:14 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
Updated schema, tests, & set cs_authToken to be MySQL-compatible.
TODO::: incorporate changes in cs-webdbupgrade that include the attribute
tables into the main SQL file(s).
/cs_authToken.class.php:
* load_table() [DELETED]:
-- this table should be included in with all the other tables.
* create_token():
-- set a default value for expiration so the database doesn't have to
set that.
-- NOTE::: any tokens with a NULL expiration and unlimited uses will
NEVER be automatically removed.
/cs_webdbupgrade.class.php:
* __construct():
-- set DB_TABLE and DB_PRIMARYKEY to hardcoded values.
* load_table():
-- updated location of schema file
-- NOTE::: this should probably be named "load_schema()", as it is
actually loading several different tables now.
/setup/authtoken_schema.pgsql.sql [DELETED]:
* incorporated into the pgsql & mysql schema files.
/setup/schema.mysql.sql:
* changed "cs_version_table" to cswal_version_table (cswal ==
CS-WebAppLibs), removed unnecessary columns (previously removed in
cs-webdbupgrade v0.2.0).
* create cswal_auth_token_table.
/setup/schema.pgsql.sql:
* (same as the mysql version).
/tests/testOfAuthToken.php:
* remove code for creating & destroying tables (NOTE: my test site
actually destroys & rebuilds the entire database... this should probably
be changed to a series of "DROP TABLE" statements).
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/cs_webdbupgrade.class.php
trunk/0.3/setup/schema.mysql.sql
trunk/0.3/setup/schema.pgsql.sql
trunk/0.3/tests/testOfAuthToken.php
Removed Paths:
-------------
trunk/0.3/setup/authtoken_schema.pgsql.sql
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-19 20:12:33 UTC (rev 114)
+++ trunk/0.3/cs_authToken.class.php 2009-08-20 01:44:14 UTC (rev 115)
@@ -48,29 +48,6 @@
//=========================================================================
/**
- * Load table into the database...
- */
- public function load_table() {
- $file = dirname(__FILE__) .'/setup/authtoken_schema.'. $this->db->get_dbtype() .'.sql';
-
- if(file_exists($file)) {
- try {
- $this->db->run_update(file_get_contents($file), true);
- }
- catch(exception $e) {
- throw new exception(__METHOD__ .": error while trying to load table::: ". $e->getMessage());
- }
- }
- else {
- throw new exception(__METHOD__ .": unsupported database type (". $this->db->get_dbtype() .")");
- }
- }//end load_table()
- //=========================================================================
-
-
-
- //=========================================================================
- /**
* Standardized method of creating a hash from a string.
*
* @param $tokenId (int) matches auth_token_id column....
@@ -110,6 +87,8 @@
'checksum' => $checksum,
'token' => '____INCOMPLETE____'
);
+
+ $insertData['expiration'] = strftime('%Y-%m-%d %T', strtotime('1 day'));
if(!is_null($lifetime) && strlen($lifetime)) {
$insertData['expiration'] = strftime('%Y-%m-%d %T', strtotime($lifetime));
}
Modified: trunk/0.3/cs_webdbupgrade.class.php
===================================================================
--- trunk/0.3/cs_webdbupgrade.class.php 2009-08-19 20:12:33 UTC (rev 114)
+++ trunk/0.3/cs_webdbupgrade.class.php 2009-08-20 01:44:14 UTC (rev 115)
@@ -99,13 +99,8 @@
$this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT');
}
- if(!defined(__CLASS__ .'-DB_PRIMARYKEY') || !defined(__CLASS__ .'-DB_TABLE')) {
- throw new exception(__METHOD__ .": no setting for DB_TABLE or DB_PRIMARYKEY, cannot continue");
- }
- else {
- $this->config['DB_TABLE'] = constant(__CLASS__ .'-DB_TABLE');
- $this->config['DB_PRIMARYKEY'] = constant(__CLASS__ .'-DB_PRIMARYKEY');
- }
+ $this->config['DB_TABLE'] = 'cswal_version_table';
+ $this->config['DB_PRIMARYKEY'] = 'version_id';
$this->sequenceName = $this->config['DB_TABLE'] .'_'. $this->config['DB_PRIMARYKEY'] .'_seq';
if(!defined('DBTYPE')) {
@@ -908,7 +903,7 @@
//=========================================================================
public function load_table() {
- $schemaFileLocation = dirname(__FILE__) .'/schema/schema.sql';
+ $schemaFileLocation = dirname(__FILE__) .'/setup/schema.'. $this->db->get_dbtype() .'.sql';
$schema = file_get_contents($schemaFileLocation);
$schema = str_replace('{tableName}', $this->config['DB_TABLE'], $schema);
$schema = str_replace('{primaryKey}', $this->config['DB_PRIMARYKEY'], $schema);
Deleted: trunk/0.3/setup/authtoken_schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 20:12:33 UTC (rev 114)
+++ trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-20 01:44:14 UTC (rev 115)
@@ -1,20 +0,0 @@
---
--- SVN INFORMATION:::
--- ---------------
--- SVN Signature::::::: $Id$
--- Last Author::::::::: $Author$
--- Current Revision:::: $Revision$
--- Repository Location: $HeadURL$
--- Last Updated:::::::: $Date$
---
-
-CREATE TABLE cswal_auth_token_table (
- auth_token_id serial NOT NULL PRIMARY KEY,
- uid integer NOT NULL DEFAULT 0,
- checksum text NOT NULL,
- token text NOT NULL,
- max_uses integer DEFAULT NULL,
- total_uses integer NOT NULL DEFAULT 0,
- creation timestamp NOT NULL DEFAULT NOW(),
- expiration timestamp NOT NULL DEFAULT NOW() + '1 day'::interval
-);
\ No newline at end of file
Modified: trunk/0.3/setup/schema.mysql.sql
===================================================================
--- trunk/0.3/setup/schema.mysql.sql 2009-08-19 20:12:33 UTC (rev 114)
+++ trunk/0.3/setup/schema.mysql.sql 2009-08-20 01:44:14 UTC (rev 115)
@@ -98,14 +98,19 @@
-- otherwise separate schema files have to be created and the code will have to
-- do extra checking...
--
--- The "{tableName}" portion will be replaced with the value of the configured
--- "DB_TABLE" setting.
-CREATE TABLE cs_version_table (
+CREATE TABLE cswal_version_table (
version_id int NOT NULL PRIMARY KEY,
project_name varchar(30) NOT NULL UNIQUE,
- version_string varchar(50) NOT NULL,
- version_major integer NOT NULL,
- version_minor integer NOT NULL,
- version_maintenance integer NOT NULL,
- version_suffix varchar(20) NOT NULL
+ version_string varchar(50) NOT NULL
);
+
+CREATE TABLE cswal_auth_token_table (
+ auth_token_id serial NOT NULL PRIMARY KEY,
+ uid integer NOT NULL DEFAULT 0,
+ checksum text NOT NULL,
+ token text NOT NULL,
+ max_uses integer DEFAULT NULL,
+ total_uses integer NOT NULL DEFAULT 0,
+ creation timestamp NOT NULL DEFAULT NOW(),
+ expiration timestamp NOT NULL
+);
\ No newline at end of file
Modified: trunk/0.3/setup/schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/schema.pgsql.sql 2009-08-19 20:12:33 UTC (rev 114)
+++ trunk/0.3/setup/schema.pgsql.sql 2009-08-20 01:44:14 UTC (rev 115)
@@ -66,13 +66,21 @@
-- This table create statement MUST work in PostgreSQL v8.2.x+ AND MySQL v5.0.x+:
-- otherwise separate schema files have to be created and the code will have to
-- do extra checking...
-CREATE TABLE cs_version_table (
+CREATE TABLE cswal_version_table (
version_id serial NOT NULL PRIMARY KEY,
project_name varchar(30) NOT NULL UNIQUE,
- version_string varchar(50) NOT NULL,
- version_major integer NOT NULL,
- version_minor integer NOT NULL,
- version_maintenance integer NOT NULL,
- version_suffix varchar(20) NOT NULL
+ version_string varchar(50) NOT NULL
);
+
+CREATE TABLE cswal_auth_token_table (
+ auth_token_id serial NOT NULL PRIMARY KEY,
+ uid integer NOT NULL DEFAULT 0,
+ checksum text NOT NULL,
+ token text NOT NULL,
+ max_uses integer DEFAULT NULL,
+ total_uses integer NOT NULL DEFAULT 0,
+ creation timestamp NOT NULL DEFAULT NOW(),
+ expiration timestamp NOT NULL
+);
+
Modified: trunk/0.3/tests/testOfAuthToken.php
===================================================================
--- trunk/0.3/tests/testOfAuthToken.php 2009-08-19 20:12:33 UTC (rev 114)
+++ trunk/0.3/tests/testOfAuthToken.php 2009-08-20 01:44:14 UTC (rev 115)
@@ -38,35 +38,6 @@
//--------------------------------------------------------------------------
- function tearDown() {
- $db = $this->create_db();
- try {
- $db->run_update('DROP TABLE cswal_auth_token_table', true);
- }
- catch(exception $e) {
- }
- }//end
- //--------------------------------------------------------------------------
-
-
-
- //--------------------------------------------------------------------------
- private function create_db() {
- $dbParams = array(
- 'host' => constant('DB_PG_HOST'),
- 'dbname' => constant('DB_PG_DBNAME'),
- 'user' => constant('DB_PG_DBUSER'),
- 'password' => constant('DB_PG_DBPASS'),
- 'port' => constant('DB_PG_PORT')
- );
- $db = new cs_phpDB(constant('DBTYPE'));
- $db->connect($dbParams);
- return($db);
- }//end create_db()
- //--------------------------------------------------------------------------
-
-
- //--------------------------------------------------------------------------
function test_basics() {
$db = $this->create_db();
$tok = new authTokenTester($db);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 20:12:40
|
Revision: 114
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=114&view=rev
Author: crazedsanity
Date: 2009-08-19 20:12:33 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Changes to work with MySQL.
/cs_authToken.class.php:
* create_token():
-- use a combination of strftime(strtotime()) to create an
appropriate expiration date based on a given lifetime (i.e. "1 day").
-- use "expiration" column instead of duration.
* get_token_data():
-- updated to use expiration instead of creation + duration.
/setup/authToken_schema.pgsql.sql:
* cswal_auth_token_table:
-- change creation to a timestamp.
-- change duration(interval) to expiration(timestamp)
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/setup/authtoken_schema.pgsql.sql
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-19 19:24:52 UTC (rev 113)
+++ trunk/0.3/cs_authToken.class.php 2009-08-19 20:12:33 UTC (rev 114)
@@ -111,7 +111,7 @@
'token' => '____INCOMPLETE____'
);
if(!is_null($lifetime) && strlen($lifetime)) {
- $insertData['duration'] = $lifetime;
+ $insertData['expiration'] = strftime('%Y-%m-%d %T', strtotime($lifetime));
}
if(!is_null($maxUses) && is_numeric($maxUses) && $maxUses > 0) {
$insertData['max_uses'] = $maxUses;
@@ -282,7 +282,7 @@
protected function get_token_data($tokenId) {
try {
$data = $this->db->run_query("SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId
- ." AND (creation + duration)::date >= CURRENT_DATE", 'auth_token_id');
+ ." AND expiration::date >= CURRENT_DATE", 'auth_token_id');
if(is_array($data) && count($data) == 1) {
$tokenData = $data;
}
Modified: trunk/0.3/setup/authtoken_schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 19:24:52 UTC (rev 113)
+++ trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 20:12:33 UTC (rev 114)
@@ -15,6 +15,6 @@
token text NOT NULL,
max_uses integer DEFAULT NULL,
total_uses integer NOT NULL DEFAULT 0,
- creation date NOT NULL DEFAULT NOW(),
- duration interval NOT NULL DEFAULT '1 day'::interval
+ creation timestamp NOT NULL DEFAULT NOW(),
+ expiration timestamp NOT NULL DEFAULT NOW() + '1 day'::interval
);
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 19:25:00
|
Revision: 113
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=113&view=rev
Author: crazedsanity
Date: 2009-08-19 19:24:52 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Headers, use get_token_data() in authenticate_token().
/cs_authToken.class.php:
* ADDED HEADERS:
-- __constructor()
-- load_table()
-- create_hash_string()
-- create_token()
-- update_token_uses()
-- destroy_token()
-- authenticate_token()
-- get_token_data()
* authenticate_token():
-- call get_token_data()
-- do extra checking on the return value that was previously in SQL.
* get_token_data():
-- updated to only show records that haven't expired.
-- extra checking for if it returns boolean false.
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-19 19:01:21 UTC (rev 112)
+++ trunk/0.3/cs_authToken.class.php 2009-08-19 19:24:52 UTC (rev 113)
@@ -28,6 +28,9 @@
private $seq = 'cswal_auth_token_table_auth_token_id_seq';
//=========================================================================
+ /**
+ * The CONSTRUCTOR. Sets internal properties & such.
+ */
public function __construct(cs_phpDB $db) {
if($db->is_connected()) {
@@ -44,6 +47,9 @@
//=========================================================================
+ /**
+ * Load table into the database...
+ */
public function load_table() {
$file = dirname(__FILE__) .'/setup/authtoken_schema.'. $this->db->get_dbtype() .'.sql';
@@ -64,6 +70,17 @@
//=========================================================================
+ /**
+ * Standardized method of creating a hash from a string.
+ *
+ * @param $tokenId (int) matches auth_token_id column....
+ * @param $uid (int) matches uid column...
+ * @param $checksum (str) This is the value that can be used by the
+ * calling code to see if the given uid matches
+ * this data (i.e. using an email address/username).
+ * @param $stringToHash (str) Data used to help create a hash, usually
+ * something very unique.
+ */
protected function create_hash_string($tokenId, $uid, $checksum, $stringToHash=NULL) {
return(md5($tokenId ."_". $uid ."_". $checksum ."_". $stringToHash));
}//end create_hash_string()
@@ -72,6 +89,20 @@
//=========================================================================
+ /**
+ * Build a token record in the database that can be authenticated against later.
+ *
+ * @param $uid (int) matches uid column...
+ * @param $checksum (str) matches checksum column...
+ * @param $stringToHash (str) unique value to help build hash from.
+ * @param $lifetime (str,optional) string (interval) representing how
+ * long the token should last.
+ * @param $maxUses (int,optional) Number of times it can be authenticated
+ * against before being removed.
+ *
+ * @return (array) PASS: contains id & hash for the token.
+ * @return (exception) FAIL: exception contains error details.
+ */
public function create_token($uid, $checksum, $stringToHash, $lifetime=null, $maxUses=null) {
$insertData = array(
@@ -112,6 +143,15 @@
//=========================================================================
+ /**
+ * Update the number of times the given token has been used (even if the
+ * maximum uses hasn't been set).
+ *
+ * @param $tokenId (int) auth_token_id to look up.
+ *
+ * @return (int) PASS: updated this many records (should always be 1)
+ * @return (exception) FAIL: exception denotes problem
+ */
protected function update_token_uses($tokenId) {
try {
@@ -129,6 +169,14 @@
//=========================================================================
+ /**
+ * Deletes the given token ID from the database.
+ *
+ * @param $tokenId (int) auth_token_id to delete
+ *
+ * @return (int) PASS: this many were deleted (should always be 1)
+ * @return (exception) FAIL: exception contains error details
+ */
protected function destroy_token($tokenId) {
try {
$sql = "DELETE FROM ". $this->table ." WHERE auth_token_id=". $tokenId;
@@ -162,22 +210,23 @@
* if($tokenUid == $realUid) {
* //token is truly authentic
* }
+ *
+ * @param $tokenId (int) auth_token_id to check against
+ * @param $checksum (str) required 'checksum' value.
+ * @param $hash (str) required 'token' value.
*/
public function authenticate_token($tokenId, $checksum, $hash) {
$authTokenRes = null;
if(is_numeric($tokenId) && strlen($checksum) && strlen($hash) == 32) {
- $sql = "SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId
- ." AND (creation + duration)::date >= CURRENT_DATE";
-
try {
- $data = $this->db->run_query($sql, 'auth_token_id');
+ $data = $this->get_token_data($tokenId);
if(count($data) == 1 && isset($data[$tokenId]) && is_array($data[$tokenId])) {
$data = $data[$tokenId];
- if($data['token'] == $hash && $data['checksum'] == $checksum) {
+ if($data['token'] == $hash && $data['checksum']) {
$methodCall = 'update_token_uses';
if(is_numeric($data['max_uses'])) {
@@ -220,15 +269,34 @@
//=========================================================================
+
//=========================================================================
+ /**
+ * Retrieve data for the given ID.
+ *
+ * @param $tokenId (int) auth_token_id to look up.
+ *
+ * @return (array) PASS: contains data about the given ID
+ * @return (exception) FAIL: exception contains error details.
+ */
protected function get_token_data($tokenId) {
try {
- $data = $this->db->run_query("SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId);
+ $data = $this->db->run_query("SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId
+ ." AND (creation + duration)::date >= CURRENT_DATE", 'auth_token_id');
+ if(is_array($data) && count($data) == 1) {
+ $tokenData = $data;
+ }
+ elseif($data === false) {
+ $tokenData = false;
+ }
+ else {
+ throw new exception("too many records returned (". count($data) .")");
+ }
}
catch(exception $e) {
throw new exception(__METHOD__ .": failed to retrieve tokenId (". $tokenId .")::: ". $e->getMessage());
}
- return($data);
+ return($tokenData);
}//end get_token_data();
//=========================================================================
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 19:01:31
|
Revision: 112
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=112&view=rev
Author: crazedsanity
Date: 2009-08-19 19:01:21 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Can authenticate against a given token.
/cs_authToken.class.php:
* create_token():
-- ARG CHANGE: NEW ARG: #4 ($lifetime=null)
-- ARG CHANGE: NEW ARG: #5 ($maxUses=null)
-- allow setting of duration ($lifetime) or max_uses ($maxUses) when
creating the token.
-- update the $insertData array with 'duration' or 'max_uses' data if
appropriate, based on args #4 and #5
* update_token_uses() [NEW]:
-- updates the number of times a given token has been used.
* destroy_token() [NEW]:
-- deletes a specific token.
* authenticate_token() [NEW]:
-- authenticates the given data against a token.
-- this handles updating uses & destroying tokens that have been used
their maximum number of times: this means that mass token expiration
can be done based purely on creation + duration.
* get_token_data() [NEW]:
-- returns data about the given token.
/setup/authtoken_schema.pgsql.sql:
* cswal_auth_token_table:
-- changed "use_limit" to "max_uses" for sanity.
/tests/testOfAuthToken.php:
* additional tests for authentication.
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/setup/authtoken_schema.pgsql.sql
trunk/0.3/tests/testOfAuthToken.php
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-19 17:44:04 UTC (rev 111)
+++ trunk/0.3/cs_authToken.class.php 2009-08-19 19:01:21 UTC (rev 112)
@@ -72,15 +72,19 @@
//=========================================================================
- public function create_token($uid, $checksum, $stringToHash) {
+ public function create_token($uid, $checksum, $stringToHash, $lifetime=null, $maxUses=null) {
- $this->db->beginTrans();
-
$insertData = array(
'uid' => $uid,
'checksum' => $checksum,
'token' => '____INCOMPLETE____'
);
+ if(!is_null($lifetime) && strlen($lifetime)) {
+ $insertData['duration'] = $lifetime;
+ }
+ if(!is_null($maxUses) && is_numeric($maxUses) && $maxUses > 0) {
+ $insertData['max_uses'] = $maxUses;
+ }
try {
$sql = "INSERT INTO cswal_auth_token_table ".
$this->gfObj->string_from_array($insertData, 'insert', null, 'sql');
@@ -105,5 +109,128 @@
}//end create_token()
//=========================================================================
+
+
+ //=========================================================================
+ protected function update_token_uses($tokenId) {
+
+ try {
+ $sql = "UPDATE ". $this->table ." SET total_uses= total_uses+1 " .
+ "WHERE auth_token_id=". $tokenId;
+ $updateRes = $this->db->run_update($sql);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to update usage count::: ". $e->getMessage());
+ }
+ return($updateRes);
+ }//end update_token_uses()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ protected function destroy_token($tokenId) {
+ try {
+ $sql = "DELETE FROM ". $this->table ." WHERE auth_token_id=". $tokenId;
+ $deleteRes = $this->db->run_update($sql);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to ");
+ }
+
+ return($deleteRes);
+ }//end destroy_token()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Determine if a token is authentic: the id is used to make the search as
+ * fast as possible, while the hash & checksum are given to compare against.
+ * Failure results in FALSE, while success returns the contact_id for the
+ * given token.
+ *
+ * NOTE: the calling program can leave it to this method to say if the
+ * token is authentic, or use a checksum which can in turn be used to get
+ * a specific contact_id; when they authenticate, the return of this
+ * method must then match the contact_id retrieved from the checksum...
+ *
+ * EXAMPLE:
+ * $tokenUid = cs_authToken::authenticate_token($tokenId, $hash, $checksum);
+ * $realUid = userClass::get_uid_from_email($checksum);
+ * if($tokenUid == $realUid) {
+ * //token is truly authentic
+ * }
+ */
+ public function authenticate_token($tokenId, $checksum, $hash) {
+
+ $authTokenRes = null;
+
+ if(is_numeric($tokenId) && strlen($checksum) && strlen($hash) == 32) {
+ $sql = "SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId
+ ." AND (creation + duration)::date >= CURRENT_DATE";
+
+ try {
+ $data = $this->db->run_query($sql, 'auth_token_id');
+
+ if(count($data) == 1 && isset($data[$tokenId]) && is_array($data[$tokenId])) {
+ $data = $data[$tokenId];
+
+ if($data['token'] == $hash && $data['checksum'] == $checksum) {
+
+ $methodCall = 'update_token_uses';
+ if(is_numeric($data['max_uses'])) {
+ $authTokenRes = null;
+ if($data['max_uses'] == $data['total_uses']) {
+ //reached max uses already... (maybe this should throw an exception?)
+ $methodCall = 'destroy_token';
+ }
+ elseif($data['total_uses'] < $data['max_uses']) {
+ $authTokenRes = $data['uid'];
+ if(($data['total_uses'] +1) == $data['max_uses']) {
+ //this is the last use: just destroy it.
+ $methodCall = 'destroy_token';
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": token (". $tokenId .") used more than max allowed uses [total=". $data['total_uses'] .", max=". $data['max_uses'] ."]");
+ }
+ }
+ else {
+ $authTokenRes = $data['uid'];
+ }
+ $this->$methodCall($tokenId);
+ }
+ }
+ elseif($data === false) {
+ $authTokenRes = null;
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid data returned:: ". $this->gfObj->debug_var_dump($data,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to authenticate token::: ". $e->getMessage());
+ }
+ }
+
+ return($authTokenRes);
+ }//end authenticate_token()
+ //=========================================================================
+
+
+ //=========================================================================
+ protected function get_token_data($tokenId) {
+ try {
+ $data = $this->db->run_query("SELECT * FROM ". $this->table ." WHERE auth_token_id=". $tokenId);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to retrieve tokenId (". $tokenId .")::: ". $e->getMessage());
+ }
+ return($data);
+ }//end get_token_data();
+ //=========================================================================
+
}
?>
Modified: trunk/0.3/setup/authtoken_schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 17:44:04 UTC (rev 111)
+++ trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 19:01:21 UTC (rev 112)
@@ -13,7 +13,7 @@
uid integer NOT NULL DEFAULT 0,
checksum text NOT NULL,
token text NOT NULL,
- use_limit integer DEFAULT NULL,
+ max_uses integer DEFAULT NULL,
total_uses integer NOT NULL DEFAULT 0,
creation date NOT NULL DEFAULT NOW(),
duration interval NOT NULL DEFAULT '1 day'::interval
Modified: trunk/0.3/tests/testOfAuthToken.php
===================================================================
--- trunk/0.3/tests/testOfAuthToken.php 2009-08-19 17:44:04 UTC (rev 111)
+++ trunk/0.3/tests/testOfAuthToken.php 2009-08-19 19:01:21 UTC (rev 112)
@@ -69,19 +69,62 @@
//--------------------------------------------------------------------------
function test_basics() {
$db = $this->create_db();
- $tok = new cs_authToken($db);
+ $tok = new authTokenTester($db);
//Generic test to ensure we get the appropriate data back.
- $tokenData = $tok->create_token(0, 'test', 'abc123');
+ $tokenData = $tok->create_token(1, 'test', 'abc123');
$this->assertTrue(is_array($tokenData));
$this->assertTrue((count($tokenData) == 2));
$this->assertTrue(isset($tokenData['id']));
$this->assertTrue(isset($tokenData['hash']));
$this->assertTrue(($tokenData['id'] > 0));
$this->assertTrue((strlen($tokenData['hash']) == 32));
+
+ $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
+
+
+ //now create a token with a maximum lifetime...
+ {
+ //Generic test to ensure we get the appropriate data back.
+ $tokenData = $tok->create_token(1, 'test', 'abc123', '2 years');
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
+
+ $this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1);
+ }
+
+ //create a token with only 1 available use and try to authenticate it twice.
+ {
+ //Generic test to ensure we get the appropriate data back.
+ $tokenData = $tok->create_token(1, 'test', 'abc123', null, 1);
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
+
+ if(!$this->assertEqual($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']), 1)) {
+ $this->gfObj->debug_print($tok->tokenData($tokenData['id']),1);
+ }
+ if(!$this->assertTrue(($tok->authenticate_token($tokenData['id'], 'test', $tokenData['hash']) === null), "Able to authenticate twice on a token with only 1 use")) {
+ $this->gfObj->debug_print($tok->tokenData($tokenData['id']));
+ }
+ }
}//end test_basics()
//--------------------------------------------------------------------------
}
+class authTokenTester extends cs_authToken {
+ public $isTest=true;
+
+ public function tokenData($id) {
+ return($this->get_token_data($id));
+ }
+}
?>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 17:44:19
|
Revision: 111
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=111&view=rev
Author: crazedsanity
Date: 2009-08-19 17:44:04 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Testing of cs_authToken & ability to create a token.
Modified Paths:
--------------
trunk/0.3/cs_authToken.class.php
trunk/0.3/setup/authtoken_schema.pgsql.sql
trunk/0.3/tests/testOfAuthToken.php
Modified: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php 2009-08-19 17:14:22 UTC (rev 110)
+++ trunk/0.3/cs_authToken.class.php 2009-08-19 17:44:04 UTC (rev 111)
@@ -18,6 +18,15 @@
/** Database object. */
private $db;
+ /** Object that helps deal with strings. */
+ private $gfObj;
+
+ /** Name of the table */
+ private $table = 'cswal_auth_token_table';
+
+ /** Sequence name for the given table (for PostgreSQL) */
+ private $seq = 'cswal_auth_token_table_auth_token_id_seq';
+
//=========================================================================
public function __construct(cs_phpDB $db) {
@@ -27,6 +36,7 @@
else {
throw new exception(__METHOD__ .": database object not connected");
}
+ $this->gfObj = new cs_globalFunctions();
}//end __construct()
//=========================================================================
@@ -54,7 +64,46 @@
//=========================================================================
+ protected function create_hash_string($tokenId, $uid, $checksum, $stringToHash=NULL) {
+ return(md5($tokenId ."_". $uid ."_". $checksum ."_". $stringToHash));
+ }//end create_hash_string()
//=========================================================================
+
+
+ //=========================================================================
+ public function create_token($uid, $checksum, $stringToHash) {
+
+ $this->db->beginTrans();
+
+ $insertData = array(
+ 'uid' => $uid,
+ 'checksum' => $checksum,
+ 'token' => '____INCOMPLETE____'
+ );
+ try {
+ $sql = "INSERT INTO cswal_auth_token_table ".
+ $this->gfObj->string_from_array($insertData, 'insert', null, 'sql');
+ $tokenId = $this->db->run_insert($sql, $this->seq);
+
+ //now that we have the ID, let's create the real has string.
+ $finalHash = $this->create_hash_string($tokenId, $uid, $checksum, $stringToHash);
+
+ $this->db->run_update("UPDATE ". $this->table ." SET token='". $finalHash ."' WHERE " .
+ "auth_token_id=". $tokenId);
+
+ $tokenInfo = array(
+ 'id' => $tokenId,
+ 'hash' => $finalHash
+ );
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to create token::: ". $e->getMessage());
+ }
+
+ return($tokenInfo);
+ }//end create_token()
+ //=========================================================================
+
}
?>
Modified: trunk/0.3/setup/authtoken_schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 17:14:22 UTC (rev 110)
+++ trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 17:44:04 UTC (rev 111)
@@ -13,6 +13,8 @@
uid integer NOT NULL DEFAULT 0,
checksum text NOT NULL,
token text NOT NULL,
+ use_limit integer DEFAULT NULL,
+ total_uses integer NOT NULL DEFAULT 0,
creation date NOT NULL DEFAULT NOW(),
duration interval NOT NULL DEFAULT '1 day'::interval
);
\ No newline at end of file
Modified: trunk/0.3/tests/testOfAuthToken.php
===================================================================
--- trunk/0.3/tests/testOfAuthToken.php 2009-08-19 17:14:22 UTC (rev 110)
+++ trunk/0.3/tests/testOfAuthToken.php 2009-08-19 17:44:04 UTC (rev 111)
@@ -71,7 +71,14 @@
$db = $this->create_db();
$tok = new cs_authToken($db);
-
+ //Generic test to ensure we get the appropriate data back.
+ $tokenData = $tok->create_token(0, 'test', 'abc123');
+ $this->assertTrue(is_array($tokenData));
+ $this->assertTrue((count($tokenData) == 2));
+ $this->assertTrue(isset($tokenData['id']));
+ $this->assertTrue(isset($tokenData['hash']));
+ $this->assertTrue(($tokenData['id'] > 0));
+ $this->assertTrue((strlen($tokenData['hash']) == 32));
}//end test_basics()
//--------------------------------------------------------------------------
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 17:14:30
|
Revision: 110
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=110&view=rev
Author: crazedsanity
Date: 2009-08-19 17:14:22 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Beginnings of cs_authToken class, for storing of generic tokens to test against.
Added Paths:
-----------
trunk/0.3/cs_authToken.class.php
trunk/0.3/setup/authtoken_schema.pgsql.sql
trunk/0.3/tests/testOfAuthToken.php
Added: trunk/0.3/cs_authToken.class.php
===================================================================
--- trunk/0.3/cs_authToken.class.php (rev 0)
+++ trunk/0.3/cs_authToken.class.php 2009-08-19 17:14:22 UTC (rev 110)
@@ -0,0 +1,60 @@
+<?php
+/*
+ * Created on Aug 19, 2009
+ *
+ * SVN INFORMATION:::
+ * -------------------
+ * Last Author::::::::: $Author$
+ * Current Revision:::: $Revision$
+ * Repository Location: $HeadURL$
+ * Last Updated:::::::: $Date$
+ */
+
+
+require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
+
+class cs_authToken extends cs_webapplibsAbstract {
+
+ /** Database object. */
+ private $db;
+
+ //=========================================================================
+ public function __construct(cs_phpDB $db) {
+
+ if($db->is_connected()) {
+ $this->db = $db;
+ }
+ else {
+ throw new exception(__METHOD__ .": database object not connected");
+ }
+
+ }//end __construct()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function load_table() {
+ $file = dirname(__FILE__) .'/setup/authtoken_schema.'. $this->db->get_dbtype() .'.sql';
+
+ if(file_exists($file)) {
+ try {
+ $this->db->run_update(file_get_contents($file), true);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error while trying to load table::: ". $e->getMessage());
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": unsupported database type (". $this->db->get_dbtype() .")");
+ }
+ }//end load_table()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ //=========================================================================
+
+}
+?>
Property changes on: trunk/0.3/cs_authToken.class.php
___________________________________________________________________
Added: svn:keywords
+ Id
Author
Revision
HeadURL
Date
Added: trunk/0.3/setup/authtoken_schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/authtoken_schema.pgsql.sql (rev 0)
+++ trunk/0.3/setup/authtoken_schema.pgsql.sql 2009-08-19 17:14:22 UTC (rev 110)
@@ -0,0 +1,18 @@
+--
+-- SVN INFORMATION:::
+-- ---------------
+-- SVN Signature::::::: $Id$
+-- Last Author::::::::: $Author$
+-- Current Revision:::: $Revision$
+-- Repository Location: $HeadURL$
+-- Last Updated:::::::: $Date$
+--
+
+CREATE TABLE cswal_auth_token_table (
+ auth_token_id serial NOT NULL PRIMARY KEY,
+ uid integer NOT NULL DEFAULT 0,
+ checksum text NOT NULL,
+ token text NOT NULL,
+ creation date NOT NULL DEFAULT NOW(),
+ duration interval NOT NULL DEFAULT '1 day'::interval
+);
\ No newline at end of file
Property changes on: trunk/0.3/setup/authtoken_schema.pgsql.sql
___________________________________________________________________
Added: svn:keywords
+ Id
Author
Revision
HeadURL
Date
Copied: trunk/0.3/tests/testOfAuthToken.php (from rev 109, trunk/0.3/tests/testOfCSVersionParse.php)
===================================================================
--- trunk/0.3/tests/testOfAuthToken.php (rev 0)
+++ trunk/0.3/tests/testOfAuthToken.php 2009-08-19 17:14:22 UTC (rev 110)
@@ -0,0 +1,80 @@
+<?php
+/*
+ * Created on Jan 25, 2009
+ *
+ * FILE INFORMATION:
+ *
+ * $HeadURL$
+ * $Id$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ */
+
+require_once(dirname(__FILE__) .'/../cs_authToken.class.php');
+
+class testOfCSAuthToken extends UnitTestCase {
+
+ //--------------------------------------------------------------------------
+ function __construct() {
+ $this->gfObj = new cs_globalFunctions;
+ $this->gfObj->debugPrintOpt=1;
+ }//end __construct()
+ //--------------------------------------------------------------------------
+
+
+
+ //--------------------------------------------------------------------------
+ function setUp() {
+ $tok = new cs_authToken($this->create_db());
+ try {
+ $tok->load_table();
+ }
+ catch(exception $e) {
+ }
+ }//end setUp()
+ //--------------------------------------------------------------------------
+
+
+
+ //--------------------------------------------------------------------------
+ function tearDown() {
+ $db = $this->create_db();
+ try {
+ $db->run_update('DROP TABLE cswal_auth_token_table', true);
+ }
+ catch(exception $e) {
+ }
+ }//end
+ //--------------------------------------------------------------------------
+
+
+
+ //--------------------------------------------------------------------------
+ private function create_db() {
+ $dbParams = array(
+ 'host' => constant('DB_PG_HOST'),
+ 'dbname' => constant('DB_PG_DBNAME'),
+ 'user' => constant('DB_PG_DBUSER'),
+ 'password' => constant('DB_PG_DBPASS'),
+ 'port' => constant('DB_PG_PORT')
+ );
+ $db = new cs_phpDB(constant('DBTYPE'));
+ $db->connect($dbParams);
+ return($db);
+ }//end create_db()
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
+ function test_basics() {
+ $db = $this->create_db();
+ $tok = new cs_authToken($db);
+
+
+ }//end test_basics()
+ //--------------------------------------------------------------------------
+}
+
+
+?>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 16:13:28
|
Revision: 109
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=109&view=rev
Author: crazedsanity
Date: 2009-08-19 16:13:16 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Use a main abstract class which they all extend, fix require_once() paths.
Modified Paths:
--------------
trunk/0.3/cs_webdblogger.class.php
trunk/0.3/cs_webdbupgrade.class.php
Added Paths:
-----------
trunk/0.3/cs_webapplibs.abstract.class.php
Added: trunk/0.3/cs_webapplibs.abstract.class.php
===================================================================
--- trunk/0.3/cs_webapplibs.abstract.class.php (rev 0)
+++ trunk/0.3/cs_webapplibs.abstract.class.php 2009-08-19 16:13:16 UTC (rev 109)
@@ -0,0 +1,20 @@
+<?php
+/*
+ * Created on Aug 19, 2009
+ *
+ * SVN INFORMATION:::
+ * -------------------
+ * Last Author::::::::: $Author$
+ * Current Revision:::: $Revision$
+ * Repository Location: $HeadURL$
+ * Last Updated:::::::: $Date$
+ */
+
+require_once(dirname(__FILE__) .'/cs_version.abstract.class.php');
+
+
+abstract class cs_webapplibsAbstract extends cs_versionAbstract {
+
+}
+
+?>
Property changes on: trunk/0.3/cs_webapplibs.abstract.class.php
___________________________________________________________________
Added: svn:keywords
+ Id
Author
Revision
HeadURL
Date
Modified: trunk/0.3/cs_webdblogger.class.php
===================================================================
--- trunk/0.3/cs_webdblogger.class.php 2009-08-19 16:10:34 UTC (rev 108)
+++ trunk/0.3/cs_webdblogger.class.php 2009-08-19 16:13:16 UTC (rev 109)
@@ -27,9 +27,9 @@
//NOTE::: this class **REQUIRES** cs-content for its "cs_phpDB" class.
-require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php');
+require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
-class cs_webdblogger extends cs_versionAbstract {
+class cs_webdblogger extends cs_webapplibsAbstract {
/** Database handle */
public $db;
Modified: trunk/0.3/cs_webdbupgrade.class.php
===================================================================
--- trunk/0.3/cs_webdbupgrade.class.php 2009-08-19 16:10:34 UTC (rev 108)
+++ trunk/0.3/cs_webdbupgrade.class.php 2009-08-19 16:13:16 UTC (rev 109)
@@ -12,10 +12,10 @@
*
*/
-require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php');
-require_once(constant('LIBDIR') .'/cs_debug.php');
+require_once(dirname(__FILE__) .'/cs_webapplibs.abstract.class.php');
+ require_once(dirname(__FILE__) .'/cs_webdblogger.class.php');
-class cs_webdbupgrade extends cs_versionAbstract {
+class cs_webdbupgrade extends cs_webapplibsAbstract {
/** cs_fileSystem{} object: for filesystem read/write operations. */
private $fsObj;
@@ -89,7 +89,6 @@
require_once(constant('LIBDIR') .'/cs-content/cs_globalFunctions.class.php');
require_once(constant('LIBDIR') .'/cs-content/cs_fileSystem.class.php');
require_once(constant('LIBDIR') .'/cs-content/cs_phpDB.class.php');
- require_once(constant('LIBDIR') .'/cs-webdblogger/cs_webdblogger.class.php');
require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlParser.class.php');
require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php');
require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php');
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 16:10:42
|
Revision: 108
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=108&view=rev
Author: crazedsanity
Date: 2009-08-19 16:10:34 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Copy tests folder for cs_versionAbstract.
Added Paths:
-----------
trunk/0.3/tests/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:47:19
|
Revision: 107
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=107&view=rev
Author: crazedsanity
Date: 2009-08-19 15:47:08 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Ignore Eclipse's ".project" file.
Property Changed:
----------------
trunk/0.3/
Property changes on: trunk/0.3
___________________________________________________________________
Added: svn:ignore
+ .project
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:44:59
|
Revision: 106
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=106&view=rev
Author: crazedsanity
Date: 2009-08-19 15:44:52 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Consolidate schema into setup files & documentation into "docs" folder.
Modified Paths:
--------------
trunk/0.3/docs/README.txt
trunk/0.3/setup/schema.mysql.sql
trunk/0.3/setup/schema.pgsql.sql
Removed Paths:
-------------
trunk/0.3/CREDITS
trunk/0.3/LICENSE
trunk/0.3/README.txt
trunk/0.3/schema/
Deleted: trunk/0.3/CREDITS
===================================================================
--- trunk/0.3/CREDITS 2009-08-19 15:35:35 UTC (rev 105)
+++ trunk/0.3/CREDITS 2009-08-19 15:44:52 UTC (rev 106)
@@ -1,3 +0,0 @@
-
-Lead Developer: Dan Falconer (cra...@us...)
-
Deleted: trunk/0.3/LICENSE
===================================================================
--- trunk/0.3/LICENSE 2009-08-19 15:35:35 UTC (rev 105)
+++ trunk/0.3/LICENSE 2009-08-19 15:44:52 UTC (rev 106)
@@ -1,291 +0,0 @@
-NOTE: a full HTML version of this license can be found at:
-http://www.opensource.org/licenses/gpl-license.php
-
-It has been reproduced below without any HTML.
-==========================================================================
-
-The GNU General Public License (GPL)
-
-Version 2, June 1991
-
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
Deleted: trunk/0.3/README.txt
===================================================================
--- trunk/0.3/README.txt 2009-08-19 15:35:35 UTC (rev 105)
+++ trunk/0.3/README.txt 2009-08-19 15:44:52 UTC (rev 106)
@@ -1,30 +0,0 @@
-
-=== CS Web DB Logger ===
-Once the appropriate schema has been built, code can be updated easily to start logging:
-
-//Create the class...
-$this->log = new cs_webdblogger($dbObj, 'Generic Activity');
-
-//Now call the logger.
-$this->log->log_by_class('User viewed page', 'info', $this->userId);
-
-
-
-UNDERSTANDING THE DATABASE SCHEMA:::
-I understand things best from real data, so here goes::::
-
-live_cs_project=# select rca.name as category, rcl.name as class, le.description from log_event_table AS le INNER JOIN log_class_table AS rcl USING (log_class_id) INNER JOIN log_category_table AS rca USING (log_category_id) limit 5;
- category | class | description
-----------+--------+--------------------------
- Project | Create | Project: created record
- Project | Delete | Project: deleted record
- Project | Update | Project: updated record
- Project | Error | Project: ERROR
- Helpdesk | Create | Helpdesk: Created record
-(5 rows)
-
-The category indicates what system it is attached to, and class is a more
-generic way of indicating what type of action it is.
-
-
-$Id$
\ No newline at end of file
Modified: trunk/0.3/docs/README.txt
===================================================================
--- trunk/0.3/docs/README.txt 2009-08-19 15:35:35 UTC (rev 105)
+++ trunk/0.3/docs/README.txt 2009-08-19 15:44:52 UTC (rev 106)
@@ -1,6 +1,39 @@
$Id$
+=== CS Web DB Logger ===
+Once the appropriate schema has been built, code can be updated easily to start logging:
+
+//Create the class...
+$this->log = new cs_webdblogger($dbObj, 'Generic Activity');
+
+//Now call the logger.
+$this->log->log_by_class('User viewed page', 'info', $this->userId);
+
+
+
+UNDERSTANDING THE DATABASE SCHEMA:::
+I understand things best from real data, so here goes::::
+
+live_cs_project=# select rca.name as category, rcl.name as class, le.description from log_event_table AS le INNER JOIN log_class_table AS rcl USING (log_class_id) INNER JOIN log_category_table AS rca USING (log_category_id) limit 5;
+ category | class | description
+----------+--------+--------------------------
+ Project | Create | Project: created record
+ Project | Delete | Project: deleted record
+ Project | Update | Project: updated record
+ Project | Error | Project: ERROR
+ Helpdesk | Create | Helpdesk: Created record
+(5 rows)
+
+The category indicates what system it is attached to, and class is a more
+generic way of indicating what type of action it is.
+
+
+
+
+=== CS Web DB Upgrade ===
+
+
This system is built to make upgrading a database-driven app seamless. No need
to coordinate SQL or schema changes with the code updates: previously, one would
have to take the entire website down, run the schema/SQL change, update the code,
Modified: trunk/0.3/setup/schema.mysql.sql
===================================================================
--- trunk/0.3/setup/schema.mysql.sql 2009-08-19 15:35:35 UTC (rev 105)
+++ trunk/0.3/setup/schema.mysql.sql 2009-08-19 15:44:52 UTC (rev 106)
@@ -92,3 +92,20 @@
--
ALTER TABLE `cswdbl_log_table`
ADD CONSTRAINT `cswdbl_log_table_event_id_fkey` FOREIGN KEY (`event_id`) REFERENCES `cswdbl_event_table` (`event_id`);
+
+
+-- This table create statement MUST work in PostgreSQL v8.2.x+ AND MySQL v5.0.x+:
+-- otherwise separate schema files have to be created and the code will have to
+-- do extra checking...
+--
+-- The "{tableName}" portion will be replaced with the value of the configured
+-- "DB_TABLE" setting.
+CREATE TABLE cs_version_table (
+ version_id int NOT NULL PRIMARY KEY,
+ project_name varchar(30) NOT NULL UNIQUE,
+ version_string varchar(50) NOT NULL,
+ version_major integer NOT NULL,
+ version_minor integer NOT NULL,
+ version_maintenance integer NOT NULL,
+ version_suffix varchar(20) NOT NULL
+);
Modified: trunk/0.3/setup/schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/schema.pgsql.sql 2009-08-19 15:35:35 UTC (rev 105)
+++ trunk/0.3/setup/schema.pgsql.sql 2009-08-19 15:44:52 UTC (rev 106)
@@ -63,3 +63,16 @@
details text NOT NULL
);
+-- This table create statement MUST work in PostgreSQL v8.2.x+ AND MySQL v5.0.x+:
+-- otherwise separate schema files have to be created and the code will have to
+-- do extra checking...
+CREATE TABLE cs_version_table (
+ version_id serial NOT NULL PRIMARY KEY,
+ project_name varchar(30) NOT NULL UNIQUE,
+ version_string varchar(50) NOT NULL,
+ version_major integer NOT NULL,
+ version_minor integer NOT NULL,
+ version_maintenance integer NOT NULL,
+ version_suffix varchar(20) NOT NULL
+);
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:35:48
|
Revision: 105
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=105&view=rev
Author: crazedsanity
Date: 2009-08-19 15:35:35 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Copied stuff from cs-webdbupgrade...
Modified Paths:
--------------
trunk/0.3/README.txt
Added Paths:
-----------
trunk/0.3/cs_webdbupgrade.class.php
trunk/0.3/docs/
trunk/0.3/schema/
Modified: trunk/0.3/README.txt
===================================================================
--- trunk/0.3/README.txt 2009-08-19 15:28:38 UTC (rev 104)
+++ trunk/0.3/README.txt 2009-08-19 15:35:35 UTC (rev 105)
@@ -1,4 +1,5 @@
+=== CS Web DB Logger ===
Once the appropriate schema has been built, code can be updated easily to start logging:
//Create the class...
Copied: trunk/0.3/cs_webdbupgrade.class.php (from rev 101, import/cs-webdbupgrade/trunk/0.2/cs_webdbupgrade.class.php)
===================================================================
--- trunk/0.3/cs_webdbupgrade.class.php (rev 0)
+++ trunk/0.3/cs_webdbupgrade.class.php 2009-08-19 15:35:35 UTC (rev 105)
@@ -0,0 +1,1096 @@
+<?php
+/*
+ * Created on Jul 2, 2007
+ *
+ * SVN INFORMATION:::
+ * ------------------
+ * SVN Signature::::::: $Id$
+ * Last Author::::::::: $Author$
+ * Current Revision:::: $Revision$
+ * Repository Location: $HeadURL$
+ * Last Updated:::::::: $Date$
+ *
+ */
+
+require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php');
+require_once(constant('LIBDIR') .'/cs_debug.php');
+
+class cs_webdbupgrade extends cs_versionAbstract {
+
+ /** cs_fileSystem{} object: for filesystem read/write operations. */
+ private $fsObj;
+
+ /** cs_globalFunctions{} object: debugging, array, and string operations. */
+ protected $gfObj;
+
+ /** Array of configuration parameters. */
+ private $config = NULL;
+
+ /** Name of primary key sequence of main table (for handling inserts with PostgreSQL) */
+ private $sequenceName;
+
+ /** Database object. */
+ protected $db;
+
+ /** Object used to log activity. */
+ protected $logsObj;
+
+ /** Name of the project as referenced in the database. */
+ protected $projectName;
+
+ /** Internal cache of the version string from the VERSION file. */
+ private $versionFileVersion = NULL;
+
+ /** Stored database version. */
+ private $databaseVersion = NULL;
+
+ /** Name (absolute location) of *.lock file that indicates an upgrade is running. */
+ private $lockfile;
+
+ /** Determines if an internal upgrade is happening (avoids some infinite loops) */
+ private $internalUpgradeInProgress = false;
+
+ /** */
+ private $allowNoDBVersion=true;
+
+ /** Log messages to store during an internal upgrade (to avoid problems) */
+ private $storedLogs = array();
+ private $debugLogs=array();
+
+ /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in
+ * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */
+ private $suffixList = array(
+ 'ALPHA', //very unstable
+ 'BETA', //kinda unstable, but probably useable
+ 'RC' //all known bugs fixed, searching for unknown ones
+ );
+
+ //=========================================================================
+ public function __construct($versionFileLocation, $upgradeConfigFile, $lockFile='upgrade.lock') {
+
+ //setup configuration parameters for database connectivity.
+ $dbParams = array(
+ 'host' => constant(__CLASS__ .'-DB_CONNECT_HOST'),
+ 'port' => constant(__CLASS__ .'-DB_CONNECT_PORT'),
+ 'dbname' => constant(__CLASS__ .'-DB_CONNECT_DBNAME'),
+ 'user' => constant(__CLASS__ .'-DB_CONNECT_USER'),
+ 'password' => constant(__CLASS__ .'-DB_CONNECT_PASSWORD')
+ );
+ $this->config['DBPARAMS'] = $dbParams;
+ //Check for some required constants.
+ $requisiteConstants = array('LIBDIR');
+ if(!defined('LIBDIR')) {
+ throw new exception(__METHOD__ .": required constant 'LIBDIR' not set");
+ }
+ if(!defined('SITE_ROOT')) {
+ throw new exception(__METHOD__ .": required constant 'SITE_ROOT' not set");
+ }
+
+ require_once(constant('LIBDIR') .'/cs-content/cs_globalFunctions.class.php');
+ require_once(constant('LIBDIR') .'/cs-content/cs_fileSystem.class.php');
+ require_once(constant('LIBDIR') .'/cs-content/cs_phpDB.class.php');
+ require_once(constant('LIBDIR') .'/cs-webdblogger/cs_webdblogger.class.php');
+ require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlParser.class.php');
+ require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php');
+ require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php');
+
+ $this->fsObj = new cs_fileSystem(constant('SITE_ROOT'));
+ $this->gfObj = new cs_globalFunctions;
+ if(defined('DEBUGPRINTOPT')) {
+ $this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT');
+ }
+
+ if(!defined(__CLASS__ .'-DB_PRIMARYKEY') || !defined(__CLASS__ .'-DB_TABLE')) {
+ throw new exception(__METHOD__ .": no setting for DB_TABLE or DB_PRIMARYKEY, cannot continue");
+ }
+ else {
+ $this->config['DB_TABLE'] = constant(__CLASS__ .'-DB_TABLE');
+ $this->config['DB_PRIMARYKEY'] = constant(__CLASS__ .'-DB_PRIMARYKEY');
+ }
+ $this->sequenceName = $this->config['DB_TABLE'] .'_'. $this->config['DB_PRIMARYKEY'] .'_seq';
+
+ if(!defined('DBTYPE')) {
+ throw new exception(__METHOD__ .": required constant 'DBTYPE' not set");
+ }
+
+ if(!file_exists($upgradeConfigFile) || !is_readable($upgradeConfigFile)) {
+ throw new exception(__METHOD__ .": required upgrade config file location (". $upgradeConfigFile .") not set or unreadable");
+ }
+ else {
+ $this->config['UPGRADE_CONFIG_FILE'] = $upgradeConfigFile;
+ }
+ if(!strlen($versionFileLocation) || !file_exists($versionFileLocation)) {
+ throw new exception(__METHOD__ .": unable to locate version file (". $versionFileLocation .")");
+ }
+ $this->set_version_file_location($versionFileLocation);
+
+ if(!defined(__CLASS__ .'-RWDIR') || !is_dir(constant(__CLASS__ .'-RWDIR')) || !is_readable(constant(__CLASS__ .'-RWDIR')) || !is_writable(constant(__CLASS__ .'-RWDIR'))) {
+ throw new exception(__METHOD__ .": missing RWDIR (". constant(__CLASS__ .'-RWDIR') .") or isn't readable/writable");
+ }
+ else {
+ $this->config['RWDIR'] = constant(__CLASS__ .'-RWDIR');
+ }
+ if(is_null($lockFile) || !strlen($lockFile)) {
+ $lockFile = 'upgrade.lock';
+ }
+ $this->lockfile = $this->config['RWDIR'] .'/'. $lockFile;
+
+ $this->db = new cs_phpDB(constant('DBTYPE'));
+ try {
+ $this->db->connect($this->config['DBPARAMS']);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to connect to database or logger error: ". $e->getMessage());
+ }
+
+ if($this->check_lockfile()) {
+ //there is an existing lockfile...
+ throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile));
+ }
+
+ $this->check_internal_upgrades();
+
+ try {
+ $loggerDb = new cs_phpDB(constant('DBTYPE'));
+ $loggerDb->connect($this->config['DBPARAMS'], true);
+ $this->logsObj = new cs_webdblogger($loggerDb, "Upgrade ". $this->projectName, false);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to create logger::: ". $e->getMessage());
+ }
+
+ $this->check_versions(false);
+ }//end __construct()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Determine if there are any upgrades that need to be performed...
+ */
+ private function check_internal_upgrades() {
+ $oldVersionFileLocation = $this->versionFileLocation;
+ $oldUpgradeConfigFile = $this->config['UPGRADE_CONFIG_FILE'];
+ $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml';
+
+
+ //set a status flag so we can store log messages (for now).
+ $this->internalUpgradeInProgress = true;
+
+
+ //do stuff here...
+ $this->set_version_file_location(dirname(__FILE__) .'/VERSION');
+ $this->read_version_file();
+
+ //if there is an error, then... uh... yeah.
+ try {
+ $this->get_database_version();
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage());
+
+ //try creating the version.
+ $this->load_initial_version();
+ }
+
+ //do upgrades here...
+ $this->check_versions(true);
+ $this->internalUpgradeInProgress = false;
+
+
+
+
+ //reset internal vars.
+ $this->set_version_file_location($oldVersionFileLocation);
+ $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile;
+ $this->read_version_file();
+
+ }//end check_internal_upgrades()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Where everything begins: checks if the version held in config.xml lines-up
+ * with the one in the VERSION file; if it does, then it checks the version
+ * listed in the database.
+ */
+ public function check_versions($performUpgrade=TRUE) {
+ if(!is_bool($performUpgrade) || is_null($performUpgrade)) {
+ $performUpgrade = true;
+ }
+
+ //first, check that all files exist.
+ $retval = NULL;
+
+ //check to see if the lock files for upgrading exist.
+ if($this->upgrade_in_progress()) {
+ $this->do_log("Upgrade in progress", 'notice');
+ throw new exception(__METHOD__ .": upgrade in progress");
+ }
+ else {
+ //okay, all files present: check the version in the VERSION file.
+ $versionFileVersion = $this->read_version_file();
+ $dbVersion = $this->get_database_version();
+ if(!is_array($dbVersion)) {
+ $this->load_initial_version();
+ }
+
+ $versionsDiffer = TRUE;
+ $retval = FALSE;
+
+ if($this->check_for_version_conflict() == false) {
+ $versionsDiffer = false;
+ $performUpgrade = false;
+ }
+ else {
+ $versionsDiffer = true;
+ }
+
+ if($versionsDiffer == TRUE && $performUpgrade === TRUE) {
+ //reset the return value, so it'll default to failure until we say otherwise.
+ $retval = NULL;
+
+ //Perform the upgrade!
+ $this->perform_upgrade();
+ }
+ }
+
+ return($retval);
+ }//end check_versions()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ protected function read_version_file() {
+ $retval = NULL;
+
+ //okay, all files present: check the version in the VERSION file.
+ $versionFileContents = $this->fsObj->read($this->versionFileLocation);
+
+
+ $versionMatches = array();
+ preg_match_all('/\nVERSION: (.*)\n/', $versionFileContents, $versionMatches);
+ if(count($versionMatches) == 2 && count($versionMatches[1]) == 1) {
+ $retval = trim($versionMatches[1][0]);
+ $this->versionFileVersion = $this->get_full_version_string($retval);
+
+ //now retrieve the PROJECT name.
+ $projectMatches = array();
+ preg_match_all('/\nPROJECT: (.*)\n/', $versionFileContents, $projectMatches);
+ if(count($projectMatches) == 2 && count($projectMatches[1]) == 1) {
+ $this->projectName = trim($projectMatches[1][0]);
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to find PROJECT name");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": could not find VERSION data");
+ }
+
+ return($retval);
+ }//end read_version_file()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Read information from our config file, so we know what to expect.
+ */
+ private function read_upgrade_config_file() {
+ try {
+ $xmlString = $this->fsObj->read($this->config['UPGRADE_CONFIG_FILE']);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to read upgrade config file::: ". $e->getMessage());
+ }
+
+ //parse the file.
+ $xmlParser = new cs_phpxmlParser($xmlString);
+
+ $config = $xmlParser->get_tree(TRUE);
+
+ if(is_array($config['UPGRADE']) && count($config['UPGRADE'])) {
+ $this->config['UPGRADELIST'] = $config['UPGRADE'];
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to retrieve 'UPGRADE' section; " .
+ "make sure upgrade.xml's ROOT element is 'UPGRADE'");
+ }
+ }//end read_upgrade_config_file()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function perform_upgrade() {
+ $this->logsObj->suspendLogging=true;
+ //make sure there's not already a lockfile.
+ if($this->upgrade_in_progress()) {
+ //ew. Can't upgrade.
+ $this->error_handler(__METHOD__ .": upgrade already in progress...????");
+ }
+ else {
+ $lockConfig = $this->upgrade_in_progress(TRUE);
+ $this->fsObj->cd("/");
+
+ $this->do_log("Starting upgrade process...", 'begin');
+
+ //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists().
+ if($lockConfig === 0) {
+ //can't create the lockfile. Die.
+ $this->error_handler(__METHOD__ .": failed to set 'upgrade in progress'");
+ }
+ else {
+ $this->do_log(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug');
+
+ //push data into our internal "config" array.
+ $this->read_upgrade_config_file();
+ $this->get_database_version();
+
+ //check for version conflicts.
+ $versionConflictInfo = $this->check_for_version_conflict();
+
+
+ if($versionConflictInfo !== false) {
+ $this->do_log("Upgrading ". $versionConflictInfo ." versions, from " .
+ "(". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'info');
+ }
+
+ $upgradeList = $this->get_upgrade_list();
+ try {
+ $i=0;
+ $this->do_log(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " .
+ "total number of upgrades to perform: ". count($upgradeList), 'debug');
+ $this->db->beginTrans(__METHOD__);
+ foreach($upgradeList as $fromVersion=>$toVersion) {
+
+ $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... ";
+ $this->do_log($details, 'system');
+ $this->do_single_upgrade($fromVersion, $toVersion);
+ $this->get_database_version();
+ $i++;
+
+ $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")";
+ $this->do_log($details, 'system');
+ }
+
+ if($i < count($upgradeList)) {
+ $this->do_log(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug');
+ }
+ else {
+ if($this->databaseVersion == $this->versionFileVersion) {
+ $this->do_log(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug');
+ $this->newVersion = $this->databaseVersion;
+ }
+ else {
+ $this->do_log(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug');
+ $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!");
+ }
+ }
+ $this->remove_lockfile();
+
+ $this->db->commitTrans();
+ }
+ catch(exception $e) {
+ $transactionStatus = $this->db->get_transaction_status(false);
+ $this->error_handler(__METHOD__ .": transaction status=(". $transactionStatus ."), upgrade aborted:::". $e->getMessage());
+ $this->db->rollbackTrans();
+ }
+ $this->logsObj->suspendLogging=false;
+ $this->do_log("Upgrade process complete", 'end');
+ }
+ }
+ $this->logsObj->suspendLogging=false;
+ $logsHandled = $this->logsObj->handle_suspended_logs();
+ }//end perform_upgrade()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function upgrade_in_progress($makeItSo=FALSE) {
+ if($makeItSo === TRUE) {
+ if(strlen($this->databaseVersion)) {
+ $details = $this->projectName .': Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s');
+ $this->create_lockfile($details);
+ $retval = TRUE;
+ }
+ else {
+ $this->error_handler(__METHOD__ .": missing internal databaseVersion (". $this->databaseVersion .")");
+ }
+ }
+ $retval = $this->check_lockfile();
+
+ return($retval);
+ }//end upgrade_in_progress()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function parse_version_string($versionString) {
+ if(is_null($versionString) || !strlen($versionString)) {
+ $this->error_handler(__METHOD__ .": invalid version string ($versionString)");
+ }
+
+ $suffix = "";
+ $explodeThis = $versionString;
+ if(preg_match('/-[A-Z]{2,5}[0-9]{1,}/', $versionString)) {
+ $bits = explode('-', $versionString);
+ $suffix = $bits[1];
+ $explodeThis = $bits[0];
+ }
+ $tmp = explode('.', $explodeThis);
+
+
+ if(is_numeric($tmp[0]) && is_numeric($tmp[1])) {
+ $retval = array(
+ 'version_string' => $versionString,
+ 'version_major' => $tmp[0],
+ 'version_minor' => $tmp[1],
+ );
+ if(isset($tmp[2])) {
+ $retval['version_maintenance'] = $tmp[2];
+ }
+ else {
+ $retval['version_maintenance'] = 0;
+ }
+
+ $retval['version_suffix'] = $suffix;
+ }
+ else {
+ $this->error_handler(__METHOD__ .": invalid version string format, requires MAJOR.MINOR syntax (". $versionString .")");
+ }
+
+ return($retval);
+ }//end parse_version_string()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Checks for issues with versions.
+ * 0 == No problems.
+ * (string) == upgrade applicable (indicates "major"/"minor"/"maintenance").
+ * NULL == encountered error
+ */
+ private function check_for_version_conflict() {
+ //set a default return...
+ $retval = NULL;
+
+ $this->read_version_file();
+
+ //parse the version strings.
+ $dbVersion = $this->get_database_version();
+ $versionFileData = $this->parse_version_string($this->versionFileVersion);
+
+ if($versionFileData['version_string'] == $dbVersion['version_string']) {
+ //good to go: no upgrade needed.
+ $retval = false;
+ }
+ else {
+ //NOTE: this seems very convoluted, but it works.
+ if($versionFileData['version_major'] == $dbVersion['version_major']) {
+ if($versionFileData['version_minor'] == $dbVersion['version_minor']) {
+ if($versionFileData['version_maintenance'] == $dbVersion['version_maintenance']) {
+ if($versionFileData['version_suffix'] == $dbVersion['version_suffix']) {
+ $this->error_handler(__METHOD__ .": no version upgrade detected, but version strings don't match (versionFile=". $versionFileData['version_string'] .", dbVersion=". $dbVersion['version_string'] .")");
+ }
+ else {
+ $retval = "suffix";
+ }
+ }
+ elseif($versionFileData['version_maintenance'] > $dbVersion['version_maintenance']) {
+ $retval = "maintenance";
+ }
+ else {
+ $this->error_handler(__METHOD__ .": downgrading from maintenance versions is unsupported");
+ }
+ }
+ elseif($versionFileData['version_minor'] > $dbVersion['version_minor']) {
+ $retval = "minor";
+ }
+ else {
+ $this->error_handler(__METHOD__ .": downgrading minor versions is unsupported");
+ }
+ }
+ elseif($versionFileData['version_major'] > $dbVersion['version_major']) {
+ $retval = "major";
+ }
+ else {
+ $this->error_handler(__METHOD__ .": downgrading major versions is unsupported");
+ }
+ }
+
+ return($retval);
+ }//end check_for_version_conflict()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function get_database_version() {
+ $this->gfObj->debugPrintOpt=1;
+ //create a database object & attempt to read the database version.
+
+ $sql = "SELECT * FROM ". $this->config['DB_TABLE'] ." WHERE project_name='" .
+ $this->gfObj->cleanString($this->projectName, 'sql') ."'";
+
+ $numrows = $this->db->exec($sql);
+ $dberror = $this->db->errorMsg();
+
+ if(strlen($dberror) || $numrows != 1) {
+ //
+ if(preg_match('/doesn\'t exist/', $dberror) || preg_match('/does not exist/', $dberror)) {
+ //add the table...
+ $loadTableResult = $this->load_table();
+ if($loadTableResult === TRUE) {
+ //now try the SQL...
+ $numrows = $this->db->exec($sql);
+ $dberror = $this->db->errorMsg();
+ }
+ else {
+ $this->error_handler(__METHOD__ .": no table in database, failed to create one... ORIGINAL " .
+ "ERROR: ". $dberror .", SCHEMA LOAD ERROR::: ". $loadTableResult);
+ }
+ }
+ elseif(!strlen($dberror) && $numrows == 0) {
+ if($this->allowNoDBVersion) {
+ $retval = false;
+ }
+ else {
+ $this->error_handler(__METHOD__ .": no version data found for (". $this->projectName .")");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror);
+ }
+ }
+ else {
+ $data = $this->db->farray_fieldnames();
+ $this->databaseVersion = $data['version_string'];
+ $retval = $this->parse_version_string($data['version_string']);
+ }
+
+ return($retval);
+ }//end get_database_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function do_single_upgrade($fromVersion, $toVersion=null) {
+ //Use the "matching_syntax" data in the upgrade.xml file to determine the filename.
+ $versionIndex = "V". $this->get_full_version_string($fromVersion);
+ if(!isset($this->config['UPGRADELIST']['MATCHING'][$versionIndex])) {
+ //version-only upgrade.
+ $this->newVersion = $toVersion;
+ $this->update_database_version($toVersion);
+ }
+ else {
+ //scripted upgrade...
+ $scriptIndex = $versionIndex;
+
+ $upgradeData = $this->config['UPGRADELIST']['MATCHING'][$versionIndex];
+
+ if(isset($upgradeData['TARGET_VERSION']) && count($upgradeData) > 1) {
+ $this->newVersion = $upgradeData['TARGET_VERSION'];
+ if(isset($upgradeData['SCRIPT_NAME']) && isset($upgradeData['CLASS_NAME']) && isset($upgradeData['CALL_METHOD'])) {
+ //good to go; it's a scripted upgrade.
+ $this->do_scripted_upgrade($upgradeData);
+ $this->update_database_version($upgradeData['TARGET_VERSION']);
+ }
+ else {
+ $this->error_handler(__METHOD__ .": not enough information to run scripted upgrade for ". $versionIndex);
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex);
+ }
+ }
+ $this->do_log("Finished upgrade to ". $this->newVersion, 'system');
+ }//end do_single_upgrade()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Updates information that's stored in the database, internal to cs-project,
+ * so the version there is consistent with all the others.
+ */
+ protected function update_database_version($newVersionString) {
+ $versionInfo = $this->parse_version_string($newVersionString);
+
+ $sql = "UPDATE ". $this->config['DB_TABLE'] ." SET version_string='".
+ $this->gfObj->cleanString($versionInfo['version_string'], 'sql')
+ ."' WHERE project_name='".
+ $this->gfObj->cleanString($this->projectName, 'sql') ."'";
+
+
+ $updateRes = $this->db->run_update($sql,false);
+ if($updateRes == 1) {
+ $retval = $updateRes;
+ }
+ else {
+ $this->error_handler(__METHOD__ .": invalid result (". $updateRes .") ");
+ }
+
+ //okay, now check that the version string matches the updated bits.
+ if(!$this->check_database_version($this->newVersion)) {
+ $this->error_handler(__METHOD__ .": database version information is invalid: (". $this->newVersion .")");
+ }
+
+ return($retval);
+
+ }//end update_database_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Checks consistency of version information in the database, and optionally
+ * against a given version string.
+ */
+ private function check_database_version() {
+ //retrieve the internal version information.
+ if(!is_null($this->newVersion)) {
+ $data = $this->get_database_version();
+ $versionString = $data['version_string'];
+
+ if($versionString == $this->newVersion) {
+ $retval = TRUE;
+ }
+ else {
+ $retval = FALSE;
+ }
+
+ if(!$retval) {
+ $this->do_log("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL');
+ }
+
+ }
+ else {
+ $this->error_handler(__METHOD__ .": no version string given (". $this->newVersion .")");
+ }
+
+ return($retval);
+ }//end check_database_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function do_scripted_upgrade(array $upgradeData) {
+ $myConfigFile = $upgradeData['SCRIPT_NAME'];
+
+ $this->do_log("Preparing to run script '". $myConfigFile ."'", 'debug');
+
+ //we've got the filename, see if it exists.
+
+ $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']);
+ $fileName = $scriptsDir .'/'. $myConfigFile;
+
+ if(file_exists($fileName)) {
+
+ $this->do_log("(". __CLASS__ .") Performing scripted upgrade (". $myConfigFile .") from file '". $fileName ."'", 'DEBUG');
+ $createClassName = $upgradeData['CLASS_NAME'];
+ $classUpgradeMethod = $upgradeData['CALL_METHOD'];
+ require_once($fileName);
+
+ //now check to see that the class we need actually exists.
+ if(class_exists($createClassName)) {
+ $upgradeObj = new $createClassName($this->db);
+ if(method_exists($upgradeObj, $classUpgradeMethod)) {
+ $upgradeResult = $upgradeObj->$classUpgradeMethod();
+
+ if($upgradeResult === true) {
+ //yay, it worked!
+ $this->do_log("Upgrade succeeded (". $upgradeResult .")", 'success');
+ }
+ else {
+ $this->error_handler(__METHOD__ .": upgrade failed (". $upgradeResult .")");
+ }
+ $this->do_log("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug');
+ }
+ else {
+ $this->error_handler(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod
+ ."), unable to perform upgrade ");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": unable to locate upgrade class name (". $createClassName .")");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": upgrade filename (". $fileName .") does not exist");
+ }
+ }//end do_scripted_upgrade()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function is_higher_version($version, $checkIfHigher) {
+ try {
+ $retval = parent::is_higher_version($version, $checkIfHigher);
+ }
+ catch(exception $e) {
+ $this->error_handler($e->getMessage());
+ }
+
+ return($retval);
+
+ }//end is_higher_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Determines list of upgrades to perform.
+ *
+ * If the current version is 1.0.1, the version file is 1.0.5, and there's a
+ * scripted upgrade at 1.0.4, this will update the database version to 1.0.3,
+ * run the scripted upgrade at 1.0.4, then update the database version to
+ * 1.0.5 (keeps from skipping the upgrade at 1.0.4)
+ */
+ private function get_upgrade_list() {
+ $this->get_database_version();
+ $dbVersion = $this->databaseVersion;
+ $newVersion = $this->versionFileVersion;
+
+ $retval = array();
+ if(!$this->is_higher_version($dbVersion, $newVersion)) {
+ $this->error_handler(__METHOD__ .": version (". $newVersion .") isn't higher than (". $dbVersion .")... something is broken");
+ }
+ elseif(is_array($this->config['UPGRADELIST']['MATCHING'])) {
+ $lastVersion = $dbVersion;
+ foreach($this->config['UPGRADELIST']['MATCHING'] as $matchVersion=>$data) {
+
+ $matchVersion = preg_replace('/^V/', '', $matchVersion);
+ if($matchVersion == $data['TARGET_VERSION']) {
+ $this->error_handler(__METHOD__ .": detected invalid TARGET_VERSION in (". $matchVersion ."): make sure TARGET_VERSION is higher than matching!");
+ }
+ elseif($this->databaseVersion == $matchVersion || $this->is_higher_version($this->databaseVersion, $matchVersion)) {
+ //the version in MATCHING is equal to or HIGHER than our database version... make sure it is NOT
+ // higher than the version in our versionFile.
+ if(!$this->is_higher_version($this->versionFileVersion, $matchVersion)) {
+ if(!count($retval) && $matchVersion != $this->databaseVersion) {
+ $retval[$this->databaseVersion] = $matchVersion;
+ }
+ //the MATCHING version is NOT higher than the version file's version, looks ok.
+ $lastVersion = $data['TARGET_VERSION'];
+ $retval[$matchVersion] = $data['TARGET_VERSION'];
+ }
+ else {
+ $this->do_log(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning');
+ }
+ }
+ else {
+ $this->do_log(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug');
+ }
+ }
+
+ if($lastVersion !== $newVersion && (!isset($retval[$lastVersion]) || $retval[$lastVersion] != $newVersion)) {
+ $retval[$lastVersion] = $newVersion;
+ }
+ }
+ else {
+ //no intermediary upgrades: just pass back the latest version.
+ $this->do_log(__METHOD__ .": no intermediary upgrades", 'debug');
+ $retval[$dbVersion] = $this->versionFileVersion;
+ }
+
+ return($retval);
+
+ }//end get_upgrade_list()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ protected function parse_suffix($suffix) {
+ $retval = NULL;
+ if(strlen($suffix)) {
+ //determine what kind it is.
+ foreach($this->suffixList as $type) {
+ if(preg_match('/^'. $type .'/', $suffix)) {
+ $checkThis = preg_replace('/^'. $type .'/', '', $suffix);
+ if(strlen($checkThis) && is_numeric($checkThis)) {
+ //oooh... it's something like "BETA3"
+ $retval = array(
+ 'type' => $type,
+ 'number' => $checkThis
+ );
+ }
+ else {
+ $this->error_handler(__METHOD__ .": invalid suffix (". $suffix .")");
+ }
+ break;
+ }
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": invalid suffix (". $suffix .")");
+ }
+
+ return($retval);
+ }//end parse_suffix()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function fix_xml_config($config, $path=null) {
+ $this->xmlLoops++;
+ if($this->xmlLoops > 1000) {
+ $this->error_handler(__METHOD__ .": infinite loop detected...");
+ }
+
+ try {
+ $a2p = new cs_arrayToPath($config);
+ }
+ catch(exception $e) {
+ $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage());
+ $this->error_handler($e->getMessage());
+ }
+ if(!is_array($this->tempXmlConfig)) {
+ $this->tempXmlConfig = array();
+ }
+ try {
+ $myA2p = new cs_arrayToPath(&$this->tempXmlConfig);
+ }
+ catch(exception $e) {
+ $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage());
+ $this->error_handler($e->getMessage());
+ }
+
+ $myData = $a2p->get_data($path);
+
+ if(is_array($myData)) {
+ if(isset($myData['type']) && $myData['type'] != 'open') {
+ if($myData['type'] == 'complete') {
+ $val = null;
+ if(isset($myData['value'])) {
+ $val = $myData['value'];
+ }
+ $oldData = $myA2p->get_data();
+ $myA2p->set_data($path, $val);
+ $this->tempXmlConfig = $myA2p->get_data();
+ }
+ else {
+ $this->error_handler(__METHOD__ .": invalid type (". $myData['type'] .")");
+ }
+ }
+ else {
+ foreach($myData as $i=>$d) {
+ if(!in_array($i, array('type', 'attributes', 'value'))) {
+ $this->fix_xml_config($config, $path .'/'. $i);
+ }
+ }
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": unable to fix data on path=(". $path .")::: ". $this->gfObj->debug_print($myData,0));
+ }
+ }//end fix_xml_config()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function load_table() {
+ $schemaFileLocation = dirname(__FILE__) .'/schema/schema.sql';
+ $schema = file_get_contents($schemaFileLocation);
+ $schema = str_replace('{tableName}', $this->config['DB_TABLE'], $schema);
+ $schema = str_replace('{primaryKey}', $this->config['DB_PRIMARYKEY'], $schema);
+ $this->db->exec($schema);
+
+ $loadTableResult = $this->db->errorMsg();
+ if(!strlen($loadTableResult)) {
+ $loadTableResult = true;
+ $logRes = 'Successfully loaded';
+ $logType = 'initialize';
+
+ //now set the initial version information...
+ if(strlen($this->projectName) && strlen($this->versionFileVersion)) {
+ $this->load_initial_version();
+ }
+ else {
+ throw new exception(__METHOD__ .": missing projectName (". $this->projectName .") " .
+ "or versionFileVersion (". $this->versionFileVersion ."), cannot load data");
+ }
+ }
+ else {
+ $logRes = 'Failed to load';
+ $logType = 'error';
+ }
+ $this->do_log($logRes .' table ('. $this->config['DB_TABLE'] .') into ' .
+ 'database::: '. $loadTableResult, $logType);
+
+ return($loadTableResult);
+ }//end load_table()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function check_lockfile() {
+ $status = false;
+ if(file_exists($this->lockfile)) {
+ $status = true;
+ }
+
+ return($status);
+ }//end check_lockfile()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Create a *.lock file that indicates the system is in the process of
+ * performing an upgrade (safer than always updating the site's configuration
+ * file).
+ */
+ public function create_lockfile($contents) {
+ if(!$this->check_lockfile()) {
+ if($this->fsObj->create_file($this->lockfile)) {
+ if(!preg_match('/\n$/', $contents)) {
+ $contents .= "\n";
+ }
+ $writeRes = $this->fsObj->write($contents);
+ if(is_numeric($writeRes) && $writeRes > 0) {
+ $this->fsObj->closeFile();
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to write contents (". $contents .") to lockfile");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to create lockfile (". $this->lockfile .")");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to create lockfile, one already exists (". $this->lockfile .")");
+ }
+ }//end create_lockfile()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Destroy the *.lock file that indicates an upgrade is underway.
+ */
+ private function remove_lockfile() {
+ if($this->check_lockfile()) {
+ if(!$this->fsObj->rm($this->lockfile)) {
+ $this->error_handler(__METHOD__ .": failed to remove lockfile (". $this->lockfile .")");
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": no lockfile (". $this->lockfile .")");
+ }
+ }//end remove_lockfile()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function get_full_version_string($versionString) {
+ if(strlen($versionString)) {
+ $bits = $this->parse_version_string($versionString);
+
+ $fullVersion = $bits['version_major'] .'.'. $bits['version_minor'] .'.'.
+ $bits['version_maintenance'];
+ if(strlen($bits['version_suffix'])) {
+ $fullVersion .= '-'. $bits['version_suffix'];
+ }
+ }
+ else {
+ $this->error_handler(__METHOD__ .": no version string given");
+ }
+
+ return($fullVersion);
+ }//end get_full_version_string()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function error_handler($details) {
+ //log the error.
+ if(!is_object($this->logsObj)) {
+ throw new exception(__METHOD__ .": error while running an internal upgrade::: ". $details);
+ }
+ if($this->internalUpgradeInProgress === false) {
+ $this->do_log($details, 'exception in code');
+ }
+
+ //now throw an exception so other code can catch it.
+ throw new exception($details);
+ }//end error_handler()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function load_initial_version() {
+ //if there's an INITIAL_VERSION in the upgrade config file, use that.
+ $this->read_upgrade_config_file();
+ $insertData = array();
+ if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) {
+ $parseThis = $this->config['UPGRADELIST']['INITIALVERSION'];
+ }
+ else {
+ $parseThis = $this->versionFileVersion;
+ }
+ $versionInfo = $this->parse_version_string($parseThis);
+ $insertData = array(
+ 'project_name' => $this->projectName,
+ 'version_string' => $versionInfo['version_string']
+ );
+
+ $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert');
+
+ if($this->db->run_insert($sql, $this->sequenceName)) {
+ $loadRes = true;
+ $this->do_log("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize');
+ }
+ else {
+ $this->error_handler(__METHOD__ .": failed to load initial version::: ". $e->getMessage());
+ }
+
+ return($loadRes);
+ }//end load_initial_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ protected function do_log($message, $type) {
+ $this->debugLogs[] = array('project'=>$this->projectName,'upgradeFile'=>$this->config['UPGRADE_CONFIG_FILE'],'message'=>$message,'type'=>$type);
+ if($this->internalUpgradeInProgress === true) {
+ $this->storedLogs[] = func_get_args();
+ }
+ else {
+ $this->logsObj->log_by_class($message, $type);
+ }
+ }//end do_log()
+ //=========================================================================
+
+
+}//end upgrade{}
+
+
+?>
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:28:47
|
Revision: 104
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=104&view=rev
Author: crazedsanity
Date: 2009-08-19 15:28:38 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Copied folders from cs-webdblogger...
Added Paths:
-----------
trunk/0.3/README.txt
trunk/0.3/cs_webdblogger.class.php
trunk/0.3/setup/
trunk/0.3/upgrades/
Copied: trunk/0.3/README.txt (from rev 101, import/cs-webdblogger/trunk/0.2/README.txt)
===================================================================
--- trunk/0.3/README.txt (rev 0)
+++ trunk/0.3/README.txt 2009-08-19 15:28:38 UTC (rev 104)
@@ -0,0 +1,29 @@
+
+Once the appropriate schema has been built, code can be updated easily to start logging:
+
+//Create the class...
+$this->log = new cs_webdblogger($dbObj, 'Generic Activity');
+
+//Now call the logger.
+$this->log->log_by_class('User viewed page', 'info', $this->userId);
+
+
+
+UNDERSTANDING THE DATABASE SCHEMA:::
+I understand things best from real data, so here goes::::
+
+live_cs_project=# select rca.name as category, rcl.name as class, le.description from log_event_table AS le INNER JOIN log_class_table AS rcl USING (log_class_id) INNER JOIN log_category_table AS rca USING (log_category_id) limit 5;
+ category | class | description
+----------+--------+--------------------------
+ Project | Create | Project: created record
+ Project | Delete | Project: deleted record
+ Project | Update | Project: updated record
+ Project | Error | Project: ERROR
+ Helpdesk | Create | Helpdesk: Created record
+(5 rows)
+
+The category indicates what system it is attached to, and class is a more
+generic way of indicating what type of action it is.
+
+
+$Id$
\ No newline at end of file
Copied: trunk/0.3/cs_webdblogger.class.php (from rev 101, import/cs-webdblogger/trunk/0.2/cs_webdblogger.class.php)
===================================================================
--- trunk/0.3/cs_webdblogger.class.php (rev 0)
+++ trunk/0.3/cs_webdblogger.class.php 2009-08-19 15:28:38 UTC (rev 104)
@@ -0,0 +1,864 @@
+<?php
+/*
+ * Created on Mar 8, 2007
+ *
+ * NOTICE::: this class was derived from the logsClass.php found in cs-projet v1.2, found
+ * at URL: https://cs-project.svn.sourceforge.net/svnroot/cs-project/trunk/1.2/lib/logsClass.php
+ * Last SVN Signature (from cs-project v1.2): "logsClass.php 819 2008-02-09 10:01:10Z crazedsanity"
+ *
+ * SVN INFORMATION:::
+ * ------------------
+ * SVN Signature::::::: $Id$
+ * Last Author::::::::: $Author$
+ * Current Revision:::: $Revision$
+ * Repository Location: $HeadURL$
+ * Last Updated:::::::: $Date$
+ *
+ *
+ * Each class that's trying to log should have an internal var statically set to indicates what category
+ * it is: this allows them to call a method within this and tell it ONLY what "class" the log should be
+ * under, so this class can determine the appropriate log_event_id. This avoids having to hard-code
+ * too many id's that might need to be changed later. Yay, dynamic code!
+ *
+ * QUERY TO GET LAST COUPLE OF LOGS::::
+ SELECT l.log_id as id, l.creation, l.event_id as lid, le.description AS event, l.details
+ FROM cswdbl_log_table AS l INNER JOIN cswdbl_event_table AS le USING (event_id) ORDER BY log_id DESC LIMIT 25;
+ */
+
+//NOTE::: this class **REQUIRES** cs-content for its "cs_phpDB" class.
+
+require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php');
+
+class cs_webdblogger extends cs_versionAbstract {
+ /** Database handle */
+ public $db;
+
+ /** Cache of all records in the class table */
+ private $logClassCache = array();
+
+ /** Cache of all records in the attribute table */
+ private $attributeCache=array();
+
+ /** The category_id value to use, set on class creation. */
+ private $logCategoryId = null;
+
+ /** Default uid (users.id) to log under when no uid is available */
+ private $defaultUid = 0;
+
+ /** Category to use when logging a database error */
+ //TODO: make SURE this category is correct...
+ private $databaseCategory = 1;
+
+ /** Check to see if setup has been performed (avoids running it multiple times) **/
+ private $setupComplete=false;
+
+ /** Last SQL file handled */
+ protected $lastSQLFile=null;
+
+ /** Global functions class from cs-content */
+ protected $gfObj;
+
+ protected $pendingLogs;
+ private $suspendLogging=false;
+
+ /** List of tables keyed off an internal reference name. */
+ protected $tables = array(
+ 'category' => 'cswdbl_category_table',
+ 'class' => 'cswdbl_class_table',
+ 'event' => 'cswdbl_event_table',
+ 'log' => 'cswdbl_log_table',
+ 'attrib' => 'cswdbl_attribute_table',
+ 'logAttrib' => 'cswdbl_log_attribute_table'
+ );
+
+ /** List of sequences keyed off an internal reference name (MUST match references above) */
+ protected $seqs = array(
+ 'category' => "cswdbl_category_table_category_id_seq",
+ 'class' => "cswdbl_class_table_class_id_seq",
+ 'event' => "cswdbl_event_table_event_id_seq",
+ 'log' => "cswdbl_log_table_log_id_seq",
+ 'attrib' => "cswdbl_attribute_table_attribute_id_seq",
+ 'logAttrib' => "cswdbl_log_attribute_table_log_attribute_id_seq"
+ );
+
+ //=========================================================================
+ /**
+ * The constructor.
+ */
+ public function __construct(cs_phpDB &$db, $logCategory=null, $checkForUpgrades=true) {
+ //assign the database object.
+ $this->db = $db;
+
+ $this->set_version_file_location(dirname(__FILE__) . '/VERSION');
+
+ //Make sure the version of cs_phpDB is HIGHER THAN (not equal to) 1.0.0-ALPHA8,
+ // which added some methods that are required.
+ $mustBeHigherThan = '1.2-ALPHA8';
+ if(!$this->is_higher_version($mustBeHigherThan, $this->db->get_version())) {
+ throw new exception(__METHOD__ .": requires cs_phpDB of higher than v". $mustBeHigherThan,1);
+ }
+
+ $this->gfObj = new cs_globalFunctions;
+
+ //see if there's an upgrade to perform...
+ if($checkForUpgrades === true) {
+ $this->suspendLogging = true;
+ $upgObj = new cs_webdbupgrade(dirname(__FILE__) . '/VERSION', dirname(__FILE__) .'/upgrades/upgrade.xml');
+ $upgObj->check_versions(true);
+ $this->suspendLogging = false;
+ $this->handle_suspended_logs();
+ }
+
+ //assign the category_id.
+ if(strlen($logCategory)) {
+ if(!is_numeric($logCategory)) {
+ //attempt to retreive the logCategoryId (assuming they passed a name)
+ $this->logCategoryId = $this->get_category_id($logCategory);
+ }
+ else {
+ //it was numeric: set it!
+ $this->logCategoryId = $logCategory;
+ }
+ }
+
+ //check for a uid in the session.
+ $this->defaultUid = $this->get_uid();
+
+
+ //build our cache.
+ $this->build_cache();
+ }//end __construct()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Execute the entire contents of the given file (with absolute path) as SQL.
+ */
+ final public function run_sql_file($filename) {
+ if(!is_object($this->fsObj)) {
+ if(class_exists('cs_fileSystem')) {
+ $fsObj = new cs_fileSystem;
+ }
+ else {
+ throw new exception(__METHOD__ .": required library (cs_fileSystem) not found");
+ }
+ }
+
+ $this->lastSQLFile = $filename;
+
+ $fileContents = $fsObj->read($filename);
+ try {
+ $this->db->run_update($fileContents, true);
+ $this->build_cache();
+ $retval = TRUE;
+ }
+ catch(exception $e) {
+ $retval = FALSE;
+ }
+
+ return($retval);
+ }//end run_sql_file()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Build internal cache to avoid extra queries.
+ */
+ private function build_cache() {
+ //build query, run it, check for errors.
+ $sql = "SELECT class_id, lower(class_name) as name FROM ". $this->tables['class'];
+
+ try {
+ $data = $this->db->run_query($sql, 'name', 'class_id');
+
+ if(is_array($data)) {
+ $this->logClassCache = $data;
+ }
+ elseif($data == false) {
+ $this->logClassCache = array();
+ }
+ else {
+ throw new exception(__METHOD__ .": unknown data returned: ". $this->gfObj->debug_var_dump($data,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to build internal class cache::: ". $e->getMessage());
+ }
+
+ //now build cache for attributes.
+ $sql = "SELECT attribute_id, lower(attribute_name) AS attribute_name FROM ". $this->tables['attrib'];
+
+ try {
+ $data = $this->db->run_query($sql, 'attribute_name', 'attribute_id');
+
+ if(is_array($data)) {
+ $this->attributeCache = $data;
+ }
+ elseif($data == false) {
+ $this->attributeCache = array();
+ }
+ else {
+ throw new exception(__METHOD__ .": unknown data returned: ". $this->gfObj->debug_var_dump($data,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error occurred while retrieving attribute cache::: ". $e->getMessage());
+ }
+ }//end build_cache()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Retrieve log_class_id value from the given name, or insert a new one.
+ */
+ private function get_class_id($name) {
+ $name = strtolower($name);
+
+ //get the id.
+ if(isset($this->logClassCache[$name])) {
+ //set the id.
+ $retval = $this->logClassCache[$name];
+ }
+ else {
+ //create the class & then rebuild cache.
+ $retval = $this->create_class($name);
+ $this->build_cache();
+ }
+
+ return($retval);
+ }//end get_class_id()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Retrieve log_event_id based on the given class name & the internal
+ * logCategoryId value.
+ */
+ function get_event_id($logClassName) {
+ $sqlArr = array(
+ 'class_id' => $this->get_class_id($logClassName),
+ 'category_id' => $this->logCategoryId
+ );
+ $sql = "SELECT event_id FROM ". $this->tables['event'] ." WHERE " .
+ $this->gfObj->string_from_array($sqlArr, 'select', NULL, 'numeric');
+
+ try {
+ $data = $this->db->run_query($sql);
+
+
+ if($data === false) {
+ //no records & no error: create one.
+ $retval = $this->auto_insert_record($sqlArr['class_id']);
+ }
+ elseif(is_array($data) && isset($data['event_id'])) {
+ $retval = $data['event_id'];
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid data returned::: ". $this->gfObj->debug_var_dump($data,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to retrieve event_id::: ". $e->getMessage());
+ }
+
+ return($retval);
+ }//end get_event_id()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * The primary means of building log entries: use log_dberror() to log an
+ * error with a bit more capabilities; throws the details of the error as
+ * an exception.
+ */
+ public function log_by_class($details, $className="error", $uid=NULL, array $logAttribs=NULL) {
+
+ if($this->suspendLogging === true) {
+ $this->pendingLogs[] = func_get_args();
+ $retval = count($this->pendingLogs) -1;
+ }
+ else {
+ if(count($this->pendingLogs)) {
+ $this->handle_suspended_logs();
+ }
+
+ //make sure there's a valid class name.
+ if(!strlen($className) || is_null($className)) {
+ $className = 'error';
+ }
+
+ //make sure we've got a uid to log under.
+ if(is_null($uid) || !is_numeric($uid)) {
+ //set it.
+ $uid = $this->defaultUid;
+ }
+
+ //determine the log_event_id.
+ try {
+ $logEventId = $this->get_event_id($className);
+ }
+ catch(Exception $e) {
+ throw new exception(__METHOD__ .": while attempting to retrieve logEventId, encountered an " .
+ "exception:::\n". $e->getMessage() ."\n\nCLASS: $className\nDETAILS: $details");
+ }
+
+ //check to see what uid to use.
+ $myUid = $this->get_uid();
+
+ //okay, setup an array of all the data we need.
+ $cleanStringArr = array(
+ 'event_id' => 'numeric',
+ 'uid' => 'numeric',
+ 'affected_uid' => 'numeric',
+ 'details' => 'sql'
+ );
+ $sqlArr = array (
+ 'event_id' => $this->gfObj->cleanString($logEventId, 'numeric'),
+ 'uid' => $myUid,
+ 'affected_uid' => $uid,
+ 'details' => $details
+ );
+
+ //build, run, error-checking.
+ $sql = "INSERT INTO ". $this->tables['log'] ." ". $this->gfObj->string_from_array($sqlArr, 'insert', NULL, $cleanStringArr, TRUE);
+
+ try {
+ $newId = $this->db->run_insert($sql, $this->seqs['log']);
+
+ if(is_numeric($newId) && $newId > 0) {
+ $retval = $newId;
+
+ if(is_array($logAttribs) && count($logAttribs)) {
+ $this->create_log_attributes($newId, $logAttribs);
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to insert id or invalid return (". $this->gfObj->debug_var_dump($newId,0) .")");
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error while creating log::: ". $e->getMessage());
+ }
+ }
+
+ return($retval);
+ }//end log_by_class()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Logs an error like log_by_class(), but also throws an exception.
+ */
+ public function log_dberror($details, $uid=NULL, $skipCurrentCatLog=FALSE) {
+ //set the error for the current category.
+ if(!$skipCurrentCatLog && ($this->logCategoryId !== $this->databaseCategory)) {
+ //yep, log it!
+ $this->log_by_class($details, 'error', $uid);
+ }
+
+ //now log the database error.
+ $originalCategoryId = $this->logCategoryId;
+ $this->logCategoryId = $this->databaseCategory;
+ $retval = $this->log_by_class($details, 'error', $uid);
+ $this->logCategoryId = $originalCategoryId;
+
+ throw new exception(__METHOD__ .": encountered error::: $details");
+ }//end log_dberror()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Attempts to auto-recover if a class was requested that doesn't exist.
+ */
+ private function auto_insert_record($logClassId) {
+ //generate a default name
+
+ $className = $this->get_class_name($logClassId);
+ $categoryName = $this->get_category_name($this->logCategoryId);
+
+ $details = ucwords($categoryName) .": ". ucwords($className);
+
+ if(strlen($details) <= 4) {
+ //something bad happened (i.e. details="0: 0")
+ throw new exception(__METHOD__ .": failed to recover with class_id=(". $logClassId .") " .
+ "AND category_id=(". $this->logCategoryId ."), details=(". $details .")");
+ }
+ else {
+ //create the sql array.
+ $sqlArr = array (
+ 'class_id' => $logClassId,
+ 'category_id' => $this->logCategoryId,
+ 'description' => "'". $this->gfObj->cleanString($details, 'sql') ."'"
+ );
+
+ //now run the insert.
+ $sql = 'INSERT INTO '. $this->tables['event'] .' '. $this->gfObj->string_from_array($sqlArr, 'insert');
+
+ try {
+ $newId = $this->db->run_insert($sql, $this->seqs['event']);
+
+ if(is_numeric($newId) && $newId > 0) {
+ $retval = $newId;
+ }
+ else {
+ throw new exception(__METHOD__ .": unable to insert id or bad return::: ". $this->gfObj->debug_var_dump($newId,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to create record::: ". $e->getMessage());
+ }
+ }
+
+ return($retval);
+ }//end auto_insert_record()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Retrieves logs with the given criteria.
+ */
+ public function get_logs(array $criteria, array $orderBy=NULL, $limit=20) {
+ //set a default for the limit.
+ if(!is_numeric($limit) || $limit < 1) {
+ //set it again.
+ $limit = 20;
+ }
+
+ if(is_null($orderBy) || count($orderBy) < 1) {
+ //set it.
+ $orderBy = array(
+ 'log_id DESC'
+ );
+ }
+
+ //set the fields that can be used, along with what alias for the table & cleaning type to use on the data.
+ $allowedCritFields = array(
+ 'class_id' => array('cl', 'numeric'),
+ 'category_id' => array('ca', 'numeric'),
+ 'uid' => array('l', 'numeric'),
+ 'affected_uid' => array('l', 'numeric'),
+ 'creation' => array('l', 'sql')
+ );
+
+ //loop through the data to create our cleaned, prefixed array of criteria.
+ $sqlArr = array();
+ foreach($criteria AS $field => $value) {
+ //is this field in the allowed list?
+ if(isset($allowedCritFields[$field])) {
+ //grab data for this field.
+ $myFieldData = $allowedCritFields[$field];
+ $cleanStringArg = $myFieldData[1];
+
+ //clean the data.
+ if($field == 'creation' && is_numeric($value)) {
+ $value = $this->gfObj->cleanString($value, 'numeric');
+ $cleanedData = ">= (NOW() - interval '". $value ." hours')";
+ }
+ else {
+ $cleanedData = $this->gfObj->cleanString($value, $cleanStringArg);
+ }
+
+ //set the prefixed column name.
+ $prefixedName = $myFieldData[0] .'.'. $field;
+
+ //now add it to our array.
+ $sqlArr[$prefixedName] = $cleanedData;
+ }
+ }
+
+
+ //build the criteria.
+ $sqlArr['ca.category_id'] = '>0';
+ $critString = $this->gfObj->string_from_array($sqlArr, 'select');
+
+ //check if "timeperiod" is in there (it's special)
+ if(isset($criteria['timeperiod']) && isset($criteria['timeperiod']['start']) && isset($criteria['timeperiod']['end'])) {
+ //add it in!
+ $myTime = $criteria['timeperiod'];
+ $addThis = "(l.creation >= '". $myTime['start'] ."'::date AND l.creation <= '". $myTime['end'] ."'::date + interval '1 day')";
+ $critString = create_list($critString, $addThis, ' AND ');
+ }
+
+ $orderString = $this->gfObj->string_from_array($orderBy, 'limit');
+ $sql = "select " .
+ "l.creation, " .
+ "l.log_id, " .
+ "l.uid, " .
+ "cl.class_name, " .
+ "ca.category_name, " .
+ "ev.description, " .
+ "l.details " .
+ "FROM ". $this->tables['log'] ." AS l " .
+ "INNER JOIN ". $this->tables['event'] ." AS ev ON (l.event_id=ev.event_id) " .
+ "INNER JOIN ". $this->tables['class'] ." AS cl ON (cl.class_id=ev.class_id) " .
+ "INNER JOIN ". $this->tables['category'] ." AS ca ON (ca.category_id=ev.category_id) " .
+ "WHERE " . $critString . " " .
+ "ORDER BY " .
+ "log_id DESC " .
+ "LIMIT ". $limit;
+
+ try {
+ //run it.
+ $data = $this->db->run_query($sql, 'log_id');
+
+ $retval = array();
+ if(is_array($data)) {
+ $retval = $data;
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": failed to retrieve logs::: ". $e->getMessage());
+ }
+
+ return($retval);
+ }//end get_logs()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Uses arbitrary criteria to retrieve the last X log entries.
+ */
+ public function get_recent_logs($numEntries=null) {
+ if(!is_numeric($numEntries) || $numEntries < 1) {
+ $numEntries = 20;
+ }
+
+ //set the criteria so we only get the last few entries.
+ $retval = $this->get_logs(array(), NULL, $numEntries);
+ return($retval);
+ }//end get_recent_logs()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Retrieve category_id from the given name.
+ */
+ private function get_category_id($catName) {
+ if(strlen($catName) && is_string($catName)) {
+ $catName = trim($catName);
+ $sql = "SELECT category_id FROM ". $this->tables['category'] ." WHERE lower(category_name) = '". strtolower($catName) ."'";
+
+ try {
+
+ $data = $this->db->run_query($sql);
+
+ $numrows = $this->db->numRows();
+ if($numrows == 1 && is_array($data) && isset($data['category_id']) && is_numeric($data['category_id'])) {
+ $retval = $data['category_id'];
+ }
+ elseif($data === false) {
+ $retval = $this->create_log_category($catName);
+ }
+ elseif($numrows > 1) {
+ throw new exception(__METHOD__ .": found too many records (". $numrows .")");
+ }
+ else {
+ throw new exception(__METHOD__ .": unknown error (bad data in array?)");
+ }
+ }
+ catch(exception $e) {
+ if($this->setupComplete === true) {
+ throw new exception(__METHOD__ .": encountered error::: ". $e->getMessage());
+ }
+ else {
+ $mySchemaFile = dirname(__FILE__) .'/setup/schema.'. $this->db->get_dbtype() .'.sql';
+ if(file_exists($mySchemaFile)) {
+ $this->setupComplete = true;
+ $this->run_sql_file($mySchemaFile);
+
+ //Create the default category.
+ $this->create_log_category('Database');
+
+ $retval = $this->create_log_category($catName);
+ }
+ else {
+ throw new exception(__METHOD__ .": missing schema file (". $mySchemaFile ."), can't run setup");
+ }
+ }
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": category name (". $catName .") is invalid");
+ }
+
+ return($retval);
+ }//end get_category_id()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Create a category_id based on the given name.
+ */
+ private function create_log_category($catName) {
+ $sql = "INSERT INTO ". $this->tables['category'] ." (category_name) VALUES ('".
+ $this->gfObj->cleanString($catName, 'sql') ."')";
+
+ try {
+ $newId = $this->db->run_insert($sql, $this->seqs['category']);
+
+ if(is_numeric($newId) && $newId > 0) {
+ $retval = $newId;
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid data returned for " .
+ "category::: ". $this->gfObj->debug_var_dump($newId,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error encountered while trying to " .
+ "create category::: ". $e->getMessage());
+ }
+
+ return($retval);
+ }//end create_log_category()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Create a log_class_id based on the given name.
+ */
+ private function create_class($className) {
+ $sql = "INSERT INTO ". $this->tables['class'] ." (class_name) VALUES ('".
+ $this->gfObj->cleanString($className, 'sql') ."')";
+
+
+ try {
+ $newId = $this->db->run_insert($sql, $this->seqs['class']);
+
+ if(is_numeric($newId) && $newId > 0) {
+ $retval = $newId;
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to insert class or invalid " .
+ "id::: ". $this->gfObj->debug_var_dump($newId,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error encountered while creating log " .
+ "class::: ". $e->getMessage());
+ }
+
+ return($retval);
+ }//end create_class()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Retrieve class name from the given id.
+ */
+ private function get_class_name($classId) {
+ if(is_numeric($classId)) {
+ $sql = "SELECT class_name FROM ". $this->tables['class'] ." WHERE class_id=". $classId;
+
+ try {
+ $data = $this->db->run_query($sql);
+
+ if(is_array($data) && isset($data['class_name']) && $this->db->numRows() == 1) {
+ $className = $data['class_name'];
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to retrieve class " .
+ "name, or invalid return data::: ". $this->gfObj->debug_print($data,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error encountered while " .
+ "retrieving class name::: ". $e->getMessage());
+ }
+
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid class ID (". $classId .")");
+ }
+
+ return($className);
+ }//end get_class_name()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ * Retrieve category name from the given ID.
+ */
+ private function get_category_name($categoryId) {
+ if(is_numeric($categoryId)) {
+ $sql = "SELECT category_name FROM ". $this->tables['category'] ." WHERE category_id=". $categoryId;
+
+ try {
+ $data = $this->db->run_query($sql);
+
+ if(is_array($data) && isset($data['category_name']) && $this->db->numRows() == 1) {
+ $categoryName = $data['category_name'];
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to retrieve " .
+ "category name::: ". $this->gfObj->debug_var_dump($data,0));
+ }
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": error encountered while " .
+ "retrieving category name::: ". $e->getMessage());
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid category ID (". $categoryId .")");
+ }
+
+ return($categoryName);
+ }//end get_category_name()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function __get($var) {
+ return($this->$var);
+ }//end __get()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function __set($var, $newVal) {
+ $res = false;
+ switch($var) {
+ case 'suspendLogging':
+ $this->$var = $newVal;
+ if($newVal === false) {
+ #$this->handle_suspended_logs();
+ }
+ $res = true;
+ break;
+
+ case 'logCategory':
+ case 'logCategoryId':
+ $this->logCategoryId = $this->get_category_id($newVal);
+ $res = true;
+ break;
+ }
+ return($res);
+ }//end __set()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function handle_suspended_logs() {
+ $retval = 0;
+ $debugThis = array();
+ if($this->suspendLogging === false && count($this->pendingLogs)) {
+ $myLogs = $this->pendingLogs;
+ $this->build_cache();
+ $this->pendingLogs = array();
+ foreach($myLogs as $i=>$args) {
+ //this is potentially deadly: call self recursively to log the items prevously suspended.
+ $newId = call_user_func_array(array($this, 'log_by_class'), $args);
+
+ $debugThis[$newId] = $args;
+ $retval++;
+ }
+ }
+ return($retval);
+ }//end handle_suspended_logs()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function get_uid() {
+ $myUid = $this->defaultUid;
+ //check for a uid in the session.
+ if(is_array($_SESSION) && isset($_SESSION['uid']) && is_numeric($_SESSION['uid'])) {
+ //got an ID in the session.
+ $myUid = $_SESSION['uid'];
+ }
+ return($myUid);
+ }//end get_uid()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function create_attribute($attribName, $buildCache=true) {
+
+ $myId = null;
+ if(isset($this->attributeCache[strtolower($attribName)])) {
+ $myId = $this->attributeCache[strtolower($attribName)];
+ }
+ else {
+ $sql = "INSERT INTO ". $this->tables['attrib'] ." (attribute_name) " .
+ "VALUES ('". $this->gfObj->cleanString($attribName, 'sql_insert') ."')";
+
+ try {
+ $myId = $this->db->run_insert($sql, $this->seqs['attrib']);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": fatal error while creating attribute (". $attribName .")::: ". $e->getMessage());
+ }
+ }
+
+ if($buildCache) {
+ $this->build_cache();
+ }
+
+ return($myId);
+ }//end create_attribute()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ private function create_log_attributes($logId, array $attribs) {
+ $myIds = array();
+ foreach($attribs as $name=>$val) {
+ $insertData = array(
+ 'log_id' => $logId,
+ 'attribute_id' => $this->create_attribute($name, false),
+ 'value_text' => $val
+ );
+ $sql = "INSERT INTO ". $this->tables['logAttrib'] ." ".
+ $this->gfObj->string_from_array($insertData, 'insert');
+
+ try {
+ $myIds[$name][] = $this->db->run_insert($sql, $this->seqs['logAttrib']);
+ }
+ catch(exception $e) {
+ throw new exception(__METHOD__ .": fatal error while creating log attribute " .
+ "(". $name .")::: ". $e->getMessage());
+ }
+ }
+ $this->build_cache();
+
+ }//end create_log_attributes()
+ //=========================================================================
+
+
+}//end logsClass{}
+?>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:27:47
|
Revision: 103
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=103&view=rev
Author: crazedsanity
Date: 2009-08-19 15:27:38 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Import of cs-versionparse.
Added Paths:
-----------
trunk/0.3/CREDITS
trunk/0.3/LICENSE
trunk/0.3/VERSION
trunk/0.3/cs_version.abstract.class.php
Copied: trunk/0.3/CREDITS (from rev 101, import/cs-versionparse/trunk/0.1/CREDITS)
===================================================================
--- trunk/0.3/CREDITS (rev 0)
+++ trunk/0.3/CREDITS 2009-08-19 15:27:38 UTC (rev 103)
@@ -0,0 +1,3 @@
+
+Lead Developer: Dan Falconer (cra...@us...)
+
Copied: trunk/0.3/LICENSE (from rev 101, import/cs-versionparse/trunk/0.1/LICENSE)
===================================================================
--- trunk/0.3/LICENSE (rev 0)
+++ trunk/0.3/LICENSE 2009-08-19 15:27:38 UTC (rev 103)
@@ -0,0 +1,291 @@
+NOTE: a full HTML version of this license can be found at:
+http://www.opensource.org/licenses/gpl-license.php
+
+It has been reproduced below without any HTML.
+==========================================================================
+
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
Copied: trunk/0.3/VERSION (from rev 101, import/cs-versionparse/trunk/0.1/VERSION)
===================================================================
--- trunk/0.3/VERSION (rev 0)
+++ trunk/0.3/VERSION 2009-08-19 15:27:38 UTC (rev 103)
@@ -0,0 +1,6 @@
+## Stores the current version of the cs-versionparse system, and it's source.
+## Please do NOT modify this file.
+
+VERSION: 0.3.0
+PROJECT: cs-webapplibs
+$HeadURL$
\ No newline at end of file
Copied: trunk/0.3/cs_version.abstract.class.php (from rev 101, import/cs-versionparse/trunk/0.1/cs_version.abstract.class.php)
===================================================================
--- trunk/0.3/cs_version.abstract.class.php (rev 0)
+++ trunk/0.3/cs_version.abstract.class.php 2009-08-19 15:27:38 UTC (rev 103)
@@ -0,0 +1,398 @@
+<?php
+/*
+ * Created on January 01, 2009 by Dan Falconer
+ *
+ * SVN INFORMATION:::
+ * -------------------
+ * Last Author::::::::: $Author$
+ * Current Revision:::: $Revision$
+ * Repository Location: $HeadURL$
+ * Last Updated:::::::: $Date$
+ */
+
+abstract class cs_versionAbstract {
+
+ public $isTest = FALSE;
+
+
+
+ private $versionFileLocation=null;
+ private $fullVersionString;
+ private $suffixList = array(
+ 'ALPHA', //very unstable
+ 'BETA', //kinda unstable, but probably useable
+ 'RC' //all known bugs fixed, searching for unknown ones
+ );
+
+
+
+ abstract public function __construct();
+
+
+
+ //=========================================================================
+ /**
+ * Retrieve our version string from the VERSION file.
+ */
+ final public function get_version($asArray=false) {
+ $retval = NULL;
+
+ $this->auto_set_version_file();
+
+ if(file_exists($this->versionFileLocation)) {
+ $myMatches = array();
+ $findIt = preg_match('/VERSION: (.+)/', file_get_contents($this->versionFileLocation), $matches);
+
+ if($findIt == 1 && count($matches) == 2) {
+ $fullVersionString = $matches[1];
+ $versionInfo = $this->parse_version_string($fullVersionString);
+ $this->fullVersionString = $this->build_full_version_string($versionInfo);
+
+
+ if($asArray) {
+ $retval = $versionInfo;
+ $retval['version_string'] = $this->fullVersionString;
+ }
+ else {
+ $retval = $this->build_full_version_string($versionInfo);
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to retrieve version string in file " .
+ "(". $this->versionFileLocation .")");
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to retrieve version information, file " .
+ "(". $this->versionFileLocation .") does not exist or was not set");
+ }
+
+ return($retval);
+ }//end get_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function __get($var) {
+ return($this->$var);
+ }//end __get()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ final public function get_project() {
+ $retval = NULL;
+ $this->auto_set_version_file();
+ if(file_exists($this->versionFileLocation)) {
+ $myMatches = array();
+ $findIt = preg_match('/PROJECT: (.+)/', file_get_contents($this->versionFileLocation), $matches);
+
+ if($findIt == 1 && count($matches) == 2 && strlen($matches[1])) {
+ $retval = $matches[1];
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to retrieve project string");
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to retrieve project information");
+ }
+
+ return($retval);
+ }//end get_project()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function set_version_file_location($location) {
+ if(file_exists($location)) {
+ $this->versionFileLocation = $location;
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid location of VERSION file (". $location .")");
+ }
+ }//end set_version_file_location()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ protected function auto_set_version_file() {
+ if(!strlen($this->versionFileLocation)) {
+ $bt = debug_backtrace();
+ foreach($bt as $callNum=>$data) {
+ if(strlen($data['class'])) {
+ if($data['class'] != __CLASS__) {
+ $dir = dirname($data['file']);
+ if(preg_match('/tests$/', $dir)) {
+ $dir = preg_replace('/\/tests$/', '', $dir);
+ }
+ elseif(preg_match('/test$/', $dir)) {
+ $dir = preg_replace('/\/test$/', '', $dir);
+ }
+ break;
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to locate the calling class in backtrace");
+ }
+ }
+
+ if(file_exists($dir .'/VERSION')) {
+ $this->set_version_file_location($dir .'/VERSION');
+ }
+ else {
+ throw new exception(__METHOD__ .": failed to automatically set version file (tried ". $dir ."/VERSION)");
+ }
+ }
+ }//end auto_set_version_file()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ /**
+ *
+ * TODO: add logic to split apart the suffix (i.e. "-ALPHA5" broken into "ALPHA" and "5").
+ */
+ public function parse_version_string($version) {
+ if(is_string($version) && strlen($version) && preg_match('/\./', $version)) {
+ $version = preg_replace('/ /', '', $version);
+
+ $pieces = explode('.', $version);
+ $retval = array(
+ 'version_major' => $pieces[0],
+ 'version_minor' => $pieces[1]
+ );
+ if(isset($pieces[2]) && strlen($pieces[2])) {
+ $retval['version_maintenance'] = $pieces[2];
+ }
+ else {
+ $retval['version_maintenance'] = 0;
+ }
+
+ if(preg_match('/-/', $retval['version_maintenance'])) {
+ $bits = explode('-', $retval['version_maintenance']);
+ $retval['version_maintenance'] = $bits[0];
+ $suffix = $bits[1];
+ }
+ elseif(preg_match('/-/', $retval['version_minor'])) {
+ $bits = explode('-', $retval['version_minor']);
+ $retval['version_minor'] = $bits[0];
+ $suffix = $bits[1];
+ }
+ else {
+ $suffix = "";
+ }
+ $retval['version_suffix'] = $suffix;
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid version string passed (". $version .")");
+ }
+
+ return($retval);
+ }//end parse_version_string()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function build_full_version_string(array $versionInfo) {
+ $requiredIndexes = array(
+ 'version_major', 'version_minor', 'version_maintenance', 'version_suffix'
+ );
+
+ $missing="";
+ $count=0;
+ foreach($requiredIndexes as $indexName) {
+ if(isset($versionInfo[$indexName])) {
+ $count++;
+ }
+ else {
+ if(strlen($missing)) {
+ $missing .= ", ". $indexName;
+ }
+ else {
+ $missing = $indexName;
+ }
+ }
+ }
+
+ if($count == count($requiredIndexes) && !strlen($missing)) {
+ $suffix = $versionInfo['version_suffix'];
+ unset($versionInfo['version_suffix']);
+
+ $retval = "";
+ foreach($versionInfo as $name=>$value) {
+ if(strlen($retval)) {
+ $retval .= ".". $value;
+ }
+ else {
+ $retval = $value;
+ }
+ }
+ if(strlen($suffix)) {
+ $retval .= "-". $suffix;
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": missing indexes in given array (". $missing .")");
+ }
+
+ return($retval);
+
+ }//end build_full_version_string()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ public function is_higher_version($version, $checkIfHigher) {
+ $retval = FALSE;
+ $this->gfObj = new cs_globalFunctions;
+ if(!is_string($version) || !is_string($checkIfHigher)) {
+ throw new exception(__METHOD__ .": no valid version strings, version=(". $version ."), checkIfHigher=(". $checkIfHigher .")");
+ }
+ elseif($version == $checkIfHigher) {
+ $retval = FALSE;
+ }
+ else {
+ $curVersionArr = $this->parse_version_string($version);
+ $checkVersionArr = $this->parse_version_string($checkIfHigher);
+
+ unset($curVersionArr['version_string'], $checkVersionArr['version_string']);
+
+
+ $curVersionSuffix = $curVersionArr['version_suffix'];
+ $checkVersionSuffix = $checkVersionArr['version_suffix'];
+
+
+ unset($curVersionArr['version_suffix']);
+
+ foreach($curVersionArr as $index=>$versionNumber) {
+ $checkThis = $checkVersionArr[$index];
+
+ if(is_numeric($checkThis) && is_numeric($versionNumber)) {
+ //set them as integers.
+ settype($versionNumber, 'int');
+ settype($checkThis, 'int');
+
+ if($checkThis > $versionNumber) {
+ $retval = TRUE;
+ break;
+ }
+ elseif($checkThis == $versionNumber) {
+ //they're equal...
+ }
+ else {
+ //TODO: should there maybe be an option to throw an exception (freak out) here?
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": ". $index ." is not numeric in one of the strings " .
+ "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")");
+ }
+ }
+
+ //now deal with those damnable suffixes, but only if the versions are so far identical: if
+ // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when
+ // we already know there's a major, minor, or maintenance version that's also higher.
+ if($retval === FALSE) {
+ //EXAMPLE: $version="1.0.0-BETA3", $checkIfHigher="1.1.0"
+ // Moving from a non-suffixed version to a suffixed version isn't supported, but the inverse is:
+ // i.e. (1.0.0-BETA3 to 1.0.0) is okay, but (1.0.0 to 1.0.0-BETA3) is NOT.
+ // Also: (1.0.0-BETA3 to 1.0.0-BETA4) is okay, but (1.0.0-BETA4 to 1.0.0-BETA3) is NOT.
+ if(strlen($curVersionSuffix) && strlen($checkVersionSuffix) && $curVersionSuffix == $checkVersionSuffix) {
+ //matching suffixes.
+ }
+ elseif(strlen($curVersionSuffix) || strlen($checkVersionSuffix)) {
+ //we know the suffixes are there and DO match.
+ if(strlen($curVersionSuffix) && strlen($checkVersionSuffix)) {
+ //okay, here's where we do some crazy things...
+ $curVersionData = $this->parse_suffix($curVersionSuffix);
+ $checkVersionData = $this->parse_suffix($checkVersionSuffix);
+
+ if($curVersionData['type'] == $checkVersionData['type']) {
+ //got the same suffix type (like "BETA"), check the number.
+ if($checkVersionData['number'] > $curVersionData['number']) {
+ //new version's suffix number higher than current...
+ $retval = TRUE;
+ }
+ elseif($checkVersionData['number'] == $curVersionData['number']) {
+ //new version's suffix number is EQUAL TO current...
+ $retval = FALSE;
+ }
+ else {
+ //new version's suffix number is LESS THAN current...
+ $retval = FALSE;
+ }
+ }
+ else {
+ //not the same suffix... see if the new one is higher.
+ $suffixValues = array_flip($this->suffixList);
+ if($suffixValues[$checkVersionData['type']] > $suffixValues[$curVersionData['type']]) {
+ $retval = TRUE;
+ }
+ else {
+ //current suffix type is higher...
+ }
+ }
+
+ }
+ elseif(strlen($curVersionSuffix) && !strlen($checkVersionSuffix)) {
+ //i.e. "1.0.0-BETA1" to "1.0.0" --->>> OKAY!
+ $retval = TRUE;
+ }
+ elseif(!strlen($curVersionSuffix) && strlen($checkVersionSuffix)) {
+ //i.e. "1.0.0" to "1.0.0-BETA1" --->>> NOT ACCEPTABLE!
+ }
+ }
+ else {
+ //no suffix to care about
+ }
+ }
+ }
+
+ return($retval);
+
+ }//end is_higher_version()
+ //=========================================================================
+
+
+
+ //=========================================================================
+ protected function parse_suffix($suffix) {
+ $retval = NULL;
+ if(strlen($suffix)) {
+ //determine what kind it is.
+ foreach($this->suffixList as $type) {
+ if(preg_match('/^'. $type .'/', $suffix)) {
+ $checkThis = preg_replace('/^'. $type .'/', '', $suffix);
+ if(strlen($checkThis) && is_numeric($checkThis)) {
+ //oooh... it's something like "BETA3"
+ $retval = array(
+ 'type' => $type,
+ 'number' => $checkThis
+ );
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid suffix (". $suffix .")");
+ }
+ break;
+ }
+ }
+ }
+ else {
+ throw new exception(__METHOD__ .": invalid suffix (". $suffix .")");
+ }
+
+ return($retval);
+ }//end parse_suffix()
+ //=========================================================================
+
+
+}
+?>
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:25:44
|
Revision: 102
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=102&view=rev
Author: crazedsanity
Date: 2009-08-19 15:25:32 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Trunk + 0.3 folder, for bleeding-edge development.
NOTE::: starting @ 0.3 instead of 0.1 to avoid overlap from the 3 existing libs, which were at max of 0.2.x...
Added Paths:
-----------
trunk/
trunk/0.3/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:18:52
|
Revision: 2
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=2&view=rev
Author: crazedsanity
Date: 2009-08-19 15:18:36 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Initial layout for importing the other libraries.
Added Paths:
-----------
import/cs-versionparse/
import/cs-webdblogger/
import/cs-webdbupgrade/
Property Changed:
----------------
import/
Property changes on: import
___________________________________________________________________
Added: svn:ignore
+ .project
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <cra...@us...> - 2009-08-19 15:08:57
|
Revision: 1
http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=1&view=rev
Author: crazedsanity
Date: 2009-08-19 15:08:50 +0000 (Wed, 19 Aug 2009)
Log Message:
-----------
Added Paths:
-----------
import/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|