module Database.Design.Ampersand.Prototype.StaticFiles_Generated where data StaticFile = SF { isNewFrontend :: Bool , filePath :: FilePath -- relative path, including extension , timeStamp :: Integer -- unix epoch time , contentString :: String } {-# NOINLINE allStaticFiles #-} allStaticFiles :: [StaticFile] allStaticFiles = [ SF False ".\\pluginsettings.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "" , SF False ".\\php\\ValidateEdit.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "\r\n" , SF False ".\\php\\testSpeed.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "" , SF False ".\\php\\plugins\\plugin_Warshall.php" 1429178701 {-2015-04-16 10:05:01 UTC -} " 1) // If we are not dealing with the first violation of a rule:\r\n { ExecEngineWhispers(\"Skipping TransitiveClosure($r,$C,$rCopy,$rStar)\");\r\n return; // this is the case if we have executed this function already in this transaction\r\n }\r\n \r\n // Compute transitive closure following Warshall's algorithm\r\n $closure = RetrievePopulation($r, $C); // get adjacency matrix\r\n OverwritePopulation($closure, $rCopy, $C); // store it in the 'rCopy' relation \r\n\r\n // Get all unique atoms from this population\r\n $atoms = array_keys($closure); // 'Src' (left) atoms of pairs in $closure \r\n foreach ($closure as $tgtAtomsList) // Loop to add 'Tgt' atoms that not yet exist\r\n { $tgtAtoms = array_keys($tgtAtomsList);\r\n foreach ($tgtAtoms as $tgtAtom)\r\n { if (!in_array($tgtAtom, $atoms)) \r\n { $atoms[] = $tgtAtom;\r\n } } }\r\n\r\n foreach ($atoms as $k)\r\n { foreach ($atoms as $i)\r\n { if ($closure[$i][$k])\r\n { foreach ($atoms as $j)\r\n { $closure[$i][$j] = $closure[$i][$j] || $closure[$k][$j];\r\n } } } }\r\n\r\n OverwritePopulation($closure, $rStar, $C);\r\n}\r\n\r\nfunction RetrievePopulation($relation, $concept)\r\n{ global $relationTableInfo; // For comments on this function see plugin_InsDelPairAtom.php\r\n global $tableColumnInfo;\r\n\r\n $found = false; // check if $relation appears in $relationTableInfo\r\n foreach($relationTableInfo as $key => $arr)\r\n { if($key == $relation && $arr['srcConcept'] == $concept && $arr['tgtConcept'] == $concept)\r\n { $found = true;\r\n $table = $arr['table'];\r\n $srcCol = $arr['srcCol'];\r\n $tgtCol = $arr['tgtCol'];\r\n }\r\n }\r\n if (!$found)\r\n { // Errors in ADL script may corrupt the database, so we die (leaving a suicide note)\r\n ExecEngineSHOUTS(\"ERROR in RetrievePopulation: Cannot find $relation\\[$concept\\*$concept\\] signature.\");\r\n ExecEngineSays(\"If you have defined this relation in Ampersand, then you must be sure to also have defined an INTERFACE that uses this relation (or else it does not show up in the PHP relation administration.\");\r\n die;\r\n }\r\n\r\n $tableEsc = escapeSQL($table);\r\n $query = \"SELECT * FROM $tableEsc\";\r\n $result = mysql_query($query);\r\n if (!$result) die ('Error: '.mysql_error());\r\n while($row = mysql_fetch_array($result, MYSQL_NUM))\r\n { $array[$row[0]][$row[1]] = true;\r\n }\r\n return (array) $array;\r\n}\r\n\r\n// Overwrite contents of &-relation $r with contents of php array $rArray\r\nfunction OverwritePopulation($rArray, $relation, $concept)\r\n{ global $relationTableInfo; // For comments on this function see plugin_InsDelPairAtom.php\r\n global $tableColumnInfo;\r\n\r\n $found = false; // check if $relation appears in $relationTableInfo\r\n foreach($relationTableInfo as $key => $arr)\r\n { if($key == $relation && $arr['srcConcept'] == $concept && $arr['tgtConcept'] == $concept)\r\n { $found = true;\r\n $table = $arr['table'];\r\n $srcCol = $arr['srcCol'];\r\n $tgtCol = $arr['tgtCol'];\r\n }\r\n }\r\n if (!$found)\r\n { // Errors in ADL script may corrupt the database, so we die (leaving a suicide note)\r\n ExecEngineSHOUTS(\"ERROR in OverwritePopulation: Cannot find $relation\\[$concept\\*$concept\\] signature.\");\r\n ExecEngineSays(\"If you have defined this relation in Ampersand, then you must be sure to also have defined an INTERFACE that uses this relation (or else it does not show up in the PHP relation administration.\");\r\n die;\r\n }\r\n\r\n $tableEsc = escapeSQL($table);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n \r\n $query = \"TRUNCATE TABLE $tableEsc\";\r\n DB_doquer($query);\r\n \r\n foreach($rArray as $src => $tgtArray)\r\n { foreach($tgtArray as $tgt => $bool)\r\n { if($bool)\r\n { $query = \"INSERT INTO $tableEsc (`$srcColEsc`, `$tgtColEsc`) VALUES ('$src','$tgt')\";\r\n DB_doquer($query);\r\n} } } } \r\n\r\n?>" , SF False ".\\php\\plugins\\plugin_SendSMS.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "setTest(true);' is (un)commented as to what behaviour you need.\r\n3) Make sure the library 'class.Messagebird.php' is available in the 'lib' directory.\r\n*/\r\n\r\nrequire_once __DIR__.'/lib/class.MessageBird.php';\r\n\r\nfunction SendSMS ($phonenumber,$message)\r\n{ \r\nglobal $SendSMS_Username;\r\nglobal $SendSMS_Password;\r\n\r\nExecEngineWhispers('Username = '.$SendSMS_Username);\r\n\r\n// Set the Messabeird username and password, and create an instance of the MessageBird class\r\n$sms = new MessageBird($SendSMS_Username, $SendSMS_Password);\r\n\r\n// Set the sender, could be a number (16 numbers) or letters (11 characters)\r\n$sms->setSender('AmProtoType');\r\n\r\n// Add the destination mobile number.\r\n// This method can be called several times to add have more then one recipient for the same message\r\n$sms->addDestination($phonenumber); //e.g. $sms->addDestination('31600000000');\r\n\r\n// Set an reference, optional\r\n// $sms->setReference('123456789');\r\n\r\n// Set a schedule date-time, optional\r\n// $sms->setTimestamp('2014-01-01 10:02');\r\n\r\n// Replace non GSM-7 characters by appropriate valid GSM-7 characters\r\n// $sms->setReplacechars(false);\r\n\r\n// If you want a dlr notification of the message send to another url then that you have set on the web site, you can use this parameter. Don't forget to set a reference!\r\n// $sms->setDlrUrl('http://www.example.com/dlr_url.php');\r\n\r\n// If $test is TRUE, then the message is not actually sent or scheduled, and there will be no credits deducted.\r\n// $sms->setTest(true);\r\n\r\n// Send the message to the destination(s)\r\n$sms->sendSms($message);\r\n\r\nExecEngineSays (\"Response:\");\r\nExecEngineSays ($sms->getResponseCode());\r\nExecEngineSays ($sms->getResponseMessage());\r\nExecEngineSays ($sms->getCreditBalance());\r\n}\r\n\r\n?>" , SF False ".\\php\\plugins\\plugin_SendEmail.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "IsSMTP(); // Set mailer to use SMTP\r\n// $mail->SMTPDebug = 1;\r\n$mail->Host = 'smtp.gmail.com'; // Specify main and backup server\r\n$mail->SMTPSecure = 'tls'; // Enable encryption, 'ssl' also accepted\r\n$mail->Port = 587;\r\n$mail->SMTPAuth = true; // Enable SMTP authentication\r\n\r\n$mail->Username = $SendEmail_Username; // SMTP username (for GMAIL)\r\n$mail->Password = $SendEmail_Password; // SMTP password\r\n\r\n$mail->From = $SendEmail_From; \r\n$mail->FromName = 'Ampersand Prototype';\r\n\r\n$mail->AddAddress($to); // Add a recipient, e.g. $to = 'rieks.joosten@tno.nl', 'Rieks Joosten'\r\n$mail->Subject = $subject;\r\n$mail->Body = $message;\r\n\r\n$mail->WordWrap = 50; // Set word wrap to 50 characters\r\n\r\n if(!$mail->Send())\r\n { ExecEngineSays('Message could not be sent.');\r\n ExecEngineSays('Mailer Error: ' . $mail->ErrorInfo);\r\n } else\r\n { ExecEngineSays('Email message sent.');\r\n }\r\n}\r\n\r\n?>" , SF False ".\\php\\plugins\\plugin_InsDelPairAtom.php" 1429178701 {-2015-04-16 10:05:01 UTC -} ";\r\n throw new Exception(\"identification string of the exception\");\r\n ; \r\n }\r\n catch (Exception $e)\r\n { ;\r\n ;\r\n }\r\n*/\r\n\r\n/*\r\n Example of rule that automatically inserts pairs into a relation (analogous stuff holds for DelPair):\r\n ROLE ExecEngine MAINTAINS \"New Customers\"\r\n RULE \"New Customers\": customerOrder[Person*Order];companyOrder[Company*Order]~ |- customerOf[Person*Company]\r\n MEANING \"If a person places an order at a company, the person is a customer of that company\"\r\n VIOLATION (TXT \"{EX} InsPair;customerOf;Person;\", SRC I, TXT\";Company;\", TGT I)\r\n*/\r\n// Use: VIOLATION (TXT \"{EX} InsPair;;;;;\")\r\nfunction InsPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom)\r\n{ /* \r\n $relationTableInfo from Generics.php \r\n contains array with all relations, for each relation the following is specified: \r\n - srcConcept : srcConcept of relation\r\n - tgtConcept : tgtConcept of relation\r\n - table : database table in which the relation is populated\r\n - srcCol : column of database table in which the srcConcept is placed\r\n - tgtCol : column of database table in which the tgtConcept is placed\r\n */\r\n global $relationTableInfo;\r\n /* \r\n $tableColumInfo from Generics.php \r\n contains array with all database tables and their columns, for each tablecolumn the following is specified: \r\n - concept : the atoms of which concept are set here\r\n - unique : whether or not the value in the column must be unique. 'true' for properties\r\n - null : whether or not the value in the column can be NULL. in case of UNI relations\r\n */\r\n global $tableColumnInfo;\r\n// check if $relation appears in $relationTableInfo\r\n $found = false;\r\n foreach($relationTableInfo as $key => $arr)\r\n { if($key == \"rel_\" . $relation . \"_\" . $srcConcept . \"_\" . $tgtConcept)\r\n { $found = true;\r\n $table = $arr['table'];\r\n $srcCol = $arr['srcCol'];\r\n $tgtCol = $arr['tgtCol'];\r\n }\r\n }\r\n if (!$found)\r\n { // Errors in ADL script may corrupt the database, so we die (leaving a suicide note)\r\n ExecEngineSHOUTS(\"ERROR: Cannot find $relation\\[$srcConcept\\*$tgtConcept\\] signature.\");\r\n ExecEngineSays(\"InsPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom)\");\r\n ExecEngineSays(\"If you have defined this relation in Ampersand, then you must be sure to also have defined an INTERFACE that uses this relation (or else it does not show up in the PHP relation administration.\");\r\n die;\r\n }\r\n// if srcAtom is specified as NULL, a new atom of srcConcept is created\r\n if ($srcAtom === \"\") ExecEngineSHOUTS(\"InsPair: srcAtom is empty string.\");\r\n if ($srcAtom === \"NULL\") \r\n { $srcAtom = InsAtom($srcConcept);\r\n } \r\n// if tgtAtom is specified as NULL, a new atom of tgtConcept is created\r\n if ($tgtAtom === \"\") ExecEngineSHOUTS(\"InsPair: tgtAtom is empty string.\");\r\n if ($tgtAtom === \"NULL\") \r\n { $tgtAtom = InsAtom($tgtConcept);\r\n }\r\n \r\n if(!isAtomInConcept($srcAtom, $srcConcept))\r\n { addAtomToConcept($srcAtom, $srcConcept);\r\n }\r\n \r\n if(!isAtomInConcept($tgtAtom, $tgtConcept))\r\n { addAtomToConcept($tgtAtom, $tgtConcept);\r\n }\r\n// get table column properties for $srcCol and $tgtCol\r\n $srcColUnique = $tableColumnInfo[$table][$srcCol]['unique'];\r\n $srcColNull = $tableColumnInfo[$table][$srcCol]['null'];\r\n $tgtColUnique = $tableColumnInfo[$table][$tgtCol]['unique'];\r\n $tgtColNull = $tableColumnInfo[$table][$tgtCol]['null'];\r\n// SQL escape table, column and atom names\r\n $tableEsc = escapeSQL($table);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n $srcAtomEsc = escapeSQL($srcAtom);\r\n $tgtAtomEsc = escapeSQL($tgtAtom);\r\n// generate database query\r\n if($srcColUnique || $tgtColUnique) // srcCol, tgtCol or both are unique ==> update query\r\n { if($srcColUnique)\r\n { $query = \"UPDATE `$tableEsc` SET `$srcColEsc`='$srcAtomEsc', `$tgtColEsc`='$tgtAtomEsc' WHERE `$srcColEsc`='$srcAtomEsc'\";\r\n if ($srcConcept == $tgtConcept)\r\n { queryDb($query);\r\n $query = \"INSERT IGNORE INTO `$tableEsc` SET `$srcColEsc` = '$tgtAtomEsc'\";\r\n }\r\n ExecEngineWhispers (\"Update $relation($srcConcept*$tgtConcept) with ($srcAtom,$tgtAtom)\");\r\n }else\r\n { $query = \"UPDATE `$tableEsc` SET `$srcColEsc`='$srcAtomEsc', `$tgtColEsc`='$tgtAtomEsc' WHERE `$tgtColEsc`='$tgtAtomEsc'\";\r\n if ($srcConcept == $tgtConcept)\r\n { queryDb($query);\r\n $query = \"INSERT IGNORE INTO `$tableEsc` SET `$tgtColEsc` = '$srcAtomEsc'\";\r\n }\r\n ExecEngineWhispers (\"Update $relation($srcConcept*$tgtConcept) with ($srcAtom,$tgtAtom)\");\r\n }\r\n }else\r\n { // neither srcCol nor tgtCol is unique ==> insert query\r\n $query = \"INSERT INTO `$tableEsc` (`$srcColEsc`, `$tgtColEsc`) VALUES ('$srcAtomEsc', '$tgtAtomEsc')\";\r\n ExecEngineWhispers (\"INSERT $relation($srcConcept*$tgtConcept) with ($srcAtom,$tgtAtom)\");\r\n }\r\n/* Trying to implement 'on duplicate key update' (doesn't seem to work like this...)\r\n$updatequery = '';\r\nif ($tgtColUnique) $updatequery = \"ON DUPLICATE KEY UPDATE `$srcColEsc`='$srcAtomEsc', `$tgtColEsc`='$tgtAtomEsc'\";// WHERE `$tgtColEsc`='$tgtAtomEsc'\";\r\nif ($srcColUnique) $updatequery = \"ON DUPLICATE KEY UPDATE `$srcColEsc`='$srcAtomEsc', `$tgtColEsc`='$tgtAtomEsc'\";// WHERE `$srcColEsc`='$srcAtomEsc'\";\r\n$query = \"INSERT INTO `$tableEsc` (`$srcColEsc`, `$tgtColEsc`) VALUES ('$srcAtomEsc', '$tgtAtomEsc') \" . $updatequery;\r\n*/ \r\n// execute database query\r\n queryDb($query); \r\n// log\r\n emitLog (\"InsPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom)\");\r\n emitLog ($query);\r\n}\r\n\r\n/*\r\nExample of a rule that automatically deletes pairs from a relation:\r\n ROLE ExecEngine MAINTAINS \"Remove Customers\"\r\n RULE \"Remove Customers\": customerOf[Person*Company] |- customerOrder[Person*Order];companyOrder[Company*Order]~\r\n MEANING \"Customers of a company for which no orders exist (any more), are no longer considered customers\"\r\n VIOLATION (TXT \"{EX} DelPair;customerOf;Person;\", SRC I, TXT\";Company;\", TGT I)\r\n*/\r\n// Use: VIOLATION (TXT \"{EX} DelPair;;;;;\")\r\nfunction DelPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom)\r\n{ if ($srcAtom === \"\") ExecEngineSHOUTS(\"DelPair: srcAtom is empty string.\");\r\n if ($srcAtom === \"\") ExecEngineSHOUTS(\"DelPair: tgtAtom is empty string.\");\r\n /* \r\n $relationTableInfo from Generics.php \r\n contains array with all relations, for each relation the following is specified: \r\n - srcConcept : srcConcept of relation\r\n - tgtConcept : tgtConcept of relation\r\n - table : database table in which the relation is populated\r\n - srcCol : column of database table in which the srcConcept is placed\r\n - tgtCol : column of database table in which the tgtConcept is placed\r\n */\r\n global $relationTableInfo;\r\n /* \r\n $tableColumInfo from Generics.php \r\n contains array with all database tables and their columns, for each tablecolumn the following is specified: \r\n - concept : the atoms of which concept are set here\r\n - unique : whether or not the value in the column must be unique. 'true' for properties\r\n - null : whether or not the value in the column can be NULL. in case of UNI relations\r\n */\r\n global $tableColumnInfo;\r\n // check if $relation appears in $relationTableInfo\r\n $found = false;\r\n foreach($relationTableInfo as $key => $arr)\r\n { if($key == \"rel_\" . $relation . \"_\" . $srcConcept . \"_\" . $tgtConcept)\r\n { $found = true;\r\n $table = $arr['table'];\r\n $srcCol = $arr['srcCol'];\r\n $tgtCol = $arr['tgtCol'];\r\n }\r\n }\r\n if (!$found)\r\n { // Errors in ADL script may corrupt the database, so we die (leaving a suicide note)\r\n ExecEngineSHOUTS(\"ERROR: Cannot find $relation\\[$srcConcept\\*$tgtConcept\\] signature.\");\r\n ExecEngineSays(\"DelPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom)\");\r\n ExecEngineSays(\"If you have defined this relation in Ampersand, then you must be sure to also have defined an INTERFACE that uses this relation (or else it does not show up in the PHP relation administration.\");\r\n die;\r\n }\r\n// get table column properties for $srcCol and $tgtCol\r\n $srcColUnique = $tableColumnInfo[$table][$srcCol]['unique'];\r\n $srcColNull = $tableColumnInfo[$table][$srcCol]['null'];\r\n $tgtColUnique = $tableColumnInfo[$table][$tgtCol]['unique'];\r\n $tgtColNull = $tableColumnInfo[$table][$tgtCol]['null'];\r\n// SQL escape table, column and atom names\r\n $tableEsc = escapeSQL($table);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n $srcAtomEsc = escapeSQL($srcAtom);\r\n $tgtAtomEsc = escapeSQL($tgtAtom);\r\n// generate database query\r\n if($srcColNull xor $tgtColNull) // srcCol xor tgtCol can be null ==> update query\r\n { if($srcColNull)\r\n { $query = \"UPDATE `$tableEsc` SET `$srcColEsc`=NULL WHERE `$srcColEsc`='$srcAtomEsc' AND `$tgtColEsc`='$tgtAtomEsc'\";\r\n }else\r\n { $query = \"UPDATE `$tableEsc` SET `$tgtColEsc`=NULL WHERE `$srcColEsc`='$srcAtomEsc' AND `$tgtColEsc`='$tgtAtomEsc'\";\r\n }\r\n }elseif($srcColNull and $tgtColNull) // both srcCol and tgtCol can be null ==> delete query -- REMARK: maybe this should be an update instead of delete query\r\n { $query = \"DELETE FROM `$tableEsc` WHERE `$srcColEsc`='$srcAtomEsc' AND `$tgtColEsc`='$tgtAtomEsc';\";\r\n }else\r\n { // neither srcCol nor tgtCol can be null ==> delete query\r\n $query = \"DELETE FROM `$tableEsc` WHERE `$srcColEsc`='$srcAtomEsc' AND `$tgtColEsc`='$tgtAtomEsc';\";\r\n }\r\n// execute database query\r\n queryDb($query); \r\n// log\r\n ExecEngineWhispers(\"Delete pair ($srcAtom,$tgtAtom) from $relation($srcConcept*$tgtConcept)\");\r\n emitLog (\"DelPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom)\");\r\n emitLog ($query);\r\n}\r\n\r\n/* The function 'NewStruct' creates a new atom in some concept and uses this\r\n atom to create two links (in relations in which the concept is SRC or TGT).\r\n\r\n Example:\r\n \r\n r :: ConceptA * ConceptB\r\n r1 :: ConceptA * ConceptC [INJ] -- multiplicity must be there (I think...)\r\n r2 :: ConceptC * ConceptB [UNI] -- multiplicity must be there (I think...)\r\n \r\n RULE \"equivalence\": r = r1;r2 -- this rule is to be maintained automatically\r\n \r\n ROLE ExecEngine MAINTAINS \"insEquivalence\" -- Creation of the atom\r\n RULE \"insEquivalence\": r |- r1;r2\r\n VIOLATION (TXT \"{EX} NewStruct;ConceptC\" -- atom generated automatically (with time stamp)\r\n ,TXT \";r1;ConceptA;\", SRC I, TXT\";ConceptC;NULL\" -- Always use NULL as ConceptC atom\r\n ,TXT \";r2;ConceptC;NULL;ConceptB;atomB;\", TGT I -- Always use NULL as ConceptC atom\r\n )\r\nAlternatively, the following construct should also work:\r\n VIOLATION (TXT \"{EX} NewStruct;ConceptC;\" SRC I -- atom generated using specified text\r\n ,TXT \";r1;ConceptA;\", SRC I, TXT\";ConceptC;NULL\" -- Always use NULL as ConceptC atom\r\n ,TXT \";r2;ConceptC;NULL;ConceptB;atomB;\", TGT I -- Always use NULL as ConceptC atom\r\n )\r\n\r\n ROLE ExecEngine MAINTAINS \"delEquivalence\" -- Deletion of the atom\r\n RULE \"delEquivalence\": I[ConceptC] |- r1~;r;r2~ \r\n VIOLATION (TXT \"{EX} DelAtom;ConceptC;\" SRC I) -- all links in other relations in which the atom occurs are deleted as well.\r\n*/\r\n\r\nfunction NewStruct() // arglist: ($ConceptC[,$newAtom][,$relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom]+)\r\n{ \r\n// We start with parsing the first one or two arguments\r\n $ConceptC = func_get_arg(0); // Name of concept for which atom is to be created\r\n $AtomC = mkUniqueAtomByTime($ConceptC); // Default marker for atom-to-be-created.\r\n if (func_num_args() % 5 == 2) // Check if name of new atom is explicitly specified\r\n { $AtomC = func_get_arg(1); // If so, we'll be using this to create the new atom\r\n } elseif (func_num_args() % 5 != 1) // check for valid number of arguments\r\n { ExecEngineSHOUTS(\"NewStruct: Illegal number of arguments: \".func_num_args());\r\n die;\r\n }\r\n// Then, we create a new atom of type $ConceptC\r\n ExecEngineWhispers (\"Creating a structure based on an atom '$AtomC' for concept '$ConceptC'\");\r\n addAtomToConcept($AtomC, $ConceptC); // insert new atom in database\r\n\r\n// Next, for every relation that follows in the argument list, we create a link\r\n for ($i = func_num_args() % 5; $i < func_num_args(); $i = $i+5)\r\n { emitLog (\"i = $i\");\r\n $relation = func_get_arg($i);\r\n $srcConcept = func_get_arg($i+1);\r\n $srcAtom = func_get_arg($i+2);\r\n $tgtConcept = func_get_arg($i+3);\r\n $tgtAtom = func_get_arg($i+4);\r\n// populate relation r1, first checking for allowed syntax:\r\n if (!($srcAtom === 'NULL' or $tgtAtom === 'NULL')) // Note: when populating a [PROP] relation, both atoms can be NULL\r\n { ExecEngineSHOUTS(\"NewStruct: relation $relation requires that atom $srcAtom or $tgtAtom must be NULL\");\r\n throw new Exception(\"Failure 1 in NewStruct in InsDelPairAtom.php\");\r\n }\r\n if (!($srcConcept == $ConceptC or $tgtConcept == $ConceptC)) // Note: when populating a [PROP] relation, both atoms can be NULL\r\n { ExecEngineSHOUTS(\"NewStruct: relation $relation requires that concept $srcConcept or $tgtConcept must be $ConceptC\");\r\n throw new Exception(\"Failure 2 in NewStruct in InsDelPairAtom.php\");\r\n }\r\n if ($srcConcept == $ConceptC)\r\n { if ($srcAtom === 'NULL')\r\n { $srcAtom = $AtomC;\r\n } else // While it strictly not necessary to err here, for most cases this helps to find errors in the ADL script\r\n { ExecEngineSHOUTS (\"NewStruct: $srcAtom must be NULL when $ConceptC is the concept (in relation $relation)\");\r\n throw new Exception(\"Failure 3 in NewStruct in InsDelPairAtom.php\");\r\n }\r\n }\r\n if ($tgtConcept == $ConceptC)\r\n { if ($tgtAtom === 'NULL')\r\n { $tgtAtom = $AtomC;\r\n } else // While it strictly not necessary to err here, for most cases this helps to find errors in the ADL script\r\n { ExecEngineSHOUTS (\"NewStruct: $tgtAtom must be NULL when $ConceptC is the concept (in relation $relation)\");\r\n \t throw new Exception(\"Failure 4 in NewStruct in InsDelPairAtom.php\");\r\n }\r\n }\r\n/* Als '$tgtAtom' nog niet in de database bestaat als een instantie van $tgtConcept, dan moet die nog wel worden toegevoegd; dat gebeurt bijvoorbeeld als '$tgtAtom' ontstaat uit de volgende ADL tekst: \r\nVIOLATION (TXT \"{EX} NewStruct;Beslissing\"\r\n ,TXT \";op;Beslissing;NULL;Verzoek;\", SRC I \r\n ...\r\n ,TXT \";reden;Beslissing;NULL;Reden;'Voldoen aan artikel 2 lid 10 Wet aanpassing arbeidsduur'\"\r\n ... -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deze tekst moet als een instantie van het concept 'Reden' worden toegevoegd (als-ie nog niet als een Reden bestaat).\r\n )\r\n*/\r\n if(!isAtomInConcept($tgtAtom, $tgtConcept))\r\n { addAtomToConcept($tgtAtom, $tgtConcept);\r\n }\r\n// Any logging is done by InsPair:\r\n InsPair($relation,$srcConcept,$srcAtom,$tgtConcept,$tgtAtom);\r\n }\r\n ExecEngineWhispers (\"Completed structure creation.\");\r\n}\r\n\r\n// Use: VIOLATION (TXT \"{EX} InsAtom;\") -- this may not be of any use in Ampersand, though.\r\nfunction InsAtom($concept)\r\n{ // call function from DatabaseUtils.php\r\n $atom = mkUniqueAtomByTime($concept); // create new atom name \r\n addAtomToConcept($atom, $concept); // insert new atom in databse\r\n// log\r\n ExecEngineWhispers(\"New atom $atom ($concept) created\");\r\n emitLog(\"addAtomToConcept($atom, $concept)\");\r\n// return created atom identifier\r\n return $atom;\r\n}\r\n\r\n// Use: VIOLATION (TXT \"{EX} DelAtom;;\")\r\nfunction DelAtom($concept, $atom)\r\n{ // call function from DatabaseUtils.php\r\n deleteAtom($atom, $concept); // delete atom + all relations with other atoms\r\n// log\r\n ExecEngineWhispers(\"Atom $atom ($concept) deleted\");\r\n emitLog(\"deleteAtom($atom, $concept)\");\r\n}\r\n\r\n?>\r\n" , SF False ".\\php\\plugins\\plugin_DateTime.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "format($formatSpec));\r\n return;\r\n}\r\n/* (Example taken from EURent):\r\nVIOLATION (TXT \"{EX} DateDifferencePlusOne\" -- Result = 1 + MAX(0, (RentalEndDate - RentalStartDate))\r\n , TXT \";computedRentalPeriod;DateDifferencePlusOne;\", SRC I, TXT \";Integer\"\r\n , TXT \";\", SRC earliestDate -- = Rental start date\r\n , TXT \";\", SRC latestDate -- = Rental end date\r\n )\r\n*/\r\nfunction DateDifferencePlusOne($relation,$srcConcept,$srcAtom,$integerConcept,$earliestDate,$latestDate)\r\n{ emitLog(\"DateDifferencePlusOne($relation,$srcConcept,$srcAtom,$integerConcept,$earliestDate,$latestDate)\");\r\n $datediff = strtotime($latestDate) - strtotime($earliestDate);\r\n $result = 1 + max(0, floor($datediff/(60*60*24)));\r\n $result = strval($result); // Writing a '0' (integer) results in an empty string.\r\n InsPair($relation,$srcConcept,$srcAtom,$integerConcept,$result);\r\n return;\r\n}\r\n/* (Example taken from EURent):\r\nVIOLATION (TXT \"{EX} DateDifference\"\r\n , TXT \";compExcessPeriod;DateDifference;\", SRC I, TXT \";Integer\"\r\n , TXT \";\", SRC firstDate\r\n , TXT \";\", SRC lastDate\r\n )\r\n*/\r\nfunction DateDifference($relation,$srcConcept,$srcAtom,$integerConcept,$firstDate,$lastDate)\r\n{ emitLog(\"DateDifference($relation,$srcConcept,$srcAtom,$integerConcept,$firstDate,$lastDate)\");\r\n $datediff = strtotime($lastDate) - strtotime($firstDate);\r\n $result = max(0, floor($datediff/(60*60*24)));\r\n $result = strval($result); // Writing a '0' (integer) results in an empty string.\r\n InsPair($relation,$srcConcept,$srcAtom,$integerConcept,$result);\r\n return;\r\n}\r\n/* COMPARING DATES AND TIMES (used e.g. in Arbeidsduur)\r\n Whenever you need to compare dates/times, you must define your own relation(s) for that, and consequently also a concept for the date/time.\r\n The functions provided in this file allow you to fill such relations.\r\n\r\n>> EXAMPLES OF USE:\r\n stdDateTime :: DateTime * DateTimeStdFormat [UNI] PRAGMA \"Standard output format for \" \" is \" \r\n\r\n ROLE ExecEngine MAINTAINS \"compute DateTime std values\"\r\n RULE \"compute DateTime std values\": I[DateTime] |- stdDateTime;stdDateTime~\r\n VIOLATION (TXT \"{EX} datimeStdFormat;stdDateTime;DateTime;\", SRC I, TXT \";DateTimeStdFormat;Y-m-d\") -- The text 'Y-m-d' may be replaced by any other format specification, see the 'Parameters' section on http://www.php.net/manual/en/function.date.php\r\n\r\n eqlDateTime :: DateTime * DateTime PRAGMA \"\" \" occurred simultaneously \"\r\n neqDateTime :: DateTime * DateTime PRAGMA \"\" \" occurred either before or after \"\r\n ltDateTime :: DateTime * DateTime PRAGMA \"\" \" has occurred before \"\r\n gtDateTime :: DateTime * DateTime PRAGMA \"\" \" has occurred after \"\r\n \r\n ROLE ExecEngine MAINTAINS \"compute DateTime comparison relations\"\r\n RULE \"compute DateTime comparison relations\": V[DateTime] |- eqlDateTime \\/ neqDateTime\r\n VIOLATION (TXT \"{EX} datimeEQL;eqlDateTime;DateTime;\", SRC I, TXT \";\", TGT I\r\n ,TXT \"{EX} datimeNEQ;neqDateTime;DateTime;\", SRC I, TXT \";\", TGT I\r\n ,TXT \"{EX} datimeLT;ltDateTime;DateTime;\", SRC I, TXT \";\", TGT I\r\n ,TXT \"{EX} datimeGT;gtDateTime;DateTime;\", SRC I, TXT \";\", TGT I\r\n )\r\n \r\n>> LIMITATIONS OF USE:\r\n If you use many atoms in DateTime, this will take increasingly more time\r\n to check for violations. So do not use that many...\r\n*/\r\n// VIOLATION (TXT \"{EX} datimeEQL;DateTime;\" SRC I, TXT \";\", TGT I)\r\nfunction datimeEQL($eqlRelation,$DateConcept,$srcAtom,$tgtAtom)\r\n{ \temitLog(\"datimeEQL($eqlRelation,$DateConcept,$srcAtom,$tgtAtom)\");\r\n if (($dt1 = strtotime($srcAtom)) === false) ExecEngineSHOUTS(\"datimeEQL: Illegal date $dt1 specified in srcAtom (3rd arg): $srcAtom\");\r\n if (($dt2 = strtotime($tgtAtom)) === false) ExecEngineSHOUTS(\"datimeEQL: Illegal date $dt2 specified in tgtAtom (4th arg): $tgtAtom\");\r\n global $execEngineWhispers; // Defined in 'pluginsettings.php'\r\n $execEngineWhispers=false;\r\n if ($dt1 == $dt2) \r\n { InsPair($eqlRelation,$DateConcept,$srcAtom,$DateConcept,$tgtAtom);\r\n// Accommodate for different representations of the same time:\r\n if ($srcAtom != $tgtAtom)\r\n { InsPair($eqlRelation,$DateConcept,$tgtAtom,$DateConcept,$srcAtom);\r\n } }\r\n return;\r\n}\r\n// VIOLATION (TXT \"{EX} datimeNEQ;DateTime;\" SRC I, TXT \";\", TGT I)\r\nfunction datimeNEQ($neqRelation,$DateConcept,$srcAtom,$tgtAtom)\r\n{ \temitLog(\"datimeNEQ($neqRelation,$DateConcept,$srcAtom,$tgtAtom)\");\r\n if (($dt1 = strtotime($srcAtom)) === false) ExecEngineSHOUTS(\"datimeNEQ: Illegal date $dt1 specified in srcAtom (3rd arg): $srcAtom\");\r\n if (($dt2 = strtotime($tgtAtom)) === false) ExecEngineSHOUTS(\"datimeNEQ: Illegal date $dt2 specified in tgtAtom (4th arg): $tgtAtom\");\r\n global $execEngineWhispers; // Defined in 'pluginsettings.php'\r\n $execEngineWhispers=false;\r\n if ($dt1 != $dt2) \r\n { InsPair($neqRelation,$DateConcept,$srcAtom,$DateConcept,$tgtAtom);\r\n InsPair($neqRelation,$DateConcept,$tgtAtom,$DateConcept,$srcAtom);\r\n }\r\n return;\r\n}\r\n\r\n// VIOLATION (TXT \"{EX} datimeLT;DateTime;\" SRC I, TXT \";\", TGT I)\r\nfunction datimeLT($ltRelation,$DateConcept,$srcAtom,$tgtAtom)\r\n{ \temitLog(\"datimeLT($ltRelation,$DateConcept,$srcAtom,$tgtAtom)\");\r\n if (($dt1 = strtotime($srcAtom)) === false) ExecEngineSHOUTS(\"datimeLT: Illegal date $dt1 specified in srcAtom (3rd arg): $srcAtom\");\r\n if (($dt2 = strtotime($tgtAtom)) === false) ExecEngineSHOUTS(\"datimeLT: Illegal date $dt2 specified in tgtAtom (4th arg): $tgtAtom\");\r\n if ($dt1 == $dt2) return;\r\n global $execEngineWhispers; // Defined in 'pluginsettings.php'\r\n $execEngineWhispers=false;\r\n if ($dt1 < $dt2)\r\n { InsPair($ltRelation,$DateConcept,$srcAtom,$DateConcept,$tgtAtom);\r\n } else\r\n { InsPair($ltRelation,$DateConcept,$tgtAtom,$DateConcept,$srcAtom);\r\n }\r\n return;\r\n}\r\n\r\n// VIOLATION (TXT \"{EX} datimeGT;DateTime;\" SRC I, TXT \";\", TGT I)\r\nfunction datimeGT($gtRelation,$DateConcept,$srcAtom,$tgtAtom)\r\n{ \temitLog(\"datimeGT($gtRelation,$DateConcept,$srcAtom,$tgtAtom)\");\r\n if (($dt1 = strtotime($srcAtom)) === false) ExecEngineSHOUTS(\"datimeGT: Illegal date $dt1 specified in srcAtom (3rd arg): $srcAtom\");\r\n if (($dt2 = strtotime($tgtAtom)) === false) ExecEngineSHOUTS(\"datimeGT: Illegal date $dt2 specified in tgtAtom (4th arg): $tgtAtom\");\r\n if ($dt1 == $dt2) return;\r\n global $execEngineWhispers; // Defined in 'pluginsettings.php'\r\n $execEngineWhispers=false;\r\n if ($dt1 > $dt2)\r\n { InsPair($gtRelation,$DateConcept,$srcAtom,$DateConcept,$tgtAtom);\r\n } else\r\n { InsPair($gtRelation,$DateConcept,$tgtAtom,$DateConcept,$srcAtom);\r\n }\r\n return;\r\n}\r\n\r\n?>" , SF False ".\\php\\plugins\\lib\\class.smtp.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "Debugoutput) {\r\n case 'error_log':\r\n error_log($str);\r\n break;\r\n case 'html':\r\n //Cleans up output a bit for a better looking display that's HTML-safe\r\n echo htmlentities(preg_replace('/[\\r\\n]+/', '', $str), ENT_QUOTES, 'UTF-8').\"
\\n\";\r\n break;\r\n case 'echo':\r\n default:\r\n //Just echoes exactly what was received\r\n echo $str;\r\n }\r\n }\r\n\r\n /**\r\n * Initialize the class so that the data is in a known state.\r\n * @access public\r\n * @return SMTP\r\n */\r\n public function __construct() {\r\n $this->smtp_conn = 0;\r\n $this->error = null;\r\n $this->helo_rply = null;\r\n\r\n $this->do_debug = 0;\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // CONNECTION FUNCTIONS\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Connect to an SMTP server\r\n *\r\n * SMTP CODE SUCCESS: 220\r\n * SMTP CODE FAILURE: 421\r\n * @access public\r\n * @param string $host SMTP server IP or host name\r\n * @param int $port The port number to connect to, or use the default port if not specified\r\n * @param int $timeout How long to wait for the connection to open\r\n * @param array $options An array of options compatible with stream_context_create()\r\n * @return bool\r\n */\r\n public function Connect($host, $port = 0, $timeout = 30, $options = array()) {\r\n // Clear errors to avoid confusion\r\n $this->error = null;\r\n\r\n // Make sure we are __not__ connected\r\n if($this->connected()) {\r\n // Already connected, generate error\r\n $this->error = array('error' => 'Already connected to a server');\r\n return false;\r\n }\r\n\r\n if(empty($port)) {\r\n $port = $this->SMTP_PORT;\r\n }\r\n\r\n // Connect to the SMTP server\r\n $errno = 0;\r\n $errstr = '';\r\n $socket_context = stream_context_create($options);\r\n //Need to suppress errors here as connection failures can be handled at a higher level\r\n $this->smtp_conn = @stream_socket_client($host.\":\".$port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $socket_context);\r\n\r\n // Verify we connected properly\r\n if(empty($this->smtp_conn)) {\r\n $this->error = array('error' => 'Failed to connect to server',\r\n 'errno' => $errno,\r\n 'errstr' => $errstr);\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . \": $errstr ($errno)\");\r\n }\r\n return false;\r\n }\r\n\r\n // SMTP server can take longer to respond, give longer timeout for first read\r\n // Windows does not have support for this timeout function\r\n if(substr(PHP_OS, 0, 3) != 'WIN') {\r\n $max = ini_get('max_execution_time');\r\n if ($max != 0 && $timeout > $max) { // Don't bother if unlimited\r\n @set_time_limit($timeout);\r\n }\r\n stream_set_timeout($this->smtp_conn, $timeout, 0);\r\n }\r\n\r\n // get any announcement\r\n $announce = $this->get_lines();\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $announce);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Initiate a TLS communication with the server.\r\n *\r\n * SMTP CODE 220 Ready to start TLS\r\n * SMTP CODE 501 Syntax error (no parameters allowed)\r\n * SMTP CODE 454 TLS not available due to temporary reason\r\n * @access public\r\n * @return bool success\r\n */\r\n public function StartTLS() {\r\n $this->error = null; # to avoid confusion\r\n\r\n if(!$this->connected()) {\r\n $this->error = array('error' => 'Called StartTLS() without being connected');\r\n return false;\r\n }\r\n\r\n $this->client_send('STARTTLS' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 220) {\r\n $this->error =\r\n array('error' => 'STARTTLS not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n // Begin encrypted connection\r\n if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Performs SMTP authentication. Must be run after running the\r\n * Hello() method. Returns true if successfully authenticated.\r\n * @access public\r\n * @param string $username\r\n * @param string $password\r\n * @param string $authtype\r\n * @param string $realm\r\n * @param string $workstation\r\n * @return bool\r\n */\r\n public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') {\r\n if (empty($authtype)) {\r\n $authtype = 'LOGIN';\r\n }\r\n\r\n switch ($authtype) {\r\n case 'PLAIN':\r\n // Start authentication\r\n $this->client_send('AUTH PLAIN' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 334) {\r\n $this->error =\r\n array('error' => 'AUTH not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n // Send encoded username and password\r\n $this->client_send(base64_encode(\"\\0\".$username.\"\\0\".$password) . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 235) {\r\n $this->error =\r\n array('error' => 'Authentication not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n break;\r\n case 'LOGIN':\r\n // Start authentication\r\n $this->client_send('AUTH LOGIN' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 334) {\r\n $this->error =\r\n array('error' => 'AUTH not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n // Send encoded username\r\n $this->client_send(base64_encode($username) . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 334) {\r\n $this->error =\r\n array('error' => 'Username not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n // Send encoded password\r\n $this->client_send(base64_encode($password) . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 235) {\r\n $this->error =\r\n array('error' => 'Password not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n break;\r\n case 'NTLM':\r\n /*\r\n * ntlm_sasl_client.php\r\n ** Bundled with Permission\r\n **\r\n ** How to telnet in windows: http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx\r\n ** PROTOCOL Documentation http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication\r\n */\r\n require_once 'extras/ntlm_sasl_client.php';\r\n $temp = new stdClass();\r\n $ntlm_client = new ntlm_sasl_client_class;\r\n if(! $ntlm_client->Initialize($temp)){//let's test if every function its available\r\n $this->error = array('error' => $temp->error);\r\n if($this->do_debug >= 1) {\r\n $this->edebug('You need to enable some modules in your php.ini file: ' . $this->error['error']);\r\n }\r\n return false;\r\n }\r\n $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1\r\n\r\n $this->client_send('AUTH NTLM ' . base64_encode($msg1) . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 334) {\r\n $this->error =\r\n array('error' => 'AUTH not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n $challenge = substr($rply, 3);//though 0 based, there is a white space after the 3 digit number....//msg2\r\n $challenge = base64_decode($challenge);\r\n $ntlm_res = $ntlm_client->NTLMResponse(substr($challenge, 24, 8), $password);\r\n $msg3 = $ntlm_client->TypeMsg3($ntlm_res, $username, $realm, $workstation);//msg3\r\n // Send encoded username\r\n $this->client_send(base64_encode($msg3) . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 235) {\r\n $this->error =\r\n array('error' => 'Could not authenticate',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n break;\r\n case 'CRAM-MD5':\r\n // Start authentication\r\n $this->client_send('AUTH CRAM-MD5' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 334) {\r\n $this->error =\r\n array('error' => 'AUTH not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n // Get the challenge\r\n $challenge = base64_decode(substr($rply, 4));\r\n\r\n // Build the response\r\n $response = $username . ' ' . $this->hmac($challenge, $password);\r\n\r\n // Send encoded credentials\r\n $this->client_send(base64_encode($response) . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($code != 235) {\r\n $this->error =\r\n array('error' => 'Credentials not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n break;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Works like hash_hmac('md5', $data, $key) in case that function is not available\r\n * @access protected\r\n * @param string $data\r\n * @param string $key\r\n * @return string\r\n */\r\n protected function hmac($data, $key) {\r\n if (function_exists('hash_hmac')) {\r\n return hash_hmac('md5', $data, $key);\r\n }\r\n\r\n // The following borrowed from http://php.net/manual/en/function.mhash.php#27225\r\n\r\n // RFC 2104 HMAC implementation for php.\r\n // Creates an md5 HMAC.\r\n // Eliminates the need to install mhash to compute a HMAC\r\n // Hacked by Lance Rushing\r\n\r\n $b = 64; // byte length for md5\r\n if (strlen($key) > $b) {\r\n $key = pack('H*', md5($key));\r\n }\r\n $key = str_pad($key, $b, chr(0x00));\r\n $ipad = str_pad('', $b, chr(0x36));\r\n $opad = str_pad('', $b, chr(0x5c));\r\n $k_ipad = $key ^ $ipad ;\r\n $k_opad = $key ^ $opad;\r\n\r\n return md5($k_opad . pack('H*', md5($k_ipad . $data)));\r\n }\r\n\r\n /**\r\n * Returns true if connected to a server otherwise false\r\n * @access public\r\n * @return bool\r\n */\r\n public function Connected() {\r\n if(!empty($this->smtp_conn)) {\r\n $sock_status = stream_get_meta_data($this->smtp_conn);\r\n if($sock_status['eof']) {\r\n // the socket is valid but we are not connected\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> NOTICE: EOF caught while checking if connected');\r\n }\r\n $this->Close();\r\n return false;\r\n }\r\n return true; // everything looks good\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Closes the socket and cleans up the state of the class.\r\n * It is not considered good to use this function without\r\n * first trying to use QUIT.\r\n * @access public\r\n * @return void\r\n */\r\n public function Close() {\r\n $this->error = null; // so there is no confusion\r\n $this->helo_rply = null;\r\n if(!empty($this->smtp_conn)) {\r\n // close the connection and cleanup\r\n fclose($this->smtp_conn);\r\n $this->smtp_conn = 0;\r\n }\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // SMTP COMMANDS\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Issues a data command and sends the msg_data to the server\r\n * finializing the mail transaction. $msg_data is the message\r\n * that is to be send with the headers. Each header needs to be\r\n * on a single line followed by a with the message headers\r\n * and the message body being separated by and additional .\r\n *\r\n * Implements rfc 821: DATA \r\n *\r\n * SMTP CODE INTERMEDIATE: 354\r\n * [data]\r\n * .\r\n * SMTP CODE SUCCESS: 250\r\n * SMTP CODE FAILURE: 552, 554, 451, 452\r\n * SMTP CODE FAILURE: 451, 554\r\n * SMTP CODE ERROR : 500, 501, 503, 421\r\n * @access public\r\n * @param string $msg_data\r\n * @return bool\r\n */\r\n public function Data($msg_data) {\r\n $this->error = null; // so no confusion is caused\r\n\r\n if(!$this->connected()) {\r\n $this->error = array(\r\n 'error' => 'Called Data() without being connected');\r\n return false;\r\n }\r\n\r\n $this->client_send('DATA' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 354) {\r\n $this->error =\r\n array('error' => 'DATA command not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n /* the server is ready to accept data!\r\n * according to rfc 821 we should not send more than 1000\r\n * including the CRLF\r\n * characters on a single line so we will break the data up\r\n * into lines by \\r and/or \\n then if needed we will break\r\n * each of those into smaller lines to fit within the limit.\r\n * in addition we will be looking for lines that start with\r\n * a period '.' and append and additional period '.' to that\r\n * line. NOTE: this does not count towards limit.\r\n */\r\n\r\n // normalize the line breaks so we know the explode works\r\n $msg_data = str_replace(\"\\r\\n\", \"\\n\", $msg_data);\r\n $msg_data = str_replace(\"\\r\", \"\\n\", $msg_data);\r\n $lines = explode(\"\\n\", $msg_data);\r\n\r\n /* we need to find a good way to determine is headers are\r\n * in the msg_data or if it is a straight msg body\r\n * currently I am assuming rfc 822 definitions of msg headers\r\n * and if the first field of the first line (':' sperated)\r\n * does not contain a space then it _should_ be a header\r\n * and we can process all lines before a blank \"\" line as\r\n * headers.\r\n */\r\n\r\n $field = substr($lines[0], 0, strpos($lines[0], ':'));\r\n $in_headers = false;\r\n if(!empty($field) && !strstr($field, ' ')) {\r\n $in_headers = true;\r\n }\r\n\r\n $max_line_length = 998; // used below; set here for ease in change\r\n\r\n while(list(, $line) = @each($lines)) {\r\n $lines_out = null;\r\n if($line == '' && $in_headers) {\r\n $in_headers = false;\r\n }\r\n // ok we need to break this line up into several smaller lines\r\n while(strlen($line) > $max_line_length) {\r\n $pos = strrpos(substr($line, 0, $max_line_length), ' ');\r\n\r\n // Patch to fix DOS attack\r\n if(!$pos) {\r\n $pos = $max_line_length - 1;\r\n $lines_out[] = substr($line, 0, $pos);\r\n $line = substr($line, $pos);\r\n } else {\r\n $lines_out[] = substr($line, 0, $pos);\r\n $line = substr($line, $pos + 1);\r\n }\r\n\r\n /* if processing headers add a LWSP-char to the front of new line\r\n * rfc 822 on long msg headers\r\n */\r\n if($in_headers) {\r\n $line = \"\\t\" . $line;\r\n }\r\n }\r\n $lines_out[] = $line;\r\n\r\n // send the lines to the server\r\n while(list(, $line_out) = @each($lines_out)) {\r\n if(strlen($line_out) > 0)\r\n {\r\n if(substr($line_out, 0, 1) == '.') {\r\n $line_out = '.' . $line_out;\r\n }\r\n }\r\n $this->client_send($line_out . $this->CRLF);\r\n }\r\n }\r\n\r\n // message data has been sent\r\n $this->client_send($this->CRLF . '.' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 250) {\r\n $this->error =\r\n array('error' => 'DATA not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Sends the HELO command to the smtp server.\r\n * This makes sure that we and the server are in\r\n * the same known state.\r\n *\r\n * Implements from rfc 821: HELO \r\n *\r\n * SMTP CODE SUCCESS: 250\r\n * SMTP CODE ERROR : 500, 501, 504, 421\r\n * @access public\r\n * @param string $host\r\n * @return bool\r\n */\r\n public function Hello($host = '') {\r\n $this->error = null; // so no confusion is caused\r\n\r\n if(!$this->connected()) {\r\n $this->error = array(\r\n 'error' => 'Called Hello() without being connected');\r\n return false;\r\n }\r\n\r\n // if hostname for HELO was not specified send default\r\n if(empty($host)) {\r\n // determine appropriate default to send to server\r\n $host = 'localhost';\r\n }\r\n\r\n // Send extended hello first (RFC 2821)\r\n if(!$this->SendHello('EHLO', $host)) {\r\n if(!$this->SendHello('HELO', $host)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Sends a HELO/EHLO command.\r\n * @access protected\r\n * @param string $hello\r\n * @param string $host\r\n * @return bool\r\n */\r\n protected function SendHello($hello, $host) {\r\n $this->client_send($hello . ' ' . $host . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER: ' . $rply);\r\n }\r\n\r\n if($code != 250) {\r\n $this->error =\r\n array('error' => $hello . ' not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n $this->helo_rply = $rply;\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Starts a mail transaction from the email address specified in\r\n * $from. Returns true if successful or false otherwise. If True\r\n * the mail transaction is started and then one or more Recipient\r\n * commands may be called followed by a Data command.\r\n *\r\n * Implements rfc 821: MAIL FROM: \r\n *\r\n * SMTP CODE SUCCESS: 250\r\n * SMTP CODE SUCCESS: 552, 451, 452\r\n * SMTP CODE SUCCESS: 500, 501, 421\r\n * @access public\r\n * @param string $from\r\n * @return bool\r\n */\r\n public function Mail($from) {\r\n $this->error = null; // so no confusion is caused\r\n\r\n if(!$this->connected()) {\r\n $this->error = array(\r\n 'error' => 'Called Mail() without being connected');\r\n return false;\r\n }\r\n\r\n $useVerp = ($this->do_verp ? ' XVERP' : '');\r\n $this->client_send('MAIL FROM:<' . $from . '>' . $useVerp . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 250) {\r\n $this->error =\r\n array('error' => 'MAIL not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Sends the quit command to the server and then closes the socket\r\n * if there is no error or the $close_on_error argument is true.\r\n *\r\n * Implements from rfc 821: QUIT \r\n *\r\n * SMTP CODE SUCCESS: 221\r\n * SMTP CODE ERROR : 500\r\n * @access public\r\n * @param bool $close_on_error\r\n * @return bool\r\n */\r\n public function Quit($close_on_error = true) {\r\n $this->error = null; // so there is no confusion\r\n\r\n if(!$this->connected()) {\r\n $this->error = array(\r\n 'error' => 'Called Quit() without being connected');\r\n return false;\r\n }\r\n\r\n // send the quit command to the server\r\n $this->client_send('quit' . $this->CRLF);\r\n\r\n // get any good-bye messages\r\n $byemsg = $this->get_lines();\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $byemsg);\r\n }\r\n\r\n $rval = true;\r\n $e = null;\r\n\r\n $code = substr($byemsg, 0, 3);\r\n if($code != 221) {\r\n // use e as a tmp var cause Close will overwrite $this->error\r\n $e = array('error' => 'SMTP server rejected quit command',\r\n 'smtp_code' => $code,\r\n 'smtp_rply' => substr($byemsg, 4));\r\n $rval = false;\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $e['error'] . ': ' . $byemsg);\r\n }\r\n }\r\n\r\n if(empty($e) || $close_on_error) {\r\n $this->Close();\r\n }\r\n\r\n return $rval;\r\n }\r\n\r\n /**\r\n * Sends the command RCPT to the SMTP server with the TO: argument of $to.\r\n * Returns true if the recipient was accepted false if it was rejected.\r\n *\r\n * Implements from rfc 821: RCPT TO: \r\n *\r\n * SMTP CODE SUCCESS: 250, 251\r\n * SMTP CODE FAILURE: 550, 551, 552, 553, 450, 451, 452\r\n * SMTP CODE ERROR : 500, 501, 503, 421\r\n * @access public\r\n * @param string $to\r\n * @return bool\r\n */\r\n public function Recipient($to) {\r\n $this->error = null; // so no confusion is caused\r\n\r\n if(!$this->connected()) {\r\n $this->error = array(\r\n 'error' => 'Called Recipient() without being connected');\r\n return false;\r\n }\r\n\r\n $this->client_send('RCPT TO:<' . $to . '>' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 250 && $code != 251) {\r\n $this->error =\r\n array('error' => 'RCPT not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Sends the RSET command to abort and transaction that is\r\n * currently in progress. Returns true if successful false\r\n * otherwise.\r\n *\r\n * Implements rfc 821: RSET \r\n *\r\n * SMTP CODE SUCCESS: 250\r\n * SMTP CODE ERROR : 500, 501, 504, 421\r\n * @access public\r\n * @return bool\r\n */\r\n public function Reset() {\r\n $this->error = null; // so no confusion is caused\r\n\r\n if(!$this->connected()) {\r\n $this->error = array('error' => 'Called Reset() without being connected');\r\n return false;\r\n }\r\n\r\n $this->client_send('RSET' . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 250) {\r\n $this->error =\r\n array('error' => 'RSET failed',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Starts a mail transaction from the email address specified in\r\n * $from. Returns true if successful or false otherwise. If True\r\n * the mail transaction is started and then one or more Recipient\r\n * commands may be called followed by a Data command. This command\r\n * will send the message to the users terminal if they are logged\r\n * in and send them an email.\r\n *\r\n * Implements rfc 821: SAML FROM: \r\n *\r\n * SMTP CODE SUCCESS: 250\r\n * SMTP CODE SUCCESS: 552, 451, 452\r\n * SMTP CODE SUCCESS: 500, 501, 502, 421\r\n * @access public\r\n * @param string $from\r\n * @return bool\r\n */\r\n public function SendAndMail($from) {\r\n $this->error = null; // so no confusion is caused\r\n\r\n if(!$this->connected()) {\r\n $this->error = array(\r\n 'error' => 'Called SendAndMail() without being connected');\r\n return false;\r\n }\r\n\r\n $this->client_send('SAML FROM:' . $from . $this->CRLF);\r\n\r\n $rply = $this->get_lines();\r\n $code = substr($rply, 0, 3);\r\n\r\n if($this->do_debug >= 2) {\r\n $this->edebug('SMTP -> FROM SERVER:' . $rply);\r\n }\r\n\r\n if($code != 250) {\r\n $this->error =\r\n array('error' => 'SAML not accepted from server',\r\n 'smtp_code' => $code,\r\n 'smtp_msg' => substr($rply, 4));\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * This is an optional command for SMTP that this class does not\r\n * support. This method is here to make the RFC821 Definition\r\n * complete for this class and __may__ be implimented in the future\r\n *\r\n * Implements from rfc 821: TURN \r\n *\r\n * SMTP CODE SUCCESS: 250\r\n * SMTP CODE FAILURE: 502\r\n * SMTP CODE ERROR : 500, 503\r\n * @access public\r\n * @return bool\r\n */\r\n public function Turn() {\r\n $this->error = array('error' => 'This method, TURN, of the SMTP '.\r\n 'is not implemented');\r\n if($this->do_debug >= 1) {\r\n $this->edebug('SMTP -> NOTICE: ' . $this->error['error']);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Sends data to the server\r\n * @param string $data\r\n * @access public\r\n * @return Integer number of bytes sent to the server or FALSE on error\r\n */\r\n public function client_send($data) {\r\n if ($this->do_debug >= 1) {\r\n $this->edebug(\"CLIENT -> SMTP: $data\");\r\n }\r\n return fwrite($this->smtp_conn, $data);\r\n }\r\n\r\n /**\r\n * Get the current error\r\n * @access public\r\n * @return array\r\n */\r\n public function getError() {\r\n return $this->error;\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // INTERNAL FUNCTIONS\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Read in as many lines as possible\r\n * either before eof or socket timeout occurs on the operation.\r\n * With SMTP we can tell if we have more lines to read if the\r\n * 4th character is '-' symbol. If it is a space then we don't\r\n * need to read anything else.\r\n * @access protected\r\n * @return string\r\n */\r\n protected function get_lines() {\r\n $data = '';\r\n $endtime = 0;\r\n /* If for some reason the fp is bad, don't inf loop */\r\n if (!is_resource($this->smtp_conn)) {\r\n return $data;\r\n }\r\n stream_set_timeout($this->smtp_conn, $this->Timeout);\r\n if ($this->Timelimit > 0) {\r\n $endtime = time() + $this->Timelimit;\r\n }\r\n while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {\r\n $str = @fgets($this->smtp_conn, 515);\r\n if($this->do_debug >= 4) {\r\n $this->edebug(\"SMTP -> get_lines(): \\$data was \\\"$data\\\"\");\r\n $this->edebug(\"SMTP -> get_lines(): \\$str is \\\"$str\\\"\");\r\n }\r\n $data .= $str;\r\n if($this->do_debug >= 4) {\r\n $this->edebug(\"SMTP -> get_lines(): \\$data is \\\"$data\\\"\");\r\n }\r\n // if 4th character is a space, we are done reading, break the loop\r\n if(substr($str, 3, 1) == ' ') { break; }\r\n // Timed-out? Log and break\r\n $info = stream_get_meta_data($this->smtp_conn);\r\n if ($info['timed_out']) {\r\n if($this->do_debug >= 4) {\r\n $this->edebug('SMTP -> get_lines(): timed-out (' . $this->Timeout . ' seconds)');\r\n }\r\n break;\r\n }\r\n // Now check if reads took too long\r\n if ($endtime) {\r\n if (time() > $endtime) {\r\n if($this->do_debug >= 4) {\r\n $this->edebug('SMTP -> get_lines(): timelimit reached (' . $this->Timelimit . ' seconds)');\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n return $data;\r\n }\r\n\r\n}\r\n" , SF False ".\\php\\plugins\\lib\\class.pop3.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "\r\n * @author Andy Prevost\r\n * @author Jim Jagielski\r\n */\r\n\r\nclass POP3 {\r\n /**\r\n * Default POP3 port\r\n * @var int\r\n */\r\n public $POP3_PORT = 110;\r\n\r\n /**\r\n * Default Timeout\r\n * @var int\r\n */\r\n public $POP3_TIMEOUT = 30;\r\n\r\n /**\r\n * POP3 Carriage Return + Line Feed\r\n * @var string\r\n */\r\n public $CRLF = \"\\r\\n\";\r\n\r\n /**\r\n * Displaying Debug warnings? (0 = now, 1+ = yes)\r\n * @var int\r\n */\r\n public $do_debug = 2;\r\n\r\n /**\r\n * POP3 Mail Server\r\n * @var string\r\n */\r\n public $host;\r\n\r\n /**\r\n * POP3 Port\r\n * @var int\r\n */\r\n public $port;\r\n\r\n /**\r\n * POP3 Timeout Value\r\n * @var int\r\n */\r\n public $tval;\r\n\r\n /**\r\n * POP3 Username\r\n * @var string\r\n */\r\n public $username;\r\n\r\n /**\r\n * POP3 Password\r\n * @var string\r\n */\r\n public $password;\r\n\r\n /**\r\n * Sets the POP3 PHPMailer Version number\r\n * @var string\r\n */\r\n public $Version = '5.2.6';\r\n\r\n /////////////////////////////////////////////////\r\n // PROPERTIES, PRIVATE AND PROTECTED\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * @var resource Resource handle for the POP connection socket\r\n */\r\n private $pop_conn;\r\n /**\r\n * @var boolean Are we connected?\r\n */\r\n private $connected;\r\n /**\r\n * @var array Error container\r\n */\r\n private $error; // Error log array\r\n\r\n /**\r\n * Constructor, sets the initial values\r\n * @access public\r\n * @return POP3\r\n */\r\n public function __construct() {\r\n $this->pop_conn = 0;\r\n $this->connected = false;\r\n $this->error = null;\r\n }\r\n\r\n /**\r\n * Combination of public events - connect, login, disconnect\r\n * @access public\r\n * @param string $host\r\n * @param bool|int $port\r\n * @param bool|int $tval\r\n * @param string $username\r\n * @param string $password\r\n * @param int $debug_level\r\n * @return bool\r\n */\r\n public function Authorise ($host, $port = false, $tval = false, $username, $password, $debug_level = 0) {\r\n $this->host = $host;\r\n\r\n // If no port value is passed, retrieve it\r\n if ($port == false) {\r\n $this->port = $this->POP3_PORT;\r\n } else {\r\n $this->port = $port;\r\n }\r\n\r\n // If no port value is passed, retrieve it\r\n if ($tval == false) {\r\n $this->tval = $this->POP3_TIMEOUT;\r\n } else {\r\n $this->tval = $tval;\r\n }\r\n\r\n $this->do_debug = $debug_level;\r\n $this->username = $username;\r\n $this->password = $password;\r\n\r\n // Refresh the error log\r\n $this->error = null;\r\n\r\n // Connect\r\n $result = $this->Connect($this->host, $this->port, $this->tval);\r\n\r\n if ($result) {\r\n $login_result = $this->Login($this->username, $this->password);\r\n\r\n if ($login_result) {\r\n $this->Disconnect();\r\n\r\n return true;\r\n }\r\n\r\n }\r\n\r\n // We need to disconnect regardless if the login succeeded\r\n $this->Disconnect();\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Connect to the POP3 server\r\n * @access public\r\n * @param string $host\r\n * @param bool|int $port\r\n * @param integer $tval\r\n * @return boolean\r\n */\r\n public function Connect ($host, $port = false, $tval = 30) {\r\n // Are we already connected?\r\n if ($this->connected) {\r\n return true;\r\n }\r\n\r\n /*\r\n On Windows this will raise a PHP Warning error if the hostname doesn't exist.\r\n Rather than suppress it with @fsockopen, let's capture it cleanly instead\r\n */\r\n\r\n set_error_handler(array(&$this, 'catchWarning'));\r\n\r\n // Connect to the POP3 server\r\n $this->pop_conn = fsockopen($host, // POP3 Host\r\n $port, // Port #\r\n $errno, // Error Number\r\n $errstr, // Error Message\r\n $tval); // Timeout (seconds)\r\n\r\n // Restore the error handler\r\n restore_error_handler();\r\n\r\n // Does the Error Log now contain anything?\r\n if ($this->error && $this->do_debug >= 1) {\r\n $this->displayErrors();\r\n }\r\n\r\n // Did we connect?\r\n if ($this->pop_conn == false) {\r\n // It would appear not...\r\n $this->error = array(\r\n 'error' => \"Failed to connect to server $host on port $port\",\r\n 'errno' => $errno,\r\n 'errstr' => $errstr\r\n );\r\n\r\n if ($this->do_debug >= 1) {\r\n $this->displayErrors();\r\n }\r\n\r\n return false;\r\n }\r\n\r\n // Increase the stream time-out\r\n\r\n // Check for PHP 4.3.0 or later\r\n if (version_compare(phpversion(), '5.0.0', 'ge')) {\r\n stream_set_timeout($this->pop_conn, $tval, 0);\r\n } else {\r\n // Does not work on Windows\r\n if (substr(PHP_OS, 0, 3) !== 'WIN') {\r\n socket_set_timeout($this->pop_conn, $tval, 0);\r\n }\r\n }\r\n\r\n // Get the POP3 server response\r\n $pop3_response = $this->getResponse();\r\n\r\n // Check for the +OK\r\n if ($this->checkResponse($pop3_response)) {\r\n // The connection is established and the POP3 server is talking\r\n $this->connected = true;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Login to the POP3 server (does not support APOP yet)\r\n * @access public\r\n * @param string $username\r\n * @param string $password\r\n * @return boolean\r\n */\r\n public function Login ($username = '', $password = '') {\r\n if ($this->connected == false) {\r\n $this->error = 'Not connected to POP3 server';\r\n\r\n if ($this->do_debug >= 1) {\r\n $this->displayErrors();\r\n }\r\n }\r\n\r\n if (empty($username)) {\r\n $username = $this->username;\r\n }\r\n\r\n if (empty($password)) {\r\n $password = $this->password;\r\n }\r\n\r\n $pop_username = \"USER $username\" . $this->CRLF;\r\n $pop_password = \"PASS $password\" . $this->CRLF;\r\n\r\n // Send the Username\r\n $this->sendString($pop_username);\r\n $pop3_response = $this->getResponse();\r\n\r\n if ($this->checkResponse($pop3_response)) {\r\n // Send the Password\r\n $this->sendString($pop_password);\r\n $pop3_response = $this->getResponse();\r\n\r\n if ($this->checkResponse($pop3_response)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Disconnect from the POP3 server\r\n * @access public\r\n */\r\n public function Disconnect () {\r\n $this->sendString('QUIT');\r\n\r\n fclose($this->pop_conn);\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // Private Methods\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Get the socket response back.\r\n * $size is the maximum number of bytes to retrieve\r\n * @access private\r\n * @param integer $size\r\n * @return string\r\n */\r\n private function getResponse ($size = 128) {\r\n $pop3_response = fgets($this->pop_conn, $size);\r\n\r\n return $pop3_response;\r\n }\r\n\r\n /**\r\n * Send a string down the open socket connection to the POP3 server\r\n * @access private\r\n * @param string $string\r\n * @return integer\r\n */\r\n private function sendString ($string) {\r\n $bytes_sent = fwrite($this->pop_conn, $string, strlen($string));\r\n\r\n return $bytes_sent;\r\n }\r\n\r\n /**\r\n * Checks the POP3 server response for +OK or -ERR\r\n * @access private\r\n * @param string $string\r\n * @return boolean\r\n */\r\n private function checkResponse ($string) {\r\n if (substr($string, 0, 3) !== '+OK') {\r\n $this->error = array(\r\n 'error' => \"Server reported an error: $string\",\r\n 'errno' => 0,\r\n 'errstr' => ''\r\n );\r\n\r\n if ($this->do_debug >= 1) {\r\n $this->displayErrors();\r\n }\r\n\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n\r\n }\r\n\r\n /**\r\n * If debug is enabled, display the error message array\r\n * @access private\r\n */\r\n private function displayErrors () {\r\n echo '
';\r\n\r\n    foreach ($this->error as $single_error) {\r\n      print_r($single_error);\r\n    }\r\n\r\n    echo '
';\r\n }\r\n\r\n /**\r\n * Takes over from PHP for the socket warning handler\r\n * @access private\r\n * @param integer $errno\r\n * @param string $errstr\r\n * @param string $errfile\r\n * @param integer $errline\r\n */\r\n private function catchWarning ($errno, $errstr, $errfile, $errline) {\r\n $this->error[] = array(\r\n 'error' => \"Connecting to the POP3 server raised a PHP warning: \",\r\n 'errno' => $errno,\r\n 'errstr' => $errstr\r\n );\r\n }\r\n\r\n // End of class\r\n}\r\n" , SF False ".\\php\\plugins\\lib\\class.phpmailer.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "UseSendmailOptions) ) {\r\n $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header);\r\n } else {\r\n $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header, $params);\r\n }\r\n return $rt;\r\n }\r\n\r\n /**\r\n * Outputs debugging info via user-defined method if debug output is enabled\r\n * @param string $str\r\n */\r\n protected function edebug($str) {\r\n if (!$this->SMTPDebug) {\r\n return;\r\n }\r\n switch ($this->Debugoutput) {\r\n case 'error_log':\r\n error_log($str);\r\n break;\r\n case 'html':\r\n //Cleans up output a bit for a better looking display that's HTML-safe\r\n echo htmlentities(preg_replace('/[\\r\\n]+/', '', $str), ENT_QUOTES, $this->CharSet).\"
\\n\";\r\n break;\r\n case 'echo':\r\n default:\r\n //Just echoes exactly what was received\r\n echo $str;\r\n }\r\n }\r\n\r\n /**\r\n * Constructor\r\n * @param boolean $exceptions Should we throw external exceptions?\r\n */\r\n public function __construct($exceptions = false) {\r\n $this->exceptions = ($exceptions == true);\r\n }\r\n\r\n /**\r\n * Destructor\r\n */\r\n public function __destruct() {\r\n if ($this->Mailer == 'smtp') { //Close any open SMTP connection nicely\r\n $this->SmtpClose();\r\n }\r\n }\r\n\r\n /**\r\n * Sets message type to HTML.\r\n * @param bool $ishtml\r\n * @return void\r\n */\r\n public function IsHTML($ishtml = true) {\r\n if ($ishtml) {\r\n $this->ContentType = 'text/html';\r\n } else {\r\n $this->ContentType = 'text/plain';\r\n }\r\n }\r\n\r\n /**\r\n * Sets Mailer to send message using SMTP.\r\n * @return void\r\n */\r\n public function IsSMTP() {\r\n $this->Mailer = 'smtp';\r\n }\r\n\r\n /**\r\n * Sets Mailer to send message using PHP mail() function.\r\n * @return void\r\n */\r\n public function IsMail() {\r\n $this->Mailer = 'mail';\r\n }\r\n\r\n /**\r\n * Sets Mailer to send message using the $Sendmail program.\r\n * @return void\r\n */\r\n public function IsSendmail() {\r\n if (!stristr(ini_get('sendmail_path'), 'sendmail')) {\r\n $this->Sendmail = '/var/qmail/bin/sendmail';\r\n }\r\n $this->Mailer = 'sendmail';\r\n }\r\n\r\n /**\r\n * Sets Mailer to send message using the qmail MTA.\r\n * @return void\r\n */\r\n public function IsQmail() {\r\n if (stristr(ini_get('sendmail_path'), 'qmail')) {\r\n $this->Sendmail = '/var/qmail/bin/sendmail';\r\n }\r\n $this->Mailer = 'sendmail';\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // METHODS, RECIPIENTS\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Adds a \"To\" address.\r\n * @param string $address\r\n * @param string $name\r\n * @return boolean true on success, false if address already used\r\n */\r\n public function AddAddress($address, $name = '') {\r\n return $this->AddAnAddress('to', $address, $name);\r\n }\r\n\r\n /**\r\n * Adds a \"Cc\" address.\r\n * Note: this function works with the SMTP mailer on win32, not with the \"mail\" mailer.\r\n * @param string $address\r\n * @param string $name\r\n * @return boolean true on success, false if address already used\r\n */\r\n public function AddCC($address, $name = '') {\r\n return $this->AddAnAddress('cc', $address, $name);\r\n }\r\n\r\n /**\r\n * Adds a \"Bcc\" address.\r\n * Note: this function works with the SMTP mailer on win32, not with the \"mail\" mailer.\r\n * @param string $address\r\n * @param string $name\r\n * @return boolean true on success, false if address already used\r\n */\r\n public function AddBCC($address, $name = '') {\r\n return $this->AddAnAddress('bcc', $address, $name);\r\n }\r\n\r\n /**\r\n * Adds a \"Reply-to\" address.\r\n * @param string $address\r\n * @param string $name\r\n * @return boolean\r\n */\r\n public function AddReplyTo($address, $name = '') {\r\n return $this->AddAnAddress('Reply-To', $address, $name);\r\n }\r\n\r\n /**\r\n * Adds an address to one of the recipient arrays\r\n * Addresses that have been added already return false, but do not throw exceptions\r\n * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'\r\n * @param string $address The email address to send to\r\n * @param string $name\r\n * @throws phpmailerException\r\n * @return boolean true on success, false if address already used or invalid in some way\r\n * @access protected\r\n */\r\n protected function AddAnAddress($kind, $address, $name = '') {\r\n if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {\r\n $this->SetError($this->Lang('Invalid recipient array').': '.$kind);\r\n if ($this->exceptions) {\r\n throw new phpmailerException('Invalid recipient array: ' . $kind);\r\n }\r\n $this->edebug($this->Lang('Invalid recipient array').': '.$kind);\r\n return false;\r\n }\r\n $address = trim($address);\r\n $name = trim(preg_replace('/[\\r\\n]+/', '', $name)); //Strip breaks and trim\r\n if (!$this->ValidateAddress($address)) {\r\n $this->SetError($this->Lang('invalid_address').': '. $address);\r\n if ($this->exceptions) {\r\n throw new phpmailerException($this->Lang('invalid_address').': '.$address);\r\n }\r\n $this->edebug($this->Lang('invalid_address').': '.$address);\r\n return false;\r\n }\r\n if ($kind != 'Reply-To') {\r\n if (!isset($this->all_recipients[strtolower($address)])) {\r\n array_push($this->$kind, array($address, $name));\r\n $this->all_recipients[strtolower($address)] = true;\r\n return true;\r\n }\r\n } else {\r\n if (!array_key_exists(strtolower($address), $this->ReplyTo)) {\r\n $this->ReplyTo[strtolower($address)] = array($address, $name);\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n /**\r\n * Set the From and FromName properties\r\n * @param string $address\r\n * @param string $name\r\n * @param boolean $auto Whether to also set the Sender address, defaults to true\r\n * @throws phpmailerException\r\n * @return boolean\r\n */\r\n public function SetFrom($address, $name = '', $auto = true) {\r\n $address = trim($address);\r\n $name = trim(preg_replace('/[\\r\\n]+/', '', $name)); //Strip breaks and trim\r\n if (!$this->ValidateAddress($address)) {\r\n $this->SetError($this->Lang('invalid_address').': '. $address);\r\n if ($this->exceptions) {\r\n throw new phpmailerException($this->Lang('invalid_address').': '.$address);\r\n }\r\n $this->edebug($this->Lang('invalid_address').': '.$address);\r\n return false;\r\n }\r\n $this->From = $address;\r\n $this->FromName = $name;\r\n if ($auto) {\r\n if (empty($this->Sender)) {\r\n $this->Sender = $address;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Check that a string looks roughly like an email address should\r\n * Static so it can be used without instantiation, public so people can overload\r\n * Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is\r\n * based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to\r\n * not allow a@b type valid addresses :(\r\n * @link http://squiloople.com/2009/12/20/email-address-validation/\r\n * @copyright regex Copyright Michael Rushton 2009-10 | http://squiloople.com/ | Feel free to use and redistribute this code. But please keep this copyright notice.\r\n * @param string $address The email address to check\r\n * @return boolean\r\n * @static\r\n * @access public\r\n */\r\n public static function ValidateAddress($address) {\r\n if (defined('PCRE_VERSION')) { //Check this instead of extension_loaded so it works when that function is disabled\r\n if (version_compare(PCRE_VERSION, '8.0') >= 0) {\r\n return (boolean)preg_match('/^(?!(?>(?1)\"?(?>\\\\\\[ -~]|[^\"])\"?(?1)){255,})(?!(?>(?1)\"?(?>\\\\\\[ -~]|[^\"])\"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\\x0D\\x0A)?[\\t ])+|(?>[\\t ]*\\x0D\\x0A)?[\\t ]+)?)(\\((?>(?2)(?>[\\x01-\\x08\\x0B\\x0C\\x0E-\\'*-\\[\\]-\\x7F]|\\\\\\[\\x00-\\x7F]|(?3)))*(?2)\\)))+(?2))|(?2))?)([!#-\\'*+\\/-9=?^-~-]+|\"(?>(?2)(?>[\\x01-\\x08\\x0B\\x0C\\x0E-!#-\\[\\]-\\x7F]|\\\\\\[\\x00-\\x7F]))*(?2)\")(?>(?1)\\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\\.(?9)){3}))\\])(?1)$/isD', $address);\r\n } else {\r\n //Fall back to an older regex that doesn't need a recent PCRE\r\n return (boolean)preg_match('/^(?!(?>\"?(?>\\\\\\[ -~]|[^\"])\"?){255,})(?!(?>\"?(?>\\\\\\[ -~]|[^\"])\"?){65,}@)(?>[!#-\\'*+\\/-9=?^-~-]+|\"(?>(?>[\\x01-\\x08\\x0B\\x0C\\x0E-!#-\\[\\]-\\x7F]|\\\\\\[\\x00-\\xFF]))*\")(?>\\.(?>[!#-\\'*+\\/-9=?^-~-]+|\"(?>(?>[\\x01-\\x08\\x0B\\x0C\\x0E-!#-\\[\\]-\\x7F]|\\\\\\[\\x00-\\xFF]))*\"))*@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\\.(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\\])$/isD', $address);\r\n }\r\n } else {\r\n //No PCRE! Do something _very_ approximate!\r\n //Check the address is 3 chars or longer and contains an @ that's not the first or last char\r\n return (strlen($address) >= 3 and strpos($address, '@') >= 1 and strpos($address, '@') != strlen($address) - 1);\r\n }\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // METHODS, MAIL SENDING\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Creates message and assigns Mailer. If the message is\r\n * not sent successfully then it returns false. Use the ErrorInfo\r\n * variable to view description of the error.\r\n * @throws phpmailerException\r\n * @return bool\r\n */\r\n public function Send() {\r\n try {\r\n if(!$this->PreSend()) return false;\r\n return $this->PostSend();\r\n } catch (phpmailerException $e) {\r\n $this->mailHeader = '';\r\n $this->SetError($e->getMessage());\r\n if ($this->exceptions) {\r\n throw $e;\r\n }\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Prep mail by constructing all message entities\r\n * @throws phpmailerException\r\n * @return bool\r\n */\r\n public function PreSend() {\r\n try {\r\n $this->mailHeader = \"\";\r\n if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {\r\n throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);\r\n }\r\n\r\n // Set whether the message is multipart/alternative\r\n if(!empty($this->AltBody)) {\r\n $this->ContentType = 'multipart/alternative';\r\n }\r\n\r\n $this->error_count = 0; // reset errors\r\n $this->SetMessageType();\r\n //Refuse to send an empty message unless we are specifically allowing it\r\n if (!$this->AllowEmpty and empty($this->Body)) {\r\n throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);\r\n }\r\n\r\n $this->MIMEHeader = $this->CreateHeader();\r\n $this->MIMEBody = $this->CreateBody();\r\n\r\n // To capture the complete message when using mail(), create\r\n // an extra header list which CreateHeader() doesn't fold in\r\n if ($this->Mailer == 'mail') {\r\n if (count($this->to) > 0) {\r\n $this->mailHeader .= $this->AddrAppend(\"To\", $this->to);\r\n } else {\r\n $this->mailHeader .= $this->HeaderLine(\"To\", \"undisclosed-recipients:;\");\r\n }\r\n $this->mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject))));\r\n }\r\n\r\n // digitally sign with DKIM if enabled\r\n if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) {\r\n $header_dkim = $this->DKIM_Add($this->MIMEHeader . $this->mailHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);\r\n $this->MIMEHeader = str_replace(\"\\r\\n\", \"\\n\", $header_dkim) . $this->MIMEHeader;\r\n }\r\n\r\n return true;\r\n\r\n } catch (phpmailerException $e) {\r\n $this->SetError($e->getMessage());\r\n if ($this->exceptions) {\r\n throw $e;\r\n }\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Actual Email transport function\r\n * Send the email via the selected mechanism\r\n * @throws phpmailerException\r\n * @return bool\r\n */\r\n public function PostSend() {\r\n try {\r\n // Choose the mailer and send through it\r\n switch($this->Mailer) {\r\n case 'sendmail':\r\n return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);\r\n case 'smtp':\r\n return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);\r\n case 'mail':\r\n return $this->MailSend($this->MIMEHeader, $this->MIMEBody);\r\n default:\r\n return $this->MailSend($this->MIMEHeader, $this->MIMEBody);\r\n }\r\n } catch (phpmailerException $e) {\r\n $this->SetError($e->getMessage());\r\n if ($this->exceptions) {\r\n throw $e;\r\n }\r\n $this->edebug($e->getMessage().\"\\n\");\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Sends mail using the $Sendmail program.\r\n * @param string $header The message headers\r\n * @param string $body The message body\r\n * @throws phpmailerException\r\n * @access protected\r\n * @return bool\r\n */\r\n protected function SendmailSend($header, $body) {\r\n if ($this->Sender != '') {\r\n $sendmail = sprintf(\"%s -oi -f%s -t\", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));\r\n } else {\r\n $sendmail = sprintf(\"%s -oi -t\", escapeshellcmd($this->Sendmail));\r\n }\r\n if ($this->SingleTo === true) {\r\n foreach ($this->SingleToArray as $val) {\r\n if(!@$mail = popen($sendmail, 'w')) {\r\n throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);\r\n }\r\n fputs($mail, \"To: \" . $val . \"\\n\");\r\n fputs($mail, $header);\r\n fputs($mail, $body);\r\n $result = pclose($mail);\r\n // implement call back function if it exists\r\n $isSent = ($result == 0) ? 1 : 0;\r\n $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);\r\n if($result != 0) {\r\n throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);\r\n }\r\n }\r\n } else {\r\n if(!@$mail = popen($sendmail, 'w')) {\r\n throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);\r\n }\r\n fputs($mail, $header);\r\n fputs($mail, $body);\r\n $result = pclose($mail);\r\n // implement call back function if it exists\r\n $isSent = ($result == 0) ? 1 : 0;\r\n $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);\r\n if($result != 0) {\r\n throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Sends mail using the PHP mail() function.\r\n * @param string $header The message headers\r\n * @param string $body The message body\r\n * @throws phpmailerException\r\n * @access protected\r\n * @return bool\r\n */\r\n protected function MailSend($header, $body) {\r\n $toArr = array();\r\n foreach($this->to as $t) {\r\n $toArr[] = $this->AddrFormat($t);\r\n }\r\n $to = implode(', ', $toArr);\r\n\r\n if (empty($this->Sender)) {\r\n $params = \" \";\r\n } else {\r\n $params = sprintf(\"-f%s\", $this->Sender);\r\n }\r\n if ($this->Sender != '' and !ini_get('safe_mode')) {\r\n $old_from = ini_get('sendmail_from');\r\n ini_set('sendmail_from', $this->Sender);\r\n }\r\n $rt = false;\r\n if ($this->SingleTo === true && count($toArr) > 1) {\r\n foreach ($toArr as $val) {\r\n $rt = $this->mail_passthru($val, $this->Subject, $body, $header, $params);\r\n // implement call back function if it exists\r\n $isSent = ($rt == 1) ? 1 : 0;\r\n $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);\r\n }\r\n } else {\r\n $rt = $this->mail_passthru($to, $this->Subject, $body, $header, $params);\r\n // implement call back function if it exists\r\n $isSent = ($rt == 1) ? 1 : 0;\r\n $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);\r\n }\r\n if (isset($old_from)) {\r\n ini_set('sendmail_from', $old_from);\r\n }\r\n if(!$rt) {\r\n throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Sends mail via SMTP using PhpSMTP\r\n * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.\r\n * @param string $header The message headers\r\n * @param string $body The message body\r\n * @throws phpmailerException\r\n * @uses SMTP\r\n * @access protected\r\n * @return bool\r\n */\r\n protected function SmtpSend($header, $body) {\r\n require_once $this->PluginDir . 'class.smtp.php';\r\n $bad_rcpt = array();\r\n\r\n if(!$this->SmtpConnect()) {\r\n throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);\r\n }\r\n $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;\r\n if(!$this->smtp->Mail($smtp_from)) {\r\n $this->SetError($this->Lang('from_failed') . $smtp_from . ' : ' .implode(',', $this->smtp->getError()));\r\n throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);\r\n }\r\n\r\n // Attempt to send attach all recipients\r\n foreach($this->to as $to) {\r\n if (!$this->smtp->Recipient($to[0])) {\r\n $bad_rcpt[] = $to[0];\r\n // implement call back function if it exists\r\n $isSent = 0;\r\n $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);\r\n } else {\r\n // implement call back function if it exists\r\n $isSent = 1;\r\n $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);\r\n }\r\n }\r\n foreach($this->cc as $cc) {\r\n if (!$this->smtp->Recipient($cc[0])) {\r\n $bad_rcpt[] = $cc[0];\r\n // implement call back function if it exists\r\n $isSent = 0;\r\n $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);\r\n } else {\r\n // implement call back function if it exists\r\n $isSent = 1;\r\n $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);\r\n }\r\n }\r\n foreach($this->bcc as $bcc) {\r\n if (!$this->smtp->Recipient($bcc[0])) {\r\n $bad_rcpt[] = $bcc[0];\r\n // implement call back function if it exists\r\n $isSent = 0;\r\n $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);\r\n } else {\r\n // implement call back function if it exists\r\n $isSent = 1;\r\n $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);\r\n }\r\n }\r\n\r\n\r\n if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses\r\n $badaddresses = implode(', ', $bad_rcpt);\r\n throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);\r\n }\r\n if(!$this->smtp->Data($header . $body)) {\r\n throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);\r\n }\r\n if($this->SMTPKeepAlive == true) {\r\n $this->smtp->Reset();\r\n } else {\r\n $this->smtp->Quit();\r\n $this->smtp->Close();\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Initiates a connection to an SMTP server.\r\n * Returns false if the operation failed.\r\n * @param array $options An array of options compatible with stream_context_create()\r\n * @uses SMTP\r\n * @access public\r\n * @throws phpmailerException\r\n * @return bool\r\n */\r\n public function SmtpConnect($options = array()) {\r\n if(is_null($this->smtp)) {\r\n $this->smtp = new SMTP;\r\n }\r\n\r\n //Already connected?\r\n if ($this->smtp->Connected()) {\r\n return true;\r\n }\r\n\r\n $this->smtp->Timeout = $this->Timeout;\r\n $this->smtp->do_debug = $this->SMTPDebug;\r\n $this->smtp->Debugoutput = $this->Debugoutput;\r\n $this->smtp->do_verp = $this->do_verp;\r\n $index = 0;\r\n $tls = ($this->SMTPSecure == 'tls');\r\n $ssl = ($this->SMTPSecure == 'ssl');\r\n $hosts = explode(';', $this->Host);\r\n $lastexception = null;\r\n\r\n foreach ($hosts as $hostentry) {\r\n $hostinfo = array();\r\n $host = $hostentry;\r\n $port = $this->Port;\r\n if (preg_match('/^(.+):([0-9]+)$/', $hostentry, $hostinfo)) { //If $hostentry contains 'address:port', override default\r\n $host = $hostinfo[1];\r\n $port = $hostinfo[2];\r\n }\r\n if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout, $options)) {\r\n try {\r\n if ($this->Helo) {\r\n $hello = $this->Helo;\r\n } else {\r\n $hello = $this->ServerHostname();\r\n }\r\n $this->smtp->Hello($hello);\r\n\r\n if ($tls) {\r\n if (!$this->smtp->StartTLS()) {\r\n throw new phpmailerException($this->Lang('connect_host'));\r\n }\r\n //We must resend HELO after tls negotiation\r\n $this->smtp->Hello($hello);\r\n }\r\n if ($this->SMTPAuth) {\r\n if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, $this->Realm, $this->Workstation)) {\r\n throw new phpmailerException($this->Lang('authenticate'));\r\n }\r\n }\r\n return true;\r\n } catch (phpmailerException $e) {\r\n $lastexception = $e;\r\n //We must have connected, but then failed TLS or Auth, so close connection nicely\r\n $this->smtp->Quit();\r\n }\r\n }\r\n }\r\n //If we get here, all connection attempts have failed, so close connection hard\r\n $this->smtp->Close();\r\n //As we've caught all exceptions, just report whatever the last one was\r\n if ($this->exceptions and !is_null($lastexception)) {\r\n throw $lastexception;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Closes the active SMTP session if one exists.\r\n * @return void\r\n */\r\n public function SmtpClose() {\r\n if ($this->smtp !== null) {\r\n if($this->smtp->Connected()) {\r\n $this->smtp->Quit();\r\n $this->smtp->Close();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Sets the language for all class error messages.\r\n * Returns false if it cannot load the language file. The default language is English.\r\n * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: \"br\")\r\n * @param string $lang_path Path to the language file directory\r\n * @return bool\r\n * @access public\r\n */\r\n function SetLanguage($langcode = 'en', $lang_path = 'language/') {\r\n //Define full set of translatable strings\r\n $PHPMAILER_LANG = array(\r\n 'authenticate' => 'SMTP Error: Could not authenticate.',\r\n 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',\r\n 'data_not_accepted' => 'SMTP Error: Data not accepted.',\r\n 'empty_message' => 'Message body empty',\r\n 'encoding' => 'Unknown encoding: ',\r\n 'execute' => 'Could not execute: ',\r\n 'file_access' => 'Could not access file: ',\r\n 'file_open' => 'File Error: Could not open file: ',\r\n 'from_failed' => 'The following From address failed: ',\r\n 'instantiate' => 'Could not instantiate mail function.',\r\n 'invalid_address' => 'Invalid address',\r\n 'mailer_not_supported' => ' mailer is not supported.',\r\n 'provide_address' => 'You must provide at least one recipient email address.',\r\n 'recipients_failed' => 'SMTP Error: The following recipients failed: ',\r\n 'signing' => 'Signing Error: ',\r\n 'smtp_connect_failed' => 'SMTP Connect() failed.',\r\n 'smtp_error' => 'SMTP server error: ',\r\n 'variable_set' => 'Cannot set or reset variable: '\r\n );\r\n //Overwrite language-specific strings. This way we'll never have missing translations - no more \"language string failed to load\"!\r\n $l = true;\r\n if ($langcode != 'en') { //There is no English translation file\r\n $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';\r\n }\r\n $this->language = $PHPMAILER_LANG;\r\n return ($l == true); //Returns false if language not found\r\n }\r\n\r\n /**\r\n * Return the current array of language strings\r\n * @return array\r\n */\r\n public function GetTranslations() {\r\n return $this->language;\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // METHODS, MESSAGE CREATION\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Creates recipient headers.\r\n * @access public\r\n * @param string $type\r\n * @param array $addr\r\n * @return string\r\n */\r\n public function AddrAppend($type, $addr) {\r\n $addr_str = $type . ': ';\r\n $addresses = array();\r\n foreach ($addr as $a) {\r\n $addresses[] = $this->AddrFormat($a);\r\n }\r\n $addr_str .= implode(', ', $addresses);\r\n $addr_str .= $this->LE;\r\n\r\n return $addr_str;\r\n }\r\n\r\n /**\r\n * Formats an address correctly.\r\n * @access public\r\n * @param string $addr\r\n * @return string\r\n */\r\n public function AddrFormat($addr) {\r\n if (empty($addr[1])) {\r\n return $this->SecureHeader($addr[0]);\r\n } else {\r\n return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . \" <\" . $this->SecureHeader($addr[0]) . \">\";\r\n }\r\n }\r\n\r\n /**\r\n * Wraps message for use with mailers that do not\r\n * automatically perform wrapping and for quoted-printable.\r\n * Original written by philippe.\r\n * @param string $message The message to wrap\r\n * @param integer $length The line length to wrap to\r\n * @param boolean $qp_mode Whether to run in Quoted-Printable mode\r\n * @access public\r\n * @return string\r\n */\r\n public function WrapText($message, $length, $qp_mode = false) {\r\n $soft_break = ($qp_mode) ? sprintf(\" =%s\", $this->LE) : $this->LE;\r\n // If utf-8 encoding is used, we will need to make sure we don't\r\n // split multibyte characters when we wrap\r\n $is_utf8 = (strtolower($this->CharSet) == \"utf-8\");\r\n $lelen = strlen($this->LE);\r\n $crlflen = strlen(self::CRLF);\r\n\r\n $message = $this->FixEOL($message);\r\n if (substr($message, -$lelen) == $this->LE) {\r\n $message = substr($message, 0, -$lelen);\r\n }\r\n\r\n $line = explode($this->LE, $message); // Magic. We know FixEOL uses $LE\r\n $message = '';\r\n for ($i = 0 ;$i < count($line); $i++) {\r\n $line_part = explode(' ', $line[$i]);\r\n $buf = '';\r\n for ($e = 0; $e $length)) {\r\n $space_left = $length - strlen($buf) - $crlflen;\r\n if ($e != 0) {\r\n if ($space_left > 20) {\r\n $len = $space_left;\r\n if ($is_utf8) {\r\n $len = $this->UTF8CharBoundary($word, $len);\r\n } elseif (substr($word, $len - 1, 1) == \"=\") {\r\n $len--;\r\n } elseif (substr($word, $len - 2, 1) == \"=\") {\r\n $len -= 2;\r\n }\r\n $part = substr($word, 0, $len);\r\n $word = substr($word, $len);\r\n $buf .= ' ' . $part;\r\n $message .= $buf . sprintf(\"=%s\", self::CRLF);\r\n } else {\r\n $message .= $buf . $soft_break;\r\n }\r\n $buf = '';\r\n }\r\n while (strlen($word) > 0) {\r\n if ($length <= 0) {\r\n break;\r\n }\r\n $len = $length;\r\n if ($is_utf8) {\r\n $len = $this->UTF8CharBoundary($word, $len);\r\n } elseif (substr($word, $len - 1, 1) == \"=\") {\r\n $len--;\r\n } elseif (substr($word, $len - 2, 1) == \"=\") {\r\n $len -= 2;\r\n }\r\n $part = substr($word, 0, $len);\r\n $word = substr($word, $len);\r\n\r\n if (strlen($word) > 0) {\r\n $message .= $part . sprintf(\"=%s\", self::CRLF);\r\n } else {\r\n $buf = $part;\r\n }\r\n }\r\n } else {\r\n $buf_o = $buf;\r\n $buf .= ($e == 0) ? $word : (' ' . $word);\r\n\r\n if (strlen($buf) > $length and $buf_o != '') {\r\n $message .= $buf_o . $soft_break;\r\n $buf = $word;\r\n }\r\n }\r\n }\r\n $message .= $buf . self::CRLF;\r\n }\r\n\r\n return $message;\r\n }\r\n\r\n /**\r\n * Finds last character boundary prior to maxLength in a utf-8\r\n * quoted (printable) encoded string.\r\n * Original written by Colin Brown.\r\n * @access public\r\n * @param string $encodedText utf-8 QP text\r\n * @param int $maxLength find last character boundary prior to this length\r\n * @return int\r\n */\r\n public function UTF8CharBoundary($encodedText, $maxLength) {\r\n $foundSplitPos = false;\r\n $lookBack = 3;\r\n while (!$foundSplitPos) {\r\n $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);\r\n $encodedCharPos = strpos($lastChunk, \"=\");\r\n if ($encodedCharPos !== false) {\r\n // Found start of encoded character byte within $lookBack block.\r\n // Check the encoded byte value (the 2 chars after the '=')\r\n $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);\r\n $dec = hexdec($hex);\r\n if ($dec < 128) { // Single byte character.\r\n // If the encoded char was found at pos 0, it will fit\r\n // otherwise reduce maxLength to start of the encoded char\r\n $maxLength = ($encodedCharPos == 0) ? $maxLength :\r\n $maxLength - ($lookBack - $encodedCharPos);\r\n $foundSplitPos = true;\r\n } elseif ($dec >= 192) { // First byte of a multi byte character\r\n // Reduce maxLength to split at start of character\r\n $maxLength = $maxLength - ($lookBack - $encodedCharPos);\r\n $foundSplitPos = true;\r\n } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back\r\n $lookBack += 3;\r\n }\r\n } else {\r\n // No encoded character found\r\n $foundSplitPos = true;\r\n }\r\n }\r\n return $maxLength;\r\n }\r\n\r\n\r\n /**\r\n * Set the body wrapping.\r\n * @access public\r\n * @return void\r\n */\r\n public function SetWordWrap() {\r\n if($this->WordWrap < 1) {\r\n return;\r\n }\r\n\r\n switch($this->message_type) {\r\n case 'alt':\r\n case 'alt_inline':\r\n case 'alt_attach':\r\n case 'alt_inline_attach':\r\n $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);\r\n break;\r\n default:\r\n $this->Body = $this->WrapText($this->Body, $this->WordWrap);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Assembles message header.\r\n * @access public\r\n * @return string The assembled header\r\n */\r\n public function CreateHeader() {\r\n $result = '';\r\n\r\n // Set the boundaries\r\n $uniq_id = md5(uniqid(time()));\r\n $this->boundary[1] = 'b1_' . $uniq_id;\r\n $this->boundary[2] = 'b2_' . $uniq_id;\r\n $this->boundary[3] = 'b3_' . $uniq_id;\r\n\r\n if ($this->MessageDate == '') {\r\n $result .= $this->HeaderLine('Date', self::RFCDate());\r\n } else {\r\n $result .= $this->HeaderLine('Date', $this->MessageDate);\r\n }\r\n\r\n if ($this->ReturnPath) {\r\n $result .= $this->HeaderLine('Return-Path', '<'.trim($this->ReturnPath).'>');\r\n } elseif ($this->Sender == '') {\r\n $result .= $this->HeaderLine('Return-Path', '<'.trim($this->From).'>');\r\n } else {\r\n $result .= $this->HeaderLine('Return-Path', '<'.trim($this->Sender).'>');\r\n }\r\n\r\n // To be created automatically by mail()\r\n if($this->Mailer != 'mail') {\r\n if ($this->SingleTo === true) {\r\n foreach($this->to as $t) {\r\n $this->SingleToArray[] = $this->AddrFormat($t);\r\n }\r\n } else {\r\n if(count($this->to) > 0) {\r\n $result .= $this->AddrAppend('To', $this->to);\r\n } elseif (count($this->cc) == 0) {\r\n $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');\r\n }\r\n }\r\n }\r\n\r\n $from = array();\r\n $from[0][0] = trim($this->From);\r\n $from[0][1] = $this->FromName;\r\n $result .= $this->AddrAppend('From', $from);\r\n\r\n // sendmail and mail() extract Cc from the header before sending\r\n if(count($this->cc) > 0) {\r\n $result .= $this->AddrAppend('Cc', $this->cc);\r\n }\r\n\r\n // sendmail and mail() extract Bcc from the header before sending\r\n if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {\r\n $result .= $this->AddrAppend('Bcc', $this->bcc);\r\n }\r\n\r\n if(count($this->ReplyTo) > 0) {\r\n $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);\r\n }\r\n\r\n // mail() sets the subject itself\r\n if($this->Mailer != 'mail') {\r\n $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));\r\n }\r\n\r\n if($this->MessageID != '') {\r\n $result .= $this->HeaderLine('Message-ID', $this->MessageID);\r\n } else {\r\n $result .= sprintf(\"Message-ID: <%s@%s>%s\", $uniq_id, $this->ServerHostname(), $this->LE);\r\n }\r\n $result .= $this->HeaderLine('X-Priority', $this->Priority);\r\n if ($this->XMailer == '') {\r\n $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (https://github.com/PHPMailer/PHPMailer/)');\r\n } else {\r\n $myXmailer = trim($this->XMailer);\r\n if ($myXmailer) {\r\n $result .= $this->HeaderLine('X-Mailer', $myXmailer);\r\n }\r\n }\r\n\r\n if($this->ConfirmReadingTo != '') {\r\n $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');\r\n }\r\n\r\n // Add custom headers\r\n for($index = 0; $index < count($this->CustomHeader); $index++) {\r\n $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));\r\n }\r\n if (!$this->sign_key_file) {\r\n $result .= $this->HeaderLine('MIME-Version', '1.0');\r\n $result .= $this->GetMailMIME();\r\n }\r\n\r\n return $result;\r\n }\r\n\r\n /**\r\n * Returns the message MIME.\r\n * @access public\r\n * @return string\r\n */\r\n public function GetMailMIME() {\r\n $result = '';\r\n switch($this->message_type) {\r\n case 'inline':\r\n $result .= $this->HeaderLine('Content-Type', 'multipart/related;');\r\n $result .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[1].'\"');\r\n break;\r\n case 'attach':\r\n case 'inline_attach':\r\n case 'alt_attach':\r\n case 'alt_inline_attach':\r\n $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');\r\n $result .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[1].'\"');\r\n break;\r\n case 'alt':\r\n case 'alt_inline':\r\n $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');\r\n $result .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[1].'\"');\r\n break;\r\n default:\r\n // Catches case 'plain': and case '':\r\n $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset='.$this->CharSet);\r\n break;\r\n }\r\n //RFC1341 part 5 says 7bit is assumed if not specified\r\n if ($this->Encoding != '7bit') {\r\n $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);\r\n }\r\n\r\n if($this->Mailer != 'mail') {\r\n $result .= $this->LE;\r\n }\r\n\r\n return $result;\r\n }\r\n\r\n /**\r\n * Returns the MIME message (headers and body). Only really valid post PreSend().\r\n * @access public\r\n * @return string\r\n */\r\n public function GetSentMIMEMessage() {\r\n return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;\r\n }\r\n\r\n\r\n /**\r\n * Assembles the message body. Returns an empty string on failure.\r\n * @access public\r\n * @throws phpmailerException\r\n * @return string The assembled message body\r\n */\r\n public function CreateBody() {\r\n $body = '';\r\n\r\n if ($this->sign_key_file) {\r\n $body .= $this->GetMailMIME().$this->LE;\r\n }\r\n\r\n $this->SetWordWrap();\r\n\r\n switch($this->message_type) {\r\n case 'inline':\r\n $body .= $this->GetBoundary($this->boundary[1], '', '', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->AttachAll('inline', $this->boundary[1]);\r\n break;\r\n case 'attach':\r\n $body .= $this->GetBoundary($this->boundary[1], '', '', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->AttachAll('attachment', $this->boundary[1]);\r\n break;\r\n case 'inline_attach':\r\n $body .= $this->TextLine('--' . $this->boundary[1]);\r\n $body .= $this->HeaderLine('Content-Type', 'multipart/related;');\r\n $body .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[2].'\"');\r\n $body .= $this->LE;\r\n $body .= $this->GetBoundary($this->boundary[2], '', '', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->AttachAll('inline', $this->boundary[2]);\r\n $body .= $this->LE;\r\n $body .= $this->AttachAll('attachment', $this->boundary[1]);\r\n break;\r\n case 'alt':\r\n $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');\r\n $body .= $this->EncodeString($this->AltBody, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n if(!empty($this->Ical)) {\r\n $body .= $this->GetBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');\r\n $body .= $this->EncodeString($this->Ical, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n }\r\n $body .= $this->EndBoundary($this->boundary[1]);\r\n break;\r\n case 'alt_inline':\r\n $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');\r\n $body .= $this->EncodeString($this->AltBody, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->TextLine('--' . $this->boundary[1]);\r\n $body .= $this->HeaderLine('Content-Type', 'multipart/related;');\r\n $body .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[2].'\"');\r\n $body .= $this->LE;\r\n $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->AttachAll('inline', $this->boundary[2]);\r\n $body .= $this->LE;\r\n $body .= $this->EndBoundary($this->boundary[1]);\r\n break;\r\n case 'alt_attach':\r\n $body .= $this->TextLine('--' . $this->boundary[1]);\r\n $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');\r\n $body .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[2].'\"');\r\n $body .= $this->LE;\r\n $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');\r\n $body .= $this->EncodeString($this->AltBody, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->EndBoundary($this->boundary[2]);\r\n $body .= $this->LE;\r\n $body .= $this->AttachAll('attachment', $this->boundary[1]);\r\n break;\r\n case 'alt_inline_attach':\r\n $body .= $this->TextLine('--' . $this->boundary[1]);\r\n $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');\r\n $body .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[2].'\"');\r\n $body .= $this->LE;\r\n $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');\r\n $body .= $this->EncodeString($this->AltBody, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->TextLine('--' . $this->boundary[2]);\r\n $body .= $this->HeaderLine('Content-Type', 'multipart/related;');\r\n $body .= $this->TextLine(\"\\tboundary=\\\"\" . $this->boundary[3].'\"');\r\n $body .= $this->LE;\r\n $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n $body .= $this->LE.$this->LE;\r\n $body .= $this->AttachAll('inline', $this->boundary[3]);\r\n $body .= $this->LE;\r\n $body .= $this->EndBoundary($this->boundary[2]);\r\n $body .= $this->LE;\r\n $body .= $this->AttachAll('attachment', $this->boundary[1]);\r\n break;\r\n default:\r\n // catch case 'plain' and case ''\r\n $body .= $this->EncodeString($this->Body, $this->Encoding);\r\n break;\r\n }\r\n\r\n if ($this->IsError()) {\r\n $body = '';\r\n } elseif ($this->sign_key_file) {\r\n try {\r\n if (!defined('PKCS7_TEXT')) {\r\n throw new phpmailerException($this->Lang('signing').' OpenSSL extension missing.');\r\n }\r\n $file = tempnam(sys_get_temp_dir(), 'mail');\r\n file_put_contents($file, $body); //TODO check this worked\r\n $signed = tempnam(sys_get_temp_dir(), 'signed');\r\n if (@openssl_pkcs7_sign($file, $signed, 'file://'.realpath($this->sign_cert_file), array('file://'.realpath($this->sign_key_file), $this->sign_key_pass), null)) {\r\n @unlink($file);\r\n $body = file_get_contents($signed);\r\n @unlink($signed);\r\n } else {\r\n @unlink($file);\r\n @unlink($signed);\r\n throw new phpmailerException($this->Lang('signing').openssl_error_string());\r\n }\r\n } catch (phpmailerException $e) {\r\n $body = '';\r\n if ($this->exceptions) {\r\n throw $e;\r\n }\r\n }\r\n }\r\n return $body;\r\n }\r\n\r\n /**\r\n * Returns the start of a message boundary.\r\n * @access protected\r\n * @param string $boundary\r\n * @param string $charSet\r\n * @param string $contentType\r\n * @param string $encoding\r\n * @return string\r\n */\r\n protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {\r\n $result = '';\r\n if($charSet == '') {\r\n $charSet = $this->CharSet;\r\n }\r\n if($contentType == '') {\r\n $contentType = $this->ContentType;\r\n }\r\n if($encoding == '') {\r\n $encoding = $this->Encoding;\r\n }\r\n $result .= $this->TextLine('--' . $boundary);\r\n $result .= sprintf(\"Content-Type: %s; charset=%s\", $contentType, $charSet);\r\n $result .= $this->LE;\r\n $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);\r\n $result .= $this->LE;\r\n\r\n return $result;\r\n }\r\n\r\n /**\r\n * Returns the end of a message boundary.\r\n * @access protected\r\n * @param string $boundary\r\n * @return string\r\n */\r\n protected function EndBoundary($boundary) {\r\n return $this->LE . '--' . $boundary . '--' . $this->LE;\r\n }\r\n\r\n /**\r\n * Sets the message type.\r\n * @access protected\r\n * @return void\r\n */\r\n protected function SetMessageType() {\r\n $this->message_type = array();\r\n if($this->AlternativeExists()) $this->message_type[] = \"alt\";\r\n if($this->InlineImageExists()) $this->message_type[] = \"inline\";\r\n if($this->AttachmentExists()) $this->message_type[] = \"attach\";\r\n $this->message_type = implode(\"_\", $this->message_type);\r\n if($this->message_type == \"\") $this->message_type = \"plain\";\r\n }\r\n\r\n /**\r\n * Returns a formatted header line.\r\n * @access public\r\n * @param string $name\r\n * @param string $value\r\n * @return string\r\n */\r\n public function HeaderLine($name, $value) {\r\n return $name . ': ' . $value . $this->LE;\r\n }\r\n\r\n /**\r\n * Returns a formatted mail line.\r\n * @access public\r\n * @param string $value\r\n * @return string\r\n */\r\n public function TextLine($value) {\r\n return $value . $this->LE;\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // CLASS METHODS, ATTACHMENTS\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Adds an attachment from a path on the filesystem.\r\n * Returns false if the file could not be found\r\n * or accessed.\r\n * @param string $path Path to the attachment.\r\n * @param string $name Overrides the attachment name.\r\n * @param string $encoding File encoding (see $Encoding).\r\n * @param string $type File extension (MIME) type.\r\n * @param string $disposition Disposition to use\r\n * @throws phpmailerException\r\n * @return bool\r\n */\r\n public function AddAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') {\r\n try {\r\n if ( !@is_file($path) ) {\r\n throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);\r\n }\r\n\r\n //If a MIME type is not specified, try to work it out from the file name\r\n if ($type == '') {\r\n $type = self::filenameToType($path);\r\n }\r\n\r\n $filename = basename($path);\r\n if ( $name == '' ) {\r\n $name = $filename;\r\n }\r\n\r\n $this->attachment[] = array(\r\n 0 => $path,\r\n 1 => $filename,\r\n 2 => $name,\r\n 3 => $encoding,\r\n 4 => $type,\r\n 5 => false, // isStringAttachment\r\n 6 => $disposition,\r\n 7 => 0\r\n );\r\n\r\n } catch (phpmailerException $e) {\r\n $this->SetError($e->getMessage());\r\n if ($this->exceptions) {\r\n throw $e;\r\n }\r\n $this->edebug($e->getMessage().\"\\n\");\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Return the current array of attachments\r\n * @return array\r\n */\r\n public function GetAttachments() {\r\n return $this->attachment;\r\n }\r\n\r\n /**\r\n * Attaches all fs, string, and binary attachments to the message.\r\n * Returns an empty string on failure.\r\n * @access protected\r\n * @param string $disposition_type\r\n * @param string $boundary\r\n * @return string\r\n */\r\n protected function AttachAll($disposition_type, $boundary) {\r\n // Return text of body\r\n $mime = array();\r\n $cidUniq = array();\r\n $incl = array();\r\n\r\n // Add all attachments\r\n foreach ($this->attachment as $attachment) {\r\n // CHECK IF IT IS A VALID DISPOSITION_FILTER\r\n if($attachment[6] == $disposition_type) {\r\n // Check for string attachment\r\n $string = '';\r\n $path = '';\r\n $bString = $attachment[5];\r\n if ($bString) {\r\n $string = $attachment[0];\r\n } else {\r\n $path = $attachment[0];\r\n }\r\n\r\n $inclhash = md5(serialize($attachment));\r\n if (in_array($inclhash, $incl)) { continue; }\r\n $incl[] = $inclhash;\r\n $filename = $attachment[1];\r\n $name = $attachment[2];\r\n $encoding = $attachment[3];\r\n $type = $attachment[4];\r\n $disposition = $attachment[6];\r\n $cid = $attachment[7];\r\n if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }\r\n $cidUniq[$cid] = true;\r\n\r\n $mime[] = sprintf(\"--%s%s\", $boundary, $this->LE);\r\n $mime[] = sprintf(\"Content-Type: %s; name=\\\"%s\\\"%s\", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);\r\n $mime[] = sprintf(\"Content-Transfer-Encoding: %s%s\", $encoding, $this->LE);\r\n\r\n if($disposition == 'inline') {\r\n $mime[] = sprintf(\"Content-ID: <%s>%s\", $cid, $this->LE);\r\n }\r\n\r\n //If a filename contains any of these chars, it should be quoted, but not otherwise: RFC2183 & RFC2045 5.1\r\n //Fixes a warning in IETF's msglint MIME checker\r\n //\r\n // Allow for bypassing the Content-Disposition header totally\r\n if (!(empty($disposition))) {\r\n if (preg_match('/[ \\(\\)<>@,;:\\\\\"\\/\\[\\]\\?=]/', $name)) {\r\n $mime[] = sprintf(\"Content-Disposition: %s; filename=\\\"%s\\\"%s\", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);\r\n } else {\r\n $mime[] = sprintf(\"Content-Disposition: %s; filename=%s%s\", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);\r\n }\r\n } else {\r\n $mime[] = $this->LE;\r\n }\r\n\r\n // Encode as string attachment\r\n if($bString) {\r\n $mime[] = $this->EncodeString($string, $encoding);\r\n if($this->IsError()) {\r\n return '';\r\n }\r\n $mime[] = $this->LE.$this->LE;\r\n } else {\r\n $mime[] = $this->EncodeFile($path, $encoding);\r\n if($this->IsError()) {\r\n return '';\r\n }\r\n $mime[] = $this->LE.$this->LE;\r\n }\r\n }\r\n }\r\n\r\n $mime[] = sprintf(\"--%s--%s\", $boundary, $this->LE);\r\n\r\n return implode(\"\", $mime);\r\n }\r\n\r\n /**\r\n * Encodes attachment in requested format.\r\n * Returns an empty string on failure.\r\n * @param string $path The full path to the file\r\n * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'\r\n * @throws phpmailerException\r\n * @see EncodeFile()\r\n * @access protected\r\n * @return string\r\n */\r\n protected function EncodeFile($path, $encoding = 'base64') {\r\n try {\r\n if (!is_readable($path)) {\r\n throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);\r\n }\r\n $magic_quotes = get_magic_quotes_runtime();\r\n if ($magic_quotes) {\r\n if (version_compare(PHP_VERSION, '5.3.0', '<')) {\r\n set_magic_quotes_runtime(0);\r\n } else {\r\n ini_set('magic_quotes_runtime', 0);\r\n }\r\n }\r\n $file_buffer = file_get_contents($path);\r\n $file_buffer = $this->EncodeString($file_buffer, $encoding);\r\n if ($magic_quotes) {\r\n if (version_compare(PHP_VERSION, '5.3.0', '<')) {\r\n set_magic_quotes_runtime($magic_quotes);\r\n } else {\r\n ini_set('magic_quotes_runtime', $magic_quotes);\r\n }\r\n }\r\n return $file_buffer;\r\n } catch (Exception $e) {\r\n $this->SetError($e->getMessage());\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Encodes string to requested format.\r\n * Returns an empty string on failure.\r\n * @param string $str The text to encode\r\n * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'\r\n * @access public\r\n * @return string\r\n */\r\n public function EncodeString($str, $encoding = 'base64') {\r\n $encoded = '';\r\n switch(strtolower($encoding)) {\r\n case 'base64':\r\n $encoded = chunk_split(base64_encode($str), 76, $this->LE);\r\n break;\r\n case '7bit':\r\n case '8bit':\r\n $encoded = $this->FixEOL($str);\r\n //Make sure it ends with a line break\r\n if (substr($encoded, -(strlen($this->LE))) != $this->LE)\r\n $encoded .= $this->LE;\r\n break;\r\n case 'binary':\r\n $encoded = $str;\r\n break;\r\n case 'quoted-printable':\r\n $encoded = $this->EncodeQP($str);\r\n break;\r\n default:\r\n $this->SetError($this->Lang('encoding') . $encoding);\r\n break;\r\n }\r\n return $encoded;\r\n }\r\n\r\n /**\r\n * Encode a header string to best (shortest) of Q, B, quoted or none.\r\n * @access public\r\n * @param string $str\r\n * @param string $position\r\n * @return string\r\n */\r\n public function EncodeHeader($str, $position = 'text') {\r\n $x = 0;\r\n\r\n switch (strtolower($position)) {\r\n case 'phrase':\r\n if (!preg_match('/[\\200-\\377]/', $str)) {\r\n // Can't use addslashes as we don't know what value has magic_quotes_sybase\r\n $encoded = addcslashes($str, \"\\0..\\37\\177\\\\\\\"\");\r\n if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\\'*+\\/=?^_`{|}~ -]/', $str)) {\r\n return ($encoded);\r\n } else {\r\n return (\"\\\"$encoded\\\"\");\r\n }\r\n }\r\n $x = preg_match_all('/[^\\040\\041\\043-\\133\\135-\\176]/', $str, $matches);\r\n break;\r\n case 'comment':\r\n $x = preg_match_all('/[()\"]/', $str, $matches);\r\n // Fall-through\r\n case 'text':\r\n default:\r\n $x += preg_match_all('/[\\000-\\010\\013\\014\\016-\\037\\177-\\377]/', $str, $matches);\r\n break;\r\n }\r\n\r\n if ($x == 0) { //There are no chars that need encoding\r\n return ($str);\r\n }\r\n\r\n $maxlen = 75 - 7 - strlen($this->CharSet);\r\n // Try to select the encoding which should produce the shortest output\r\n if ($x > strlen($str)/3) { //More than a third of the content will need encoding, so B encoding will be most efficient\r\n $encoding = 'B';\r\n if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {\r\n // Use a custom function which correctly encodes and wraps long\r\n // multibyte strings without breaking lines within a character\r\n $encoded = $this->Base64EncodeWrapMB($str, \"\\n\");\r\n } else {\r\n $encoded = base64_encode($str);\r\n $maxlen -= $maxlen % 4;\r\n $encoded = trim(chunk_split($encoded, $maxlen, \"\\n\"));\r\n }\r\n } else {\r\n $encoding = 'Q';\r\n $encoded = $this->EncodeQ($str, $position);\r\n $encoded = $this->WrapText($encoded, $maxlen, true);\r\n $encoded = str_replace('='.self::CRLF, \"\\n\", trim($encoded));\r\n }\r\n\r\n $encoded = preg_replace('/^(.*)$/m', \" =?\".$this->CharSet.\"?$encoding?\\\\1?=\", $encoded);\r\n $encoded = trim(str_replace(\"\\n\", $this->LE, $encoded));\r\n\r\n return $encoded;\r\n }\r\n\r\n /**\r\n * Checks if a string contains multibyte characters.\r\n * @access public\r\n * @param string $str multi-byte text to wrap encode\r\n * @return bool\r\n */\r\n public function HasMultiBytes($str) {\r\n if (function_exists('mb_strlen')) {\r\n return (strlen($str) > mb_strlen($str, $this->CharSet));\r\n } else { // Assume no multibytes (we can't handle without mbstring functions anyway)\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Correctly encodes and wraps long multibyte strings for mail headers\r\n * without breaking lines within a character.\r\n * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php\r\n * @access public\r\n * @param string $str multi-byte text to wrap encode\r\n * @param string $lf string to use as linefeed/end-of-line\r\n * @return string\r\n */\r\n public function Base64EncodeWrapMB($str, $lf=null) {\r\n $start = \"=?\".$this->CharSet.\"?B?\";\r\n $end = \"?=\";\r\n $encoded = \"\";\r\n if ($lf === null) {\r\n $lf = $this->LE;\r\n }\r\n\r\n $mb_length = mb_strlen($str, $this->CharSet);\r\n // Each line must have length <= 75, including $start and $end\r\n $length = 75 - strlen($start) - strlen($end);\r\n // Average multi-byte ratio\r\n $ratio = $mb_length / strlen($str);\r\n // Base64 has a 4:3 ratio\r\n $offset = $avgLength = floor($length * $ratio * .75);\r\n\r\n for ($i = 0; $i < $mb_length; $i += $offset) {\r\n $lookBack = 0;\r\n\r\n do {\r\n $offset = $avgLength - $lookBack;\r\n $chunk = mb_substr($str, $i, $offset, $this->CharSet);\r\n $chunk = base64_encode($chunk);\r\n $lookBack++;\r\n }\r\n while (strlen($chunk) > $length);\r\n\r\n $encoded .= $chunk . $lf;\r\n }\r\n\r\n // Chomp the last linefeed\r\n $encoded = substr($encoded, 0, -strlen($lf));\r\n return $encoded;\r\n }\r\n\r\n /**\r\n * Encode string to RFC2045 (6.7) quoted-printable format\r\n * @access public\r\n * @param string $string The text to encode\r\n * @param integer $line_max Number of chars allowed on a line before wrapping\r\n * @return string\r\n * @link PHP version adapted from http://www.php.net/manual/en/function.quoted-printable-decode.php#89417\r\n */\r\n public function EncodeQP($string, $line_max = 76) {\r\n if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)\r\n return quoted_printable_encode($string);\r\n }\r\n //Fall back to a pure PHP implementation\r\n $string = str_replace(array('%20', '%0D%0A.', '%0D%0A', '%'), array(' ', \"\\r\\n=2E\", \"\\r\\n\", '='), rawurlencode($string));\r\n $string = preg_replace('/[^\\r\\n]{'.($line_max - 3).'}[^=\\r\\n]{2}/', \"$0=\\r\\n\", $string);\r\n return $string;\r\n }\r\n\r\n /**\r\n * Wrapper to preserve BC for old QP encoding function that was removed\r\n * @see EncodeQP()\r\n * @access public\r\n * @param string $string\r\n * @param integer $line_max\r\n * @param bool $space_conv\r\n * @return string\r\n */\r\n public function EncodeQPphp($string, $line_max = 76, $space_conv = false) {\r\n return $this->EncodeQP($string, $line_max);\r\n }\r\n\r\n /**\r\n * Encode string to q encoding.\r\n * @link http://tools.ietf.org/html/rfc2047\r\n * @param string $str the text to encode\r\n * @param string $position Where the text is going to be used, see the RFC for what that means\r\n * @access public\r\n * @return string\r\n */\r\n public function EncodeQ($str, $position = 'text') {\r\n //There should not be any EOL in the string\r\n $pattern = '';\r\n $encoded = str_replace(array(\"\\r\", \"\\n\"), '', $str);\r\n switch (strtolower($position)) {\r\n case 'phrase':\r\n $pattern = '^A-Za-z0-9!*+\\/ -';\r\n break;\r\n\r\n case 'comment':\r\n $pattern = '\\(\\)\"';\r\n //note that we don't break here!\r\n //for this reason we build the $pattern without including delimiters and []\r\n\r\n case 'text':\r\n default:\r\n //Replace every high ascii, control =, ? and _ characters\r\n //We put \\075 (=) as first value to make sure it's the first one in being converted, preventing double encode\r\n $pattern = '\\075\\000-\\011\\013\\014\\016-\\037\\077\\137\\177-\\377' . $pattern;\r\n break;\r\n }\r\n\r\n if (preg_match_all(\"/[{$pattern}]/\", $encoded, $matches)) {\r\n foreach (array_unique($matches[0]) as $char) {\r\n $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);\r\n }\r\n }\r\n\r\n //Replace every spaces to _ (more readable than =20)\r\n return str_replace(' ', '_', $encoded);\r\n}\r\n\r\n\r\n /**\r\n * Adds a string or binary attachment (non-filesystem) to the list.\r\n * This method can be used to attach ascii or binary data,\r\n * such as a BLOB record from a database.\r\n * @param string $string String attachment data.\r\n * @param string $filename Name of the attachment.\r\n * @param string $encoding File encoding (see $Encoding).\r\n * @param string $type File extension (MIME) type.\r\n * @param string $disposition Disposition to use\r\n * @return void\r\n */\r\n public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = '', $disposition = 'attachment') {\r\n //If a MIME type is not specified, try to work it out from the file name\r\n if ($type == '') {\r\n $type = self::filenameToType($filename);\r\n }\r\n // Append to $attachment array\r\n $this->attachment[] = array(\r\n 0 => $string,\r\n 1 => $filename,\r\n 2 => basename($filename),\r\n 3 => $encoding,\r\n 4 => $type,\r\n 5 => true, // isStringAttachment\r\n 6 => $disposition,\r\n 7 => 0\r\n );\r\n }\r\n\r\n /**\r\n * Add an embedded attachment from a file.\r\n * This can include images, sounds, and just about any other document type.\r\n * @param string $path Path to the attachment.\r\n * @param string $cid Content ID of the attachment; Use this to reference\r\n * the content when using an embedded image in HTML.\r\n * @param string $name Overrides the attachment name.\r\n * @param string $encoding File encoding (see $Encoding).\r\n * @param string $type File MIME type.\r\n * @param string $disposition Disposition to use\r\n * @return bool True on successfully adding an attachment\r\n */\r\n public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') {\r\n if ( !@is_file($path) ) {\r\n $this->SetError($this->Lang('file_access') . $path);\r\n return false;\r\n }\r\n\r\n //If a MIME type is not specified, try to work it out from the file name\r\n if ($type == '') {\r\n $type = self::filenameToType($path);\r\n }\r\n\r\n $filename = basename($path);\r\n if ( $name == '' ) {\r\n $name = $filename;\r\n }\r\n\r\n // Append to $attachment array\r\n $this->attachment[] = array(\r\n 0 => $path,\r\n 1 => $filename,\r\n 2 => $name,\r\n 3 => $encoding,\r\n 4 => $type,\r\n 5 => false, // isStringAttachment\r\n 6 => $disposition,\r\n 7 => $cid\r\n );\r\n return true;\r\n }\r\n\r\n\r\n /**\r\n * Add an embedded stringified attachment.\r\n * This can include images, sounds, and just about any other document type.\r\n * Be sure to set the $type to an image type for images:\r\n * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.\r\n * @param string $string The attachment binary data.\r\n * @param string $cid Content ID of the attachment; Use this to reference\r\n * the content when using an embedded image in HTML.\r\n * @param string $name\r\n * @param string $encoding File encoding (see $Encoding).\r\n * @param string $type MIME type.\r\n * @param string $disposition Disposition to use\r\n * @return bool True on successfully adding an attachment\r\n */\r\n public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') {\r\n //If a MIME type is not specified, try to work it out from the name\r\n if ($type == '') {\r\n $type = self::filenameToType($name);\r\n }\r\n\r\n // Append to $attachment array\r\n $this->attachment[] = array(\r\n 0 => $string,\r\n 1 => $name,\r\n 2 => $name,\r\n 3 => $encoding,\r\n 4 => $type,\r\n 5 => true, // isStringAttachment\r\n 6 => $disposition,\r\n 7 => $cid\r\n );\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns true if an inline attachment is present.\r\n * @access public\r\n * @return bool\r\n */\r\n public function InlineImageExists() {\r\n foreach($this->attachment as $attachment) {\r\n if ($attachment[6] == 'inline') {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns true if an attachment (non-inline) is present.\r\n * @return bool\r\n */\r\n public function AttachmentExists() {\r\n foreach($this->attachment as $attachment) {\r\n if ($attachment[6] == 'attachment') {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Does this message have an alternative body set?\r\n * @return bool\r\n */\r\n public function AlternativeExists() {\r\n return !empty($this->AltBody);\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // CLASS METHODS, MESSAGE RESET\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Clears all recipients assigned in the TO array. Returns void.\r\n * @return void\r\n */\r\n public function ClearAddresses() {\r\n foreach($this->to as $to) {\r\n unset($this->all_recipients[strtolower($to[0])]);\r\n }\r\n $this->to = array();\r\n }\r\n\r\n /**\r\n * Clears all recipients assigned in the CC array. Returns void.\r\n * @return void\r\n */\r\n public function ClearCCs() {\r\n foreach($this->cc as $cc) {\r\n unset($this->all_recipients[strtolower($cc[0])]);\r\n }\r\n $this->cc = array();\r\n }\r\n\r\n /**\r\n * Clears all recipients assigned in the BCC array. Returns void.\r\n * @return void\r\n */\r\n public function ClearBCCs() {\r\n foreach($this->bcc as $bcc) {\r\n unset($this->all_recipients[strtolower($bcc[0])]);\r\n }\r\n $this->bcc = array();\r\n }\r\n\r\n /**\r\n * Clears all recipients assigned in the ReplyTo array. Returns void.\r\n * @return void\r\n */\r\n public function ClearReplyTos() {\r\n $this->ReplyTo = array();\r\n }\r\n\r\n /**\r\n * Clears all recipients assigned in the TO, CC and BCC\r\n * array. Returns void.\r\n * @return void\r\n */\r\n public function ClearAllRecipients() {\r\n $this->to = array();\r\n $this->cc = array();\r\n $this->bcc = array();\r\n $this->all_recipients = array();\r\n }\r\n\r\n /**\r\n * Clears all previously set filesystem, string, and binary\r\n * attachments. Returns void.\r\n * @return void\r\n */\r\n public function ClearAttachments() {\r\n $this->attachment = array();\r\n }\r\n\r\n /**\r\n * Clears all custom headers. Returns void.\r\n * @return void\r\n */\r\n public function ClearCustomHeaders() {\r\n $this->CustomHeader = array();\r\n }\r\n\r\n /////////////////////////////////////////////////\r\n // CLASS METHODS, MISCELLANEOUS\r\n /////////////////////////////////////////////////\r\n\r\n /**\r\n * Adds the error message to the error container.\r\n * @access protected\r\n * @param string $msg\r\n * @return void\r\n */\r\n protected function SetError($msg) {\r\n $this->error_count++;\r\n if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {\r\n $lasterror = $this->smtp->getError();\r\n if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {\r\n $msg .= '

' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . \"

\\n\";\r\n }\r\n }\r\n $this->ErrorInfo = $msg;\r\n }\r\n\r\n /**\r\n * Returns the proper RFC 822 formatted date.\r\n * @access public\r\n * @return string\r\n * @static\r\n */\r\n public static function RFCDate() {\r\n //Set the time zone to whatever the default is to avoid 500 errors\r\n //Will default to UTC if it's not set properly in php.ini\r\n date_default_timezone_set(@date_default_timezone_get());\r\n return date('D, j M Y H:i:s O');\r\n }\r\n\r\n /**\r\n * Returns the server hostname or 'localhost.localdomain' if unknown.\r\n * @access protected\r\n * @return string\r\n */\r\n protected function ServerHostname() {\r\n if (!empty($this->Hostname)) {\r\n $result = $this->Hostname;\r\n } elseif (isset($_SERVER['SERVER_NAME'])) {\r\n $result = $_SERVER['SERVER_NAME'];\r\n } else {\r\n $result = 'localhost.localdomain';\r\n }\r\n\r\n return $result;\r\n }\r\n\r\n /**\r\n * Returns a message in the appropriate language.\r\n * @access protected\r\n * @param string $key\r\n * @return string\r\n */\r\n protected function Lang($key) {\r\n if(count($this->language) < 1) {\r\n $this->SetLanguage('en'); // set the default language\r\n }\r\n\r\n if(isset($this->language[$key])) {\r\n return $this->language[$key];\r\n } else {\r\n return 'Language string failed to load: ' . $key;\r\n }\r\n }\r\n\r\n /**\r\n * Returns true if an error occurred.\r\n * @access public\r\n * @return bool\r\n */\r\n public function IsError() {\r\n return ($this->error_count > 0);\r\n }\r\n\r\n /**\r\n * Changes every end of line from CRLF, CR or LF to $this->LE.\r\n * @access public\r\n * @param string $str String to FixEOL\r\n * @return string\r\n */\r\n public function FixEOL($str) {\r\n\t// condense down to \\n\r\n\t$nstr = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\r\n\t// Now convert LE as needed\r\n\tif ($this->LE !== \"\\n\") {\r\n\t\t$nstr = str_replace(\"\\n\", $this->LE, $nstr);\r\n\t}\r\n return $nstr;\r\n }\r\n\r\n /**\r\n * Adds a custom header. $name value can be overloaded to contain\r\n * both header name and value (name:value)\r\n * @access public\r\n * @param string $name custom header name\r\n * @param string $value header value\r\n * @return void\r\n */\r\n public function AddCustomHeader($name, $value=null) {\r\n\tif ($value === null) {\r\n\t\t// Value passed in as name:value\r\n\t\t$this->CustomHeader[] = explode(':', $name, 2);\r\n\t} else {\r\n\t\t$this->CustomHeader[] = array($name, $value);\r\n\t}\r\n }\r\n\r\n /**\r\n * Creates a message from an HTML string, making modifications for inline images and backgrounds\r\n * and creates a plain-text version by converting the HTML\r\n * Overwrites any existing values in $this->Body and $this->AltBody\r\n * @access public\r\n * @param string $message HTML message string\r\n * @param string $basedir baseline directory for path\r\n * @param bool $advanced Whether to use the advanced HTML to text converter\r\n * @return string $message\r\n */\r\n public function MsgHTML($message, $basedir = '', $advanced = false) {\r\n preg_match_all(\"/(src|background)=[\\\"'](.*)[\\\"']/Ui\", $message, $images);\r\n if (isset($images[2])) {\r\n foreach ($images[2] as $i => $url) {\r\n // do not change urls for absolute images (thanks to corvuscorax)\r\n if (!preg_match('#^[A-z]+://#', $url)) {\r\n $filename = basename($url);\r\n $directory = dirname($url);\r\n if ($directory == '.') {\r\n $directory = '';\r\n }\r\n $cid = md5($url).'@phpmailer.0'; //RFC2392 S 2\r\n if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {\r\n $basedir .= '/';\r\n }\r\n if (strlen($directory) > 1 && substr($directory, -1) != '/') {\r\n $directory .= '/';\r\n }\r\n if ($this->AddEmbeddedImage($basedir.$directory.$filename, $cid, $filename, 'base64', self::_mime_types(self::mb_pathinfo($filename, PATHINFO_EXTENSION)))) {\r\n $message = preg_replace(\"/\".$images[1][$i].\"=[\\\"']\".preg_quote($url, '/').\"[\\\"']/Ui\", $images[1][$i].\"=\\\"cid:\".$cid.\"\\\"\", $message);\r\n }\r\n }\r\n }\r\n }\r\n $this->IsHTML(true);\r\n if (empty($this->AltBody)) {\r\n $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . \"\\n\\n\";\r\n }\r\n //Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better\r\n $this->Body = $this->NormalizeBreaks($message);\r\n $this->AltBody = $this->NormalizeBreaks($this->html2text($message, $advanced));\r\n return $this->Body;\r\n }\r\n\r\n /**\r\n * Convert an HTML string into a plain text version\r\n * @param string $html The HTML text to convert\r\n * @param bool $advanced Should this use the more complex html2text converter or just a simple one?\r\n * @return string\r\n */\r\n public function html2text($html, $advanced = false) {\r\n if ($advanced) {\r\n require_once 'extras/class.html2text.php';\r\n $h = new html2text($html);\r\n return $h->get_text();\r\n }\r\n return html_entity_decode(trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\\/\\\\1>/si', '', $html))), ENT_QUOTES, $this->CharSet);\r\n }\r\n\r\n /**\r\n * Gets the MIME type of the embedded or inline image\r\n * @param string $ext File extension\r\n * @access public\r\n * @return string MIME type of ext\r\n * @static\r\n */\r\n public static function _mime_types($ext = '') {\r\n $mimes = array(\r\n 'xl' => 'application/excel',\r\n 'hqx' => 'application/mac-binhex40',\r\n 'cpt' => 'application/mac-compactpro',\r\n 'bin' => 'application/macbinary',\r\n 'doc' => 'application/msword',\r\n 'word' => 'application/msword',\r\n 'class' => 'application/octet-stream',\r\n 'dll' => 'application/octet-stream',\r\n 'dms' => 'application/octet-stream',\r\n 'exe' => 'application/octet-stream',\r\n 'lha' => 'application/octet-stream',\r\n 'lzh' => 'application/octet-stream',\r\n 'psd' => 'application/octet-stream',\r\n 'sea' => 'application/octet-stream',\r\n 'so' => 'application/octet-stream',\r\n 'oda' => 'application/oda',\r\n 'pdf' => 'application/pdf',\r\n 'ai' => 'application/postscript',\r\n 'eps' => 'application/postscript',\r\n 'ps' => 'application/postscript',\r\n 'smi' => 'application/smil',\r\n 'smil' => 'application/smil',\r\n 'mif' => 'application/vnd.mif',\r\n 'xls' => 'application/vnd.ms-excel',\r\n 'ppt' => 'application/vnd.ms-powerpoint',\r\n 'wbxml' => 'application/vnd.wap.wbxml',\r\n 'wmlc' => 'application/vnd.wap.wmlc',\r\n 'dcr' => 'application/x-director',\r\n 'dir' => 'application/x-director',\r\n 'dxr' => 'application/x-director',\r\n 'dvi' => 'application/x-dvi',\r\n 'gtar' => 'application/x-gtar',\r\n 'php3' => 'application/x-httpd-php',\r\n 'php4' => 'application/x-httpd-php',\r\n 'php' => 'application/x-httpd-php',\r\n 'phtml' => 'application/x-httpd-php',\r\n 'phps' => 'application/x-httpd-php-source',\r\n 'js' => 'application/x-javascript',\r\n 'swf' => 'application/x-shockwave-flash',\r\n 'sit' => 'application/x-stuffit',\r\n 'tar' => 'application/x-tar',\r\n 'tgz' => 'application/x-tar',\r\n 'xht' => 'application/xhtml+xml',\r\n 'xhtml' => 'application/xhtml+xml',\r\n 'zip' => 'application/zip',\r\n 'mid' => 'audio/midi',\r\n 'midi' => 'audio/midi',\r\n 'mp2' => 'audio/mpeg',\r\n 'mp3' => 'audio/mpeg',\r\n 'mpga' => 'audio/mpeg',\r\n 'aif' => 'audio/x-aiff',\r\n 'aifc' => 'audio/x-aiff',\r\n 'aiff' => 'audio/x-aiff',\r\n 'ram' => 'audio/x-pn-realaudio',\r\n 'rm' => 'audio/x-pn-realaudio',\r\n 'rpm' => 'audio/x-pn-realaudio-plugin',\r\n 'ra' => 'audio/x-realaudio',\r\n 'wav' => 'audio/x-wav',\r\n 'bmp' => 'image/bmp',\r\n 'gif' => 'image/gif',\r\n 'jpeg' => 'image/jpeg',\r\n 'jpe' => 'image/jpeg',\r\n 'jpg' => 'image/jpeg',\r\n 'png' => 'image/png',\r\n 'tiff' => 'image/tiff',\r\n 'tif' => 'image/tiff',\r\n 'eml' => 'message/rfc822',\r\n 'css' => 'text/css',\r\n 'html' => 'text/html',\r\n 'htm' => 'text/html',\r\n 'shtml' => 'text/html',\r\n 'log' => 'text/plain',\r\n 'text' => 'text/plain',\r\n 'txt' => 'text/plain',\r\n 'rtx' => 'text/richtext',\r\n 'rtf' => 'text/rtf',\r\n 'xml' => 'text/xml',\r\n 'xsl' => 'text/xml',\r\n 'mpeg' => 'video/mpeg',\r\n 'mpe' => 'video/mpeg',\r\n 'mpg' => 'video/mpeg',\r\n 'mov' => 'video/quicktime',\r\n 'qt' => 'video/quicktime',\r\n 'rv' => 'video/vnd.rn-realvideo',\r\n 'avi' => 'video/x-msvideo',\r\n 'movie' => 'video/x-sgi-movie'\r\n );\r\n return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];\r\n }\r\n\r\n /**\r\n * Try to map a file name to a MIME type, default to application/octet-stream\r\n * @param string $filename A file name or full path, does not need to exist as a file\r\n * @return string\r\n * @static\r\n */\r\n public static function filenameToType($filename) {\r\n //In case the path is a URL, strip any query string before getting extension\r\n $qpos = strpos($filename, '?');\r\n if ($qpos !== false) {\r\n $filename = substr($filename, 0, $qpos);\r\n }\r\n $pathinfo = self::mb_pathinfo($filename);\r\n return self::_mime_types($pathinfo['extension']);\r\n }\r\n\r\n /**\r\n * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.\r\n * Works similarly to the one in PHP >= 5.2.0\r\n * @link http://www.php.net/manual/en/function.pathinfo.php#107461\r\n * @param string $path A filename or path, does not need to exist as a file\r\n * @param integer|string $options Either a PATHINFO_* constant, or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2\r\n * @return string|array\r\n * @static\r\n */\r\n public static function mb_pathinfo($path, $options = null) {\r\n $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');\r\n $m = array();\r\n preg_match('%^(.*?)[\\\\\\\\/]*(([^/\\\\\\\\]*?)(\\.([^\\.\\\\\\\\/]+?)|))[\\\\\\\\/\\.]*$%im', $path, $m);\r\n if(array_key_exists(1, $m)) {\r\n $ret['dirname'] = $m[1];\r\n }\r\n if(array_key_exists(2, $m)) {\r\n $ret['basename'] = $m[2];\r\n }\r\n if(array_key_exists(5, $m)) {\r\n $ret['extension'] = $m[5];\r\n }\r\n if(array_key_exists(3, $m)) {\r\n $ret['filename'] = $m[3];\r\n }\r\n switch($options) {\r\n case PATHINFO_DIRNAME:\r\n case 'dirname':\r\n return $ret['dirname'];\r\n break;\r\n case PATHINFO_BASENAME:\r\n case 'basename':\r\n return $ret['basename'];\r\n break;\r\n case PATHINFO_EXTENSION:\r\n case 'extension':\r\n return $ret['extension'];\r\n break;\r\n case PATHINFO_FILENAME:\r\n case 'filename':\r\n return $ret['filename'];\r\n break;\r\n default:\r\n return $ret;\r\n }\r\n }\r\n\r\n /**\r\n * Set (or reset) Class Objects (variables)\r\n *\r\n * Usage Example:\r\n * $page->set('X-Priority', '3');\r\n *\r\n * @access public\r\n * @param string $name\r\n * @param mixed $value\r\n * NOTE: will not work with arrays, there are no arrays to set/reset\r\n * @throws phpmailerException\r\n * @return bool\r\n * @todo Should this not be using __set() magic function?\r\n */\r\n public function set($name, $value = '') {\r\n try {\r\n if (isset($this->$name) ) {\r\n $this->$name = $value;\r\n } else {\r\n throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);\r\n }\r\n } catch (Exception $e) {\r\n $this->SetError($e->getMessage());\r\n if ($e->getCode() == self::STOP_CRITICAL) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Strips newlines to prevent header injection.\r\n * @access public\r\n * @param string $str\r\n * @return string\r\n */\r\n public function SecureHeader($str) {\r\n return trim(str_replace(array(\"\\r\", \"\\n\"), '', $str));\r\n }\r\n\r\n /**\r\n * Normalize UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format\r\n * Defaults to CRLF (for message bodies) and preserves consecutive breaks\r\n * @param string $text\r\n * @param string $breaktype What kind of line break to use, defaults to CRLF\r\n * @return string\r\n * @access public\r\n * @static\r\n */\r\n public static function NormalizeBreaks($text, $breaktype = \"\\r\\n\") {\r\n return preg_replace('/(\\r\\n|\\r|\\n)/ms', $breaktype, $text);\r\n }\r\n\r\n\r\n\t/**\r\n * Set the private key file and password to sign the message.\r\n *\r\n * @access public\r\n * @param string $cert_filename\r\n * @param string $key_filename\r\n * @param string $key_pass Password for private key\r\n */\r\n public function Sign($cert_filename, $key_filename, $key_pass) {\r\n $this->sign_cert_file = $cert_filename;\r\n $this->sign_key_file = $key_filename;\r\n $this->sign_key_pass = $key_pass;\r\n }\r\n\r\n /**\r\n * Set the private key file and password to sign the message.\r\n *\r\n * @access public\r\n * @param string $txt\r\n * @return string\r\n */\r\n public function DKIM_QP($txt) {\r\n $line = '';\r\n for ($i = 0; $i < strlen($txt); $i++) {\r\n $ord = ord($txt[$i]);\r\n if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {\r\n $line .= $txt[$i];\r\n } else {\r\n $line .= \"=\".sprintf(\"%02X\", $ord);\r\n }\r\n }\r\n return $line;\r\n }\r\n\r\n /**\r\n * Generate DKIM signature\r\n *\r\n * @access public\r\n * @param string $s Header\r\n * @throws phpmailerException\r\n * @return string\r\n */\r\n public function DKIM_Sign($s) {\r\n if (!defined('PKCS7_TEXT')) {\r\n if ($this->exceptions) {\r\n throw new phpmailerException($this->Lang(\"signing\").' OpenSSL extension missing.');\r\n }\r\n return '';\r\n }\r\n $privKeyStr = file_get_contents($this->DKIM_private);\r\n if ($this->DKIM_passphrase != '') {\r\n $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);\r\n } else {\r\n $privKey = $privKeyStr;\r\n }\r\n if (openssl_sign($s, $signature, $privKey)) {\r\n return base64_encode($signature);\r\n }\r\n return '';\r\n }\r\n\r\n /**\r\n * Generate DKIM Canonicalization Header\r\n *\r\n * @access public\r\n * @param string $s Header\r\n * @return string\r\n */\r\n public function DKIM_HeaderC($s) {\r\n $s = preg_replace(\"/\\r\\n\\s+/\", \" \", $s);\r\n $lines = explode(\"\\r\\n\", $s);\r\n foreach ($lines as $key => $line) {\r\n list($heading, $value) = explode(\":\", $line, 2);\r\n $heading = strtolower($heading);\r\n $value = preg_replace(\"/\\s+/\", \" \", $value) ; // Compress useless spaces\r\n $lines[$key] = $heading.\":\".trim($value) ; // Don't forget to remove WSP around the value\r\n }\r\n $s = implode(\"\\r\\n\", $lines);\r\n return $s;\r\n }\r\n\r\n /**\r\n * Generate DKIM Canonicalization Body\r\n *\r\n * @access public\r\n * @param string $body Message Body\r\n * @return string\r\n */\r\n public function DKIM_BodyC($body) {\r\n if ($body == '') return \"\\r\\n\";\r\n // stabilize line endings\r\n $body = str_replace(\"\\r\\n\", \"\\n\", $body);\r\n $body = str_replace(\"\\n\", \"\\r\\n\", $body);\r\n // END stabilize line endings\r\n while (substr($body, strlen($body) - 4, 4) == \"\\r\\n\\r\\n\") {\r\n $body = substr($body, 0, strlen($body) - 2);\r\n }\r\n return $body;\r\n }\r\n\r\n /**\r\n * Create the DKIM header, body, as new header\r\n *\r\n * @access public\r\n * @param string $headers_line Header lines\r\n * @param string $subject Subject\r\n * @param string $body Body\r\n * @return string\r\n */\r\n public function DKIM_Add($headers_line, $subject, $body) {\r\n $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms\r\n $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body\r\n $DKIMquery = 'dns/txt'; // Query method\r\n $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)\r\n $subject_header = \"Subject: $subject\";\r\n $headers = explode($this->LE, $headers_line);\r\n $from_header = '';\r\n $to_header = '';\r\n $current = '';\r\n foreach($headers as $header) {\r\n if (strpos($header, 'From:') === 0) {\r\n $from_header = $header;\r\n $current = 'from_header';\r\n } elseif (strpos($header, 'To:') === 0) {\r\n $to_header = $header;\r\n $current = 'to_header';\r\n } else {\r\n if($current && strpos($header, ' =?') === 0){\r\n $current .= $header;\r\n } else {\r\n $current = '';\r\n }\r\n }\r\n }\r\n $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));\r\n $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));\r\n $subject = str_replace('|', '=7C', $this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable\r\n $body = $this->DKIM_BodyC($body);\r\n $DKIMlen = strlen($body) ; // Length of body\r\n $DKIMb64 = base64_encode(pack(\"H*\", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body\r\n $ident = ($this->DKIM_identity == '')? '' : \" i=\" . $this->DKIM_identity . \";\";\r\n $dkimhdrs = \"DKIM-Signature: v=1; a=\" . $DKIMsignatureType . \"; q=\" . $DKIMquery . \"; l=\" . $DKIMlen . \"; s=\" . $this->DKIM_selector . \";\\r\\n\".\r\n \"\\tt=\" . $DKIMtime . \"; c=\" . $DKIMcanonicalization . \";\\r\\n\".\r\n \"\\th=From:To:Subject;\\r\\n\".\r\n \"\\td=\" . $this->DKIM_domain . \";\" . $ident . \"\\r\\n\".\r\n \"\\tz=$from\\r\\n\".\r\n \"\\t|$to\\r\\n\".\r\n \"\\t|$subject;\\r\\n\".\r\n \"\\tbh=\" . $DKIMb64 . \";\\r\\n\".\r\n \"\\tb=\";\r\n $toSign = $this->DKIM_HeaderC($from_header . \"\\r\\n\" . $to_header . \"\\r\\n\" . $subject_header . \"\\r\\n\" . $dkimhdrs);\r\n $signed = $this->DKIM_Sign($toSign);\r\n return $dkimhdrs.$signed.\"\\r\\n\";\r\n }\r\n\r\n /**\r\n * Perform callback\r\n * @param boolean $isSent\r\n * @param string $to\r\n * @param string $cc\r\n * @param string $bcc\r\n * @param string $subject\r\n * @param string $body\r\n * @param string $from\r\n */\r\n protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null) {\r\n if (!empty($this->action_function) && is_callable($this->action_function)) {\r\n $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);\r\n call_user_func_array($this->action_function, $params);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Exception handler for PHPMailer\r\n * @package PHPMailer\r\n */\r\nclass phpmailerException extends Exception {\r\n /**\r\n * Prettify error message output\r\n * @return string\r\n */\r\n public function errorMessage() {\r\n $errorMsg = '' . $this->getMessage() . \"
\\n\";\r\n return $errorMsg;\r\n }\r\n}\r\n" , SF False ".\\php\\plugins\\lib\\class.MessageBird.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "username = $username;\r\n $this->password = $password;\r\n }\r\n\r\n /**\r\n * Adds MSISDN to the destination array\r\n *\r\n * @param Integer $destination The destination MSISDN (Mobile number)\r\n */\r\n public function addDestination($destination)\r\n {\r\n $this->destination[] = $destination;\r\n }\r\n\r\n /**\r\n * Sets the reference linked to the MSISDN so the correct status can be retrieved later.\r\n *\r\n * @param Integer $reference An unique reference so delivery reports can be linked to the correct message and MSISDN\r\n */\r\n public function setReference($reference)\r\n {\r\n $this->reference = (int) $reference;\r\n }\r\n\r\n /**\r\n * Sets the sender. This can be an MSISDN (Mobile number) or an Text.\r\n * When it is only numbers it can be 16 numbers, when it is text, it can only be 11 characters long.\r\n *\r\n * @param string /integer $sender The sender of the message which the recipient will see.\r\n */\r\n public function setSender($sender)\r\n {\r\n $this->sender = $sender;\r\n }\r\n\r\n /**\r\n * Sets the date and time when the message should be sent.\r\n * NOTE: This should be in the timezone that is configured in your settings on the website.\r\n *\r\n * possible values for dateTime:\r\n * instance of DateTime class\r\n * unix time stamp - time()\r\n * timestamp - date('YmdHi')\r\n * date - date('Y-m-d H:i')\r\n *\r\n * @param integer /DateTime $dateTime\r\n * @param DateTimeZone $timeZone\r\n */\r\n public function setTimestamp($dateTime, DateTimeZone $timeZone = null)\r\n {\r\n if (! ($dateTime instanceof DateTime)) {\r\n $dateTime = new DateTime($dateTime, $timeZone);\r\n }\r\n\r\n if ($timeZone) {\r\n $dateTime->setTimezone($timeZone);\r\n }\r\n\r\n // Our API needs the timestamp in YearMonthDayHourMinute so we convert it to this format\r\n $this->timestamp = $dateTime->format('YmdHi');\r\n }\r\n\r\n /**\r\n * Sets the response type to be used for retrieveing the response in specific manner.\r\n * You can change the response type to anything which is in the API Documentation.\r\n *\r\n * @param String $responseType Could be XML, PLAIN or SIMPLE (Default: XML)\r\n */\r\n public function setResponseType($responseType)\r\n {\r\n $this->responseType = $responseType;\r\n }\r\n\r\n /**\r\n * If you want the sender to be an MessageBird mobile number, set this to TRUE\r\n *\r\n * @param boolean $inbox\r\n */\r\n public function setInbox($inbox)\r\n {\r\n if ($inbox === true) {\r\n $this->inbox = true;\r\n } else {\r\n $this->inbox = false;\r\n }\r\n }\r\n\r\n /**\r\n * If you want a dlr notification of the message send to another url then that you have set on the web site, you can use this parameter.\r\n *\r\n * @param $dlrUrl\r\n *\r\n * @throws Exception\r\n */\r\n public function setDlrUrl($dlrUrl)\r\n {\r\n if (filter_var($dlrUrl, FILTER_VALIDATE_URL) === false) {\r\n throw new Exception('$dlrUrl expected a valid URL.');\r\n }\r\n $this->dlrUrl = $dlrUrl;\r\n }\r\n\r\n /**\r\n *\r\n * If $replacechars is true, then characters that are not listed in the GSM-7 character set are replaced by alternative characters.\r\n * If $replacechars is false, then no characters are converted into alternative characters, if there are any characters that are not listed in the GSM-7 character set, the message is sent as UTF-8 (unicode)\r\n *\r\n * @param boolean $replacechars\r\n *\r\n * @throws Exception\r\n */\r\n public function setReplacechars($replacechars)\r\n {\r\n if (is_bool($replacechars) === false) {\r\n throw new Exception('$replacechars expected a boolean.');\r\n }\r\n\r\n if ($replacechars === true) {\r\n $this->replacechars = true;\r\n } else {\r\n $this->replacechars = false;\r\n }\r\n }\r\n\r\n /**\r\n * If $test is TRUE, then the message is not actually sent or scheduled, and there will be no credits deducted.\r\n * Validation of the message will take place, and you will also receive a normal response back from the API.\r\n *\r\n * @param boolean $test\r\n */\r\n public function setTest($test)\r\n {\r\n if ($test === true) {\r\n $this->test = true;\r\n } else {\r\n $this->test = false;\r\n }\r\n }\r\n\r\n /**\r\n * Will actualy send the given message to the destinations given using addDestination()\r\n *\r\n * @param String $message The message which should be sent to the added destinations.\r\n */\r\n public function sendSms($message)\r\n {\r\n $destination = implode(',', $this->destination);\r\n\r\n $postParams = array (\r\n 'username' => $this->username,\r\n 'password' => $this->password,\r\n 'destination' => $destination,\r\n 'responsetype' => $this->responseType,\r\n 'sender' => $this->sender,\r\n 'body' => $message,\r\n );\r\n\r\n // If there is a reference set, add it to the parameters\r\n if ($this->reference !== null) {\r\n $postParams['reference'] = $this->reference;\r\n }\r\n\r\n // If there is a timestamp set, add it to the parameters\r\n if ($this->timestamp !== null) {\r\n $postParams['timestamp'] = $this->timestamp;\r\n }\r\n\r\n // If we want the SMS to be send from a MessageBird mobile number\r\n if ($this->inbox !== false) {\r\n $postParams['inbox'] = 'true';\r\n }\r\n\r\n // If we do not want to replace characters\r\n if ($this->replacechars === false) {\r\n $postParams['replacechars'] = 'false';\r\n }\r\n\r\n // If we want to add a DLR url\r\n if ($this->dlrUrl) {\r\n $postParams['dlr_url'] = $this->dlrUrl;\r\n }\r\n\r\n // If we want to send a test message, we set this parameter.\r\n if ($this->test !== false) {\r\n $postParams['test'] = 'true';\r\n }\r\n\r\n // urlencode/concatinate all the paramters using http_build_query()\r\n $postData = http_build_query($postParams, '', '&');\r\n\r\n $result = $this->sendToHost('api.messagebird.com', '/api/sms', $postData);\r\n list($headers, $xml) = preg_split(\"/(\\r?\\n){2}/\", $result, 2);\r\n $this->XMLtoResult($xml);\r\n }\r\n\r\n /**\r\n * Send data to Host\r\n *\r\n * @param $host\r\n * @param $path\r\n * @param $postData\r\n *\r\n * @return string\r\n */\r\n protected function sendToHost($host, $path, $postData)\r\n {\r\n $fp = @fsockopen($host, 80);\r\n $buf = '';\r\n if ($fp) {\r\n @fputs($fp, \"POST $path HTTP/1.1\\r\\n\");\r\n @fputs($fp, \"Host: $host\\r\\n\");\r\n @fputs($fp, \"Content-type: application/x-www-form-urlencoded\\r\\n\");\r\n @fputs($fp, \"Content-length: \" . strlen($postData) . \"\\r\\n\");\r\n @fputs($fp, \"Connection: close\\r\\n\\r\\n\");\r\n @fputs($fp, $postData);\r\n while (! @feof($fp)) {\r\n $buf .= @fgets($fp, 128);\r\n }\r\n @fclose($fp);\r\n }\r\n\r\n return $buf;\r\n }\r\n\r\n /**\r\n * Save XML parameters to strings\r\n *\r\n * @param String $xml\r\n */\r\n protected function XMLtoResult($xml)\r\n {\r\n // Newer version of the libXML can be speed-up by this extra setting.\r\n if (LIBXML_VERSION >= 20621) {\r\n $xmlOptions = LIBXML_COMPACT;\r\n } else {\r\n $xmlOptions = null;\r\n }\r\n $data = simplexml_load_string($xml, null, $xmlOptions);\r\n\r\n $this->apiResponseCode = $data->item->responseCode;\r\n $this->apiResponseMessage = $data->item->responseMessage;\r\n $this->apiCreditBalance = $data->item->credits;\r\n }\r\n\r\n /**\r\n * Will return the response code which is returned after sending the the message.\r\n *\r\n * @return String The response code\r\n */\r\n public function getResponseCode()\r\n {\r\n return $this->apiResponseCode;\r\n }\r\n\r\n /**\r\n * Will return the response message.\r\n *\r\n * @return String The response message\r\n */\r\n public function getResponseMessage()\r\n {\r\n return $this->apiResponseMessage;\r\n }\r\n\r\n /**\r\n * Will return the current credit balance left after sending the messages.\r\n *\r\n * @return integer The current credit balance after sending the message. (0 when an error occurred)\r\n */\r\n public function getCreditBalance()\r\n {\r\n return $this->apiCreditBalance;\r\n }\r\n}" , SF False ".\\php\\loadplugins.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "\";\r\n}\r\n\r\n?>" , SF False ".\\php\\InstallMysqlProcedures.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "--ERROR-- ROLE DATABASE MAINTAINS $rulename does not lead to a stored procedure.
\");\r\n die;\r\n// Om de zaak te redden kunnen we deze regel toekennen aan de rol 'ExecEngine' i.p.v. aan DATABASE\r\n// We kunnen overigens NIET het omgekeerde doen (alle ExecEngine regels aan DATABASE toekennen)\r\n $expressions = array(); // empty arry\r\n }\r\n \r\n foreach($expressions as $key => $expression)\r\n {\r\n $expression = trim($expression);\r\n procDBGecho(\"* Expression: $expression\");\r\n \r\n // check if $expression starts with '-' (e.g. -bfGebruiktARM20_DefProp)\r\n if(substr($expression, 0, 1) == \"-\") {\r\n $expressionIsNegative = true;\r\n procDBGecho(\" --Expression is negative\");\r\n $expression = substr($expression, 1); // remove '-' before expression\r\n }else{\r\n $expressionIsNegative = false;\r\n procDBGecho(\" --Expression is non negative\");\r\n }\r\n \r\n // check if $expression is flipped (e.g. relation~)\r\n if(substr($expression, -1) == \"~\"){\r\n $expressionIsFlipped = true;\r\n procDBGecho(\" --Expression is flipped\");\r\n $expression = substr($expression, 0, -1); // remove '~' after expression\r\n }else{\r\n $expressionIsFlipped = false;\r\n procDBGecho(\" --Expression is not flipped\");\r\n }\r\n \r\n if(array_key_exists($expression, $relationTableInfo))\r\n {\r\n procDBGecho(\" --Expression exists in relationTableInfo as $expression\");\r\n $relation = $expression; // $expression exists in $relationTableInfo, so we call it a $relation\r\n \r\n // if $expressionIsFlipped provide ERROR and stop script\r\n if($expressionIsFlipped)\r\n {\r\n echo \" --ERROR: Relation must not be flipped\";\r\n die;\r\n } \r\n /* Decision table for deciding whether it must be an 'delpair' or 'inspair' procedure\r\n |************|********|***********|*********************|**********|\r\n | | | Negative | Relation left/right | |\r\n | | Symbol | relation | of symbol | Outcome |\r\n |************|********|***********|*********************|**********|\r\n | r |- exp | |- | false | left ($key == 0) | delpair |\r\n | exp |- r | |- | false | right ($key == 1) | inspair |\r\n | -r |- exp | |- | true | left ($key == 0) | inspair |\r\n | exp |- -r | |- | true | right ($key == 1) | delpair |\r\n | r -| exp | -| | false | left ($key == 0) | inspair |\r\n | exp -| r | -| | false | right ($key == 1) | delpair |\r\n | -r -| exp | -| | true | left ($key == 0) | delpair |\r\n | exp -| -r | -| | true | right ($key == 1) | inspair |\r\n |************|********|***********|*********************|**********|\r\n */\r\n switch($symbol)\r\n {\r\n case \"|-\":\r\n switch($expressionIsNegative)\r\n {\r\n case false:\r\n switch ($key)\r\n {\r\n case 0:\r\n // delpair\r\n $query = makeDelpairSqlProcedure($ruleName, $relation);\r\n break;\r\n case 1:\r\n // inspair\r\n $query = makeInspairSqlProcedure($ruleName, $relation);\r\n break;\r\n }\r\n break;\r\n case true:\r\n switch ($key)\r\n {\r\n case 0:\r\n // inspair\r\n $query = makeInspairSqlProcedure($ruleName, $relation);\r\n break;\r\n case 1:\r\n // delpair\r\n $query = makeDelpairSqlProcedure($ruleName, $relation);\r\n break;\r\n }\r\n break;\r\n }\r\n break;\r\n case \"-|\":\r\n switch($expressionIsNegative)\r\n {\r\n case false:\r\n switch ($key)\r\n {\r\n case 0:\r\n // inspair\r\n $query = makeInspairSqlProcedure($ruleName, $relation);\r\n break;\r\n case 1:\r\n // delpair\r\n $query = makeDelpairSqlProcedure($ruleName, $relation);\r\n break;\r\n }\r\n break;\r\n case true:\r\n switch ($key)\r\n {\r\n case 0:\r\n // delpair\r\n $query = makeDelpairSqlProcedure($ruleName, $relation);\r\n break;\r\n case 1:\r\n // inspair\r\n $query = makeInspairSqlProcedure($ruleName, $relation);\r\n break;\r\n }\r\n break;\r\n }\r\n break; \r\n }\r\n \r\n // query uitvoeren\r\n mysqli_query($link, \"DROP PROCEDURE IF EXISTS \".escapeSQL(makeDBFunctionName($allRules[$ruleName]['name'])));\r\n mysqli_query($link, $query); \r\n echo(mysqli_error($link));\r\n \r\n // reporting\r\n// procDBGecho($query);\r\n procDBGecho(\" --Stored procedure aangemaakt voor $ruleName\");\r\n }else\r\n {\r\n procDBGecho(\" --Expression not in relationTableInfo
\");\r\n }\r\n }\r\n \r\n if (!$storedProcedureCreated) // Since stored procedure is uncreated, we MUST warn the developer/user!!\r\n { \r\n echo(\"Rule $ruleName could not be created as a stored procedure!\");\r\n die;\r\n }\r\n procDBGecho(\"
\");\r\n }\r\n \r\n }\r\n}\r\n\r\n// AllProcedures PROCEDURE aanmaken\r\n$query = makeAllProceduresProcedure(); // Dit werkt niet als er geen stored procedures zijn\r\nmysqli_query($link, \"DROP PROCEDURE IF EXISTS AllProcedures\");\r\nmysqli_query($link, $query); \r\nprocDBGecho(\"InstallMysqlProcdures - make all procedures\". mysqli_error($link));\r\nprocDBGecho($query . \"\");\r\nprocDBGecho(\"AllProcedures PROCEDURE aangemaakt
\");\r\n\r\nfunction makeInspairSqlProcedure($ruleName, $relation){\r\n global $allRules;\r\n global $relationTableInfo;\r\n global $tableColumnInfo;\r\n global $procedures;\r\n global $storedProcedureCreated;\r\n \r\n // get table, srcCol and tgtCol for $relation\r\n $table = $relationTableInfo[$relation]['table'];\r\n $srcCol = $relationTableInfo[$relation]['srcCol'];\r\n $tgtCol = $relationTableInfo[$relation]['tgtCol'];\r\n \r\n // get table column properties for $srcCol and $tgtCol\r\n $srcColUnique = $tableColumnInfo[$table][$srcCol]['unique'];\r\n $tgtColUnique = $tableColumnInfo[$table][$tgtCol]['unique'];\r\n \r\n // SQL escape table and column names\r\n $tableEsc = escapeSQL($table);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n $srcAtomEsc = 'srcAtom'; // This is correct! without $, because 'srcAtom' is the column name of query result in the procedure\r\n $tgtAtomEsc = 'tgtAtom'; // This is correct! without $, because 'tgtAtom' is the column name of query result in the procedure\r\n \r\n // build database query\r\n if($srcColUnique || $tgtColUnique) // srcCol, tgtCol or both are unique ==> update query\r\n {\r\n if($srcColUnique){\r\n $query = \"UPDATE `$tableEsc` SET `$srcColEsc`= $srcAtomEsc, `$tgtColEsc`= $tgtAtomEsc WHERE `$srcColEsc`= $srcAtomEsc\";\r\n }else{\r\n $query = \"UPDATE `$tableEsc` SET `$srcColEsc`= $srcAtomEsc, `$tgtColEsc`= $tgtAtomEsc WHERE `$tgtColEsc`= $tgtAtomEsc\";\r\n }\r\n }else{ // neither srcCol nor tgtCol is unique ==> insert query\r\n $query = \"INSERT INTO `$tableEsc` (`$srcColEsc`, `$tgtColEsc`) VALUES ($srcAtomEsc, $tgtAtomEsc)\";\r\n }\r\n \r\n // build procedure\r\n $query = \"CREATE PROCEDURE \".escapeSQL(makeDBFunctionName($allRules[$ruleName]['name'])).\"() \r\n BEGIN \r\n DECLARE done INT DEFAULT 0; \r\n DECLARE srcAtom varchar(4000); \r\n DECLARE tgtAtom varchar(4000); \r\n DECLARE cur_1 CURSOR FOR \".$allRules[$ruleName]['violationsSQL'].\"; \r\n DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; \r\n OPEN cur_1; \r\n REPEAT \r\n FETCH cur_1 INTO srcAtom, tgtAtom; \r\n IF NOT done THEN \r\n $query;\r\n END IF; \r\n UNTIL done END REPEAT; \r\n CLOSE cur_1; \r\n END \"; \r\n \r\n procDBGecho(\" --Inspair PROCEDURE aanmaken\");\r\n addProcedureToAllProcedures(makeDBFunctionName($allRules[$ruleName]['name'])); // add this procedure to AllProcedures in order to call all procedures at once\r\n $storedProcedureCreated = TRUE;\r\n\r\n return $query;\r\n}\r\n\r\nfunction makeDelpairSqlProcedure($ruleName, $relation){\r\n global $allRules;\r\n global $relationTableInfo;\r\n global $tableColumnInfo;\r\n global $procedures;\r\n global $storedProcedureCreated;\r\n \r\n // get table, srcCol and tgtCol for $relation\r\n $table = $relationTableInfo[$relation]['table'];\r\n $srcCol = $relationTableInfo[$relation]['srcCol'];\r\n $tgtCol = $relationTableInfo[$relation]['tgtCol'];\r\n \r\n // get table column properties for $srcCol and $tgtCol\r\n $srcColNull = $tableColumnInfo[$table][$srcCol]['null'];\r\n $tgtColNull = $tableColumnInfo[$table][$tgtCol]['null'];\r\n \r\n // SQL escape table and column names\r\n $tableEsc = escapeSQL($table);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n \r\n // build database query\r\n if($srcColNull xor $tgtColNull) // srcCol xor tgtCol can be null ==> update query\r\n {\r\n if($srcColNull){\r\n $query = \"UPDATE `$tableEsc` SET `$srcColEsc`= NULL WHERE `$srcColEsc`= srcAtom AND `$tgtColEsc`= tgtAtom\";\r\n }else{\r\n $query = \"UPDATE `$tableEsc` SET `$tgtColEsc`= NULL WHERE `$srcColEsc`= srcAtom AND `$tgtColEsc`= tgtAtom\";\r\n }\r\n }elseif($srcColNull and $tgtColNull) // both srcCol and tgtCol can be null ==> delete query -- REMARK: maybe this should be an update instead of delete query\r\n {\r\n $query = \"DELETE FROM `$tableEsc` WHERE `$srcColEsc`= srcAtom AND `$tgtColEsc`= tgtAtom\";\r\n }else{ // neither srcCol nor tgtCol can be null ==> delete query\r\n $query = \"DELETE FROM `$tableEsc` WHERE `$srcColEsc`= srcAtom AND `$tgtColEsc`= tgtAtom\";\r\n }\r\n // build procedure\r\n $sql = \"CREATE PROCEDURE \".escapeSQL(makeDBFunctionName($allRules[$ruleName]['name'])).\"() \r\n BEGIN \r\n DECLARE done INT DEFAULT 0; \r\n DECLARE srcAtom varchar(4000); \r\n DECLARE tgtAtom varchar(4000); \r\n DECLARE cur_1 CURSOR FOR \".$allRules[$ruleName]['violationsSQL'].\"; \r\n DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; \r\n OPEN cur_1; \r\n REPEAT \r\n FETCH cur_1 INTO srcAtom, tgtAtom; \r\n IF NOT done THEN \r\n $query;\r\n END IF; \r\n UNTIL done END REPEAT; \r\n CLOSE cur_1; \r\n END\";\r\n \r\n procDBGecho(\" --Delpair PROCEDURE aanmaken\");\r\n addProcedureToAllProcedures(makeDBFunctionName($allRules[$ruleName]['name'])); // add this procedure to AllProcedures in order to call all procedures at once\r\n $storedProcedureCreated = TRUE;\r\n \r\n return $sql; \r\n}\r\n\r\n// add $procedureName to AllProcedures in order to call all procedures at once\r\nfunction addProcedureToAllProcedures($procedureName){\r\n global $procedures;\r\n $procedures[] = escapeSQL($procedureName);\r\n}\r\n\r\n// build procedure AllProcedures()\r\nfunction makeAllProceduresProcedure(){\r\n global $procedures;\r\n \r\n $query = \"CREATE PROCEDURE AllProcedures() BEGIN \";\r\n foreach ((array)$procedures as $procedure)\r\n {\r\n $query .= \"CALL $procedure;\";\r\n }\r\n $query .= \"END \";\r\n procDBGecho(\"AllProcedures PROCEDURE aanmaken\");\r\n return $query;\r\n}\r\n\r\n\r\nfunction procDBGecho ($text)\r\n{ \r\n //echo(\" \".$text.\"
\");\r\n \r\n} \r\n\r\nfunction makeDBFunctionName($functionName){\r\n $search = array(' ', '-');\r\n return str_replace($search, '_', $functionName);\r\n}\r\n\r\n?>\r\n" , SF False ".\\php\\DatabaseUtils.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "
Error while connecting to MySQL: \" \r\n . mysqli_connect_error() \r\n . \"
The database may not have been initialized yet. (Initialize database)
\"\r\n );\r\n}\r\n// Set sql_mode to ANSI\r\nDB_doquer(\"SET SESSION sql_mode = 'ANSI'\");\r\n\r\n// let PHP also report undefined variable references\r\nfunction terminate_missing_variables($errno, $errstr, $errfile, $errline) {\r\n if (($errno == E_NOTICE) and (strstr($errstr, \"Undefined variable\")))\r\n echo (\"$errstr in $errfile line $errline\");\r\n \r\n return false; // Let the PHP error handler handle all the rest\r\n}\r\nset_error_handler(\"terminate_missing_variables\");\r\n\r\n// Sessions\r\n\r\ndefine(\"EXPIRATION_TIME\", 60 * 60); // expiration time in seconds\r\n\r\nfunction initSession() {\r\n // when using $_SESSION, we get a nonsense warning if not declared global, however here\r\n // we only do isset, so no need for global\r\n global $allConcepts;\r\n \r\n session_start(); // Start a new, or resume the existing, PHP session\r\n \r\n // only execute session code when concept SESSION is used by adl script\r\n if (isset($allConcepts['SESSION'])) { \r\n // TODO: until error handling is improved, this hack tries a dummy query and returns silently if it fails.\r\n // This way, errors during initSession do not prevent the reset-database link from being visible.\r\n DB_doquerErr(\"SELECT * FROM `__SessionTimeout__` WHERE false\", $error);\r\n if ($error)\r\n return;\r\n \r\n // Remove expired Ampersand-sessions from __SessionTimeout__ and all concept tables and relations where it appears.\r\n $expirationLimit = time() - EXPIRATION_TIME;\r\n $expiredSessions = firstCol(DB_doquer(\"SELECT SESSION FROM `__SessionTimeout__` WHERE lastAccess < $expirationLimit;\"));\r\n foreach ($expiredSessions as $expiredSessionAtom)\r\n deleteSession($expiredSessionAtom);\r\n \r\n // Create a new session if sessionAtom in php _SESSION is not set (browser started a new session)\r\n // or sessionAtom is not in SESSIONS (previous session expired)\r\n if (!isset($_SESSION['sessionAtom']) || !isAtomInConcept($_SESSION['sessionAtom'], 'SESSION')) {\r\n $sessionAtom = mkUniqueAtomByTime('SESSION');\r\n $_SESSION['sessionAtom'] = $sessionAtom;\r\n addAtomToConcept($sessionAtom, 'SESSION', false);\r\n } else {\r\n $sessionAtom = $_SESSION['sessionAtom'];\r\n }\r\n // echo \"sessionAtom = [$sessionAtom]
\";\r\n \r\n $timeInSeconds = time();\r\n DB_doquer( \"INSERT INTO `__SessionTimeout__` (`SESSION`,`lastAccess`) VALUES ('$_SESSION[sessionAtom]','$timeInSeconds')\" \r\n . \"ON DUPLICATE KEY UPDATE `lastAccess` = '$timeInSeconds'\");\r\n // echo \"SessionAtom is $sessionAtom access is $timeInSeconds\";\r\n }\r\n}\r\n\r\nfunction resetSession() {\r\n global $allConcepts;\r\n \r\n if ($allConcepts['SESSION']) { // only execute session code when concept SESSION is used by adl script\r\n deleteSession($_SESSION['sessionAtom']);\r\n }\r\n}\r\n\r\nfunction deleteSession($sessionAtom) { // echo \"deleting $sessionAtom
\";\r\n DB_doquer(\"DELETE FROM `__SessionTimeout__` WHERE SESSION = '$sessionAtom';\");\r\n deleteAtom($sessionAtom, 'SESSION');\r\n}\r\n\r\n// Queries\r\nfunction DB_doquer($quer) {\r\n $result = DB_doquerErr($quer, $error);\r\n \r\n if ($error)\r\n die(\"
$error
\");\r\n return $result;\r\n}\r\n\r\nfunction DB_doquerErr($quer, &$error) {\r\n global $_SESSION; // when using $_SESSION, we get a nonsense warning if not declared global\r\n global $DB_link;\r\n global $DB_errs;\r\n \r\n // Replace the special atom value _SESSION by the current sessionAtom\r\n // NOTE: we only replace if the query contains _SESSION, otherwise the initialization DB_doquerErr calls will yield warnings.\r\n $quer = strpos($quer, '_SESSION') !== FALSE ? str_replace(\"_SESSION\", $_SESSION['sessionAtom'], $quer) : $quer;\r\n\r\n $result = mysqli_query($DB_link, $quer);\r\n if (!$result) {\r\n $error = 'Error ' . ($ernr = mysqli_errno($DB_link)) . ' in query \"' . $quer . '\": ' . mysqli_error($DB_link);\r\n return false;\r\n }\r\n if ($result === true)\r\n return true; // success.. but no contents..\r\n $rows = Array ();\r\n while ($row = mysqli_fetch_array($result)) {\r\n $rows[] = $row;\r\n unset($row);\r\n }\r\n return $rows;\r\n}\r\n\r\nfunction getSpecializations($concept) {\r\n global $allSpecializations;\r\n \r\n return isset($allSpecializations[$concept]) ? $allSpecializations[$concept] : array ();\r\n}\r\n\r\nfunction getView($concept) {\r\n global $allViews;\r\n \r\n foreach ($allViews as $view)\r\n if ($concept == $view['concept'] || in_array($concept, getSpecializations($view['concept'])))\r\n return $view;\r\n \r\n return null;\r\n}\r\n\r\nfunction showViewAtom($atom, $concept) {\r\n $viewDef = getView($concept);\r\n \r\n if (!$viewDef || $atom == '') {\r\n return $atom;\r\n } else {\r\n $viewStrs = array ();\r\n foreach ($viewDef['segments'] as $viewSegment)\r\n if ($viewSegment['segmentType'] == 'Text')\r\n $viewStrs[] = htmlSpecialChars($viewSegment['Text']);\r\n elseif ($viewSegment['segmentType'] == 'Html')\r\n $viewStrs[] = $viewSegment['Html'];\r\n else {\r\n if ($viewSegment['expSQL'] == \"\")\r\n ExecEngineSHOUTS(\"showViewAtom($atom, $concept)\");\r\n $r = getCoDomainAtoms($atom, $viewSegment['expSQL']);\r\n $txt = count($r) ? $r[0] : \"\";\r\n $viewStrs[] = htmlSpecialChars($txt);\r\n // this can happen in a create-new interface when the view fields have not yet been\r\n // filled out, while the atom is shown (but hidden by css) at the top.\r\n }\r\n return implode($viewStrs);\r\n }\r\n}\r\n\r\nfunction showPair($srcAtom, $srcConcept, $srcNrOfIfcs, $tgtAtom, $tgtConcept, $tgtNrOfIfcs, $pairView) {\r\n $srcHasInterfaces = $srcNrOfIfcs == 0 ? '' : ' hasInterface=' . ($srcNrOfIfcs == 1 ? 'single' : 'multiple');\r\n $tgtHasInterfaces = $tgtNrOfIfcs == 0 ? '' : ' hasInterface=' . ($tgtNrOfIfcs == 1 ? 'single' : 'multiple');\r\n \r\n if (count($pairView) == 0) {\r\n $source = showViewAtom($srcAtom, $srcConcept);\r\n $target = showViewAtom($tgtAtom, $tgtConcept);\r\n \r\n // if source and target are the same atom and we have a view for it, don't show a tuple\r\n if ($srcAtom == $tgtAtom && $srcConcept == $tgtConcept && getView($srcConcept))\r\n return \"\" \r\n . \"$source\"\r\n . \"\";\r\n else\r\n return \"(\" \r\n . \"'$source'\"\r\n . \", '$target'\"\r\n . \")\";\r\n } else {\r\n $pairStrs = array (\r\n \"\" );\r\n foreach ($pairView as $segment)\r\n if ($segment['segmentType'] == 'Text')\r\n $pairStrs[] = $segment['Text'];\r\n else {\r\n $atom = $segment['srcOrTgt'] == 'Src' ? $srcAtom : $tgtAtom;\r\n $concept = $segment['srcOrTgt'] == 'Src' ? $srcConcept : $tgtConcept;\r\n $hasInterfaces = $segment['srcOrTgt'] == 'Src' ? $srcHasInterfaces : $tgtHasInterfaces;\r\n if ($segment['expSQL'] == \"\")\r\n ExecEngineSHOUTS(\"showPair($srcAtom, $srcConcept, $srcNrOfIfcs, $tgtAtom, $tgtConcept, $tgtNrOfIfcs, $pairView)\");\r\n $r = getCoDomainAtoms($atom, $segment['expSQL']);\r\n \r\n // we label all expressionsegments as violation source or target based on the source of their expression\r\n $pairStrs[] = \"\";\r\n $pairStrs[] = showViewAtom($r[0], $segment['expTgt']) . \"\";\r\n }\r\n $pairStrs[] = \"\";\r\n return implode($pairStrs);\r\n }\r\n}\r\n\r\nfunction execPair($srcAtom, $srcConcept, $tgtAtom, $tgtConcept, $pairView) {\r\n $pairStrs = array ();\r\n foreach ($pairView as $segment) {\r\n if ($segment['segmentType'] == 'Text') {\r\n $pairStrs[] = $segment['Text'];\r\n } else {\r\n $atom = $segment['srcOrTgt'] == 'Src' ? $srcAtom : $tgtAtom;\r\n $concept = $segment['srcOrTgt'] == 'Src' ? $srcConcept : $tgtConcept;\r\n if ($segment['expSQL'] == \"\")\r\n ExecEngineSHOUTS(\"execPair($srcAtom, $srcConcept, $tgtAtom, $tgtConcept, $pairView)\");\r\n $r = getCoDomainAtoms($atom, $segment['expSQL']); // SRC of TGT kunnen door een expressie gevolgd worden\r\n $pairStrs[] = $r[0]; // Even er van uit gaan dat we maar 1 atoom kunnen behandelen...\r\n }\r\n }\r\n return implode($pairStrs);\r\n}\r\n\r\n// return an atom \"Concept_\" that is not in $existingAtoms (make sure that $existingAtoms covers all concept tables)\r\nfunction mkUniqueAtom($existingAtoms, $concept) {\r\n $generatedAtomNrs = array ();\r\n foreach (array_unique($existingAtoms) as $atom) {\r\n preg_match('/\\A' . $concept . '\\_(?P[123456789]\\d*)\\z/', $atom, $matches);\r\n // don't match nrs with leading 0's since we don't generate those\r\n $generatedAtomNrs[] = $matches['number'];\r\n }\r\n \r\n $generatedAtomNrs = array_filter($generatedAtomNrs); // filter out all the non-numbers (which are null)\r\n sort($generatedAtomNrs);\r\n foreach ($generatedAtomNrs as $i => &$nr) {\r\n if ($nr != $i + 1) // as soon as $generatedAtomNrs[i] != i+1, we arrived at a gap in the sorted number sequence and we can use i+1\r\n return $concept . '_' . ($i + 1);\r\n }\r\n return $concept . '_' . (count($generatedAtomNrs) + 1);\r\n}\r\n\r\nfunction mkUniqueAtomByTime($concept) {\r\n $time = explode(' ', microTime()); // yields [seconds,microseconds] both in seconds, e.g. [\"1322761879\", \"0.85629400\"]\r\n return $concept . '_' . $time[1] . \"_\" . substr($time[0], 2, 6); // we drop the leading \"0.\" and trailing \"00\" from the microseconds\r\n}\r\n\r\nfunction addAtomToConcept($newAtom, $concept, $shouldLog = false) { // Insert 'newAtom' only if it does not yet exist...\r\n global $allConcepts;\r\n \r\n if ($shouldLog)\r\n emitLog(\"adding to concept tables: $newAtom : $concept (\" . count($allConcepts[$concept]['conceptTables']) . \" columns)\");\r\n foreach ($allConcepts[$concept]['conceptTables'] as $conceptTableCol) {\r\n // $allConcepts[$concept]['conceptTables'] is an array of tables with arrays of columns maintaining $concept.\r\n // (we have an array rather than a single column because of generalizations)\r\n $conceptTable = $conceptTableCol['table'];\r\n $conceptCols = $conceptTableCol['cols']; // We insert the new atom in each of them.\r\n\r\n $conceptTableEsc = escapeSQL($conceptTable);\r\n $newAtomEsc = escapeSQL($newAtom);\r\n \r\n // invariant: all concept tables (which are columns) are maintained properly, so we can query an arbitrary one for checking the existence of a concept\r\n $firstConceptColEsc = escapeSQL($conceptCols[0]);\r\n \r\n $existingAtoms = firstCol(DB_doquer(\"SELECT `$firstConceptColEsc` FROM `$conceptTableEsc`\")); // no need to filter duplicates and NULLs\r\n\r\n if (!in_array($newAtom, $existingAtoms)) {\r\n $allConceptColsEsc = '`' . implode('`, `', $conceptCols) . '`';\r\n $newAtomsEsc = array_fill(0, count($conceptCols), $newAtomEsc);\r\n $allValuesEsc = \"'\" . implode(\"', '\", $newAtomsEsc) . \"'\";\r\n \r\n $query = \"INSERT INTO `$conceptTableEsc` ($allConceptColsEsc) VALUES ($allValuesEsc)\";\r\n if ($shouldLog)\r\n emitLog($query);\r\n DB_doquer($query);\r\n }\r\n }\r\n}\r\n\r\n// Remove all occurrences of $atom in the database (all concept tables and all relations)\r\n// In tables where the atom may not be null, the entire row is removed.\r\n// TODO: If all relation fields in a wide table are null, the entire row could be deleted, but this doesn't\r\n// happen now. As a result, relation queries may return some nulls, but these are filtered out anyway.\r\nfunction deleteAtom($atom, $concept) {\r\n global $tableColumnInfo;\r\n \r\n foreach ($tableColumnInfo as $table => $tableInfo)\r\n foreach ($tableInfo as $column => $fieldInfo) {\r\n // TODO: could be optimized by doing one query per table. But deleting per column yields the same result.\r\n // (unlike adding)\r\n if ($fieldInfo['concept'] == $concept) {\r\n $tableEsc = escapeSQL($table);\r\n $columnEsc = escapeSQL($column);\r\n $atomEsc = escapeSQL($atom);\r\n \r\n if ($fieldInfo['null']) // if the field can be null, we set all occurrences to null\r\n $query = \"UPDATE `$tableEsc` SET `$columnEsc`=NULL WHERE `$columnEsc`='$atomEsc';\";\r\n else // otherwise, we remove the entire row for each occurrence\r\n $query = \"DELETE FROM `$tableEsc` WHERE `$columnEsc` = '$atomEsc';\";\r\n // echo $query;\r\n DB_doquer($query);\r\n }\r\n }\r\n}\r\n\r\n// Currently not used. Javascript creates a unique name and index.php adds to to the concept in a temporary transaction.\r\nfunction createNewAtom($concept) {\r\n $newAtom = mkUniqueAtomByTime($concept);\r\n \r\n addAtomToConcept($newAtom, $concept, false);\r\n return $newAtom;\r\n}\r\n\r\n/* invariant: all concept tables (which are columns) are maintained properly, so we can query an arbitrary one to obtain the list of atoms */\r\nfunction getAllConceptAtoms($concept) {\r\n global $allConcepts;\r\n \r\n $conceptTable = $allConcepts[$concept]['conceptTables'][0]['table']; // $allConcepts[$concept]['conceptTables'] is an array of tables with arrays of columns maintaining $concept\r\n $conceptCol = $allConcepts[$concept]['conceptTables'][0]['cols'][0]; // for lookup, we just take the first table and its first column\r\n $conceptTableEsc = escapeSQL($conceptTable);\r\n $conceptColEsc = escapeSQL($conceptCol);\r\n \r\n // need to do array_unique and array_filter, since concept table may contain duplicates and NULLs\r\n // TODO: more elegant to filter dups and nulls in SQL: (\"SELECT DISTINCT `$conceptColEsc` FROM `$conceptTableEsc` WHERE `$conceptColEsc` IS NOT NULL\")\r\n return array_unique(array_filter(firstCol(DB_doquer(\"SELECT `$conceptColEsc` FROM `$conceptTableEsc`\")),'notNull')); \r\n} \r\n\r\nfunction notNull($atom) { // need a type-based comparison, otherwise 0 is also null\r\n return $atom !== null;\r\n}\r\n\r\nfunction isAtomInConcept($atom, $concept) {\r\n return in_array($atom, getAllConceptAtoms($concept));\r\n}\r\n\r\nfunction getRelationContents($relationInfo) {\r\n global $allRelations;\r\n $table = $relationInfo['table'];\r\n $srcCol = $relationInfo['srcCol'];\r\n $tgtCol = $relationInfo['tgtCol'];\r\n \r\n $tableEsc = escapeSQL($table);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n\r\n $query = \"SELECT `$srcColEsc` as `src`, `$tgtColEsc` as `tgt` FROM `$tableEsc` WHERE `$srcColEsc` IS NOT NULL AND `$tgtColEsc` IS NOT NULL\";\r\n $pairs = queryDb($query);\r\n return $pairs;\r\n}\r\n\r\n\r\nfunction isInterfaceForRole($interface, $roleNr) {\r\n return $roleNr == -1 || count($interface['interfaceRoles']) == 0 || in_array(getRoleName($roleNr), $interface['interfaceRoles']);\r\n // an interface is visible if: no role is selected; the interface does not specify roles; or the interface roles contain $role\r\n}\r\n\r\nfunction getTopLevelInterfacesForConcept($concept, $roleNr) {\r\n global $allInterfaceObjects;\r\n $interfacesForConcept = array ();\r\n foreach ($allInterfaceObjects as $interface) {\r\n if ( ($interface['srcConcept'] == $concept || in_array($concept, getSpecializations($interface['srcConcept']))) \r\n && isInterfaceForRole($interface, $roleNr) )\r\n $interfacesForConcept[] = $interface;\r\n }\r\n return $interfacesForConcept;\r\n}\r\n\r\nfunction getNrOfInterfaces($concept, $roleNr) {\r\n return count(getTopLevelInterfacesForConcept($concept, $roleNr));\r\n}\r\n\r\n\r\n// Misc utils\r\n\r\nfunction getRoleName($roleNr) {\r\n global $allRoles;\r\n \r\n return $roleNr == -1 ? 'Algemeen' : $allRoles[$roleNr]['name'];\r\n}\r\n\r\nfunction firstRow($rows) {\r\n return $rows[0];\r\n}\r\n\r\nfunction firstCol($rows) {\r\n foreach ($rows as $i => &$v)\r\n $v = $v[0];\r\n return $rows;\r\n}\r\n\r\nfunction targetCol($rows) {\r\n foreach ($rows as $i => &$v)\r\n $v = $v['tgt'];\r\n return $rows;\r\n}\r\n\r\nfunction getCoDomainAtoms($atom, $selectRel) {\r\n // ExecEngineWhispers(\">> getCoDomainAtoms($atom, $selectRel)\");\r\n return targetCol(DB_doquer(selectCoDomain($atom, $selectRel)));\r\n}\r\n\r\nfunction selectCoDomain($atom, $selectRel) {\r\n return 'SELECT DISTINCT `tgt` FROM (' . $selectRel . ') AS results WHERE src=\\'' . escapeSQL($atom) . '\\'';\r\n}\r\n\r\n\r\n// Timestamps\r\n\r\n// return the most recent modification time for the database (only Ampersand edit operations are recorded)\r\nfunction getTimestamp(&$error) {\r\n $timestampRow = DB_doquerErr(\"SELECT MAX(`Seconds`) FROM `__History__`\", $error);\r\n \r\n if ($error)\r\n return '0';\r\n else\r\n return $timestampRow[0][0];\r\n}\r\n\r\n// set modification timestamp to the current time\r\nfunction setTimestamp() {\r\n $time = explode(' ', microTime()); // yields [seconds,microseconds] both in seconds, e.g. [\"1322761879\", \"0.85629400\"]\r\n $microseconds = substr($time[0], 2,6); // we drop the leading \"0.\" and trailing \"00\" from the microseconds\r\n $seconds =$time[1].$microseconds; \r\n date_default_timezone_set('Europe/Amsterdam');\r\n $date = date(\"j-M-Y, H:i:s.\").$microseconds; \r\n DB_doquer(\"INSERT INTO `__History__` (`Seconds`,`Date`) VALUES ('$seconds','$date')\");\r\n // TODO: add error checking\r\n}\r\n\r\n\r\n// Dump population to ADL\r\n\r\nfunction getPopulationADL() {\r\n global $dbName;\r\n global $contextName;\r\n global $versionInfo;\r\n global $allConcepts;\r\n global $allRelations;\r\n\r\n date_default_timezone_set('Europe/Amsterdam');\r\n $date = date(\"j-M-Y at H:i:s\");\r\n $adl = \"CONTEXT {$contextName}_PopulationDump IN ENGLISH\\n\"\r\n . \"-- Population dump for database '$dbName' (context: '$contextName') on $date\\n\"\r\n . \"-- Generated by $versionInfo.\\n\\n\";\r\n foreach (array_keys($allConcepts) as $concept) {\r\n if ($concept != \"ONE\") { \r\n $conceptEsc = escapeAndQuote($concept);\r\n $adl .= \"POPULATION $conceptEsc CONTAINS \".showAtomListADL(getAllConceptAtoms($concept)).\"\\n\";\r\n }\r\n }\r\n foreach ($allRelations as $relationInfo) {\r\n $srcEsc = escapeAndQuote($relationInfo[srcConcept]);\r\n $tgtEsc = escapeAndQuote($relationInfo[tgtConcept]);\r\n $adl .= \"$relationInfo[name] :: $srcEsc * $tgtEsc = \"\r\n . showPairListADL(getRelationContents($relationInfo)).\"\\n\";\r\n }\r\n $adl .= \"ENDCONTEXT\";\r\n echo $adl;\r\n}\r\n\r\n// ADL generation utils\r\n\r\nfunction showPairListADL($pairs) {\r\n return '['. implode(';', array_map('showPairADL', $pairs)) .']';\r\n}\r\n\r\nfunction showPairADL($pair) {\r\n return '('.escapeAndQuote($pair['src']).','.escapeAndQuote($pair['tgt']).')';\r\n}\r\n\r\nfunction showAtomListADL($atoms) {\r\n return '['. implode(',', array_map('escapeAndQuote', $atoms)) .']';\r\n} \r\n\r\nfunction escapeAndQuote($str) {\r\n return '\"'.addslashes($str).'\"';\r\n}\r\n\r\n// Html generation utils\r\n\r\nfunction printBinaryTable($table) {\r\n echo '';\r\n foreach ($table as $row)\r\n echo '';\r\n echo '
' . $row['src'] . ' ' . $row['tgt'] . ' 
';\r\n}\r\n\r\nfunction echoLn($str) {\r\n echo $str . '
';\r\n}\r\n\r\nfunction emit(&$lines, $line) {\r\n $lines .= $line . \"\\n\";\r\n}\r\n\r\n// for use in specifiying values for attributes to html elements (eg.
)\r\n// \" -> ",\r\nfunction showHtmlAttrStr($str) {\r\n return '\"' . escapeHtmlAttrStr($str) . '\"';\r\n}\r\n\r\nfunction showHtmlAttrBool($b) {\r\n return $b ? '\"true\"' : '\"false\"';\r\n}\r\n\r\nfunction escapeHtmlAttrStr($str) {\r\n return str_replace(array ('\"'), array ('"'), $str); // we do escapeSQL and replace \\\" by " and \\' by '\r\n}\r\n\r\nfunction showJsStr($str) {\r\n return \"'\" . escapeJsStr($str) . \"'\";\r\n}\r\n\r\nfunction escapeJsStr($str) {\r\n return escapeSQL($str);\r\n}\r\n\r\n// This is needed for non-javascript urls, where javascript would call encodeURIComponent\r\n// We only handle the &, the browser takes care of the rest.\r\nfunction escapeURI($str) {\r\n return str_replace(array ('&'), array ('%26'), $str); // replace & by %26\r\n}\r\n\r\nfunction escapeSQL($str) {\r\n return addslashes($str);\r\n}\r\n?>\r\n" , SF False ".\\php\\Database.php" 1429178701 {-2015-04-16 10:05:01 UTC -} "';\r\n \r\n if ($_REQUEST['interface']) {\r\n $interface = urldecode($_REQUEST['interface']);\r\n } else {\r\n error(\"Parameter 'interface' not present in POST request\");\r\n }\r\n \r\n dbStartTransaction();\r\n \r\n processCommands(); // update database according to edit commands\r\n \r\n $conjunctViolationCache = array (); // array of arrays of violations, indexed by conjunct id, for caching conjuncts evaluated during rule checking/reporting\r\n // Haskell(ish) type: $conjunctViolationCache :: [ (ConjuncId, [(Src, Tgt)]) ]\r\n \r\n echo '
';\r\n $invariantRulesHold = checkInvariants($interface, $conjunctViolationCache);\r\n echo '
';\r\n \r\n // updateSignals is separate from checkInvariants, because we might not want to update signals when invariants fail\r\n // (in which case, updateSignals would be called after 'if ($invariantRulesHold)' below)\r\n updateSignals($interface, $conjunctViolationCache);\r\n echo '
';\r\n reportSignals($selectedRoleNr, $conjunctViolationCache);\r\n echo '
';\r\n\r\n if ($invariantRulesHold) {\r\n setTimeStamp();\r\n dbCommitTransaction();\r\n } else {\r\n dbRollbackTransaction();\r\n }\r\n echo '
';\r\n}\r\n\r\nfunction processCommands()\r\n{ $commandsJson = $_POST['commands']; \r\n if (isset($commandsJson))\r\n processCommandsJson($commandsJson);\r\n}\r\n\r\nfunction processCommandsJson($commandsJson)\r\n{ $commandArray = json_decode($commandsJson);\r\n foreach ($commandArray as $command) processCommand($command);\r\n}\r\n\r\nfunction processCommand($command) {\r\n if (!isset($command->dbCmd))\r\n error(\"Malformed command, missing 'dbCmd'\");\r\n switch ($command->dbCmd) {\r\n case 'addToConcept':\r\n if (array_key_exists('atom', $command) && array_key_exists('concept', $command))\r\n editAddToConcept($command->atom, $command->concept);\r\n else\r\n error(\"Command $command->dbCmd is missing parameters\");\r\n break;\r\n case 'update':\r\n if (array_key_exists('relation', $command) && array_key_exists('isFlipped', $command) &&\r\n array_key_exists('parentAtom', $command) && array_key_exists('parentConcept', $command) &&\r\n array_key_exists('childAtom', $command) && array_key_exists('childConcept', $command) &&\r\n array_key_exists('parentOrChild', $command) && array_key_exists('originalAtom', $command))\r\n editUpdate($command->relation, $command->isFlipped, $command->parentAtom, $command->parentConcept,\r\n $command->childAtom, $command->childConcept, $command->parentOrChild, $command->originalAtom);\r\n else\r\n error(\"Command $command->dbCmd is missing parameters\");\r\n break;\r\n case 'delete':\r\n if (array_key_exists('relation', $command) && array_key_exists('isFlipped', $command) &&\r\n array_key_exists('parentAtom', $command) && array_key_exists('childAtom', $command))\r\n editDelete($command->relation, $command->isFlipped, $command->parentAtom, $command->childAtom);\r\n else\r\n error(\"Command $command->dbCmd is missing parameters\");\r\n break;\r\n default :\r\n error(\"Unknown command '$command->dbCmd'\");\r\n }\r\n}\r\n\r\nfunction editAddToConcept($atom, $concept) {\r\n emitLog(\"editAddToConcept($atom, $concept)\");\r\n addAtomToConcept($atom, $concept, true);\r\n}\r\n\r\n// NOTE: if $originalAtom == '', editUpdate means insert\r\nfunction editUpdate($rel, $isFlipped, $parentAtom, $parentConcept, $childAtom, $childConcept, $parentOrChild, $originalAtom) {\r\n global $allRelations;\r\n global $tableColumnInfo;\r\n \r\n emitLog(\"editUpdate($rel, \" . ($isFlipped ? 'true' : 'false') . \", $parentAtom, $childAtom, $parentOrChild, $originalAtom)\");\r\n /* There seems to be a bug in 'editUpdate', nl. when a $relation occurs multiple times as KEY in the relationTableInfo (which we have seen happening when you overload an (Ampersand) relation (name). The following code may be used to find the right entry in the relationTableInfo, but that is not used by 'editUpdate'.\r\n // check if $relation appears in $allRelations\r\n if (array_key_exists($relation, $allRelations))\r\n { foreach($allRelations as $key => $arr)\r\n if($key == $relation)\r\n { if($arr['srcConcept'] == $srcConcept && $arr['tgtConcept'] == $tgtConcept)\r\n { $table = $arr['table'];\r\n $srcCol = $arr['srcCol'];\r\n $tgtCol = $arr['tgtCol'];\r\n echo \"
[FOUND: table=$table, srcCol=$srcCol, tgtCol=$tgtCol]\";\r\n }\r\n }\r\n } else\r\n { echo \"ERROR: Relation $relation does not exist (in table info)\";\r\n }\r\n*/\r\n $table = $allRelations[$rel]['table'];\r\n $srcCol = $allRelations[$rel]['srcCol'];\r\n $tgtCol = $allRelations[$rel]['tgtCol'];\r\n $parentCol = $isFlipped ? $tgtCol : $srcCol;\r\n $childCol = $isFlipped ? $srcCol : $tgtCol;\r\n \r\n $stableConcept = $parentOrChild == 'parent' ? $childConcept : $parentConcept;\r\n $modifiedConcept = $parentOrChild == 'parent' ? $parentConcept : $childConcept;\r\n $modifiedCol = $parentOrChild == 'parent' ? $parentCol : $childCol;\r\n $modifiedAtom = $parentOrChild == 'parent' ? $parentAtom : $childAtom;\r\n $stableCol = $parentOrChild == 'parent' ? $childCol : $parentCol;\r\n $stableAtom = $parentOrChild == 'parent' ? $childAtom : $parentAtom;\r\n \r\n $tableEsc = escapeSQL($table);\r\n $modifiedColEsc = escapeSQL($modifiedCol);\r\n $stableColEsc = escapeSQL($stableCol);\r\n $modifiedAtomEsc = escapeSQL($modifiedAtom);\r\n $stableAtomEsc = escapeSQL($stableAtom);\r\n $originalAtomEsc = escapeSQL($originalAtom);\r\n \r\n // ensure that the $modifiedAtom is in the concept tables for $modifiedConcept\r\n addAtomToConcept($modifiedAtom, $modifiedConcept, true);\r\n // TODO: errors here are not reported correctly\r\n \r\n // only if the stable column is unique, we do an update\r\n // TODO: maybe we can do updates also in non-unique columns\r\n// emitLog('table ' . $table . ' col ' . $stableCol . ' ' . $tableColumnInfo[$table][$stableCol]['unique']);\r\n if ($tableColumnInfo[$table][$stableCol]['unique']) { // note: this uniqueness is not set as an SQL table attribute\r\n $query = \"UPDATE `$tableEsc` SET `$modifiedColEsc`='$modifiedAtomEsc' WHERE `$stableColEsc`='$stableAtomEsc'\";\r\n emitLog($query);\r\n queryDb($query);\r\n } elseif ($tableColumnInfo[$table][$modifiedCol]['unique']) { // todo: is this ok? no, we'd also have to delete stableAtom originalAtom and check if modified atom even exists, otherwise we need an insert, not an update.\r\n $query = \"UPDATE `$tableEsc` SET `$stableColEsc`='$stableAtomEsc' WHERE `$modifiedColEsc`='$modifiedAtomEsc'\";\r\n emitLog($query);\r\n queryDb($query);\r\n } else {\r\n if ($originalAtom != '') { // delete only if there was an $originalAtom \r\n $query = \"DELETE FROM `$tableEsc` WHERE `$stableColEsc`='$stableAtomEsc' AND `$modifiedColEsc`='$originalAtomEsc';\";\r\n emitLog($query);\r\n queryDb($query);\r\n }\r\n \r\n //$stableSuperColsEsc = array_map(escapeSQL, getSuperColumns($table, $stableConcept ));\r\n //$modifiedSuperColsEsc = array_map(escapeSQL, getSuperColumns($table, $modifiedConcept));\r\n //emitLog('$stableSuperColsEsc: '.var_export($stableSuperColsEsc, true));\r\n //emitLog('$modifiedSuperColsEsc: '.var_export($modifiedSuperColsEsc, true));\r\n \r\n $query = \"INSERT INTO `$tableEsc` (`$stableColEsc`, `$modifiedColEsc`) VALUES ('$stableAtomEsc', '$modifiedAtomEsc')\";\r\n emitLog($query);\r\n queryDb($query);\r\n }\r\n}\r\n\r\nfunction getSuperColumns($table, $concept) {\r\n global $tableColumnInfo;\r\n \r\n // won't work. there is not enough info in generics.php to determine the appropriate super columns\r\n // (if the concept of a column is a superconcept of $concept, it may also be in one of the relation target fields instead of the kernel,\r\n // in which case we should not touch it)\r\n emitLog('Get super columns in table ' . $table . ' for concept ' . $concept);\r\n $tableInfo = $tableColumnInfo[$table];\r\n foreach ($tableInfo as $column => $fieldInfo) {\r\n emitLog('column: ' . $column . ' ');\r\n }\r\n \r\n return array ();\r\n}\r\n\r\nfunction editDelete($rel, $isFlipped, $parentAtom, $childAtom) {\r\n global $allRelations;\r\n global $tableColumnInfo;\r\n \r\n emitLog(\"editDelete($rel, \" . ($isFlipped ? 'true' : 'false') . \", $parentAtom, $childAtom)\");\r\n $srcAtom = $isFlipped ? $childAtom : $parentAtom;\r\n $tgtAtom = $isFlipped ? $parentAtom : $childAtom;\r\n \r\n $table = $allRelations[$rel]['table'];\r\n $srcCol = $allRelations[$rel]['srcCol'];\r\n $tgtCol = $allRelations[$rel]['tgtCol'];\r\n \r\n $tableEsc = escapeSQL($table);\r\n $srcAtomEsc = escapeSQL($srcAtom);\r\n $tgtAtomEsc = escapeSQL($tgtAtom);\r\n $srcColEsc = escapeSQL($srcCol);\r\n $tgtColEsc = escapeSQL($tgtCol);\r\n \r\n if ($tableColumnInfo[$table][$tgtCol]['null']) // note: this uniqueness is not set as an SQL table attribute\r\n $query = \"UPDATE `$tableEsc` SET `$tgtColEsc`=NULL WHERE `$srcColEsc`='$srcAtomEsc' AND `$tgtColEsc`='$tgtAtomEsc';\";\r\n else\r\n $query = \"DELETE FROM `$tableEsc` WHERE `$srcColEsc`='$srcAtomEsc' AND `$tgtColEsc`='$tgtAtomEsc';\";\r\n \r\n emitLog($query);\r\n queryDb($query);\r\n}\r\n\r\n// new function\r\nfunction runAllProcedures() {\r\n $query = \"CALL AllProcedures\";\r\n emitLog($query);\r\n queryDb($query);\r\n}\r\n\r\n\r\n\r\n\r\n//// TODO: rule-checking code should move to a different module (e.g. Eval.php) but is kept here for now to allow easy access\r\n// to the history while fixing the exec engine functionality.\r\n\r\n\r\n\r\n// TODO: add ExecEngine support\r\nfunction checkInvariants($interface, &$conjunctViolationCache) {\r\n global $allInterfaceObjects;\r\n global $allRoles;\r\n global $allRules;\r\n global $allConjuncts;\r\n\r\n $invConjunctIds = $allInterfaceObjects[$interface]['invConjunctIds'];\r\n //emitLog(\"Checking invariant rules for interface \".$interface);\r\n //emitLog(\"Corresponding conjuncts: \".print_r($conjunctIds, true));\r\n\r\n $violationsPerRule = computeAllViolationsPerRule($invConjunctIds, $conjunctViolationCache);\r\n \r\n // Report violations for each rule\r\n foreach ($violationsPerRule as $ruleName => $violations) {\r\n $rule = $allRules[$ruleName];\r\n emitAmpersandLog( brokenRuleMessage($rule) );\r\n foreach ( violationMessages($roleNr, $rule, $violations) as $msg )\r\n emitAmpersandLog( $msg );\r\n }\r\n\r\n return count($violationsPerRule) == 0;\r\n}\r\n\r\nfunction computeAllViolationsPerRule($invConjunctIds, &$conjunctViolationCache) {\r\n global $allConjuncts;\r\n\r\n $violationsPerRule = array (); // will contain all violations, indexed by rule name\r\n foreach ($invConjunctIds as $conjunctId) {\r\n // evaluate each conjunct that and store violations in $violationsPerRule\r\n\r\n $conjunct = $allConjuncts[$conjunctId];\r\n $ruleNames = $conjunct['invariantRuleNames'];\r\n $ruleNamesStr = \"invariants: [\".join(\",\", $ruleNames).\"]\";\r\n \r\n $violationsSQL = $conjunct['violationsSQL'];\r\n $error = '';\r\n emitLog(\"SQL eval conjunct $conjunctId (for $ruleNamesStr)\");\r\n $conjunctViolations = DB_doquerErr($violationsSQL, $error); // execute violationsSQL to check for violations\r\n if ($error)\r\n error(\"While evaluating conjunct $conjunctId ($ruleNamesStr):\\n\" . $error);\r\n $conjunctViolationCache[$conjunctId] = $conjunctViolations;\r\n // cache violations so we don't need to re-evaluate on updating signal tables\r\n // NOTE: since we loop over the conjuncts rather than the invariants, there is no need to\r\n // use the cache within the invariant checking (no evaluated conjuncts will be encountered)\r\n \r\n if (count($conjunctViolations) == 0) {\r\n emitLog(\"Conjunct $conjunctId ($ruleNamesStr) holds\"); // log successful conjunct validation\r\n } else {\r\n emitLog(\"Conjunct $conjunctId ($ruleNamesStr) is broken\");\r\n \r\n // store this conjunct's violations for its originating rules in $violationsPerRule\r\n foreach($ruleNames as $ruleName) { \r\n $rule = $allRules[$ruleName]; \r\n if (!$violationsPerRule[ $ruleName ])\r\n $violationsPerRule[ $ruleName ] = array ();\r\n \r\n $violationsPerRule[$ruleName] = array_merge( $violationsPerRule[ $ruleName ], $conjunctViolations);\r\n }\r\n }\r\n }\r\n \r\n return $violationsPerRule;\r\n}\r\n\r\n// TODO: add ExecEngine support\r\nfunction updateSignals($interface, $conjunctViolationCache) {\r\n // $conjunctViolationCache contains violations for already evaluated conjuncts (during invariant checking)\r\n // if updateSignals is only called on succesful invariant checking, the cached conjuncts will always have 0 violations.\r\n // Since any SQL evaluation is kept at the MySQL server by INSERTing it immediately, the cache is not modified here\r\n // and $conjunctViolationCache is not a reference parameter.\r\n \r\n global $signalTableName;\r\n global $allInterfaceObjects;\r\n global $allRules;\r\n global $allConjuncts;\r\n\r\n $sigConjunctIds = $allInterfaceObjects[$interface]['sigConjunctIds'];\r\n //emitLog(\"Checking signals for interface '$interface'\");\r\n //emitLog(\"Conjuncts: [\".join(',',$sigConjunctIds).\"]\");\r\n \r\n // Remove all signal conjunct violations for this interface from the signal table\r\n queryDb(\"DELETE FROM `$signalTableName` \".mkWhereDisjunction($sigConjunctIds));\r\n\r\n $signalTableRows = array ();\r\n foreach ($sigConjunctIds as $conjunctId) {\r\n $conjunct = $allConjuncts[$conjunctId];\r\n $ruleNames = $conjunct['signalRuleNames'];\r\n \r\n //emitLog('Checking conjunct: ' . $conjunctId . ', signal table: ' . $signalTableName);\r\n //emitLog(\"Coming from (signals: [\".join(\",\", $ruleNames).\"])\");\r\n\r\n $evaluatedConjunct = $conjunctViolationCache[$conjunctId];\r\n if (isset($evaluatedConjunct)) { // the conjunct has already been evaluated\r\n emitLog(\"update: Cached SQL eval conjunct: $conjunctId\");\r\n\r\n $conjunctViolationRows = array_map(function($violation) use ($conjunctId){\r\n return array('conjId' => $conjunctId, 'src' => escapeSQL($violation['src']), 'tgt' => escapeSQL($violation['tgt']));\r\n }, $evaluatedConjunct);\r\n $signalTableRows = array_merge($signalTableRows, $conjunctViolationRows);\r\n //emitLog('Rows: '.print_r($conjunctViolationRows, true));\r\n\r\n } else {\r\n // Compute and insert the new violations.\r\n $violationsSQL = $conjunct['violationsSQL']; \r\n emitLog(\"SQL local eval signal conjunct $conjunctId\");\r\n $query = \"INSERT INTO `$signalTableName`\"\r\n . \" SELECT '$conjunctId' AS conjId, violations.src, violations.tgt\"\r\n . \" FROM ($violationsSQL) AS violations\";\r\n //emitLog($query);\r\n queryDb($query);\r\n } \r\n }\r\n \r\n if (count($signalTableRows) > 0 ) { // only insert when violations>0 (sql doesn't handle empty lists elegantly)\r\n $valueTuples =array_map(function($row) {\r\n return \"('\".$row['conjId'].\"','\".$row['src'].\"','\".$row['tgt'].\"')\";\r\n }, $signalTableRows);\r\n $query = \"INSERT INTO `$signalTableName` (conjId,src,tgt) VALUES \". implode(',', $valueTuples);\r\n emitLog($query);\r\n queryDb($query);\r\n }\r\n}\r\n\r\nfunction reportSignals($roleNr, $conjunctViolationCache = array()) {\r\n // $conjunctViolationCache contains violations for already evaluated conjuncts (during invariant checking)\r\n // if reportSignals is only called on succesful invariant checking, the cached conjuncts will always have 0 violations.\r\n \r\n global $signalTableName;\r\n global $allRoles;\r\n global $allRules;\r\n $allRoleRules = array ();\r\n //emitAmpersandLog('$conjunctViolationCache = '.print_r($conjunctViolationCache,true));\r\n \r\n // Compute $allRoleRules (the process rules that need to be reported to this role)\r\n if ($roleNr == -1) { // if no role is selected, evaluate the rules for all roles\r\n for ($r = 0; $r < count($allRoles); $r++) { \r\n if ($allRoles[$r]['name'] != 'DATABASE') { // filter rules for role 'DATABASE', these will be handled by runAllProcedures() \r\n $allRoleRules = array_merge((array)$allRoleRules, $allRoles[$r]['ruleNames']); // merge process rules of all roles\r\n }\r\n }\r\n $allRoleRules = array_unique((array)$allRoleRules); // remove duplicate ruleNames\r\n } else {\r\n $role = $allRoles[$roleNr];\r\n $allRoleRules = $role['ruleNames'];\r\n } \r\n //emitAmpersandLog('$allRoleRules: '.print_r($allRoleRules,true));\r\n \r\n // Determine which conjunctIds need to be looked up in the SQL signal table\r\n $lookupConjunctIds = array ();\r\n foreach ($allRoleRules as $ruleName) {\r\n //emitAmpersandLog(\"Rule: $ruleName\");\r\n $rule = $allRules[$ruleName];\r\n if (!$rule)\r\n error(\"Rule \\\"$ruleName\\\" does not exist.\");\r\n \r\n foreach ($rule['conjunctIds'] as $conjunctId) {\r\n if ($conjunctViolationCache[$conjunctId]) {\r\n //emitAmpersandLog(\"report: Cached SQL eval conjunct: $conjunctId\");\r\n } else { // the conjunct is not in the cache, so we look it up in the SQL signal table\r\n //emitAmpersandLog(\"report: SQL lookup queued for conjunct $conjunctId (for signal $ruleName)\");\r\n $lookupConjunctIds[] = $conjunctId;\r\n }\r\n }\r\n }\r\n $lookupConjunctIds = array_unique($lookupConjunctIds); // Remove duplicates\r\n foreach ($lookupConjunctIds as $conjunctId) { // Insert empty arrays in cache, in case sql does not return violations for the conjunct\r\n $conjunctViolationCache[$conjunctId] = array ();\r\n }\r\n //emitAmpersandLog('-conjunct id: '.$conjunctId.' table: '.$signalTableName);\r\n $query = \"SELECT conjId, src,tgt FROM `$signalTableName` \".mkWhereDisjunction($lookupConjunctIds);\r\n //emitAmpersandLog('Conjunct lookup on conjuncts: ['.join(',',$lookupConjunctIds).']');\r\n //emitAmpersandLog('Query: '.$query);\r\n $signalTableRows = queryDb($query); // query all non-cached signal conjuncts\r\n \r\n foreach ($signalTableRows as $signalTableRow) { // and add them to the cache\r\n $conjunctViolationCache[$signalTableRow['conjId']][] = array ('src' => $signalTableRow['src'], 'tgt' => $signalTableRow['tgt']);\r\n }\r\n \r\n //emitAmpersandLog('$conjunctViolationCache = '.print_r($conjunctViolationCache,true));\r\n\r\n // Iterate over the process rules again to report violations per rule\r\n foreach ($allRoleRules as $ruleName) {\r\n //emitAmpersandLog(\"Rule: $ruleName\");\r\n $rule = $allRules[$ruleName];\r\n \r\n //emitLog('reporting signal: '.$ruleName);\r\n $ruleViolations = array ();\r\n \r\n foreach ($rule['conjunctIds'] as $conjunctId) {\r\n //emitAmpersandLog(\"Reporting conjunct $conjunctId\");\r\n $ruleViolations = array_merge($ruleViolations, $conjunctViolationCache[$conjunctId]);\r\n //emitAmpersandLog(\"done\");\r\n }\r\n \r\n if (count($ruleViolations) > 0) { \r\n emitAmpersandLog( brokenRuleMessage($rule) );\r\n foreach ( violationMessages($roleNr, $rule, $ruleViolations) as $msg )\r\n emitAmpersandLog( $msg );\r\n }\r\n }\r\n}\r\n\r\n// returns \"WHERE conjId = $conjunctIds[0] OR .. OR conjId = $conjunctIds[n-1]\" \r\nfunction mkWhereDisjunction($conjunctIds) {\r\n if (count($conjunctIds) > 0) {\r\n return 'WHERE '.implode(' OR ', array_map( function($conjunctId) {return \"conjId = '$conjunctId'\";}, $conjunctIds));\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nfunction brokenRuleMessage($rule) {\r\n // if the rule has an associated message, we show that instead of the name and the meaning\r\n return $rule['message'] ? $rule['message'] : \"Rule '$rule[name]' is broken: $rule[meaning]\";\r\n}\r\n\r\nfunction violationMessages($roleNr, $rule, $violations) {\r\n $srcNrOfIfcs = getNrOfInterfaces($rule['srcConcept'], $roleNr);\r\n $tgtNrOfIfcs = getNrOfInterfaces($rule['tgtConcept'], $roleNr);\r\n \r\n $pairView = $rule['pairView']; // pairView contains an array with the fragments of the violations message (if specified)\r\n \r\n $msgs = array ();\r\n \r\n $violationsNoDups = array_map(\"unserialize\", array_unique(array_map(\"serialize\", $violations)));\r\n // Not the most elegant way to remove duplicates, but then again, this is php.\r\n \r\n foreach ($violationsNoDups as $violation) {\r\n $pair = showPair($violation['src'], $rule['srcConcept'], $srcNrOfIfcs, $violation['tgt'], $rule['tgtConcept'], $tgtNrOfIfcs, $pairView);\r\n array_push($msgs, '- ' . $pair);\r\n }\r\n return $msgs;\r\n}\r\n\r\n// Numbering transactions allows optimization of ExecEngine rules, e.g. transitive closure computations.\r\nfunction dbStartTransaction() {\r\n emitLog('START TRANSACTION');\r\n queryDb('START TRANSACTION');\r\n}\r\n\r\nfunction dbCommitTransaction() {\r\n emitLog('COMMIT');\r\n queryDb('COMMIT');\r\n}\r\n\r\nfunction dbRollbackTransaction() {\r\n emitLog('ROLLBACK');\r\n queryDb('ROLLBACK');\r\n}\r\n\r\nfunction queryDb($querySql) {\r\n $result = DB_doquerErr($querySql, $error);\r\n if ($error)\r\n error($error);\r\n \r\n return $result;\r\n}\r\n\r\nfunction ExecEngineWhispers($msg) {\r\n global $execEngineWhispers; // set in 'pluginsettings.php'\r\n global $execEngineSays; // set in 'pluginsettings.php'\r\n if ($execEngineWhispers && $execEngineSays)\r\n echo \"
$msg
\";\r\n}\r\n\r\nfunction ExecEngineSays($msg) {\r\n global $execEngineSays; // set in 'pluginsettings.php'\r\n if ($execEngineSays)\r\n echo \"
$msg
\";\r\n}\r\n\r\nfunction ExecEngineSHOUTS($msg) {\r\n echo \"
$msg
\";\r\n}\r\n\r\nfunction emitAmpersandLog($msg) {\r\n echo \"
$msg
\\n\";\r\n}\r\n\r\nfunction emitLog($msg) {\r\n echo \"
$msg
\\n\";\r\n}\r\n\r\nfunction error($err) {\r\n die(\"
Error in Database.php: $err
\");\r\n} // because of this die, the top-level div is not closed, but that's better than continuing in an erroneous situtation\r\n // the current php session is broken off, which corresponds to a rollback. (doing an explicit roll back here is awkward\r\n // since it may trigger an error again, causing a loop)\r\n \r\nfunction testRule($ruleName) {\r\n global $isDev;\r\n global $allRules;\r\n global $allConjuncts;\r\n \r\n if (!$isDev) {\r\n echo \"Rule test unavailable: prototype was not generated with --dev option.\";\r\n return;\r\n }\r\n if (!$allRules[$ruleName]) {\r\n echo \"Error: rule \\\"$ruleName\\\" does not exist.\";\r\n return;\r\n }\r\n \r\n echo \"Reset database\";\r\n echo \"

Testing rule $ruleName

\";\r\n $rule = $allRules[$ruleName];\r\n $ruleAdl = escapeHtmlAttrStr($rule['ruleAdl']);\r\n echo \"ADL: $ruleAdl
\";\r\n echo \"Conjunct ids: [\".join(\",\", $rule['conjunctIds']).\"]\";\r\n echo \"

Rule SQL

$rule[contentsSQL]

results:

\";\r\n\r\n\r\n $rows = queryDb($rule['contentsSQL']);\r\n printBinaryTable($rows);\r\n \r\n foreach ($rule['conjunctIds'] as $conjunctId) {\r\n $conjunct = $allConjuncts[$conjunctId];\r\n echo \"

Violation SQL conjunct $conjunctId

$conjunct[violationsSQL]

Conjunct violations:

\";\r\n $rows = queryDb($conjunct['violationsSQL']);\r\n printBinaryTable($rows);\r\n }\r\n}\r\n\r\nfunction timestampHtml() {\r\n $timestamp = getTimestamp($error);\r\n if ($error) // Show error if there is one. If there is a problem, we will be able to trace it in the browser network log.\r\n echo \"SQL error while fetching timestamp:\\n\".$error.\"\\n\";\r\n echo \"
$timestamp
\";\r\n}\r\n\r\nfunction showPopulationADL() {\r\n echo getPopulationADL();\r\n}\r\n?>\r\n" , SF False ".\\js\\navigate.js" 1429178701 {-2015-04-16 10:05:01 UTC -} "// JavaScript (c) by Bas Joosten 2009\r\n// requires jQuer 1.3+\r\n\r\n/////////////////////////\r\n// //\r\n// document onload //\r\n// //\r\n/////////////////////////\r\n$(function documentLoad() {\r\n $('.GotoArrow,.GotoLink').click(function(){\r\n var id='#Go'+$(this).attr('id').split('.').join('\\\\.');\r\n var offset=$(this).offset();\r\n $(id).css('top',offset.top-5);\r\n $(id).css('left',offset.left+$(this).width()+5);\r\n if($(id).css('display')=='none'){\r\n $('.Goto').hide();\r\n $(id).show();\r\n } else $(id).hide();\r\n });\r\n});" , SF False ".\\js\\jquery-ui-1.8.16.custom.min.js" 1429178701 {-2015-04-16 10:05:01 UTC -} "/*!\r\n * jQuery UI 1.8.16\r\n *\r\n * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)\r\n * Dual licensed under the MIT or GPL Version 2 licenses.\r\n * http://jquery.org/license\r\n *\r\n * http://docs.jquery.com/UI\r\n */\r\n(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if(\"area\"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!==\"map\")return false;a=c(\"img[usemap=#\"+d+\"]\")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:\"a\"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,\"visibility\")===\"hidden\"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:\"1.8.16\",\r\nkeyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({propAttr:c.fn.prop||c.fn.attr,_focus:c.fn.focus,focus:function(a,b){return typeof a===\"number\"?this.each(function(){var d=\r\nthis;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css(\"position\"))||/absolute/.test(this.css(\"position\"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,\"position\",1))&&/(auto|scroll)/.test(c.curCSS(this,\"overflow\",1)+c.curCSS(this,\"overflow-y\",1)+c.curCSS(this,\"overflow-x\",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,\r\n\"overflow\",1)+c.curCSS(this,\"overflow-y\",1)+c.curCSS(this,\"overflow-x\",1))}).eq(0);return/fixed/.test(this.css(\"position\"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css(\"zIndex\",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css(\"position\");if(b===\"absolute\"||b===\"relative\"||b===\"fixed\"){b=parseInt(a.css(\"zIndex\"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?\"selectstart\":\r\n\"mousedown\")+\".ui-disableSelection\",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(\".ui-disableSelection\")}});c.each([\"Width\",\"Height\"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,\"padding\"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,\"border\"+this+\"Width\",true))||0;if(n)g-=parseFloat(c.curCSS(f,\"margin\"+this,true))||0});return g}var e=b===\"Width\"?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,\r\nouterWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn[\"inner\"+b]=function(f){if(f===j)return i[\"inner\"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+\"px\")})};c.fn[\"outer\"+b]=function(f,g){if(typeof f!==\"number\")return i[\"outer\"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+\"px\")})}});c.extend(c.expr[\":\"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,\"tabindex\")))},tabbable:function(a){var b=c.attr(a,\r\n\"tabindex\"),d=isNaN(b);return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement(\"div\"));c.extend(b.style,{minHeight:\"100px\",height:\"auto\",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart=\"onselectstart\"in b;a.removeChild(b).style.display=\"none\"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&\r\na.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!==\"center\"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]===\"left\"?-a.elemWidth:a.my[0]===\"right\"?a.elemWidth:0,e=a.at[0]===\"left\"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+=\r\na.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!==\"center\"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]===\"top\"?-a.elemHeight:a.my[1]===\"bottom\"?a.elemHeight:0,e=a.at[1]===\"top\"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,\"position\")))b.style.position=\"relative\";var d=c(b),\r\ng=d.offset(),e=parseInt(c.curCSS(b,\"top\",true),10)||0,h=parseInt(c.curCSS(b,\"left\",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};\"using\"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery);\r\n;/*\r\n * jQuery UI Autocomplete 1.8.16\r\n *\r\n * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)\r\n * Dual licensed under the MIT or GPL Version 2 licenses.\r\n * http://jquery.org/license\r\n *\r\n * http://docs.jquery.com/UI/Autocomplete\r\n *\r\n * Depends:\r\n *\tjquery.ui.core.js\r\n *\tjquery.ui.widget.js\r\n *\tjquery.ui.position.js\r\n */\r\n(function(d){var e=0;d.widget(\"ui.autocomplete\",{options:{appendTo:\"body\",autoFocus:false,delay:300,minLength:1,position:{my:\"left top\",at:\"left bottom\",collision:\"none\"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass(\"ui-autocomplete-input\").attr(\"autocomplete\",\"off\").attr({role:\"textbox\",\"aria-autocomplete\":\"list\",\"aria-haspopup\":\"true\"}).bind(\"keydown.autocomplete\",function(c){if(!(a.options.disabled||a.element.propAttr(\"readOnly\"))){g=\r\nfalse;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move(\"previousPage\",c);break;case f.PAGE_DOWN:a._move(\"nextPage\",c);break;case f.UP:a._move(\"previous\",c);c.preventDefault();break;case f.DOWN:a._move(\"next\",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!=\r\na.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind(\"keypress.autocomplete\",function(c){if(g){g=false;c.preventDefault()}}).bind(\"focus.autocomplete\",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind(\"blur.autocomplete\",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)};\r\nthis.menu=d(\"
    \").addClass(\"ui-autocomplete\").appendTo(d(this.options.appendTo||\"body\",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(\".ui-menu-item\").length||setTimeout(function(){d(document).one(\"mousedown\",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data(\"item.autocomplete\");false!==a._trigger(\"focus\",c,{item:f})&&/^key/.test(c.originalEvent.type)&&\r\na.element.val(f.value)},selected:function(c,f){var h=f.item.data(\"item.autocomplete\"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger(\"select\",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(\":visible\")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data(\"menu\");\r\nd.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass(\"ui-autocomplete-input\").removeAttr(\"autocomplete\").removeAttr(\"role\").removeAttr(\"aria-autocomplete\").removeAttr(\"aria-haspopup\");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a===\"source\"&&this._initSource();if(a===\"appendTo\")this.menu.element.appendTo(d(b||\"body\",this.element[0].ownerDocument)[0]);a===\"disabled\"&&\r\nb&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source===\"string\"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:\"json\",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source=\r\nthis.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length\").data(\"item.autocomplete\",b).append(d(\"\").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(\":visible\"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g,\r\n\"\\\\$&\")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),\"i\");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery);\r\n(function(d){d.widget(\"ui.menu\",{_create:function(){var e=this;this.element.addClass(\"ui-menu ui-widget ui-widget-content ui-corner-all\").attr({role:\"listbox\",\"aria-activedescendant\":\"ui-active-menuitem\"}).click(function(a){if(d(a.target).closest(\".ui-menu-item a\").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children(\"li:not(.ui-menu-item):has(a)\").addClass(\"ui-menu-item\").attr(\"role\",\"menuitem\").children(\"a\").addClass(\"ui-corner-all\").attr(\"tabindex\",\r\n-1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children(\"a\").addClass(\"ui-state-hover\").attr(\"id\",\"ui-active-menuitem\").end();this._trigger(\"focus\",e,{item:a})},deactivate:function(){if(this.active){this.active.children(\"a\").removeClass(\"ui-state-hover\").removeAttr(\"id\");\r\nthis._trigger(\"blur\");this.active=null}},next:function(e){this.move(\"next\",\".ui-menu-item:first\",e)},previous:function(e){this.move(\"prev\",\".ui-menu-item:last\",e)},first:function(){return this.active&&!this.active.prevAll(\".ui-menu-item\").length},last:function(){return this.active&&!this.active.nextAll(\".ui-menu-item\").length},move:function(e,a,b){if(this.active){e=this.active[e+\"All\"](\".ui-menu-item\").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b,\r\nthis.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(\".ui-menu-item:first\"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(\".ui-menu-item\").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(\".ui-menu-item:last\"));this.activate(e,g)}else this.activate(e,this.element.children(\".ui-menu-item\").filter(!this.active||\r\nthis.last()?\":first\":\":last\"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(\".ui-menu-item:last\"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(\".ui-menu-item\").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(\".ui-menu-item:first\"));this.activate(e,result)}else this.activate(e,this.element.children(\".ui-menu-item\").filter(!this.active||\r\nthis.first()?\":last\":\":first\"))},hasScroll:function(){return this.element.height()\").addClass(\"ui-effects-wrapper\").css({fontSize:\"100%\",background:\"transparent\",border:\"none\",margin:0,padding:0}),\r\nd=document.activeElement;c.wrap(b);if(c[0]===d||f.contains(c[0],d))f(d).focus();b=c.parent();if(c.css(\"position\")==\"static\"){b.css({position:\"relative\"});c.css({position:\"relative\"})}else{f.extend(a,{position:c.css(\"position\"),zIndex:c.css(\"z-index\")});f.each([\"top\",\"left\",\"bottom\",\"right\"],function(e,g){a[g]=c.css(g);if(isNaN(parseInt(a[g],10)))a[g]=\"auto\"});c.css({position:\"relative\",top:0,left:0,right:\"auto\",bottom:\"auto\"})}return b.css(a).show()},removeWrapper:function(c){var a,b=document.activeElement;\r\nif(c.parent().is(\".ui-effects-wrapper\")){a=c.parent().replaceWith(c);if(c[0]===b||f.contains(c[0],b))f(b).focus();return a}return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)});\r\nreturn d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode=\"show\";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode=\"hide\";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c===\"boolean\"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,\r\narguments);a[1].mode=\"toggle\";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each([\"em\",\"px\",\"%\",\"pt\"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:\"easeOutQuad\",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/\r\n2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,\r\nd,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,\r\na,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,\r\nd,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h\").appendTo(b),e=d.css(\"display\");d.remove();if(e===\"none\"||e===\"\"){ch||(ch=c.createElement(\"iframe\"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode===\"CSS1Compat\"?\"\":\"\")+\"\"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,\"display\"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!==\"border\"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,\"padding\"+this))||0),c===\"margin\"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,\"border\"+this+\"Width\"))||0});return d+\"px\"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,\"padding\"+this))||0,c!==\"padding\"&&(d+=parseFloat(f.css(a,\"border\"+this+\"Width\"))||0),c===\"margin\"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+\"px\"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:\"script\"}):f.globalEval((b.text||b.textContent||b.innerHTML||\"\").replace(be,\"/*$0*/\")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,\"input\")?bk(a):\"getElementsByTagName\"in a&&f.grep(a.getElementsByTagName(\"input\"),bk)}function bk(a){if(a.type===\"checkbox\"||a.type===\"radio\")a.defaultChecked=a.checked}function bj(a){return\"getElementsByTagName\"in a?a.getElementsByTagName(\"*\"):\"querySelectorAll\"in a?a.querySelectorAll(\"*\"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c===\"object\")b.outerHTML=a.outerHTML;else if(c!==\"input\"||a.type!==\"checkbox\"&&a.type!==\"radio\"){if(c===\"option\")b.selected=a.defaultSelected;else if(c===\"input\"||c===\"textarea\")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!==\"*\"?a+\".\":\"\")+b.replace(z,\"`\").replace(A,\"&\")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,\"events\");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type===\"click\")){a.namespace&&(n=new RegExp(\"(^|\\\\.)\"+a.namespace.split(\".\").join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+\"defer\",g=c+\"queue\",h=c+\"mark\",i=f.data(a,e,b,!0);i&&(d===\"queue\"||!f.data(a,g,b,!0))&&(d===\"mark\"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!==\"toJSON\")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e=\"data-\"+c.replace(j,\"$1-$2\").toLowerCase();d=a.getAttribute(e);if(typeof d==\"string\"){try{d=d===\"true\"?!0:d===\"false\"?!1:d===\"null\"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll(\"left\")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,j=/\\S/,k=/^\\s+/,l=/\\s+$/,m=/\\d/,n=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,o=/^[\\],:{}\\s]*$/,p=/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,r=/(?:^|:|,)(?:\\s*\\[)+/g,s=/(webkit)[ \\/]([\\w.]+)/,t=/(opera)(?:.*version)?[ \\/]([\\w.]+)/,u=/(msie) ([\\w.]+)/,v=/(mozilla)(?:.*? rv:([\\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a===\"body\"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a==\"string\"){a.charAt(0)!==\"<\"||a.charAt(a.length-1)!==\">\"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:\"\",jquery:\"1.6.2\",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b===\"find\"?d.selector=this.selector+(this.selector?\" \":\"\")+c:b&&(d.selector=this.selector+\".\"+b+\"(\"+c+\")\");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),\"slice\",F.call(arguments).join(\",\"))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==\"boolean\"&&(l=i,i=arguments[1]||{},j=2),typeof i!=\"object\"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger(\"ready\").unbind(\"ready\")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState===\"complete\")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener(\"DOMContentLoaded\",B,!1),a.addEventListener(\"load\",e.ready,!1);else if(c.attachEvent){c.attachEvent(\"onreadystatechange\",B),a.attachEvent(\"onload\",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)===\"function\"},isArray:Array.isArray||function(a){return e.type(a)===\"array\"},isWindow:function(a){return a&&typeof a==\"object\"&&\"setInterval\"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||\"object\"},isPlainObject:function(a){if(!a||e.type(a)!==\"object\"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,\"constructor\")&&!D.call(a.constructor.prototype,\"isPrototypeOf\"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=\"string\"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,\"@\").replace(q,\"]\").replace(r,\"\")))return(new Function(\"return \"+b))();e.error(\"Invalid JSON: \"+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,\"text/xml\")):(c=new ActiveXObject(\"Microsoft.XMLDOM\"),c.async=\"false\",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName===\"parsererror\")&&e.error(\"Invalid XML: \"+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
    a\",d=a.getElementsByTagName(\"*\"),e=a.getElementsByTagName(\"a\")[0];if(!d||!d.length||!e)return{};g=c.createElement(\"select\"),h=g.appendChild(c.createElement(\"option\")),i=a.getElementsByTagName(\"input\")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName(\"tbody\").length,htmlSerialize:!!a.getElementsByTagName(\"link\").length,style:/top/.test(e.getAttribute(\"style\")),hrefNormalized:e.getAttribute(\"href\")===\"/a\",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value===\"on\",optSelected:h.selected,getSetAttribute:a.className!==\"t\",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent(\"onclick\",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent(\"onclick\")),i=c.createElement(\"input\"),i.value=\"t\",i.setAttribute(\"type\",\"radio\"),k.radioValue=i.value===\"t\",i.setAttribute(\"checked\",\"checked\"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML=\"\",a.style.width=a.style.paddingLeft=\"1px\",m=c.getElementsByTagName(\"body\")[0],o=c.createElement(m?\"div\":\"body\"),p={visibility:\"hidden\",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:\"absolute\",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,\"zoom\"in a.style&&(a.style.display=\"inline\",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display=\"\",a.innerHTML=\"
    \",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML=\"
    t
    \",q=a.getElementsByTagName(\"td\"),u=q[0].offsetHeight===0,q[0].style.display=\"\",q[1].style.display=\"none\",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML=\"\",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement(\"div\"),j.style.width=\"0\",j.style.marginRight=\"0\",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML=\"\",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s=\"on\"+t,u=s in a,u||(a.setAttribute(s,\"return;\"),u=typeof a[s]==\"function\"),k[t+\"Bubbles\"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\\{.*\\}|\\[.*\\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:\"jQuery\"+(f.fn.jquery+Math.random()).replace(/\\D/g,\"\"),noData:{embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c==\"string\",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c==\"object\"||typeof c==\"function\")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c===\"events\"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute(\"classid\")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a==\"undefined\"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&\"get\"in c&&(d=c.get(e,\"value\"))!==b)return d;d=e.value;return typeof d==\"string\"?d.replace(p,\"\"):d==null?\"\":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h=\"\":typeof h==\"number\"?h+=\"\":f.isArray(h)&&(h=f.map(h,function(a){return a==null?\"\":a+\"\"})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!(\"set\"in c)||c.set(this,h,\"value\")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type===\"select-one\";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:\"tabIndex\"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!(\"getAttribute\"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!==\"className\"&&(f.nodeName(a,\"form\")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&\"set\"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,\"\"+d);return d}if(i&&\"get\"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,\"\"),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error(\"type property can't be changed\");else if(!f.support.radioValue&&b===\"radio\"&&f.nodeName(a,\"input\")){var c=a.value;a.setAttribute(\"type\",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode(\"tabIndex\");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,\"button\"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,\"button\"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&\"set\"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&\"get\"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==\"\"?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each([\"width\",\"height\"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===\"\"){a.setAttribute(b,\"auto\");return c}}})})),f.support.hrefNormalized||f.each([\"href\",\"src\",\"width\",\"height\"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=\"\"+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each([\"radio\",\"checkbox\"],function(){f.valHooks[this]={get:function(a){return a.getAttribute(\"value\")===null?\"on\":a.value}}}),f.each([\"radio\",\"checkbox\"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\\./g,A=/ /g,B=/[^\\w\\s.|`]/g,C=function(a){return a.replace(B,\"\\\\$&\")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!=\"undefined\"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(\" \");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(\".\")>-1?(n=l.split(\".\"),l=n.shift(),h.namespace=n.slice(0).sort().join(\".\")):(n=[],h.namespace=\"\"),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent(\"on\"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c==\"string\"&&c.charAt(0)===\".\"){c=c||\"\";for(h in t)f.event.remove(a,h+c);return}c=c.split(\" \");while(h=c[k++]){r=h,q=null,l=h.indexOf(\".\")<0,m=[],l||(m=h.split(\".\"),h=m.shift(),n=new RegExp(\"(^|\\\\.)\"+f.map(m.slice(0).sort(),C).join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(\".\")>=0&&(i=h.split(\".\"),h=i.\r\nshift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c==\"object\"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join(\".\"),c.namespace_re=new RegExp(\"(^|\\\\.)\"+i.join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(\":\")<0?\"on\"+h:\"\";do{var m=f._data(k,\"handle\");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!==\"click\"||!f.nodeName(e,\"a\"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,\"events\")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join(\"-\"):\"\":f.nodeName(a,\"select\")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,\"_change_data\"),g=I(d),(c.type!==\"focusout\"||d.type!==\"radio\")&&f._data(d,\"_change_data\",g);if(e===b||g===e)return;if(e!=null||g)c.type=\"change\",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,\"input\")?b.type:\"\";(c===\"radio\"||c===\"checkbox\"||f.nodeName(b,\"select\"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,\"input\")?b.type:\"\";(a.keyCode===13&&!f.nodeName(b,\"textarea\")||a.keyCode===32&&(c===\"checkbox\"||c===\"radio\")||c===\"select-multiple\")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,\"_change_data\",I(b))}},setup:function(a,b){if(this.type===\"file\")return!1;for(var c in H)f.event.add(this,c+\".specialChange\",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,\".specialChange\");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each([\"bind\",\"one\"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a==\"object\"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c===\"one\"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a===\"unload\"&&c!==\"one\")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\\\/g,j=/\\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=\"string\")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(\"\"),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]===\"~\"||x[0]===\"+\")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r=\"\",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)===\"[object Array]\")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e\":function(a,b){var c,d=typeof b==\"string\",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,\"\")},TAG:function(a,b){return a[1].replace(i,\"\").toLowerCase()},CHILD:function(a){if(a[1]===\"nth\"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\\+|\\s*/g,\"\");var b=/(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(a[2]===\"even\"&&\"2n\"||a[2]===\"odd\"&&\"2n+1\"||!/\\D/.test(a[2])&&\"0n+\"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,\"\");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||\"\").replace(i,\"\"),a[2]===\"~=\"&&(a[4]=\" \"+a[4]+\" \");return a},PSEUDO:function(b,c,d,e,f){if(b[1]===\"not\")if((a.exec(b[3])||\"\").length>1||/^\\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!==\"hidden\"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute(\"type\"),c=a.type;return a.nodeName.toLowerCase()===\"input\"&&\"text\"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"radio\"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"checkbox\"===a.type},file:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"file\"===a.type},password:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"password\"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b===\"input\"||b===\"button\")&&\"submit\"===a.type},image:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"image\"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b===\"input\"||b===\"button\")&&\"reset\"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b===\"input\"&&\"button\"===a.type||b===\"button\"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e===\"contains\")return(a.textContent||a.innerText||k.getText([a])||\"\").indexOf(b[3])>=0;if(e===\"not\"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute(\"id\")===b},TAG:function(a,b){return b===\"*\"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(\" \"+(a.className||a.getAttribute(\"class\"))+\" \").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+\"\",f=b[2],g=b[4];return d==null?f===\"!=\":f===\"=\"?e===g:f===\"*=\"?e.indexOf(g)>=0:f===\"~=\"?(\" \"+e+\" \").indexOf(g)>=0:g?f===\"!=\"?e!==g:f===\"^=\"?e.indexOf(g)===0:f===\"$=\"?e.substr(e.length-g.length)===g:f===\"|=\"?e===g||e.substr(0,g.length+1)===g+\"-\":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return\"\\\\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\\[]*\\])(?![^\\(]*\\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\\r|\\n)*?)/.source+l.match[o].source.replace(/\\\\(\\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)===\"[object Array]\")Array.prototype.push.apply(d,a);else if(typeof a.length==\"number\")for(var f=a.length;c\",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=\"undefined\"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=\"undefined\"&&e.getAttributeNode(\"id\").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=\"undefined\"&&a.getAttributeNode(\"id\");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement(\"div\");a.appendChild(c.createComment(\"\")),a.getElementsByTagName(\"*\").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]===\"*\"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML=\"\",a.firstChild&&typeof a.firstChild.getAttribute!=\"undefined\"&&a.firstChild.getAttribute(\"href\")!==\"#\"&&(l.attrHandle.href=function(a){return a.getAttribute(\"href\",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement(\"div\"),d=\"__sizzle__\";b.innerHTML=\"

    \";if(!b.querySelectorAll||b.querySelectorAll(\".TEST\").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b===\"body\"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!==\"object\"){var m=e,n=e.getAttribute(\"id\"),o=n||d,q=e.parentNode,r=/^\\s*[+~]/.test(b);n?o=o.replace(/'/g,\"\\\\$&\"):e.setAttribute(\"id\",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll(\"[id='\"+o+\"'] \"+b),f)}catch(s){}finally{n||m.removeAttribute(\"id\")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement(\"div\"),\"div\"),e=!1;try{b.call(c.documentElement,\"[test!='']:sizzle\")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g,\"='$1']\");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement(\"div\");a.innerHTML=\"
    \";if(!!a.getElementsByClassName&&a.getElementsByClassName(\"e\").length!==0){a.lastChild.className=\"e\";if(a.getElementsByClassName(\"e\").length===1)return;l.order.splice(1,0,\"CLASS\"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=\"undefined\"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!==\"HTML\":!1};var v=function(a,b){var c,d=[],e=\"\",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,\"\");a=l.relative[a]?a+\"*\":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!=\"string\"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,\"closest\",a)},index:function(a){if(!a||typeof a==\"string\")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==\"string\"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return f.dir(a,\"parentNode\",c)},next:function(a){return f.nth(a,2,\"nextSibling\")},prev:function(a){return f.nth(a,2,\"previousSibling\")},nextAll:function(a){return f.dir(a,\"nextSibling\")},prevAll:function(a){return f.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return f.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return f.dir(a,\"previousSibling\",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,\"iframe\")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d==\"string\"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(\",\"))}}),f.extend({filter:function(a,b,c){c&&(a=\":not(\"+a+\")\");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\\d+=\"(?:\\d+|null)\"/g,Y=/^\\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,$=/<([\\w:]+)/,_=/\",\"\"],legend:[1,\"
    \",\"
    \"],thead:[1,\"\",\"
    \"],tr:[2,\"\",\"
    \"],td:[3,\"\",\"
    \"],col:[2,\"\",\"
    \"],area:[1,\"\",\"\"],_default:[0,\"\",\"\"]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,\"div
    \",\"
    \"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!=\"object\"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,\"body\")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,\"before\",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,\"after\",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName(\"*\")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName(\"*\"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,\"\"):null;if(typeof a==\"string\"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(Z,\"<$1>\");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j\r\n)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement==\"undefined\"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k==\"number\"&&(k+=\"\");if(!k)continue;if(typeof k==\"string\")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,\"<$1>\");var l=($.exec(k)||[\"\",\"\"])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement(\"div\");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l===\"table\"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===\"\"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],\"tbody\")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)==\"number\")for(i=0;i=0)return b+\"px\"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||\"\")?parseFloat(RegExp.$1)/100+\"\":b?\"1\":\"\"},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?\"\":\"alpha(opacity=\"+b*100+\")\",g=d&&d.filter||c.filter||\"\";c.filter=bn.test(g)?g.replace(bn,e):g+\" \"+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:\"inline-block\"},function(){b?c=bx(a,\"margin-right\",\"marginRight\"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,\"-$1\").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===\"\"&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b===\"fontSize\"?\"1em\":d||0,d=f.pixelLeft+\"px\",f.left=c,e&&(a.runtimeStyle.left=e));return d===\"\"?\"auto\":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,\"display\"))===\"none\"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\\[\\]$/,bD=/\\r?\\n/g,bE=/#.*$/,bF=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\\-storage|.+\\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\\/\\//,bK=/\\?/,bL=/)<[^<]*)*<\\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\\s+/,bO=/([?&])_=[^&]*/,bP=/^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement(\"a\"),bT.href=\"\",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!=\"string\"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(\" \");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h=\"GET\";c&&(f.isFunction(c)?(d=c,c=b):typeof c==\"object\"&&(c=f.param(c,f.ajaxSettings.traditional),h=\"POST\"));var i=this;f.ajax({url:a,type:h,dataType:\"html\",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f(\"
    \").append(c.replace(bL,\"\")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,\"\\r\\n\")}}):{name:b.name,value:c.replace(bD,\"\\r\\n\")}}).get()}}),f.each(\"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split(\" \"),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each([\"get\",\"post\"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,\"script\")},getJSON:function(a,b,c){return f.get(a,b,c,\"json\")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:\"GET\",contentType:\"application/x-www-form-urlencoded\",processData:!0,async:!0,accepts:{xml:\"application/xml, text/xml\",html:\"text/html\",text:\"text/plain\",json:\"application/json, text/javascript\",\"*\":\"*/*\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\"},converters:{\"* text\":a.String,\"text html\":!0,\"text json\":f.parseJSON,\"text xml\":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||\"\",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader(\"Last-Modified\"))f.lastModified[k]=x;if(y=v.getResponseHeader(\"Etag\"))f.etag[k]=y}if(a===304)c=\"notmodified\",o=!0;else try{r=b$(d,w),c=\"success\",o=!0}catch(z){c=\"parsererror\",u=z}}else{u=c;if(!c||a)c=\"error\",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger(\"ajax\"+(o?\"Success\":\"Error\"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger(\"ajaxComplete\",[v,d]),--f.active||f.event.trigger(\"ajaxStop\"))}}typeof a==\"object\"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||\"abort\",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+\"\").replace(bE,\"\").replace(bJ,bU[1]+\"//\"),d.dataTypes=f.trim(d.dataType||\"*\").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]===\"http:\"?80:443))==(bU[3]||(bU[1]===\"http:\"?80:443)))),d.data&&d.processData&&typeof d.data!=\"string\"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger(\"ajaxStart\");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?\"&\":\"?\")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,\"$1_=\"+x);d.url=y+(y===d.url?(bK.test(d.url)?\"&\":\"?\")+\"_=\"+x:\"\")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader(\"Content-Type\",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader(\"If-Modified-Since\",f.lastModified[k]),f.etag[k]&&v.setRequestHeader(\"If-None-Match\",f.etag[k])),v.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!==\"*\"?\", */*; q=0.01\":\"\"):d.accepts[\"*\"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,\"No Transport\");else{v.readyState=1,t&&g.trigger(\"ajaxSend\",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort(\"timeout\")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join(\"&\").replace(bB,\"+\")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\\=)\\?(&|$)|\\?\\?/i;f.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){return f.expando+\"_\"+b_++}}),f.ajaxPrefilter(\"json jsonp\",function(b,c,d){var e=b.contentType===\"application/x-www-form-urlencoded\"&&typeof b.data==\"string\";if(b.dataTypes[0]===\"jsonp\"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l=\"$1\"+h+\"$2\";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\\?/.test(j)?\"&\":\"?\")+b.jsonp+\"=\"+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters[\"script json\"]=function(){g||f.error(h+\" was not called\");return g[0]},b.dataTypes[0]=\"json\";return\"script\"}}),f.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/javascript|ecmascript/},converters:{\"text script\":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter(\"script\",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\",a.global=!1)}),f.ajaxTransport(\"script\",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName(\"head\")[0]||c.documentElement;return{send:function(f,g){d=c.createElement(\"script\"),d.async=\"async\",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,\"success\")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&\"withCredentials\"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e[\"X-Requested-With\"]&&(e[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=\"\"}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,cl,cm=[[\"height\",\"marginTop\",\"marginBottom\",\"paddingTop\",\"paddingBottom\"],[\"width\",\"marginLeft\",\"marginRight\",\"paddingLeft\",\"paddingRight\"],[\"opacity\"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr(\"show\",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each([\"\",\"X\",\"Y\"],function(a,b){d.style[\"overflow\"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
    \";f.extend(b.style,{position:\"absolute\",top:0,left:0,margin:0,border:0,width:\"1px\",height:\"1px\",visibility:\"hidden\"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position=\"fixed\",e.style.top=\"20px\",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top=\"\",d.style.overflow=\"hidden\",d.style.position=\"relative\",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,\"marginTop\"))||0,c+=parseFloat(f.css(a,\"marginLeft\"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,\"position\");d===\"static\"&&(a.style.position=\"relative\");var e=f(a),g=e.offset(),h=f.css(a,\"top\"),i=f.css(a,\"left\"),j=(d===\"absolute\"||d===\"fixed\")&&f.inArray(\"auto\",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),\"using\"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,\"marginTop\"))||0,c.left-=parseFloat(f.css(a,\"marginLeft\"))||0,d.top+=parseFloat(f.css(b[0],\"borderTopWidth\"))||0,d.left+=parseFloat(f.css(b[0],\"borderLeftWidth\"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,\"position\")===\"static\")a=a.offsetParent;return a})}}),f.each([\"Left\",\"Top\"],function(a,c){var d=\"scroll\"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?\"pageXOffset\"in g?g[a?\"pageYOffset\":\"pageXOffset\"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each([\"Height\",\"Width\"],function(a,c){var d=c.toLowerCase();f.fn[\"inner\"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,\"padding\")):null},f.fn[\"outer\"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?\"margin\":\"border\")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement[\"client\"+c];return e.document.compatMode===\"CSS1Compat\"&&g||e.document.body[\"client\"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement[\"client\"+c],e.body[\"scroll\"+c],e.documentElement[\"scroll\"+c],e.body[\"offset\"+c],e.documentElement[\"offset\"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a==\"string\"?a:a+\"px\")}}),a.jQuery=a.$=f})(window);" , SF False ".\\js\\jquery-1.3.2.min.js" 1429178701 {-2015-04-16 10:05:01 UTC -} "/*\r\n * jQuery JavaScript Library v1.3.2\r\n * http://jquery.com/\r\n *\r\n * Copyright (c) 2009 John Resig\r\n * Dual licensed under the MIT and GPL licenses.\r\n * http://docs.jquery.com/License\r\n *\r\n * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)\r\n * Revision: 6246\r\n */\r\n(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,ECps){return new o.fn.init(E,ECps)},D=/^[^<]*(<(.|\\s)+>)[^>]*$|^#([\\w-]+)$/,f=/^.[^:#\\[\\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E===\"string\"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var ECps=o(I||[]);ECps.context=document;ECps.selector=E;return ECps}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:\"\",jquery:\"1.3.2\",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(ECps,H,E){var G=o(ECps);G.prevObject=this;G.context=this.context;if(H===\"find\"){G.selector=this.selector+(this.selector?\" \":\"\")+E}else{if(H){G.selector=this.selector+\".\"+H+\"(\"+E+\")\"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(ECps,E){return o.each(this,ECps,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(ECps,H,G){var E=ECps;if(typeof ECps===\"string\"){if(H===g){return this[0]&&o[G||\"attr\"](this[0],ECps)}else{E={};E[ECps]=H}}return this.each(function(I){for(ECps in E){o.attr(G?this.style:this,ECps,o.prop(this,E[ECps],G,I,ECps))}})},css:function(E,ECps){if((E==\"width\"||E==\"height\")&&parseFloat(ECps)<0){ECps=g}return this.attr(E,ECps,\"curCSS\")},text:function(ECps){if(typeof ECps!==\"object\"&&ECps!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(ECps))}var E=\"\";o.each(ECps||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var ECps=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){ECps.insertBefore(this[0])}ECps.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var ECps=this.pushStack([],\"find\",E);ECps.length=0;o.find(E,this[0],ECps);return ECps}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),\"find\",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement(\"div\");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\\d+=\"(?:\\d+|null)\"/g,\"\").replace(/^\\s*/,\"\")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find(\"*\").andSelf(),ECps=0;E.find(\"*\").andSelf().each(function(){if(this.nodeName!==H[ECps].nodeName){return}var I=o.data(H[ECps],\"events\");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}ECps++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,ECps){return E.call(G,ECps)})||o.multiFilter(E,o.grep(this,function(ECps){return ECps.nodeType===1})),\"filter\",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,ECps=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,\"closest\",ECps);return H}H=H.parentNode;ECps++}})},not:function(E){if(typeof E===\"string\"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),\"not\",E)}else{E=o.multiFilter(E,this)}}var ECps=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return ECps?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E===\"string\"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is(\".\"+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,\"option\")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,\"select\")){var I=E.selectedIndex,L=[],M=E.options,H=E.type==\"select-one\";if(I<0){return null}for(var ECps=H?I:0,J=H?I+1:M.length;ECps=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,\"select\")){var N=o.makeArray(K);o(\"option\",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\\d+=\"(?:\\d+|null)\"/g,\"\"):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),\"slice\",Array.prototype.slice.call(arguments).join(\",\"))},map:function(E){return this.pushStack(o.map(this,function(G,ECps){return E.call(G,ECps,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),ECps=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(ECps){o.each(ECps,z)}}return this;function K(N,O){return M&&o.nodeName(N,\"table\")&&o.nodeName(O,\"tr\")?(N.getElementsByTagName(\"tbody\")[0]||N.appendChild(N.ownerDocument.createElement(\"tbody\"))):N}}};o.fn.init.prototype=o.fn;function z(E,ECps){if(ECps.src){o.ajax({url:ECps.src,async:false,dataType:\"script\"})}else{o.globalEval(ECps.text||ECps.textContent||ECps.innerHTML||\"\")}if(ECps.parentNode){ECps.parentNode.removeChild(ECps)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J===\"boolean\"){E=J;J=arguments[1]||{};H=2}if(typeof J!==\"object\"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var ECps in G){E[ECps]=H.style[ECps];H.style[ECps]=G[ECps]}I.call(H);for(var ECps in G){H.style[ECps]=E[ECps]}},css:function(H,ECps,J,E){if(ECps==\"width\"||ECps==\"height\"){var L,G={position:\"absolute\",visibility:\"hidden\",display:\"block\"},K=ECps==\"width\"?[\"Left\",\"Right\"]:[\"Top\",\"Bottom\"];function I(){L=ECps==\"width\"?H.offsetWidth:H.offsetHeight;if(E===\"border\"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,\"padding\"+this,true))||0}if(E===\"margin\"){L+=parseFloat(o.curCSS(H,\"margin\"+this,true))||0}else{L-=parseFloat(o.curCSS(H,\"border\"+this+\"Width\",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,ECps,J)},curCSS:function(I,ECps,G){var L,E=I.style;if(ECps==\"opacity\"&&!o.support.opacity){L=o.attr(E,\"opacity\");return L==\"\"?\"1\":L}if(ECps.match(/float/i)){ECps=w}if(!G&&E&&E[ECps]){L=E[ECps]}else{if(q.getComputedStyle){if(ECps.match(/float/i)){ECps=\"float\"}ECps=ECps.replace(/([A-Z])/g,\"-$1\").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(ECps)}if(ECps==\"opacity\"&&L==\"\"){L=\"1\"}}else{if(I.currentStyle){var J=ECps.replace(/\\-(\\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[ECps]||I.currentStyle[J];if(!/^\\d+(px)?$/i.test(L)&&/^\\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+\"px\";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(ECps,K,I){K=K||document;if(typeof K.createElement===\"undefined\"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&ECps.length===1&&typeof ECps[0]===\"string\"){var H=/^<(\\w+)\\s*\\/?>$/.exec(ECps[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement(\"div\");o.each(ECps,function(P,S){if(typeof S===\"number\"){S+=\"\"}if(!S){return}if(typeof S===\"string\"){S=S.replace(/(<(\\w+)[^>]*?)\\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+\">\"});var O=S.replace(/^\\s+/,\"\").substring(0,10).toLowerCase();var Q=!O.indexOf(\"\",\"\"]||!O.indexOf(\"\",\"\"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,\"\",\"
    \"]||!O.indexOf(\"\",\"\"]||(!O.indexOf(\"\",\"\"]||!O.indexOf(\"\",\"\"]||!o.support.htmlSerialize&&[1,\"div
    \",\"
    \"]||[0,\"\",\"\"];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/\"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],\"tbody\")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],\"script\")&&(!G[J].type||G[J].type.toLowerCase()===\"text/javascript\")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName(\"script\"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var ECps=/href|src|style/.test(G);if(G==\"selected\"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!ECps){if(L){if(G==\"type\"&&o.nodeName(J,\"input\")&&J.parentNode){throw\"type property can't be changed\"}J[G]=K}if(o.nodeName(J,\"form\")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G==\"tabIndex\"){var I=J.getAttributeNode(\"tabIndex\");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G==\"style\"){return o.attr(J.style,\"cssText\",K)}if(L){J.setAttribute(G,\"\"+K)}var E=!o.support.hrefNormalized&&H&&ECps?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G==\"opacity\"){if(L){J.zoom=1;J.filter=(J.filter||\"\").replace(/alpha\\([^)]*\\)/,\"\")+(parseInt(K)+\"\"==\"NaN\"?\"\":\"alpha(opacity=\"+K*100+\")\")}return J.filter&&J.filter.indexOf(\"opacity=\")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+\"\":\"\"}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||\"\").replace(/^\\s+|\\s+$/g,\"\")},makeArray:function(G){var E=[];if(G!=null){var ECps=G.length;if(ECps==null||typeof G===\"string\"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(ECps){E[--ECps]=G[ECps]}}}return E},inArray:function(G,H){for(var E=0,ECps=H.length;E0?this.clone(true):this).get();o.fn[ECps].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,\"\");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(ECps,E){if(typeof E!==\"boolean\"){E=!o.className.has(this,ECps)}o.className[E?\"add\":\"remove\"](this,ECps)},remove:function(E){if(!E||o.filter(E,[this]).length){o(\"*\",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,ECps){o.fn[E]=function(){return this.each(ECps,arguments)}});function j(E,ECps){return E[0]&&parseInt(o.curCSS(E[0],ECps,true),10)||0}var h=\"jQuery\"+e(),v=0,A={};o.extend({cache:{},data:function(ECps,E,G){ECps=ECps==l?A:ECps;var H=ECps[h];if(!H){H=ECps[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(ECps,E){ECps=ECps==l?A:ECps;var H=ECps[h];if(E){if(o.cache[H]){delete o.cache[H][E];E=\"\";for(E in o.cache[H]){break}if(!E){o.removeData(ECps)}}}else{try{delete ECps[h]}catch(G){if(ECps.removeAttribute){ECps.removeAttribute(h)}}delete o.cache[H]}},queue:function(ECps,E,H){if(ECps){E=(E||\"fx\")+\"queue\";var G=o.data(ECps,E);if(!G||o.isArray(H)){G=o.data(ECps,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),ECps=E.shift();if(!G||G===\"fx\"){ECps=E[0]}if(ECps!==g){ECps.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(\".\");H[1]=H[1]?\".\"+H[1]:\"\";if(G===g){var ECps=this.triggerHandler(\"getData\"+H[1]+\"!\",[H[0]]);if(ECps===g&&this.length){ECps=o.data(this[0],E)}return ECps===g&&H[1]?this.data(H[0]):ECps}else{return this.trigger(\"setData\"+H[1]+\"!\",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,ECps){if(typeof E!==\"string\"){ECps=E;E=\"fx\"}if(ECps===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,ECps);if(E==\"fx\"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});\r\n/*\r\n * Sizzle CSS Selector Engine - v0.9.3\r\n * Copyright 2009, The Dojo Foundation\r\n * Released under the MIT, BSD, and GPL Licenses.\r\n * More information: http://sizzlejs.com/\r\n */\r\n(function(){var R=/((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^[\\]]*\\]|['\"][^'\"]*['\"]|[^[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?/g,L=0,H=Object.prototype.toString;var ECps=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!==\"string\"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:ECps(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:ECps.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=ECps.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=\"\"}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw\"Syntax error, unrecognized expression: \"+(ah||Y)}if(H.call(ai)===\"[object Array]\"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){ECps(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa\":function(Z,U,aa){var X=typeof U===\"string\";if(X&&!/\\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\\\/g,\"\")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]==\"nth\"){var U=/(-?)(\\d*)n((?:\\+|-)?\\d*)/.exec(T[2]==\"even\"&&\"2n\"||T[2]==\"odd\"&&\"2n+1\"||!/\\D/.test(T[2])&&\"0n+\"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\\\/g,\"\");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]===\"~=\"){X[4]=\" \"+X[4]+\" \"}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]===\"not\"){if(X[3].match(R).length>1||/^\\w/.test(X[3])){X[3]=ECps(X[3],null,null,U)}else{var W=ECps.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!==\"hidden\"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!ECps(T[3],V).length},header:function(T){return/h\\d/i.test(T.nodeName)},text:function(T){return\"text\"===T.type},radio:function(T){return\"radio\"===T.type},checkbox:function(T){return\"checkbox\"===T.type},file:function(T){return\"file\"===T.type},password:function(T){return\"password\"===T.type},submit:function(T){return\"submit\"===T.type},image:function(T){return\"image\"===T.type},reset:function(T){return\"reset\"===T.type},button:function(T){return\"button\"===T.type||T.nodeName.toUpperCase()===\"BUTTON\"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U===\"contains\"){return(Z.textContent||Z.innerText||\"\").indexOf(V[3])>=0}else{if(U===\"not\"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute(\"id\")===T},TAG:function(U,T){return(T===\"*\"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(\" \"+(U.className||U.getAttribute(\"class\"))+\" \").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+\"\",X=W[2],U=W[4];return T==null?X===\"!=\":X===\"=\"?Z===U:X===\"*=\"?Z.indexOf(U)>=0:X===\"~=\"?(\" \"+Z+\" \").indexOf(U)>=0:!U?Z&&T!==false:X===\"!=\"?Z!=U:X===\"^=\"?Z.indexOf(U)===0:X===\"$=\"?Z.substr(Z.length-U.length)===U:X===\"|=\"?Z===U||Z.substr(0,U.length+1)===U+\"-\":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\\[]*\\])(?![^\\(]*\\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)===\"[object Array]\"){Array.prototype.push.apply(U,X)}else{if(typeof X.length===\"number\"){for(var V=0,T=X.length;V\";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!==\"undefined\"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!==\"undefined\"&&W.getAttributeNode(\"id\").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!==\"undefined\"&&Y.getAttributeNode(\"id\");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement(\"div\");T.appendChild(document.createComment(\"\"));if(T.getElementsByTagName(\"*\").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]===\"*\"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML=\"\";if(T.firstChild&&typeof T.firstChild.getAttribute!==\"undefined\"&&T.firstChild.getAttribute(\"href\")!==\"#\"){I.attrHandle.href=function(U){return U.getAttribute(\"href\",2)}}})();if(document.querySelectorAll){(function(){var T=ECps,U=document.createElement(\"div\");U.innerHTML=\"

    \";if(U.querySelectorAll&&U.querySelectorAll(\".TEST\").length===0){return}ECps=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};ECps.find=T.find;ECps.filter=T.filter;ECps.selectors=T.selectors;ECps.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement(\"div\");T.innerHTML=\"
    \";if(T.getElementsByClassName(\"e\").length===0){return}T.lastChild.className=\"e\";if(T.getElementsByClassName(\"e\").length===1){return}I.order.splice(1,0,\"CLASS\");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!==\"undefined\"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U==\"previousSibling\"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!==\"HTML\"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X=\"\",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,\"\")}T=I.relative[T]?T+\"*\":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};ECps.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=\":not(\"+V+\")\"}return ECps.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=ECps})();o.event={add:function(I,ECps,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,\"events\")||o.data(I,\"events\",{}),J=o.data(I,\"handle\")||o.data(I,\"handle\",function(){return typeof o!==\"undefined\"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(ECps.split(/\\s+/),function(M,N){var O=N.split(\".\");N=O.shift();H.type=O.slice().sort().join(\".\");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent(\"on\"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,\"events\"),ECps,E;if(G){if(H===g||(typeof H===\"string\"&&H.charAt(0)==\".\")){for(var I in G){this.remove(K,I+(H||\"\"))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\\s+/),function(M,O){var Q=O.split(\".\");O=Q.shift();var N=RegExp(\"(^|\\\\.)\"+Q.slice().sort().join(\".*\\\\.\")+\"(\\\\.|$)\");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(ECps in G[O]){break}if(!ECps){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,\"handle\"),false)}else{if(K.detachEvent){K.detachEvent(\"on\"+O,o.data(K,\"handle\"))}}}ECps=null;delete G[O]}}})}for(ECps in G){break}if(!ECps){var L=o.data(K,\"handle\");if(L){L.elem=null}o.removeData(K,\"events\");o.removeData(K,\"handle\")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I===\"object\"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf(\"!\")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,\"handle\");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,\"a\")&&G==\"click\"))&&H[\"on\"+G]&&H[\"on\"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,\"a\")&&G==\"click\")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var ECps=H.parentNode||H.ownerDocument;if(ECps){o.event.trigger(I,K,ECps,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(\".\");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp(\"(^|\\\\.)\"+L.slice().sort().join(\".*\\\\.\")+\"(\\\\.|$)\");E=(o.data(this,\"events\")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var ECps=H.apply(this,arguments);if(ECps!==g){K.result=ECps;if(ECps===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:\"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which\".split(\" \"),fix:function(H){if(H[h]){return H}var ECps=H;H=o.Event(ECps);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=ECps[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(ECps,E){E=E||function(){return ECps.apply(this,arguments)};E.guid=ECps.guid=ECps.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,ECps){o.event.add(this,ECps[0],c)},teardown:function(G){if(G.length){var E=0,ECps=RegExp(\"(^|\\\\.)\"+G[0]+\"(\\\\.|$)\");o.each((o.data(this,\"events\").live||{}),function(){if(ECps.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(ECps){var E=ECps.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){ECps.type=ECps.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:\"mouseenter\",mouseout:\"mouseleave\"},function(ECps,E){o.event.special[E]={setup:function(){o.event.add(this,ECps,a,E)},teardown:function(){o.event.remove(this,ECps,a)}}});o.fn.extend({bind:function(ECps,G,E){return ECps==\"unload\"?this.one(ECps,G,E):this.each(function(){o.event.add(this,ECps,E||G,E&&G)})},one:function(G,H,ECps){var E=o.event.proxy(ECps||H,function(I){o(this).unbind(I,E);return(ECps||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,ECps&&H)})},unbind:function(ECps,E){return this.each(function(){o.event.remove(this,ECps,E)})},trigger:function(E,ECps){return this.each(function(){o.event.trigger(E,ECps,this)})},triggerHandler:function(E,G){if(this[0]){var ECps=o.Event(E);ECps.preventDefault();ECps.stopPropagation();o.event.trigger(ECps,G,this[0]);return ECps.result}},toggle:function(G){var E=arguments,ECps=1;while(ECps
    a';var H=K.getElementsByTagName(\"*\"),E=K.getElementsByTagName(\"a\")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName(\"tbody\").length,objectAll:!!K.getElementsByTagName(\"object\")[0].getElementsByTagName(\"*\").length,htmlSerialize:!!K.getElementsByTagName(\"link\").length,style:/red/.test(E.getAttribute(\"style\")),hrefNormalized:E.getAttribute(\"href\")===\"/a\",opacity:E.style.opacity===\"0.5\",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type=\"text/javascript\";try{G.appendChild(document.createTextNode(\"window.\"+J+\"=1;\"))}catch(I){}ECps.insertBefore(G,ECps.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}ECps.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent(\"onclick\",function(){o.support.noCloneEvent=false;K.detachEvent(\"onclick\",arguments.callee)});K.cloneNode(true).fireEvent(\"onclick\")}o(function(){var L=document.createElement(\"div\");L.style.width=L.style.paddingLeft=\"1px\";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display=\"none\"})})();var w=o.support.cssFloat?\"cssFloat\":\"styleFloat\";o.props={\"for\":\"htmlFor\",\"class\":\"className\",\"float\":w,cssFloat:w,styleFloat:w,readonly:\"readOnly\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",rowspan:\"rowSpan\",tabindex:\"tabIndex\"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!==\"string\"){return this._load(G)}var I=G.indexOf(\" \");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H=\"GET\";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J===\"object\"){J=o.param(J);H=\"POST\"}}}var ECps=this;o.ajax({url:G,type:H,dataType:\"html\",data:J,complete:function(M,L){if(L==\"success\"||L==\"notmodified\"){ECps.html(E?o(\"
    \").append(M.responseText.replace(//g,\"\")).find(E):M.responseText)}if(K){ECps.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,ECps){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:ECps.name,value:I}}):{name:ECps.name,value:G}}).get()}});o.each(\"ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend\".split(\",\"),function(E,ECps){o.fn[ECps]=function(G){return this.bind(ECps,G)}});var r=e();o.extend({get:function(E,G,H,ECps){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:\"GET\",url:E,data:G,success:H,dataType:ECps})},getScript:function(E,ECps){return o.get(E,null,ECps,\"script\")},getJSON:function(E,ECps,G){return o.get(E,ECps,G,\"json\")},post:function(E,G,H,ECps){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:\"POST\",url:E,data:G,success:H,dataType:ECps})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:\"GET\",contentType:\"application/x-www-form-urlencoded\",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject(\"Microsoft.XMLHTTP\"):new XMLHttpRequest()},accepts:{xml:\"application/xml, text/xml\",html:\"text/html\",script:\"text/javascript, application/javascript\",json:\"application/json, text/javascript\",text:\"text/plain\",_default:\"*/*\"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,ECps=/=\\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!==\"string\"){M.data=o.param(M.data)}if(M.dataType==\"jsonp\"){if(G==\"GET\"){if(!M.url.match(ECps)){M.url+=(M.url.match(/\\?/)?\"&\":\"?\")+(M.jsonp||\"callback\")+\"=?\"}}else{if(!M.data||!M.data.match(ECps)){M.data=(M.data?M.data+\"&\":\"\")+(M.jsonp||\"callback\")+\"=?\"}}M.dataType=\"json\"}if(M.dataType==\"json\"&&(M.data&&M.data.match(ECps)||M.url.match(ECps))){W=\"jsonp\"+r++;if(M.data){M.data=(M.data+\"\").replace(ECps,\"=\"+W+\"$1\")}M.url=M.url.replace(ECps,\"=\"+W+\"$1\");M.dataType=\"script\";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType==\"script\"&&M.cache==null){M.cache=false}if(M.cache===false&&G==\"GET\"){var E=e();var U=M.url.replace(/(\\?|&)_=.*?(&|$)/,\"$1_=\"+E+\"$2\");M.url=U+((U==M.url)?(M.url.match(/\\?/)?\"&\":\"?\")+\"_=\"+E:\"\")}if(M.data&&G==\"GET\"){M.url+=(M.url.match(/\\?/)?\"&\":\"?\")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger(\"ajaxStart\")}var Q=/^(\\w+:)?\\/\\/([^\\/?#]+)/.exec(M.url);if(M.dataType==\"script\"&&G==\"GET\"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName(\"head\")[0];var T=document.createElement(\"script\");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState==\"loaded\"||this.readyState==\"complete\")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader(\"Content-Type\",M.contentType)}if(M.ifModified){J.setRequestHeader(\"If-Modified-Since\",o.lastModified[M.url]||\"Thu, 01 Jan 1970 00:00:00 GMT\")}J.setRequestHeader(\"X-Requested-With\",\"XMLHttpRequest\");J.setRequestHeader(\"Accept\",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+\", */*\":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger(\"ajaxStop\")}J.abort();return false}if(M.global){o.event.trigger(\"ajaxSend\",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger(\"ajaxStop\")}}}else{if(!K&&J&&(J.readyState==4||X==\"timeout\")){K=true;if(P){clearInterval(P);P=null}R=X==\"timeout\"?\"timeout\":!o.httpSuccess(J)?\"error\":M.ifModified&&o.httpNotModified(J,M.url)?\"notmodified\":\"success\";if(R==\"success\"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R=\"parsererror\"}}if(R==\"success\"){var Y;try{Y=J.getResponseHeader(\"Last-Modified\")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N(\"timeout\")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger(\"ajaxSuccess\",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger(\"ajaxComplete\",[J,M])}if(M.global&&!--o.active){o.event.trigger(\"ajaxStop\")}}return J},handleError:function(ECps,H,E,G){if(ECps.error){ECps.error(H,E,G)}if(ECps.global){o.event.trigger(\"ajaxError\",[H,ECps,G])}},active:0,httpSuccess:function(ECps){try{return !ECps.status&&location.protocol==\"file:\"||(ECps.status>=200&&ECps.status<300)||ECps.status==304||ECps.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader(\"Last-Modified\");return G.status==304||H==o.lastModified[E]}catch(ECps){}return false},httpData:function(J,H,G){var ECps=J.getResponseHeader(\"content-type\"),E=H==\"xml\"||!H&&ECps&&ECps.indexOf(\"xml\")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName==\"parsererror\"){throw\"parsererror\"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I===\"string\"){if(H==\"script\"){o.globalEval(I)}if(H==\"json\"){I=l[\"eval\"](\"(\"+I+\")\")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+\"=\"+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var ECps in E){if(o.isArray(E[ECps])){o.each(E[ECps],function(){H(ECps,this)})}else{H(ECps,o.isFunction(E[ECps])?E[ECps]():E[ECps])}}}return G.join(\"&\").replace(/%20/g,\"+\")}});var m={},n,d=[[\"height\",\"marginTop\",\"marginBottom\",\"paddingTop\",\"paddingBottom\"],[\"width\",\"marginLeft\",\"marginRight\",\"paddingLeft\",\"paddingRight\"],[\"opacity\"]];function t(ECps,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=ECps});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t(\"show\",3),J,L)}else{for(var H=0,ECps=this.length;H\").appendTo(\"body\");K=I.css(\"display\");if(K===\"none\"){K=\"block\"}I.remove();m[G]=K}o.data(this[H],\"olddisplay\",K)}}for(var H=0,ECps=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t(\"show\",1),slideUp:t(\"hide\",1),slideToggle:t(\"toggle\",1),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"}},function(E,ECps){o.fn[E]=function(G,H){return this.animate(ECps,G,H)}});o.extend({speed:function(G,H,ECps){var E=typeof G===\"object\"?G:{complete:ECps||!ECps&&H||o.isFunction(G)&&G,duration:G,easing:ECps&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration===\"number\"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,ECps){return E+ECps*G},swing:function(G,H,E,ECps){return((-Math.cos(G*Math.PI)/2)+0.5)*ECps+E}},timers:[],fx:function(ECps,E,G){this.options=E;this.elem=ECps;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop==\"height\"||this.prop==\"width\")&&this.elem.style){this.elem.style.display=\"block\"}},cur:function(ECps){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,ECps));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||\"px\";this.now=this.start;this.pos=this.state=0;var E=this;function ECps(J){return E.step(J)}ECps.elem=this.elem;if(ECps()&&o.timers.push(ECps)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var ECps in this.options.curAnim){if(this.options.curAnim[ECps]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,\"display\")==\"none\"){this.elem.style.display=\"block\"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?\"swing\":\"linear\")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,\"opacity\",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,ECps=J.body,E=J.documentElement,L=E.clientTop||ECps.clientTop||0,K=E.clientLeft||ECps.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||ECps.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||ECps.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,ECps=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}ECps=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!==\"visible\"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position===\"relative\"||E.position===\"static\"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position===\"fixed\"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,ECps=document.createElement(\"div\"),H,G,N,I,M,E,J=L.style.marginTop,K='
    ';M={position:\"absolute\",top:0,left:0,margin:0,border:0,width:\"1px\",height:\"1px\",visibility:\"hidden\"};for(E in M){ECps.style[E]=M[E]}ECps.innerHTML=K;L.insertBefore(ECps,L.firstChild);H=ECps.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow=\"hidden\",H.style.position=\"relative\";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop=\"1px\";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(ECps);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,ECps=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,\"marginTop\",true),10)||0,ECps+=parseInt(o.curCSS(E,\"marginLeft\",true),10)||0}return{top:G,left:ECps}}};o.fn.extend({position:function(){var I=0,H=0,ECps;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,\"marginTop\");J.left-=j(this,\"marginLeft\");E.top+=j(G,\"borderTopWidth\");E.left+=j(G,\"borderLeftWidth\");ECps={top:J.top-E.top,left:J.left-E.left}}return ECps},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,\"position\")==\"static\")){E=E.offsetParent}return o(E)}});o.each([\"Left\",\"Top\"],function(ECps,E){var G=\"scroll\"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!ECps?H:o(l).scrollLeft(),ECps?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[ECps?\"pageYOffset\":\"pageXOffset\"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each([\"Height\",\"Width\"],function(I,G){var E=I?\"Left\":\"Top\",H=I?\"Right\":\"Bottom\",ECps=G.toLowerCase();o.fn[\"inner\"+G]=function(){return this[0]?o.css(this[0],ECps,false,\"padding\"):null};o.fn[\"outer\"+G]=function(K){return this[0]?o.css(this[0],ECps,false,K?\"margin\":\"border\"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode==\"CSS1Compat\"&&document.documentElement[\"client\"+G]||document.body[\"client\"+G]:this[0]==document?Math.max(document.documentElement[\"client\"+G],document.body[\"scroll\"+G],document.documentElement[\"scroll\"+G],document.body[\"offset\"+G],document.documentElement[\"offset\"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K===\"string\"?K:K+\"px\")}})})();" , SF False ".\\js\\edit.js" 1429178701 {-2015-04-16 10:05:01 UTC -} "// JavaScript (c) by Bas Joosten 2009\r\n// requires jQuer 1.3+\r\n\r\nvar editbox = document.createElement(\"input\"); // an input box for user interaction\r\neditbox.setAttribute(\"id\",\"editbx\");\r\neditbox.setAttribute(\"name\",\"editbx\");\r\neditbox.setAttribute(\"type\",\"text\");\r\nvar editObject=null; // current editing object. Null for none\r\nvar editContent=null; // the old value, used to restore the object, should we undo the edit\r\n// editsNew tells whether the current editing object (ie editObject!=null) is new.\r\n// This is used to answer these questions:\r\n// should 'tab' give a new element?\r\n// should unEdit(false) destroy the element?\r\nvar editsNew=false;\r\n// tabHover is the current element we're hovering over, using the mouse or tab-key\r\nvar tabHover=null; // code to set it is written at the 'attatch hover/click events'\r\n\r\n\r\n///////////////////////\r\n// //\r\n// save function //\r\n// //\r\n///////////////////////\r\nfunction save(url,id){ // id can be used as an extra parameter, to set the ID value\r\n $('#errorPopup').remove(); // remove the previous error, if still present\r\n var all=($(\".item\").get()).concat($(\".itemshow\").get());\r\n var flds=new Array();\r\n for(var i=0;i
    x
    '+data+'
    ').prependTo('.content:first').hide().slideDown();\r\n // add the functionality to the 'x' button\r\n $('#errorClose').click(function(){\r\n $('#errorPopup').slideUp(function(me){$('#errorPopup').remove();});\r\n });\r\n }\r\n });\r\n}\r\n\r\n// Set jQuery autocomplete values for edit field obj.\r\n// The values are retrieved from the server with an atomList= request, so there is a slight\r\n// delay before they are shown.\r\nfunction setAutocomplete(obj) {\r\n var context = $(obj).attr('context');\r\n var interface = $(obj).attr('interface');\r\n var concept = $(obj).attr('concept');\r\n if (context && interface && concept) {\r\n $.post(context+\".php\",{ content: interface, atomList: concept },function receiveDataOnPost(data){\r\n\t var resultOrError = JSON.parse(data); // contains .res or .err\r\n\t if (typeof resultOrError.res !== 'undefined')\r\n $(\"input#editbx\").autocomplete({ source:resultOrError.res }, { minLength: 0});\r\n\t else\r\n console.error(\"Ampersand: Error while retrieving auto-complete values:\\n\"+resultOrError.err);\r\n });\r\n } else\r\n console.error(\"Ampersand: Missing 'context', 'interface' or 'concept' html attribute for auto-complete edit field\");\r\n}\r\n\r\n//////////////////////////\r\n// //\r\n// Editing function //\r\n// //\r\n//////////////////////////\r\nfunction edit(obj){\r\n if(obj==null) return;\r\n editsNew=false;\r\n if(tabHover!=null) $(tabHover).removeClass('hover');\r\n // get the UI class function\r\n cls = getUIClass(obj);\r\n if($(obj).is('.new')){\r\n ////////////////////\r\n // create new //\r\n ////////////////////\r\n if($(obj).is('div'))\r\n editObject=obj;\r\n else{\r\n editsNew=true;\r\n editObject=$(obj).clone().insertBefore(obj);\r\n var nrs=$(obj).attr('id').split('.');\r\n nrs[nrs.length-1]-=-1; // add one numerically\r\n $(obj).attr('id',nrs.join('.'));\r\n }\r\n if(eval('typeof '+cls)=='function'){\r\n ///////////////////////////////\r\n // create complex object //\r\n // and edit its first item //\r\n // //\r\n editsNew=false;\r\n $(editObject).html(eval(cls+'(\\''+$(editObject).attr('id')+'\\')'));\r\n reassign($(editObject).find(\".new,.item\"));\r\n reassign($(editObject));\r\n firstObj=$(editObject).find('.item:not(:has(.item,.new))').eq(0);\r\n edit(firstObj);\r\n $(editObject).removeClass(\"new\");\r\n $(editObject).addClass(\"item\");\r\n // //\r\n // unfortunately, the cancel //\r\n // key won't work so well //\r\n ///////////////////////////////\r\n }else{\r\n ///////////////////////////////\r\n // create a new leaf-element //\r\n // and edit it //\r\n reassign(editObject);\r\n editBoxIt(editObject).value='';\r\n $(editObject).removeClass(\"new\");\r\n $(editObject).addClass(\"item\");\r\n \r\n setAutocomplete(obj);\r\n }\r\n }else{\r\n //////////////////////\r\n // edit current //\r\n //////////////////////\r\n if(eval('typeof '+cls)=='function'){ // remove the item (since we can create a new one!)\r\n if(!$(obj).is('li')){ // not a list item: create my own 'New'\r\n var newitm=$('
    Nothing
    ');\r\n $(obj).replaceWith(newitm);\r\n reassign(newitm);\r\n }else{\r\n remove(obj);\r\n }\r\n } else {\r\n var txt=$.trim($(obj).text()); //$.trim is needed to trim a trailing whitespace introduced by text() in LI items in IE\r\n editBoxIt(obj).value=txt;\r\n\r\n setAutocomplete(obj);\r\n }\r\n }\r\n}\r\n////////////////////////////////////////\r\n// //\r\n//..and the function to stop editing //\r\n// //\r\n////////////////////////////////////////\r\nfunction unEdit(submit,reset){ if(reset==null) reset=true;\r\n if(editObject==null) return false;\r\n $(editObject).addClass('hover');\r\n tabHover=editObject;\r\n $(editObject).empty();\r\n if(!submit) editbox.value=editContent;\r\n if(editbox.value==''){\r\n if($(editObject).is('li')) {\r\n var obj=$(editObject);\r\n editObject=prev(obj,\".item:not(:has(.item,.new))\");\r\n // the line below ensures the next item won't be \"new\" again: move on to next field\r\n // comment the line to get blocking behaviour\r\n // editsNew=false;\r\n remove(obj);\r\n }else{\r\n if($(editObject).is('div')){\r\n var cls=getUIClass(editObject);\r\n var id=$(editObject).attr('id');\r\n var newitm=$('
    Nothing
    ');\r\n $(editObject).replaceWith(newitm);\r\n reassign(newitm);\r\n } // in other cases, the object is a SPAN, which cannot be empty!\r\n }\r\n }else $(editObject).text(editbox.value);\r\n if(reset) editObject=null;\r\n}\r\n\r\nfunction remove(obj){\r\n var nrs = $(obj).attr('id').split('.');\r\n var i=nrs.pop()-0;\r\n var start=nrs.join('.');\r\n var jstart=nrs.join('\\\\.');\r\n if(nrs.length){ start+='.'; jstart+='\\\\.'; }\r\n for(i++;$('#'+jstart+i).attr('id')!=null;i++){\r\n $('#'+jstart+i).attr('id',start+(i-1));\r\n }\r\n $(obj).remove();\r\n}\r\n\r\n// change the item into an editbox, and ensure it is possible to change it back later\r\nfunction editBoxIt(obj){\r\n editObject=obj;\r\n if($(obj).is('.item')) editContent=$(obj).get(0).innerHTML; else editContent='';\r\n $(obj).empty();\r\n $(obj).append(editbox);\r\n editbox.focus();\r\n $(tabHover).removeClass('hover');\r\n setTimeout('uneditBlur();',1);\r\n $(editbox).blur(function blurEditbox(){\r\n $(editbox).focus();\r\n return false;\r\n });\r\n return editbox;\r\n}\r\nfunction uneditBlur(){\r\n $(editbox).blur(function blurEditbox(){\r\n unEdit(true);\r\n });\r\n}\r\nfunction getUIClass(obj){\r\n var classes=$(obj).attr('class').split(' ');\r\n for(var i=0;i0){E=\" \"+E}}else{if(B400}if(I==500){I=400}for(var J in G){if(!k(G,J)){continue}J=parseInt(J,10);if(!ECps||JD){D=J}K.push(J)}if(ID){I=D}K.sort(function(M,L){return(E?(M>=I&&L>=I)?ML:(M<=I&&L<=I)?M>L:MO){O=K}if(I>N){N=I}if(Kcufoncanvas{text-indent:0;}@media screen{cvml\\\\:shape,cvml\\\\:rect,cvml\\\\:fill,cvml\\\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute;}cufoncanvas{position:absolute;text-align:left;}cufon{display:inline-block;position:relative;vertical-align:'+(h?\"middle\":\"text-bottom\")+\";}cufon cufontext{position:absolute;left:-10000in;font-size:1px;}a cufon{cursor:pointer}}@media print{cufon cufoncanvas{display:none;}}\").replace(/;/g,\"!important;\"));function c(i,j){return a(i,/(?:em|ex|%)$|^[a-z-]+$/i.test(j)?\"1em\":j)}function a(l,m){if(m===\"0\"){return 0}if(/px$/i.test(m)){return parseFloat(m)}var k=l.style.left,j=l.runtimeStyle.left;l.runtimeStyle.left=l.currentStyle.left;l.style.left=m.replace(\"%\",\"em\");var i=l.style.pixelLeft;l.style.left=k;l.runtimeStyle.left=j;return i}function f(l,k,j,n){var i=\"computed\"+n,m=k[i];if(isNaN(m)){m=k.get(n);k[i]=m=(m==\"normal\")?0:~~j.convertFrom(a(l,m))}return m}var g={};function d(p){var q=p.id;if(!g[q]){var n=p.stops,o=document.createElement(\"cvml:fill\"),i=[];o.type=\"gradient\";o.angle=180;o.focus=\"0\";o.method=\"sigma\";o.color=n[0][1];for(var m=1,l=n.length-1;m').html(data);\r\n if ($resetPage.find(\"#ResetSuccess\").length > 0) {\r\n alert('The database has been reset to its initial population.');\r\n window.location.reload();\r\n } else\r\n // In case of an error, we simply navigate to the old Installer.php to show the error\r\n // Of course there is a very small possibility that reset will succeed now, but that does not cause any problems\r\n window.location.href = 'Installer.php'; \r\n },\r\n error: function(data){ alert('NETWORK ERROR\\n\\nThe database has not been reset.'); }\r\n });\r\n}\r\n\r\n/* A clone of the top-level atom is parked on #Rollback at edit start. On cancel, the atom and its navigation handlers are put back \r\n * on #ScrollPane. This is a feasible solution since the interfaces will be of a manageable size */\r\nfunction startEditing() {\r\n $('#Rollback').empty(); // in case we start twice for some reason\r\n if ($('#AmpersandRoot').attr('isNew')!='true') // for create new, we don't need to roll back (cancel is navigate back)\r\n $('#Rollback').append($('#ScrollPane > .Atom').clone(true, true)); /* (true,true) is needed to deep-copy edit handlers */\r\n $('#AmpersandRoot').attr('editing','true');\r\n $('#AmpersandRoot').attr('style',''); // dummy update to have Safari refresh css (it doesn't recognize non-standard attribute changes)\r\n clearNavigationHandlers();\r\n setEditHandlers();\r\n traceDbCommands(); // to initialize command list\r\n\r\n clearLogItems($('#ErrorLog')); // lists are cleared here and in cancelEditing, in case back button causes multiple start or cancel actions\r\n clearLogItems($('#PhpLog'));\r\n}\r\n\r\nfunction cancelEditing() {\r\n window.onbeforeunload = null; // disable the navigation warning (it is set in computeDbCommands)\r\n \r\n if ($('#AmpersandRoot').attr('isNew')=='true') {\r\n // When the creation of an atom is canceled, we simply navigate back. The atom was created in a temporary transaction,\r\n // so we don't need to delete anything.\r\n history.go(-1);\r\n } else {\r\n $('#ScrollPane > .Atom').remove(); \r\n $('#ScrollPane').append($('#Rollback > .Atom')); // this constitutes a move\r\n \r\n clearLogItems($('#ErrorLog')); // lists are cleared here and in startEditing, in case back button causes multiple start or cancel actions\r\n clearLogItems($('#PhpLog'));\r\n \r\n $('#AmpersandRoot').attr('editing','false');\r\n $('#AmpersandRoot').attr('style',''); // dummy update to have Safari refresh css (it doesn't recognize non-standard attribute changes)\r\n }\r\n}\r\n\r\nfunction commitEditing() {\r\n var dbCommands = getCommandsToSend();\r\n if (getCommandsToSend()) {\r\n window.onbeforeunload = null; // disable the navigation warning (it is set in computeDbCommands)\r\n sendCommands(dbCommands);\r\n }\r\n}\r\n\r\n// Return current edit commands (if valid) as a download link\r\nfunction downloadEditScript(anchorElt, event) {\r\n event.stopPropagation(); // To prevent edit log from collapsing/expanding on button click.\r\n var context = $('#AmpersandRoot').attr('context');\r\n var interface = $('#AmpersandRoot').attr('interface');\r\n\r\n var dbCommands = getCommandsToSend();\r\n if (dbCommands) {\r\n var commandsJson = JSON.stringify(dbCommands);\r\n // Returning a download link from JavaScript is surprisingly tricky, but we can do it by modifying the element that contains the download button.\r\n $(anchorElt).attr(\r\n { 'download': context + '_' + interface + '_editCommands.json'\r\n , 'href': 'data:application/json;charset=utf-8,' + encodeURI(commandsJson) // encodeURI prevents spaces from disappearing\r\n , 'target': '_blank'\r\n });\r\n }\r\n}\r\n\r\n// Stop editing, and, if commands are valid (no empty's or duplicated), return command array\r\nfunction getCommandsToSend() {\r\n $editedAtom = getEnclosingAtom( $('#atomEditor') );\r\n if ($editedAtom.length > 0) // autocomplete is extremely slow in its cancel and somehow blurs after the cancel event is handled,\r\n stopAtomEditing($editedAtom); // so we check whether it was active and stop any editing here.\r\n \r\n if (getEmptyAtomsNotInTemplates().length > 0) {\r\n alert('Please fill out all atoms first.');\r\n return null;\r\n }\r\n if (getNonUniqueAtomLists().length > 0) {\r\n alert('Please resolve duplicate atom names.');\r\n return null;\r\n }\r\n \r\n var dbCommands = computeDbCommands();\r\n if ($('#AmpersandRoot').attr('isNew')=='true') {\r\n // If we commit a newly created atom, we also need to add the atom to the concept table.\r\n var atom = $('#AmpersandRoot').attr('atom');\r\n var concept = $('#AmpersandRoot').attr('concept');\r\n dbCommands.unshift( mkDbCommandAddToConcept(atom,concept) ); // put addToConcept command in front\r\n }\r\n return dbCommands;\r\n}\r\n\r\nfunction sendCommands(dbCommands) {\r\n var interface = $('#AmpersandRoot').attr('interface');\r\n $.post('php/Database.php', \r\n { commands: JSON.stringify(dbCommands), interface: encodeURIComponent(interface), role: getSelectedRole() },\r\n function(data) {\r\n $results = $(data);\r\n $errors = $(data).find('.Error');\r\n $logMessages = $(data).find('.LogMsg');\r\n $invariantViolations = $(data).find('#InvariantRuleResults > .AmpersandErr');\r\n $signals = $(data).find('#ProcessRuleResults > .AmpersandErr');\r\n setLogItems($('#SignalLog'), $signals);\r\n\r\n setLogItems($('#PhpLog'), $logMessages);\r\n \r\n if ($errors.length + $invariantViolations.length > 0) {\r\n setLogItems($('#ErrorLog'), $invariantViolations);\r\n addLogItems($('#ErrorLog'), $errors);\r\n $('#ErrorLog').attr('minimized','false'); // always maximize window\r\n } \r\n else { // we could simply reload here, but this way the state of the log windows is not changed/\r\n getNoCache( window.location.href, function(data){\r\n $newPage = $('
    ').html(data); \r\n // NOTE: need to be careful here not to put elements with id's in the DOM before removing the old ones\r\n\r\n // replace the root Atom with the new one\r\n $('#ScrollPane > .Atom').remove();\r\n $('#ScrollPane').append($newPage.find('#ScrollPane > .Atom'));\r\n\r\n // update the timestamp\r\n $('#AmpersandRoot').attr('timestamp', $newPage.find('#AmpersandRoot').attr('timestamp') );\r\n $('#AmpersandRoot').attr('isNew', $newPage.find('#AmpersandRoot').attr('isNew') );\r\n $('#AmpersandRoot').attr('editing','false');\r\n\r\n // we ignore the signals from $newPage, since we have just set them.\r\n \r\n initializeAtoms(); \r\n $('#AmpersandRoot').attr('style',''); // dummy update to have Safari refresh css (it doesn't recognize non-standard attribute changes)\r\n });\r\n }\r\n });\r\n}\r\n\r\n\r\nfunction getEmptyAtomsNotInTemplates() {\r\n $emptyAtomsNotInTemplates = $('#AmpersandRoot .Atom[atom=\"\"]').map( function() {\r\n if ($(this).parents().filter('[rowType=NewAtomTemplate]').length)\r\n return null;\r\n else \r\n return $(this);\r\n });\r\n return $emptyAtomsNotInTemplates;\r\n}\r\n\r\nfunction getNonUniqueAtomLists() {\r\n $nonUniqueAtomLists =$('#AmpersandRoot .AtomList').map( function() { // called also on lists in templates, but that's not a big deal\r\n $atoms = $(this).find('>.AtomRow[rowType=Normal]>.AtomListElt>.Atom');\r\n for (var i=0; i<$atoms.length; i++)\r\n for (var j=i+1; j<$atoms.length; j++)\r\n if ($($atoms[i]).attr('atom') == $($atoms[j]).attr('atom'))\r\n return $(this); \r\n return null;\r\n });\r\n return $nonUniqueAtomLists;\r\n}\r\n\r\nfunction preventNameClashes(dbCommands) {\r\n var safeDbCommands = new Array();\r\n var renameCommands = new Array();\r\n var tempCounter = 1;\r\n \r\n while (dbCommands.length) {\r\n\t var dbCommand = dbCommands.shift();\r\n\t \r\n\t var safeDbCommand = dbCommand;\r\n\t \r\n\t if (dbCommand.dbCmd=='update' &&\r\n\t \t\tisEditSourceTuple(dbCommand.relation, dbCommand.isFlipped, dbCommand.parentAtom, dbCommand.childAtom, dbCommands)) {\r\n\t \tlog('clash');\r\n var tempAtom = mkUniqueAtomName('Temp'+tempCounter++);\r\n\t \tif (dbCommand.parentOrChild=='parent') {\r\n\t \t\tvar finalAtom = safeDbCommand.parentAtom; \r\n\t \t\tsafeDbCommand.parentAtom = tempAtom;\r\n \trenameCommands.push(mkDbCommandUpdate(dbCommand.relation, dbCommand.isFlipped, finalAtom, dbCommand.parentConcept,\r\n \t dbCommand.childAtom, dbCommand.childConcept, 'parent', tempAtom));\r\n\t \t}\r\n else {\r\n\t \t\tvar finalAtom = safeDbCommand.childAtom; \r\n \tsafeDbCommand.childAtom = tempAtom;\r\n \trenameCommands.push(mkDbCommandUpdate(dbCommand.relation, dbCommand.isFlipped, dbCommand.parentAtom, dbCommand.parentConcept,\r\n \t finalAtom, dbCommand.childConcept, 'child', tempAtom));\r\n }\r\n\t }\r\n\t \t\r\n\t safeDbCommands.push(safeDbCommand);\r\n }\r\n\r\n\treturn [].concat(safeDbCommands, renameCommands);\r\n}\r\n\r\nfunction isEditSourceTuple(relation, isFlipped, parentAtom, childAtom, dbCommands) {\r\n\tlog('checking: ' +relation +' '+ isFlipped+' '+ parentAtom+' '+childAtom);\r\n\tfor (var i=0; i'+relation+(isFlipped?'~':'')+''; \r\n}\r\n\r\nfunction showAtom(atom) {\r\n return atom ? atom : 'EMPTY';\r\n}\r\n\r\nfunction showDbCommand(dbCommand) {\r\n switch (dbCommand.dbCmd) {\r\n case 'update':\r\n var originalPair = '('+(dbCommand.parentOrChild == 'parent' ? dbCommand.originalAtom + ',' + dbCommand.childAtom \r\n : dbCommand.parentAtom + ',' + dbCommand.originalAtom) + ')';\r\n var newPair = '(' + showAtom(dbCommand.parentAtom) + ' : ' + dbCommand.parentConcept \r\n + ',' + showAtom(dbCommand.childAtom) + ' : ' + dbCommand.childConcept + ')';\r\n if (dbCommand.originalAtom =='')\r\n return 'Add ' + showRelation(dbCommand.relation,dbCommand.isFlipped) + ': ' +\r\n newPair;\r\n else\r\n return 'Update ' + showRelation(dbCommand.relation,dbCommand.isFlipped) + ': ' +\r\n originalPair+' ~> '+newPair;\r\n case 'delete':\r\n return 'Delete ' + showRelation(dbCommand.relation,dbCommand.isFlipped)+': ' +\r\n '('+showAtom(dbCommand.parentAtom)+','+showAtom(dbCommand.childAtom)+')';\r\n }\r\n return 'Undefined command: '+dbCommand;\r\n}\r\n\r\n\r\nfunction mkDbCommandAddToConcept(atom, concept) {\r\n return {dbCmd: 'addToConcept', atom:atom, concept:concept};\r\n}\r\n\r\n// update with '' as originalAtom is insert\r\nfunction mkDbCommandUpdate(relation, relationIsFlipped, parentAtom, parentConcept, childAtom, childConcept, parentOrChild, originalAtom) {\r\n return {dbCmd: 'update', relation:relation, isFlipped:relationIsFlipped, parentAtom:parentAtom, parentConcept:parentConcept,\r\n childAtom:childAtom, childConcept:childConcept, parentOrChild:parentOrChild, originalAtom:originalAtom};\r\n}\r\n\r\nfunction mkDbCommandDelete(relation, relationIsFlipped, parentAtom, childAtom) {\r\n return {dbCmd: 'delete', relation:relation, isFlipped:relationIsFlipped, parentAtom:parentAtom, childAtom:childAtom};\r\n}\r\n\r\nfunction computeDbCommands() {\r\n dbCommands = new Array();\r\n $('.Atom .Atom').map(function () { // for every parent child pair of atoms (only immediate, so no .. .. )\r\n $childAtom = $(this);\r\n if ($childAtom.parents().filter('[rowType=NewAtomTemplate]').length == 0) {\r\n //log(getEnclosingAtom($childAtom).attr('atom') + '<-->' + $childAtom.attr('atom'));\r\n \r\n var $atomList = getEnclosingAtomList($childAtom);\r\n var relation = $atomList.attr('relation'); \r\n \r\n if (relation && $atomList.attr('relationIsEditable')) {\r\n var relationIsFlipped = $atomList.attr('relationIsFlipped') ? attrBoolValue($atomList.attr('relationIsFlipped')) : false;\r\n var $parentAtom = getEnclosingAtom($childAtom);\r\n var parentAtom = $parentAtom.attr('atom');\r\n var parentConcept = getConcept($parentAtom);\r\n var childAtom = $childAtom.attr('atom');\r\n var childConcept = getConcept($childAtom);\r\n\r\n // parent deleted does not affect child\r\n // if parent is new, then all updates will be handled at child\r\n \r\n if( $parentAtom.attr('status') == 'modified') {\r\n if ($childAtom.attr('status') != 'new' && $childAtom.attr('status') != 'deleted' ) {\r\n var originalAtom = $parentAtom.attr('originalAtom');\r\n var unmodifiedChildAtom = $childAtom.attr('originalatom') ? $childAtom.attr('originalAtom') : childAtom;\r\n // we want to delete/update the original tuple with the original child, not a modified one\r\n dbCommands.push(mkDbCommandUpdate(relation, relationIsFlipped, parentAtom, parentConcept, \r\n unmodifiedChildAtom, childConcept, 'parent', originalAtom));\r\n }\r\n }\r\n\r\n switch($childAtom.attr('status')) {\r\n case 'new':\r\n dbCommands.push(mkDbCommandUpdate(relation, relationIsFlipped, parentAtom, parentConcept,\r\n childAtom, childConcept, 'child', ''));\r\n break;\r\n case 'deleted':\r\n var unmodifiedParentAtom = $parentAtom.attr('originalAtom') ? $parentAtom.attr('originalAtom') : parentAtom;\r\n var unmodifiedChildAtom = $childAtom.attr('originalatom') ? $childAtom.attr('originalAtom') : childAtom;\r\n dbCommands.push(mkDbCommandDelete(relation, relationIsFlipped, unmodifiedParentAtom, unmodifiedChildAtom));\r\n break;\r\n case 'modified':\r\n var originalAtom = $childAtom.attr('originalAtom');\r\n // - if parent is modified, the original tuple will already have been deleted (tree traversal handles parent first)\r\n // so we can update the tuple with the modified parent. Hence no special case for parent with status=modified\r\n // - if parent is new, original atom will be empty, since the atom was automatically inserted because of multiplicities\r\n // - parent cannot be deleted, since then its children would also be deleted\r\n dbCommands.push(mkDbCommandUpdate(relation, relationIsFlipped, parentAtom, parentConcept,\r\n childAtom, childConcept, 'child', originalAtom));\r\n break;\r\n } \r\n }\r\n }\r\n });\r\n \r\n if (dbCommands.length > 0 && navigationWarningEnabled) { \r\n window.onbeforeunload = function() { return \"The page has been modified, are you sure you wish to navigate away?\"; };\r\n } else {\r\n window.onbeforeunload = null;\r\n }\r\n \r\n return preventNameClashes(dbCommands);\r\n}\r\n\r\nfunction traceDbCommands() {\r\n clearLogItems($('#EditLog'));\r\n var dbCmds = computeDbCommands();\r\n for (var i=0; i'+showDbCommand(dbCmds[i])+'
    '));\r\n}\r\n\r\n\r\n\r\n// Editing UI\r\n\r\nfunction clearEditHandlers() {\r\n $('#AmpersandRoot .AtomList').unbind('mouseenter mouseleave');\r\n $('#AmpersandRoot .AtomName').unbind('click');\r\n $('#AmpersandRoot .DeleteStub').unbind('click');\r\n $('#AmpersandRoot .InsertStub').unbind('click');\r\n}\r\n\r\n// When an atom is modified, we disable editing on all of its ancestors to the root, and also on\r\n// all its descendents. Note that the atom itself, as well as its siblings and their descendents\r\n// remain editable.\r\n// This code only has an effect when atoms with subinterfaces are explicitly unhidden\r\n// during editing in a Custom.css.\r\nfunction disableEditingAncestorsDescendents($atom) {\r\n\tvar $ancestors = $atom.parents().filter('.Atom').find('>.AtomName'); \r\n\tvar $descendents = $atom.find('>.InterfaceList .AtomName'); \r\n\t$ancestors.unbind('click');\r\n\t$descendents.unbind('click');\r\n}\r\n\r\nfunction setEditHandlers() {\r\n setEditHandlersBelow($('#AmpersandRoot'));\r\n}\r\n\r\nfunction setEditHandlersBelow($elt) {\r\n\r\n //on hover over an AtomList, set the attribute hover to true for that AtomList, but not for any child AtomLists\r\n // (this is not possible with normal css hover pseudo elements)\r\n $elt.find('.AtomList').hover(function () { \r\n // mouse enter handler\r\n \r\n var $atomList = getEnclosingAtomList($(this));\r\n $atomList.attr('hover', 'false');\r\n $(this).attr('hover', 'true');\r\n }, function () {\r\n // mouse exit handler\r\n \r\n $atomList = getEnclosingAtomList($(this));\r\n $atomList.attr('hover', 'true');\r\n $(this).attr('hover', 'false');\r\n });\r\n \r\n $elt.find('.AtomName').click(function(){\r\n var $atomList = getEnclosingAtomList($(this));\r\n var relationToParent = $atomList.attr('relation');\r\n \r\n var $atom = getEnclosingAtom($(this)); \r\n \r\n // this code also allows editing if there is a child atom in an editable relation\r\n //var childrenWithRelation = $atom.find('>.InterfaceList>.Interface>.AtomList[relation]');\r\n if (relationToParent /* || childrenWithRelation.length != 0 */) {\r\n startAtomEditing($atom);\r\n }\r\n });\r\n \r\n $elt.find('.DeleteStub').click(function() {\r\n var $atom = $(this).next().children().first(); // children is for AtomListElt\r\n var $atomList = getEnclosingAtomList($(this));\r\n \r\n if ($atom.attr('status')=='new')\r\n getEnclosingAtomRow($(this)).remove(); // remove the row of the table containing delete stub and atom\r\n else {\r\n if ($atom.attr('status') == 'modified') { // restore the original atom name on delete\r\n $atom.attr('atom', $atom.attr('originalAtom'));\r\n $atom.find('.AtomName').text($atom.attr('originalAtom')); // text() automatically escapes text\r\n }\r\n $atom.attr('status','deleted');\r\n getEnclosingAtomRow($(this)).attr('rowStatus','deleted'); // to make the entire row invisible\r\n // we cannot use rowType for this, since we only change visibility, the rest of the style should be same as for Normal\r\n \r\n $atom.find('.InterfaceList').remove(); // delete all interfaces below to prevent any updates on the children to be sent to the server\r\n }\r\n \r\n updateNrOfAtoms($atomList);\r\n traceDbCommands();\r\n });\r\n \r\n $elt.find('.InsertStub').click(function (event) {\r\n var $atomList = getEnclosingAtomList($(this));\r\n \r\n $newAtomTemplate = $atomList.children().filter('[rowType=NewAtomTemplate]');\r\n \r\n $newAtomTableRow = $newAtomTemplate.clone();\r\n\r\n $newAtomTableRow.attr('rowType','Normal'); // remove the NewAtomTemplate class to make the new atom visible\r\n $newAtomTemplate.before( $newAtomTableRow ); \r\n \r\n setEditHandlersBelow($newAtomTableRow); // add the necessary handlers to the new element\r\n // don't need to add navigation handlers, since page will be refreshed before navigating is allowed\r\n \r\n var $newAtom = $newAtomTableRow.find('>.AtomListElt>.Atom');\r\n setUniqueNamesForEmptyAtoms($newAtom); // set unique name if atom name is invisible (also for child atoms) \r\n\r\n // if the atom name is visible, we start editing it.\r\n if ( $newAtom.find('>.AtomName').is(\":visible\") )\r\n startAtomEditing($newAtom);\r\n \r\n updateNrOfAtoms($atomList);\r\n traceDbCommands();\r\n });\r\n}\r\n\r\nfunction updateNrOfAtoms($atomList) {\r\n var $normalRows = $atomList.find('>.AtomRow[rowType=\"Normal\"]');\r\n $atomList.attr('nrOfAtoms', $normalRows.length - $normalRows.filter('[rowStatus=\"deleted\"]').length );\r\n // with --dev, rows are not removed but have their status set to deleted\r\n}\r\n\r\n// Create a form that contains a text field, put it after $atom, and hide $atom.\r\nfunction startAtomEditing($atom) {\r\n var $atomName = $atom.find('>.AtomName');\r\n if ($atom.attr('status')=='deleted')\r\n return;\r\n \r\n $textfield = $('');\r\n// SJ 4 nov 2013; For Blobs, this should be:\r\n// $textfield = $('');\r\n// to allow larger input fields.\r\n $form = $('
    '); // we use a form to catch the Return key event\r\n $form.append($textfield);\r\n $atomName.after($form);\r\n\r\n // stop editing when the textfield loses focus\r\n \r\n $textfield.focusout(function (obj) {\r\n // jQuery bug (or really bad feature): a select in the autocomplete menu triggers a blur event on the textfield.\r\n // If we stopEditing on this blur, the select action is not registered.\r\n // As a workaround, we don't stopEditing if the menu is visible. In that case, stopEditing is called in the \r\n // autocomplete close event handler below. A consequence of this approach is that whenever the autocomplete menu is\r\n // closed, atom editing is also ended. However, this is not a big deal and also seems to be the only solution, as\r\n // there is no way to detect whether the blur was a genuine blur, or caused by select.\r\n if ($('.ui-autocomplete:visible').length == 0)\r\n stopAtomEditing($atom);\r\n \r\n return true;\r\n });\r\n // and when the user presses the return key\r\n $form.submit(function () {\r\n stopAtomEditing($atom);\r\n return false; // this prevents the browser from actually submitting the form\r\n });\r\n\r\n initializeAutocomplete($textfield, $atom);\r\n $textfield.focus().select();\r\n $atomName.hide();\r\n\r\n}\r\n\r\n// take the old value from $atom and replace its atom attribute as well as its text\r\n// contents with the new value from the text field. Then show $atom again and\r\n// remove the text field.\r\nfunction stopAtomEditing($atom) {\r\n var concept = getConcept($atom); \r\n\r\n var $atomName = $atom.find('>.AtomName');\r\n var atom = $atom.attr('atom');\r\n \r\n var $form = $('#atomEditor');\r\n var newAtomText = $form.children().filter('input').attr('value');\r\n// SJ 4 nov 2013; just for blobs, this should be something like:\r\n// var newAtomText = $form.children().filter('textarea').val();\r\n// in order to allow textareas rather than inputs.\r\n $form.remove();\r\n\r\n // todo if newAtom is viewed and has no atom, don't do anything\r\n var newAtom;\r\n if (conceptHasView(concept)) { // if concept has a view, we map the view back onto an atom (todo: use autocomplete selection, so we don't need this lookup)\r\n newAtom = getAtomForView(newAtomText, concept);\r\n \r\n if (!newAtom) { // If the entered view does not correspond to an atom, the edit operation is ignored.\r\n $atomName.attr('style',''); // Undo the hide() action from above. We don't use show, because that sets a style attribute on the div,\r\n // which overrides all stylesheets\r\n return;\r\n }\r\n } else {\r\n newAtom = newAtomText; // if concept has no view, then newAtom is simply atomText\r\n }\r\n $atom.attr('atom',newAtom);\r\n \r\n $atomName.text(newAtomText);\r\n $atomName.attr('style',''); // undo hide()\r\n \r\n if (newAtom!=atom) {\r\n \r\n if ($atom.attr('status')!='new') {\r\n \r\n if (!$atom.attr('originalAtom')) { // first time we edit this field, set originalAtom to the old value \r\n $atom.attr('originalAtom',atom);\r\n $atom.attr('status','modified');\r\n \r\n disableEditingAncestorsDescendents($atom);\r\n } else // the atom was edited before\r\n if ($atom.attr('originalAtom')==newAtom)\r\n $atom.attr('status','unchanged'); // apparently, it was changed back to its original value\r\n }\r\n\r\n traceDbCommands();\r\n }\r\n}\r\n\r\n// For documentation, make sure to read docs.jquery.com/UI/Autocomplete and not docs.jquery.com/Plugins/autocomplete (which is incorrect)\r\nfunction initializeAutocomplete($textfield, $atom) {\r\n var $atomList = getEnclosingAtomList($atom);\r\n var concept = $atomList.length ? $atomList.attr('concept') : $('#AmpersandRoot').attr('concept'); \r\n // If there is no enclosing list, we are at the top-level atom and take the concept from AmpersandRoot \r\n\r\n $textfield.autocomplete({ source: getAllConceptAtoms(concept)\r\n , minLength: 0\r\n , close: function(event, ui) { \r\n if (typeof event.originalEvent != 'undefined')\r\n stopAtomEditing($atom);\r\n // We only stop editing here if the close was caused by an explicit event.\r\n // If the menu disappears because the user is typing (when the text does not match any autocomplete string) \r\n // the originalEvent is not defined and we don't stop editing.\r\n }\r\n , select: function(event, ui) { \r\n // Another jQuery problem: on a mouse click, the textfield has not been updated\r\n // at this point, so stopAtomEditing does not register the selected value.\r\n // As a workaround, we explicitly set the value to the menu selection.\r\n // Strangely enough, there is no problem for the Return key event.\r\n if (event.originalEvent && event.originalEvent.originalEvent &&\r\n event.originalEvent.originalEvent.type == \"click\")\r\n $textfield.attr('value', ui.item.value);\r\n\r\n stopAtomEditing($atom); \r\n return true;\r\n }});\r\n}\r\n\r\n\r\n//Navigation\r\n\r\nfunction navigateTo(interface, atom) {\r\n window.location.href = 'index.php?'+(typeof(interface) != 'undefined' && typeof(atom) != 'undefined' ?\r\n 'interface='+encodeURIComponent(interface)+'&atom='+encodeURIComponent(atom) : '')\r\n +'&role='+getSelectedRole();\r\n // the check for undefined is necessary for when navigateTo is called on a role change from the Main page\r\n}\r\n\r\nfunction navigateToNew(interface, concept) {\r\n var atom = mkUniqueAtomName(concept);\r\n window.location.href = 'index.php?interface='+encodeURIComponent(interface)+'&atom='+encodeURIComponent(atom) + \r\n '&role='+getSelectedRole(); \r\n}\r\n\r\nfunction clearNavigationHandlers() {\r\n $('#AmpersandRoot .AtomName').unbind('click'); \r\n}\r\n\r\nfunction setLogNavigationHandlers($logWindow) {\r\n $logWindow.find(\".Pair > .PairAtom\").map(function () {\r\n $pairAtom = $(this); \r\n var concept =$pairAtom.attr('concept');\r\n var atom = $pairAtom.attr('atom');\r\n \r\n setAtomNavigationHandler( $pairAtom, atom, concept );\r\n });\r\n}\r\n\r\nfunction setNavigationHandlers() {\r\n $(\"#AmpersandRoot .AtomName\").map(function () {\r\n $atomList = getEnclosingAtomList($(this)); \r\n $atom=getEnclosingAtom($(this));\r\n var concept =$atomList.attr('concept');\r\n var atom = $atom.attr('atom');\r\n \r\n setAtomNavigationHandler( $(this), atom, concept );\r\n });\r\n}\r\n\r\nfunction setAtomNavigationHandler($elt, atom, concept) {\r\n var interfaces = getInterfacesMap()[concept]; // NOTE: getInterfacesMap is assumed to be declared \r\n // (since js has no import mechanism and we don't want to pass variables around all the time, a more elegant solution is not possible)\r\n \r\n if (typeof(interfaces) != 'undefined' && interfaces.length > 0) { // if there are no interfaces for this concept, don't change the pointer and don't insert a click event\r\n // undefined means no interfaces are defined, length == 0 means no interfaces are visible for selected role\r\n //$elt.click(function (event) {\r\n $elt.css({\"text-decoration\":\"underline\",\"font-weight\":\"bold\"}).click(function (event) {\r\n if (interfaces.length == 1)\r\n navigateTo(interfaces[0], atom);\r\n else\r\n mkInterfaceMenu(event, interfaces, atom);\r\n });\r\n } \r\n}\r\n\r\nfunction mkInterfaceMenu(event, interfaces, atom) {\r\n $('#InterfaceContextMenu').remove();\r\n var $fullScreenMask = $(\"
    \"); /* the mask is for hiding the menu if we click anywhere outside it */\r\n var $menu = $('
    ');\r\n\r\n $fullScreenMask.click(function () {\r\n $menu.remove();\r\n $fullScreenMask.remove();\r\n });\r\n $('body').append($fullScreenMask);\r\n $fullScreenMask.append($menu);\r\n \r\n for (var i=0; i'+interfaces[i]+'
    '); \r\n\r\n $menu = $menu.append($item);\r\n \r\n addClickEvent($item,interfaces[i],atom);\r\n // We need this separate function here to get a reference to i's value rather than the variable i.\r\n // (otherwise we encounter the 'infamous loop problem': all i's have the value of i after the loop)\r\n }\r\n \r\n // take into account menu size and page size, so menu is always visible, also at the edges\r\n $menu.offset({ left: Math.min(event.pageX, $(document).width() - $menu.outerWidth() - 2 )\r\n , top: Math.min(event.pageY, $(document).height() - $menu.outerHeight() - 2) });\r\n\r\n}\r\n\r\nfunction addClickEvent($item, interface, atom) { \r\n $item.click(function () {\r\n navigateTo(interface, atom);\r\n $('#InterfaceContextMenu').remove(); // so the menu + mask are gone when we press back (maybe not necessary anymore, since we disable the cache)\r\n $('#FullScreenMask').remove();\r\n return false;\r\n });\r\n}\r\n\r\n\r\n//Views\r\n\r\nfunction conceptHasView(concept) {\r\n return getEditableConceptInfo()[concept]['hasView'];\r\n}\r\n\r\n// return the atom for view, or null if the view is not in the atomViewMap\r\nfunction getAtomForView(view, concept) {\r\n var conceptAtomViewMap = getEditableConceptInfo()[concept]['atomViewMap'];\r\n \r\n var atom = null;\r\n for (var i=0; i\"); /* the mask is for hiding the menu if we click anywhere outside it */\r\n \r\n $fullScreenMask.click(function () {\r\n $('#CreateMenu').hide();\r\n $fullScreenMask.remove();\r\n });\r\n $('#CreateMenu').show();\r\n $('body').append($fullScreenMask);\r\n });\r\n \r\n $('#CreateMenu>.MenuItem').map(function () {\r\n $(this).click(function () {\r\n navigateToNew($(this).attr('interface'), $(this).attr('concept'));\r\n $('#CreateMenu').hide(); // so the menu + mask are gone when we press back (maybe not necessary anymore, since we disable the cache)\r\n $fullScreenMask.remove();\r\n });\r\n });\r\n}\r\n\r\n\r\n// LogWindows\r\n\r\nfunction initLogWindows() {\r\n $('.LogWindow>.Title').click(minimaximizeParentLogWindow);\r\n $('.LogWindow>.MinMaxButton').click(minimaximizeParentLogWindow);\r\n $('#SignalLog>.LogMsg').remove(); // don't show logs here\r\n if ($('#SignalLog>.LogItem').length>0)\r\n $('#SignalLog').attr('nonEmpty','true');\r\n setLogNavigationHandlers($(\".LogWindow\"));\r\n}\r\n\r\nfunction minimaximizeParentLogWindow(event) {\r\n $logWindow = $(this).parents().filter('.LogWindow');\r\n $logWindow.attr('minimized', $logWindow.attr('minimized')=='true' ? 'false' : 'true');\r\n return false;\r\n}\r\n\r\nfunction clearLogItems($logWindow) {\r\n $logWindow.find('.LogItem').remove();\r\n $logWindow.attr('nonEmpty','false');\r\n}\r\n\r\n// $logItems is a jQuery set of divs (LogItem class is added here)\r\nfunction addLogItems($logWindow, $logItems) {\r\n $logItems.addClass('LogItem'); \r\n $logWindow.append($logItems);\r\n if ($logItems.length > 0)\r\n $logWindow.attr('nonEmpty','true');\r\n setLogNavigationHandlers($logItems);\r\n}\r\n\r\nfunction setLogItems($logWindow, $logItems) {\r\n clearLogItems($logWindow);\r\n addLogItems($logWindow, $logItems);\r\n}\r\n\r\n\r\n// Roles\r\n\r\nfunction changeRole() {\r\n if ($('#AmpersandRoot').attr('isNew')=='true') {\r\n // Role changes are events in the history, so for create new, this means the old create-new page remains in the\r\n // history and will be shown after save or cancel. Unfortunately, it is not reloaded, so it's still in edit mode showing empty fields.\r\n // Forcing a refresh after going back, or removing the current history item and moving to a different page is not possible using normal page navigation,\r\n // so until we have an ajax-based implementation, this is not supported. Disabling the cache to force a refresh even on a normal browser back could\r\n // also solve the problem, but this seems to be very tricky.\r\n alert('Role changes during create new are currently not supported.');\r\n return;\r\n } else {\r\n var interface = $('#AmpersandRoot').attr('interface');\r\n \r\n var atom = $('#AmpersandRoot').attr('atom');\r\n navigateTo(interface, atom); // navigate to takes the role from the updated selector\r\n }\r\n}\r\n\r\n\r\n// Refresh timer\r\n\r\nfunction startRefreshTimer() {\r\n var refreshInterval = $('#AmpersandRoot').attr('refresh');\r\n\r\n if (refreshInterval>0) {\r\n setRefreshTimer(refreshInterval*1000);\r\n }\r\n}\r\n\r\nfunction setRefreshTimer(ms) { \r\n timer = setTimeout('checkDbUpdates()',ms);\r\n}\r\n\r\nfunction stopRefreshTimer() {\r\n clearTimeout(timer);\r\n}\r\n\r\nfunction checkDbUpdates() {\r\n if ($('#AmpersandRoot').attr('editing') == 'true') // no refresh during editing \r\n startRefreshTimer();\r\n else {\r\n var currentTimestamp = $('#AmpersandRoot').attr('timestamp');\r\n \r\n // todo: is this okay without nocache?\r\n $.post(\"php/Database.php?getTimestamp\",function(data){\r\n var dbTimestamp = $(data).attr('timestamp');\r\n var dbIsModified = dbTimestamp != currentTimestamp;\r\n log(currentTimestamp + ' vs '+dbTimestamp + ' ' + (dbIsModified ? 'modified' : 'not modified')); \r\n \r\n // If the timestamp on the server is different, it must be newer, so we need a refresh\r\n if (dbIsModified) {\r\n getNoCache(window.location.href, function(data){\r\n $newPage = $('
    ').html(data);\r\n // NOTE: need to be careful here not to put elements with id's in the DOM before removing the old ones\r\n\r\n // replace the root Atom with the new one\r\n var $oldRootAtom = $('#ScrollPane > .Atom'); // save the old atom so we can do a diff below\r\n $('#ScrollPane > .Atom').remove(); \r\n $('#ScrollPane').append($newPage.find('#ScrollPane > .Atom'));\r\n\r\n // update the signals\r\n $signals = $(data).find('#SignalLog > .AmpersandErr');\r\n setLogItems($('#SignalLog'), $signals);\r\n\r\n // update the timestamp\r\n $('#AmpersandRoot').attr('timestamp', $newPage.find('#AmpersandRoot').attr('timestamp') );\r\n\r\n initializeAtoms(); \r\n startRefreshTimer();\r\n markDifference($('#ScrollPane > .Atom'), $oldRootAtom);\r\n });\r\n }\r\n else\r\n startRefreshTimer();\r\n });\r\n }\r\n}\r\n\r\nfunction markDifference($newAtom, $oldAtom) {\r\n $diffRoot = getDiffRoot($newAtom, $oldAtom);\r\n if ($diffRoot)\r\n animateDifference($diffRoot);\r\n}\r\n\r\nfunction getDiffRoot($newAtom, $oldAtom) {\r\n //log ($newAtom.attr('atom') + ' vs ' + $oldAtom.attr('atom'));\r\n if ($newAtom.find('>.AtomName').text() != $oldAtom.find('>.AtomName').text())\r\n return $newAtom.find('>.AtomName');\r\n else {\r\n var $newChildInterfaces = $newAtom.find('>.InterfaceList>.Interface'); \r\n var $oldChildInterfaces = $oldAtom.find('>.InterfaceList>.Interface');\r\n \r\n for (var j=0; j<$newChildInterfaces.length; j++) { \r\n // interfaces won't change, but we need to traverse them to be able to create markers at the AtomList level\r\n \r\n var $newChildAtoms = $newChildInterfaces.eq(j).find('>.AtomList>.AtomRow[rowType=Normal]>.AtomListElt>.Atom'); \r\n var $oldChildAtoms = $oldChildInterfaces.eq(j).find('>.AtomList>.AtomRow[rowType=Normal]>.AtomListElt>.Atom'); \r\n \r\n if ($newChildAtoms.length != $oldChildAtoms.length)\r\n return $newChildInterfaces.eq(j);\r\n else {\r\n for (var i=0; i<$newChildAtoms.length; i++) {\r\n //log ('child '+i);\r\n var $differentElt = getDiffRoot($newChildAtoms.eq(i), $oldChildAtoms.eq(i));\r\n if ($differentElt)\r\n return $differentElt;\r\n }\r\n }\r\n }\r\n return null;\r\n }\r\n}\r\n\r\nfunction animateTo($elt, color, k) {\r\n $elt.animate({ backgroundColor: color }, 500, null, k);\r\n}\r\n\r\nfunction animateDifference( $elt ) {\r\n var color = \"red\"; \r\n animateTo($elt, color, function () {\r\n animateTo($elt, \"transparent\", function () {\r\n animateTo($elt, color, function () {\r\n animateTo($elt, \"transparent\", function () {\r\n animateTo($elt, color, function () {\r\n animateTo($elt, \"transparent\", function () {\r\n }); }); }); }); }); });\r\n}\r\n\r\n\r\n// Utils\r\n\r\nfunction log(msg) {\r\n if (typeof console!='undefined') // only log when Firebug console is present\r\n console.log(msg);\r\n}\r\n\r\n// for errors that should only show up for a user with Firebug \r\nfunction logError(msg) {\r\n if (typeof console!='undefined')\r\n console.error(msg);\r\n}\r\n\r\n// precondition: concept appears on the page (and is therefore represented in getEditableConceptInfo)\r\nfunction getAllConceptAtoms(concept) {\r\n var atomViewMap = getEditableConceptInfo()[concept][\"atomViewMap\"];\r\n var atoms = new Array();\r\n for (var i=0; i