diff --git a/code/web/app/app_achievements/_AchWebParser/AchWebParser.php b/code/web/app/app_achievements/_AchWebParser/AchWebParser.php
new file mode 100644
index 000000000..3e2cae8df
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/AchWebParser.php
@@ -0,0 +1,94 @@
+connect($CONF['mysql_server'],$CONF['mysql_user'],$CONF['mysql_pass'],$CONF['mysql_database']);
+
+ #MISSING: mode -> single, cron, debug
+
+ require_once("class/DataSourceHandler_class.php");
+ require_once("class/DataSource_abstract.php");
+
+ //create datasource handler
+ $_DATA = new DataSourceHandler();
+ foreach($CONF['data_source'] as $elem) { //populate
+ require_once("source/".$elem."/".$elem."_class.php");
+ eval('$tmp = new '.$elem.'();');
+ $_DATA->registerDataSource($tmp);
+ }
+
+ #MISSING: fetch candidates
+
+ foreach() {
+ #MISSING: fetch objectives to evaluate
+ foreach() {
+ #MISSING: fetch atoms
+ foreach() {
+ #MISSING: evaluate atoms
+ }
+ #MISSING: evaluate objective
+ }
+ #MISSING: evaluate perk
+ }
+
+ #WORKPAD:####
+
+ Trigger:
+ by value
+ (by event)
+
+ Sources:
+ XML
+ valuecache
+ (Achievement Service)
+ (Mirror Service)
+
+
+ VALUE dappers = c_money
+ if(dappers >= 5000) {
+ GRANT
+ }
+
+ VALUE tmp = c_fame[scorchers]
+ if(tmp == 0) {
+ DENY:3600
+ }
+
+ EVENT:player_death
+ ON player_death {
+ UNLOCK
+ }
+
+ #############
+
+
+
+ #MISSING: self call on cron mode
+ if() {
+ $fp = fsockopen($CONF['self_host'], 80, $errno, $errstr, 30);
+ if(!$fp) {
+ logf("ERROR: self call; socket: ".$errstr." (."$errno.")");
+ }
+ else {
+ $out = "GET ".$CONF['self_path']." HTTP/1.1\r\n";
+ $out .= "Host: ".$CONF['self_host']."\r\n";
+ $out .= "Connection: Close\r\n\r\n";
+
+ fwrite($fp, $out);
+ fclose($fp);
+ }
+ }
+
+ exit(0);
+?>
\ No newline at end of file
diff --git a/code/web/app/app_achievements/_AchWebParser/_doc/Class_scheme.dia b/code/web/app/app_achievements/_AchWebParser/_doc/Class_scheme.dia
new file mode 100644
index 000000000..aa0d65c93
Binary files /dev/null and b/code/web/app/app_achievements/_AchWebParser/_doc/Class_scheme.dia differ
diff --git a/code/web/app/app_achievements/_AchWebParser/_doc/Class_scheme.png b/code/web/app/app_achievements/_AchWebParser/_doc/Class_scheme.png
new file mode 100644
index 000000000..98722b96e
Binary files /dev/null and b/code/web/app/app_achievements/_AchWebParser/_doc/Class_scheme.png differ
diff --git a/code/web/app/app_achievements/_AchWebParser/class/DataSourceHandler_class.php b/code/web/app/app_achievements/_AchWebParser/class/DataSourceHandler_class.php
new file mode 100644
index 000000000..53b64d8d6
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/class/DataSourceHandler_class.php
@@ -0,0 +1,41 @@
+source = array();
+ $this->alloc = array();
+
+
+ }
+
+ function registerDataSource($src) {
+ $i = sizeof($this->source);
+ $this->source[$i] = $src;
+ foreach($src->getTypes() as $elem) {
+ if(!is_array($this->alloc[$elem])) {
+ $this->alloc[$elem] = array();
+ }
+ //add to list
+ $this->alloc[$elem][$src->getPriority($elem)] = $i;
+ }
+ }
+
+ function getData($type,$field,$ident) {
+ return $this->getDataSource($type)->getData($type,$field,$ident);
+ }
+
+ private function getDataSource($type) {
+ //find the highest priority datasource for given type
+ if(!$this->alloc[$type]) {
+ return false; //unknown type
+ }
+ $pos = array_keys($this->alloc[$type]);
+ if(sizeof($pos) == 0) {
+ return false; //no datasource for type // should not happen since type is defined by datasource
+ }
+ return $this->alloc[$type][$pos[0]];
+ }
+ }
+?>
\ No newline at end of file
diff --git a/code/web/app/app_achievements/_AchWebParser/class/DataSource_abstract.php b/code/web/app/app_achievements/_AchWebParser/class/DataSource_abstract.php
new file mode 100644
index 000000000..4b5d64bf6
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/class/DataSource_abstract.php
@@ -0,0 +1,24 @@
+types;
+ }
+
+ function getPriority($type) {
+ return $this->priority[$type];
+ }
+
+ abstract function getData($type,$ident,$field = array());
+
+ abstract function writeData($type,$ident,$field = array(),$value = array());
+ }
+?>
\ No newline at end of file
diff --git a/code/web/app/app_achievements/_AchWebParser/class/mySQL_class.php b/code/web/app/app_achievements/_AchWebParser/class/mySQL_class.php
new file mode 100644
index 000000000..4202ffcd8
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/class/mySQL_class.php
@@ -0,0 +1,151 @@
+$elem) {
+ $in[$key] = mysql_real_escape_string(stripslashes($elem));
+ }
+ }
+ else {
+ $in = mysql_real_escape_string(stripslashes($in));
+ }
+ return $in;
+ }
+
+ function mySQL($err=false) {
+ $this->DBstats = array();
+ $this->DBc = false;
+ if($err === "DIE" || $err === "PRINT" || $err === "ALERT" || $err === "HIDE") {
+ $this->DBerror = $err;
+ }
+ else {
+ $this->DBerror = "HIDE";
+ }
+ $this->resetStats();
+ $this->cached = false;
+ }
+
+ function connect($ip,$user,$pass,$db=false) {
+ $this->DBc = mysql_pconnect($ip,$user,$pass) or $this->error(mysql_error());
+ if($db) {
+ $this->database($db);
+ }
+ $this->resetStats();
+ }
+
+ function database($db) {
+ mysql_select_db($db,$this->DBc) or $this->error(mysql_error());
+ }
+
+ function resetStats() {
+ $this->DBstats['query'] = 0;
+ $this->DBstats['error'] = 0;
+ }
+
+ function getStats() {
+ return $this->DBstats;
+ }
+
+ function sendSQL($query,$handling="PLAIN",$buffer=false) { // can be INSERT, DELETE, UPDATE, ARRAY, NONE, PLAIN
+ #if($this->cached !== false) {
+ #$this->unlinkSql($this->cached);
+ #}
+
+ if($buffer === false && $handling !== "PLAIN") {
+ $res = mysql_unbuffered_query($query,$this->DBc) or $this->error(mysql_error(),$query);
+ }
+ else {
+ $res = mysql_query($query,$this->DBc) or $this->error(mysql_error(),$query);
+ }
+
+ #$this->cached = $res;
+
+ $this->DBstats['query']++;
+
+ if($res) {
+ if($handling === "INSERT") {
+ $tmp = mysql_insert_id($this->DBc) or $this->error(mysql_error());;
+ $this->unlinkSql($res);
+ return $tmp;
+ }
+ elseif($handling === "DELETE" || $handling === "UPDATE") {
+ $tmp = mysql_affected_rows($this->DBc) or $this->error(mysql_error());
+ $this->unlinkSql($res);
+ return $tmp;
+ }
+ elseif($handling === "ARRAY") {
+ $tmp = $this->parseSql($res);
+ $this->unlinkSql($res);
+ return $tmp;
+ }
+ elseif($handling === "NONE") {
+ $this->unlinkSql($res);
+ return true;
+ }
+ else {
+ return $res;
+ }
+ mysql_free_result($res);
+ }
+ else {
+ return false;
+ }
+ }
+
+ function unlinkSql($res) {
+ @mysql_free_result($res);
+ }
+
+ private function parseSql($res) {
+ $data = array();
+ $k = 0;
+ while($tmp = mysql_fetch_array($res,MYSQL_ASSOC)) {
+ $data[$k] = $tmp;
+ $k++;
+ }
+
+ return $data;
+ }
+
+ function getNext($res) {
+ if($res) {
+ if($tmp = mysql_fetch_array($res,MYSQL_ASSOC)) {
+ return $tmp;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+ }
+
+ private function error($error,$query = false) {
+ $this->DBstats['error']++;
+
+ if($query != false) {
+ $error .= " -->|".$query."|<--";
+ }
+
+ switch($this->DBerror) {
+ case 'DIE':
+ die($error);
+ break;
+ case 'PRINT':
+ echo "
".$error."
";
+ break;
+ case 'ALERT':
+ echo "";
+ break;
+ default:
+ flush();
+ break;
+ }
+ }
+ }
+?>
\ No newline at end of file
diff --git a/code/web/app/app_achievements/_AchWebParser/include/functions_inc.php b/code/web/app/app_achievements/_AchWebParser/include/functions_inc.php
new file mode 100644
index 000000000..17e9a89ae
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/include/functions_inc.php
@@ -0,0 +1,19 @@
+ ".$txt;
+ }
+?>
\ No newline at end of file
diff --git a/code/web/app/app_achievements/_AchWebParser/source/ValueCache/ValueCache_class.php b/code/web/app/app_achievements/_AchWebParser/source/ValueCache/ValueCache_class.php
new file mode 100644
index 000000000..84c174124
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/source/ValueCache/ValueCache_class.php
@@ -0,0 +1,26 @@
+types[] = "c_cache";
+
+ $this->write = true;
+ }
+
+ function getData($type,$ident,$field) {
+
+ }
+
+ function writeData($type,$ident,$field = array(),$value = array()) {
+ global $DBc;
+
+ if($type == "c_cache") {
+ $DBc->sendSQL("INSERT INTO ach_player_valuecache () VALUES () ON DUPLICATE KEY UPDATE ");
+
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+?>
\ No newline at end of file
diff --git a/code/web/app/app_achievements/_AchWebParser/source/XMLapi/XMLapi_class.php b/code/web/app/app_achievements/_AchWebParser/source/XMLapi/XMLapi_class.php
new file mode 100644
index 000000000..6ae24a6ac
--- /dev/null
+++ b/code/web/app/app_achievements/_AchWebParser/source/XMLapi/XMLapi_class.php
@@ -0,0 +1,19 @@
+types[] = "c_stats";
+ $this->types[] = "c_items";
+
+ $this->write = false;
+ }
+
+ function getData() {
+
+ }
+
+ function writeData() {
+ return false;
+ }
+
+ }
+?>
\ No newline at end of file