AjaXplorer/0000777000000000000000000000000011302275501014010 5ustar adminadministratorsAjaXplorer/inc/0000777000000000000000000000000011330552707014570 5ustar adminadministratorsAjaXplorer/inc/cfg-AjaXplorer.php0000766000000000000000000000135511300346563020110 0ustar adminadministrators
  • "._NPKG_LINK."
  • "; ?>AjaXplorer/inc/mnu-AjaXplorer.php0000766000000000000000000000156311330554317020152 0ustar adminadministrators"; ?>AjaXplorer/AjaXplorer/0000777000000000000000000000000011300350773016062 5ustar adminadministratorsAjaXplorer/AjaXplorer/admin.php0000766000000000000000000002603311122202530017655 0ustar adminadministratorsgetId() != "admin") { print("Forbidden"); exit(0); } $action = ""; if(isSet($_GET["get_action"])) $action = $_GET["get_action"]; switch ($action) { case "update_user_right" : if(!isSet($_GET["user_id"]) || !isSet($_GET["repository_id"]) || !isSet($_GET["right"]) || !AuthService::userExists($_GET["user_id"])) { AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, "Wrong arguments"); print(""); AJXP_XMLWriter::close(); exit(1); } $user = new AJXP_User($_GET["user_id"]); $user->setRight($_GET["repository_id"], $_GET["right"]); $user->save(); AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage("Changed right for user ".$_GET["user_id"], null); print("canRead($_GET["repository_id"])."\" write=\"".$user->canWrite($_GET["repository_id"])."\"/>"); AJXP_XMLWriter::close(); exit(1); break; case "update_user_pwd" : if(!isSet($_GET["user_id"]) || !isSet($_GET["user_pwd"]) || !AuthService::userExists($_GET["user_id"]) || trim($_GET["user_pwd"]) == "") { AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, "Wrong Arguments!"); AJXP_XMLWriter::close(); exit(1); } $res = AuthService::updatePassword($_GET["user_id"], $_GET["user_pwd"]); AJXP_XMLWriter::header(); if($res === true) { AJXP_XMLWriter::sendMessage("Password changed successfully for user ".$_GET["user_id"], null); } else { AJXP_XMLWriter::sendMessage(null, "Cannot update password : $res"); } AJXP_XMLWriter::close(); exit(1); break; case "create_user" : if(!isset($_GET["new_login"]) || $_GET["new_login"] == "" ||!isset($_GET["new_pwd"]) || $_GET["new_pwd"] == "") { AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, "Wrong Arguments!"); AJXP_XMLWriter::close(); exit(1); } $forbidden = array("guest", "admin", "share"); if(AuthService::userExists($_GET["new_login"]) || in_array($_GET["new_login"], $forbidden)) { AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, "User already exists, please choose another login!"); AJXP_XMLWriter::close(); exit(1); } if(get_magic_quotes_gpc()) $_GET["new_login"] = stripslashes($_GET["new_login"]); $_GET["new_login"] = str_replace("'", "", $_GET["new_login"]); $newUser = new AJXP_User($_GET["new_login"]); $newUser->save(); //AuthService::updatePassword($_GET["new_login"], $_GET["new_pwd"]); AuthService::createUser($_GET["new_login"], $_GET["new_pwd"]); AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage("User created successfully", null); print(""); AJXP_XMLWriter::close(); exit(1); break; case "delete_user" : $forbidden = array("guest", "admin", "share"); if(!isset($_GET["user_id"]) || $_GET["user_id"]=="" || in_array($_GET["user_id"], $forbidden)) { AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, "Wrong Arguments!"); AJXP_XMLWriter::close(); exit(1); } $res = AuthService::deleteUser($_GET["user_id"]); AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage("User successfully erased", null); print(""); AJXP_XMLWriter::close(); exit(1); case "users_list": $allUsers = AuthService::listUsers(); $userObject = new AJXP_User(""); //print("
    "); foreach ($allUsers as $userId => $userObject) { if($userId == "shared") continue; print("
    "); $imgSrc = "user_normal.png"; if($userId == "admin") $imgSrc = "user_sysadmin.png"; else if($userId == "guest") $imgSrc = "user_guest.png"; print("
    User $userId
    "); print("
    "); print("
    Repositories Rights"); foreach (ConfService::getRootDirsList() as $rootDirId => $rootDirObject) { print(""); print(""); } print("
    . ".$rootDirObject->getDisplay()." : "); $disabledString = ""; if($userId == "admin") $disabledString = "disabled"; print("Read canRead($rootDirId)?"checked":"").">"); print("    Write canWrite($rootDirId)?"checked":"").">"); print("
    "); if($userId != "guest") { print("
    Modify Password"); print(""); print(""); print(""); print("
    New Password Confirm Password
    "); } if($userId != "admin" && $userId !="guest") { print("
    Delete User"); print("To delete, check the box to confirm "); print("
    "); } print("
    "); print("
    "); //.$userObject->getId()."
    "); } //print(""); exit(1); break; case "drivers_list": AJXP_XMLWriter::header("ajxpdrivers"); print(ConfService::availableDriversToXML()); AJXP_XMLWriter::close("ajxpdrivers"); exit(1); break; case "create_repository" : $options = array(); $repDef = $_GET; unset($repDef["get_action"]); foreach ($repDef as $key => $value){ if(get_magic_quotes_gpc()) $value = stripslashes($value); if(strpos($key, "DRIVER_OPTION_")!== false && strpos($key, "DRIVER_OPTION_")==0){ $options[substr($key, strlen("DRIVER_OPTION_"))] = $value; unset($repDef[$key]); }else{ $repDef[$key] = $value; } } if(count($options)){ $repDef["DRIVER_OPTIONS"] = $options; } // NOW SAVE THIS REPOSITORY! $newRep = ConfService::createRepositoryFromArray(0, $repDef); $res = ConfService::addRepository($newRep); AJXP_XMLWriter::header(); if($res == -1){ AJXP_XMLWriter::sendMessage(null, "The conf directory is not writeable"); }else{ AJXP_XMLWriter::sendMessage("Successfully created repository", null); } AJXP_XMLWriter::close(); exit(1); break; case "repository_list" : $repList = ConfService::getRootDirsList(); AJXP_XMLWriter::header("repositories"); foreach ($repList as $index => $value){ $nested = array(); print(" $option){ if(!is_array($option)){ print(" $name=\"$option\" "); }else if(is_array($option)){ $nested[] = $option; } } if(count($nested)){ print(">"); foreach ($nested as $option){ foreach ($option as $key => $optValue){ if(strpos(strtolower($key), "auth") !== false) continue; print(""); } } print(""); }else{ print("/>"); } } AJXP_XMLWriter::close("repositories"); exit(1); break; case "delete_repository" : $repLabel = $_GET["repo_label"]; if(get_magic_quotes_gpc()) $repLabel = stripslashes($repLabel); $res = ConfService::deleteRepository($repLabel); AJXP_XMLWriter::header(); if($res == -1){ AJXP_XMLWriter::sendMessage(null, "The conf directory is not writeable"); }else{ AJXP_XMLWriter::sendMessage("Successfully deleted repository", null); } AJXP_XMLWriter::close(); exit(1); break; case "list_logs" : AJXP_XMLWriter::header("log_files"); AJXP_Logger::xmlListLogFiles(); AJXP_XMLWriter::close("log_files"); exit(1); break; case "read_log" : $logDate = (isSet($_GET["date"])?$_GET["date"]:date('m-d-y')); AJXP_XMLWriter::header("logs"); AJXP_Logger::xmlLogs($logDate); AJXP_XMLWriter::close("logs"); exit(1); break; case "install_log" : $log = array(); $log["PHP Version"] = phpversion(); $log["AJXP Version"] = AJXP_VERSION; $log["Server OS"] = PHP_OS; require_once("server/classes/class.SystemTextEncoding.php"); $log["Server detected encoding"] = SystemTextEncoding::getEncoding(); $log["'server' folder writeable"] = is_writable(INSTALL_PATH."/server"); $log["'logs' folder writeable"] = is_writable(INSTALL_PATH."/server/logs"); $log["'conf' folder writeable"] = is_writable(INSTALL_PATH."/server/conf"); $log["Users enabled"] = ENABLE_USERS; $log["Guest enabled"] = ALLOW_GUEST_BROWSING; $log["Gzip configuration"] = GZIP_DOWNLOAD; $log["Magic Quotes Gpc"] = get_magic_quotes_gpc(); $log["Client"] = $_SERVER['HTTP_USER_AGENT']; foreach ($log as $id => $value){ print "
    $id : $value
    "; } exit(1); break; } include(CLIENT_RESOURCES_FOLDER."/html/admin.html"); include(ConfService::getConf("BOTTOM_PAGE")); session_write_close(); ?>AjaXplorer/AjaXplorer/plugins/0000777000000000000000000000000011300346027017540 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.mysql/0000777000000000000000000000000011300346024021643 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.mysql/mysqlActions.xml0000766000000000000000000003542211122202524025060 0ustar adminadministrators 0){ path = window.actionArguments[0]; }else{ userSelection = ajaxplorer.getFilesList().getUserSelection(); if(userSelection && userSelection.isUnique() && (userSelection.hasDir() || userSelection.hasMime(["zip"]))){ path = userSelection.getUniqueFileName(); } } if(path){ ajaxplorer.getFoldersTree().goToDeepPath(path); ajaxplorer.filesList.loadXmlList(path); ajaxplorer.getActionBar().updateLocationBar(path); } ]]>
    Field Name Type Size or Set NULL Default Other Flags PK IDX UNIQ
    Step 1: Choose a number of fields
    Name of the table :
    Number of fields :
    ]]>
    ]]> ]]> ]]>
    #{current_folder}
    #{folders_string} : #{filelist_folders_count}
    #{files_string} : #{filelist_files_count}
    #{totalsize_string} #{filelist_totalsize}
    ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.mysql/mysql_icon.png0000766000000000000000000000665411122202524024540 0ustar adminadministratorsPNG  IHDRa pHYs.#.#x?v OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATxTKoUse AjaXplorer/AjaXplorer/plugins/ajxp.mysql/class.mysqlDriver.php0000766000000000000000000004573211122202524026013 0ustar adminadministratorscreateDbLink(); $this->closeDbLink($link); } function switchAction($action, $httpVars, $fileVars){ if(!isSet($this->actions[$action])) return; $xmlBuffer = ""; foreach($httpVars as $getName=>$getValue){ $$getName = Utils::securePath($getValue); } $selection = new UserSelection(); $selection->initFromHttpVars($httpVars); if(isSet($dir) && $action != "upload") { $safeDir = $dir; $dir = SystemTextEncoding::fromUTF8($dir); } if(isSet($dest)) { $dest = SystemTextEncoding::fromUTF8($dest); } $mess = ConfService::getMessages(); switch($action) { //------------------------------------ // ONLINE EDIT //------------------------------------ case "edit_record"; $isNew = false; if(isSet($record_is_new) && $record_is_new == "true") $isNew = true; $tableName = $_POST["table_name"]; $pkName = $_POST["pk_name"]; $query = ""; $arrValues = array(); foreach ($_POST as $key=>$value){ if(substr($key, 0, strlen("ajxp_mysql_")) == "ajxp_mysql_"){ $newKey = substr($key, strlen("ajxp_mysql_")); $arrValues[$newKey] = $value; } } if($isNew){ $string = ""; $index = 0; foreach ($arrValues as $k=>$v){ // CHECK IF AUTO KEY!!! $string .= "'".addslashes(SystemTextEncoding::fromUTF8($v))."'"; if($index < count($arrValues)-1) $string.=","; $index++; } $query = "INSERT INTO $tableName VALUES ($string)"; }else{ $string = ""; $index = 0; foreach ($arrValues as $k=>$v){ if($k == $pkName){ $pkValue = $v; }else{ $string .= $k."='".addslashes(SystemTextEncoding::fromUTF8($v))."'"; if($indexcreateDbLink(); $res = $this->execQuery($query); $this->closeDbLink($link); if(is_a($res, "AJXP_Exception")){ $errorMessage = $res->messageId; }else{ $logMessage = $query; $reload_file_list = true; } break; //------------------------------------ // CHANGE COLUMNS OR CREATE TABLE //------------------------------------ case "edit_table": $link = $this->createDbLink(); if(isSet($httpVars["current_table"])){ if(isSet($httpVars["delete_column"])){ $query = "ALTER TABLE ".$httpVars["current_table"]." DROP COLUMN ".$httpVars["delete_column"]; $res = $this->execQuery($query); if(is_a($res, "AJXP_Exception")){ $errorMessage = $res->messageId; }else{ $logMessage = $query; $reload_file_list = true; } $this->closeDbLink($link); break; } if(isSet($httpVars["add_column"])){ $defString = $this->makeColumnDef($httpVars, "add_field_"); $query = "ALTER TABLE ".$httpVars["current_table"]." ADD COLUMN ($defString)"; if(isSet($httpVars["add_field_pk"]) && $httpVars["add_field_pk"]=="1"){ $query.= ", ADD PRIMARY KEY (".$httpVars["add_field_name"].")"; } if(isSet($httpVars["add_field_index"]) && $httpVars["add_field_index"]=="1"){ $query.= ", ADD INDEX (".$httpVars["add_field_name"].")"; } if(isSet($httpVars["add_field_uniq"]) && $httpVars["add_field_uniq"]=="1"){ $query.= ", ADD UNIQUE (".$httpVars["add_field_name"].")"; } $res = $this->execQuery($query); if(is_a($res, "AJXP_Exception")){ $errorMessage = $res->messageId; }else{ $logMessage = $query; $reload_file_list = true; } $this->closeDbLink($link); break; } } $fields = array("origname","name", "default", "null", "size", "type", "flags", "pk", "index", "uniq"); $rows = array(); foreach ($httpVars as $k=>$val){ $split = split("_", $k); if(count($split) == 3 && $split[0]=="field" && is_numeric($split[2]) && in_array($split[1], $fields)){ if(!isSet($rows[intval($split[2])])) $rows[intval($split[2])] = array(); $rows[intval($split[2])][$split[1]] = $val; } } if(isSet($current_table)){ $qMessage = ''; foreach ($rows as $row){ $sizeString = ($row["size"]!=""?"(".$row["size"].")":""); $defString = ($row["default"]!=""?" DEFAULT ".$row["default"]."":""); $query = "ALTER TABLE $current_table CHANGE ".$row["origname"]." ".$row["name"]." ".$row["type"].$sizeString.$defString." ".$row["null"]; $res = $this->execQuery(trim($query)); if(is_a($res, "AJXP_Exception")){ $errorMessage = $res->messageId; $this->closeDbLink($link); break; }else{ $qMessage .= $query; $reload_file_list = true; } } $logMessage = $qMessage; }else if(isSet($new_table)){ $fieldsDef = ""; $pks = array(); $indexes = array(); $uniqs = array(); foreach ($rows as $index=>$row){ $fieldsDef .= $this->makeColumnDef($row); // Analyse keys if($row["pk"] == "1")$pks[] = $row["name"]; if($row["index"]=="1") $indexes[] = $row["name"]; if($row["uniq"]=="1") $uniqs[] = $row["name"]; if($index < count($rows)-1){ $fieldsDef.=","; } } if(count($pks)){ $fieldsDef.= ",PRIMARY KEY (".join(",", $pks).")"; } if(count($indexes)){ $fieldsDef.=",INDEX (".join(",", $indexes).")"; } if(count($uniqs)){ $fieldsDef.=",UNIQUE (".join(",", $uniqs).")"; } $query = "CREATE TABLE $new_table ($fieldsDef)"; $res = $this->execQuery((trim($query))); if(is_a($res, "AJXP_Exception")){ $errorMessage = $res->messageId; }else{ $logMessage = $query; $reload_file_list = true; $reload_current_node = true; } } $this->closeDbLink($link); break; //------------------------------------ // SUPPRIMER / DELETE //------------------------------------ case "delete_table": case "delete_record": $dir = basename($dir); $link = $this->createDbLink(); if(trim($dir) == ""){ // ROOT NODE => DROP TABLES $tables = $selection->getFiles(); $query = "DROP TABLE"; foreach ($tables as $index => $tableName){ $tables[$index] = basename($tableName); } $query.= " ".join(",", $tables); $res = $this->execQuery($query); $reload_current_node = true; }else{ // TABLE NODE => DELETE RECORDS $tableName = $dir; $pks = $selection->getFiles(); foreach ($pks as $key => $pkString){ $parts = split("\.", $pkString); array_pop($parts); // remove .pk extension array_shift($parts); // remove record prefix foreach ($parts as $index => $pkPart){ $parts[$index] = str_replace("__", "='", $pkPart)."'"; } $pks[$key] = "(".implode(" AND ", $parts).")"; } $query = "DELETE FROM $tableName WHERE ". implode(" OR ", $pks); $res = $this->execQuery($query); } AJXP_Exception::errorToXml($res); if(is_a($res, "AJXP_Exception")){ $errorMessage = $res->messageId; }else{ $logMessage = $query; $reload_file_list = true; } $this->closeDbLink($link); break; //------------------------------------ // RENOMMER / RENAME //------------------------------------ case "set_query": $query = $httpVars["query"]; $_SESSION["LAST_SQL_QUERY"] = $query; print(""); break; //------------------------------------ // XML LISTING //------------------------------------ case "ls": if(!isSet($dir) || $dir == "/") $dir = ""; $searchMode = $fileListMode = $completeMode = false; if(isSet($mode)){ if($mode == "search") $searchMode = true; else if($mode == "file_list") $fileListMode = true; else if($mode == "complete") $completeMode = true; } $link = $this->createDbLink(); AJXP_Exception::errorToXml($link); if($dir == ""){ AJXP_XMLWriter::header(); $tables = $this->listTables(); print ''; $icon = ($mode == "file_list"?"table_empty.png":CLIENT_RESOURCES_FOLDER."/images/crystal/mimes/16/table_empty_tree.png"); foreach ($tables as $tableName){ $size = $this->getSize($tableName); $count = $this->getCount($tableName); print ""; } print ""; AJXP_XMLWriter::close(); }else{ $tableName = basename($dir); if(isSet($page))$currentPage = $page; else $currentPage = 1; $query = "SELECT * FROM $tableName"; $searchQuery = false; if($tableName == "ajxpmysqldriver_searchresults"){ if(isSet($_SESSION["LAST_SQL_QUERY"])){ $query = $_SESSION["LAST_SQL_QUERY"]; $matches = array(); if(preg_match("/SELECT [\S, ]* FROM (\S*).*/i", $query, $matches)!==false){ $tableName = $matches[1]; $searchQuery = true; }else{ break; } }else{ break; } } $result = $this->showRecords($query, $tableName, $currentPage); if($searchQuery && is_a($result, "AJXP_Exception")){ unset($_SESSION["LAST_SQL_QUERY"]); // Do not store wrong query! } AJXP_Exception::errorToXml($result); AJXP_XMLWriter::header(); $blobCols = array(); print ''; foreach ($result["COLUMNS"] as $col){ print "cleanFlagString($col["FLAGS"])."\" field_pk=\"".(eregi("primary", $col["FLAGS"])?"1":"0")."\" field_null=\"".(eregi("not_null", $col["FLAGS"])?"NOT_NULL":"NULL")."\" sortType=\"".$this->sqlTypeToSortType($col["TYPE"])."\" field_default=\"".$col["DEFAULT"]."\"/>"; if(stristr($col["TYPE"],"blob")!==false && ($col["FLAGS"]!="" && stristr($col["FLAGS"], "binary"))){ $blobCols[]=$col["NAME"]; } } print ''; print ''; foreach ($result["ROWS"] as $row){ print '$value){ if(in_array($key, $blobCols)){ $sizeStr = "-NULL"; if(strlen($value)) $sizeStr = "-".Utils::roundSize(strlen($sizeStr)); print "$key=\"BLOB$sizeStr\" "; }else{ $value = str_replace("\"", "", $value); $value = Utils::xmlEntities($value); print $key.'="'.SystemTextEncoding::toUTF8($value).'" '; if($result["HAS_PK"]>0){ if(in_array($key, $result["PK_FIELDS"])){ $pkString .= $key."__".$value."."; } } } } if($result["HAS_PK"] > 0){ print 'filename="record.'.$pkString.'pk" '; }else{ print 'filename="record.no_pk" '; } print 'is_file="1" />'; } AJXP_XMLWriter::close(); } $this->closeDbLink($link); exit(1); break; } if(isset($logMessage) || isset($errorMessage)) { $xmlBuffer .= AJXP_XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null), false); } if(isset($requireAuth)) { $xmlBuffer .= AJXP_XMLWriter::requireAuth(false); } if(isset($reload_current_node) && $reload_current_node == "true") { $xmlBuffer .= AJXP_XMLWriter::reloadCurrentNode(false); } if(isset($reload_dest_node) && $reload_dest_node != "") { $xmlBuffer .= AJXP_XMLWriter::reloadNode($reload_dest_node, false); } if(isset($reload_file_list)) { $xmlBuffer .= AJXP_XMLWriter::reloadFileList($reload_file_list, false); } return $xmlBuffer; } function createDbLink(){ $link = FALSE; //Connects to the MySQL Database. $repo = ConfService::getRepository(); $user = $repo->getOption("DB_USER"); $pass = $repo->getOption("DB_PASS"); $host = $repo->getOption("DB_HOST"); $dbname = $repo->getOption("DB_NAME"); $link = @mysql_connect($host, $user, $pass); if(!$link) { $ajxpExp = new AJXP_Exception("Cannot connect to server!"); AJXP_Exception::errorToXml($ajxpExp); } if(!@mysql_select_db($dbname, $link)){ $ajxpExp = new AJXP_Exception("Cannot find database!"); AJXP_Exception::errorToXml($ajxpExp); } return $link; } function closeDbLink($link){ if(!mysql_close($link)){ return new AJXP_Exception("Cannot close connection!"); } } function getSize($tablename){ $repo = ConfService::getRepository(); $dbname = $repo->getOption("DB_NAME"); $like=""; $total=""; $t=0; if($tablename !=""){ $like=" like '$tablename'"; } $sql= "SHOW TABLE STATUS FROM $dbname $like"; $result=$this->execQuery($sql); if($result){ while($rec = mysql_fetch_array($result)){ $t+=($rec['Data_length'] + $rec['Index_length']); } $total = Utils::roundSize($t); }else{ $total="Unknown"; } return($total); } function getCount($tableName){ $sql = "SELECT count(*) FROM $tableName"; $result = $this->execQuery($sql); $t = 0; if($result){ while($res = mysql_fetch_array($result)){ $t+=$res[0]; } } return $t; } function getColumnData($tableName, $columnName){ $sql = "SHOW COLUMNS FROM $tableName LIKE '$columnName'"; $res = $this->execQuery($sql); if($res){ return mysql_fetch_array($res); // ["Field", "Type", "Null", "Key", "Default", "Extra"] => Type is like "enum('a', 'b', 'c')" } } function makeColumnDef($row, $prefix="", $suffix=""){ $defString = ""; if(isSet($row[$prefix."default".$suffix]) && trim($row[$prefix."default".$suffix]) != ""){ $defString = " DEFAULT ".$row[$prefix."default".$suffix]; } $sizeString = ($row[$prefix."size".$suffix]!=""?"(".$row[$prefix."size".$suffix].")":""); $fieldsDef = $row[$prefix."name".$suffix]." ".$row[$prefix."type".$suffix].$sizeString.$defString." ".$row[$prefix."null".$suffix]." ".$row[$prefix."flags".$suffix]; return trim($fieldsDef); } function cleanFlagString($flagString){ $arr = split(" ", $flagString); $newFlags = array(); foreach ($arr as $flag){ if($flag == "primary_key" || $flag == "null" || $flag == "not_null"){ continue; } $newFlags[] = $flag; } return join(" ", $newFlags); } function sqlTypeToSortType($fieldType){ switch ($fieldType){ case "int": return "Number"; case "string": case "datetime": case "timestamp": return "String"; case "blob": return "NumberKo"; default: return "String"; } } function listTables(){ $repo = ConfService::getRepository(); $result = mysql_list_tables($repo->getOption("DB_NAME")); $numtab = mysql_num_rows ($result); $allTables = array(); for ($i =0; $i < $numtab; $i++) { $table = trim(mysql_tablename($result, $i)); $allTables[] = $table; } return $allTables; } function showRecords($query, $tablename, $currentPage=1, $rpp=50, $searchval='' ){ $repo = ConfService::getRepository(); $dbname=$repo->getOption("DB_NAME"); $result=$this->execQuery($query); $columns = array(); $rows = array(); if(is_a($result, "AJXP_Exception")) return $result; $num_rows = mysql_num_rows($result); $pg=$currentPage-1; if(isset($_POST['first'])){ $pg=0; }else if(isset($_POST['back'])){ $pg=$pg-1; }else if(isset($_POST['next'])){ $pg++; }else if(isset($_POST['last'])){ $pgs = $num_rows/$rpp; $pg=ceil($pgs)-1; } if($pg < 0 ){ $pg=0; } if($pg > $num_rows/$rpp){ $pg=ceil($num_rows/$rpp)-1; } $totalPages = ceil($num_rows/$rpp); $beg = $pg * $rpp; $flds = mysql_num_fields($result); $fields = @mysql_list_fields( $dbname, $tablename); if(!$fields){ return new AJXP_Exception("Non matching fields for table '$tablename'"); } $z=0; $x=0; $pkfield=array(); // MAKE COLUMNS HEADER for ($i = 0; $i < $flds; $i++) { $c=$i+1; $title=mysql_field_name($fields, $i); $type=mysql_field_type($fields, $i); $size=mysql_field_len($fields, $i); $flagstring = mysql_field_flags ($fields, $i); $colData = $this->getColumnData($tablename, $title); $colDataType = $colData["Type"]; if(preg_match("/(.*)\((.*)\)/", $colDataType, $matches)){ $type = $matches[1]; $size = $matches[2]; } $columns[] = array("NAME" => $title, "TYPE"=>$type, "LENGTH"=>$size, "FLAGS"=>$flagstring, "DEFAULT"=>$colData["Default"]); //Find the primary key $flagstring = mysql_field_flags ($result, $i); if(eregi("primary",$flagstring )){ $pk[$z] = $i; $pkfield[$z]= mysql_field_name($fields, $i); $z++; } } $v=$flds+1; if($z > 0){ $cpk=count($pk); }else{ $cpk=0; } // MAKE ROWS RESULT for ($s=$beg; $s < $beg + $rpp; $s++){ if($s < $num_rows){ if (!mysql_data_seek ($result, $s)) { continue; } $row=mysql_fetch_array($result); if(!isset($pk)){ $pk=' '; $pkfield= array(); } $values = array(); for($col = 0; $col < $flds; $col ++) { $values[mysql_field_name($fields, $col)] = stripslashes($row[$col]); } $rows[] = $values; } } return array("COLUMNS" => $columns, "ROWS" => $rows, "HAS_PK"=>$cpk, "TOTAL_PAGES"=>$totalPages, "PK_FIELDS"=>$pkfield); } function execQuery($sql =''){ $output=''; if($sql !=''){ $result= @mysql_query( $sql ); if($result){ AJXP_Logger::logAction("exec", array($sql)); return $result; }else{ return new AJXP_Exception($sql.":".mysql_error()); } }else{ return new AJXP_Exception('Empty Query'); } } } ?> AjaXplorer/AjaXplorer/plugins/ajxp.ssh/0000777000000000000000000000000011300346025021274 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.ssh/sshActions.xml0000766000000000000000000011347511122202524024145 0ustar adminadministrators 0){ path = window.actionArguments[0]; }else{ userSelection = ajaxplorer.getFilesList().getUserSelection(); if(userSelection && userSelection.isUnique() && (userSelection.hasDir() || userSelection.hasMime(["zip"]))){ path = userSelection.getUniqueFileName(); } } if(path){ ajaxplorer.getFoldersTree().goToDeepPath(path); ajaxplorer.filesList.loadXmlList(path); ajaxplorer.getActionBar().updateLocationBar(path); } ]]> = 8 && document.location.href.substring(0,5)!='https') { modal.setCloseAction(function(){ $('closeFlashUploadBox').disabled=false; }); modal.showDialogForm('Upload', 'flash_upload_form', null, function(){ hideLightBox(); return false; }, null, true, true); } else { $('hidden_frames').innerHTML = ''; var onLoadFunction = function(oForm){ this.multi_selector = new MultiSelector(oForm, oForm.getElementsBySelector('div.uploadFilesList')[0], '6' ); this.multi_selector.addElement(oForm.getElementsBySelector('.dialogFocus')[0]); var rep = document.createElement('input'); rep.setAttribute('type', 'hidden'); rep.setAttribute('name', 'dir'); rep.setAttribute('value', ajaxplorer.getFilesList().getCurrentRep()); oForm.appendChild(rep); }.bind(ajaxplorer.actionBar); modal.setCloseAction(function(){ ajaxplorer.filesList.reload(); }); modal.showDialogForm('Upload', 'originalUploadForm', onLoadFunction, function(){ajaxplorer.actionBar.multi_selector.submitMainForm();return false;}); } ]]>
    ]]>
    AJXP_MESSAGE[173]
    ]]>
    AJXP_MESSAGE[174]
    ]]>
    AJXP_MESSAGE[119]

    ]]>
    ]]>
    Actual Size(100%)Fit To Screen
    % s
    ]]>
    AJXP_MESSAGE[6]  AJXP_MESSAGE[42]
    ]]>
    AJXP_MESSAGE[175]
    ]]>
    ]]> AjaXplorer MP3 Player
    AjaXplorer Player
    '+MessageHash[141]+': #{current_folder}
    '); var mp3Items = new Array(); $A(ajaxplorer.getFilesList().getItems()).each(function(rowItem){ var filename = rowItem.getAttribute('filename'); if(getFileExtension(filename) == 'mp3') mp3Items.push(filename); }); var mp3_url = ''; mp3Items.each(function(url){ mp3_url += 'content.php?action=mp3_proxy%26file='+url; if(url != mp3Items.last()) mp3_url += '|'; }); newWin = window.open('', 'mp3_multi_player', 'width=260,height=30,directories=no,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no'); newWin.document.write(template.evaluate({mp3_url:mp3_url, current_folder:ajaxplorer.getFilesList().getCurrentRep()})); newWin.document.close(); ]]>
    #{current_folder} #{folders_string} : #{filelist_folders_count}
    #{files_string} : #{filelist_files_count}
    #{totalsize_string} #{filelist_totalsize} ]]>
    #{name_string} : #{basename}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{dim_string} : #{image_width}px X #{image_height}px
    #{size_string} : #{filesize}
    #{type_string} : #{image_type}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.ssh/testSSHOp.php0000766000000000000000000000064111122202524023640 0ustar adminadministratorsTesting connection"; echo $SSHOp->checkConnection()."
    "; $arr = $SSHOp->listFilesIn('/www'); print_r($arr[0]); // Create a file on the server $SSHOp->setRemoteContent('/home/ajaxplorer/www/test.html', 'Hello'); ?> AjaXplorer/AjaXplorer/plugins/ajxp.ssh/install.txt0000766000000000000000000000456011122202524023506 0ustar adminadministratorsQuick and dirty install step: You must be able to set a script as executable on the server for this plugin to work. While you're reading this file, I guess you've correctly extracted the plugin. Now, in a server shell, issue a "chmod +x /path/to/showPass.php" as the webserver user, to allow this script to be executed by the ssh command. Similarly, the host you are trying to connect to must be in your known host, as there is no way for the script to ask you if you want to add it. If it doesn't work with the script make sure the command: "ssh bob@myserver.com ls" returns the listing of bob's home directory on myserver.com If it does, issue the following command, as root: # su -l apache_user $ ssh bob@myserver.com ls Should list the files in the default directory of bob on myserver.com If you wonder what showPass does, it simply print out the environement variable SSH_PASSWORD the plugin set when using SSH. That way, the password (when decyphered) is never written to disk, as environment of script execution is hard to read (but not impossible). Concerning security, any user with read access to /proc/PID_SSH_PROCESS/environ could be able to read the password (with PID_SSH_PROCESS being the process ID of the SSH process being run). Fortunately, only the calling user is allowed (usually Apache's default user www-data) to read such environment. Moreover, even if another script hack this server to poll for such files (randomly), the SSH process doesn't live for too long (and when it closes, there is no trace of password anywhere). It's more than difficult. (BTW, theorically you can defeat any security system by dumping /dev/memory at the right time) If it's not safe enough for you, then you could hack the SSHOperation script to write the password(cyphered with the script process PID, salt, and remote user name) to a shared memory area. Then hack the showPass.php script to read from the same shared memory, and decypher with parent pid (so any other process wouldn't be able to get clear text because it can't infer the parent PID and the chose salt). The showPass's argv[1] is the user name. Use posix_getppid() to get parent pid. Good luck Currently, the SSH client auto configure itself on first launch. If this doesn't work for you (SSH server on non-unix based system, for example), you can still hack the command that work for your server in SSHOperation script. AjaXplorer/AjaXplorer/plugins/ajxp.ssh/class.sshDriver.php0000766000000000000000000006543411122202524025074 0ustar adminadministratorsgetOption("PATH"); $accountLimit = strpos($repositoryPath, "@"); if ($accountLimit !== false) { $account = substr($repositoryPath, 0, $accountLimit); $repositoryPath = substr($repositoryPath, $accountLimit+1); $repository->setOption("PATH", $repositoryPath); } // TODO Set the password from a per user specific config $account = "ajaxplorer"; $password = "dumbpass"; $this->SSHOperation = new SSHOperations($repositoryPath, $account, $password); parent::AbstractDriver($driverName, $filePath, $repository); } function initRepository(){ $path = $this->repository->getOption("PATH"); // We cache this in the session object so it's only done once global $_SESSION; if (!isset($_SESSION["cwd"])) { $param = $this->SSHOperation->checkConnection(); if (count($param)==0) { return new AJXP_Exception("Cannot connect to remote server. Please check repository configuration and install.txt!"); } $_SESSION["cwd"] = trim($param[0]); $_SESSION["charset"] = trim($param[1]); } // If it's set, then cache the result to avoid multiple connection on the remote server $this->serverCwd = rtrim(trim($_SESSION["cwd"]), '/').'/'; $this->charset = trim($_SESSION["charset"]); } function switchAction($action, $httpVars, $fileVars){ if(!isSet($this->actions[$action])) return; $xmlBuffer = ""; foreach($httpVars as $getName=>$getValue){ $$getName = Utils::securePath($getValue); } $selection = new UserSelection(); $selection->initFromHttpVars($httpVars); if(isSet($dir) && $action != "upload") { $safeDir = $dir; $dir = SystemTextEncoding::fromUTF8($dir); } if(isSet($dest)) $dest = SystemTextEncoding::fromUTF8($dest); $mess = ConfService::getMessages(); $recycleBinOption = $this->repository->getOption("RECYCLE_BIN"); // FILTER ACTION FOR DELETE if($recycleBinOption!="" && $action == "delete" && $dir != "/".$recycleBinOption) { $action = "move"; $dest = "/".$recycleBinOption; $dest_node = "AJAXPLORER_RECYCLE_NODE"; } // FILTER ACTION FOR RESTORE if($recycleBinOption!="" && $action == "restore" && $dir == "/".$recycleBinOption) { $originalRep = RecycleBinManager::getFileOrigin($selection->getUniqueFile()); if($originalRep != "") { $action = "move"; $dest = $originalRep; } } switch($action) { //------------------------------------ // DOWNLOAD, IMAGE & MP3 PROXYS //------------------------------------ case "download"; AJXP_Logger::logAction("Download", array("files"=>$selection)); $zip = false; if($selection->isUnique()){ if(is_dir($this->getPath()."/".$selection->getUniqueFile())) { $zip = true; $dir .= "/".basename($selection->getUniqueFile()); } }else{ $zip = true; } if($zip){ // Make a temp zip and send it as download $this->sendFile($this->SSHOperation->getRemoteContent($this->makeName($selection->getFiles())), "force-download", "archive.zip", false); }else{ $this->sendFile($this->SSHOperation->getRemoteContent($this->makeName($selection->getUniqueFile())), "force-download", $selection->getUniqueFile()); } exit(0); break; case "image_proxy": $this->sendFile($this->SSHOperation->getRemoteContent($this->makeName($file)), "image", $file); exit(0); break; case "mp3_proxy": $this->sendFile($this->SSHOperation->getRemoteContent($this->makeName($file)), "mp3", $file); exit(0); break; //------------------------------------ // ONLINE EDIT //------------------------------------ case "edit"; if(isset($save) && $save==1) { AJXP_Logger::logAction("Online Edition", array("file"=>SystemTextEncoding::fromUTF8($file))); $code=stripslashes($code); $code=str_replace("<","<",$code); $this->SSHOperation->setRemoteContent($this->makeName($file), $code); echo $mess[115]; } else { $this->sendFile($this->SSHOperation->getRemoteContent($this->makeName($file)), "plain", $file); } exit(0); break; //------------------------------------ // COPY / MOVE //------------------------------------ case "copy"; case "move"; if($selection->isEmpty()) { $errorMessage = $mess[113]; break; } $success = $error = array(); if ($action == "move") $this->SSHOperation->moveFile($this->makeName($selection->getFiles()), $this->makeName($dest)); else $this->SSHOperation->copyFile($this->makeName($selection->getFiles()), $this->makeName($dest)); if(count($error)){ $errorMessage = join("\n", $error); } else { $logMessage = join("\n", $success); AJXP_Logger::logAction(($action=="move"?"Move":"Copy"), array("files"=>$selection, "destination"=>$dest)); } $reload_current_node = true; if(isSet($dest_node)) $reload_dest_node = $dest_node; $reload_file_list = true; break; //------------------------------------ // SUPPRIMER / DELETE //------------------------------------ case "delete"; if($selection->isEmpty()) { $errorMessage = $mess[113]; break; } $logMessages = array(); $errorMessage = $this->SSHOperation->deleteFile($this->makeName($selection->getFiles())); if(count($logMessages)) { $logMessage = join("\n", $logMessages); } AJXP_Logger::logAction("Delete", array("files"=>$selection)); $reload_current_node = true; $reload_file_list = true; break; //------------------------------------ // RENOMMER / RENAME //------------------------------------ case "rename"; $filename_new = $dir."/".$filename_new; $error = $this->SSHOperation->moveFile($this->makeName($file), $this->makeName($filename_new)); if($error != null) { $errorMessage = $error; break; } $logMessage= SystemTextEncoding::toUTF8($file)." $mess[41] ".SystemTextEncoding::toUTF8($filename_new); $reload_current_node = true; $reload_file_list = basename($filename_new); AJXP_Logger::logAction("Rename", array("original"=>$file, "new"=>$filename_new)); break; //------------------------------------ // CREER UN REPERTOIRE / CREATE DIR //------------------------------------ case "mkdir"; $messtmp=""; $dirname=Utils::processFileName($dirname); $error = $this->SSHOperation->createRemoteDirectory($this->makeName($dir."/".$dirname)); if(isSet($error)){ $errorMessage = $error; break; } $reload_file_list = $dirname; $messtmp.="$mess[38] ".SystemTextEncoding::toUTF8($dirname)." $mess[39] "; if($dir=="") {$messtmp.="/";} else {$messtmp.= SystemTextEncoding::toUTF8($dir);} $logMessage = $messtmp; $reload_current_node = true; AJXP_Logger::logAction("Create Dir", array("dir"=>$dir."/".$dirname)); break; //------------------------------------ // CREER UN FICHIER / CREATE FILE //------------------------------------ case "mkfile"; $messtmp=""; $filename=Utils::processFileName($filename); $error = $this->SSHOperation->setRemoteContent($this->makeName($dir."/".$filename), ""); if(isSet($error)){ $errorMessage = $error; break; } $messtmp.="$mess[34] ".SystemTextEncoding::toUTF8($filename)." $mess[39] "; if($dir=="") {$messtmp.="/";} else {$messtmp.=SystemTextEncoding::toUTF8($dir);} $logMessage = $messtmp; $reload_file_list = $filename; AJXP_Logger::logAction("Create File", array("file"=>$dir."/".$filename)); break; //------------------------------------ // UPLOAD //------------------------------------ case "upload": $errorMessage="411 Error"; break; /* if($dir!=""){$rep_source="/$dir";} else $rep_source = ""; $destination=SystemTextEncoding::fromUTF8($this->getPath().$rep_source); if(!$this->isWriteable($destination)) { $errorMessage = "$mess[38] ".SystemTextEncoding::toUTF8($dir)." $mess[99]."; break; } $logMessage = ""; $fancyLoader = false; foreach ($fileVars as $boxName => $boxData) { if($boxName != "Filedata" && substr($boxName, 0, 9) != "userfile_") continue; if($boxName == "Filedata") $fancyLoader = true; $err = Utils::parseFileDataErrors($boxData, $fancyLoader); if($err != null) { $errorMessage = $err; break; } $userfile_name = $boxData["name"]; if($fancyLoader) $userfile_name = SystemTextEncoding::fromUTF8($userfile_name); $userfile_name=Utils::processFileName($userfile_name); if(isSet($auto_rename)){ $userfile_name = sshFSDriver::autoRenameForDest($destination, $userfile_name); } if (!move_uploaded_file($boxData["tmp_name"], "$destination/".$userfile_name)) { $errorMessage=($fancyLoader?"411 ":"")."$mess[33] ".$userfile_name; break; } chmod($destination."/".$userfile_name, 0777); $logMessage.="$mess[34] ".SystemTextEncoding::toUTF8($userfile_name)." $mess[35] $dir"; AJXP_Logger::logAction("Upload File", array("file"=>$dir."/".$userfile_name)); } if($fancyLoader) { if(isSet($errorMessage)){ header('HTTP/1.0 '.$errorMessage); die('Error '.$errorMessage); }else{ header('HTTP/1.0 200 OK'); die("200 OK"); } } else { print(""); } exit; */ break; //------------------------------------ // XML LISTING //------------------------------------ case "ls": if(!isSet($dir) || $dir == "/") $dir = ""; $searchMode = $fileListMode = $completeMode = false; if(isSet($mode)){ if($mode == "search") $searchMode = true; else if($mode == "file_list") $fileListMode = true; else if($mode == "complete") $completeMode = true; } $nom_rep = $dir; AJXP_Exception::errorToXml($nom_rep); $result = $this->SSHOperation->listFilesIn($nom_rep); AJXP_XMLWriter::header(); foreach ($result as $file) { $attributes = ""; $fileName = SystemTextEncoding::toUTF8($file["name"]); $icon = Utils::mimetype($fileName, "image", $file["isDir"]==1); if ($searchMode) { if($file["isDir"] == 0) { $attributes = "is_file=\"true\" icon=\"".SystemTextEncoding::toUTF8($icon)."\""; } } else if ($fileListMode) { $atts = array(); $atts[] = "is_file=\"".(1 - $file["isDir"])."\""; $atts[] = "is_image=\"".Utils::is_image($fileName)."\""; $atts[] = "mimestring=\"".Utils::mimetype($fileName, "type", $file["isDir"]==1)."\""; $atts[] = "modiftime=\"".$this->dateModif($file["time"])."\""; $atts[] = "filesize=\"".Utils::roundSize($file["size"])."\""; $atts[] = "bytesize=\"".$file["size"]."\""; $atts[] = "filename=\"".str_replace("&", "&", $dir."/".$fileName)."\""; $atts[] = "icon=\"".($file["isDir"]==1 ? "folder.png" : SystemTextEncoding::toUTF8($icon))."\""; $attributes = join(" ", $atts); } else if ($file["isDir"]==1) { $link = SERVER_ACCESS."?dir=".$dir."/".$fileName; $link = urlencode($link); $folderBaseName = str_replace("&", "&", $fileName); $folderFullName = "$dir/".$folderBaseName; $parentFolderName = $dir; if(!$completeMode){ $icon = CLIENT_RESOURCES_FOLDER."/images/foldericon.png"; $openicon = CLIENT_RESOURCES_FOLDER."/images/openfoldericon.png"; if(eregi("\.zip$",$file["name"])){ $icon = $openicon = CLIENT_RESOURCES_FOLDER."/images/crystal/actions/16/accessories-archiver.png"; } $attributes = "icon=\"$icon\" openicon=\"$openicon\" filename=\"".$folderFullName."\" src=\"$link\""; } } if (strlen($attributes) > 0) { print("SSHOperation->unescapeFileName($file["name"])))."\" $attributes>"); print(""); } } AJXP_XMLWriter::close(); exit(1); break; } if(isset($logMessage) || isset($errorMessage)) { $xmlBuffer .= AJXP_XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null), false); } if(isset($requireAuth)) { $xmlBuffer .= AJXP_XMLWriter::requireAuth(false); } if(isset($reload_current_node) && $reload_current_node == "true") { $xmlBuffer .= AJXP_XMLWriter::reloadCurrentNode(false); } if(isset($reload_dest_node) && $reload_dest_node != "") { $xmlBuffer .= AJXP_XMLWriter::reloadNode($reload_dest_node, false); } if(isset($reload_file_list)) { $xmlBuffer .= AJXP_XMLWriter::reloadFileList($reload_file_list, false); } return $xmlBuffer; } function getPath(){ return $this->repository->getOption("PATH"); } function makeName($param) { if (is_array($param)) { $retArray = array(); foreach($param as $item) { $retArray[] = $this->serverCwd.SystemTextEncoding::fromUTF8(trim($item, './')); } return $retArray; } else { $param = SystemTextEncoding::fromUTF8(trim($param, './')); return $this->serverCwd.$param; } } function zipListing($zipPath, $localPath, &$filteredList){ require_once("server/classes/pclzip.lib.php"); $crtZip = new PclZip($this->getPath()."/".$zipPath); $liste = $crtZip->listContent(); $files = array(); if($localPath[strlen($localPath)-1] != "/") $localPath.="/"; foreach ($liste as $item){ $stored = $item["stored_filename"]; if($stored[0] != "/") $stored = "/".$stored; $pathPos = strpos($stored, $localPath); if($pathPos !== false){ $afterPath = substr($stored, $pathPos+strlen($localPath)); if($afterPath != "" && strpos($afterPath, "/")=== false || strpos($afterPath, "/") == strlen($afterPath)-1){ $item["filename"] = $zipPath.$localPath.$afterPath; if($item["folder"]){ $filteredList[] = $item; }else{ $files[] = $item; } } } } $filteredList = array_merge($filteredList, $files); return $crtZip; } function initName($dir) { $racine = $this->getPath(); $mess = ConfService::getMessages(); if(!isset($dir) || $dir=="" || $dir == "/") { $nom_rep=$racine; } else { $nom_rep="$racine/$dir"; } if(!file_exists($racine)) { return new AJXP_Exception(72); } if(!is_dir($nom_rep)) { return new AJXP_Exception(100); } return $nom_rep; } function sendFile($filePath, $headerType="plain", $fileName, $gzip=true) { $size = strlen($filePath); if($headerType == "plain") { header("Content-type:text/plain"); } else if($headerType == "image") { header("Content-Type: ".Utils::getImageMimeType(basename($fileName))."; name=\"".basename($fileName)."\""); header("Content-Length: ".$size); header('Cache-Control: public'); } else if($headerType == "mp3") { header("Content-Type: audio/mp3; name=\"".basename($fileName)."\""); header("Content-Length: ".$size); } else { header("Content-Type: application/force-download; name=\"".$fileName."\""); header("Content-Transfer-Encoding: binary"); if($gzip) header("Content-Encoding: gzip"); header("Content-Length: ".$size); header("Content-Disposition: attachment; filename=\"".$fileName."\""); header("Expires: 0"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); // For SSL websites there is a bug with IE see article KB 323308 // therefore we must reset the Cache-Control and Pragma Header if (ConfService::getConf("USE_HTTPS")==1 && preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT'])) { header("Cache-Control:"); header("Pragma:"); } if($gzip){ print(gzencode($filePath, 9)); return ; } } print($filePath); } function dateModif($time) { $tmp = mktime(substr($time, 11, 2), substr($time, 14, 2), 0, substr($time, 5, 2), substr($time, 8, 2), substr($time, 0, 4)); return date("d/m/Y H:i",$tmp); } function renameAction($actionName, $httpVars) { $filePath = SystemTextEncoding::fromUTF8($httpVars["file"]); $newFilename = SystemTextEncoding::fromUTF8($httpVars["filename_new"]); return $this->rename($filePath, $newFilename); } function rename($filePath, $filename_new) { $nom_fic=basename($filePath); $mess = ConfService::getMessages(); $filename_new=Utils::processFileName($filename_new); $old=$this->getPath()."/$filePath"; if(!is_writable($old)) { return $mess[34]." ".$nom_fic." ".$mess[99]; } $new=dirname($old)."/".$filename_new; if($filename_new=="") { return "$mess[37]"; } if(file_exists($new)) { return "$filename_new $mess[43]"; } if(!file_exists($old)) { return $mess[100]." $nom_fic"; } rename($old,$new); return null; } function autoRenameForDest($destination, $fileName){ if(!is_file($destination."/".$fileName)) return $fileName; $i = 1; $ext = ""; $name = ""; $split = split("\.", $fileName); if(count($split) > 1){ $ext = ".".$split[count($split)-1]; array_pop($split); $name = join("\.", $split); }else{ $name = $fileName; } while (is_file($destination."/".$name."-$i".$ext)) { $i++; // increment i until finding a non existing file. } return $name."-$i".$ext; } function mkDir($crtDir, $newDirName) { $mess = ConfService::getMessages(); if($newDirName=="") { return "$mess[37]"; } if(file_exists($this->getPath()."/$crtDir/$newDirName")) { return "$mess[40]"; } if(!is_writable($this->getPath()."/$crtDir")) { return $mess[38]." $crtDir ".$mess[99]; } mkdir($this->getPath()."/$crtDir/$newDirName",0775); return null; } function createEmptyFile($crtDir, $newFileName) { $mess = ConfService::getMessages(); if($newFileName=="") { return "$mess[37]"; } if(file_exists($this->getPath()."/$crtDir/$newFileName")) { return "$mess[71]"; } if(!is_writable($this->getPath()."/$crtDir")) { return "$mess[38] $crtDir $mess[99]"; } $fp=fopen($this->getPath()."/$crtDir/$newFileName","w"); if($fp) { if(eregi("\.html$",$newFileName)||eregi("\.htm$",$newFileName)) { fputs($fp,"\n\nNew Document - Created By AjaXplorer\n\n\n\n\n\n\n"); } fclose($fp); return null; } else { return "$mess[102] $crtDir/$newFileName (".$fp.")"; } } function delete($selectedFiles, &$logMessages) { $mess = ConfService::getMessages(); foreach ($selectedFiles as $selectedFile) { if($selectedFile == "" || $selectedFile == DIRECTORY_SEPARATOR) { return $mess[120]; } $fileToDelete=$this->getPath().$selectedFile; if(!file_exists($fileToDelete)) { $logMessages[]=$mess[100]." ".SystemTextEncoding::toUTF8($selectedFile); continue; } $this->deldir($fileToDelete); if(is_dir($fileToDelete)) { $logMessages[]="$mess[38] ".SystemTextEncoding::toUTF8($selectedFile)." $mess[44]."; } else { $logMessages[]="$mess[34] ".SystemTextEncoding::toUTF8($selectedFile)." $mess[44]."; } } return null; } function copyOrMoveFile($destDir, $srcFile, &$error, &$success, $move = false) { $mess = ConfService::getMessages(); $destFile = $this->repository->getOption("PATH").$destDir."/".basename($srcFile); $realSrcFile = $this->repository->getOption("PATH")."/$srcFile"; $recycle = $this->repository->getOption("RECYCLE_BIN"); if(!file_exists($realSrcFile)) { $error[] = $mess[100].$srcFile; return ; } if($realSrcFile==$destFile) { $error[] = $mess[101]; return ; } if(is_dir($realSrcFile)) { $errors = array(); $succFiles = array(); $dirRes = $this->dircopy($realSrcFile, $destFile, $errors, $succFiles); if(count($errors)) { $error[] = $mess[114]; return ; } } else { $res = copy($realSrcFile,$destFile); if($res != 1) { $error[] = $mess[114]; return ; } } if($move) { // Now delete original $this->deldir($realSrcFile); // both file and dir $messagePart = $mess[74]." ".SystemTextEncoding::toUTF8($destDir); if($destDir == "/".$recycle) { RecycleBinManager::fileToRecycle($srcFile); $messagePart = $mess[123]." ".$mess[122]; } if(isset($dirRes)) { $success[] = $mess[117]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$messagePart." (".SystemTextEncoding::toUTF8($dirRes)." ".$mess[116].") "; } else { $success[] = $mess[34]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$messagePart; } } else { if($destDir == "/".$this->repository->getOption("RECYCLE_BIN")) { RecycleBinManager::fileToRecycle($srcFile); } if(isSet($dirRes)) { $success[] = $mess[117]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$mess[73]." ".SystemTextEncoding::toUTF8($destDir)." (".SystemTextEncoding::toUTF8($dirRes)." ".$mess[116].")"; } else { $success[] = $mess[34]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$mess[73]." ".SystemTextEncoding::toUTF8($destDir); } } } // A function to copy files from one directory to another one, including subdirectories and // nonexisting or newer files. Function returns number of files copied. // This function is PHP implementation of Windows xcopy A:\dir1\* B:\dir2 /D /E /F /H /R /Y // Syntaxis: [$number =] dircopy($sourcedirectory, $destinationdirectory [, $verbose]); // Example: $num = dircopy('A:\dir1', 'B:\dir2', 1); function dircopy($srcdir, $dstdir, &$errors, &$success, $verbose = false) { $num = 0; if(!is_dir($dstdir)) mkdir($dstdir); if($curdir = opendir($srcdir)) { while($file = readdir($curdir)) { if($file != '.' && $file != '..') { $srcfile = $srcdir . DIRECTORY_SEPARATOR . $file; $dstfile = $dstdir . DIRECTORY_SEPARATOR . $file; if(is_file($srcfile)) { if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1; if($ow > 0) { if($verbose) echo "Copying '$srcfile' to '$dstfile'..."; if(copy($srcfile, $dstfile)) { touch($dstfile, filemtime($srcfile)); $num++; if($verbose) echo "OK\n"; $success[] = $srcfile; } else { $errors[] = $srcfile; } } } else if(is_dir($srcfile)) { $num += $this->dircopy($srcfile, $dstfile, $errors, $success, $verbose); } } } closedir($curdir); } return $num; } function simpleCopy($origFile, $destFile) { return copy($origFile, $destFile); } function isWriteable($dir) { return is_writable($dir); } function deldir($location) { if(is_dir($location)) { $all=opendir($location); while ($file=readdir($all)) { if (is_dir("$location/$file") && $file !=".." && $file!=".") { $this->deldir("$location/$file"); if(file_exists("$location/$file")){rmdir("$location/$file"); } unset($file); } elseif (!is_dir("$location/$file")) { if(file_exists("$location/$file")){unlink("$location/$file"); } unset($file); } } closedir($all); rmdir($location); } else { if(file_exists("$location")) {unlink("$location");} } if(basename(dirname($location)) == $this->repository->getOption("RECYCLE_BIN")) { // DELETING FROM RECYCLE RecycleBinManager::deleteFromRecycle($location); } } /** * @return zipfile */ function makeZip ($src, $dest, $basedir) { set_time_limit(60); require_once(SERVER_RESOURCES_FOLDER."/pclzip.lib.php"); $filePaths = array(); $totalSize = 0; foreach ($src as $item){ $filePaths[] = $this->getPath().$item; } $archive = new PclZip($dest); $vList = $archive->create($filePaths, PCLZIP_OPT_REMOVE_PATH, $this->getPath().$basedir, PCLZIP_OPT_NO_COMPRESSION); if($vList == 0) return false; } /** * @param $selection UserSelection */ function convertSelectionToTmpFiles($tmpDir, $selection){ $zipPath = $selection->getZipPath(); $localDir = $selection->getZipLocalPath(); $files = $selection->getFiles(); foreach ($files as $key => $item){// Remove path $item = substr($item, strlen($zipPath)); if($item[0] == "/") $item = substr($item, 1); $files[$key] = $item; } require_once("server/classes/pclzip.lib.php"); $zip = new PclZip($this->getPath().$zipPath); $err = $zip->extract(PCLZIP_OPT_BY_NAME, $files, PCLZIP_OPT_PATH, $this->getPath()."/".$tmpDir); foreach ($files as $key => $item){// Remove path $files[$key] = $tmpDir."/".$item; } $selection->setFiles($files); } } ?> AjaXplorer/AjaXplorer/plugins/ajxp.ssh/class.SSHOperations.php0000766000000000000000000003337411122202524025622 0ustar adminadministratorslsCommand = "ls -l -n -F --quoting-style=escape --time-style=long-iso "; $this->catCommand = "cat "; $this->zipCommand = "zip -9 -q -r -j - "; $this->setFileCommand = "cat > "; $this->getServerCharsetCommand = "set | grep 'LANG=' | sed -e 's/LANG=//'"; $this->copyCommand = "cp -R "; $this->moveCommand = "mv "; $this->makeDirCommand = "mkdir -p "; $this->deleteCommand = "rm -rf "; $this->server = $server; $this->account = $account; $this->password = $password; $this->configFile = $configFile; } // Helpers /** Helper function to fetch the content of a stream */ function streamGetContents($stream, $maxLength = -1, $offset = 0) { if (function_exists(stream_get_contents)) return stream_get_contents($stream, $maxLength, $offset); // Else, first get all the bytes up to the given offset @fread($stream, $offset); // Then get the content if ($maxLength == -1) { $buffer = ""; while (!feof($stream)) $buffer.= fread($stream, 1); return $buffer; } else return fread($stream, $maxLength); } /** This function split the given text in fields with space as a separator It is different from the basic split function because it only accumulate non empty field */ function smartSplit($text) { $retArray = array(); $lastPos = 0; for($i = 0; $i < strlen($text); $i++) { if ($text[$i] == ' ') { $retArray[] = substr($text, $lastPos, $i - $lastPos); while ($i < strlen($text) && $text[$i] == ' ') $i++; $lastPos = $i; } } $retArray[] = substr($text, $lastPos, $i - $lastPos); return $retArray; } /** Parse a file name to create an unescaped UTF-8 version of that name (to the browser file list name) @param $name The file name to parse @return A string containing the unescaped UTF-8 version of the file name */ function unescapeFileName($name) { // In theory should retrieve the charset from the server fs with such command: set | grep "LANG=" // In practice, most Unix are UTF8 and so is the browser output, so if I have time I'll add this conversion later on. return str_replace('\\', '', $name); } /** This function parse the output of a remote ls command and returns an array of files on the remote size with all their attributes (isDir, type, access, uid, gid, size, time, name) @return isDir Set to 1 if the item is a directory or behave like a directory (like a symbolic link to a directory) @return type Any of 'file', 'dir', 'link', 'block', 'char', 'fifo', 'socket' @return access Any of 'read', 'read-write', 'write' @return uid, gid The user UID/GID (this number is specific to the target system) @return size The item's size in bytes @return time The item's time as ISO date : YYYY-MM-DD HH:MM @return name The item's name in the server charset, escaped so can be reused as-is */ function parseLs($content) { // Check the first line $lines = split("\n", $content); if (stristr($lines[0], "total")) array_shift($lines); // Ok, split each line with a file $retArray = array(); $typeArray = array('-'=>'file', 'd'=>'dir', 'l'=>'link', 'b'=>'block', 'c'=>'char', 'p'=>'fifo', 's'=>'socket'); foreach($lines as $line) { $columns = $this->smartSplit($line); if (count($columns) < 7) break; // The first column is the rights $right = $columns[0]; // Should parse rights here (for now, we simply extract the type) $isDir = $right[0]=='d'; $isLink = $right[0]=='l'; $isExe = $right[3]=='x' || $right[6]=='x' || $right[9]=='x'; $isRead = $right[1]=='r' || $right[4]=='r' || $right[7]=='r'; $isWrite = $right[2]=='w' || $right[5]=='w' || $right[8]=='w'; $isFifo = $right[0]=='p'; $name = implode(' ', array_slice($columns, 7)); // If the link is on a directory, let's fix it if ($isLink && substr($name, -1)=='/') $isDir = true; // Remove the last char when it's been appended if ($isDir || $isExe || $isFifo) $name = substr($name, 0, -1); if ($isLink) { // Remove all text after -> $name = substr($name, 0, strpos($name, '->')); } // Show the other colimns $retArray[] = array("isDir" => $isDir ? 1 : 0, "type"=> $typeArray[$right[0]], "access" => $isRead ? ($isWrite ? 'read-write' : 'read') : ($isWrite ? 'write' : ''), "uid"=>$columns[2], "gid"=>$columns[3], "size"=>$columns[4], "time"=>$columns[5]." ".$columns[6], "name"=>trim($name)); } return $retArray; } /** Execute the given command, expecting only to read input from the command @param $server The server to contact @param $account The account to use while connecting on the remote server @param $password The account password to use while connecting on the remote server @param $command The command to execute (must be full command and valid on the remote side) @return the command output text */ function executeRemoteCommand($server, $account, $password, $command) { $fileName = __FILE__; $fileName = substr($fileName, 0, strrpos($fileName, "/")); $finalCommand = "export DISPLAY=xxx && export SSH_PASSWORD=".$password." && export SSH_ASKPASS='".$fileName."/showPass.php' && ssh ".$account."@".$server." ".$command; $handle = popen($finalCommand, "r"); $output = $this->streamGetContents($handle); pclose($handle); return $output; } /** Execute the given command, expecting only to write input to the command @param $server The server to contact @param $account The account to use while connecting on the remote server @param $password The account password to use while connecting on the remote server @param $command The command to execute (must be full command and valid on the remote side) @return the command output text */ function executeRemoteWriting($server, $account, $password, $command, $content) { $fileName = __FILE__; $fileName = substr($fileName, 0, strrpos($fileName, "/")); $finalCommand = "export DISPLAY=xxx && export SSH_PASSWORD=".$password." && export SSH_ASKPASS='".$fileName."/showPass.php' && ssh ".$account."@".$server." ".$command; $handle = popen($finalCommand, "w"); $writtenSize = 0; if (is_resource($handle)) $writtenSize = @fwrite($handle, $content); pclose($handle); return $writtenSize == strlen($content); } /* function remoteCommand while (!feof($handle)) { $read = fgets($handle, 2096); echo $read; } pclose($handle); $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("pipe", "r") // stderr is a file to write to ); putenv('some_option=aeiou'); $process = proc_open($lsCommand . $cwd, $descriptorspec, $pipes); if (is_resource($process)) { // $pipes now looks like this: // 0 => writeable handle connected to child stdin // 1 => readable handle connected to child stdout // Any error output will be appended to /tmp/error-output.txt fwrite($pipes[0], ''); fclose($pipes[0]); $content = stream_get_contentsW($pipes[1]); $ret = parseLs($content); print_r($ret); fclose($pipes[1]); // It is important that you close any pipes before calling // proc_close in order to avoid a deadlock $return_value = proc_close($process); // echo "command returned $return_value\n"; } } */ // Interface /** Get the list of files for the given remote directory @param $path The path on the remote side to list @return an array of file as specified in the parseLs method */ function listFilesIn($path) { $output = $this->executeRemoteCommand($this->server, $this->account, $this->password, $this->lsCommand.".".$path."/"); return $this->parseLs($output); } /** Check if the connection is successful (and retrieve the current directory on the remote server) */ function checkConnection() { $pwd = $this->executeRemoteCommand($this->server, $this->account, $this->password, "pwd"); $charset = $this->executeRemoteCommand($this->server, $this->account, $this->password, $this->getCharsetCommand); $pwd = trim($pwd); $charset = trim($charset); $retArray = array($pwd, $charset); return $retArray; } /** Get the given files either as an archive or as a single file download @param $pathToFile Can be an array or a string if a single file */ function getRemoteContent($pathToFile) { if (is_array($pathToFile)) { // Need to get an archive here $command = $this->zipCommand.implode($pathToFile, " "); return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$command.'"');//'"'.$this->zipCommand.implode(" ", $pathToFile).'"'); } else { // Single file download return $this->executeRemoteCommand($this->server, $this->account, $this->password, $this->catCommand.$pathToFile); } } /** Save the given content onto the given file on the server @param $pathToFile The full, escaped path to the destination file @param $content The final file content (can be empty, will create a file) @return true on success */ function setRemoteContent($pathToFile, $content) { $command = '"'.$this->setFileCommand.str_replace('"', '\\"', $pathToFile).'"'; return $this->executeRemoteWriting($this->server, $this->account, $this->password, $command, $content); } /** Create a remote directory */ function createRemoteDirectory($pathToFile) { $command = '"'.$this->makeDirCommand.str_replace('"', '\\"', $pathToFile).'"'; return $this->executeRemoteCommand($this->server, $this->account, $this->password, $command); } /** Copy a file (or directory) to a remote location */ function copyFile($pathToFile, $finalPath) { if (is_array($pathToFile)) { // Need to get an archive here $command = $this->copyCommand.implode($pathToFile, " "); return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$command.'"'); } else { // Single file download return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$this->copyCommand.$pathToFile." ".$finalPath.'"'); } } /** Copy a file (or directory) to a remote location */ function moveFile($pathToFile, $finalPath) { if (is_array($pathToFile)) { // Need to get an archive here $command = $this->moveCommand.implode($pathToFile, " "); return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$command." ".$finalPath.'"'); } else { // Single file download return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$this->moveCommand.$pathToFile." ".$finalPath.'"'); } } /** Delete a file (or directory) */ function deleteFile($pathToFile) { if (is_array($pathToFile)) { // Need to get an archive here $command = $this->deleteCommand.implode($pathToFile, " "); return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$command.'"'); } else { // Single file download return $this->executeRemoteCommand($this->server, $this->account, $this->password, '"'.$this->deleteCommand.$pathToFile.'"'); } } } ?> AjaXplorer/AjaXplorer/plugins/ajxp.ssh/showPass.php0000766000000000000000000000017611122202524023616 0ustar adminadministrators#!/usr/bin/php AjaXplorer/AjaXplorer/plugins/ajxp.ssh/manifest.xml0000766000000000000000000000063511122202524023626 0ustar adminadministrators AjaXplorer/AjaXplorer/plugins/ajxp.demo/0000777000000000000000000000000011300346025021423 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.demo/fsActions.xml0000766000000000000000000011362511122202524024104 0ustar adminadministrators 0){ path = window.actionArguments[0]; }else{ userSelection = ajaxplorer.getFilesList().getUserSelection(); if(userSelection && userSelection.isUnique() && (userSelection.hasDir() || userSelection.hasMime(["zip"]))){ path = userSelection.getUniqueFileName(); } } if(path){ ajaxplorer.getFoldersTree().goToDeepPath(path); ajaxplorer.filesList.loadXmlList(path); ajaxplorer.getActionBar().updateLocationBar(path); } ]]> = 8 && document.location.href.substring(0,5)!='https') { modal.setCloseAction(function(){ $('closeFlashUploadBox').disabled=false; ajaxplorer.filesList.reload(); }); modal.showDialogForm('Upload', 'flash_upload_form', null, function(){ hideLightBox(); return false; }, null, true, true); } else { $('hidden_frames').innerHTML = ''; var onLoadFunction = function(oForm){ this.multi_selector = new MultiSelector(oForm, oForm.getElementsBySelector('div.uploadFilesList')[0], '6' ); this.multi_selector.addElement(oForm.getElementsBySelector('.dialogFocus')[0]); var rep = document.createElement('input'); rep.setAttribute('type', 'hidden'); rep.setAttribute('name', 'dir'); rep.setAttribute('value', ajaxplorer.getFilesList().getCurrentRep()); oForm.appendChild(rep); }.bind(ajaxplorer.actionBar); modal.setCloseAction(function(){ ajaxplorer.filesList.reload(); }); modal.showDialogForm('Upload', 'originalUploadForm', onLoadFunction, function(){ajaxplorer.actionBar.multi_selector.submitMainForm();return false;}); } ]]>
    ]]>
    ]]>
    AJXP_MESSAGE[173]
    ]]>
    AJXP_MESSAGE[174]
    ]]>
    AJXP_MESSAGE[119]

    ]]>
    ]]>
    Actual Size(100%)Fit To Screen
    % s
    ]]>
    AJXP_MESSAGE[6]  AJXP_MESSAGE[42]
    ]]>
    AJXP_MESSAGE[175]
    ]]>
    ]]> AjaXplorer MP3 Player
    AjaXplorer Player
    '+MessageHash[141]+': #{current_folder}
    '); var mp3Items = new Array(); $A(ajaxplorer.getFilesList().getItems()).each(function(rowItem){ var filename = rowItem.getAttribute('filename'); if(getFileExtension(filename) == 'mp3') mp3Items.push(filename); }); var mp3_url = ''; mp3Items.each(function(url){ mp3_url += 'content.php?action=mp3_proxy%26file='+url; if(url != mp3Items.last()) mp3_url += '|'; }); newWin = window.open('', 'mp3_multi_player', 'width=260,height=30,directories=no,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no'); newWin.document.write(template.evaluate({mp3_url:mp3_url, current_folder:ajaxplorer.getFilesList().getCurrentRep()})); newWin.document.close(); ]]>
    #{name_string} : #{basename}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{dim_string} : #{image_width}px X #{image_height}px
    #{size_string} : #{filesize}
    #{type_string} : #{image_type}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.demo/class.demoDriver.php0000766000000000000000000000402211122202524025334 0ustar adminadministratorsactions[$action])) return; $errorMessage = "This is a demo, all 'write' actions are disabled!"; switch($action) { //------------------------------------ // ONLINE EDIT //------------------------------------ case "edit": if(isset($save) && $save==1) { $xmlBuffer .= AJXP_XMLWriter::sendMessage(null, $errorMessage, false); } else { $this->readFile($this->getPath()."/".SystemTextEncoding::fromUTF8(Utils::securePath($_GET["file"])), "plain"); } exit(0); break; //------------------------------------ // COPY / MOVE //------------------------------------ case "copy": case "move": case "rename": case "delete": case "mkdir": case "mkfile": return AJXP_XMLWriter::sendMessage(null, $errorMessage, false); break; //------------------------------------ // UPLOAD //------------------------------------ case "upload": $fancyLoader = false; foreach ($fileVars as $boxName => $boxData) { if($boxName == "Filedata") $fancyLoader = true; } if($fancyLoader) { header('HTTP/1.0 '.$errorMessage); die('Error '.$errorMessage); } else { print(""); } exit; break; default: break; } return parent::switchAction($action, $httpVars, $fileVars); } } ?> AjaXplorer/AjaXplorer/plugins/ajxp.demo/manifest.xml0000766000000000000000000000125211122202524023751 0ustar adminadministrators AjaXplorer/AjaXplorer/plugins/ajxp.remote_svn/0000777000000000000000000000000011300346026022661 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.remote_svn/svnActions.xml0000766000000000000000000001241311122202524025530 0ustar adminadministrators 0){ var path = window.actionArguments[0]; ajaxplorer.getFoldersTree().goToDeepPath(path); ajaxplorer.getActionBar().updateLocationBar(path); ajaxplorer.filesList.loadXmlList(path); } ]]> ]]>
    #{name_string} : #{basename}
    #{author_string} : #{author}
    #{revision_string} : #{revision}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{author_string} : #{author}
    #{revision_string} : #{revision}
    #{modif_string} : #{modiftime} ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.remote_svn/class.remote_svnDriver.php0000766000000000000000000000612111122202524030030 0ustar adminadministratorsxmlFilePath = INSTALL_PATH."/plugins/ajxp.remote_svn/svnActions.xml"; $this->parseXMLActions(); } function sendInfoPanelsDef(){ $fileData = file_get_contents(INSTALL_PATH."/plugins/ajxp.remote_svn/svnActions.xml"); $matches = array(); preg_match('/.*<\/infoPanels>/', str_replace("\n", "",$fileData), $matches); if(count($matches)){ AJXP_XMLWriter::header(); AJXP_XMLWriter::write($this->replaceAjxpXmlKeywords(str_replace("\n", "",$matches[0])), true); AJXP_XMLWriter::close(); exit(1); } } function svnStubAction($actionName, $httpVars, $filesVars){ if($actionName == "svnlog"){ AJXP_XMLWriter::header(); echo 'cdujeu2008-02-19Commit type errorsmbronni2008-02-19New Functioncdujeu2008-02-19New Factory Class '; AJXP_XMLWriter::close(); }else if($actionName == "svndownload"){ $file = $httpVars["file"]; $rev = $httpVars["revision"]; parent::switchAction("download", $httpVars); } exit(1); } function svnDownload($actionName, $httpVars, $filesVars){ $sessionId = ""; $crtRep = ConfService::getRepository(); $httpClient = $this->getRemoteConnexion($sessionId); $httpVars["ajxp_sessid"] = $sessionId; $method = "get"; if($method == "get"){ $httpClient->get($crtRep->getOption("URI"), $httpVars); }else{ $httpClient->post($crtRep->getOption("URI"), $httpVars); } // check if session is expired if(strpos($httpClient->getHeader("content-type"), "text/xml") !== false && strpos($httpClient->getContent(), "require_auth") != false){ $httpClient = $this->getRemoteConnexion($sessionId, true); $httpVars["ajxp_sessid"] = $sessionId; $method = "get"; if($method == "get"){ $httpClient->get($crtRep->getOption("URI"), $httpVars); }else{ $httpClient->post($crtRep->getOption("URI"), $httpVars); } } $size=strlen($httpClient->content); $filePath = $httpVars["file"]; $svnFileName = $httpClient->getHeader("AjaXplorer-SvnFileName"); header("Content-Type: application/force-download; name=\"".$svnFileName."\""); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".$size); header("Content-Disposition: attachment; filename=\"".$svnFileName."\""); header("Expires: 0"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); // For SSL websites, bug with IE see article KB 323308 if (ConfService::getConf("USE_HTTPS")==1 && preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT'])){ header("Cache-Control:"); header("Pragma:"); } print $httpClient->getContent(); session_write_close(); exit(); } } ?>AjaXplorer/AjaXplorer/plugins/ajxp.fs/0000777000000000000000000000000011300346026021110 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.fs/fsActions.xml0000766000000000000000000011626211122202524023570 0ustar adminadministrators 0){ path = window.actionArguments[0]; }else{ userSelection = ajaxplorer.getFilesList().getUserSelection(); if(userSelection && userSelection.isUnique() && (userSelection.hasDir() || userSelection.hasMime(["zip"]))){ path = userSelection.getUniqueFileName(); } } if(path){ ajaxplorer.getFoldersTree().goToDeepPath(path); ajaxplorer.filesList.loadXmlList(path); ajaxplorer.getActionBar().updateLocationBar(path); } ]]> = 8 && document.location.href.substring(0,5)!='https') { modal.setCloseAction(function(){ $('closeFlashUploadBox').disabled=false; }); modal.showDialogForm('Upload', 'flash_upload_form', null, function(){ hideLightBox(); return false; }, null, true, true); } else { $('hidden_frames').innerHTML = ''; var onLoadFunction = function(oForm){ this.multi_selector = new MultiSelector(oForm, oForm.getElementsBySelector('div.uploadFilesList')[0], '6' ); this.multi_selector.addElement(oForm.getElementsBySelector('.dialogFocus')[0]); var rep = document.createElement('input'); rep.setAttribute('type', 'hidden'); rep.setAttribute('name', 'dir'); rep.setAttribute('value', ajaxplorer.getFilesList().getCurrentRep()); oForm.appendChild(rep); }.bind(ajaxplorer.actionBar); modal.setCloseAction(function(){ ajaxplorer.filesList.reload(); }); modal.showDialogForm('Upload', 'originalUploadForm', onLoadFunction, function(){ajaxplorer.actionBar.multi_selector.submitMainForm();return false;}); } ]]>
    ]]>
    AJXP_MESSAGE[173]
    ]]>
    AJXP_MESSAGE[174]
    ]]>
    AJXP_MESSAGE[119]

    ]]>
    ]]>
    Actual Size(100%)Fit To Screen
    % s
    ]]>
    AJXP_MESSAGE[6]  AJXP_MESSAGE[42]
    ]]>
    AJXP_MESSAGE[175]
    ]]>
    ]]> AjaXplorer MP3 Player
    AjaXplorer Player
    '+MessageHash[141]+': #{current_folder}
    '); var mp3Items = new Array(); $A(ajaxplorer.getFilesList().getItems()).each(function(rowItem){ var filename = rowItem.getAttribute('filename'); if(getFileExtension(filename) == 'mp3') mp3Items.push(filename); }); var mp3_url = ''; mp3Items.each(function(url){ mp3_url += 'content.php?action=mp3_proxy%26file='+url; if(url != mp3Items.last()) mp3_url += '|'; }); newWin = window.open('', 'mp3_multi_player', 'width=260,height=30,directories=no,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no'); newWin.document.write(template.evaluate({mp3_url:mp3_url, current_folder:ajaxplorer.getFilesList().getCurrentRep()})); newWin.document.close(); ]]>
    #{current_folder} #{folders_string} : #{filelist_folders_count}
    #{files_string} : #{filelist_files_count}
    #{totalsize_string} #{filelist_totalsize} ]]>
    #{name_string} : #{basename}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{dim_string} : #{image_width}px X #{image_height}px
    #{size_string} : #{filesize}
    #{type_string} : #{image_type}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.fs/class.fsDriver.php0000766000000000000000000010530111122202524024506 0ustar adminadministratorsrepository->getOption("CREATE"); $path = $this->repository->getOption("PATH"); $recycle = $this->repository->getOption("RECYCLE_BIN"); if($create == true){ if(!is_dir($path)) @mkdir($path); if(!is_dir($path)){ return new AJXP_Exception("Cannot create root path for repository. Please check repository configuration or that your folder is writeable!"); } if($recycle!= "" && !is_dir($path."/".$recycle)){ @mkdir($path."/".$recycle); if(!is_dir($path."/".$recycle)){ return new AJXP_Exception("Cannot create recycle bin folder. Please check repository configuration or that your folder is writeable!"); } } }else{ if(!is_dir($path)){ return new AJXP_Exception("Cannot find base path for your repository! Please check the configuration!"); } } } function switchAction($action, $httpVars, $fileVars){ if(!isSet($this->actions[$action])) return; $xmlBuffer = ""; foreach($httpVars as $getName=>$getValue){ $$getName = Utils::securePath($getValue); } $selection = new UserSelection(); $selection->initFromHttpVars($httpVars); if(isSet($dir) && $action != "upload") { $safeDir = $dir; $dir = SystemTextEncoding::fromUTF8($dir); } if(isSet($dest)) $dest = SystemTextEncoding::fromUTF8($dest); $mess = ConfService::getMessages(); $recycleBinOption = $this->repository->getOption("RECYCLE_BIN"); // FILTER ACTION FOR DELETE if($recycleBinOption!="" && $action == "delete" && $dir != "/".$recycleBinOption) { $action = "move"; $dest = "/".$recycleBinOption; $dest_node = "AJAXPLORER_RECYCLE_NODE"; } // FILTER ACTION FOR RESTORE if($recycleBinOption!="" && $action == "restore" && $dir == "/".$recycleBinOption) { $originalRep = RecycleBinManager::getFileOrigin($selection->getUniqueFile()); if($originalRep != "") { $action = "move"; $dest = $originalRep; } } switch($action) { //------------------------------------ // DOWNLOAD, IMAGE & MP3 PROXYS //------------------------------------ case "download"; AJXP_Logger::logAction("Download", array("files"=>$selection)); if($selection->inZip()){ $tmpDir = dirname($selection->getZipPath())."/.tmpExtractDownload"; @mkdir($this->getPath()."/".$tmpDir); $this->convertSelectionToTmpFiles($tmpDir, $selection); } $zip = false; if($selection->isUnique()){ if(is_dir($this->getPath()."/".$selection->getUniqueFile())) { $zip = true; $dir .= "/".basename($selection->getUniqueFile()); } }else{ $zip = true; } if($zip){ // Make a temp zip and send it as download $loggedUser = AuthService::getLoggedUser(); $file = USERS_DIR."/".($loggedUser?$loggedUser->getId():"shared")."/".time()."tmpDownload.zip"; $zipFile = $this->makeZip($selection->getFiles(), $file, $dir); if(!$zipFile) AJXP_Exception::errorToXml("Error while compressing"); $localName = (basename($dir)==""?"Files":basename($dir)).".zip"; $this->readFile($file, "force-download", $localName, false, false); register_shutdown_function("unlink", $file); }else{ $this->readFile($this->getPath()."/".$selection->getUniqueFile(), "force-download"); } if(isSet($tmpDir)){ //$this->deldir($this->getPath()."/".$tmpDir); $delDir = $this->getPath()."/".$tmpDir; register_shutdown_function(array($this, "deldir"), $delDir); } exit(0); break; case "image_proxy": if($split = UserSelection::detectZip(SystemTextEncoding::fromUTF8($file))){ require_once("server/classes/pclzip.lib.php"); $zip = new PclZip($this->getPath().$split[0]); $data = $zip->extract(PCLZIP_OPT_BY_NAME, substr($split[1], 1), PCLZIP_OPT_EXTRACT_AS_STRING); header("Content-Type: ".Utils::getImageMimeType(basename($split[1]))."; name=\"".basename($split[1])."\""); header("Content-Length: ".strlen($data[0]["content"])); header('Cache-Control: public'); print($data[0]["content"]); }else{ $this->readFile($this->getPath()."/".SystemTextEncoding::fromUTF8($file), "image"); } exit(0); break; case "mp3_proxy": if($split = UserSelection::detectZip(SystemTextEncoding::fromUTF8($file))){ require_once("server/classes/pclzip.lib.php"); $zip = new PclZip($this->getPath().$split[0]); $data = $zip->extract(PCLZIP_OPT_BY_NAME, substr($split[1], 1), PCLZIP_OPT_EXTRACT_AS_STRING); header("Content-Type: audio/mp3; name=\"".basename($split[1])."\""); header("Content-Length: ".strlen($data[0]["content"])); print($data[0]["content"]); }else{ $this->readFile($this->getPath()."/".SystemTextEncoding::fromUTF8($file), "mp3"); } exit(0); break; //------------------------------------ // ONLINE EDIT //------------------------------------ case "edit"; if(isset($save) && $save==1 && isSet($code)) { // Reload "code" variable directly from POST array, do not "securePath"... $code = $_POST["code"]; AJXP_Logger::logAction("Online Edition", array("file"=>SystemTextEncoding::fromUTF8($file))); $code=stripslashes($code); $code=str_replace("<","<",$code); $fp=fopen($this->getPath().SystemTextEncoding::fromUTF8("/$file"),"w"); fputs ($fp,$code); fclose($fp); echo $mess[115]; } else { $this->readFile($this->getPath()."/".SystemTextEncoding::fromUTF8($file), "plain"); } exit(0); break; //------------------------------------ // COPY / MOVE //------------------------------------ case "copy"; case "move"; if($selection->isEmpty()) { $errorMessage = $mess[113]; break; } if($selection->inZip()){ $tmpDir = dirname($selection->getZipPath())."/.tmpExtractDownload"; @mkdir($this->getPath()."/".$tmpDir); $this->convertSelectionToTmpFiles($tmpDir, $selection); if(is_dir($tmpDir)) $this->deldir($this->getPath()."/".$tmpDir); } $success = $error = array(); $this->copyOrMove($dest, $selection->getFiles(), $error, $success, ($action=="move"?true:false)); if(count($error)){ $errorMessage = join("\n", $error); } else { $logMessage = join("\n", $success); AJXP_Logger::logAction(($action=="move"?"Move":"Copy"), array("files"=>$selection, "destination"=>$dest)); } $reload_current_node = true; if(isSet($dest_node)) $reload_dest_node = $dest_node; $reload_file_list = true; break; //------------------------------------ // SUPPRIMER / DELETE //------------------------------------ case "delete"; if($selection->isEmpty()) { $errorMessage = $mess[113]; break; } $logMessages = array(); $errorMessage = $this->delete($selection->getFiles(), $logMessages); if(count($logMessages)) { $logMessage = join("\n", $logMessages); } AJXP_Logger::logAction("Delete", array("files"=>$selection)); $reload_current_node = true; $reload_file_list = true; break; //------------------------------------ // RENOMMER / RENAME //------------------------------------ case "rename"; $file = SystemTextEncoding::fromUTF8($file); $filename_new = SystemTextEncoding::fromUTF8($filename_new); $error = $this->rename($file, $filename_new); if($error != null) { $errorMessage = $error; break; } $logMessage= SystemTextEncoding::toUTF8($file)." $mess[41] ".SystemTextEncoding::toUTF8($filename_new); $reload_current_node = true; $reload_file_list = basename($filename_new); AJXP_Logger::logAction("Rename", array("original"=>$file, "new"=>$filename_new)); break; //------------------------------------ // CREER UN REPERTOIRE / CREATE DIR //------------------------------------ case "mkdir"; $messtmp=""; $dirname=Utils::processFileName(SystemTextEncoding::fromUTF8($dirname)); $error = $this->mkDir($dir, $dirname); if(isSet($error)){ $errorMessage = $error; break; } $reload_file_list = $dirname; $messtmp.="$mess[38] ".SystemTextEncoding::toUTF8($dirname)." $mess[39] "; if($dir=="") {$messtmp.="/";} else {$messtmp.= SystemTextEncoding::toUTF8($dir);} $logMessage = $messtmp; $reload_current_node = true; AJXP_Logger::logAction("Create Dir", array("dir"=>$dir."/".$dirname)); break; //------------------------------------ // CREER UN FICHIER / CREATE FILE //------------------------------------ case "mkfile"; $messtmp=""; $filename=Utils::processFileName(SystemTextEncoding::fromUTF8($filename)); $error = $this->createEmptyFile($dir, $filename); if(isSet($error)){ $errorMessage = $error; break; } $messtmp.="$mess[34] ".SystemTextEncoding::toUTF8($filename)." $mess[39] "; if($dir=="") {$messtmp.="/";} else {$messtmp.=SystemTextEncoding::toUTF8($dir);} $logMessage = $messtmp; $reload_file_list = $filename; AJXP_Logger::logAction("Create File", array("file"=>$dir."/".$filename)); break; //------------------------------------ // UPLOAD //------------------------------------ case "upload": if($dir!=""){$rep_source="/$dir";} else $rep_source = ""; $destination=SystemTextEncoding::fromUTF8($this->getPath().$rep_source); if(!$this->isWriteable($destination)) { $errorMessage = "$mess[38] ".SystemTextEncoding::toUTF8($dir)." $mess[99]."; break; } $logMessage = ""; $fancyLoader = false; foreach ($fileVars as $boxName => $boxData) { if($boxName != "Filedata" && substr($boxName, 0, 9) != "userfile_") continue; if($boxName == "Filedata") $fancyLoader = true; $err = Utils::parseFileDataErrors($boxData, $fancyLoader); if($err != null) { $errorMessage = $err; break; } $userfile_name = $boxData["name"]; if($fancyLoader) $userfile_name = SystemTextEncoding::fromUTF8($userfile_name); $userfile_name=Utils::processFileName($userfile_name); if(isSet($auto_rename)){ $userfile_name = fsDriver::autoRenameForDest($destination, $userfile_name); } if (!move_uploaded_file($boxData["tmp_name"], "$destination/".$userfile_name)) { $errorMessage=($fancyLoader?"411 ":"")."$mess[33] ".$userfile_name; break; } chmod($destination."/".$userfile_name, 0777); $logMessage.="$mess[34] ".SystemTextEncoding::toUTF8($userfile_name)." $mess[35] $dir"; AJXP_Logger::logAction("Upload File", array("file"=>SystemTextEncoding::fromUTF8($dir)."/".$userfile_name)); } if($fancyLoader) { if(isSet($errorMessage)){ header('HTTP/1.0 '.$errorMessage); die('Error '.$errorMessage); }else{ header('HTTP/1.0 200 OK'); die("200 OK"); } } else { print(""); } exit; break; //------------------------------------ // XML LISTING //------------------------------------ case "ls": if(!isSet($dir) || $dir == "/") $dir = ""; $searchMode = $fileListMode = $completeMode = false; if(isSet($mode)){ if($mode == "search") $searchMode = true; else if($mode == "file_list") $fileListMode = true; else if($mode == "complete") $completeMode = true; } if(isSet($skipZip) && $skipZip == "true"){ $skipZip = true; }else{ $skipZip = false; } if($test = UserSelection::detectZip($dir)){ $liste = array(); $zip = $this->zipListing($test[0], $test[1], $liste); AJXP_XMLWriter::header(); $tmpDir = $this->getPath().dirname($test[0]).".tmpZipExtract"; foreach ($liste as $zipEntry){ $atts = array(); if(!$fileListMode && !$zipEntry["folder"]) continue; $atts[] = "is_file=\"".($zipEntry["folder"]?"false":"true")."\""; $atts[] = "text=\"".basename(SystemTextEncoding::toUTF8($zipEntry["stored_filename"]))."\""; $atts[] = "filename=\"".SystemTextEncoding::toUTF8($zipEntry["filename"])."\""; if($fileListMode){ $atts[] = "filesize=\"".Utils::roundSize($zipEntry["size"])."\""; $atts[] = "bytesize=\"".$zipEntry["size"]."\""; $atts[] = "modiftime=\"".date("d/m/Y H:i",$zipEntry["mtime"])."\""; $atts[] = "mimestring=\"".Utils::mimetype($zipEntry["stored_filename"], "mime", $zipEntry["folder"])."\""; $atts[] = "icon=\"".Utils::mimetype($zipEntry["stored_filename"], "image", $zipEntry["folder"])."\""; $is_image = Utils::is_image(basename($zipEntry["stored_filename"])); $atts[] = "is_image=\"".$is_image."\""; if($is_image){ if(!is_dir($tmpDir)) mkdir($tmpDir); $currentFile = $tmpDir."/".basename($zipEntry["stored_filename"]); $data = $zip->extract(PCLZIP_OPT_BY_NAME, $zipEntry["stored_filename"], PCLZIP_OPT_REMOVE_ALL_PATH, PCLZIP_OPT_PATH, $tmpDir); list($width, $height, $type, $attr) = @getimagesize($currentFile); $atts[] = "image_type=\"".image_type_to_mime_type($type)."\""; $atts[] = "image_width=\"$width\""; $atts[] = "image_height=\"$height\""; unlink($currentFile); } }else{ $atts[] = "icon=\"client/images/foldericon.png\""; $atts[] = "openicon=\"client/images/foldericon.png\""; $atts[] = "src=\"content.php?dir=".urlencode(SystemTextEncoding::toUTF8($zipEntry["filename"]))."\""; } print(""); if(is_dir($tmpDir)){ rmdir($tmpDir); } } AJXP_XMLWriter::close(); exit(0); } $nom_rep = $this->initName($dir); AJXP_Exception::errorToXml($nom_rep); $result = $this->listing($nom_rep, !($searchMode || $fileListMode)); $reps = $result[0]; AJXP_XMLWriter::header(); foreach ($reps as $repIndex => $repName) { if(eregi("\.zip$",$repName) && $skipZip) continue; $attributes = ""; if($searchMode) { if(is_file($nom_rep."/".$repIndex)) {$attributes = "is_file=\"true\" icon=\"$repName\""; $repName = $repIndex;} } else if($fileListMode) { $currentFile = $nom_rep."/".$repIndex; $atts = array(); $atts[] = "is_file=\"".(is_file($currentFile)?"1":"0")."\""; $atts[] = "is_image=\"".Utils::is_image($currentFile)."\""; if(Utils::is_image($currentFile)) { list($width, $height, $type, $attr) = @getimagesize($currentFile); $atts[] = "image_type=\"".image_type_to_mime_type($type)."\""; $atts[] = "image_width=\"$width\""; $atts[] = "image_height=\"$height\""; } $atts[] = "mimestring=\"".Utils::mimetype($currentFile, "type", is_dir($currentFile))."\""; $atts[] = "modiftime=\"".$this->date_modif($currentFile)."\""; $atts[] = "filesize=\"".Utils::roundSize(filesize($currentFile))."\""; $bytesize = filesize($currentFile); if($bytesize < 0) $bytesize = sprintf("%u", $bytesize); $atts[] = "bytesize=\"".$bytesize."\""; $atts[] = "filename=\"".str_replace("&", "&", SystemTextEncoding::toUTF8($dir."/".$repIndex))."\""; $atts[] = "icon=\"".(is_file($currentFile)?SystemTextEncoding::toUTF8($repName):"folder.png")."\""; $attributes = join(" ", $atts); $repName = $repIndex; } else { $link = SystemTextEncoding::toUTF8(SERVER_ACCESS."?dir=".$dir."/".$repName); $link = urlencode($link); $folderBaseName = str_replace("&", "&", $repName); $folderFullName = "$dir/".$folderBaseName; $parentFolderName = $dir; if(!$completeMode){ $icon = CLIENT_RESOURCES_FOLDER."/images/foldericon.png"; $openicon = CLIENT_RESOURCES_FOLDER."/images/openfoldericon.png"; if(eregi("\.zip$",$repName)){ $icon = $openicon = CLIENT_RESOURCES_FOLDER."/images/crystal/actions/16/accessories-archiver.png"; } $attributes = "icon=\"$icon\" openicon=\"$openicon\" filename=\"".SystemTextEncoding::toUTF8($folderFullName)."\" src=\"$link\""; } } print(""); print(""); } // ADD RECYCLE BIN TO THE LIST if($nom_rep == $this->repository->getOption("PATH") && $recycleBinOption!="" && !$completeMode && !$skipZip) { if($fileListMode) { print("date_modif($this->repository->getOption("PATH")."/".$recycleBinOption)."\" filename=\"/".$recycleBinOption."\" icon=\"trashcan.png\">"); } else { print(""); } } AJXP_XMLWriter::close(); exit(1); break; } if(isset($logMessage) || isset($errorMessage)) { $xmlBuffer .= AJXP_XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null), false); } if(isset($requireAuth)) { $xmlBuffer .= AJXP_XMLWriter::requireAuth(false); } if(isset($reload_current_node) && $reload_current_node == "true") { $xmlBuffer .= AJXP_XMLWriter::reloadCurrentNode(false); } if(isset($reload_dest_node) && $reload_dest_node != "") { $xmlBuffer .= AJXP_XMLWriter::reloadNode($reload_dest_node, false); } if(isset($reload_file_list)) { $xmlBuffer .= AJXP_XMLWriter::reloadFileList($reload_file_list, false); } return $xmlBuffer; } function getPath(){ return $this->repository->getOption("PATH"); } function zipListing($zipPath, $localPath, &$filteredList){ require_once("server/classes/pclzip.lib.php"); $crtZip = new PclZip($this->getPath()."/".$zipPath); $liste = $crtZip->listContent(); $files = array(); if($localPath[strlen($localPath)-1] != "/") $localPath.="/"; foreach ($liste as $item){ $stored = $item["stored_filename"]; if($stored[0] != "/") $stored = "/".$stored; $pathPos = strpos($stored, $localPath); if($pathPos !== false){ $afterPath = substr($stored, $pathPos+strlen($localPath)); if($afterPath != "" && strpos($afterPath, "/")=== false || strpos($afterPath, "/") == strlen($afterPath)-1){ $item["filename"] = $zipPath.$localPath.$afterPath; if($item["folder"]){ $filteredList[] = $item; }else{ $files[] = $item; } } } } $filteredList = array_merge($filteredList, $files); return $crtZip; } function initName($dir) { $racine = $this->getPath(); $mess = ConfService::getMessages(); if(!isset($dir) || $dir=="" || $dir == "/") { $nom_rep=$racine; } else { $nom_rep="$racine/$dir"; } if(!file_exists($racine)) { return new AJXP_Exception(72); } if(!is_dir($nom_rep)) { return new AJXP_Exception(100); } return $nom_rep; } function readFile($filePathOrData, $headerType="plain", $localName="", $data=false, $gzip=GZIP_DOWNLOAD) { $size = ($data?strlen($filePathOrData):filesize($filePathOrData)); if(!$data && $size < 0){ // fix files above 2Gb $size = sprintf("%u", $size); } if($gzip && ($size > GZIP_LIMIT || !function_exists("gzencode") || @strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE)){ $gzip = false; // disable gzip } $localName = ($localName==""?basename($filePathOrData):$localName); if($headerType == "plain") { header("Content-type:text/plain"); } else if($headerType == "image") { //$size=filesize($filePathOrData); header("Content-Type: ".Utils::getImageMimeType(basename($filePathOrData))."; name=\"".basename($filePathOrData)."\""); header("Content-Length: ".$size); header('Cache-Control: public'); } else if($headerType == "mp3") { //$size=filesize($filePathOrData); header("Content-Type: audio/mp3; name=\"".basename($filePathOrData)."\""); header("Content-Length: ".$size); } else { //$size=filesize($filePathOrData); //if($localName == "") $localName = basename($filePathOrData); header("Content-Type: application/force-download; name=\"".$localName."\""); header("Content-Transfer-Encoding: binary"); if($gzip){ header("Content-Encoding: gzip"); // If gzip, recompute data size! $gzippedData = ($data?gzencode($filePathOrData,9):gzencode(file_get_contents($filePathOrData), 9)); $size = strlen($gzippedData); } header("Content-Length: ".$size); header("Content-Disposition: attachment; filename=\"".$localName."\""); header("Expires: 0"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); // For SSL websites there is a bug with IE see article KB 323308 // therefore we must reset the Cache-Control and Pragma Header if (ConfService::getConf("USE_HTTPS")==1 && preg_match('/ MSIE /',$_SERVER['HTTP_USER_AGENT'])) { header("Cache-Control:"); header("Pragma:"); } if($gzip){ print $gzippedData; return ; } } if($data){ print($filePathOrData); }else{ readfile($filePathOrData); } } function listing($nom_rep, $dir_only = false) { $size_unit = ConfService::getConf("SIZE_UNIT"); $sens = 0; $ordre = "nom"; $poidstotal=0; $handle=opendir($nom_rep); $recycle = $this->repository->getOption("RECYCLE_BIN"); while ($file = readdir($handle)) { if($file!="." && $file!=".." && Utils::showHiddenFiles($file)==1) { if($recycle != "" && $nom_rep == $this->repository->getOption("PATH")."/".$recycle && $file == RecycleBinManager::getCacheFileName()){ continue; } $poidsfic=filesize("$nom_rep/$file"); $poidstotal+=$poidsfic; if(is_dir("$nom_rep/$file")) { if($recycle != "" && $this->getPath()."/".$recycle == "$nom_rep/$file") { continue; } if($ordre=="mod") {$liste_rep[$file]=filemtime("$nom_rep/$file");} else {$liste_rep[$file]=$file;} } else { if(!$dir_only) { if($ordre=="nom") {$liste_fic[$file]=Utils::mimetype("$nom_rep/$file","image", is_dir("$nom_rep/$file"));} else if($ordre=="taille") {$liste_fic[$file]=$poidsfic;} else if($ordre=="mod") {$liste_fic[$file]=filemtime("$nom_rep/$file");} else if($ordre=="type") {$liste_fic[$file]=Utils::mimetype("$nom_rep/$file","type",is_dir("$nom_rep/$file"));} else {$liste_fic[$file]=Utils::mimetype("$nom_rep/$file","image", is_dir("$nom_rep/$file"));} } else if(eregi("\.zip$",$file) && ConfService::zipEnabled()){ if(!isSet($liste_zip)) $liste_zip = array(); $liste_zip[$file] = $file; } } } } closedir($handle); if(isset($liste_fic) && is_array($liste_fic)) { if($ordre=="nom") {if($sens==0){ksort($liste_fic);}else{krsort($liste_fic);}} else if($ordre=="mod") {if($sens==0){arsort($liste_fic);}else{asort($liste_fic);}} else if($ordre=="taille"||$ordre=="type") {if($sens==0){asort($liste_fic);}else{arsort($liste_fic);}} else {if($sens==0){ksort($liste_fic);}else{krsort($liste_fic);}} } else { $liste_fic = array(); } if(isset($liste_rep) && is_array($liste_rep)) { if($ordre=="mod") {if($sens==0){arsort($liste_rep);}else{asort($liste_rep);}} else {if($sens==0){ksort($liste_rep);}else{krsort($liste_rep);}} } else ($liste_rep = array()); $liste = Utils::mergeArrays($liste_rep,$liste_fic); if(isSet($liste_zip)){ $liste = Utils::mergeArrays($liste,$liste_zip); } if ($poidstotal >= 1073741824) {$poidstotal = round($poidstotal / 1073741824 * 100) / 100 . " G".$size_unit;} elseif ($poidstotal >= 1048576) {$poidstotal = round($poidstotal / 1048576 * 100) / 100 . " M".$size_unit;} elseif ($poidstotal >= 1024) {$poidstotal = round($poidstotal / 1024 * 100) / 100 . " K".$size_unit;} else {$poidstotal = $poidstotal . " ".$size_unit;} return array($liste,$poidstotal); } function date_modif($file) { $tmp = filemtime($file); return date("d/m/Y H:i",$tmp); } function copyOrMove($destDir, $selectedFiles, &$error, &$success, $move = false) { $mess = ConfService::getMessages(); if(!is_writable($this->getPath()."/".$destDir)) { $error[] = $mess[38]." ".$destDir." ".$mess[99]; return ; } foreach ($selectedFiles as $selectedFile) { if($move && !is_writable(dirname($this->getPath()."/".$selectedFile))) { $error[] = "\n".$mess[38]." ".dirname($selectedFile)." ".$mess[99]; continue; } $this->copyOrMoveFile($destDir, $selectedFile, $error, $success, $move); } } function renameAction($actionName, $httpVars) { $filePath = SystemTextEncoding::fromUTF8($httpVars["file"]); $newFilename = SystemTextEncoding::fromUTF8($httpVars["filename_new"]); return $this->rename($filePath, $newFilename); } function rename($filePath, $filename_new) { $nom_fic=basename($filePath); $mess = ConfService::getMessages(); $filename_new=Utils::processFileName($filename_new); $old=$this->getPath()."/$filePath"; if(!is_writable($old)) { return $mess[34]." ".$nom_fic." ".$mess[99]; } $new=dirname($old)."/".$filename_new; if($filename_new=="") { return "$mess[37]"; } if(file_exists($new)) { return "$filename_new $mess[43]"; } if(!file_exists($old)) { return $mess[100]." $nom_fic"; } rename($old,$new); return null; } function autoRenameForDest($destination, $fileName){ if(!is_file($destination."/".$fileName)) return $fileName; $i = 1; $ext = ""; $name = ""; $split = split("\.", $fileName); if(count($split) > 1){ $ext = ".".$split[count($split)-1]; array_pop($split); $name = join("\.", $split); }else{ $name = $fileName; } while (is_file($destination."/".$name."-$i".$ext)) { $i++; // increment i until finding a non existing file. } return $name."-$i".$ext; } function mkDir($crtDir, $newDirName) { $mess = ConfService::getMessages(); if($newDirName=="") { return "$mess[37]"; } if(file_exists($this->getPath()."/$crtDir/$newDirName")) { return "$mess[40]"; } if(!is_writable($this->getPath()."/$crtDir")) { return $mess[38]." $crtDir ".$mess[99]; } mkdir($this->getPath()."/$crtDir/$newDirName",0775); return null; } function createEmptyFile($crtDir, $newFileName) { $mess = ConfService::getMessages(); if($newFileName=="") { return "$mess[37]"; } if(file_exists($this->getPath()."/$crtDir/$newFileName")) { return "$mess[71]"; } if(!is_writable($this->getPath()."/$crtDir")) { return "$mess[38] $crtDir $mess[99]"; } $fp=fopen($this->getPath()."/$crtDir/$newFileName","w"); if($fp) { if(eregi("\.html$",$newFileName)||eregi("\.htm$",$newFileName)) { fputs($fp,"\n\nNew Document - Created By AjaXplorer\n\n\n\n\n\n\n"); } fclose($fp); return null; } else { return "$mess[102] $crtDir/$newFileName (".$fp.")"; } } function delete($selectedFiles, &$logMessages) { $mess = ConfService::getMessages(); foreach ($selectedFiles as $selectedFile) { if($selectedFile == "" || $selectedFile == DIRECTORY_SEPARATOR) { return $mess[120]; } $fileToDelete=$this->getPath().$selectedFile; if(!file_exists($fileToDelete)) { $logMessages[]=$mess[100]." ".SystemTextEncoding::toUTF8($selectedFile); continue; } $this->deldir($fileToDelete); if(is_dir($fileToDelete)) { $logMessages[]="$mess[38] ".SystemTextEncoding::toUTF8($selectedFile)." $mess[44]."; } else { $logMessages[]="$mess[34] ".SystemTextEncoding::toUTF8($selectedFile)." $mess[44]."; } } return null; } function copyOrMoveFile($destDir, $srcFile, &$error, &$success, $move = false) { $mess = ConfService::getMessages(); $destFile = $this->repository->getOption("PATH").$destDir."/".basename($srcFile); $realSrcFile = $this->repository->getOption("PATH")."/$srcFile"; $recycle = $this->repository->getOption("RECYCLE_BIN"); if(!file_exists($realSrcFile)) { $error[] = $mess[100].$srcFile; return ; } if($realSrcFile==$destFile) { $error[] = $mess[101]; return ; } if(is_dir($realSrcFile)) { $errors = array(); $succFiles = array(); $dirRes = $this->dircopy($realSrcFile, $destFile, $errors, $succFiles); if(count($errors)) { $error[] = $mess[114]; return ; } } else { $res = copy($realSrcFile,$destFile); if($res != 1) { $error[] = $mess[114]; return ; } } if($move) { // Now delete original $this->deldir($realSrcFile); // both file and dir $messagePart = $mess[74]." ".SystemTextEncoding::toUTF8($destDir); if($destDir == "/".$recycle) { RecycleBinManager::fileToRecycle($srcFile); $messagePart = $mess[123]." ".$mess[122]; } if(isset($dirRes)) { $success[] = $mess[117]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$messagePart." (".SystemTextEncoding::toUTF8($dirRes)." ".$mess[116].") "; } else { $success[] = $mess[34]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$messagePart; } } else { if($destDir == "/".$this->repository->getOption("RECYCLE_BIN")) { RecycleBinManager::fileToRecycle($srcFile); } if(isSet($dirRes)) { $success[] = $mess[117]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$mess[73]." ".SystemTextEncoding::toUTF8($destDir)." (".SystemTextEncoding::toUTF8($dirRes)." ".$mess[116].")"; } else { $success[] = $mess[34]." ".SystemTextEncoding::toUTF8(basename($srcFile))." ".$mess[73]." ".SystemTextEncoding::toUTF8($destDir); } } } // A function to copy files from one directory to another one, including subdirectories and // nonexisting or newer files. Function returns number of files copied. // This function is PHP implementation of Windows xcopy A:\dir1\* B:\dir2 /D /E /F /H /R /Y // Syntaxis: [$number =] dircopy($sourcedirectory, $destinationdirectory [, $verbose]); // Example: $num = dircopy('A:\dir1', 'B:\dir2', 1); function dircopy($srcdir, $dstdir, &$errors, &$success, $verbose = false) { $num = 0; if(!is_dir($dstdir)) mkdir($dstdir); if($curdir = opendir($srcdir)) { while($file = readdir($curdir)) { if($file != '.' && $file != '..') { $srcfile = $srcdir . DIRECTORY_SEPARATOR . $file; $dstfile = $dstdir . DIRECTORY_SEPARATOR . $file; if(is_file($srcfile)) { if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1; if($ow > 0) { if($verbose) echo "Copying '$srcfile' to '$dstfile'..."; if(copy($srcfile, $dstfile)) { touch($dstfile, filemtime($srcfile)); $num++; if($verbose) echo "OK\n"; $success[] = $srcfile; } else { $errors[] = $srcfile; } } } else if(is_dir($srcfile)) { $num += $this->dircopy($srcfile, $dstfile, $errors, $success, $verbose); } } } closedir($curdir); } return $num; } function simpleCopy($origFile, $destFile) { return copy($origFile, $destFile); } function isWriteable($dir) { return is_writable($dir); } function deldir($location) { if(is_dir($location)) { $all=opendir($location); while ($file=readdir($all)) { if (is_dir("$location/$file") && $file !=".." && $file!=".") { $this->deldir("$location/$file"); if(file_exists("$location/$file")){rmdir("$location/$file"); } unset($file); } elseif (!is_dir("$location/$file")) { if(file_exists("$location/$file")){unlink("$location/$file"); } unset($file); } } closedir($all); rmdir($location); } else { if(file_exists("$location")) {unlink("$location");} } if(basename(dirname($location)) == $this->repository->getOption("RECYCLE_BIN")) { // DELETING FROM RECYCLE RecycleBinManager::deleteFromRecycle($location); } } /** * @return zipfile */ function makeZip ($src, $dest, $basedir) { set_time_limit(60); require_once(SERVER_RESOURCES_FOLDER."/pclzip.lib.php"); $filePaths = array(); $totalSize = 0; foreach ($src as $item){ $filePaths[] = array(PCLZIP_ATT_FILE_NAME => $this->getPath().$item, PCLZIP_ATT_FILE_NEW_SHORT_NAME => basename($item)); } $archive = new PclZip($dest); $vList = $archive->create($filePaths, PCLZIP_OPT_REMOVE_PATH, $this->getPath().$basedir, PCLZIP_OPT_NO_COMPRESSION); if($vList == 0) return false; } /** * @param $selection UserSelection */ function convertSelectionToTmpFiles($tmpDir, &$selection){ $zipPath = $selection->getZipPath(); $localDir = $selection->getZipLocalPath(); $files = $selection->getFiles(); foreach ($files as $key => $item){// Remove path $item = substr($item, strlen($zipPath)); if($item[0] == "/") $item = substr($item, 1); $files[$key] = $item; } require_once("server/classes/pclzip.lib.php"); $zip = new PclZip($this->getPath().$zipPath); $err = $zip->extract(PCLZIP_OPT_BY_NAME, $files, PCLZIP_OPT_PATH, $this->getPath()."/".$tmpDir); foreach ($files as $key => $item){// Remove path $files[$key] = $tmpDir."/".$item; } $selection->setFiles($files); } } ?> AjaXplorer/AjaXplorer/plugins/ajxp.fs/icon.png0000766000000000000000000000177611122202524022556 0ustar adminadministratorsPNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb Nb៣' XXfa|3C];/_ELLLOKKYXYؘ888޾;]޽{@,,J< ?~`LH63  & AAQ} b ,,@_ ?cbdR* NNn-..߿;Ab3 # 4@ XE5LL4~'fK l}gegPUUbaa EEYU--߁ v? r߿ /00ՕYxyLERRT ?BL(ـ.dv'':&@pq۷o@5Hd(b P??@1rqq-8@d *?7 oY˷& 4GnY>} ؿ@W0t>#Ï߿^x;_ F33 c'@_9% !O۷u vV?LLLll,?q^bdc,fd.W \%)um_^|o`hÇw,'O_ A LLI//-./4(4 R +nnix >~|rȱ>c?ט90ܻaČ7?{tD bi`& _|ѻw10Ȱ1 3<@W@ ',f k0#IENDB`AjaXplorer/AjaXplorer/plugins/ajxp.fs/manifest.xml0000766000000000000000000000123511122202524023436 0ustar adminadministrators AjaXplorer/AjaXplorer/plugins/ajxp.svn/0000777000000000000000000000000011300346027021307 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.svn/svn_executor.inc.php0000766000000000000000000001247311122202524025317 0ustar adminadministratorsGetRepositoryRoot(), $cmd); $cmd = str_replace('%webspace%', $config->GetWebspaceRootDir(), $cmd); $cmd = str_replace('%rep%', $config->GetRepositoryRoot(), $cmd); $cmd = str_replace('%ws%', $config->GetWebspaceRootDir(), $cmd); $result[IDX_ERROUT] = array(T(TK_RESULT_ERROR_NO_SVN_CMD__CMD, $cmd)); $rc = stripos($cmd, 'svn'); if ($rc !== false && $rc == 0){ $result = ExecSvnCmd($cmd); $result[IDX_TITLE] = T(TK_RESULT_CMD_EXEC); } } $results[] = $result; break; } } return $results; } ?> AjaXplorer/AjaXplorer/plugins/ajxp.svn/class.svnDriver.php0000766000000000000000000001171511122202524025107 0ustar adminadministratorscrtPath = ""; if(isSet($httpVars["dir"]) && $httpVars["dir"] != ""){ $this->crtPath = $httpVars["dir"]; } $this->crtListingMode = (isSet($httpVars["mode"])?$httpVars["mode"]:"complete"); $res = ListRepository($this->repository, $this->crtPath); //$res[IDX_STDOUT] = ""; //header("content-type:text/xml"); //print_r($res[IDX_STDOUT]); $this->parseListing($res[IDX_STDOUT]); //print_r($this->listElements); //exit(); AJXP_XMLWriter::header(); // FIRST PASS FOR FOLDERS; foreach ($this->listElements as $element){ if($element["is_file"] == "1") continue; print(" $attValue){ print "$attName=\"".$attValue."\" "; } print("/>"); } if($this->crtListingMode != "complete"){ foreach ($this->listElements as $element){ if($element["is_file"] == "0") continue; print(" $attValue){ print "$attName=\"".$attValue."\" "; } print("/>"); } } AJXP_XMLWriter::close(); exit(1); }else if($action == "log" && isSet($httpVars["file"])){ $res = GetWebspaceLog($this->repository, $httpVars["file"]); //print_r($res); AJXP_XMLWriter::header(); if(is_array($res)) print(ereg_replace("[\r\n]","",str_replace('', "", $res[IDX_STDOUT]))); AJXP_XMLWriter::close(); exit(1); } } function parseListing($xmlContent){ $this->listElements = array(); $this->listingParser = xml_parser_create( "UTF-8" ); //xml_parser_set_option( $this->xml_parser, XML_OPTION_CASE_FOLDING, false ); xml_set_object( $this->listingParser, $this ); xml_set_element_handler( $this->listingParser, "listingStartElement", "listingEndElement"); xml_set_character_data_handler( $this->listingParser, "listingCData" ); xml_parse( $this->listingParser, $xmlContent, true ); xml_parser_free( $this->listingParser); return $this->listElements; } function listingStartElement($parser, $tag, $attributeList){ if($tag == "ENTRY"){ $this->crtElement = array(); if(isSet($attributeList["KIND"]) && $attributeList["KIND"] == "file"){ $this->crtElement["is_file"] = true; } else{ $this->crtElement["is_file"] = false; } }else if($tag == "NAME" || $tag == "AUTHOR" || $tag == "DATE" || $tag == "SIZE"){ $this->cdataBuffer = ""; }else if($tag == "COMMIT" && $this->crtListingMode == "file_list"){ $this->crtElement["revision"] = $attributeList["REVISION"]; } } function listingEndElement($parser, $tag){ if($tag == "ENTRY"){ if($this->crtListingMode == "file_list" || $this->crtListingMode == "search"){ if(!$this->crtElement["is_file"]){ $this->crtElement["filesize"] = "-"; } $this->crtElement["mimestring"] = Utils::mimetype($this->crtElement["filename"],"text",!$this->crtElement["is_file"]); $this->crtElement["icon"] = Utils::mimetype($this->crtElement["filename"], "image",!$this->crtElement["is_file"]); $this->crtElement["is_file"] = $this->crtElement["is_file"]?"1":"0"; $this->listElements[] = $this->crtElement; }else { if(!$this->crtElement["is_file"]){ $this->crtElement["icon"] = CLIENT_RESOURCES_FOLDER."/images/foldericon.png"; $this->crtElement["openicon"] = CLIENT_RESOURCES_FOLDER."/images/openfoldericon.png"; $this->crtElement["src"] = SERVER_ACCESS."?dir=".$this->crtPath."/".$this->crtElement["text"]; $this->crtElement["parentname"] = ($this->crtPath == "/"?"":$this->crtPath); $this->crtElement["action"] = "javascript:ajaxplorer.getFoldersTree().clickNode(CURRENT_ID)"; $this->crtElement["is_file"] = $this->crtElement["is_file"]?"1":"0"; $this->listElements[] = $this->crtElement; } } }else if($tag == "NAME"){ $this->crtElement["filename"] = $this->cdataBuffer; $this->crtElement["text"] = basename($this->cdataBuffer); }else if($tag == "AUTHOR" && $this->crtListingMode == "file_list"){ $this->crtElement["author"] = $this->cdataBuffer; }else if($tag == "SIZE" && $this->crtListingMode == "file_list"){ $this->crtElement["filesize"] = Utils::roundSize(intval($this->cdataBuffer)); }else if($tag == "DATE" && $this->crtListingMode == "file_list"){ $date = $this->cdataBuffer; $split = split("T",$date); $realDate = $split[0]; $split = split("\.", $split[1]); $realTime = $split[0]; $this->crtElement["modiftime"] = date("d/m/Y H:i", strtotime($realDate." ".$realTime)); } } function listingCData($parser, $cData){ $this->cdataBuffer .= $cData; } } ?>AjaXplorer/AjaXplorer/plugins/ajxp.svn/svnActions.xml0000766000000000000000000000641211122202524024157 0ustar adminadministrators ]]>
    #{name_string} : #{basename}
    Author: : #{author}
    Revision: : #{revision}
    #{size_string} : #{filesize}
    #{type_string} : #{mimestring}
    #{modif_string} : #{modiftime} ]]>
    #{name_string} : #{basename}
    #{author_string} : #{author}
    #{revision_string} : #{revision}
    #{modif_string} : #{modiftime} ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.svn/svn_lib.inc.php0000766000000000000000000005216111122202524024225 0ustar adminadministratorssvn. * @return array svn help output in * form of a result array as produced * by ExecSvnCmd. * @see ExecSvnCmd * * @since v1.0.0 */ function GetSvnHelp(){ $command = 'svn'; $switches = '--help'; $result = ExecSvnCmd($command, '', $switches); return $result; } /** * Returns the help output of svnlook. * @return array svnlook help output in * form of a result array as produced * by ExecSvnCmd. * @see ExecSvnCmd * * @since v1.0.0 */ function GetSvnLookHelp(){ $command = 'svnlook'; $switches = '--help'; $result = ExecSvnCmd($command, '', $switches); return $result; } /** * Returns the help output of svnadmin. * @return array svnadmin help output in * form of a result array as produced * by ExecSvnCmd. * @see ExecSvnCmd * * @since v1.0.0 */ function GetSvnAdminHelp(){ $command = 'svnadmin'; $switches = '--help'; $result = ExecSvnCmd($command, '', $switches); return $result; } /** * Returns the help output of svnversion. * @return array svnversion help output in * form of a result array as produced * by ExecSvnCmd. * @see ExecSvnCmd * * @since v1.0.0 */ function GetSvnVersionHelp(){ $command = 'svnversion'; $switches = '--help'; $result = ExecSvnCmd($command, '', $switches); return $result; } /** * Returns the version of SVN. * @return string Version of Subversion * * @since v1.0.0 */ function GetSvnVersion(){ $command = 'svn'; $switches = '--version'; static $version = NULL; if ($version == NULL){ $result = ExecSvnCmd($command, '', $switches); if ($result[IDX_CMD_RC] == 0){ $version = ParseArray($result[IDX_STDOUT], ', ', ' (r'); $version = substr($version, strpos($version, '.')-1); } } return $version; } /** * Returns the output of svn info for * the repository contained in a result * array as produced by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Output line by line. * @see ExecSvnCmd * * @since v1.1.0 */ function &GetRepositoryInfo($config){ $command = 'svn info'; $arg = $config->GetRepositoryRoot(); $switches = '--xml'; static $result = NULL; if (empty($result)){ $result = ExecSvnCmd($command, $arg, $switches); } return $result; } /** * Returns the number of the youngest SVN revision (HEAD) * available in the repository. * @param SwcConfig $config SWC config for the operation. * @return int Number of HEAD revision * * @since v1.0.0 * */ function GetHeadRevision($config){ $info = GetRepositoryInfo($config); $rev = ParseArray($info[IDX_STDOUT], 'revision="', '">'); return $rev; } /** * Returns the formated date of the latest changes * within the repository. * @param SwcConfig $config SWC config for the operation. * @return string Date of HEAD revision. * * @since v1.0.0 */ function GetHeadDate($config){ $info = GetRepositoryInfo($config); $timestamp = ParseArray($info[IDX_STDOUT], '', ''); $timestamp = strtotime($timestamp); $ts = GetLocalizedTimestamp($timestamp); return $ts; } /** * Returns the output of svn info * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @param boolean $xml_output Whether or not output shall * be printed in xml format (default). * @return array Output line by line. * @see ExecSvnCmd * * @version v1.1.0 * @since v1.0.0 */ function &GetWebspaceInfo($config, $xml_output = true){ $command = 'svn info'; $arg = $config->GetWebspaceRootDir(); $switches = ''; static $result_plain = NULL; static $result_xml = NULL; if (!$xml_output && empty($result_plain)){ $result_plain = ExecSvnCmd($command, $arg, $switches); }else if ($xml_output && empty($result_xml)){ $switches .= '--xml'; $result_xml = ExecSvnCmd($command, $arg, $switches); } $res = ($xml_output ? $result_xml : $result_plain); return $res; } /** * Returns the number of the SVN revision * of the webspace. * @param SwcConfig $config SWC config for the operation. * @return int Webspace revision. * * @since v1.0.0 */ function GetWebspaceRevision($config){ $info = GetWebspaceInfo($config); return ParseArray($info[IDX_STDOUT], 'revision="', '">'); } /** * Returns the path of the repository * where the webspace referes to with * repository root directory. * @param SwcConfig $config SWC config for the operation. * @return string Repository path the webspace points to. * * @since v1.0.0 */ function GetWebspaceSourcePath($config){ $info = GetWebspaceInfo($config); $ws_path = ParseArray($info[IDX_STDOUT], '', ''); $ws_root = ParseArray($info[IDX_STDOUT], '', ''); $path = substr($ws_path, strlen($ws_root)); return $path; } /** * Returns the formated date of the * revision of the workspace. * @param SwcConfig $config SWC config for the operation. * @return string Date of webspace revision. * * @since v1.0.0 */ function GetWebspaceRevisionDate($config){ $info = GetWebspaceInfo($config); $timestamp = ParseArray($info[IDX_STDOUT], '', ''); $timestamp = strtotime($timestamp); return GetLocalizedTimestamp($timestamp); } /** * Returns the output of svn status * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Result of svn status execution. * @see ExecSvnCmd * * @since v1.0.0 */ function &GetWebspaceStatus($config){ $command = 'svn status'; $switches = '--verbose --show-updates --non-interactive'; $switches .= GetSvnUsr($config); $switches .= GetSvnPw($config); $arg = $config->GetWebspaceRootDir(); static $result = NULL; if ($result == NULL){ $result = ExecSvnCmd($command, $arg, $switches); for ($i = count($result[IDX_STDOUT]); $i > 0; $i--){ $result[IDX_STDOUT][$i] = $result[IDX_STDOUT][$i-1]; } $result[IDX_STDOUT][0] = T(TK_WEBSPACE_STATUS_LIST_HEADER); } return $result; } /** * Returns the output of svn log * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Result of svn log execution. * @see ExecSvnCmd * * @since v1.0.0 */ function &GetWebspaceLog($config, $path){ $command = 'svn log'; $switches = '--xml --non-interactive'; //$switches .= GetSvnUsr($config); //$switches .= GetSvnPw($config); $arg = $config->getOption("REPOSITORY_ROOT").$path; $result = ExecSvnCmd($command, $arg, $switches); return $result; } /** * Returns the output of svn list * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Result of svn list execution. * @see ExecSvnCmd * * @since v1.1.0 */ function ListRepository($config, $path){ //$rep_root = $config->GetRepositoryRoot(); $rep_root = $config->getOption("REPOSITORY_ROOT").$path; $command = 'svn list'; //$switches = '--recursive'; $switches = '--xml'; $paths = array(); $arg = trim($rep_root); $res = ExecSvnCmd($command, $arg, $switches); return $res; } /** * Returns the array of tags available * in the repository. * @param SwcConfig $config SWC config for the operation. * @return array Version tags. * * @since v1.0.0 */ function &GetTags($config){ $tag_dirs = $config->GetTagDirs(); $depth = $config->GetMaxTagDirDepth(); $paths = GetRepositoryPaths($config, $tag_dirs, $depth); return $paths; } /** * Returns the array of branches available * in the repository. * @param SwcConfig $config SWC config for the operation. * @return array Version branches. * * @since v1.0.0 */ function &GetBranches($config){ $branch_dirs = $config->GetBranchDirs(); $depth = $config->GetMaxBranchDirDepth(); $paths = GetRepositoryPaths($config, $branch_dirs, $depth); return $paths; } /** * Returns an array of repository paths starting * at $root with maximum directory count given in $level. * @param SwcConfig $config SWC config for the operation. * @param string or array $roots (Array of) repository directories to start from * @param int $depth Maximum directory depth. * @return array Array of paths of repository. * * @since v1.0.0 */ function GetRepositoryPaths($config, $roots, $depth){ $rep_root = $config->GetRepositoryRoot(); if (!is_array($roots)){ $root_dirs[] = $roots; } else { $root_dirs = $roots; } $command = 'svn list'; $switches = '--recursive'; $paths = array(); foreach($root_dirs as $dir){ $parent_dir = trim($dir); $arg = trim($rep_root).$parent_dir; $res = ExecSvnCmd($command, $arg, $switches); if ($res[IDX_CMD_RC] == 0){ $paths = BuildSvnDirTree($paths, $res[IDX_STDOUT], $depth, $parent_dir); } } return $paths; } /** * Builds SVN directory tree. * @param array $paths Reference to SVN path array * @param array $tree Reference to 'svnlook tree' stdout that * should be transformed into SVN paths. * @param int $max_level Mamimum level for paths. * @param string $parent_dir Parent directory in path. * @return array Paths already found. * @version v1.1.0 * @since v1.0.0 */ function &BuildSvnDirTree(&$paths, &$tree, $max_level, $parent_dir = ''){ if (! empty($parent_dir)){ $paths[] = $parent_dir; } foreach($tree as $path){ $level = 0; $offset = strpos($path, '/'); while ($offset !== false && ($level < $max_level)){ $offset = strpos($path, '/', $offset); ++$level; } if ($offset === false){ $offset = strrpos($path, '/'); } $path = substr($path, 0, $offset); if (!empty($parent_dir)){ $path = $parent_dir.'/'.$path; } $paths[$path] = $path; } return $paths; } /** * Performs webspace update to head revision * and returns the output of 'svn update' * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Result of svn update execution. * @see ExecSvnCmd * * @since v1.0.0 */ function UpdateWebspace($config){ $command = 'svn update'; $switches = '--non-interactive'; $switches .= GetSvnUsr($config); $switches .= GetSvnPw($config); $arg = $config->GetWebspaceRootDir(); static $result = NULL; if ($result == NULL){ $result = ExecSvnCmd($command, $arg, $switches); } return $result; } /** * Performs workspace (webspace) checkout * and returns the output of 'svn checkout' * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Result of svn checkout execution. * @see ExecSvnCmd * * @since v1.0.0 */ function CheckoutWebspace($config){ $trunk_path = $config->GetTrunkDir(); $command = 'svn checkout'; $switches = '--revision HEAD --non-interactive'; $switches .= GetSvnUsr($config); $switches .= GetSvnPw($config); $arg = $config->GetRepositoryRoot().'/'.$trunk_path; $arg = $arg.' '.$config->GetWebspaceRootDir(); return ExecSvnCmd($command, $arg); } /** * Performs webspace cleanup * and returns the output of svn cleanup * contained in a result array as produced * by ExecSvnCmd. * @param SwcConfig $config SWC config for the operation. * @return array Result of svn cleanup execution. * @see ExecSvnCmd * * @since v1.0.0 */ function &CleanupWebspace($config){ $command = 'svn cleanup'; $switches = '--non-interactive'; $switches .= GetSvnUsr($config); $switches .= GetSvnPw($config); $arg = $config->GetWebspaceRootDir(); $result = ExecSvnCmd($command, $arg); return $result; } /** * Switches webspace to given repository path. * @param SwcConfig $config SWC config for the operation. * @param string $path Repository path to switch to * A path without repository root should be applied. * @return array Result of svn switch execution. * @see ExecSvnCmd * * @since v1.0.0 */ function SwitchWebspace($config, $path){ if ($path == NULL){ $path = $config->GetTrunkDir(); } $command = 'svn switch'; $switches = '--non-interactive'; $switches .= GetSvnUsr($config); $switches .= GetSvnPw($config); $arg = $config->GetRepositoryRoot(); $arg .= '/'.$path; $arg .= ' '.$config->GetWebspaceRootDir(); return ExecSvnCmd($command, $arg); } /** * Returns the SVN User switch for the given config. * @param SwcConfig $config Config for retrieving user. * @return string svn switch for user (empty string if no user * is applied. * * @since v1.0.0 */ function GetSvnUsr($config){ $user = $config->GetSvnUser(); $switch = ''; if ($user != NULL && $user != ''){ $switch = ' --username '.$user; } return $switch; } /** * Returns the SVN password switch for the given config. * @param SwcConfig $config Config for retrieving user. * @return string svn switch for password (empty string if no password * is applied. * * @since v1.0.0 */ function GetSvnPw($config){ $pw = $config->GetSvnPassword(); $switch = ''; if ($pw != NULL && $pw != ''){ $switch = ' --password '.$pw; } return $switch; } /** * Executes an SVN command. * @param string $cmd Command to execute * @param string $switch Switches to be applied for the given command * @param string $arg Arguments of the command * @return array Result array containing commandline (idx = IDX_CMDLINE), * standard out array (idx = IDX_STDOUT), error array (idx = IDX_ERROUT), * and return code of the command (idx = IDX_CMD_RC). * * @since v1.0.0 */ function &ExecSvnCmd($cmd, $arg = '', $switches = ''){ $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("pipe", "w") // stderr is a pipe to write to ); $cwd = NULL; //'/tmp'; $pipes = NULL; $cmdline = $cmd." ".$switches." ".$arg; $output = shell_exec($cmdline); $result = array(); $result[IDX_CMDLINE] = $cmdline; if(strpos($switches, "xml")){ $result[IDX_STDOUT] = $output; }else{ $result[IDX_STDOUT] = split("\n", $output); } $result[IDX_ERROUT] = ""; /* $process = proc_open($cmdline, $descriptorspec, $pipes); $result = array(); $result[IDX_CMDLINE] = $cmdline; $result[IDX_STDOUT] = array(); $result[IDX_ERROUT] = array(); $result[IDX_CMD_RC] = -1; if (is_resource($process)) { // $pipes now looks like this: // 0 => writeable handle connected to child stdin // 1 => readable handle connected to child stdout // 2 => readable handle connected to child errout fclose($pipes[0]); $result = array(); $result[IDX_CMDLINE] = $cmdline; if(strpos($switches, "xml")){ $result[IDX_STDOUT] = GetLineString($pipes[1]); }else{ $result[IDX_STDOUT] = GetLineArray($pipes[1]); } fclose($pipes[1]); $result[IDX_ERROUT] = GetLineArray($pipes[2]); fclose($pipes[2]); // It is important that you close any pipes before calling // proc_close in order to avoid a deadlock $result[IDX_CMD_RC] = proc_close($process); // echo "CMD: $cmdline
    "; // PrintDebugArray($result, "Result"); } */ return $result; } /** * Reads data from a resource (e.g. pipe) and * returns an array that contains each line for a * separate index. * @param resource $handle Resource handle * @param int $length Maximum line length used if a line is not delimited. * @return array Array containing a delimited line per index. * * @since v1.0.0 */ function &GetLineArray($handle, $length = 4096){ $content = array(); $line = fgets($handle, $length); while ($line !== false){ $content[] = $line; $line = fgets($handle, $length); } return $content; } /** * Reads data from a resource (e.g. pipe) and * returns an array that contains each line for a * separate index. * @param resource $handle Resource handle * @param int $length Maximum line length used if a line is not delimited. * @return array Array containing a delimited line per index. * * @since v1.0.0 */ function &GetLineString($handle, $length = 4096){ $content = ""; $line = fgets($handle, $length); while ($line !== false){ $content .= $line; $line = fgets($handle, $length); } return $content; } /** * Returns a string of the given array that is * encapsulated within $startstr and $endstr. * @param array $array Line array as provided by 'GetLineArray' to * search the string within. * @param string $startstr String to search. * @param string $endstr String to delimit search. If NULL, the returned string * is not delimited. * @return string String within a 'line' of $array that starts with '$startstr' * and ends with '$endstr'. If $startstr is not found, '?' is returned. $startstr * is not returned. * * @since v1.0.0 */ function ParseArray (&$array, $startstr, $endstr = NULL){ $idx = 0; while ($idx < count($array) && strpos($array[$idx], $startstr) === false){ $idx++; } $val = '?'; if ($idx < count($array)){ $start = strpos($array[$idx], $startstr) + strlen($startstr); if ($endstr != NULL){ $len = strpos($array[$idx], $endstr) - $start; $val = substr($array[$idx], $start, $len); } else { $val = substr($array[$idx], $start); } $val = trim($val); } return $val; } /** * HTML and user friendly output of an array. * @param array $array Array to print * @param string $name Name of the array, also printed. * @param boolean $encode_html_chars Whether or not to * encode special characters to HTML equivalents (default). * @version v.1.1.0 * @since v1.0.0 */ function PrintArray($array, $name = '', $encode_html_chars = true){ if (is_array($array)){ if (strlen($name) > 0){ echo ''.$name.'
    '; } echo '
    ';
    			foreach($array as $line){
    				if ($encode_html_chars){
    					echo htmlspecialchars($line);
    				} else {
    					echo ($line);
    				}
    			}
    			echo '
    '; } } ?> AjaXplorer/AjaXplorer/plugins/ajxp.remote_fs/0000777000000000000000000000000011300346030022456 5ustar adminadministratorsAjaXplorer/AjaXplorer/plugins/ajxp.remote_fs/remote_fs_icon.png0000766000000000000000000000157611122202524026172 0ustar adminadministratorsPNG  IHDRagAMA75IDATxmKL\u1s;S`Z"2 QIdhPCMWMh\ǢIƸָ11q4i1M`AR3j@[#S@ {;s.os|'H<+w_=7jۅ0gn;at1̉b,*eS!D,Dt$>1pwh,-͆o"0&%r"ˊ)>r2]tKovfFl o)sr!1+x;zZJ pP`8Niw"4$I&ez6L6o Թ6Nr3o;g"Łt*gIENDB`AjaXplorer/AjaXplorer/plugins/ajxp.remote_fs/class.remote_fsDriver.php0000766000000000000000000001761611122202524027447 0ustar adminadministratorsactions["upload"]); // ADD additional actions $this->xmlFilePath = INSTALL_PATH."/plugins/ajxp.remote_fs/additionalActions.xml"; $this->parseXMLActions(); } function switchAction($action, $httpVars, $filesVars){ $sessionId = ""; $crtRep = ConfService::getRepository(); $httpClient = $this->getRemoteConnexion($sessionId); $httpVars["ajxp_sessid"] = $sessionId; $method = "get"; if($action == "edit" && isSet($httpVars["save"])) $method = "post"; if($method == "get"){ if($action == "download" || $action=="image_proxy" || $action=="mp3_proxy"){ $httpClient->directForwarding = true; } $httpClient->get($crtRep->getOption("URI"), $httpVars); }else{ $httpClient->post($crtRep->getOption("URI"), $httpVars); } // check if session is expired if(strpos($httpClient->getHeader("content-type"), "text/xml") !== false && strpos($httpClient->getContent(), "require_auth") != false){ $httpClient = $this->getRemoteConnexion($sessionId, true); $httpVars["ajxp_sessid"] = $sessionId; $method = "get"; if($method == "get"){ if($action == "download"){ $httpClient->directForwarding = true; } $httpClient->get($crtRep->getOption("URI"), $httpVars); }else{ $httpClient->post($crtRep->getOption("URI"), $httpVars); } } switch ($action){ case "image_proxy": case "download": case "mp3_proxy": session_write_close(); exit(); break; case "edit": header("Content-type:text/plain"); break; default: header("Content-type: text/xml"); break; } print $httpClient->getContent(); session_write_close(); exit(); } function uploadActions($action, $httpVars, $filesVars){ switch ($action){ case "trigger_remote_copy": if(!$this->hasFilesToCopy()) break; $toCopy = $this->getFileNameToCopy(); AJXP_XMLWriter::header(); AJXP_XMLWriter::triggerBgAction("next_to_remote", array(), "Copying file ".$toCopy." to remote server"); AJXP_XMLWriter::close(); exit(1); break; case "next_to_remote": if(!$this->hasFilesToCopy()) break; $fData = $this->getNextFileToCopy(); $nextFile = ''; if($this->hasFilesToCopy()){ $nextFile = $this->getFileNameToCopy(); } $crtRep = ConfService::getRepository(); session_write_close(); $sessionId = ""; $httpClient = $this->getRemoteConnexion($sessionId); //$httpClient->setDebug(true); $postData = array( "get_action"=>"upload", "dir"=>$fData["destination"]); $httpClient->postFile($crtRep->getOption("URI")."?ajxp_sessid=$sessionId", $postData, "Filedata", $fData); if(strpos($httpClient->getHeader("content-type"), "text/xml") !== false && strpos($httpClient->getContent(), "require_auth") != false){ $httpClient = $this->getRemoteConnexion($sessionId, true); $postData["ajxp_sessid"] = $sessionId; $httpClient->postFile($crtRep->getOption("URI"), $postData, "Filedata", $fData); } unlink($fData["tmp_name"]); $response = $httpClient->getContent(); AJXP_XMLWriter::header(); if(intval($response)>=400){ AJXP_XMLWriter::sendMessage(null, "Error : ".intval($response)); }else{ if($nextFile!=''){ AJXP_XMLWriter::triggerBgAction("next_to_remote", array(), "Copying file ".$nextFile." to remote server"); }else{ AJXP_XMLWriter::sendMessage("Done", null); } } AJXP_XMLWriter::close(); exit(1); break; case "upload": if(isSet($httpVars['dir']) && $httpVars['dir']!=""){$rep_source=$httpVars['dir'];} else $rep_source = "/"; $logMessage = ""; $fancyLoader = false; foreach ($filesVars as $boxName => $boxData) { if($boxName != "Filedata" && substr($boxName, 0, 9) != "userfile_") continue; if($boxName == "Filedata") $fancyLoader = true; $err = Utils::parseFileDataErrors($boxData, $fancyLoader); if($err != null) { $errorMessage = $err; break; } $boxData["destination"] = $rep_source; $destCopy = INSTALL_PATH."/".$this->repository->getOption("TMP_UPLOAD"); if(!is_dir($destCopy)){ if(! @mkdir($destCopy)){ $errorMessage = "Warning, cannot create folder for temporary copy."; break; } } if(!is_writeable($destCopy)){ $errorMessage = "Warning, cannot write into temporary folder."; break; } $destName = $destCopy."/".basename($boxData["tmp_name"]); if(move_uploaded_file($boxData["tmp_name"], $destName)){ $boxData["tmp_name"] = $destName; $this->storeFileToCopy($boxData); }else{ $mess = ConfService::getMessages(); $errorMessage=($fancyLoader?"411 ":"")."$mess[33] ".$boxData["name"]; } } if($fancyLoader) { session_write_close(); if(isSet($errorMessage)){ header('HTTP/1.0 '.$errorMessage); die('Error '.$errorMessage); }else{ header('HTTP/1.0 200 OK'); die("200 OK"); } } else { print(""); } session_write_close(); exit; break; default: break; } } /** * @return HttpClient */ function getRemoteConnexion(&$remoteSessionId, $refreshSessId=false){ require_once(INSTALL_PATH."/server/classes/class.HttpClient.php"); $crtRep = ConfService::getRepository(); $httpClient = new HttpClient($crtRep->getOption("HOST")); $httpClient->cookie_host = $crtRep->getOption("HOST"); $httpClient->timeout = 50; //$httpClient->setDebug(true); if($crtRep->getOption("AUTH_URI") != ""){ $httpClient->setAuthorization($crtRep->getOption("AUTH_NAME"), $crtRep->getOption("AUTH_PASS")); } if(!isSet($_SESSION["AJXP_REMOTE_SESSION"]) || $refreshSessId){ $httpClient->setHeadersOnly(true); $httpClient->get($crtRep->getOption("AUTH_URI")); $httpClient->setHeadersOnly(false); $cookies = $httpClient->getCookies(); if(isSet($cookies["PHPSESSID"])){ $_SESSION["AJXP_REMOTE_SESSION"] = $cookies["PHPSESSID"]; $remoteSessionId = $cookies["PHPSESSID"]; } }else{ $remoteSessionId = $_SESSION["AJXP_REMOTE_SESSION"]; $httpClient->setCookies(array("PHPSESSID"=>$remoteSessionId)); } return $httpClient; } function storeFileToCopy($fileData){ $user = AuthService::getLoggedUser(); $files = $user->loadUserFile("tmp_upload"); $files[] = $fileData; $user->saveUserFile("tmp_upload", $files); } function getFileNameToCopy(){ $user = AuthService::getLoggedUser(); $files = $user->loadUserFile("tmp_upload"); return $files[0]["name"]; } function getNextFileToCopy(){ if(!$this->hasFilesToCopy()) return ""; $user = AuthService::getLoggedUser(); $files = $user->loadUserFile("tmp_upload"); $fData = $files[0]; array_shift($files); $user->saveUserFile("tmp_upload", $files); return $fData; } function hasFilesToCopy(){ $user = AuthService::getLoggedUser(); $files = $user->loadUserFile("tmp_upload"); return (count($files)?true:false); } function sendInfoPanelsDef(){ $fileData = file_get_contents(INSTALL_PATH."/plugins/ajxp.fs/fsActions.xml"); $matches = array(); preg_match('/.*<\/infoPanels>/', str_replace("\n", "",$fileData), $matches); if(count($matches)){ AJXP_XMLWriter::header(); AJXP_XMLWriter::write($this->replaceAjxpXmlKeywords(str_replace("\n", "",$matches[0])), true); AJXP_XMLWriter::close(); exit(1); } } } ?>AjaXplorer/AjaXplorer/plugins/ajxp.remote_fs/additionalActions.xml0000766000000000000000000000744111122202524026641 0ustar adminadministrators = 8 && document.location.href.substring(0,5)!='https') { modal.setCloseAction(function(){ $('closeFlashUploadBox').disabled=false; var bgManager = ajaxplorer.actionBar.bgManager; bgManager.queueAction("trigger_remote_copy", new Hash(), "Copying files to server"); bgManager.next(); }); modal.showDialogForm('Upload', 'flash_upload_form', null, function(){ hideLightBox(); return false; }, null, true, true); } else { $('hidden_frames').innerHTML = ''; var onLoadFunction = function(oForm){ this.multi_selector = new MultiSelector(oForm, oForm.getElementsBySelector('div.uploadFilesList')[0], '6' ); this.multi_selector.addElement(oForm.getElementsBySelector('.dialogFocus')[0]); var rep = document.createElement('input'); rep.setAttribute('type', 'hidden'); rep.setAttribute('name', 'dir'); rep.setAttribute('value', ajaxplorer.getFilesList().getCurrentRep()); oForm.appendChild(rep); }.bind(ajaxplorer.actionBar); modal.setCloseAction(function(){ ajaxplorer.filesList.reload(); var bgManager = ajaxplorer.actionBar.bgManager; bgManager.queueAction("trigger_remote_copy", new Hash(), "Copying files to server"); bgManager.next(); }); modal.showDialogForm('Upload', 'originalUploadForm', onLoadFunction, function(){ajaxplorer.actionBar.multi_selector.submitMainForm();return false;}); } ]]>
    ]]>
    AjaXplorer/AjaXplorer/plugins/ajxp.remote_fs/manifest.xml0000766000000000000000000000247111122202524025014 0ustar adminadministrators AjaXplorer/AjaXplorer/index.php0000766000000000000000000000673611122202530017704 0ustar adminadministratorscanRead(ConfService::getCurrentRootDirIndex()) && AuthService::getDefaultRootId() != ConfService::getCurrentRootDirIndex()) { ConfService::switchRootDir(AuthService::getDefaultRootId()); } } $ROOT_DIR_NAME = "null"; $ROOT_DIR_ID = "null"; $ROOT_DIRS_LIST = "null"; $ROOT_DIRS_SETTINGS = "null"; } else { $ROOT_DIR_NAME = ConfService::getCurrentRootDirDisplay(); $ROOT_DIR_ID = ConfService::getCurrentRootDirIndex(); $ROOT_DIRS_LIST = HTMLWriter::writeRootDirListAsJsString(ConfService::getRootDirsList()); $ROOT_DIRS_SETTINGS = HTMLWriter::writeRepoSettingsAsJS(ConfService::getRootDirsList()); } $EXT_REP = "/"; if(isSet($_GET["folder"])) $EXT_REP = urldecode($_GET["folder"]); $CRT_USER = "shared_bookmarks"; if(isSet($_GET["user"])) $CRT_USER = $_GET["user"]; $ZIP_ENABLED = (ConfService::zipEnabled()?"true":"false"); $loggedUser = AuthService::getLoggedUser(); $DEFAULT_DISPLAY = "list"; if($loggedUser != null && $loggedUser->getId() != "guest") { if($loggedUser->getPref("lang") != "") ConfService::setLanguage($loggedUser->getPref("lang")); if($loggedUser->getPref("display") != "") $DEFAULT_DISPLAY = $loggedUser->getPref("display"); } else { if(isSet($_COOKIE["AJXP_lang"])) ConfService::setLanguage($_COOKIE["AJXP_lang"]); if(isSet($_COOKIE["AJXP_display"]) && ($_COOKIE["AJXP_display"]=="list" || $_COOKIE["AJXP_display"]=="thumb")) $DEFAULT_DISPLAY = $_COOKIE["AJXP_display"]; } if(isSet($_GET["compile"])){ require_once(SERVER_RESOURCES_FOLDER."/class.AJXP_JSPacker.php"); AJXP_JSPacker::pack(); } $JS_DEBUG = false; $mess = ConfService::getMessages(); if($JS_DEBUG){ include_once(CLIENT_RESOURCES_FOLDER."/html/gui.html"); }else{ include_once(CLIENT_RESOURCES_FOLDER."/html/gui-z.html"); } HTMLWriter::writeI18nMessagesClass($mess); include_once(ConfService::getConf("BOTTOM_PAGE")); ?> AjaXplorer/AjaXplorer/content.php0000766000000000000000000001526311122202530020242 0ustar adminadministratorscanRead(ConfService::getCurrentRootDirIndex()) && AuthService::getDefaultRootId() != ConfService::getCurrentRootDirIndex()) { ConfService::switchRootDir(AuthService::getDefaultRootId()); } } if($loggedUser == null) { $requireAuth = true; } if(isset($loggingResult) || (isSet($_GET["get_action"]) && $_GET["get_action"] == "logged_user")) { AJXP_XMLWriter::header(); if(isSet($loggingResult)) AJXP_XMLWriter::loggingResult($loggingResult, $rememberLogin, $rememberPass); AJXP_XMLWriter::sendUserData(); AJXP_XMLWriter::close(); exit(1); } } $loggedUser = AuthService::getLoggedUser(); if($loggedUser != null) { if($loggedUser->getPref("lang") != "") ConfService::setLanguage($loggedUser->getPref("lang")); } $mess = ConfService::getMessages(); foreach($_GET as $getName=>$getValue) { $$getName = Utils::securePath($getValue); } foreach($_POST as $getName=>$getValue) { $$getName = Utils::securePath($getValue); } $selection = new UserSelection(); $selection->initFromHttpVars(); if(isSet($action) || isSet($get_action)) $action = (isset($get_action)?$get_action:$action); else $action = ""; if(isSet($dir) && $action != "upload") $dir = SystemTextEncoding::fromUTF8($dir); if(isSet($dest)) $dest = SystemTextEncoding::fromUTF8($dest); //------------------------------------------------------------ // SPECIAL HANDLING FOR FANCY UPLOADER RIGHTS FOR THIS ACTION //------------------------------------------------------------ if(AuthService::usersEnabled()) { $loggedUser = AuthService::getLoggedUser(); if($action == "upload" && ($loggedUser == null || !$loggedUser->canWrite(ConfService::getCurrentRootDirIndex()."")) && isSet($_FILES['Filedata'])) { header('HTTP/1.0 ' . '410 Not authorized'); die('Error 410 Not authorized!'); } } // FIRST INIT STD DRIVER $ajxpDriver = new AJXP_ClientDriver(ConfService::getRepository()); if($ajxpDriver->hasAction($action)){ $xmlBuffer = $ajxpDriver->applyAction($action, array_merge($_GET, $_POST), $_FILES); if($xmlBuffer != ""){ AJXP_XMLWriter::header(); AJXP_XMLWriter::write($xmlBuffer, true); AJXP_XMLWriter::close(); exit(1); } } // INIT DRIVER $Driver = ConfService::getRepositoryDriver(); if($Driver == null || !is_a($Driver, "AbstractDriver")){ AJXP_XMLWriter::header(); if(is_a($Driver, "AJXP_Exception")){ AJXP_XMLWriter::sendMessage(null, "Cannot initialize driver : ".$Driver->getMessage()); }else{ AJXP_XMLWriter::sendMessage(null, "Cannot find driver!"); } AJXP_XMLWriter::close(); exit(1); } if($Driver->hasAction($action)){ // CHECK RIGHTS if(AuthService::usersEnabled()){ $loggedUser = AuthService::getLoggedUser(); if( $Driver->actionNeedsRight($action, "r") && ($loggedUser == null || !$loggedUser->canRead(ConfService::getCurrentRootDirIndex().""))){ AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, $mess[208]); AJXP_XMLWriter::requireAuth(); AJXP_XMLWriter::close(); exit(1); } if( $Driver->actionNeedsRight($action, "w") && ($loggedUser == null || !$loggedUser->canWrite(ConfService::getCurrentRootDirIndex().""))){ AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, $mess[207]); AJXP_XMLWriter::requireAuth(); AJXP_XMLWriter::close(); exit(1); } } $xmlResult = $Driver->applyAction($action, array_merge($_GET, $_POST), $_FILES); if($xmlResult != ""){ AJXP_XMLWriter::header(); print($xmlResult); AJXP_XMLWriter::close(); exit(1); } } AJXP_XMLWriter::header(); if(isset($logMessage) || isset($errorMessage)) { AJXP_XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null)); } if(isset($requireAuth)) { AJXP_XMLWriter::requireAuth(); } if(isset($reload_current_node) && $reload_current_node == "true") { AJXP_XMLWriter::reloadCurrentNode(); } if(isset($reload_dest_node) && $reload_dest_node != "") { AJXP_XMLWriter::reloadNode($reload_dest_node); } if(isset($reload_file_list)) { AJXP_XMLWriter::reloadFileList($reload_file_list); } AJXP_XMLWriter::close(); session_write_close(); ?> AjaXplorer/AjaXplorer/server/0000777000000000000000000000000011300346034017363 5ustar adminadministratorsAjaXplorer/AjaXplorer/server/logs/0000777000000000000000000000000011300352654020334 5ustar adminadministratorsAjaXplorer/AjaXplorer/server/classes/0000777000000000000000000000000011300346033021017 5ustar adminadministratorsAjaXplorer/AjaXplorer/server/classes/class.HTMLWriter.php0000766000000000000000000000756011122202526024606 0ustar adminadministrators
    ".(isset($logMessage)?$logMessage:$errorMessage)."".$mess[98]."
    "; echo ""; } function bookmarkBar($allBookmarks) { //echo '
    MyBookmarks  
    '; $mess = ConfService::getMessages(); foreach (array_reverse($allBookmarks) as $path) { if(is_array($path)) $path = $path["PATH"]; echo ''; } } function getDocFile($docFileName) { $realName = INSTALL_PATH."/".DOCS_FOLDER."/".$docFileName.".txt"; if(is_file($realName)) { $string = ""; $content = implode("
    ", file($realName)); $content = preg_replace("(http:\/\/[a-z|.|\/|\-|0-9]*)", "$0", $content); $content = preg_replace("(\[(.*)\])", "
    $1
    ", $content); $content = preg_replace("(\+\+ (.*) \+\+)", "
    $1
    ", $content); $content = str_replace("__AJXP_VERSION__", AJXP_VERSION, $content); $content = str_replace("__AJXP_VERSION_DATE__", AJXP_VERSION_DATE, $content); $string .= $content.""; return $string; } return "File not found : ".$docFileName; } function writeRootDirListAsJsString($rootDirsList) { $buffer = "\$H({"; $parts = array(); foreach ($rootDirsList as $rIndex => $rObject) { $parts[] = "\"$rIndex\":'".$rObject->getDisplay()."'"; //if($rIndex < count($rootDirsList)-1) $buffer .= ", "; } $buffer.=join(", ", $parts); $buffer .= "})"; return $buffer; } function writeRepoSettingsAsJS($rootDirsList){ $buffer = "\$H({"; $hashParts = array(); foreach ($rootDirsList as $rIndex => $rObject) { //$buffer .= "$rIndex:"; $props = $rObject->getClientSettings(); $hashParts[] = "\"$rIndex\":\$H({".str_replace(array(" ", "\"", "="), array(",", "'", ":"), trim($props))."})"; //if($rIndex < count($rootDirsList)-1) $buffer .= ", "; } $buffer .= join(", ", $hashParts); $buffer .= "})"; return $buffer; } function writeI18nMessagesClass($mess) { echo "\n"; } } ?> AjaXplorer/AjaXplorer/server/classes/class.ConfService.php0000766000000000000000000002131111122202526025041 0ustar adminadministratorsgetDisplay(); } /** * @param array $repositories * @return array */ function initRepositoriesList($defaultRepositories) { $objList = array(); foreach($defaultRepositories as $index=>$repository) { $repo = ConfService::createRepositoryFromArray($index, $repository); $repo->setWriteable(false); $objList[$repo->getUniqueId()] = $repo; } $confRepo = ConfService::loadRepoFile(); foreach ($confRepo as $repo){ $repo->setWriteable(true); $objList[$repo->getUniqueId()] = $repo; } return $objList; } /** * Create a repository object from a config options array * * @param integer $index * @param Array $repository * @return Repository */ function createRepositoryFromArray($index, $repository){ $repo = new Repository($index, $repository["DISPLAY"], $repository["DRIVER"]); if(array_key_exists("DRIVER_OPTIONS", $repository) && is_array($repository["DRIVER_OPTIONS"])){ foreach ($repository["DRIVER_OPTIONS"] as $oName=>$oValue){ $repo->addOption($oName, $oValue); } } // BACKWARD COMPATIBILITY! if(array_key_exists("PATH", $repository)){ $repo->addOption("PATH", $repository["PATH"]); $repo->addOption("CREATE", $repository["CREATE"]); $repo->addOption("RECYCLE_BIN", $repository["RECYCLE_BIN"]); } return $repo; } /** * Add dynamically created repository * * @param Repository $oRepository * @return -1 if error */ function addRepository($oRepository){ // update list $confRepoList = ConfService::loadRepoFile(); $confRepoList[] = $oRepository; $res = ConfService::saveRepoFile($confRepoList); if($res == -1){ return $res; } AJXP_Logger::logAction("Create Repository", array("repo_name"=>$oRepository->getDisplay())); global $G_DEFAULT_REPOSITORIES, $G_REPOSITORIES; $G_REPOSITORIES = ConfService::initRepositoriesList($G_DEFAULT_REPOSITORIES); } function deleteRepository($repoLabel){ $confRepoList = ConfService::loadRepoFile(); $newList = array(); foreach ($confRepoList as $repo){ if($repo->getDisplay() == $repoLabel){ continue; } $newList[] = $repo; } $res = ConfService::saveRepoFile($newList); if($res == -1){ return $res; } AJXP_Logger::logAction("Delete Repository", array("repo_name"=>$repoLabel)); global $G_DEFAULT_REPOSITORIES, $G_REPOSITORIES; $G_REPOSITORIES = ConfService::initRepositoriesList($G_DEFAULT_REPOSITORIES); } function zipEnabled() { return (function_exists("gzopen")?true:false); } function getMessages() { global $G_MESSAGES, $G_LANGUE; if(!isset($G_MESSAGES)) { require(INSTALL_PATH."/".CLIENT_RESOURCES_FOLDER."/i18n/${G_LANGUE}.php"); $G_MESSAGES = $mess; } return $G_MESSAGES; } function listAvailableLanguages(){ // Cache in session! if(isSet($_SESSION["AJXP_LANGUAGES"]) && !isSet($_GET["refresh_langs"])){ return $_SESSION["AJXP_LANGUAGES"]; } $langDir = INSTALL_PATH."/".CLIENT_RESOURCES_FOLDER."/i18n"; $languages = array(); if($dh = opendir($langDir)){ while (($file = readdir($dh)) !== false) { $matches = array(); if(preg_match("/(.*)\.php/", $file, $matches) == 1){ $fRadical = $matches[1]; include($langDir."/".$fRadical.".php"); $langName = isSet($mess["languageLabel"])?$mess["languageLabel"]:"Not Found"; $languages[$fRadical] = $langName; } } closedir($dh); } if(count($languages)){ $_SESSION["AJXP_LANGUAGES"] = $languages; } return $languages; } function getConf($varName) { global $G_LANGUE,$G_AVAILABLE_LANG,$G_MESSAGES,$G_USE_HTTPS,$G_WM_EMAIL,$G_SIZE_UNIT,$G_MAX_CHAR,$G_SHOW_HIDDEN,$G_BOTTOM_PAGE, $G_UPLOAD_MAX_NUMBER, $G_UPLOAD_MAX_TOTAL, $G_UPLOAD_MAX_FILE; $globVarName = "G_".$varName; return $$globVarName; } function setLanguage($lang) { global $G_LANGUE, $G_AVAILABLE_LANG; if(array_key_exists($lang, $G_AVAILABLE_LANG)) { $G_LANGUE = $lang; } } function getLanguage() { global $G_LANGUE; return $G_LANGUE; } /** * @return Repository */ function getRepository() { global $G_REPOSITORY; return $G_REPOSITORY; } /** * Returns the repository access driver * * @return AbstractDriver */ function getRepositoryDriver() { global $G_ACCESS_DRIVER; if(isSet($G_ACCESS_DRIVER) && is_a($G_ACCESS_DRIVER, "AbstractDriver")){ return $G_ACCESS_DRIVER; } ConfService::switchRootDir(); $crtRepository = ConfService::getRepository(); $accessType = $crtRepository->getAccessType(); $driverName = $accessType."Driver"; $path = INSTALL_PATH."/plugins/ajxp.".$accessType; $filePath = $path."/class.".$driverName.".php"; $xmlPath = $path."/".$accessType."Actions.xml"; if(is_file($filePath)){ include_once($filePath); if(class_exists($driverName)){ $G_ACCESS_DRIVER = new $driverName($accessType, $xmlPath, $crtRepository); $res = $G_ACCESS_DRIVER->initRepository(); if($res!=null && is_a($res, "AJXP_Exception")){ $G_ACCESS_DRIVER = null; return $res; } return $G_ACCESS_DRIVER; } } } function availableDriversToXML(){ $manifests = array(); $base = INSTALL_PATH."/plugins"; $xmlString = ""; if($fp = opendir($base)){ while (($subdir = readdir($fp))!==false) { $manifName = $base."/".$subdir."/manifest.xml"; if(is_file($manifName) && is_readable($manifName)){ $lines = file($manifName); array_shift($lines);// Remove first line (xml declaration); $xmlString .= implode("", $lines); } } closedir($fp); } return str_replace("\t", "", str_replace("\n", "", $xmlString)); } function loadRepoFile(){ $result = array(); if(is_file(INSTALL_PATH."/server/conf/repo.ser")) { $fileLines = file(INSTALL_PATH."/server/conf/repo.ser"); $result = unserialize($fileLines[0]); } return $result; } function saveRepoFile($value){ if(!is_writeable(INSTALL_PATH."/server/conf")) return -1; $fp = @fopen(INSTALL_PATH."/server/conf/repo.ser", "w"); fwrite($fp, serialize($value)); fclose($fp); } } ?> AjaXplorer/AjaXplorer/server/classes/class.Repository.php0000766000000000000000000000535611122202526025025 0ustar adminadministratorssetAccessType($driver); $this->setDisplay($display); $this->setId($id); } function getUniqueId(){ return md5(serialize($this)); } function getClientSettings(){ $fileName = INSTALL_PATH."/plugins/ajxp.".$this->accessType."/manifest.xml"; $settingLine = ""; if(is_readable($fileName)){ $lines = file($fileName); foreach ($lines as $line){ if(eregi("client_settings", trim($line)) > -1){ $settingLine = str_replace(array(""), "", trim($line)); } } } return $settingLine; } function addOption($oName, $oValue){ if(strpos($oName, "PATH") !== false){ $oValue = str_replace("\\", "/", $oValue); } $this->options[$oName] = $oValue; } function getOption($oName){ if(isSet($this->options[$oName])){ $value = $this->options[$oName]; if(is_string($value) && strpos($value, "AJXP_USER")!==false){ if(AuthService::usersEnabled()){ $loggedUser = AuthService::getLoggedUser(); if($loggedUser != null){ $loggedUser = $loggedUser->getId(); $value = str_replace("AJXP_USER", $loggedUser, $value); }else{ return ""; } }else{ $value = str_replace("AJXP_USER", "shared", $value); } } if(is_string($value) && strpos($value, "AJXP_INSTALL_PATH") !== false){ $value = str_replace("AJXP_INSTALL_PATH", INSTALL_PATH, $value); } return $value; } return ""; } /** * @return String */ function getAccessType() { return $this->accessType; } /** * @return String */ function getDisplay() { return $this->display; } /** * @return int */ function getId() { return $this->id; } /** * @return boolean */ function getCreate() { return $this->getOption("CREATE"); } /** * @param boolean $create */ function setCreate($create) { $this->options["CREATE"] = $create; } /** * @param String $accessType */ function setAccessType($accessType) { $this->accessType = $accessType; } /** * @param String $display */ function setDisplay($display) { $this->display = $display; } /** * @param int $id */ function setId($id) { $this->id = $id; } function isWriteable(){ return $this->writeable; } function setWriteable($w){ $this->writeable = $w; } function isEnabled(){ return $this->enabled; } function setEnabled($e){ $this->enabled = $e; } } ?> AjaXplorer/AjaXplorer/server/classes/class.AJXP_XMLWriter.php0000766000000000000000000000724411122202526025323 0ustar adminadministrators'); print("<$docNode>"); } function close($docNode="tree") { print(""); } function write($data, $print){ if($print) { print($data); return ""; }else{ return $data; } } function reloadCurrentNode($print = true) { return AJXP_XMLWriter::write("", $print); } function reloadNode($nodeName, $print = true) { return AJXP_XMLWriter::write("", $print); } function requireAuth($print = true) { return AJXP_XMLWriter::write("", $print); } function triggerBgAction($actionName, $parameters, $messageId, $print=true){ $data = AJXP_XMLWriter::write("", $print); foreach ($parameters as $paramName=>$paramValue){ $data .= AJXP_XMLWriter::write("", $print); } $data .= AJXP_XMLWriter::write("", $print); return $data; } function reloadFileList($fileOrBool, $print = true) { if(is_string($fileOrBool)) return AJXP_XMLWriter::write("", $print); else return AJXP_XMLWriter::write("", $print); } function writeBookmarks($allBookmarks) { foreach ($allBookmarks as $bookmark) { $path = ""; $title = ""; if(is_array($bookmark)){ $path = $bookmark["PATH"]; $title = $bookmark["TITLE"]; }else if(is_string($bookmark)){ $path = $bookmark; $title = basename($bookmark); } print(""); } } function sendMessage($logMessage, $errorMessage, $print = true) { $messageType = ""; $message = ""; if($errorMessage == null) { $messageType = "SUCCESS"; $message = $logMessage; } else { $messageType = "ERROR"; $message = $errorMessage; } return AJXP_XMLWriter::write("".$message."", $print); } function sendUserData() { $loggedUser = AuthService::getLoggedUser(); if($loggedUser != null) { print("id."\">"); print("canWrite(ConfService::getCurrentRootDirIndex())?"1":"0")."\" read=\"".($loggedUser->canRead(ConfService::getCurrentRootDirIndex())?"1":"0")."\"/>"); print(""); foreach (ConfService::getRootDirsList() as $rootDirIndex => $rootDirObject) { $iconString = ""; if($loggedUser->canRead($rootDirIndex)) print("getClientSettings().">".SystemTextEncoding::toUTF8($rootDirObject->getDisplay()).""); } print(""); print(""); print("getPref("display")."\"/>"); print("getPref("lang")."\"/>"); print(""); print(""); } } function loggingResult($result, $rememberLogin="", $rememberPass = "") { $remString = ""; if($rememberPass != "" && $rememberLogin!= ""){ $remString = " remember_login=\"$rememberLogin\" remember_pass=\"$rememberPass\""; } print(""); } } ?> AjaXplorer/AjaXplorer/server/classes/class.UserSelection.php0000766000000000000000000000436111122202526025425 0ustar adminadministratorsfiles = array(); } function initFromHttpVars($passedArray=null) { if($passedArray != null){ $this->initFromArray($passedArray); }else{ $this->initFromArray($_GET); $this->initFromArray($_POST); } } function initFromArray($array) { if(!is_array($array)) { return ; } if(isSet($array[$this->varPrefix]) && $array[$this->varPrefix] != "") { $this->files[] = SystemTextEncoding::fromUTF8($array[$this->varPrefix]); $this->isUnique = true; //return ; } if(isSet($array[$this->varPrefix."_0"])) { $index = 0; while(isSet($array[$this->varPrefix."_".$index])) { $this->files[] = SystemTextEncoding::fromUTF8($array[$this->varPrefix."_".$index]); $index ++; } $this->isUnique = false; if(count($this->files) == 1) { $this->isUnique = true; } //return ; } if(isSet($array[$this->dirPrefix])){ $this->dir = $array[$this->dirPrefix]; if($test = $this->detectZip($this->dir)){ $this->inZip = true; $this->zipFile = $test[0]; $this->localZipPath = $test[1]; } } } function isUnique() { return $this->isUnique; } function inZip(){ return $this->inZip; } function getZipPath(){ return $this->zipFile; } function getZipLocalPath(){ return $this->localZipPath; } function getCount() { return count($this->files); } function getFiles() { return $this->files; } function getUniqueFile() { return $this->files[0]; } function isEmpty() { if(count($this->files) == 0) { return true; } return false; } function detectZip($dirPath){ $contExt = strpos(strtolower($dirPath), ".zip"); if($contExt !== false){ $zipPath = substr($dirPath, 0, $contExt+4); $localPath = substr($dirPath, $contExt+4); if($localPath == "") $localPath = "/"; return array($zipPath, $localPath); } return false; } function setFiles($files){ $this->files = $files; } } ?> AjaXplorer/AjaXplorer/server/classes/class.AJXP_JSPacker.php0000766000000000000000000000242511122202526025124 0ustar adminadministratorspack(); if($mode == "None"){ // css case, hack for I.E. $packed = str_replace("solid#", "solid #", $packed); } @file_put_contents($out, $packed); return true; } } ?>AjaXplorer/AjaXplorer/server/classes/class.AJXP_Logger.php0000766000000000000000000001217511122202526024704 0ustar adminadministrators "Debug", INFO => "Info", NOTICE => "Notice", WARNING => "Warning", ERROR => "Error"); */ /** * AJXP_Logger constructor * * @access private */ function AJXP_Logger() { $this->severityDescription = 0; if (!file_exists(LOCAL_STORAGE_DIR)) { @mkdir(LOCAL_STORAGE_DIR, LOG_GROUP_RIGHTS); } $this->fileHandle = fopen(LOCAL_STORAGE_DIR . LOG_FILE_NAME, "at+"); if ($this->fileHandle === false) { //print "Failed to obtain a handle to log file '" . LOG_FILE_NAME . "'"; } } function logAction($action, $params=array()){ $logger = AJXP_Logger::getInstance(); $message = "$action\t"; if(count($params)){ $message.=$logger->arrayToString($params); } $logger->write($message, LOG_LEVEL_INFO); $logger->close(); } function arrayToString($params){ $st = ""; $index=0; foreach ($params as $key=>$value){ $index++; if(!is_numeric($key)){ $st.="$key="; } if(is_string($value)){ $st.=$value; }else if(is_array($value)){ $st.=$this->arrayToString($value); }else if(is_bool($value)){ $st.=($value?"true":"false"); }else if(is_a($value, "UserSelection")){ $st.=$this->arrayToString($value->getFiles()); } if($index < count($params)){ if(is_numeric($key)){ $st.=","; }else{ $st.=";"; } } } return $st; } /** * returns an instance of the AJXP_Logger object * * @access public * @static * * @return AJXP_Logger an instance of the AJXP_Logger object */ function getInstance() { global $AJXP_LOGGER; if (!isset($AJXP_LOGGER)) { $AJXP_LOGGER = new AJXP_Logger(); } return $AJXP_LOGGER; } function write($textMessage, $severityLevel = LOG_LEVEL_DEBUG) { $textMessage = $this->formatMessage($textMessage, $severityLevel); if ($this->fileHandle !== false) { if (@fwrite($this->fileHandle, $textMessage) === false) { //print "There was an error writing to log file."; } } } /** * closes the handle to the log file * * @access public */ function close() { $success = @fclose($this->fileHandle); if ($success === false) { // Failure to close the log file $this->write("AJXP_Logger failed to close the handle to the log file", LOG_LEVEL_ERROR); } } /** * formats the error message in representable manner * * @param message this is the message to be formatted * * @return $severity Severity level of the message */ function formatMessage($message, $severity) { $msg = date("m-d-y") . " " . date("G:i:s") . "\t"; $msg .= $_SERVER['REMOTE_ADDR']; $msg .= "\t".strtoupper($severity)."\t"; // Get the user if it exists $user = "No User"; if(AuthService::usersEnabled()){ $logged = AuthService::getLoggedUser(); if($logged != null){ $user = $logged->getId(); }else{ $user = "shared"; } } $msg .= "$user\t"; //$msg .= $severity; $msg .= "" . $message . "\n"; return $msg; } function xmlListLogFiles(){ $dir = LOCAL_STORAGE_DIR; if(!is_dir(LOCAL_STORAGE_DIR)) return ; if(($handle = opendir(LOCAL_STORAGE_DIR))!==false){ while($file = readdir($handle)){ $split = split("\.", $file); if(!count($split) || $split[0] == "") continue; $split2 = split("_", $split[0]); $date = $split2[1]; $dSplit = split("-", $date); $display = date("D. d M. Y", mktime(0,0,1,$dSplit[0], $dSplit[1], $dSplit[2])); print(""); } closedir($handle); } return ; } function xmlLogs($date){ $fName = LOCAL_STORAGE_DIR."log_".$date.".txt"; if(!is_file($fName) || !is_readable($fName)) return; $res = ""; $lines = file($fName); foreach ($lines as $line){ $matches = array(); if(preg_match("/(.*)\t(.*)\t(.*)\t(.*)\t(.*)\t(.*)$/", $line, $matches)!==false){ print(utf8_encode("")); } } return ; } } ?>AjaXplorer/AjaXplorer/server/classes/class.AJXP_User.php0000766000000000000000000000710511122202526024400 0ustar adminadministratorsid = $id; $this->load(); } function getId(){ return $this->id; } function getRight($rootDirId){ if(isSet($this->rights[$rootDirId])) return $this->rights[$rootDirId]; return ""; } function canRead($rootDirId){ $right = $this->getRight($rootDirId); if($right == "rw" || $right == "r") return true; return false; } function canWrite($rootDirId){ $right = $this->getRight($rootDirId); if($right == "rw") return true; return false; } function setRight($rootDirId, $rightString){ $this->rights[$rootDirId] = $rightString; } function removeRights($rootDirId){ if(isSet($this->rights[$rootDirId])) unset($this->rights[$rootDirId]); } function getPref($prefName){ if(isSet($this->prefs[$prefName])) return $this->prefs[$prefName]; return ""; } function setPref($prefName, $prefValue){ $this->prefs[$prefName] = $prefValue; } function addBookmark($path, $title="", $repId = -1){ if(!isSet($this->bookmarks)) $this->bookmarks = array(); if($repId == -1) $repId = ConfService::getCurrentRootDirIndex(); if($title == "") $title = basename($path); if(!isSet($this->bookmarks[$repId])) $this->bookmarks[$repId] = array(); foreach ($this->bookmarks[$repId] as $v) { $toCompare = ""; if(is_string($v)) $toCompare = $v; else if(is_array($v)) $toCompare = $v["PATH"]; if($toCompare == trim($path)) return ; // RETURN IF ALREADY HERE! } $this->bookmarks[$repId][] = array("PATH"=>trim($path), "TITLE"=>$title); } function removeBookmark($path){ $repId = ConfService::getCurrentRootDirIndex(); if(isSet($this->bookmarks) && isSet($this->bookmarks[$repId]) && is_array($this->bookmarks[$repId])) { foreach ($this->bookmarks[$repId] as $k => $v) { $toCompare = ""; if(is_string($v)) $toCompare = $v; else if(is_array($v)) $toCompare = $v["PATH"]; if($toCompare == trim($path)) unset($this->bookmarks[$repId][$k]); } } } function renameBookmark($path, $title){ $repId = ConfService::getCurrentRootDirIndex(); if(isSet($this->bookmarks) && isSet($this->bookmarks[$repId]) && is_array($this->bookmarks[$repId])) { foreach ($this->bookmarks[$repId] as $k => $v) { $toCompare = ""; if(is_string($v)) $toCompare = $v; else if(is_array($v)) $toCompare = $v["PATH"]; if($toCompare == trim($path)){ $this->bookmarks[$repId][$k] = array("PATH"=>trim($path), "TITLE"=>$title); } } } } function getBookmarks() { if(isSet($this->bookmarks) && isSet($this->bookmarks[ConfService::getCurrentRootDirIndex()])) return $this->bookmarks[ConfService::getCurrentRootDirIndex()]; return array(); } function load(){ $this->rights = $this->loadUserFile("rights"); $this->prefs = $this->loadUserFile("prefs"); $this->bookmarks = $this->loadUserFile("bookmarks"); } function save(){ $this->saveUserFile("rights", $this->rights); $this->saveUserFile("prefs", $this->prefs); $this->saveUserFile("bookmarks", $this->bookmarks); } function loadUserFile($file){ $result = array(); if(is_file(USERS_DIR."/".$this->id."/".$file.".ser")) { $fileLines = file(USERS_DIR."/".$this->id."/".$file.".ser"); $result = unserialize($fileLines[0]); } return $result; } function saveUserFile($file, $value){ if(!is_dir(USERS_DIR."/".$this->id)) mkdir(USERS_DIR."/".$this->id); $fp = fopen(USERS_DIR."/".$this->id."/".$file.".ser", "w"); fwrite($fp, serialize($value)); fclose($fp); } } ?>AjaXplorer/AjaXplorer/server/classes/class.BookmarksManager.php0000766000000000000000000000420711122202526026063 0ustar adminadministratorscurrentUser = $user; } function addBookMark($path) { $currentBMarks = $this->getBookMarks(); if(in_array($path, $currentBMarks)) return; $fp = fopen($this->bookmarksFolder."/".$this->currentUser.".txt", "a"); fwrite($fp, ConfService::getCurrentRootDirIndex().":".$path."\n"); fclose($fp); } function getBookMarks($currentRootOnly = true) { $bMarks = array(); if(is_file($this->bookmarksFolder."/".$this->currentUser.".txt")) { $file = file($this->bookmarksFolder."/".$this->currentUser.".txt"); foreach ($file as $index => $bookmark) { $bookmark = str_replace("\n", "", $bookmark); if(trim($bookmark) != "") { $bmRootId = 0; $splitTest = split(":", $bookmark); if(is_array($splitTest) && count($splitTest) == 2) { $bmRootId = intval($splitTest[0]); $bookmark = $splitTest[1]; } if(!$currentRootOnly) { if(!isset($bMarks[$bmRootId])) $bMarks[$bmRootId] = array(); $bMarks[$bmRootId][] = $bookmark; } else if($bmRootId == ConfService::getCurrentRootDirIndex()) { $bMarks[] = $bookmark; } } } } return $bMarks; } function removeBookMark($path) { $currentBMarksByRoot = $this->getBookMarks(false); $found = false; foreach ($currentBMarksByRoot as $currentBMarks) { if(in_array($path, $currentBMarks)){ $found = true; break; } } if(!$found) return ; $newBookMarks = array(); foreach ($currentBMarksByRoot as $crtRoot => $currentBMarks) { foreach ($currentBMarks as $bookmark) { if($bookmark == $path || trim($bookmark) == "") continue; $newBookMarks[] = $crtRoot.":".$bookmark; } } unlink($this->bookmarksFolder."/".$this->currentUser.".txt"); $fp = fopen($this->bookmarksFolder."/".$this->currentUser.".txt", "w"); fwrite($fp, join("\n", $newBookMarks)."\n"); fclose($fp); } function getCurrentUser() { return $this->currentUser; } } ?>AjaXplorer/AjaXplorer/server/classes/class.HttpClient.php0000766000000000000000000003406311122202526024721 0ustar adminadministratorscookies array ready for the next request // Note: This currently ignores the cookie path (and time) completely. Time is not important, // but path could possibly lead to security problems. var $persist_referers = true; // For each request, sends path of last request as referer var $debug = false; var $handle_redirects = true; // Auaomtically redirect if Location or URI header is found var $max_redirects = 5; var $headers_only = false; // If true, stops receiving once headers have been read. // Basic authorization variables var $username; var $password; // Response vars var $status; var $headers = array(); var $content = ''; var $errormsg; // Tracker variables var $redirect_count = 0; var $cookie_host = ''; var $postFileName = "userfile"; var $postFileData = array(); var $postDataArray = array(); var $directForwarding = false; function HttpClient($host, $port=80) { $this->host = $host; $this->port = $port; } function get($path, $data = false) { $this->path = $path; $this->method = 'GET'; if ($data) { $this->path .= '?'.$this->buildQueryString($data); } return $this->doRequest(); } function post($path, $data) { $this->path = $path; $this->method = 'POST'; $this->postdata = $this->buildQueryString($data); return $this->doRequest(); } function postFile($path, $postData, $fileVarName, $fileData){ $this->path = $path; $this->method = 'POST'; $this->postFileData = $fileData; $this->postDataArray = $postData; $this->postFileName = $fileVarName; $this->postdata = $this->buildQueryString($postData); return $this->doRequest(); } function buildQueryString($data) { $querystring = ''; if (is_array($data)) { // Change data in to postable data foreach ($data as $key => $val) { if (is_array($val)) { foreach ($val as $val2) { $querystring .= urlencode($key).'='.urlencode($val2).'&'; } } else { $querystring .= urlencode($key).'='.urlencode($val).'&'; } } $querystring = substr($querystring, 0, -1); // Eliminate unnecessary & } else { $querystring = $data; } return $querystring; } function doRequest() { // Performs the actual HTTP request, returning true or false depending on outcome if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) { // Set error message switch($errno) { case -3: $this->errormsg = 'Socket creation failed (-3)'; case -4: $this->errormsg = 'DNS lookup failure (-4)'; case -5: $this->errormsg = 'Connection refused or timed out (-5)'; default: $this->errormsg = 'Connection failed on '.$this->host.'('.$errno.')'; $this->errormsg .= ' '.$errstr; $this->debug($this->errormsg); } return false; } socket_set_timeout($fp, $this->timeout); $request = $this->buildRequest(); $this->debug('Request', $request); @fwrite($fp, $request); // Reset all the variables that should not persist between requests $this->headers = array(); $this->content = ''; $this->errormsg = ''; // Set a couple of flags $inHeaders = true; $atStart = true; // Now start reading back the response while (!feof($fp)) { $line = fgets($fp, 4096); if ($atStart) { // Deal with first line of returned data $atStart = false; if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) { $this->errormsg = "Status code line invalid: ".htmlentities($line); $this->debug($this->errormsg); return false; } $http_version = $m[1]; // not used $this->status = $m[2]; $status_string = $m[3]; // not used $this->debug(trim($line)); continue; } if ($inHeaders) { if (trim($line) == '') { $inHeaders = false; $this->debug('Received Headers', $this->headers); if ($this->headers_only) { break; // Skip the rest of the input } continue; } if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) { // Skip to the next header continue; } $key = strtolower(trim($m[1])); $val = trim($m[2]); if($this->directForwarding){ header($line, true); continue; } // Deal with the possibility of multiple headers of same name if (isset($this->headers[$key])) { if (is_array($this->headers[$key])) { $this->headers[$key][] = $val; } else { $this->headers[$key] = array($this->headers[$key], $val); } } else { $this->headers[$key] = $val; } continue; } // We're not in the headers, so append the line to the contents if($this->directForwarding){ print $line; continue; } $this->content .= $line; } fclose($fp); if($this->directForwarding){ return ; } // If data is compressed, uncompress it if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') { $this->debug('Content is gzip encoded, unzipping it'); if(!$this->headers_only){ $this->content = substr($this->content, 10); // See http://www.php.net/manual/en/function.gzencode.php $this->content = gzinflate($this->content); } } // If $persist_cookies, deal with any cookies if ($this->persist_cookies && isset($this->headers['set-cookie']) && $this->host == $this->cookie_host) { $cookies = $this->headers['set-cookie']; if (!is_array($cookies)) { $cookies = array($cookies); } foreach ($cookies as $cookie) { if (preg_match('/([^=]+)=([^;]+);/', $cookie, $m)) { $this->cookies[$m[1]] = $m[2]; } } // Record domain of cookies for security reasons $this->cookie_host = $this->host; } // If $persist_referers, set the referer ready for the next request if ($this->persist_referers) { $this->debug('Persisting referer: '.$this->getRequestURL()); $this->referer = $this->getRequestURL(); } // Finally, if handle_redirects and a redirect is sent, do that if ($this->handle_redirects) { if (++$this->redirect_count >= $this->max_redirects) { $this->errormsg = 'Number of redirects exceeded maximum ('.$this->max_redirects.')'; $this->debug($this->errormsg); $this->redirect_count = 0; return false; } $location = isset($this->headers['location']) ? $this->headers['location'] : ''; $uri = isset($this->headers['uri']) ? $this->headers['uri'] : ''; if ($location || $uri) { $url = parse_url($location.$uri); // This will FAIL if redirect is to a different site return $this->get($url['path']); } } return true; } function buildRequest() { $headers = array(); $headers[] = "{$this->method} {$this->path} HTTP/1.0"; // Using 1.1 leads to all manner of problems, such as "chunked" encoding $headers[] = "Host: {$this->host}"; $headers[] = "User-Agent: {$this->user_agent}"; $headers[] = "Accept: {$this->accept}"; if ($this->use_gzip) { $headers[] = "Accept-encoding: {$this->accept_encoding}"; } $headers[] = "Accept-language: {$this->accept_language}"; if ($this->referer) { $headers[] = "Referer: {$this->referer}"; } // Cookies if ($this->cookies) { $cookie = 'Cookie: '; foreach ($this->cookies as $key => $value) { $cookie .= "$key=$value; "; } $headers[] = $cookie; } // Basic authentication if ($this->username && $this->password) { $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password); } if(!count($this->postFileData)){ // If this is a POST, set the content type and length if ($this->postdata) { $headers[] = 'Content-Type: application/x-www-form-urlencoded'; $headers[] = 'Content-Length: '.strlen($this->postdata); } $request = implode("\r\n", $headers)."\r\n\r\n".$this->postdata; }else{ srand((double)microtime()*1000000); $boundary = "----".substr(md5(rand(0,32000)),0,10); $headers[] = "Content-Type: multipart/form-data; boundary=$boundary"; $data = array(); // attach post vars $this->postDataArray["Filename"] = $this->postFileData["name"]; foreach($this->postDataArray as $index => $value){ $data[]="--$boundary"; $data[]= "content-disposition: form-data; name=\"".$index."\""; $data[]= "\r\n".$value.""; } // and attach the file //$data[]= "--$boundary"; $content_file = join("", file($this->postFileData["tmp_name"])); $data[]="--$boundary"; $data[]="content-disposition: form-data; name=\"".$this->postFileName."\"; filename=\"".$this->postFileData["name"]."\""; $data[]= "Content-Type: ".$this->postFileData['type']."\r\n"; $data[]= "".$content_file.""; $data[]="--$boundary--"; //$headers[]= "Content-Length: " . strlen(implode("",$data)); $data = implode("\r\n", $data); $headers[]= "Content-Length: " . strlen($data); $headers[] = "Cache-Control: no-cache"; $headers[] = "Connection: Keep-Alive"; $request = implode("\r\n", $headers)."\r\n\r\n".$data; } return $request; } function getStatus() { return $this->status; } function getContent() { return $this->content; } function getHeaders() { return $this->headers; } function getHeader($header) { $header = strtolower($header); if (isset($this->headers[$header])) { return $this->headers[$header]; } else { return false; } } function getError() { return $this->errormsg; } function getCookies() { return $this->cookies; } function getRequestURL() { $url = 'http://'.$this->host; if ($this->port != 80) { $url .= ':'.$this->port; } $url .= $this->path; return $url; } // Setter methods function setUserAgent($string) { $this->user_agent = $string; } function setAuthorization($username, $password) { $this->username = $username; $this->password = $password; } function setCookies($array) { $this->cookies = $array; } // Option setting methods function useGzip($boolean) { $this->use_gzip = $boolean; } function setPersistCookies($boolean) { $this->persist_cookies = $boolean; } function setPersistReferers($boolean) { $this->persist_referers = $boolean; } function setHandleRedirects($boolean) { $this->handle_redirects = $boolean; } function setMaxRedirects($num) { $this->max_redirects = $num; } function setHeadersOnly($boolean) { $this->headers_only = $boolean; } function setDebug($boolean) { $this->debug = $boolean; } // "Quick" static methods function quickGet($url) { $bits = parse_url($url); $host = $bits['host']; $port = isset($bits['port']) ? $bits['port'] : 80; $path = isset($bits['path']) ? $bits['path'] : '/'; if (isset($bits['query'])) { $path .= '?'.$bits['query']; } $client = new HttpClient($host, $port); if (!$client->get($path)) { return false; } else { return $client->getContent(); } } function quickPost($url, $data) { $bits = parse_url($url); $host = $bits['host']; $port = isset($bits['port']) ? $bits['port'] : 80; $path = isset($bits['path']) ? $bits['path'] : '/'; $client = new HttpClient($host, $port); if (!$client->post($path, $data)) { return false; } else { return $client->getContent(); } } function debug($msg, $object = false) { if ($this->debug) { print '
    HttpClient Debug: '.$msg; if ($object) { ob_start(); print_r($object); $content = htmlentities(ob_get_contents()); ob_end_clean(); print '
    '.$content.'
    '; } print '
    '; } } } ?>AjaXplorer/AjaXplorer/server/classes/class.Utils.php0000766000000000000000000002424211122202526023741 0ustar adminadministrators : * ? | ! + ^ $fileName=stripslashes($fileName); // Unless I'm mistaken, ' is a valid char for a file name (under both Linux and Windows). // I've found this regular expression for Windows file name validation, not sure how it applies for linux : // ^[^\\\./:\*\?\"<>\|]{1}[^\\/:\*\?\"<>\|]{0,254}$ This reg ex remove ^ \ . / : * ? " < > | as the first char, and (same thing but . for any other char), and it limits to 254 chars (could use max_caracteres instead) // Anyway, here is the corrected version of the big str_replace calls below that doesn't kill UTF8 encoding $fileNameTmp=ereg_replace("['\"&,;/`<>:\*\|\?!\+\^]", "", $fileName); return substr($fileNameTmp, 0, $max_caracteres); } function mimetype($fileName,$mode, $isDir) { $mess = ConfService::getMessages(); if($isDir){$image="folder.png";$typeName=$mess[8];} else if(eregi("\.mid$",$fileName)){$image="midi.png";$typeName=$mess[9];} else if(eregi("\.txt$",$fileName)){$image="txt2.png";$typeName=$mess[10];} else if(eregi("\.sql$",$fileName)){$image="txt2.png";$typeName=$mess[10];} else if(eregi("\.js$",$fileName)){$image="javascript.png";$typeName=$mess[11];} else if(eregi("\.gif$",$fileName)){$image="image.png";$typeName=$mess[12];} else if(eregi("\.jpg$",$fileName)){$image="image.png";$typeName=$mess[13];} else if(eregi("\.html$",$fileName)){$image="html.png";$typeName=$mess[14];} else if(eregi("\.htm$",$fileName)){$image="html.png";$typeName=$mess[15];} else if(eregi("\.rar$",$fileName)){$image="archive.png";$typeName=$mess[60];} else if(eregi("\.gz$",$fileName)){$image="zip.png";$typeName=$mess[61];} else if(eregi("\.tgz$",$fileName)){$image="archive.png";$typeName=$mess[61];} else if(eregi("\.z$",$fileName)){$image="archive.png";$typeName=$mess[61];} else if(eregi("\.ra$",$fileName)){$image="video.png";$typeName=$mess[16];} else if(eregi("\.ram$",$fileName)){$image="video.png";$typeName=$mess[17];} else if(eregi("\.rm$",$fileName)){$image="video.png";$typeName=$mess[17];} else if(eregi("\.pl$",$fileName)){$image="source_pl.png";$typeName=$mess[18];} else if(eregi("\.zip$",$fileName)){$image="zip.png";$typeName=$mess[19];} else if(eregi("\.wav$",$fileName)){$image="sound.png";$typeName=$mess[20];} else if(eregi("\.php$",$fileName)){$image="php.png";$typeName=$mess[21];} else if(eregi("\.php3$",$fileName)){$image="php.png";$typeName=$mess[22];} else if(eregi("\.phtml$",$fileName)){$image="php.png";$typeName=$mess[22];} else if(eregi("\.exe$",$fileName)){$image="exe.png";$typeName=$mess[50];} else if(eregi("\.bmp$",$fileName)){$image="image.png";$typeName=$mess[56];} else if(eregi("\.png$",$fileName)){$image="image.png";$typeName=$mess[57];} else if(eregi("\.css$",$fileName)){$image="css.png";$typeName=$mess[58];} else if(eregi("\.mp3$",$fileName)){$image="sound.png";$typeName=$mess[59];} else if(eregi("\.xls$",$fileName)){$image="spreadsheet.png";$typeName=$mess[64];} else if(eregi("\.doc$",$fileName)){$image="document.png";$typeName=$mess[65];} else if(eregi("\.pdf$",$fileName)){$image="pdf.png";$typeName=$mess[79];} else if(eregi("\.mov$",$fileName)){$image="video.png";$typeName=$mess[80];} else if(eregi("\.avi$",$fileName)){$image="video.png";$typeName=$mess[81];} else if(eregi("\.mpg$",$fileName)){$image="video.png";$typeName=$mess[82];} else if(eregi("\.mpeg$",$fileName)){$image="video.png";$typeName=$mess[83];} else if(eregi("\.swf$",$fileName)){$image="flash.png";$typeName=$mess[91];} else {$image="mime_empty.png";$typeName=$mess[23];} if($mode=="image"){return $image;} else {return $typeName;} } function getAjxpMimes($keyword){ if($keyword == "editable"){ return "txt,sql,php,php3,phtml,htm,html,cgi,pl,js,css,inc,xml,xsl,java"; }else if($keyword == "image"){ return "png,bmp,jpg,jpeg,gif"; }else if($keyword == "audio"){ return "mp3"; }else if($keyword == "zip"){ if(ConfService::zipEnabled()){ return "zip"; }else{ return "none_allowed"; } } return ""; } function is_image($fileName) { if(eregi("\.png$|\.bmp$|\.jpg$|\.jpeg$|\.gif$",$fileName)){ return 1; } return 0; } function is_mp3($fileName) { if(eregi("\.mp3$",$fileName)) return 1; return 0; } function getImageMimeType($fileName) { if(eregi("\.jpg$|\.jpeg$",$fileName)){return "image/jpeg";} else if(eregi("\.png$",$fileName)){return "image/png";} else if(eregi("\.bmp$",$fileName)){return "image/bmp";} else if(eregi("\.gif$",$fileName)){return "image/gif";} } function roundSize($filesize) { $size_unit = ConfService::getConf("SIZE_UNIT"); if($filesize < 0){ $filesize = sprintf("%u", $filesize); } if ($filesize >= 1073741824) {$filesize = round($filesize / 1073741824 * 100) / 100 . " G".$size_unit;} elseif ($filesize >= 1048576) {$filesize = round($filesize / 1048576 * 100) / 100 . " M".$size_unit;} elseif ($filesize >= 1024) {$filesize = round($filesize / 1024 * 100) / 100 . " K".$size_unit;} else {$filesize = $filesize . " ".$size_unit;} if($filesize==0) {$filesize="-";} return $filesize; } function showHiddenFiles($fileName) { $showhidden = ConfService::getConf("SHOW_HIDDEN"); if(substr($fileName,0,1)=="." && $showhidden==0) { return 0; } return 1; } /** * Convert a shorthand byte value from a PHP configuration directive to an integer value * @param string $value * @return int */ function convertBytes( $value ) { if ( is_numeric( $value ) ) { return $value; } else { $value_length = strlen( $value ); $qty = substr( $value, 0, $value_length - 1 ); $unit = strtolower( substr( $value, $value_length - 1 ) ); switch ( $unit ) { case 'k': $qty *= 1024; break; case 'm': $qty *= 1048576; break; case 'g': $qty *= 1073741824; break; } return $qty; } } function xmlEntities($string){ return str_replace(array("&", "<",">"), array("&", "<",">"), $string); } } ?>AjaXplorer/AjaXplorer/server/classes/class.RecycleBinManager.php0000766000000000000000000000315011122202526026146 0ustar adminadministratorsgetOption("RECYCLE_BIN"); if($recycle == "") return null; $cachePath = $repository->getOption("PATH")."/".$recycle."/".RecycleBinManager::getCacheFileName(); if(is_file($cachePath)) { $fileLines = file($cachePath); $result = unserialize($fileLines[0]); } return $result; } function saveCache($value){ $repository = ConfService::getRepository(); $recycle = $repository->getOption("RECYCLE_BIN"); if($recycle == "") return ; $cachePath = $repository->getOption("PATH")."/".$recycle."/".RecycleBinManager::getCacheFileName(); if(!is_dir($repository->getOption("PATH")."/".$recycle)) { mkdir($repository->getOption("PATH")."/".$recycle); } $fp = fopen($cachePath, "w"); fwrite($fp, serialize($value)); fclose($fp); } } ?>AjaXplorer/AjaXplorer/server/classes/class.AJXP_ClientDriver.php0000766000000000000000000001354411132607307026067 0ustar adminadministratorsactions["get_driver_actions"]); unset($this->actions["get_driver_info_panels"]); $this->actions["get_ajxp_actions"] = array(); $this->actions["get_ajxp_info_panels"] = array(); } function switchAction($action, $httpVars, $fileVars) { if(!isSet($this->actions[$action])) return; $xmlBuffer = ""; foreach($httpVars as $getName=>$getValue){ $$getName = Utils::securePath($getValue); } if(isSet($dir) && $action != "upload") $dir = SystemTextEncoding::fromUTF8($dir); $mess = ConfService::getMessages(); switch ($action){ //------------------------------------ // SWITCH THE ROOT REPOSITORY //------------------------------------ case "switch_root_dir": if(!isSet($root_dir_index)) { break; } $dirList = ConfService::getRootDirsList(); if(!isSet($dirList[$root_dir_index])) { $errorMessage = "Trying to switch to an unkown folder!"; break; } ConfService::switchRootDir($root_dir_index); $logMessage = "Successfully Switched!"; AJXP_Logger::logAction("Switch Repository", array("rep. id"=>$root_dir_index)); break; //------------------------------------ // GET AN HTML TEMPLATE //------------------------------------ case "get_template": //header("Content-type:text/html"); header("Content-type:text/html; charset=UTF-8"); //KenChen@QNAP if(isset($template_name) && is_file(CLIENT_RESOURCES_FOLDER."/html/".$template_name)) { if($template_name == "gui_tpl.html"){ include(CLIENT_RESOURCES_FOLDER."/html/usertemplate_top.html"); } include(CLIENT_RESOURCES_FOLDER."/html/".$template_name); if($template_name == "gui_tpl.html"){ include(CLIENT_RESOURCES_FOLDER."/html/usertemplate_bottom.html"); } } exit(0); break; //------------------------------------ // GET I18N MESSAGES //------------------------------------ case "get_i18n_messages": header("Content-type:text/javascript"); HTMLWriter::writeI18nMessagesClass(ConfService::getMessages()); exit(0); break; //------------------------------------ // BOOKMARK BAR //------------------------------------ case "get_bookmarks": $bmUser = null; if(AuthService::usersEnabled() && AuthService::getLoggedUser() != null) { $bmUser = AuthService::getLoggedUser(); } else if(!AuthService::usersEnabled()) { $bmUser = new AJXP_User("shared"); } if($bmUser == null) exit(1); if(isSet($_GET["bm_action"]) && isset($_GET["bm_path"])) { if($_GET["bm_action"] == "add_bookmark") { $title = ""; if(isSet($_GET["title"])) $title = $_GET["title"]; if($title == "" && $_GET["bm_path"]=="/") $title = ConfService::getCurrentRootDirDisplay(); $bmUser->addBookMark($_GET["bm_path"], $title); } else if($_GET["bm_action"] == "delete_bookmark") { $bmUser->removeBookmark($_GET["bm_path"]); } else if($_GET["bm_action"] == "rename_bookmark" && isset($_GET["bm_title"])) { $bmUser->renameBookmark($_GET["bm_path"], $_GET["bm_title"]); } } if(AuthService::usersEnabled() && AuthService::getLoggedUser() != null) { $bmUser->save(); AuthService::updateUser($bmUser); } else if(!AuthService::usersEnabled()) { $bmUser->save(); } AJXP_XMLWriter::header(); AJXP_XMLWriter::writeBookmarks($bmUser->getBookmarks()); AJXP_XMLWriter::close(); exit(1); break; //------------------------------------ // SAVE USER PREFERENCE //------------------------------------ case "save_user_pref": $userObject = AuthService::getLoggedUser(); if($userObject == null) exit(1); $i = 0; while(isSet($_GET["pref_name_".$i]) && isSet($_GET["pref_value_".$i])) { $prefName = $_GET["pref_name_".$i]; $prefValue = $_GET["pref_value_".$i]; if($prefName != "password") { $userObject->setPref($prefName, $prefValue); $userObject->save(); AuthService::updateUser($userObject); setcookie("AJXP_$prefName", $prefValue); } else { if(isSet($_GET["crt"]) && AuthService::checkPassword($userObject->getId(), $_GET["crt"])){ AuthService::updatePassword($userObject->getId(), $prefValue); }else{ //$errorMessage = "Wrong password!"; header("text/plain"); print "PASS_ERROR"; exit(1); } } $i++; } header("text/plain"); print "SUCCESS"; exit(1); break; //------------------------------------ // DISPLAY DOC //------------------------------------ case "display_doc": echo HTMLWriter::getDocFile($_GET["doc_file"]); exit(1); break; default; break; } if(isset($logMessage) || isset($errorMessage)) { $xmlBuffer .= AJXP_XMLWriter::sendMessage((isSet($logMessage)?$logMessage:null), (isSet($errorMessage)?$errorMessage:null), false); } if(isset($requireAuth)) { $xmlBuffer .= AJXP_XMLWriter::requireAuth(false); } if(isset($reload_current_node) && $reload_current_node == "true") { $xmlBuffer .= AJXP_XMLWriter::reloadCurrentNode(false); } if(isset($reload_dest_node) && $reload_dest_node != "") { $xmlBuffer .= AJXP_XMLWriter::reloadNode($reload_dest_node, false); } if(isset($reload_file_list)) { $xmlBuffer .= AJXP_XMLWriter::reloadFileList($reload_file_list, false); } return $xmlBuffer; } } ?> AjaXplorer/AjaXplorer/server/classes/class.AbstractDriver.php0000766000000000000000000001272511122202526025563 0ustar adminadministratorsdriverName = $driverName; $this->xmlFilePath = $filePath; $this->repository = $repository; $this->parseXMLActions(); // Create fake action for sending its own actions to client. $this->actions["get_driver_actions"] = array(); $this->actions["get_driver_info_panels"] = array(); } function initRepository(){ // To be implemented by subclasses } function hasAction($actionName){ return isSet($this->actions[$actionName]); } function actionNeedsRight($actionName, $right){ if($right == 'r') $rString = "READ"; else $rString = "WRITE"; $action = $this->actions[$actionName]; if(isSet($action["rights"]) && isSet($action["rights"][$rString]) && $action["rights"][$rString] == "true"){ return true; } return false; } function applyAction($actionName, $httpVars, $filesVar) { if($actionName == "get_driver_actions" || $actionName == "get_ajxp_actions"){ $this->sendActionsToClient(false, null); exit(1); } else if($actionName == "get_ajxp_info_panels" || $actionName == "get_driver_info_panels"){ $this->sendInfoPanelsDef(); return; } if(isSet($this->actions[$actionName])){ // use callback; $action = $this->actions[$actionName]; $callBack = $action["callback"]; return call_user_func(array(&$this, $callBack), $actionName, $httpVars, $filesVar); } } /** * Print the XML for actions * * @param boolean $filterByRight * @param User $user */ function sendActionsToClient($filterByRight, $user){ AJXP_XMLWriter::header(); foreach($this->actions as $name => $action){ if($name == "get_driver_actions" || $name == "get_ajxp_actions") continue; if($filterByRight && $this->actionNeedsRight($name, "r")){ if($user==null || !$user->canRead($this->repository->getId())) continue; } if($filterByRight && $this->actionNeedsRight($name, "w")){ if($user==null || !$user->canWrite($this->repository->getId())) continue; } if(isSet($action["XML"])){ $xml = $action["XML"]; $xml = $this->replaceAjxpXmlKeywords($xml); $xml = preg_replace("/[\n\r]?/", "", $xml); $xml = preg_replace("/\t/", " ", $xml); AJXP_XMLWriter::write($xml, true); } } AJXP_XMLWriter::close(); } function replaceAjxpXmlKeywords($xml){ $messages = ConfService::getMessages(); $matches = array(); $xml = str_replace("AJXP_CLIENT_RESOURCES_FOLDER", CLIENT_RESOURCES_FOLDER, $xml); $xml = str_replace("AJXP_SERVER_ACCESS", SERVER_ACCESS, $xml); $xml = str_replace("AJXP_MIMES_EDITABLE", Utils::getAjxpMimes("editable"), $xml); $xml = str_replace("AJXP_MIMES_IMAGE", Utils::getAjxpMimes("image"), $xml); $xml = str_replace("AJXP_MIMES_AUDIO", Utils::getAjxpMimes("audio"), $xml); $xml = str_replace("AJXP_MIMES_ZIP", Utils::getAjxpMimes("zip"), $xml); if(preg_match_all("/AJXP_MESSAGE(\[.*?\])/", $xml, $matches, PREG_SET_ORDER)){ foreach($matches as $match){ $messId = str_replace("]", "", str_replace("[", "", $match[1])); $xml = str_replace("AJXP_MESSAGE[$messId]", $messages[$messId], $xml); } } return $xml; } function fillActionsWithXML(){ $fileData = file_get_contents($this->xmlFilePath); $matches = array(); foreach ($this->actions as $actionName => $actionData){ preg_match_all('/(.*?<\/action>)/', str_replace("\n", "", $fileData), $matches); if(count($matches) && count($matches[0])){ $actionXML = $matches[0][0]; $this->actions[$actionName]["XML"] = $actionXML; } } } function sendInfoPanelsDef(){ $fileData = file_get_contents($this->xmlFilePath); $matches = array(); preg_match('/.*<\/infoPanels>/', str_replace("\n", "",$fileData), $matches); if(count($matches)){ AJXP_XMLWriter::header(); AJXP_XMLWriter::write($this->replaceAjxpXmlKeywords(str_replace("\n", "",$matches[0])), true); AJXP_XMLWriter::close(); exit(1); } } function parseXMLActions() { $this->xml_data = file_get_contents($this->xmlFilePath); $this->xml_parser = xml_parser_create( "UTF-8" ); //xml_parser_set_option( $this->xml_parser, XML_OPTION_CASE_FOLDING, false ); xml_set_object( $this->xml_parser, $this ); xml_set_element_handler( $this->xml_parser, "_startElement", "_endElement"); xml_set_character_data_handler( $this->xml_parser, "_cData" ); xml_parse( $this->xml_parser, $this->xml_data, true ); xml_parser_free( $this->xml_parser ); $this->fillActionsWithXML(); //print_r($this->actions); } function _startElement($parser, $tag, $attributeList){ if($tag == 'ACTION'){ $this->crtAction = array(); $this->crtAction["name"] = $attributeList["NAME"]; }else if($tag == 'SERVERCALLBACK'){ $this->crtAction["callback"] = $attributeList["METHODNAME"]; }else if($tag == "RIGHTSCONTEXT"){ $this->crtAction["rights"] = $attributeList; } } function _endElement($parser, $tag){ if($tag == "ACTION"){ $this->actions[$this->crtAction["name"]] = $this->crtAction; } } function _cData($parser, $data){} } ?>AjaXplorer/AjaXplorer/server/classes/packer/0000777000000000000000000000000011300346033022264 5ustar adminadministratorsAjaXplorer/AjaXplorer/server/classes/packer/class.JavaScriptPacker.php0000766000000000000000000005622611122202524027307 0ustar adminadministratorspack(); * * or * * $myPacker = new JavaScriptPacker($script, 'Normal', true, false); * $packed = $myPacker->pack(); * * or (default values) * * $myPacker = new JavaScriptPacker($script); * $packed = $myPacker->pack(); * * * params of the constructor : * $script: the JavaScript to pack, string. * $encoding: level of encoding, int or string : * 0,10,62,95 or 'None', 'Numeric', 'Normal', 'High ASCII'. * default: 62. * $fastDecode: include the fast decoder in the packed result, boolean. * default : true. * $specialChars: if you are flagged your private and local variables * in the script, boolean. * default: false. * * The pack() method return the compressed JavasScript, as a string. * * see http://dean.edwards.name/packer/usage/ for more information. * * Notes : * # need PHP 5 . Tested with PHP 5.1.2, 5.1.3, 5.1.4, 5.2.3 * * # The packed result may be different than with the Dean Edwards * version, but with the same length. The reason is that the PHP * function usort to sort array don't necessarily preserve the * original order of two equal member. The Javascript sort function * in fact preserve this order (but that's not require by the * ECMAScript standard). So the encoded keywords order can be * different in the two results. * * # Be careful with the 'High ASCII' Level encoding if you use * UTF-8 in your files... */ class JavaScriptPacker { // constants const IGNORE = '$1'; // validate parameters private $_script = ''; private $_encoding = 62; private $_fastDecode = true; private $_specialChars = false; private $LITERAL_ENCODING = array( 'None' => 0, 'Numeric' => 10, 'Normal' => 62, 'High ASCII' => 95 ); public function __construct($_script, $_encoding = 62, $_fastDecode = true, $_specialChars = false) { $this->_script = $_script . "\n"; if (array_key_exists($_encoding, $this->LITERAL_ENCODING)) $_encoding = $this->LITERAL_ENCODING[$_encoding]; $this->_encoding = min((int)$_encoding, 95); $this->_fastDecode = $_fastDecode; $this->_specialChars = $_specialChars; } public function pack() { $this->_addParser('_basicCompression'); if ($this->_specialChars) $this->_addParser('_encodeSpecialChars'); if ($this->_encoding) $this->_addParser('_encodeKeywords'); // go! return $this->_pack($this->_script); } // apply all parsing routines private function _pack($script) { for ($i = 0; isset($this->_parsers[$i]); $i++) { $script = call_user_func(array(&$this,$this->_parsers[$i]), $script); } return $script; } // keep a list of parsing functions, they'll be executed all at once private $_parsers = array(); private function _addParser($parser) { $this->_parsers[] = $parser; } // zero encoding - just removal of white space and comments private function _basicCompression($script) { $parser = new ParseMaster(); // make safe $parser->escapeChar = '\\'; // protect strings $parser->add('/\'[^\'\\n\\r]*\'/', self::IGNORE); $parser->add('/"[^"\\n\\r]*"/', self::IGNORE); // remove comments $parser->add('/\\/\\/[^\\n\\r]*[\\n\\r]/', ' '); $parser->add('/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//', ' '); // protect regular expressions $parser->add('/\\s+(\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?)/', '$2'); // IGNORE $parser->add('/[^\\w\\x24\\/\'"*)\\?:]\\/[^\\/\\n\\r\\*][^\\/\\n\\r]*\\/g?i?/', self::IGNORE); // remove: ;;; doSomething(); if ($this->_specialChars) $parser->add('/;;;[^\\n\\r]+[\\n\\r]/'); // remove redundant semi-colons $parser->add('/\\(;;\\)/', self::IGNORE); // protect for (;;) loops $parser->add('/;+\\s*([};])/', '$2'); // apply the above $script = $parser->exec($script); // remove white-space $parser->add('/(\\b|\\x24)\\s+(\\b|\\x24)/', '$2 $3'); $parser->add('/([+\\-])\\s+([+\\-])/', '$2 $3'); $parser->add('/\\s+/', ''); // done return $parser->exec($script); } private function _encodeSpecialChars($script) { $parser = new ParseMaster(); // replace: $name -> n, $$name -> na $parser->add('/((\\x24+)([a-zA-Z$_]+))(\\d*)/', array('fn' => '_replace_name') ); // replace: _name -> _0, double-underscore (__name) is ignored $regexp = '/\\b_[A-Za-z\\d]\\w*/'; // build the word list $keywords = $this->_analyze($script, $regexp, '_encodePrivate'); // quick ref $encoded = $keywords['encoded']; $parser->add($regexp, array( 'fn' => '_replace_encoded', 'data' => $encoded ) ); return $parser->exec($script); } private function _encodeKeywords($script) { // escape high-ascii values already in the script (i.e. in strings) if ($this->_encoding > 62) $script = $this->_escape95($script); // create the parser $parser = new ParseMaster(); $encode = $this->_getEncoder($this->_encoding); // for high-ascii, don't encode single character low-ascii $regexp = ($this->_encoding > 62) ? '/\\w\\w+/' : '/\\w+/'; // build the word list $keywords = $this->_analyze($script, $regexp, $encode); $encoded = $keywords['encoded']; // encode $parser->add($regexp, array( 'fn' => '_replace_encoded', 'data' => $encoded ) ); if (empty($script)) return $script; else { //$res = $parser->exec($script); //$res = $this->_bootStrap($res, $keywords); //return $res; return $this->_bootStrap($parser->exec($script), $keywords); } } private function _analyze($script, $regexp, $encode) { // analyse // retreive all words in the script $all = array(); preg_match_all($regexp, $script, $all); $_sorted = array(); // list of words sorted by frequency $_encoded = array(); // dictionary of word->encoding $_protected = array(); // instances of "protected" words $all = $all[0]; // simulate the javascript comportement of global match if (!empty($all)) { $unsorted = array(); // same list, not sorted $protected = array(); // "protected" words (dictionary of word->"word") $value = array(); // dictionary of charCode->encoding (eg. 256->ff) $this->_count = array(); // word->count $i = count($all); $j = 0; //$word = null; // count the occurrences - used for sorting later do { --$i; $word = '$' . $all[$i]; if (!isset($this->_count[$word])) { $this->_count[$word] = 0; $unsorted[$j] = $word; // make a dictionary of all of the protected words in this script // these are words that might be mistaken for encoding //if (is_string($encode) && method_exists($this, $encode)) $values[$j] = call_user_func(array(&$this, $encode), $j); $protected['$' . $values[$j]] = $j++; } // increment the word counter $this->_count[$word]++; } while ($i > 0); // prepare to sort the word list, first we must protect // words that are also used as codes. we assign them a code // equivalent to the word itself. // e.g. if "do" falls within our encoding range // then we store keywords["do"] = "do"; // this avoids problems when decoding $i = count($unsorted); do { $word = $unsorted[--$i]; if (isset($protected[$word]) /*!= null*/) { $_sorted[$protected[$word]] = substr($word, 1); $_protected[$protected[$word]] = true; $this->_count[$word] = 0; } } while ($i); // sort the words by frequency // Note: the javascript and php version of sort can be different : // in php manual, usort : // " If two members compare as equal, // their order in the sorted array is undefined." // so the final packed script is different of the Dean's javascript version // but equivalent. // the ECMAscript standard does not guarantee this behaviour, // and thus not all browsers (e.g. Mozilla versions dating back to at // least 2003) respect this. usort($unsorted, array(&$this, '_sortWords')); $j = 0; // because there are "protected" words in the list // we must add the sorted words around them do { if (!isset($_sorted[$i])) $_sorted[$i] = substr($unsorted[$j++], 1); $_encoded[$_sorted[$i]] = $values[$i]; } while (++$i < count($unsorted)); } return array( 'sorted' => $_sorted, 'encoded' => $_encoded, 'protected' => $_protected); } private $_count = array(); private function _sortWords($match1, $match2) { return $this->_count[$match2] - $this->_count[$match1]; } // build the boot function used for loading and decoding private function _bootStrap($packed, $keywords) { $ENCODE = $this->_safeRegExp('$encode\\($count\\)'); // $packed: the packed script $packed = "'" . $this->_escape($packed) . "'"; // $ascii: base for encoding $ascii = min(count($keywords['sorted']), $this->_encoding); if ($ascii == 0) $ascii = 1; // $count: number of words contained in the script $count = count($keywords['sorted']); // $keywords: list of words contained in the script foreach ($keywords['protected'] as $i=>$value) { $keywords['sorted'][$i] = ''; } // convert from a string to an array ksort($keywords['sorted']); $keywords = "'" . implode('|',$keywords['sorted']) . "'.split('|')"; $encode = ($this->_encoding > 62) ? '_encode95' : $this->_getEncoder($ascii); $encode = $this->_getJSFunction($encode); $encode = preg_replace('/_encoding/','$ascii', $encode); $encode = preg_replace('/arguments\\.callee/','$encode', $encode); $inline = '\\$count' . ($ascii > 10 ? '.toString(\\$ascii)' : ''); // $decode: code snippet to speed up decoding if ($this->_fastDecode) { // create the decoder $decode = $this->_getJSFunction('_decodeBody'); if ($this->_encoding > 62) $decode = preg_replace('/\\\\w/', '[\\xa1-\\xff]', $decode); // perform the encoding inline for lower ascii values elseif ($ascii < 36) $decode = preg_replace($ENCODE, $inline, $decode); // special case: when $count==0 there are no keywords. I want to keep // the basic shape of the unpacking funcion so i'll frig the code... if ($count == 0) $decode = preg_replace($this->_safeRegExp('($count)\\s*=\\s*1'), '$1=0', $decode, 1); } // boot function $unpack = $this->_getJSFunction('_unpack'); if ($this->_fastDecode) { // insert the decoder $this->buffer = $decode; $unpack = preg_replace_callback('/\\{/', array(&$this, '_insertFastDecode'), $unpack, 1); } $unpack = preg_replace('/"/', "'", $unpack); if ($this->_encoding > 62) { // high-ascii // get rid of the word-boundaries for regexp matches $unpack = preg_replace('/\'\\\\\\\\b\'\s*\\+|\\+\s*\'\\\\\\\\b\'/', '', $unpack); } if ($ascii > 36 || $this->_encoding > 62 || $this->_fastDecode) { // insert the encode function $this->buffer = $encode; $unpack = preg_replace_callback('/\\{/', array(&$this, '_insertFastEncode'), $unpack, 1); } else { // perform the encoding inline $unpack = preg_replace($ENCODE, $inline, $unpack); } // pack the boot function too $unpackPacker = new JavaScriptPacker($unpack, 0, false, true); $unpack = $unpackPacker->pack(); // arguments $params = array($packed, $ascii, $count, $keywords); if ($this->_fastDecode) { $params[] = 0; $params[] = '{}'; } $params = implode(',', $params); // the whole thing return 'eval(' . $unpack . '(' . $params . "))\n"; } private $buffer; private function _insertFastDecode($match) { return '{' . $this->buffer . ';'; } private function _insertFastEncode($match) { return '{$encode=' . $this->buffer . ';'; } // mmm.. ..which one do i need ?? private function _getEncoder($ascii) { return $ascii > 10 ? $ascii > 36 ? $ascii > 62 ? '_encode95' : '_encode62' : '_encode36' : '_encode10'; } // zero encoding // characters: 0123456789 private function _encode10($charCode) { return $charCode; } // inherent base36 support // characters: 0123456789abcdefghijklmnopqrstuvwxyz private function _encode36($charCode) { return base_convert($charCode, 10, 36); } // hitch a ride on base36 and add the upper case alpha characters // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ private function _encode62($charCode) { $res = ''; if ($charCode >= $this->_encoding) { $res = $this->_encode62((int)($charCode / $this->_encoding)); } $charCode = $charCode % $this->_encoding; if ($charCode > 35) return $res . chr($charCode + 29); else return $res . base_convert($charCode, 10, 36); } // use high-ascii values // characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ private function _encode95($charCode) { $res = ''; if ($charCode >= $this->_encoding) $res = $this->_encode95($charCode / $this->_encoding); return $res . chr(($charCode % $this->_encoding) + 161); } private function _safeRegExp($string) { return '/'.preg_replace('/\$/', '\\\$', $string).'/'; } private function _encodePrivate($charCode) { return "_" . $charCode; } // protect characters used by the parser private function _escape($script) { return preg_replace('/([\\\\\'])/', '\\\$1', $script); } // protect high-ascii characters already in the script private function _escape95($script) { return preg_replace_callback( '/[\\xa1-\\xff]/', array(&$this, '_escape95Bis'), $script ); } private function _escape95Bis($match) { return '\x'.((string)dechex(ord($match))); } private function _getJSFunction($aName) { if (defined('self::JSFUNCTION'.$aName)) return constant('self::JSFUNCTION'.$aName); else return ''; } // JavaScript Functions used. // Note : In Dean's version, these functions are converted // with 'String(aFunctionName);'. // This internal conversion complete the original code, ex : // 'while (aBool) anAction();' is converted to // 'while (aBool) { anAction(); }'. // The JavaScript functions below are corrected. // unpacking function - this is the boot strap function // data extracted from this packing routine is passed to // this function when decoded in the target // NOTE ! : without the ';' final. const JSFUNCTION_unpack = 'function($packed, $ascii, $count, $keywords, $encode, $decode) { while ($count--) { if ($keywords[$count]) { $packed = $packed.replace(new RegExp(\'\\\\b\' + $encode($count) + \'\\\\b\', \'g\'), $keywords[$count]); } } return $packed; }'; /* 'function($packed, $ascii, $count, $keywords, $encode, $decode) { while ($count--) if ($keywords[$count]) $packed = $packed.replace(new RegExp(\'\\\\b\' + $encode($count) + \'\\\\b\', \'g\'), $keywords[$count]); return $packed; }'; */ // code-snippet inserted into the unpacker to speed up decoding const JSFUNCTION_decodeBody = //_decode = function() { // does the browser support String.replace where the // replacement value is a function? ' if (!\'\'.replace(/^/, String)) { // decode all the values we need while ($count--) { $decode[$encode($count)] = $keywords[$count] || $encode($count); } // global replacement function $keywords = [function ($encoded) {return $decode[$encoded]}]; // generic match $encode = function () {return \'\\\\w+\'}; // reset the loop counter - we are now doing a global replace $count = 1; } '; //}; /* ' if (!\'\'.replace(/^/, String)) { // decode all the values we need while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count); // global replacement function $keywords = [function ($encoded) {return $decode[$encoded]}]; // generic match $encode = function () {return\'\\\\w+\'}; // reset the loop counter - we are now doing a global replace $count = 1; }'; */ // zero encoding // characters: 0123456789 const JSFUNCTION_encode10 = 'function($charCode) { return $charCode; }';//;'; // inherent base36 support // characters: 0123456789abcdefghijklmnopqrstuvwxyz const JSFUNCTION_encode36 = 'function($charCode) { return $charCode.toString(36); }';//;'; // hitch a ride on base36 and add the upper case alpha characters // characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ const JSFUNCTION_encode62 = 'function($charCode) { return ($charCode < _encoding ? \'\' : arguments.callee(parseInt($charCode / _encoding))) + (($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36)); }'; // use high-ascii values // characters: ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ const JSFUNCTION_encode95 = 'function($charCode) { return ($charCode < _encoding ? \'\' : arguments.callee($charCode / _encoding)) + String.fromCharCode($charCode % _encoding + 161); }'; } class ParseMaster { public $ignoreCase = false; public $escapeChar = ''; // constants const EXPRESSION = 0; const REPLACEMENT = 1; const LENGTH = 2; // used to determine nesting levels private $GROUPS = '/\\(/';//g private $SUB_REPLACE = '/\\$\\d/'; private $INDEXED = '/^\\$\\d+$/'; private $TRIM = '/([\'"])\\1\\.(.*)\\.\\1\\1$/'; private $ESCAPE = '/\\\./';//g private $QUOTE = '/\'/'; private $DELETED = '/\\x01[^\\x01]*\\x01/';//g public function add($expression, $replacement = '') { // count the number of sub-expressions // - add one because each pattern is itself a sub-expression $length = 1 + preg_match_all($this->GROUPS, $this->_internalEscape((string)$expression), $out); // treat only strings $replacement if (is_string($replacement)) { // does the pattern deal with sub-expressions? if (preg_match($this->SUB_REPLACE, $replacement)) { // a simple lookup? (e.g. "$2") if (preg_match($this->INDEXED, $replacement)) { // store the index (used for fast retrieval of matched strings) $replacement = (int)(substr($replacement, 1)) - 1; } else { // a complicated lookup (e.g. "Hello $2 $1") // build a function to do the lookup $quote = preg_match($this->QUOTE, $this->_internalEscape($replacement)) ? '"' : "'"; $replacement = array( 'fn' => '_backReferences', 'data' => array( 'replacement' => $replacement, 'length' => $length, 'quote' => $quote ) ); } } } // pass the modified arguments if (!empty($expression)) $this->_add($expression, $replacement, $length); else $this->_add('/^$/', $replacement, $length); } public function exec($string) { // execute the global replacement $this->_escaped = array(); // simulate the _patterns.toSTring of Dean $regexp = '/'; foreach ($this->_patterns as $reg) { $regexp .= '(' . substr($reg[self::EXPRESSION], 1, -1) . ')|'; } $regexp = substr($regexp, 0, -1) . '/'; $regexp .= ($this->ignoreCase) ? 'i' : ''; $string = $this->_escape($string, $this->escapeChar); $string = preg_replace_callback( $regexp, array( &$this, '_replacement' ), $string ); $string = $this->_unescape($string, $this->escapeChar); return preg_replace($this->DELETED, '', $string); } public function reset() { // clear the patterns collection so that this object may be re-used $this->_patterns = array(); } // private private $_escaped = array(); // escaped characters private $_patterns = array(); // patterns stored by index // create and add a new pattern to the patterns collection private function _add() { $arguments = func_get_args(); $this->_patterns[] = $arguments; } // this is the global replace function (it's quite complicated) private function _replacement($arguments) { if (empty($arguments)) return ''; $i = 1; $j = 0; // loop through the patterns while (isset($this->_patterns[$j])) { $pattern = $this->_patterns[$j++]; // do we have a result? if (isset($arguments[$i]) && ($arguments[$i] != '')) { $replacement = $pattern[self::REPLACEMENT]; if (is_array($replacement) && isset($replacement['fn'])) { if (isset($replacement['data'])) $this->buffer = $replacement['data']; return call_user_func(array(&$this, $replacement['fn']), $arguments, $i); } elseif (is_int($replacement)) { return $arguments[$replacement + $i]; } $delete = ($this->escapeChar == '' || strpos($arguments[$i], $this->escapeChar) === false) ? '' : "\x01" . $arguments[$i] . "\x01"; return $delete . $replacement; // skip over references to sub-expressions } else { $i += $pattern[self::LENGTH]; } } } private function _backReferences($match, $offset) { $replacement = $this->buffer['replacement']; $quote = $this->buffer['quote']; $i = $this->buffer['length']; while ($i) { $replacement = str_replace('$'.$i--, $match[$offset + $i], $replacement); } return $replacement; } private function _replace_name($match, $offset){ $length = strlen($match[$offset + 2]); $start = $length - max($length - strlen($match[$offset + 3]), 0); return substr($match[$offset + 1], $start, $length) . $match[$offset + 4]; } private function _replace_encoded($match, $offset) { return $this->buffer[$match[$offset]]; } // php : we cannot pass additional data to preg_replace_callback, // and we cannot use &$this in create_function, so let's go to lower level private $buffer; // encode escaped characters private function _escape($string, $escapeChar) { if ($escapeChar) { $this->buffer = $escapeChar; return preg_replace_callback( '/\\' . $escapeChar . '(.)' .'/', array(&$this, '_escapeBis'), $string ); } else { return $string; } } private function _escapeBis($match) { $this->_escaped[] = $match[1]; return $this->buffer; } // decode escaped characters private function _unescape($string, $escapeChar) { if ($escapeChar) { $regexp = '/'.'\\'.$escapeChar.'/'; $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0); return preg_replace_callback ( $regexp, array(&$this, '_unescapeBis'), $string ); } else { return $string; } } private function _unescapeBis() { if (isset($this->_escaped[$this->buffer['i']]) && $this->_escaped[$this->buffer['i']] != '') { $temp = $this->_escaped[$this->buffer['i']]; } else { $temp = ''; } $this->buffer['i']++; return $this->buffer['escapeChar'] . $temp; } private function _internalEscape($string) { return preg_replace($this->ESCAPE, '', $string); } } ?> AjaXplorer/AjaXplorer/server/classes/class.SystemTextEncoding.php0000766000000000000000000000345611122202526026445 0ustar adminadministrators AjaXplorer/AjaXplorer/server/classes/class.AuthService.php0000766000000000000000000001356611122202526025072 0ustar adminadministratorssetDebug(false); if(AUTH_MODE_REMOTE_USER != ""){ $client->setAuthorization(AUTH_MODE_REMOTE_USER, AUTH_MODE_REMOTE_PASSWORD); } $client->setCookies(array("PHPSESSID", $remoteSessionId)); $result = $client->get(AUTH_MODE_REMOTE_URL, array("session_id"=>$remoteSessionId)); if($result) { $user = $client->getContent(); if(AuthService::userExists($user)) AuthService::logUser($user, "", true); } } else if(AUTH_MODE == "wordpress"){ global $current_user; wp_get_current_user(); if($current_user->user_login == '' || $current_user->wp_user_level < 8 || !function_exists('ajxp_content')){ die("You are not allowed to see this page!"); } AuthService::logUser($current_user->user_login, "", true); } } function logUser($user_id, $pwd, $bypass_pwd = false, $encodedPwd = false) { if($user_id == null) { if(isSet($_SESSION["AJXP_USER"])) return 1; if(ALLOW_GUEST_BROWSING) { if(!AuthService::userExists("guest")) { AuthService::createUser("guest", ""); $guest = new AJXP_User("guest"); $guest->save(); } AuthService::logUser("guest", null); return 1; } return 0; } // CHECK USER PASSWORD HERE! if(!AuthService::userExists($user_id)) return 0; if(!$bypass_pwd){ if(!AuthService::checkPassword($user_id, $pwd, $encodedPwd)) return -1; } $user = new AJXP_User($user_id); if($user_id == "admin") { $user = AuthService::updateAdminRights($user); } $_SESSION["AJXP_USER"] = $user; AJXP_Logger::logAction("Log In"); return 1; } function updateUser($userObject) { $_SESSION["AJXP_USER"] = $userObject; } function disconnect() { if(isSet($_SESSION["AJXP_USER"])){ AJXP_Logger::logAction("Log Out"); unset($_SESSION["AJXP_USER"]); } } function getDefaultRootId() { $loggedUser = AuthService::getLoggedUser(); if($loggedUser == null) return 0; foreach (array_keys(ConfService::getRootDirsList()) as $rootDirIndex) { if($loggedUser->canRead($rootDirIndex."")) return $rootDirIndex; } return 0; } /** * @param AJXP_User $adminUser */ function updateAdminRights($adminUser) { foreach (array_keys(ConfService::getRootDirsList()) as $rootDirIndex) { $adminUser->setRight($rootDirIndex, "rw"); } $adminUser->save(); return $adminUser; } function userExists($userId) { $users = AuthService::loadLocalUsersList(); if(!is_array($users) || !array_key_exists($userId, $users)) return false; return true; //return(is_dir(USERS_DIR."/".$userId)); } function encodePassword($pass){ return crypt($pass, "ajxp"); } function checkPassword($userId, $userPass, $encodedPass = false) { if($userId == "guest") return true; $users = AuthService::loadLocalUsersList(); if(!$encodedPass){ $cPass = AuthService::encodePassword($userPass); }else{ $cPass = $userPass; } if(!array_key_exists($userId, $users) || $users[$userId] != $cPass) return false; else return true; } function updatePassword($userId, $userPass) { $users = AuthService::loadLocalUsersList(); if(!is_array($users) || !array_key_exists($userId, $users)) return "Error!"; $users[$userId] = AuthService::encodePassword($userPass); AuthService::saveLocalUsersList($users); AJXP_Logger::logAction("Update Password", array("user_id"=>$userId)); return true; } function createUser($userId, $userPass) { $users = AuthService::loadLocalUsersList(); if(!is_array($users)) $users = array(); if(array_key_exists($userId, $users)) return "exists"; $users[$userId] = AuthService::encodePassword($userPass); AuthService::saveLocalUsersList($users); AJXP_Logger::logAction("Create User", array("user_id"=>$userId)); return null; } function deleteUser($userId) { $users = AuthService::loadLocalUsersList(); if(is_array($users) && array_key_exists($userId, $users)) { unset($users[$userId]); AuthService::saveLocalUsersList($users); } if(is_dir(USERS_DIR."/".$userId)) { $rp = opendir(USERS_DIR."/".$userId); while ($file = readdir($rp)) { if($file != "." && $file != "..") { unlink(USERS_DIR."/".$userId."/".$file); } } @rmdir(USERS_DIR."/".$userId); } AJXP_Logger::logAction("Delete User", array("user_id"=>$userId)); return true; } function listUsers() { $allUsers = array(); $users = AuthService::loadLocalUsersList(); foreach (array_keys($users) as $userId) { if($userId == "guest" && !ALLOW_GUEST_BROWSING) continue; $allUsers[$userId] = new AJXP_User($userId); } return $allUsers; } function loadLocalUsersList() { $result = array(); if(is_file(USERS_DIR."/users.ser") && is_readable(USERS_DIR."/users.ser")) { $fileLines = file(USERS_DIR."/users.ser"); $result = unserialize($fileLines[0]); } return $result; } function saveLocalUsersList($usersList) { $fp = fopen(USERS_DIR."/users.ser", "w"); fwrite($fp, serialize($usersList)); fclose($fp); } } ?>AjaXplorer/AjaXplorer/server/classes/class.AJXP_Exception.php0000766000000000000000000000124211122202526025414 0ustar adminadministratorsmessageId = $messageId; } function getMessage(){ return $this->messageId; } function errorToXml($mixed) { if(is_a($mixed, "AJXP_Exception")) { $messages = ConfService::getMessages(); $error = "Unkown Error"; if(isSet($mixed->messageId) && array_key_exists($mixed->messageId, $messages)) { $error = $messages[$mixed->messageId]; }else{ $error = $mixed->messageId; } AJXP_XMLWriter::header(); AJXP_XMLWriter::sendMessage(null, $error); AJXP_XMLWriter::close(); exit(1); } } } ?> AjaXplorer/AjaXplorer/server/classes/pclzip.lib.php0000766000000000000000000076070311122202526023614 0ustar adminadministratorszipname = $p_zipname; $this->zip_fd = 0; $this->magic_quotes_status = -1; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1); return; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : // create($p_filelist, $p_add_dir="", $p_remove_dir="") // create($p_filelist, $p_option, $p_option_value, ...) // Description : // This method supports two different synopsis. The first one is historical. // This method creates a Zip Archive. The Zip file is created in the // filesystem. The files and directories indicated in $p_filelist // are added in the archive. See the parameters description for the // supported format of $p_filelist. // When a directory is in the list, the directory and its content is added // in the archive. // In this synopsis, the function takes an optional variable list of // options. See bellow the supported options. // Parameters : // $p_filelist : An array containing file or directory names, or // a string containing one filename or one directory name, or // a string containing a list of filenames and/or directory // names separated by spaces. // $p_add_dir : A path to add before the real path of the archived file, // in order to have it memorized in the archive. // $p_remove_dir : A path to remove from the real path of the file to archive, // in order to have a shorter path memorized in the archive. // When $p_add_dir and $p_remove_dir are set, $p_remove_dir // is removed first, before $p_add_dir is added. // Options : // PCLZIP_OPT_ADD_PATH : // PCLZIP_OPT_REMOVE_PATH : // PCLZIP_OPT_REMOVE_ALL_PATH : // PCLZIP_OPT_COMMENT : // PCLZIP_CB_PRE_ADD : // PCLZIP_CB_POST_ADD : // Return Values : // 0 on failure, // The list of the added files, with a status of the add action. // (see PclZip::listContent() for list entry format) // -------------------------------------------------------------------------------- function create($p_filelist) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ..."); $v_result=1; // ----- Reset the error handler $this->privErrorReset(); // ----- Set default values $v_options = array(); $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; // ----- Look for variable options arguments $v_size = func_num_args(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method"); // ----- Look for arguments if ($v_size > 1) { // ----- Get the arguments $v_arg_list = func_get_args(); // ----- Remove from the options list the first argument array_shift($v_arg_list); $v_size--; // ----- Look for first arg if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected"); // ----- Parse the options $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (PCLZIP_OPT_REMOVE_PATH => 'optional', PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', PCLZIP_OPT_ADD_PATH => 'optional', PCLZIP_CB_PRE_ADD => 'optional', PCLZIP_CB_POST_ADD => 'optional', PCLZIP_OPT_NO_COMPRESSION => 'optional', PCLZIP_OPT_COMMENT => 'optional' //, PCLZIP_OPT_CRYPT => 'optional' )); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } } // ----- Look for 2 args // Here we need to support the first historic synopsis of the // method. else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis"); // ----- Get the first argument $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0]; // ----- Look for the optional second argument if ($v_size == 2) { $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; } else if ($v_size > 2) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return 0; } } } // ----- Init $v_string_list = array(); $v_att_list = array(); $v_filedescr_list = array(); $p_result_list = array(); // ----- Look if the $p_filelist is really an array if (is_array($p_filelist)) { // ----- Look if the first element is also an array // This will mean that this is a file description entry if (isset($p_filelist[0]) && is_array($p_filelist[0])) { $v_att_list = $p_filelist; } // ----- The list is a list of string names else { $v_string_list = $p_filelist; } } // ----- Look if the $p_filelist is a string else if (is_string($p_filelist)) { // ----- Create a list from the string $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); } // ----- Invalid variable type for $p_filelist else { PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Reformat the string list if (sizeof($v_string_list) != 0) { foreach ($v_string_list as $v_string) { if ($v_string != '') { $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Ignore an empty filename"); } } } // ----- For each file in the list check the attributes $v_supported_attributes = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' ,PCLZIP_ATT_FILE_MTIME => 'optional' ,PCLZIP_ATT_FILE_CONTENT => 'optional' ,PCLZIP_ATT_FILE_COMMENT => 'optional' ); foreach ($v_att_list as $v_entry) { $v_result = $this->privFileDescrParseAtt($v_entry, $v_filedescr_list[], $v_options, $v_supported_attributes); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } } // ----- Expand the filelist (expand directories) $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Call the create fct $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list); return $p_result_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : // add($p_filelist, $p_add_dir="", $p_remove_dir="") // add($p_filelist, $p_option, $p_option_value, ...) // Description : // This method supports two synopsis. The first one is historical. // This methods add the list of files in an existing archive. // If a file with the same name already exists, it is added at the end of the // archive, the first one is still present. // If the archive does not exist, it is created. // Parameters : // $p_filelist : An array containing file or directory names, or // a string containing one filename or one directory name, or // a string containing a list of filenames and/or directory // names separated by spaces. // $p_add_dir : A path to add before the real path of the archived file, // in order to have it memorized in the archive. // $p_remove_dir : A path to remove from the real path of the file to archive, // in order to have a shorter path memorized in the archive. // When $p_add_dir and $p_remove_dir are set, $p_remove_dir // is removed first, before $p_add_dir is added. // Options : // PCLZIP_OPT_ADD_PATH : // PCLZIP_OPT_REMOVE_PATH : // PCLZIP_OPT_REMOVE_ALL_PATH : // PCLZIP_OPT_COMMENT : // PCLZIP_OPT_ADD_COMMENT : // PCLZIP_OPT_PREPEND_COMMENT : // PCLZIP_CB_PRE_ADD : // PCLZIP_CB_POST_ADD : // Return Values : // 0 on failure, // The list of the added files, with a status of the add action. // (see PclZip::listContent() for list entry format) // -------------------------------------------------------------------------------- function add($p_filelist) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ..."); $v_result=1; // ----- Reset the error handler $this->privErrorReset(); // ----- Set default values $v_options = array(); $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; // ----- Look for variable options arguments $v_size = func_num_args(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method"); // ----- Look for arguments if ($v_size > 1) { // ----- Get the arguments $v_arg_list = func_get_args(); // ----- Remove form the options list the first argument array_shift($v_arg_list); $v_size--; // ----- Look for first arg if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected"); // ----- Parse the options $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (PCLZIP_OPT_REMOVE_PATH => 'optional', PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', PCLZIP_OPT_ADD_PATH => 'optional', PCLZIP_CB_PRE_ADD => 'optional', PCLZIP_CB_POST_ADD => 'optional', PCLZIP_OPT_NO_COMPRESSION => 'optional', PCLZIP_OPT_COMMENT => 'optional', PCLZIP_OPT_ADD_COMMENT => 'optional', PCLZIP_OPT_PREPEND_COMMENT => 'optional' //, PCLZIP_OPT_CRYPT => 'optional' )); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } } // ----- Look for 2 args // Here we need to support the first historic synopsis of the // method. else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis"); // ----- Get the first argument $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0]; // ----- Look for the optional second argument if ($v_size == 2) { $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; } else if ($v_size > 2) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return 0; } } } // ----- Init $v_string_list = array(); $v_att_list = array(); $v_filedescr_list = array(); $p_result_list = array(); // ----- Look if the $p_filelist is really an array if (is_array($p_filelist)) { // ----- Look if the first element is also an array // This will mean that this is a file description entry if (isset($p_filelist[0]) && is_array($p_filelist[0])) { $v_att_list = $p_filelist; } // ----- The list is a list of string names else { $v_string_list = $p_filelist; } } // ----- Look if the $p_filelist is a string else if (is_string($p_filelist)) { // ----- Create a list from the string $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); } // ----- Invalid variable type for $p_filelist else { PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Reformat the string list if (sizeof($v_string_list) != 0) { foreach ($v_string_list as $v_string) { $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; } } // ----- For each file in the list check the attributes $v_supported_attributes = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' ,PCLZIP_ATT_FILE_MTIME => 'optional' ,PCLZIP_ATT_FILE_CONTENT => 'optional' ,PCLZIP_ATT_FILE_COMMENT => 'optional' ); foreach ($v_att_list as $v_entry) { $v_result = $this->privFileDescrParseAtt($v_entry, $v_filedescr_list[], $v_options, $v_supported_attributes); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } } // ----- Expand the filelist (expand directories) $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Call the create fct $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list); return $p_result_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : listContent() // Description : // This public method, gives the list of the files and directories, with their // properties. // The properties of each entries in the list are (used also in other functions) : // filename : Name of the file. For a create or add action it is the filename // given by the user. For an extract function it is the filename // of the extracted file. // stored_filename : Name of the file / directory stored in the archive. // size : Size of the stored file. // compressed_size : Size of the file's data compressed in the archive // (without the headers overhead) // mtime : Last known modification date of the file (UNIX timestamp) // comment : Comment associated with the file // folder : true | false // index : index of the file in the archive // status : status of the action (depending of the action) : // Values are : // ok : OK ! // filtered : the file / dir is not extracted (filtered by user) // already_a_directory : the file can not be extracted because a // directory with the same name already exists // write_protected : the file can not be extracted because a file // with the same name already exists and is // write protected // newer_exist : the file was not extracted because a newer file exists // path_creation_fail : the file is not extracted because the folder // does not exists and can not be created // write_error : the file was not extracted because there was a // error while writing the file // read_error : the file was not extracted because there was a error // while reading the file // invalid_header : the file was not extracted because of an archive // format error (bad file header) // Note that each time a method can continue operating when there // is an action error on a file, the error is only logged in the file status. // Return Values : // 0 on an unrecoverable failure, // The list of the files in the archive. // -------------------------------------------------------------------------------- function listContent() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', ""); $v_result=1; // ----- Reset the error handler $this->privErrorReset(); // ----- Check archive if (!$this->privCheckFormat()) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return(0); } // ----- Call the extracting fct $p_list = array(); if (($v_result = $this->privList($p_list)) != 1) { unset($p_list); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo()); return(0); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list); return $p_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : // extract($p_path="./", $p_remove_path="") // extract([$p_option, $p_option_value, ...]) // Description : // This method supports two synopsis. The first one is historical. // This method extract all the files / directories from the archive to the // folder indicated in $p_path. // If you want to ignore the 'root' part of path of the memorized files // you can indicate this in the optional $p_remove_path parameter. // By default, if a newer file with the same name already exists, the // file is not extracted. // // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append // at the end of the path value of PCLZIP_OPT_PATH. // Parameters : // $p_path : Path where the files and directories are to be extracted // $p_remove_path : First part ('root' part) of the memorized path // (if any similar) to remove while extracting. // Options : // PCLZIP_OPT_PATH : // PCLZIP_OPT_ADD_PATH : // PCLZIP_OPT_REMOVE_PATH : // PCLZIP_OPT_REMOVE_ALL_PATH : // PCLZIP_CB_PRE_EXTRACT : // PCLZIP_CB_POST_EXTRACT : // Return Values : // 0 or a negative value on failure, // The list of the extracted files, with a status of the action. // (see PclZip::listContent() for list entry format) // -------------------------------------------------------------------------------- function extract() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", ""); $v_result=1; // ----- Reset the error handler $this->privErrorReset(); // ----- Check archive if (!$this->privCheckFormat()) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return(0); } // ----- Set default values $v_options = array(); // $v_path = "./"; $v_path = ''; $v_remove_path = ""; $v_remove_all_path = false; // ----- Look for variable options arguments $v_size = func_num_args(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method"); // ----- Default values for option $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; // ----- Look for arguments if ($v_size > 0) { // ----- Get the arguments $v_arg_list = func_get_args(); // ----- Look for first arg if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options"); // ----- Parse the options $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (PCLZIP_OPT_PATH => 'optional', PCLZIP_OPT_REMOVE_PATH => 'optional', PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', PCLZIP_OPT_ADD_PATH => 'optional', PCLZIP_CB_PRE_EXTRACT => 'optional', PCLZIP_CB_POST_EXTRACT => 'optional', PCLZIP_OPT_SET_CHMOD => 'optional', PCLZIP_OPT_BY_NAME => 'optional', PCLZIP_OPT_BY_EREG => 'optional', PCLZIP_OPT_BY_PREG => 'optional', PCLZIP_OPT_BY_INDEX => 'optional', PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional', PCLZIP_OPT_REPLACE_NEWER => 'optional' ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional' )); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Set the arguments if (isset($v_options[PCLZIP_OPT_PATH])) { $v_path = $v_options[PCLZIP_OPT_PATH]; } if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; } if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; } if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { // ----- Check for '/' in last path char if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { $v_path .= '/'; } $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; } } // ----- Look for 2 args // Here we need to support the first historic synopsis of the // method. else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis"); // ----- Get the first argument $v_path = $v_arg_list[0]; // ----- Look for the optional second argument if ($v_size == 2) { $v_remove_path = $v_arg_list[1]; } else if ($v_size > 2) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo()); return 0; } } } // ----- Trace //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'"); // ----- Call the extracting fct $p_list = array(); $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options); if ($v_result < 1) { unset($p_list); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo()); return(0); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list); return $p_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : // extractByIndex($p_index, $p_path="./", $p_remove_path="") // extractByIndex($p_index, [$p_option, $p_option_value, ...]) // Description : // This method supports two synopsis. The first one is historical. // This method is doing a partial extract of the archive. // The extracted files or folders are identified by their index in the // archive (from 0 to n). // Note that if the index identify a folder, only the folder entry is // extracted, not all the files included in the archive. // Parameters : // $p_index : A single index (integer) or a string of indexes of files to // extract. The form of the string is "0,4-6,8-12" with only numbers // and '-' for range or ',' to separate ranges. No spaces or ';' // are allowed. // $p_path : Path where the files and directories are to be extracted // $p_remove_path : First part ('root' part) of the memorized path // (if any similar) to remove while extracting. // Options : // PCLZIP_OPT_PATH : // PCLZIP_OPT_ADD_PATH : // PCLZIP_OPT_REMOVE_PATH : // PCLZIP_OPT_REMOVE_ALL_PATH : // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and // not as files. // The resulting content is in a new field 'content' in the file // structure. // This option must be used alone (any other options are ignored). // PCLZIP_CB_PRE_EXTRACT : // PCLZIP_CB_POST_EXTRACT : // Return Values : // 0 on failure, // The list of the extracted files, with a status of the action. // (see PclZip::listContent() for list entry format) // -------------------------------------------------------------------------------- //function extractByIndex($p_index, options...) function extractByIndex($p_index) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ..."); $v_result=1; // ----- Reset the error handler $this->privErrorReset(); // ----- Check archive if (!$this->privCheckFormat()) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return(0); } // ----- Set default values $v_options = array(); // $v_path = "./"; $v_path = ''; $v_remove_path = ""; $v_remove_all_path = false; // ----- Look for variable options arguments $v_size = func_num_args(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method"); // ----- Default values for option $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; // ----- Look for arguments if ($v_size > 1) { // ----- Get the arguments $v_arg_list = func_get_args(); // ----- Remove form the options list the first argument array_shift($v_arg_list); $v_size--; // ----- Look for first arg if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options"); // ----- Parse the options $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (PCLZIP_OPT_PATH => 'optional', PCLZIP_OPT_REMOVE_PATH => 'optional', PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', PCLZIP_OPT_ADD_PATH => 'optional', PCLZIP_CB_PRE_EXTRACT => 'optional', PCLZIP_CB_POST_EXTRACT => 'optional', PCLZIP_OPT_SET_CHMOD => 'optional', PCLZIP_OPT_REPLACE_NEWER => 'optional' ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional' )); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Set the arguments if (isset($v_options[PCLZIP_OPT_PATH])) { $v_path = $v_options[PCLZIP_OPT_PATH]; } if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; } if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; } if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { // ----- Check for '/' in last path char if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { $v_path .= '/'; } $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; } if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) { $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set."); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set."); } } // ----- Look for 2 args // Here we need to support the first historic synopsis of the // method. else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis"); // ----- Get the first argument $v_path = $v_arg_list[0]; // ----- Look for the optional second argument if ($v_size == 2) { $v_remove_path = $v_arg_list[1]; } else if ($v_size > 2) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return 0; } } } // ----- Trace //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'"); // ----- Trick // Here I want to reuse extractByRule(), so I need to parse the $p_index // with privParseOptions() $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index); $v_options_trick = array(); $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, array (PCLZIP_OPT_BY_INDEX => 'optional' )); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX]; // ----- Call the extracting fct if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo()); return(0); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list); return $p_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : // delete([$p_option, $p_option_value, ...]) // Description : // This method removes files from the archive. // If no parameters are given, then all the archive is emptied. // Parameters : // None or optional arguments. // Options : // PCLZIP_OPT_BY_INDEX : // PCLZIP_OPT_BY_NAME : // PCLZIP_OPT_BY_EREG : // PCLZIP_OPT_BY_PREG : // Return Values : // 0 on failure, // The list of the files which are still present in the archive. // (see PclZip::listContent() for list entry format) // -------------------------------------------------------------------------------- function delete() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", ""); $v_result=1; // ----- Reset the error handler $this->privErrorReset(); // ----- Check archive if (!$this->privCheckFormat()) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return(0); } // ----- Set default values $v_options = array(); // ----- Look for variable options arguments $v_size = func_num_args(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method"); // ----- Look for arguments if ($v_size > 0) { // ----- Get the arguments $v_arg_list = func_get_args(); // ----- Parse the options $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, array (PCLZIP_OPT_BY_NAME => 'optional', PCLZIP_OPT_BY_EREG => 'optional', PCLZIP_OPT_BY_PREG => 'optional', PCLZIP_OPT_BY_INDEX => 'optional' )); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } } // ----- Magic quotes trick $this->privDisableMagicQuotes(); // ----- Call the delete fct $v_list = array(); if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) { $this->privSwapBackMagicQuotes(); unset($v_list); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo()); return(0); } // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_list); return $v_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : deleteByIndex() // Description : // ***** Deprecated ***** // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered. // -------------------------------------------------------------------------------- function deleteByIndex($p_index) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'"); $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list); return $p_list; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : properties() // Description : // This method gives the properties of the archive. // The properties are : // nb : Number of files in the archive // comment : Comment associated with the archive file // status : not_exist, ok // Parameters : // None // Return Values : // 0 on failure, // An array with the archive properties. // -------------------------------------------------------------------------------- function properties() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", ""); // ----- Reset the error handler $this->privErrorReset(); // ----- Magic quotes trick $this->privDisableMagicQuotes(); // ----- Check archive if (!$this->privCheckFormat()) { $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return(0); } // ----- Default properties $v_prop = array(); $v_prop['comment'] = ''; $v_prop['nb'] = 0; $v_prop['status'] = 'not_exist'; // ----- Look if file exists if (@is_file($this->zipname)) { // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) { $this->privSwapBackMagicQuotes(); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0); return 0; } // ----- Read the central directory informations $v_central_dir = array(); if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) { $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return 0; } // ----- Close the zip file $this->privCloseFd(); // ----- Set the user attributes $v_prop['comment'] = $v_central_dir['comment']; $v_prop['nb'] = $v_central_dir['entries']; $v_prop['status'] = 'ok'; } // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_prop); return $v_prop; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : duplicate() // Description : // This method creates an archive by copying the content of an other one. If // the archive already exist, it is replaced by the new one without any warning. // Parameters : // $p_archive : The filename of a valid archive, or // a valid PclZip object. // Return Values : // 1 on success. // 0 or a negative value on error (error code). // -------------------------------------------------------------------------------- function duplicate($p_archive) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", ""); $v_result = 1; // ----- Reset the error handler $this->privErrorReset(); // ----- Look if the $p_archive is a PclZip object if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'"); // ----- Duplicate the archive $v_result = $this->privDuplicate($p_archive->zipname); } // ----- Look if the $p_archive is a string (so a filename) else if (is_string($p_archive)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'"); // ----- Check that $p_archive is a valid zip file // TBC : Should also check the archive format if (!is_file($p_archive)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'"); $v_result = PCLZIP_ERR_MISSING_FILE; } else { // ----- Duplicate the archive $v_result = $this->privDuplicate($p_archive); } } // ----- Invalid variable else { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); $v_result = PCLZIP_ERR_INVALID_PARAMETER; } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : merge() // Description : // This method merge the $p_archive_to_add archive at the end of the current // one ($this). // If the archive ($this) does not exist, the merge becomes a duplicate. // If the $p_archive_to_add archive does not exist, the merge is a success. // Parameters : // $p_archive_to_add : It can be directly the filename of a valid zip archive, // or a PclZip object archive. // Return Values : // 1 on success, // 0 or negative values on error (see below). // -------------------------------------------------------------------------------- function merge($p_archive_to_add) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", ""); $v_result = 1; // ----- Reset the error handler $this->privErrorReset(); // ----- Check archive if (!$this->privCheckFormat()) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0); return(0); } // ----- Look if the $p_archive_to_add is a PclZip object if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object"); // ----- Merge the archive $v_result = $this->privMerge($p_archive_to_add); } // ----- Look if the $p_archive_to_add is a string (so a filename) else if (is_string($p_archive_to_add)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename"); // ----- Create a temporary archive $v_object_archive = new PclZip($p_archive_to_add); // ----- Merge the archive $v_result = $this->privMerge($v_object_archive); } // ----- Invalid variable else { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); $v_result = PCLZIP_ERR_INVALID_PARAMETER; } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : errorCode() // Description : // Parameters : // -------------------------------------------------------------------------------- function errorCode() { if (PCLZIP_ERROR_EXTERNAL == 1) { return(PclErrorCode()); } else { return($this->error_code); } } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : errorName() // Description : // Parameters : // -------------------------------------------------------------------------------- function errorName($p_with_code=false) { $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR', PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL', PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL', PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER', PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE', PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG', PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP', PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE', PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL', PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION', PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT', PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL', PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL', PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM', PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE', PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE', PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE' ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION' ); if (isset($v_name[$this->error_code])) { $v_value = $v_name[$this->error_code]; } else { $v_value = 'NoName'; } if ($p_with_code) { return($v_value.' ('.$this->error_code.')'); } else { return($v_value); } } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : errorInfo() // Description : // Parameters : // -------------------------------------------------------------------------------- function errorInfo($p_full=false) { if (PCLZIP_ERROR_EXTERNAL == 1) { return(PclErrorString()); } else { if ($p_full) { return($this->errorName(true)." : ".$this->error_string); } else { return($this->error_string." [code ".$this->error_code."]"); } } } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** // ***** ***** // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privCheckFormat() // Description : // This method check that the archive exists and is a valid zip archive. // Several level of check exists. (futur) // Parameters : // $p_level : Level of check. Default 0. // 0 : Check the first bytes (magic codes) (default value)) // 1 : 0 + Check the central directory (futur) // 2 : 1 + Check each file header (futur) // Return Values : // true on success, // false on error, the error code is set. // -------------------------------------------------------------------------------- function privCheckFormat($p_level=0) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", ""); $v_result = true; // ----- Reset the file system cache clearstatcache(); // ----- Reset the error handler $this->privErrorReset(); // ----- Look if the file exits if (!is_file($this->zipname)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo()); return(false); } // ----- Check that the file is readeable if (!is_readable($this->zipname)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo()); return(false); } // ----- Check the magic code // TBC // ----- Check the central header // TBC // ----- Check each file header // TBC // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privParseOptions() // Description : // This internal methods reads the variable list of arguments ($p_options_list, // $p_size) and generate an array with the options and values ($v_result_list). // $v_requested_options contains the options that can be present and those that // must be present. // $v_requested_options is an array, with the option value as key, and 'optional', // or 'mandatory' as value. // Parameters : // See above. // Return Values : // 1 on success. // 0 on failure. // -------------------------------------------------------------------------------- function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", ""); $v_result=1; // ----- Read the options $i=0; while ($i<$p_size) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'"); // ----- Check if the option is supported if (!isset($v_requested_options[$p_options_list[$i]])) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Look for next option switch ($p_options_list[$i]) { // ----- Look for options that request a path value case PCLZIP_OPT_PATH : case PCLZIP_OPT_REMOVE_PATH : case PCLZIP_OPT_ADD_PATH : // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'"); $i++; break; case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value if ( is_string($p_options_list[$i+1]) && ($p_options_list[$i+1] != '')) { $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'"); $i++; } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." set with an empty value is ignored."); } break; // ----- Look for options that request an array of string for value case PCLZIP_OPT_BY_NAME : // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value if (is_string($p_options_list[$i+1])) { $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1]; } else if (is_array($p_options_list[$i+1])) { $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; } else { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'"); $i++; break; // ----- Look for options that request an EREG or PREG expression case PCLZIP_OPT_BY_EREG : case PCLZIP_OPT_BY_PREG : //case PCLZIP_OPT_CRYPT : // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value if (is_string($p_options_list[$i+1])) { $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; } else { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'"); $i++; break; // ----- Look for options that takes a string case PCLZIP_OPT_COMMENT : case PCLZIP_OPT_ADD_COMMENT : case PCLZIP_OPT_PREPEND_COMMENT : // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '" .PclZipUtilOptionText($p_options_list[$i]) ."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value if (is_string($p_options_list[$i+1])) { $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; } else { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '" .PclZipUtilOptionText($p_options_list[$i]) ."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'"); $i++; break; // ----- Look for options that request an array of index case PCLZIP_OPT_BY_INDEX : // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value $v_work_list = array(); if (is_string($p_options_list[$i+1])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'"); // ----- Remove spaces $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', ''); // ----- Parse items $v_work_list = explode(",", $p_options_list[$i+1]); } else if (is_integer($p_options_list[$i+1])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'"); $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1]; } else if (is_array($p_options_list[$i+1])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array"); $v_work_list = $p_options_list[$i+1]; } else { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Reduce the index list // each index item in the list must be a couple with a start and // an end value : [0,3], [5-5], [8-10], ... // ----- Check the format of each item $v_sort_flag=false; $v_sort_value=0; for ($j=0; $j= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'"); $i++; break; // ----- Look for options that request a call-back case PCLZIP_CB_PRE_EXTRACT : case PCLZIP_CB_POST_EXTRACT : case PCLZIP_CB_PRE_ADD : case PCLZIP_CB_POST_ADD : /* for futur use case PCLZIP_CB_PRE_DELETE : case PCLZIP_CB_POST_DELETE : case PCLZIP_CB_PRE_LIST : case PCLZIP_CB_POST_LIST : */ // ----- Check the number of parameters if (($i+1) >= $p_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Get the value $v_function_name = $p_options_list[$i+1]; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'"); // ----- Check that the value is a valid existing function if (!function_exists($v_function_name)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Set the attribute $v_result_list[$p_options_list[$i]] = $v_function_name; $i++; break; default : // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Unknown parameter '" .$p_options_list[$i]."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Next options $i++; } // ----- Look for mandatory options if ($v_requested_options !== false) { for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { // ----- Look for mandatory option if ($v_requested_options[$key] == 'mandatory') { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")"); // ----- Look if present if (!isset($v_result_list[$key])) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } } } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privFileDescrParseAtt() // Description : // Parameters : // Return Values : // 1 on success. // 0 on failure. // -------------------------------------------------------------------------------- function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrParseAtt", ""); $v_result=1; // ----- For each file in the list check the attributes foreach ($p_file_list as $v_key => $v_value) { // ----- Check if the option is supported if (!isset($v_requested_options[$v_key])) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Look for attribute switch ($v_key) { case PCLZIP_ATT_FILE_NAME : if (!is_string($v_value)) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } $p_filedescr['filename'] = PclZipUtilPathReduction($v_value); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'"); if ($p_filedescr['filename'] == '') { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } break; case PCLZIP_ATT_FILE_NEW_SHORT_NAME : if (!is_string($v_value)) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'"); if ($p_filedescr['new_short_name'] == '') { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } break; case PCLZIP_ATT_FILE_NEW_FULL_NAME : if (!is_string($v_value)) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'"); if ($p_filedescr['new_full_name'] == '') { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } break; // ----- Look for options that takes a string case PCLZIP_ATT_FILE_COMMENT : if (!is_string($v_value)) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } $p_filedescr['comment'] = $v_value; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'"); break; case PCLZIP_ATT_FILE_MTIME : if (!is_integer($v_value)) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } $p_filedescr['mtime'] = $v_value; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'"); break; case PCLZIP_ATT_FILE_CONTENT : $p_filedescr['content'] = $v_value; ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'"); break; default : // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Unknown parameter '".$v_key."'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Look for mandatory options if ($v_requested_options !== false) { for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { // ----- Look for mandatory option if ($v_requested_options[$key] == 'mandatory') { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")"); // ----- Look if present if (!isset($p_file_list[$key])) { PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } } } // end foreach } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privFileDescrExpand() // Description : // Parameters : // Return Values : // 1 on success. // 0 on failure. // -------------------------------------------------------------------------------- function privFileDescrExpand(&$p_filedescr_list, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrExpand", ""); $v_result=1; // ----- Create a result list $v_result_list = array(); // ----- Look each entry for ($i=0; $iprivCalculateStoredFilename($v_descr, $p_options); // ----- Add the descriptor in result list $v_result_list[sizeof($v_result_list)] = $v_descr; // ----- Look for folder if ($v_descr['type'] == 'folder') { // ----- List of items in folder $v_dirlist_descr = array(); $v_dirlist_nb = 0; if ($v_folder_handler = @opendir($v_descr['filename'])) { while (($v_item_handler = @readdir($v_folder_handler)) !== false) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for '".$v_item_handler."' in the directory"); // ----- Skip '.' and '..' if (($v_item_handler == '.') || ($v_item_handler == '..')) { continue; } // ----- Compose the full filename $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler; // ----- Look for different stored filename // Because the name of the folder was changed, the name of the // files/sub-folders also change if ($v_descr['stored_filename'] != $v_descr['filename']) { if ($v_descr['stored_filename'] != '') { $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler; } else { $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler; } } $v_dirlist_nb++; } @closedir($v_folder_handler); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to open dir '".$v_descr['filename']."' in read mode. Skipped."); // TBC : unable to open folder in read mode } // ----- Expand each element of the list if ($v_dirlist_nb != 0) { // ----- Expand if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Concat the resulting list //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Merging result list (size '".sizeof($v_result_list)."') with dirlist (size '".sizeof($v_dirlist_descr)."')"); $v_result_list = array_merge($v_result_list, $v_dirlist_descr); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "merged result list is size '".sizeof($v_result_list)."'"); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Nothing in this folder to expand."); } // ----- Free local array unset($v_dirlist_descr); } } // ----- Get the result list $p_filedescr_list = $v_result_list; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privCreate() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privCreate($p_filedescr_list, &$p_result_list, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list"); $v_result=1; $v_list_detail = array(); // ----- Magic quotes trick $this->privDisableMagicQuotes(); // ----- Open the file in write mode if (($v_result = $this->privOpenFd('wb')) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Add the list of files $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options); // ----- Close $this->privCloseFd(); // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privAdd() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privAdd($p_filedescr_list, &$p_result_list, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list"); $v_result=1; $v_list_detail = array(); // ----- Look if the archive exists or is empty if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it."); // ----- Do a create $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Magic quotes trick $this->privDisableMagicQuotes(); // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_result=$this->privOpenFd('rb')) != 1) { // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Read the central directory informations $v_central_dir = array(); if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Go to beginning of File //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'"); // ----- Creates a temporay file $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; // ----- Open the temporary file in write mode //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Copy the files from the archive to the temporary file // TBC : Here I should better append the file and go back to erase the central dir $v_size = $v_central_dir['offset']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = fread($this->zip_fd, $v_read_size); @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Swap the file descriptor // Here is a trick : I swap the temporary fd with the zip fd, in order to use // the following methods on the temporary fil and not the real archive $v_swap = $this->zip_fd; $this->zip_fd = $v_zip_temp_fd; $v_zip_temp_fd = $v_swap; // ----- Add the files $v_header_list = array(); if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) { fclose($v_zip_temp_fd); $this->privCloseFd(); @unlink($v_zip_temp_name); $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Store the offset of the central dir $v_offset = @ftell($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset"); // ----- Copy the block of file headers from the old archive $v_size = $v_central_dir['size']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @fread($v_zip_temp_fd, $v_read_size); @fwrite($this->zip_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Create the Central Dir files header for ($i=0, $v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { fclose($v_zip_temp_fd); $this->privCloseFd(); @unlink($v_zip_temp_name); $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } $v_count++; } // ----- Transform the header to a 'usable' info $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); } // ----- Zip file comment $v_comment = $v_central_dir['comment']; if (isset($p_options[PCLZIP_OPT_COMMENT])) { $v_comment = $p_options[PCLZIP_OPT_COMMENT]; } if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) { $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT]; } if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) { $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment; } // ----- Calculate the size of the central header $v_size = @ftell($this->zip_fd)-$v_offset; // ----- Create the central dir footer if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) { // ----- Reset the file list unset($v_header_list); $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Swap back the file descriptor $v_swap = $this->zip_fd; $this->zip_fd = $v_zip_temp_fd; $v_zip_temp_fd = $v_swap; // ----- Close $this->privCloseFd(); // ----- Close the temporary file @fclose($v_zip_temp_fd); // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Delete the zip file // TBC : I should test the result ... @unlink($this->zipname); // ----- Rename the temporary file // TBC : I should test the result ... //@rename($v_zip_temp_name, $this->zipname); PclZipUtilRename($v_zip_temp_name, $this->zipname); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privOpenFd() // Description : // Parameters : // -------------------------------------------------------------------------------- function privOpenFd($p_mode) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode); $v_result=1; // ----- Look if already open if ($this->zip_fd != 0) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode'); if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privCloseFd() // Description : // Parameters : // -------------------------------------------------------------------------------- function privCloseFd() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", ""); $v_result=1; if ($this->zip_fd != 0) @fclose($this->zip_fd); $this->zip_fd = 0; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privAddList() // Description : // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is // different from the real path of the file. This is usefull if you want to have PclTar // running in any directory, and memorize relative path from an other directory. // Parameters : // $p_list : An array containing the file or directory names to add in the tar // $p_result_list : list of added files with their properties (specially the status field) // $p_add_dir : Path to add in the filename path archived // $p_remove_dir : Path to remove in the filename path archived // Return Values : // -------------------------------------------------------------------------------- // function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) function privAddList($p_filedescr_list, &$p_result_list, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list"); $v_result=1; // ----- Add the files $v_header_list = array(); if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Store the offset of the central dir $v_offset = @ftell($this->zip_fd); // ----- Create the Central Dir files header for ($i=0,$v_count=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } $v_count++; } // ----- Transform the header to a 'usable' info $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); } // ----- Zip file comment $v_comment = ''; if (isset($p_options[PCLZIP_OPT_COMMENT])) { $v_comment = $p_options[PCLZIP_OPT_COMMENT]; } // ----- Calculate the size of the central header $v_size = @ftell($this->zip_fd)-$v_offset; // ----- Create the central dir footer if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) { // ----- Reset the file list unset($v_header_list); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privAddFileList() // Description : // Parameters : // $p_filedescr_list : An array containing the file description // or directory names to add in the zip // $p_result_list : list of added files with their properties (specially the status field) // Return Values : // -------------------------------------------------------------------------------- function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "filedescr_list"); $v_result=1; $v_header = array(); // ----- Recuperate the current number of elt in list $v_nb = sizeof($p_result_list); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have ".$v_nb." elements"); // ----- Loop on the files for ($j=0; ($jprivAddFile($p_filedescr_list[$j], $v_header, $p_options); if ($v_result != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Store the file infos $p_result_list[$v_nb++] = $v_header; } } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have ".$v_nb." elements"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privAddFile() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privAddFile($p_filedescr, &$p_header, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='".$p_filedescr['filename']."'"); $v_result=1; // ----- Working variable $p_filename = $p_filedescr['filename']; // TBC : Already done in the fileAtt check ... ? if ($p_filename == "") { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Look for a stored different filename /* TBC : Removed if (isset($p_filedescr['stored_filename'])) { $v_stored_filename = $p_filedescr['stored_filename']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is NOT the same "'.$v_stored_filename.'"'); } else { $v_stored_filename = $p_filedescr['stored_filename']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is the same'); } */ // ----- Set the file properties clearstatcache(); $p_header['version'] = 20; $p_header['version_extracted'] = 10; $p_header['flag'] = 0; $p_header['compression'] = 0; $p_header['crc'] = 0; $p_header['compressed_size'] = 0; $p_header['filename_len'] = strlen($p_filename); $p_header['extra_len'] = 0; $p_header['disk'] = 0; $p_header['internal'] = 0; $p_header['offset'] = 0; $p_header['filename'] = $p_filename; // TBC : Removed $p_header['stored_filename'] = $v_stored_filename; $p_header['stored_filename'] = $p_filedescr['stored_filename']; $p_header['extra'] = ''; $p_header['status'] = 'ok'; $p_header['index'] = -1; // ----- Look for regular file if ($p_filedescr['type']=='file') { $p_header['external'] = 0x00000000; $p_header['size'] = filesize($p_filename); } // ----- Look for regular folder else if ($p_filedescr['type']=='folder') { $p_header['external'] = 0x00000010; $p_header['mtime'] = filemtime($p_filename); $p_header['size'] = filesize($p_filename); } // ----- Look for virtual file else if ($p_filedescr['type'] == 'virtual_file') { $p_header['external'] = 0x00000000; $p_header['size'] = strlen($p_filedescr['content']); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header external extension '".sprintf("0x%X",$p_header['external'])."'"); // ----- Look for filetime if (isset($p_filedescr['mtime'])) { $p_header['mtime'] = $p_filedescr['mtime']; } else if ($p_filedescr['type'] == 'virtual_file') { $p_header['mtime'] = mktime(); } else { $p_header['mtime'] = filemtime($p_filename); } // ------ Look for file comment if (isset($p_filedescr['comment'])) { $p_header['comment_len'] = strlen($p_filedescr['comment']); $p_header['comment'] = $p_filedescr['comment']; } else { $p_header['comment_len'] = 0; $p_header['comment'] = ''; } // ----- Look for pre-add callback if (isset($p_options[PCLZIP_CB_PRE_ADD])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction"); // ----- Generate a local information $v_local_header = array(); $this->privConvertHeader2FileInfo($p_header, $v_local_header); // ----- Call the callback // Here I do not use call_user_func() because I need to send a reference to the // header. eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);'); if ($v_result == 0) { // ----- Change the file status $p_header['status'] = "skipped"; $v_result = 1; } // ----- Update the informations // Only some fields can be modified if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'"); } } // ----- Look for empty stored filename if ($p_header['stored_filename'] == "") { $p_header['status'] = "filtered"; } // ----- Check the path length if (strlen($p_header['stored_filename']) > 0xFF) { $p_header['status'] = 'filename_too_long'; } // ----- Look if no error, or file not skipped if ($p_header['status'] == 'ok') { // ----- Look for a file // if (is_file($p_filename)) if ( ($p_filedescr['type'] == 'file') || ($p_filedescr['type'] == 'virtual_file')) { // ----- Get content from real file if ($p_filedescr['type'] == 'file') { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file"); // ----- Open the source file if (($v_file = @fopen($p_filename, "rb")) == 0) { PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Read the file content $v_content = @fread($v_file, $p_header['size']); // ----- Close the file @fclose($v_file); } else if ($p_filedescr['type'] == 'virtual_file') { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Add by string"); $v_content = $p_filedescr['content']; } // ----- Calculate the CRC $p_header['crc'] = @crc32($v_content); // ----- Look for no compression if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed"); // ----- Set header parameters $p_header['compressed_size'] = $p_header['size']; $p_header['compression'] = 0; } // ----- Look for normal compression else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed"); // ----- Compress the content $v_content = @gzdeflate($v_content); // ----- Set header parameters $p_header['compressed_size'] = strlen($v_content); $p_header['compression'] = 8; } // ----- Look for encryption /* if ((isset($p_options[PCLZIP_OPT_CRYPT])) && ($p_options[PCLZIP_OPT_CRYPT] != "")) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File need to be crypted ...."); // Should be a random header $v_header = 'xxxxxxxxxxxx'; $v_content_compressed = PclZipUtilZipEncrypt($v_content_compressed, $p_header['compressed_size'], $v_header, $p_header['crc'], "test"); $p_header['compressed_size'] += 12; $p_header['flag'] = 1; // ----- Add the header to the data $v_content_compressed = $v_header.$v_content_compressed; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size after header : ".strlen($v_content_compressed).""); } */ // ----- Call the header generation if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { @fclose($v_file); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Write the compressed (or not) content @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); } // ----- Look for a directory else if ($p_filedescr['type'] == 'folder') { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a folder"); // ----- Look for directory last '/' if (@substr($p_header['stored_filename'], -1) != '/') { $p_header['stored_filename'] .= '/'; } // ----- Set the file properties $p_header['size'] = 0; //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked $p_header['external'] = 0x00000010; // Value for a folder : to be checked // ----- Call the header generation if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } } } // ----- Look for post-add callback if (isset($p_options[PCLZIP_CB_POST_ADD])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction"); // ----- Generate a local information $v_local_header = array(); $this->privConvertHeader2FileInfo($p_header, $v_local_header); // ----- Call the callback // Here I do not use call_user_func() because I need to send a reference to the // header. eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);'); if ($v_result == 0) { // ----- Ignored $v_result = 1; } // ----- Update the informations // Nothing can be modified } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privCalculateStoredFilename() // Description : // Based on file descriptor properties and global options, this method // calculate the filename that will be stored in the archive. // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privCalculateStoredFilename(&$p_filedescr, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCalculateStoredFilename", "filename='".$p_filedescr['filename']."'"); $v_result=1; // ----- Working variables $p_filename = $p_filedescr['filename']; if (isset($p_options[PCLZIP_OPT_ADD_PATH])) { $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH]; } else { $p_add_dir = ''; } if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) { $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH]; } else { $p_remove_dir = ''; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Remove path ='".$p_remove_dir."'"); if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH]; } else { $p_remove_all_dir = 0; } // ----- Look for full name change if (isset($p_filedescr['new_full_name'])) { $v_stored_filename = $p_filedescr['new_full_name']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing full name of '".$p_filename."' for '".$v_stored_filename."'"); } // ----- Look for path and/or short name change else { // ----- Look for short name change if (isset($p_filedescr['new_short_name'])) { $v_path_info = pathinfo($p_filename); $v_dir = ''; if ($v_path_info['dirname'] != '') { $v_dir = $v_path_info['dirname'].'/'; } $v_stored_filename = $v_dir.$p_filedescr['new_short_name']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing short name of '".$p_filename."' for '".$v_stored_filename."'"); } else { // ----- Calculate the stored filename $v_stored_filename = $p_filename; } // ----- Look for all path to remove if ($p_remove_all_dir) { $v_stored_filename = basename($p_filename); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove all path selected change '".$p_filename."' for '".$v_stored_filename."'"); } // ----- Look for partial path remove else if ($p_remove_dir != "") { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Partial path to remove"); if (substr($p_remove_dir, -1) != '/') $p_remove_dir .= "/"; if ( (substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./")) { if ( (substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./")) { $p_remove_dir = "./".$p_remove_dir; } if ( (substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./")) { $p_remove_dir = substr($p_remove_dir, 2); } } $v_compare = PclZipUtilPathInclusion($p_remove_dir, $v_stored_filename); if ($v_compare > 0) { if ($v_compare == 2) { $v_stored_filename = ""; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder"); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$v_stored_filename'"); $v_stored_filename = substr($v_stored_filename, strlen($p_remove_dir)); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Result is '$v_stored_filename'"); } } } // ----- Look for path to add if ($p_add_dir != "") { if (substr($p_add_dir, -1) == "/") $v_stored_filename = $p_add_dir.$v_stored_filename; else $v_stored_filename = $p_add_dir."/".$v_stored_filename; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'"); } } // ----- Filename (reduce the path of stored name) $v_stored_filename = PclZipUtilPathReduction($v_stored_filename); $p_filedescr['stored_filename'] = $v_stored_filename; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Stored filename will be '".$p_filedescr['stored_filename']."', strlen ".strlen($p_filedescr['stored_filename'])); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privWriteFileHeader() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privWriteFileHeader(&$p_header) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"'); $v_result=1; // ----- Store the offset position of the file $p_header['offset'] = ftell($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']); // ----- Transform UNIX mtime to DOS format mdate/mtime //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\''); $v_date = getdate($p_header['mtime']); $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; // ----- Packed data $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len']); // ----- Write the first 148 bytes of the header in the archive fputs($this->zip_fd, $v_binary_data, 30); // ----- Write the variable fields if (strlen($p_header['stored_filename']) != 0) { fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); } if ($p_header['extra_len'] != 0) { fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privWriteCentralFileHeader() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privWriteCentralFileHeader(&$p_header) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"'); $v_result=1; // TBC //for(reset($p_header); $key = key($p_header); next($p_header)) { // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]); //} // ----- Transform UNIX mtime to DOS format mdate/mtime //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\''); $v_date = getdate($p_header['mtime']); $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$p_header['comment_len'].'\''); // ----- Packed data $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'], $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']); // ----- Write the 42 bytes of the header in the zip file fputs($this->zip_fd, $v_binary_data, 46); // ----- Write the variable fields if (strlen($p_header['stored_filename']) != 0) { fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); } if ($p_header['extra_len'] != 0) { fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); } if ($p_header['comment_len'] != 0) { fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privWriteCentralHeader() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"'); $v_result=1; // ----- Packed data $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment)); // ----- Write the 22 bytes of the header in the zip file fputs($this->zip_fd, $v_binary_data, 22); // ----- Write the variable fields if (strlen($p_comment) != 0) { fputs($this->zip_fd, $p_comment, strlen($p_comment)); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privList() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privList(&$p_list) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list"); $v_result=1; // ----- Magic quotes trick $this->privDisableMagicQuotes(); // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) { // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Read the central directory informations $v_central_dir = array(); if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) { $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Go to beginning of Central Dir //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'"); if (@fseek($this->zip_fd, $v_central_dir['offset'])) { $this->privSwapBackMagicQuotes(); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'"); // ----- Read each entry for ($i=0; $i<$v_central_dir['entries']; $i++) { // ----- Read the file header if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) { $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } $v_header['index'] = $i; // ----- Get the only interesting attributes $this->privConvertHeader2FileInfo($v_header, $p_list[$i]); unset($v_header); } // ----- Close the zip file $this->privCloseFd(); // ----- Magic quotes trick $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privConvertHeader2FileInfo() // Description : // This function takes the file informations from the central directory // entries and extract the interesting parameters that will be given back. // The resulting file infos are set in the array $p_info // $p_info['filename'] : Filename with full path. Given by user (add), // extracted in the filesystem (extract). // $p_info['stored_filename'] : Stored filename in the archive. // $p_info['size'] = Size of the file. // $p_info['compressed_size'] = Compressed size of the file. // $p_info['mtime'] = Last modification date of the file. // $p_info['comment'] = Comment associated with the file. // $p_info['folder'] = true/false : indicates if the entry is a folder or not. // $p_info['status'] = status of the action on the file. // $p_info['crc'] = CRC of the file content. // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privConvertHeader2FileInfo($p_header, &$p_info) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'"); $v_result=1; // ----- Get the interesting attributes $p_info['filename'] = $p_header['filename']; $p_info['stored_filename'] = $p_header['stored_filename']; $p_info['size'] = $p_header['size']; $p_info['compressed_size'] = $p_header['compressed_size']; $p_info['mtime'] = $p_header['mtime']; $p_info['comment'] = $p_header['comment']; $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); $p_info['index'] = $p_header['index']; $p_info['status'] = $p_header['status']; $p_info['crc'] = $p_header['crc']; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privExtractByRule() // Description : // Extract a file or directory depending of rules (by index, by name, ...) // Parameters : // $p_file_list : An array where will be placed the properties of each // extracted file // $p_path : Path to add while writing the extracted files // $p_remove_path : Path to remove (from the file memorized path) while writing the // extracted files. If the path does not match the file path, // the file is extracted with its memorized path. // $p_remove_path does not apply to 'list' mode. // $p_path and $p_remove_path are commulative. // Return Values : // 1 on success,0 or less on error (see error code list) // -------------------------------------------------------------------------------- function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'"); $v_result=1; // ----- Magic quotes trick $this->privDisableMagicQuotes(); // ----- Check the path if ( ($p_path == "") || ( (substr($p_path, 0, 1) != "/") && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/"))) $p_path = "./".$p_path; // ----- Reduce the path last (and duplicated) '/' if (($p_path != "./") && ($p_path != "/")) { // ----- Look for the path end '/' while (substr($p_path, -1) == "/") { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'"); $p_path = substr($p_path, 0, strlen($p_path)-1); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]"); } } // ----- Look for path to remove format (should end by /) if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) { $p_remove_path .= '/'; } $p_remove_path_size = strlen($p_remove_path); // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_result = $this->privOpenFd('rb')) != 1) { $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Read the central directory informations $v_central_dir = array(); if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) { // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Start at beginning of Central Dir $v_pos_entry = $v_central_dir['offset']; // ----- Read each entry $j_start = 0; for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'"); // ----- Read next Central dir entry //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'"); if (@fseek($this->zip_fd, $v_pos_entry)) { // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'"); // ----- Read the file header $v_header = array(); if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) { // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Store the index $v_header['index'] = $i; // ----- Store the file position $v_pos_entry = ftell($this->zip_fd); // ----- Look for the specific extract rules $v_extract = false; // ----- Look for extract by name rule if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'"); // ----- Look if the filename is in the list for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path"); $v_extract = true; } } // ----- Look for a filename elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one."); $v_extract = true; } } } // ----- Look for extract by ereg rule else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'"); if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression"); $v_extract = true; } } // ----- Look for extract by preg rule else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'"); if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression"); $v_extract = true; } } // ----- Look for extract by index rule else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'"); // ----- Look if the index is in the list for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range"); $v_extract = true; } if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop"); $j_start = $j+1; } if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop"); break; } } } // ----- Look for no rule, which means extract all the archive else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)"); $v_extract = true; } // ----- Check compression method if ( ($v_extract) && ( ($v_header['compression'] != 8) && ($v_header['compression'] != 0))) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported compression method (".$v_header['compression'].")"); $v_header['status'] = 'unsupported_compression'; // ----- Look for PCLZIP_OPT_STOP_ON_ERROR if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped"); $this->privSwapBackMagicQuotes(); PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION, "Filename '".$v_header['stored_filename']."' is " ."compressed by an unsupported compression " ."method (".$v_header['compression'].") "); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Check encrypted files if (($v_extract) && (($v_header['flag'] & 1) == 1)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported file encryption"); $v_header['status'] = 'unsupported_encryption'; // ----- Look for PCLZIP_OPT_STOP_ON_ERROR if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped"); $this->privSwapBackMagicQuotes(); PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, "Unsupported encryption for " ." filename '".$v_header['stored_filename'] ."'"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Look for real extraction if (($v_extract) && ($v_header['status'] != 'ok')) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "No need for extract"); $v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++]); if ($v_result != 1) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } $v_extract = false; } // ----- Look for real extraction if ($v_extract) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'"); // ----- Go to the file position //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'"); if (@fseek($this->zip_fd, $v_header['offset'])) { // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'"); // ----- Look for extraction as string if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) { // ----- Extracting the file $v_result1 = $this->privExtractFileAsString($v_header, $v_string); if ($v_result1 < 1) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1); return $v_result1; } // ----- Get the only interesting attributes if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) { // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Set the file content $p_file_list[$v_nb_extracted]['content'] = $v_string; // ----- Next extracted file $v_nb_extracted++; // ----- Look for user callback abort if ($v_result1 == 2) { break; } } // ----- Look for extraction in standard output elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) { // ----- Extracting the file in standard output $v_result1 = $this->privExtractFileInOutput($v_header, $p_options); if ($v_result1 < 1) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1); return $v_result1; } // ----- Get the only interesting attributes if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Look for user callback abort if ($v_result1 == 2) { break; } } // ----- Look for normal extraction else { // ----- Extracting the file $v_result1 = $this->privExtractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_options); if ($v_result1 < 1) { $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1); return $v_result1; } // ----- Get the only interesting attributes if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Look for user callback abort if ($v_result1 == 2) { break; } } } } // ----- Close the zip file $this->privCloseFd(); $this->privSwapBackMagicQuotes(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privExtractFile() // Description : // Parameters : // Return Values : // // 1 : ... ? // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback // -------------------------------------------------------------------------------- function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'"); $v_result=1; // ----- Read the file header if (($v_result = $this->privReadFileHeader($v_header)) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'"); // ----- Check that the file header is coherent with $p_entry info if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { // TBC } // ----- Look for all path to remove if ($p_remove_all_path == true) { // ----- Look for folder entry that not need to be extracted if (($p_entry['external']&0x00000010)==0x00000010) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The entry is a folder : need to be filtered"); $p_entry['status'] = "filtered"; //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "All path is removed"); // ----- Get the basename of the path $p_entry['filename'] = basename($p_entry['filename']); } // ----- Look for path to remove else if ($p_remove_path != "") { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look for some path to remove"); if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'"); // ----- Change the file status $p_entry['status'] = "filtered"; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } $p_remove_path_size = strlen($p_remove_path); if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'"); // ----- Remove the path $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'"); } } // ----- Add the path if ($p_path != '') { $p_entry['filename'] = $p_path."/".$p_entry['filename']; } // ----- Check a base_dir_restriction if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Check the extract directory restriction"); $v_inclusion = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], $p_entry['filename']); if ($v_inclusion == 0) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_EXTRACT_DIR_RESTRICTION is selected, file is outside restriction"); PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, "Filename '".$p_entry['filename']."' is " ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Look for pre-extract callback if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction"); // ----- Generate a local information $v_local_header = array(); $this->privConvertHeader2FileInfo($p_entry, $v_local_header); // ----- Call the callback // Here I do not use call_user_func() because I need to send a reference to the // header. eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); if ($v_result == 0) { // ----- Change the file status $p_entry['status'] = "skipped"; $v_result = 1; } // ----- Look for abort result if ($v_result == 2) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction"); // ----- This status is internal and will be changed in 'skipped' $p_entry['status'] = "aborted"; $v_result = PCLZIP_ERR_USER_ABORTED; } // ----- Update the informations // Only some fields can be modified $p_entry['filename'] = $v_local_header['filename']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'"); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'"); // ----- Look if extraction should be done if ($p_entry['status'] == 'ok') { // ----- Look for specific actions while the file exist if (file_exists($p_entry['filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists"); // ----- Look if file is a directory if (is_dir($p_entry['filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory"); // ----- Change the file status $p_entry['status'] = "already_a_directory"; // ----- Look for PCLZIP_OPT_STOP_ON_ERROR // For historical reason first PclZip implementation does not stop // when this kind of error occurs. if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped"); PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, "Filename '".$p_entry['filename']."' is " ."already used by an existing directory"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Look if file is write protected else if (!is_writeable($p_entry['filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected"); // ----- Change the file status $p_entry['status'] = "write_protected"; // ----- Look for PCLZIP_OPT_STOP_ON_ERROR // For historical reason first PclZip implementation does not stop // when this kind of error occurs. if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped"); PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, "Filename '".$p_entry['filename']."' exists " ."and is write protected"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Look if the extracted file is older else if (filemtime($p_entry['filename']) > $p_entry['mtime']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is newer (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")"); // ----- Change the file status if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER])) && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_REPLACE_NEWER is selected, file will be replaced"); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be replaced"); $p_entry['status'] = "newer_exist"; // ----- Look for PCLZIP_OPT_STOP_ON_ERROR // For historical reason first PclZip implementation does not stop // when this kind of error occurs. if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped"); PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, "Newer version of '".$p_entry['filename']."' exists " ."and option PCLZIP_OPT_REPLACE_NEWER is not selected"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is older than the extrated one - will be replaced by the extracted one (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")"); } } // ----- Check the directory availability and create it if necessary else { if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) $v_dir_to_check = $p_entry['filename']; else if (!strstr($p_entry['filename'], "/")) $v_dir_to_check = ""; else $v_dir_to_check = dirname($p_entry['filename']); if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'"); // ----- Change the file status $p_entry['status'] = "path_creation_fail"; // ----- Return ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); //return $v_result; $v_result = 1; } } } // ----- Look if extraction should be done if ($p_entry['status'] == 'ok') { // ----- Do the extraction (if not a folder) if (!(($p_entry['external']&0x00000010)==0x00000010)) { // ----- Look for not compressed file if ($p_entry['compression'] == 0) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file"); // ----- Opening destination file if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode"); // ----- Change the file status $p_entry['status'] = "write_error"; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read '".$p_entry['size']."' bytes"); // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks $v_size = $p_entry['compressed_size']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes"); $v_buffer = @fread($this->zip_fd, $v_read_size); /* Try to speed up the code $v_binary_data = pack('a'.$v_read_size, $v_buffer); @fwrite($v_dest_file, $v_binary_data, $v_read_size); */ @fwrite($v_dest_file, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Closing the destination file fclose($v_dest_file); // ----- Change the file mtime touch($p_entry['filename'], $p_entry['mtime']); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (Compression method ".$p_entry['compression'].")"); // ----- TBC // Need to be finished if (($p_entry['flag'] & 1) == 1) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File is encrypted"); /* // ----- Read the encryption header //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read 12 encryption header bytes"); $v_encryption_header = @fread($this->zip_fd, 12); // ----- Read the encrypted & compressed file in a buffer //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".($p_entry['compressed_size']-12)."' compressed & encrypted bytes"); $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']-12); // ----- Decrypt the buffer $this->privDecrypt($v_encryption_header, $v_buffer, $p_entry['compressed_size']-12, $p_entry['crc']); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Buffer is '".$v_buffer."'"); */ } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".$p_entry['compressed_size']."' compressed bytes"); // ----- Read the compressed file in a buffer (one shot) $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); } // ----- Decompress the file $v_file_content = @gzinflate($v_buffer); unset($v_buffer); if ($v_file_content === FALSE) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to inflate compressed file"); // ----- Change the file status // TBC $p_entry['status'] = "error"; //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Opening destination file if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode"); // ----- Change the file status $p_entry['status'] = "write_error"; //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Write the uncompressed data @fwrite($v_dest_file, $v_file_content, $p_entry['size']); unset($v_file_content); // ----- Closing the destination file @fclose($v_dest_file); // ----- Change the file mtime @touch($p_entry['filename'], $p_entry['mtime']); } // ----- Look for chmod option if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'"); // ----- Change the mode of the file @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done"); } } // ----- Change abort status if ($p_entry['status'] == "aborted") { $p_entry['status'] = "skipped"; } // ----- Look for post-extract callback elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction"); // ----- Generate a local information $v_local_header = array(); $this->privConvertHeader2FileInfo($p_entry, $v_local_header); // ----- Call the callback // Here I do not use call_user_func() because I need to send a reference to the // header. eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); // ----- Look for abort result if ($v_result == 2) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction"); $v_result = PCLZIP_ERR_USER_ABORTED; } } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privExtractFileInOutput() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privExtractFileInOutput(&$p_entry, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', ""); $v_result=1; // ----- Read the file header if (($v_result = $this->privReadFileHeader($v_header)) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'"); // ----- Check that the file header is coherent with $p_entry info if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { // TBC } // ----- Look for pre-extract callback if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction"); // ----- Generate a local information $v_local_header = array(); $this->privConvertHeader2FileInfo($p_entry, $v_local_header); // ----- Call the callback // Here I do not use call_user_func() because I need to send a reference to the // header. eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); if ($v_result == 0) { // ----- Change the file status $p_entry['status'] = "skipped"; $v_result = 1; } // ----- Look for abort result if ($v_result == 2) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction"); // ----- This status is internal and will be changed in 'skipped' $p_entry['status'] = "aborted"; $v_result = PCLZIP_ERR_USER_ABORTED; } // ----- Update the informations // Only some fields can be modified $p_entry['filename'] = $v_local_header['filename']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'"); } // ----- Trace //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'"); // ----- Look if extraction should be done if ($p_entry['status'] == 'ok') { // ----- Do the extraction (if not a folder) if (!(($p_entry['external']&0x00000010)==0x00000010)) { // ----- Look for not compressed file if ($p_entry['compressed_size'] == $p_entry['size']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes"); // ----- Read the file in a buffer (one shot) $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); // ----- Send the file to the output echo $v_buffer; unset($v_buffer); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes"); // ----- Read the compressed file in a buffer (one shot) $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); // ----- Decompress the file $v_file_content = gzinflate($v_buffer); unset($v_buffer); // ----- Send the file to the output echo $v_file_content; unset($v_file_content); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done"); } } // ----- Change abort status if ($p_entry['status'] == "aborted") { $p_entry['status'] = "skipped"; } // ----- Look for post-extract callback elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction"); // ----- Generate a local information $v_local_header = array(); $this->privConvertHeader2FileInfo($p_entry, $v_local_header); // ----- Call the callback // Here I do not use call_user_func() because I need to send a reference to the // header. eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); // ----- Look for abort result if ($v_result == 2) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction"); $v_result = PCLZIP_ERR_USER_ABORTED; } } //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privExtractFileAsString() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privExtractFileAsString(&$p_entry, &$p_string) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'"); $v_result=1; // ----- Read the file header $v_header = array(); if (($v_result = $this->privReadFileHeader($v_header)) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'"); // ----- Check that the file header is coherent with $p_entry info if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { // TBC } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file in string (with path) '".$p_entry['filename']."', size '$v_header[size]'"); // ----- Do the extraction (if not a folder) if (!(($p_entry['external']&0x00000010)==0x00000010)) { // ----- Look for not compressed file // if ($p_entry['compressed_size'] == $p_entry['size']) if ($p_entry['compression'] == 0) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes"); // ----- Reading the file $p_string = @fread($this->zip_fd, $p_entry['compressed_size']); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (compression method '".$p_entry['compression']."')"); // ----- Reading the file $v_data = @fread($this->zip_fd, $p_entry['compressed_size']); // ----- Decompress the file if (($p_string = @gzinflate($v_data)) === FALSE) { // TBC } } // ----- Trace //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done"); } else { // TBC : error : can not extract a folder in a string } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privReadFileHeader() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privReadFileHeader(&$p_header) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", ""); $v_result=1; // ----- Read the 4 bytes signature $v_binary_data = @fread($this->zip_fd, 4); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'"); $v_data = unpack('Vid', $v_binary_data); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'"); // ----- Check signature if ($v_data['id'] != 0x04034b50) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header"); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Read the first 42 bytes of the header $v_binary_data = fread($this->zip_fd, 26); // ----- Look for invalid block size if (strlen($v_binary_data) != 26) { $p_header['filename'] = ""; $p_header['status'] = "invalid_header"; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data)); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Extract the values //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'"); $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); // ----- Get filename //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']); $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\''); // ----- Get extra_fields //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']); if ($v_data['extra_len'] != 0) { $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']); } else { $p_header['extra'] = ''; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\''); // ----- Extract properties $p_header['version_extracted'] = $v_data['version']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : ('.$p_header['version_extracted'].') \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\''); $p_header['compression'] = $v_data['compression']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.$p_header['compression'].'\''); $p_header['size'] = $v_data['size']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\''); $p_header['compressed_size'] = $v_data['compressed_size']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\''); $p_header['crc'] = $v_data['crc']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\''); $p_header['flag'] = $v_data['flag']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\''); $p_header['filename_len'] = $v_data['filename_len']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename_len : \''.$p_header['filename_len'].'\''); // ----- Recuperate date in UNIX format $p_header['mdate'] = $v_data['mdate']; $p_header['mtime'] = $v_data['mtime']; if ($p_header['mdate'] && $p_header['mtime']) { // ----- Extract time $v_hour = ($p_header['mtime'] & 0xF800) >> 11; $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; $v_seconde = ($p_header['mtime'] & 0x001F)*2; // ----- Extract date $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; $v_month = ($p_header['mdate'] & 0x01E0) >> 5; $v_day = $p_header['mdate'] & 0x001F; // ----- Get UNIX date format $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\''); } else { $p_header['mtime'] = time(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\''); } // TBC //for(reset($v_data); $key = key($v_data); next($v_data)) { // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]); //} // ----- Set the stored filename $p_header['stored_filename'] = $p_header['filename']; // ----- Set the status field $p_header['status'] = "ok"; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privReadCentralFileHeader() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privReadCentralFileHeader(&$p_header) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", ""); $v_result=1; // ----- Read the 4 bytes signature $v_binary_data = @fread($this->zip_fd, 4); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'"); $v_data = unpack('Vid', $v_binary_data); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'"); // ----- Check signature if ($v_data['id'] != 0x02014b50) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature"); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Read the first 42 bytes of the header $v_binary_data = fread($this->zip_fd, 42); // ----- Look for invalid block size if (strlen($v_binary_data) != 42) { $p_header['filename'] = ""; $p_header['status'] = "invalid_header"; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data)); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Extract the values //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'"); $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); // ----- Get filename //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']); if ($p_header['filename_len'] != 0) $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']); else $p_header['filename'] = ''; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\''); // ----- Get extra //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']); if ($p_header['extra_len'] != 0) $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']); else $p_header['extra'] = ''; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\''); // ----- Get comment //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']); if ($p_header['comment_len'] != 0) $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']); else $p_header['comment'] = ''; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\''); // ----- Extract properties //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\''); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\''); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\''); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\''); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\''); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\''); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\''); // ----- Recuperate date in UNIX format //if ($p_header['mdate'] && $p_header['mtime']) // TBC : bug : this was ignoring time with 0/0/0 if (1) { // ----- Extract time $v_hour = ($p_header['mtime'] & 0xF800) >> 11; $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; $v_seconde = ($p_header['mtime'] & 0x001F)*2; // ----- Extract date $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; $v_month = ($p_header['mdate'] & 0x01E0) >> 5; $v_day = $p_header['mdate'] & 0x001F; // ----- Get UNIX date format $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\''); } else { $p_header['mtime'] = time(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\''); } // ----- Set the stored filename $p_header['stored_filename'] = $p_header['filename']; // ----- Set default status to ok $p_header['status'] = 'ok'; // ----- Look if it is a directory //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'"); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "External (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".(($p_header['external']&0x00000010)==0x00000010?'is a folder':'is a file').')'); if (substr($p_header['filename'], -1) == '/') { //$p_header['external'] = 0x41FF0010; $p_header['external'] = 0x00000010; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.sprintf("Ox%04X", $p_header['external']).'\''); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Header of filename : \''.$p_header['filename'].'\''); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privCheckFileHeaders() // Description : // Parameters : // Return Values : // 1 on success, // 0 on error; // -------------------------------------------------------------------------------- function privCheckFileHeaders(&$p_local_header, &$p_central_header) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFileHeaders", ""); $v_result=1; // ----- Check the static values // TBC if ($p_local_header['filename'] != $p_central_header['filename']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename" : TBC To Be Completed'); } if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "version_extracted" : TBC To Be Completed'); } if ($p_local_header['flag'] != $p_central_header['flag']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "flag" : TBC To Be Completed'); } if ($p_local_header['compression'] != $p_central_header['compression']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "compression" : TBC To Be Completed'); } if ($p_local_header['mtime'] != $p_central_header['mtime']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "mtime" : TBC To Be Completed'); } if ($p_local_header['filename_len'] != $p_central_header['filename_len']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename_len" : TBC To Be Completed'); } // ----- Look for flag bit 3 if (($p_local_header['flag'] & 8) == 8) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Purpose bit flag bit 3 set !'); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'File size, compression size and crc found in central header'); $p_local_header['size'] = $p_central_header['size']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_local_header['size'].'\''); $p_local_header['compressed_size'] = $p_central_header['compressed_size']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_local_header['compressed_size'].'\''); $p_local_header['crc'] = $p_central_header['crc']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_local_header['crc']).'\''); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privReadEndCentralDir() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privReadEndCentralDir(&$p_central_dir) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", ""); $v_result=1; // ----- Go to the end of the zip file $v_size = filesize($this->zipname); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size"); @fseek($this->zip_fd, $v_size); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\''); if (@ftell($this->zip_fd) != $v_size) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\''); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- First try : look if this is an archive with no commentaries (most of the time) // in this case the end of central dir is at 22 bytes of the file end $v_found = 0; if ($v_size > 26) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment'); @fseek($this->zip_fd, $v_size-22); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\''); if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Read for bytes $v_binary_data = @fread($this->zip_fd, 4); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'"); $v_data = @unpack('Vid', $v_binary_data); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'"); // ----- Check signature if ($v_data['id'] == 0x06054b50) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position."); $v_found = 1; } $v_pos = ftell($this->zip_fd); } // ----- Go back to the maximum possible size of the Central Dir End Record if (!$v_found) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir'); $v_maximum_size = 65557; // 0xFFFF + 22; if ($v_maximum_size > $v_size) $v_maximum_size = $v_size; @fseek($this->zip_fd, $v_size-$v_maximum_size); if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\''); // ----- Read byte per byte in order to find the signature $v_pos = ftell($this->zip_fd); $v_bytes = 0x00000000; while ($v_pos < $v_size) { // ----- Read a byte $v_byte = @fread($this->zip_fd, 1); // ----- Add the byte $v_bytes = ($v_bytes << 8) | Ord($v_byte); // ----- Compare the bytes if ($v_bytes == 0x504b0506) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\''); $v_pos++; break; } $v_pos++; } // ----- Look if not found end of central dir if ($v_pos == $v_size) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature"); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Read the first 18 bytes of the header $v_binary_data = fread($this->zip_fd, 18); // ----- Look for invalid block size if (strlen($v_binary_data) != 18) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Extract the values ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'"); ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'"); $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); // ----- Check the global size //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']); if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The central dir is not at the end of the archive. Some trailing bytes exists after the archive."); // ----- Removed in release 2.2 see readme file // The check of the file size is a little too strict. // Some bugs where found when a zip is encrypted/decrypted with 'crypt'. // While decrypted, zip has training 0 bytes if (0) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'The central dir is not at the end of the archive.' .' Some trailing bytes exists after the archive.'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } } // ----- Get comment //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$v_data['comment_size'].'\''); if ($v_data['comment_size'] != 0) { $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']); } else $p_central_dir['comment'] = ''; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\''); $p_central_dir['entries'] = $v_data['entries']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\''); $p_central_dir['disk_entries'] = $v_data['disk_entries']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\''); $p_central_dir['offset'] = $v_data['offset']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\''); $p_central_dir['size'] = $v_data['size']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\''); $p_central_dir['disk'] = $v_data['disk']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\''); $p_central_dir['disk_start'] = $v_data['disk_start']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\''); // TBC //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) { // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]); //} // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privDeleteByRule() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privDeleteByRule(&$p_result_list, &$p_options) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", ""); $v_result=1; $v_list_detail = array(); // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_result=$this->privOpenFd('rb')) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Read the central directory informations $v_central_dir = array(); if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) { $this->privCloseFd(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Go to beginning of File //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'"); // ----- Scan all the files // ----- Start at beginning of Central Dir $v_pos_entry = $v_central_dir['offset']; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'"); if (@fseek($this->zip_fd, $v_pos_entry)) { // ----- Close the zip file $this->privCloseFd(); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'"); // ----- Read each entry $v_header_list = array(); $j_start = 0; for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')"); // ----- Read the file header $v_header_list[$v_nb_extracted] = array(); if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) { // ----- Close the zip file $this->privCloseFd(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename (index '$i') : '".$v_header_list[$v_nb_extracted]['stored_filename']."'"); // ----- Store the index $v_header_list[$v_nb_extracted]['index'] = $i; // ----- Look for the specific extract rules $v_found = false; // ----- Look for extract by name rule if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'"); // ----- Look if the filename is in the list for ($j=0; ($j strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path"); $v_found = true; } elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory"); $v_found = true; } } // ----- Look for a filename elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one."); $v_found = true; } } } // ----- Look for extract by ereg rule else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'"); if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression"); $v_found = true; } } // ----- Look for extract by preg rule else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'"); if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression"); $v_found = true; } } // ----- Look for extract by index rule else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'"); // ----- Look if the index is in the list for ($j=$j_start; ($j=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range"); $v_found = true; } if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop"); $j_start = $j+1; } if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop"); break; } } } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "No argument mean remove all file"); $v_found = true; } // ----- Look for deletion if ($v_found) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted"); unset($v_header_list[$v_nb_extracted]); } else { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted"); $v_nb_extracted++; } } // ----- Look if something need to be deleted if ($v_nb_extracted > 0) { // ----- Creates a temporay file $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; // ----- Creates a temporary zip archive $v_temp_zip = new PclZip($v_zip_temp_name); // ----- Open the temporary zip file in write mode //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode"); if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) { $this->privCloseFd(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Look which file need to be kept for ($i=0; $izip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'"); if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) { // ----- Close the zip file $this->privCloseFd(); $v_temp_zip->privCloseFd(); @unlink($v_zip_temp_name); // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'"); // ----- Read the file header $v_local_header = array(); if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) { // ----- Close the zip file $this->privCloseFd(); $v_temp_zip->privCloseFd(); @unlink($v_zip_temp_name); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Check that local file header is same as central file header if ($this->privCheckFileHeaders($v_local_header, $v_header_list[$i]) != 1) { // TBC } unset($v_local_header); // ----- Write the file header if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) { // ----- Close the zip file $this->privCloseFd(); $v_temp_zip->privCloseFd(); @unlink($v_zip_temp_name); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'"); // ----- Read/write the data block if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) { // ----- Close the zip file $this->privCloseFd(); $v_temp_zip->privCloseFd(); @unlink($v_zip_temp_name); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } } // ----- Store the offset of the central dir $v_offset = @ftell($v_temp_zip->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset"); // ----- Re-Create the Central Dir files header //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory"); for ($i=0; $iprivWriteCentralFileHeader($v_header_list[$i])) != 1) { $v_temp_zip->privCloseFd(); $this->privCloseFd(); @unlink($v_zip_temp_name); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Transform the header to a 'usable' info $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the central directory footer"); // ----- Zip file comment $v_comment = ''; if (isset($p_options[PCLZIP_OPT_COMMENT])) { $v_comment = $p_options[PCLZIP_OPT_COMMENT]; } // ----- Calculate the size of the central header $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset; // ----- Create the central dir footer if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) { // ----- Reset the file list unset($v_header_list); $v_temp_zip->privCloseFd(); $this->privCloseFd(); @unlink($v_zip_temp_name); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Close $v_temp_zip->privCloseFd(); $this->privCloseFd(); // ----- Delete the zip file // TBC : I should test the result ... @unlink($this->zipname); // ----- Rename the temporary file // TBC : I should test the result ... //@rename($v_zip_temp_name, $this->zipname); PclZipUtilRename($v_zip_temp_name, $this->zipname); // ----- Destroy the temporary archive unset($v_temp_zip); } // ----- Remove every files : reset the file else if ($v_central_dir['entries'] != 0) { $this->privCloseFd(); if (($v_result = $this->privOpenFd('wb')) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } $this->privCloseFd(); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privDirCheck() // Description : // Check if a directory exists, if not it creates it and all the parents directory // which may be useful. // Parameters : // $p_dir : Directory path to check. // Return Values : // 1 : OK // -1 : Unable to create directory // -------------------------------------------------------------------------------- function privDirCheck($p_dir, $p_is_dir=false) { $v_result = 1; //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'"); // ----- Remove the final '/' if (($p_is_dir) && (substr($p_dir, -1)=='/')) { $p_dir = substr($p_dir, 0, strlen($p_dir)-1); } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'"); // ----- Check the directory availability if ((is_dir($p_dir)) || ($p_dir == "")) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory"); return 1; } // ----- Extract parent directory $p_parent_dir = dirname($p_dir); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'"); // ----- Just a check if ($p_parent_dir != $p_dir) { // ----- Look for parent directory if ($p_parent_dir != "") { if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } } } // ----- Create the directory //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'"); if (!@mkdir($p_dir, 0777)) { // ----- Error log PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created"); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privMerge() // Description : // If $p_archive_to_add does not exist, the function exit with a success result. // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privMerge(&$p_archive_to_add) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'"); $v_result=1; // ----- Look if the archive_to_add exists if (!is_file($p_archive_to_add->zipname)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge."); // ----- Nothing to merge, so merge is a success $v_result = 1; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Look if the archive exists if (!is_file($this->zipname)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add."); // ----- Do a duplicate $v_result = $this->privDuplicate($p_archive_to_add->zipname); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_result=$this->privOpenFd('rb')) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Read the central directory informations $v_central_dir = array(); if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) { $this->privCloseFd(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Go to beginning of File //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'"); @rewind($this->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'"); // ----- Open the archive_to_add file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode"); if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) { $this->privCloseFd(); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Read the central directory informations $v_central_dir_to_add = array(); if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) { $this->privCloseFd(); $p_archive_to_add->privCloseFd(); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Go to beginning of File //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'"); @rewind($p_archive_to_add->zip_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'"); // ----- Creates a temporay file $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; // ----- Open the temporary file in write mode //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { $this->privCloseFd(); $p_archive_to_add->privCloseFd(); PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Copy the files from the archive to the temporary file // TBC : Here I should better append the file and go back to erase the central dir $v_size = $v_central_dir['offset']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = fread($this->zip_fd, $v_read_size); @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Copy the files from the archive_to_add into the temporary file $v_size = $v_central_dir_to_add['offset']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size); @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Store the offset of the central dir $v_offset = @ftell($v_zip_temp_fd); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset"); // ----- Copy the block of file headers from the old archive $v_size = $v_central_dir['size']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @fread($this->zip_fd, $v_read_size); @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Copy the block of file headers from the archive_to_add $v_size = $v_central_dir_to_add['size']; while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size); @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Merge the file comments $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment']; // ----- Calculate the size of the (new) central header $v_size = @ftell($v_zip_temp_fd)-$v_offset; // ----- Swap the file descriptor // Here is a trick : I swap the temporary fd with the zip fd, in order to use // the following methods on the temporary fil and not the real archive fd $v_swap = $this->zip_fd; $this->zip_fd = $v_zip_temp_fd; $v_zip_temp_fd = $v_swap; // ----- Create the central dir footer if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) { $this->privCloseFd(); $p_archive_to_add->privCloseFd(); @fclose($v_zip_temp_fd); $this->zip_fd = null; // ----- Reset the file list unset($v_header_list); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Swap back the file descriptor $v_swap = $this->zip_fd; $this->zip_fd = $v_zip_temp_fd; $v_zip_temp_fd = $v_swap; // ----- Close $this->privCloseFd(); $p_archive_to_add->privCloseFd(); // ----- Close the temporary file @fclose($v_zip_temp_fd); // ----- Delete the zip file // TBC : I should test the result ... @unlink($this->zipname); // ----- Rename the temporary file // TBC : I should test the result ... //@rename($v_zip_temp_name, $this->zipname); PclZipUtilRename($v_zip_temp_name, $this->zipname); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privDuplicate() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privDuplicate($p_archive_filename) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'"); $v_result=1; // ----- Look if the $p_archive_filename exists if (!is_file($p_archive_filename)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate."); // ----- Nothing to duplicate, so duplicate is a success. $v_result = 1; // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Open the zip file //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_result=$this->privOpenFd('wb')) != 1) { // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Open the temporary file in write mode //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode"); if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) { $this->privCloseFd(); PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode'); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo()); return PclZip::errorCode(); } // ----- Copy the files from the archive to the temporary file // TBC : Here I should better append the file and go back to erase the central dir $v_size = filesize($p_archive_filename); while ($v_size != 0) { $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes"); $v_buffer = fread($v_zip_temp_fd, $v_read_size); @fwrite($this->zip_fd, $v_buffer, $v_read_size); $v_size -= $v_read_size; } // ----- Close $this->privCloseFd(); // ----- Close the temporary file @fclose($v_zip_temp_fd); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privErrorLog() // Description : // Parameters : // -------------------------------------------------------------------------------- function privErrorLog($p_error_code=0, $p_error_string='') { if (PCLZIP_ERROR_EXTERNAL == 1) { PclError($p_error_code, $p_error_string); } else { $this->error_code = $p_error_code; $this->error_string = $p_error_string; } } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privErrorReset() // Description : // Parameters : // -------------------------------------------------------------------------------- function privErrorReset() { if (PCLZIP_ERROR_EXTERNAL == 1) { PclErrorReset(); } else { $this->error_code = 0; $this->error_string = ''; } } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privDecrypt() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privDecrypt($p_encryption_header, &$p_buffer, $p_size, $p_crc) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDecrypt', "size=".$p_size.""); $v_result=1; // ----- To Be Modified ;-) $v_pwd = "test"; $p_buffer = PclZipUtilZipDecrypt($p_buffer, $p_size, $p_encryption_header, $p_crc, $v_pwd); // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privDisableMagicQuotes() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privDisableMagicQuotes() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDisableMagicQuotes', ""); $v_result=1; // ----- Look if function exists if ( (!function_exists("get_magic_quotes_runtime")) || (!function_exists("set_magic_quotes_runtime"))) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Look if already done if ($this->magic_quotes_status != -1) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote already disabled"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Get and memorize the magic_quote value $this->magic_quotes_status = @get_magic_quotes_runtime(); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Current magic_quotes_runtime status is '".($this->magic_quotes_status==0?'disable':'enable')."'"); // ----- Disable magic_quotes if ($this->magic_quotes_status == 1) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Disable magic_quotes"); @set_magic_quotes_runtime(0); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : privSwapBackMagicQuotes() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function privSwapBackMagicQuotes() { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privSwapBackMagicQuotes', ""); $v_result=1; // ----- Look if function exists if ( (!function_exists("get_magic_quotes_runtime")) || (!function_exists("set_magic_quotes_runtime"))) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Look if something to do if ($this->magic_quotes_status != -1) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote not modified"); //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // ----- Swap back magic_quotes if ($this->magic_quotes_status == 1) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Enable back magic_quotes"); @set_magic_quotes_runtime($this->magic_quotes_status); } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- } // End of class // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : PclZipUtilPathReduction() // Description : // Parameters : // Return Values : // -------------------------------------------------------------------------------- function PclZipUtilPathReduction($p_dir) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'"); $v_result = ""; // ----- Look for not empty path if ($p_dir != "") { // ----- Explode path by directory names $v_list = explode("/", $p_dir); // ----- Study directories from last to first $v_skip = 0; for ($i=sizeof($v_list)-1; $i>=0; $i--) { // ----- Look for current path if ($v_list[$i] == ".") { // ----- Ignore this directory // Should be the first $i=0, but no check is done } else if ($v_list[$i] == "..") { $v_skip++; } else if ($v_list[$i] == "") { // ----- First '/' i.e. root slash if ($i == 0) { $v_result = "/".$v_result; if ($v_skip > 0) { // ----- It is an invalid path, so the path is not modified // TBC $v_result = $p_dir; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid path is unchanged"); $v_skip = 0; } } // ----- Last '/' i.e. indicates a directory else if ($i == (sizeof($v_list)-1)) { $v_result = $v_list[$i]; } // ----- Double '/' inside the path else { // ----- Ignore only the double '//' in path, // but not the first and last '/' } } else { // ----- Look for item to skip if ($v_skip > 0) { $v_skip--; } else { $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); } } } // ----- Look for skip if ($v_skip > 0) { while ($v_skip > 0) { $v_result = '../'.$v_result; $v_skip--; } } } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : PclZipUtilPathInclusion() // Description : // This function indicates if the path $p_path is under the $p_dir tree. Or, // said in an other way, if the file or sub-dir $p_path is inside the dir // $p_dir. // The function indicates also if the path is exactly the same as the dir. // This function supports path with duplicated '/' like '//', but does not // support '.' or '..' statements. // Parameters : // Return Values : // 0 if $p_path is not inside directory $p_dir // 1 if $p_path is inside directory $p_dir // 2 if $p_path is exactly the same as $p_dir // -------------------------------------------------------------------------------- function PclZipUtilPathInclusion($p_dir, $p_path) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'"); $v_result = 1; // ----- Look for path beginning by ./ if ( ($p_dir == '.') || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) { $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_dir '".$p_dir."'"); } if ( ($p_path == '.') || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) { $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_path '".$p_path."'"); } // ----- Explode dir and path by directory separator $v_list_dir = explode("/", $p_dir); $v_list_dir_size = sizeof($v_list_dir); $v_list_path = explode("/", $p_path); $v_list_path_size = sizeof($v_list_path); // ----- Study directories paths $i = 0; $j = 0; while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'"); // ----- Look for empty dir (path reduction) if ($v_list_dir[$i] == '') { $i++; continue; } if ($v_list_path[$j] == '') { $j++; continue; } // ----- Compare the items if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different"); $v_result = 0; } // ----- Next items $i++; $j++; } // ----- Look if everything seems to be the same if ($v_result) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break"); // ----- Skip all the empty items while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".($i < $v_list_dir_size?$v_list_dir[$i]:'')."' and path($j)='".($j < $v_list_path_size?$v_list_path[$j]:'')."'"); if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { // ----- There are exactly the same $v_result = 2; } else if ($i < $v_list_dir_size) { // ----- The path is shorter than the dir $v_result = 0; } } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : PclZipUtilCopyBlock() // Description : // Parameters : // $p_mode : read/write compression mode // 0 : src & dest normal // 1 : src gzip, dest normal // 2 : src normal, dest gzip // 3 : src & dest gzip // Return Values : // -------------------------------------------------------------------------------- function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode"); $v_result = 1; if ($p_mode==0) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src))); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest))); while ($p_size != 0) { $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @fread($p_src, $v_read_size); @fwrite($p_dest, $v_buffer, $v_read_size); $p_size -= $v_read_size; } //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src))); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest))); } else if ($p_mode==1) { while ($p_size != 0) { $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @gzread($p_src, $v_read_size); @fwrite($p_dest, $v_buffer, $v_read_size); $p_size -= $v_read_size; } } else if ($p_mode==2) { while ($p_size != 0) { $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @fread($p_src, $v_read_size); @gzwrite($p_dest, $v_buffer, $v_read_size); $p_size -= $v_read_size; } } else if ($p_mode==3) { while ($p_size != 0) { $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes"); $v_buffer = @gzread($p_src, $v_read_size); @gzwrite($p_dest, $v_buffer, $v_read_size); $p_size -= $v_read_size; } } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : PclZipUtilRename() // Description : // This function tries to do a simple rename() function. If it fails, it // tries to copy the $p_src file in a new $p_dest file and then unlink the // first one. // Parameters : // $p_src : Old filename // $p_dest : New filename // Return Values : // 1 on success, 0 on failure. // -------------------------------------------------------------------------------- function PclZipUtilRename($p_src, $p_dest) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest"); $v_result = 1; // ----- Try to rename the files if (!@rename($p_src, $p_dest)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink"); // ----- Try to copy & unlink the src if (!@copy($p_src, $p_dest)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file"); $v_result = 0; } else if (!@unlink($p_src)) { //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename"); $v_result = 0; } } // ----- Return //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : PclZipUtilOptionText() // Description : // Translate option value in text. Mainly for debug purpose. // Parameters : // $p_option : the option value. // Return Values : // The option text value. // -------------------------------------------------------------------------------- function PclZipUtilOptionText($p_option) { //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'"); $v_list = get_defined_constants(); for (reset($v_list); $v_key = key($v_list); next($v_list)) { $v_prefix = substr($v_key, 0, 10); if (( ($v_prefix == 'PCLZIP_OPT') || ($v_prefix == 'PCLZIP_CB_') || ($v_prefix == 'PCLZIP_ATT')) && ($v_list[$v_key] == $p_option)) { //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_key); return $v_key; } } $v_result = 'Unknown'; //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result); return $v_result; } // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // Function : PclZipUtilTranslateWinPath() // Description : // Translate windows path by replacing '\' by '/' and optionally removing // drive letter. // Parameters : // $p_path : path to translate. // $p_remove_disk_letter : true | false // Return Values : // The path translated. // -------------------------------------------------------------------------------- function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true) { if (stristr(php_uname(), 'windows')) { // ----- Look for potential disk letter if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { $p_path = substr($p_path, $v_position+1); } // ----- Change potential windows directory separator if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { $p_path = strtr($p_path, '\\', '/'); } } return $p_path; } // -------------------------------------------------------------------------------- ?> AjaXplorer/AjaXplorer/server/users/0000777000000000000000000000000011300452504020524 5ustar adminadministratorsAjaXplorer/AjaXplorer/server/users/.htaccess0000767000000000000000000000001511122202524022315 0ustar adminadministratorsdeny from allAjaXplorer/AjaXplorer/server/conf/0000777000000000000000000000000011300347517020317 5ustar adminadministratorsAjaXplorer/AjaXplorer/server/conf/.htaccess0000767000000000000000000000001511122202524022101 0ustar adminadministratorsdeny from allAjaXplorer/AjaXplorer/server/conf/conf.php0000766000000000000000000001170211300345400021744 0ustar adminadministrators"Repositories" /*********************************************************/ $REPOSITORIES[0] = array( "DISPLAY" => "Download", "DRIVER" => "fs", "DRIVER_OPTIONS"=> array( "PATH" => "/share/Download", "CREATE" => true, "RECYCLE_BIN" => 'recycle_bin' ) ); $REPOSITORIES[1] = array( "DISPLAY" => "Music", "DRIVER" => "fs", "DRIVER_OPTIONS"=> array( "PATH" => "/share/Music", "CREATE" => true, "RECYCLE_BIN" => 'recycle_bin' ) ); $REPOSITORIES[2] = array( "DISPLAY" => "Photo", "DRIVER" => "fs", "DRIVER_OPTIONS"=> array( "PATH" => "/share/Photo", "CREATE" => true, "RECYCLE_BIN" => 'recycle_bin' ) ); $REPOSITORIES[3] = array( "DISPLAY" => "Video", "DRIVER" => "fs", "DRIVER_OPTIONS"=> array( "PATH" => "/share/Video", "CREATE" => true, "RECYCLE_BIN" => 'recycle_bin' ) ); /** * Specific config for wordpress plugin, do not touch if you are not sure! */ if(AUTH_MODE == "wordpress"){ $REPOSITORIES[0] = array( "DISPLAY" => "Wordpress", "DRIVER" => "fs", "DRIVER_OPTIONS"=> array( "PATH" => realpath(dirname(__FILE__)."/../../../../../wp-content"), "CREATE" => false, "RECYCLE_BIN" => 'recycle_bin' ) ); } //------------------------ // UPLOAD CONFIG //------------------------ // Maximum number of files for each upload. Leave to 0 for no limit. $upload_max_number = 16; // Maximum size per file allowed to upload. By default, this is fixed by php config 'upload_max_filesize'. // Use this one only if you want to set it smaller than the php config. If you want to increase the php value, // please check the PHP documentation for how to set a php config. // // Use either the php config syntax with letters for size (e.g. "2M" for 2MegaBytes , "1G" for one gigabyte, etc.) // or an integer value like 2097152 for 2 megabytes. $upload_max_size_per_file = 0; // Maximum total size (all files size cumulated) by upload. // Leave to 0 if you do not want any limit. // See the previous variable for syntax ("2M" or 2097152 ) $upload_max_size_total = 0; /*********************************************/ /* WEBMASTER EMAIL / NOT USED AT THE MOMENT!! /*********************************************/ $webmaster_email = "webmaster@yourdomain.com"; /* RECYCLE BIN : leave blank if you do not want to use it. /********************************/ $recycle_bin = "recycle_bin"; /* HTTPS DOMAIN? (USED TO CORRECT A BUG IN IE) /**************************************************/ $use_https=false; // UNITE DE TAILLE DES FICHIER (octets "o", bytes "b") // (Unit of file size, "o" or "b") $size_unit="b"; // NOMBRE DE CARACTERES MAXIMUM POUR LES NOMS DE FICHIER // (max number chars for file and directory names) $max_caracteres=50; // AFFICHAGE DES FICHIERS CACHES : oui=1, non=0 (UN FICHIER CACHE COMMENCE PAR UN POINT) // (Show hidden files, yes=1, no=0) $showhidden=0; //------------------------------------------------------ // DO NOT CHANGE THESE VARIABLES BELOW //------------------------------------------------------ $installPath = realpath(dirname(__FILE__)."/../.."); define("INSTALL_PATH", $installPath); define("USERS_DIR", $installPath."/server/users"); define("SERVER_ACCESS", "content.php"); define("ADMIN_ACCESS", "admin.php"); define("IMAGES_FOLDER", "client/images"); define("CLIENT_RESOURCES_FOLDER", "client"); define("SERVER_RESOURCES_FOLDER", "server/classes"); define("DOCS_FOLDER", "client/doc"); define("OLD_USERS_DIR", $installPath."/bookmarks"); define("INITIAL_ADMIN_PASSWORD", "admin"); define("GZIP_DOWNLOAD", false); define("GZIP_LIMIT", 10*1048576); // Do not Gzip files above 1M // PAGES D'ENTETE ET DE BAS DE PAGE // (header and footer files ) $baspage=CLIENT_RESOURCES_FOLDER."/html/bottom.html"; ?> AjaXplorer/AjaXplorer/client/0000777000000000000000000000000011300346147017340 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/doc/0000777000000000000000000000000011300346036020102 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/doc/INSTALL.txt0000766000000000000000000001562011122202526021753 0ustar adminadministrators ------------------------------------------------ | AjaXplorer Installation Instructions | ------------------------------------------------ 1 SYSTEM REQUIREMENTS & QUICK INSTALL To be able to run this system on your webserver, it must have PHP 3 or higher running, and you must have an FTP access to upload the files on the server. That's all! No database is needed. If you want to use it as fast as possible, just change the ADMIN_PASSWORD in the conf/conf.php file and upload on your server. Check that the both "files" and "users" folders are both readable and writeable. | INFO : FOR UPGRADE FROM 2.2 TO 2.2.1 | Copy the files in a different folder. | + From the old distrib to the new one, copy the whole content of users/ | + Backup the basic conf/conf.php file and copy the line with "$available_languages" | + Copy the old conf/conf.php in place of the new one, and update the $available_languages line. | That's it! For further configuration, read below. 2 CONFIGURATION After unzipping the file into a local folder on your computer, use a text editor to edit the configuration file located in conf/conf.php You have to main configuration to change: the $REPOSITORIES variable and all the USERS constants. 2.1 REPOSITORIES In AjaXplorer, a repository is a folder that you want to browse/modify with the application. A repository does not have to be inside the ajaxplorer installation folder, since you set it with an absolute path on your server. You can set as many repositories as you want : you will be able to switch from one to another when logged to AjaXplorer, and you can precisely set rights for each users (see paragraph 2.2) on each repository. Note that repository are really separated, and for example AjaXplorer does not let you copy a file from a repository to another. By default, the basic repository is set to the "files" folder inside the ajaxplorer installation folder. You can change it to whatever you want, using absolute path like : /home/login/www/location, or /C:/myfolder/ on windows. Note that a repository does not have to be accessible to the internet, AjaXplorer will work as a "proxy" between your files and the web. 2.2 USERS MANAGEMENT An evoluted users management system has been developed in AjaXplorer. You are encouraged to use it to secure your data, but it's up to you, you can disable it totally (for example if you are already working in a very secure zone, and don't need any users profiles). If you are a beginner, just change the ADMIN_PASSWORD variable before uploading on your server everything should be fine. If you do not change it, you will be reminded to change the first time you log in, because otherwise anybody knowing AjaXplorer could login with the standard initial password "admin"... You can add / modify / delete users by logging in AjaXplorer as "admin" and clicking on "Settings" button. For each user, you will be able to give read and/or right access separately on each repository. Note that a user that has no rights on any repository cannot log in. For a better integration in existing systems, AjaXplorer can "prelog" a user from external data or logging system. Users must still be created in AjaXplorer, since their rights on repositories and preferences are stored by the application. But they will not be able to change their password, since they are in that case managed by an external application. 2.2.1 CONFIGURATION ENABLE_USERS => 1 Users management is enabled 0 Users management is totally disabled. No logging required and all users share the same preferences. ALLOW_GUEST_BROWSING => 1 In the "Settings" console accessed by admin user, a "guest" user is created on which you can set rights on repositories like any other user. This user will be automatically logged in if no user is identified. 0 When no user is identified, the login screen appears and no repository is loaded. AUTH_MODE => "ajaxplorer" Default value, Ajaxplorer is doing all the work. "local_http" If you already use some ".htaccess" file for http authentication in the zone where AjaXplorer will be installed, AjaXplorer can retrieve the current logged user directly when loading, avoiding the user to log him self again. "remote" If a standard scenario would be that users come from another server of yours on which they are logged, you can pass a session identifier to AjaXplorer and configure it to ask a remote server for the current user logged id. (cf 2.2.3) 2.2.3 REMOTE LOGGING Here is how to configure the REMOTE_ config variables for asking a remote server the current user logged. AUTH_MODE_REMOTE_SERVER => The host to request. For example "www.yourdomain.com" AUTH_MODE_REMOTE_URL => The url to request on host. The script should take a session_id (or any identifier you want) as a GET variable in input and output a user login in its response. For example /public/yourscript.php" or "logger.jsp". AUTH_MODE_REMOTE_USER => Http Authentication login on remote host. Leave blank if not needed. AUTH_MODE_REMOTE_PASSWORD =>Http Authentication password on remote host. Leave blank if not needed. AUTH_MODE_REMOTE_PORT => Http Port to use AUTH_MODE_REMOTE_SESSION_NAME => Name of the variable in the GET query that will contain your session id. For example "session_id". Once this is properly configured, you can append the ajaxplorer url with the query string "?remote_session=YOURSESSIONID" and ajaXplorer will call your script with "session_id=YOURSESSIONID" to check if a user is logged. 2.3 FURTHER CONFIGURATION . $dft_langue => Default language to use, please use "en" or "fr" for the moment. . $size_unit => Use "o" like "octets" or "b" like "bytes" for file size display. . $max_caracteres => Max number of characters for file and directory names. . $showhidden => Show hidden files or not when browsing folders. . $upload_max_number=> Allowed simultaneous upload to the server. . $webmaster_email => The email of the webmaster, not used for the moment . $recycle_bin => Create a recycle bin folder in your repositories to act as a buffer for files suppression (like windows recycle bin). Set it's name if you want to use it, or leave it blank otherwise. . $user_https => Set this to 'true' if you are working on https connexion. 3 TIME TO WASTE? Visit http://www.almasound.com/ and listen to good Reggae Dub & Salsa music! AjaXplorer/AjaXplorer/client/doc/CREDITS.txt0000766000000000000000000000365511122202526021747 0ustar adminadministratorsAjaXplorer Version __AJXP_VERSION__ - __AJXP_VERSION_DATE__ Please read /doc/INSTALL.txt to find help with configuration. [MAIN DEVELOPER] AjaXplorer is developed and maintained by Charles du Jeu, from Paris France. Project Page : http://www.ajaxplorer.info/ Developer's Band : http://www.almasound.com/ (reggae-salsa-dub) [EXTERNAL LIBRARIES] AjaXplorer was developed using various free libraries that are mentionned below. It is mainly an engineering work that used a lot of off-the-shelf components. Please check their websites! ++ ORIGINAL PHP SCRIPT ++ The original php script (simple file manager, no ajax gui) was called WebJeff File Manager and was developed by Jean-François Gazet. http://www.webjeff.org ++ ZIP FUNCTIONNALITIES ++ All the zip/unzip functionnalities implemented are based on the excellent PclZip class developped by PhpConcept. http://www.phpconcept.net/pclzip/index.en.php ++ JAVASCRIPT FRAMEWORKS & PLUGINS ++ The Ajax client is mainly based on the prototype.js library. http://www.prototypejs.org/ ++ WEBFX WIDGETS ++ The Ajax widgets used for the Tree (XLoadTree) and for table sorting and selection were developed by WebFX. http://webfx.eae.net/ ++ MODAL WINDOWS ++ The modal windows are done with a modification of the Leightbox script (itself a modification of lightbox.js). http://www.eight.nl/files/leightbox/ http://www.huddletogether.com/projects/lightbox/ ++ CODEPRESS : Syntax highlighting ++ The online edition was done integrating CodePress. Very powerful! http://www.codepress.org/ ++ DEWPLAYER : MP3 Flash Player ++ The online mp3 flash player is developed by a french webagency, AlsaCréation. http://www.alsacreations.fr/mp3-dewplayer.html ++ MC MEDIA PLAYER : FLV Player ++ MC Media Player is a Flash-based media player for embedding video, audio and still images in web pages. It is free to use for both non-profit and commercial websites. http://www.mcmediaplayer.com/ Big respect to those developers! AjaXplorer/AjaXplorer/client/doc/LICENSE.txt0000766000000000000000000004446611122202526021741 0ustar adminadministrators GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS AjaXplorer/AjaXplorer/client/doc/ajaxplorer-manual-2.37-dist.html0000766000000000000000000005535311122202526025753 0ustar adminadministrators Untitled Document

    AjaXplorer Users Manual

    AjaXplorer is an easy-to-install file explorer for remotely managing files on a web server or operation as a simple file-sharing system.  Its rich layout and actions make it easily accessible to virtually any end-user.  It requires PHP and server access (either local or remote via FTP) for installation.  It uses an AJAX based interface, providing streamlined and intuitive functionalities, similar to that of a standard file-system explorer on any operating system.

    Quick Links:

    Project: http://ajaxplorer.info/
    Demo: http://www.ajaxplorer.info/demo/
    Download: http://sourceforge.net/project/showfiles.php?group_id=192639

    Copyright (c) 2008 Trent Scott - trescott3[at]users.sourceforge.net
    Doc Version: 2.3.7

    Contents:


    Chapter 1: Introduction to AjaXplorer

    1.1 About AjaXplorer

    AjaXplorer is an easy-to-install file explorer for remotely managing files on a web server or operation as a simple file-sharing system.  Its rich layout and actions make it easily accessible to virtually any end-user.  It requires PHP and server access (either local or remote via FTP) for installation.  It uses an AJAX based interface, providing streamlined and intuitive functionalities, similar to that of a standard file-system explorer on any operating system.

    1.2 Features

    • File Manipulation
      • Rename/Copy/Move/Delete/Download files or folders
      • Upload multiple files and track status with progress bar (Flash required and no https)
      • Create folders and empty files
      • Edit Text files and code files (js, php, html, java, sql, perl), syntax is highlighted in the editor
      • View Images online, preview images in the list, diaporama of a given folder
      • Listen to MP3s online without downloading them
      • Browse and Extract ZIP files online
    • Rich GUI
      • Select multiple files or folders (copy/move/delete action can be applied)
      • Drag'n'Drop selection to copy/move
      • List/Thumbnail Display
      • Keyboard Shortcuts: Ctrl + Up/Down Arrow = toggle selection, Tab = navigate between panels, Esc = close dialog windows
    • Advanced Features
      • Bookmarks system
      • Search recursively in folders
      • Send URLs with file links to a friend for convenient sharing
      • Recycle Bin with "restore action
      • User Preferences to set preferred language, display or password
      • Multiple Languages: English, French, Dutch, German, Italian and Spanish
      • Customizable GUI with header and footer templates
    • Admin Features
      • User Management system
      • Multiple Root Directory to define separate repositories and assign access rights for each user
      • Logging system
    • Development
      • Plug-In Architecture to easily extend the application
        • Currently supported plug-ins: fs (filesystem), remote_fs (remote server with AjaXplorer installed), MySQL (browse, edit and search MySQL database), and demo (all write actions disabled)
      • MySQL DB Management (AJXP.MySQL Driver)
        • Configure a repository with your MySQL data (host, username, password, database) and browse the tables, execute MySQL queries and edit/add/remove records or structures within tables

    Chapter 2: Basics

    2.1 Download

    The current build of AjaXplorer can be downloaded from http://sourceforge.net/projects/ajaxplorer/.  Unzip using WinZip, ZipGenius or tar -xzf AjaXplorer-core-2.3.7-dist.zip.

    2.2 Installation

    Now that we’ve got our files, we can upload the whole directory to the web server (using your favorite FTP program) in case you’re not already working there.

    AjaXplorer needs to save/download files and be able to modify user registry. Therefore make sure the following directories (and file within) are writeable for the web server:

    • files
    • server/user

    2.3 Configuration

    Browse to server/conf and open the file conf.php. Use your favorite text editor to open and modify this document. We’ll customize settings in this file for your unique server configuration and security purposes. Make the mandatory changes listed in section 2.4 Required Settings.

    2.4 Required Settings

    • $dft_langue="en": Set the default language to be used (modify bold portion).
    • define("ADMIN_PASSWORD", "admin"): Set the administrator password which is granted most permissions (access) on your file server (modify bold portion).

    2.5 Optional Settings

    • ENABLE_USERS: Toggle user accounts on/off.
    • ALLOW_GUEST_BROWSING: Toggle whether guests (unauthenticated users) can browse your files.
    • AUTH_MODE: Specify the method of authentication to be used by the server for user accounts [default=ajaxplorer].
    • AUTH_MODE_REMOTE_XXXXX: Specific settings for a remote server (optional).
    • $size_unit: Unit of file size (b=bytes, o=octets) [default=b].
    • $max_caracteres: Maximum number of characters for file/directory names [default=50].
    • $showhidden: Toggle whether hidden files are visible (1) or invisible (0).
    • $upload_max_number: Maximum number of files allowed to be uploaded at once [default=6].
    • $webmaster_email: Administrator’s email address (also from address used in ‘Send Link to Friend’ email function). *Note: your servers “mail” function must be enabled.
    • $recycle_bin: Clearing the value in this field will turn off recycle bin functionality (archive of deleted files).
    • $use_https: Change value to “true” if using an HTTPS (SSL) domain.

    2.6 Protect Your Installation

    Access through your web server to the following directories should be denied upon completing configuration:

    • server/conf
    • server/users

    Note: AjaXplorer uses .htaccess files to protect these directories automatically, be sure to allow override of the Limit directives on your web server (contact your Webmaster).

    2.7 Running AjaXplorer

    Upon completing installation, browse to your live site on the web server (http://yourdomain.com). As AjaXplorer loads, it will display "Loading Components… Main Template Loaded… Action Bar Initialized… List Loaded". Once you arrive at the login screen, login using your credentials. [default username=admin / password=admin]

    Select Remember Me to save a cookie with your login credentials to the local machine. Note: Do not use on public computers.


    Chapter 3: Toolbar

    3.1 Buttons

    AjaXplorer’s intuitive toolbar (top of the screen) has 15 buttons, corresponding to unique features/functions that can be performed. From left to right, the buttons are as follows:

    • Parent: Switch the active view up to the main hierarchical file level. This is the root folder of whatever repository is specified for a user.
    • Refresh: Updates the window to display the current files and folders. After making changes, a refresh of the current screen might be necessary.
    • Thumbs/List: Change the display output of the files and folders in AjaXplorer. Toggle between thumbnail and list view (including details like size, directory, type and date/time last modified).
    • Bookmark: Save a current location as a favorite for quick and easy access.
    • Upload: Add files to the current repository [default=6 max]. From the Upload window, click Browse, select the file(s) on your local drive to add and click Send to begin the process. To remove all files from the queue for uploading click Clear. To interrupt the upload process, click Stop.
    • New Folder: Create a new folder in the current repository.
    • New File: Create a new text file (.txt) in the current repository.
    • Download: Download the current selection. This may be an individual file, group of files or entire directory (downloaded as a .zip file).
    • Rename: Change the name of a selected file or folder.
    • Copy: Make a duplicate of selected file(s) or folders.
    • Move: Relocate selected file(s) or folders to a different location in the current repository.
    • Delete: Delete selected file(s) or folders from the current repository. Deleted items will move to the recycle bin, if enabled in the Settings.
    • Logout: Terminate the active session in AjaXplorer.

    Chapter 4: Details/Search Pane

    4.1 Details

    Click the Details tab in the lower left pane (below Folders) to display current file or folder attributes (name, date/time modified). If a folder is selected, click Explore to view its contents. Click Download to compress the folder contents into a .zip file and download them to your local machine.

    4.2 Search

    Click the Search tab in the lower left pane (below Folders) to enter a search string (phrase) to find in the current repository. File or folder names are acceptable queries. Click the magnifying glass icon to begin the search or X icon to clear the field. Previous searches are displayed in the box below.


    Chapter 5: Navigation

    5.1 Folders Pane

    The Folders pane (left) provides a quick view of all folders in the current repository. To browse folders within the current repository, simply click the folder name listed. Click the + icon next to a folder to display its subfolders.

    The Folders pane is also used to navigate between other repositories (file spaces). To switch repositories, select the repository name from the dropdown menu with Default Files (unless modifed) as the current repository.

    5.2 Path

    The field below the toolbar (top) displays the current path relative to the root directory (default repository). You can traverse between folders by modifying the path listed here as an alternative to the file browser (below). Click the blue arrow icon to go to the given location and the gold star to bookmark it.


    Chapter 6: User Settings

    6.1 User Preferences

    To modify your individual user settings (the account you're logged in on), click Logged in as xxxx in the upper right corner (xxxx=your username). This opens the User Preferences window wherein you can specify the current Language, Default Display method (details or thumbnails) and Change Password for the account.


    Chapter 7: Admin Settings

    Note: Admin account is required to change server settings. [default username=admin / password=admin]

    7.1 User Management

    In the Settings window, click User Management at the top. Under the section labeled Create User, you can specify a new username/password.

    The User List section displays all current users on your AjaXplorer file system. To edit a user, click on their name (must be done from admin account). You can specify their Repositories Rights (read/write privileges), modify their password or delete the account.

    7.2 Repositories Management

    In the Settings window, click Repositories Management at the top. All current repositories (file spaces) will be displayed here and new repositories can be created by giving them a unique label (name) and choosing an access driver.

    After specifying the name and driver, you must specify the path to root folder on the server (e.g. files/). You also have the option to specify the name for the recycle bin folder to be used for deleted files.

    When finished, click Create (if it is a new repository) or Save (if modifying settings for an existing repository).

    To delete a repository, click the red X next to its name under the Repositories List.

    7.3 Logs

    The built-in logging system in AjaXplorer is useful for debugging and troubleshooting your file server. In the Settings window, click Logs and specify a log file (by date) using the dropdown menu labeled Choose a log file. Log entries are sorted by Date/Time, IP address, Level, User, Action (whatever was done) and Parameters (specific to each operation).


    Chapter 8: FAQ

    8.1 Where are the log files?

    As admin, open the “Settings” window. You probably see a Logs tab but nothing listed inside of it. If so, there is probably a write permission missing -- the “logs” folder is created inside the “server” folder. Thus the /path/to/install/server/ folder should be writeable.

    8.2 My file upload size is limited, how can I change this?

    File upload size limit is not an AjaXplorer limitation, but a server configuration for PHP. If on a shared host, it is unlikely that you can access this configuration. If you are on your own server and can edit the PHP configuration file (php.ini), please have a look at the “upload_max_filesize” instruction on the PHP website.

    8.3 I created a repository but cannot see it?

    This often happens if you have created a repository but not granted access to this repository for each user. Logged in as “admin”, open the Settings window, Users Management tab, and give read/write access to the newly created repository to whichever user you want.

    8.4 How do I create user-specific repositories accessible only to them?

    As admin, open the Settings window, click Create Repository” and in the Path form, use the AJXP_USER keyword to create a path that will be adapted to each user. For example, use the following configuration:

    Repository Label : “My Files”
    Driver : “File System”
    Path : “AJXP_INSTALL_PATH/files/AJPX_USER”
    Create : “Yes”
    Recycle bin folder : “recycle_bin”

    (Each user will have their own unique repository and the admin can view them when browsing the Default Repository packed with AjaXplorer.)

    8.5 I want to develop my own extensions but the JavaScript and CSS files are unreadable?

    Change the $JS_DEBUG variable to true in the file index.php at line 72. After doing so, AjaXplorer will load all JS files and CSS files separately, instead of the big compressed file used normally.


    Chapter 9: Credits

    AjaXplorer was created by Charles du Jeu. Other developers include Mathieu Baudier, Trent Scott and Stage NexVistion.

    Components: WebFX widgets (XLoadTree, SortableTable and Selectable), LightBox modified by Leightbox, and the very nice CodePress syntax highlighter.

    Please visit our website, http://ajaxplorer.info for more information.

    AjaXplorer/AjaXplorer/client/doc/Ajaxplorer-DriverAPI-v2.3.pdf0000766000000000000000000036547111122202526025173 0ustar adminadministrators%PDF-1.4 %äüöß 2 0 obj <> stream x\ˎ Wz-@@= @Av 3~DEY"7w\n[oy|ă`1z&5䨎*Shb7=5<0_~RIU*k_˷nZy_o?o[~r]ߧ_w{J"8΅\Lc(У:QwZLe^owa Ї 8*rbnfYs^Yۉ8 =|ۅ:o:s~ c[%&a6ZY8 UZ`NxBFߙu^|}iX2XHg0,O3ҁ\L~Fp8񺾮wFO 3 ?aǻ^_=/{ K!uuCf4z]_?( 1ccՁ#=Zy K@ .k gK=hd(b "SN PLGX {HGW,QwA79KC`?@@r딈]gn4[m ƻᐭ%X b"@(}f0^8-ClٞCǡpiZ4J#lzcgQ 5AŴ.҇K|DlNhsj lۖ^EH+9b#W5C+1COa-4滙qcl^o4-ŷ"ü$z#c27.[JS*w$w>*iI{^b^$)xI;WΗR|*ދR\H| , ({T4eEbpSKLYF*iׅ*[Grqt945pˌ0sw BBh{aۛ }I3WMٹ0c^k0NNjĒ]QM[4y6̈́e$b<7> cXj4ٷ :M "j"eI.Sh,BNd3C8T0*$v^$ XJAЋ ̲GsЦʙQ #?iĠ"N+ml<>zɸvzr (0>X"p-v % -@ M,D6wp32t4=?ܚ2ETfyNVKi *t# 2;'~U $ xϡ]g t]^44) S40I_m LaJb,YCry`Xg]EMno σAx->Cԏbƶ0.DEiY S4\@zMq$Kz )vNjUҷBo,q9r Fl!`źfM㶲*ӟ @d'omS3\_7\Ţb6\|OjP^+MI4+-c!R[dK"YECNPV kZ,tAS"y>]N+WGfC"|5a.?Si;Cn7v&Z(5SQg1֙SHT]Kx[]MK}L0qڲj Z,R aaPe_r1ZK%msWXۈ4K#eYON@1`F5/ƍ*Ɇ cLN5LS[8UfY)QTn[?6Z]` + Қ#' ‰*~s}<GZA{( o",[rIDׄxz~𚈧q3 OBf TMYvmA*В-.ٰk80L@p._btx]]U]=\@L[ [j/!S҅kieVE9. uR Y)(Z}qMūW+&ʊBD0D[m|+Oe?Z2Mɦ suc YDfN#q m|ѵnf9`lҋcZ9bǭl)lH ]dBͭ|{ qV6) 3I8l$u7NT aTth}=ѝ@eJ_a`Ǫrʷĺr_6lt)M c,9|;>RHv;m%4 #], $}u"En䚟 (4moN%޲01n}nb|Iq97=r}V5.0Pg(8jrEv7q 'UKh6YxC&OspwϬ0eqn,1N޴f-&~vbwFCimNz>ߑ ۛ)mhǨK:9B0f;P,\xxL"42-SȢEndnc:QKR6*FvW-J*B8F1Z7hJ]EYr8&pA)b\NI-"):eeQxy0{FnǢB٤)K/" i\ LMǐN(hYi%}GNyfQע{c6D;ˈ>ϣ~rq6;&uKX1̰(ڔ eoA=wnM;;t>19_-CىiG_ף\[ZF UY5ʿc3*uiuŕ! RU)z(~&tŕPv۾_`7X endstream endobj 3 0 obj 3163 endobj 5 0 obj <> stream xYI$E_gᵱ MC&x}A<##8FDfUewuV z\bb-n> ȓ~˛p7f6?6n%MzWuЫ{uW{A [ZW|&Yj݋=Z8Ld#'Pth"urm}oJGf78ǮH| F^ȷ{C= iGA0?`]w=wH_cZ1waZ-ū[Np512[ܒ?//N޼qx{ {>YO]|*,QP1tLNAtAKf1]u9VázCgQng#cs}~Yn  Ӑ*BWs-d:CQ[ϡ*Ѣ X w>W@Ώ*ye*ɬƤg%6 J&l]ϓe1]̂[2Cc FhdXlY,L:^-kM7\J^M 2 p# D$^2y0bŒ >kc|Ϭ(լI!0.Jܿ-L[?YŋM:5 IŊÃt$'G,8%)A"r;7$6=R>=a!r.Zj~dѾv4A͋7fRmGnZs^y:d׷~FT*I3t /fĶ΢^.KDXB: sd:ɂ\B:amdEVk#^tw߼a:,vN7W`=y cӊ9zF X:Rʕb$/Yϻ/+ҚXoIqa9{}P6[K9cR+ Źe*t4\Nvp+Uis]EfkRZ5vêQD&MpTm, Y.qB~妖M2N j%\\zS:Bį0/'M(@(*.Lw8 x* kmm|;IcC6Zہд#w6 I^4"v~=5u%/6Yƙe-aeU1xۤ0/5ٱqg9 (WM`f_8Dd)rJL%ؙjdt T^8&]^]=5?1Thك>ťo"7&(.$SCӃWؕGܣo}t`~D-&(Qʢ-`L&Oj?>0慾89kQ g}eq1-85*d~j&*Zt~Q=&)r͡%? ~T$A,mF8N"iUV tep  GDf|k;b=]tQ͔ri-[*[_ȅobuA|GwmYz endstream endobj 6 0 obj 1753 endobj 8 0 obj <> stream xYI7 _s犤V롷!M 4FXS4bϓH'.?oKnOhav~iכ'xs~v!l}ƯʞZ`o{61qݣE&ae.^'py^ #`C>F\6|/qɇvF|@%=\2.5%u%!V+}i4nL vLrPؘcz)_0岉?~t`9hp6/ ȫ?}vx|_'eIm0ɟ)9ΘOOrb$Eˣ9i>eBWfsV}_iU΂G4RVӳlu2gsQ9!@q %d,t#ωxy>8ŸrR'x"8ڵ.`=v+0!Q62DE"YA3$p9$N@4$: HP!z.řڱ*G|$Jk_t!caBo΢xdpq +w$[=ϧ'!/gX]8smbdin9BIQrx.Ӹ6U&\=2#=.-f/D-iuz.IOB9p+]~Lbw.l\{C44V%Ea.x169J° &8+7$;Mt,w&9N%RBNھlp8U XYfK1[5D<ɋw{ \K @(($Y98M|g6IK)0Pz"[t+QH O:E̪4ү?&a޳bdzd6oJ$B9H|Qul,:UCa؝aDq٩9wƷn; 4Ph7ķp?I<ڤ8U8| }T\DV̼xTτ.+Z(0gB8^Ap`ʮV5\E"lB^AebϔK(CXv3[] JV*3Ɠ܄%sK #Ie%tuS?,Rׁ{܍ )kh Dc7Q\o_E(mkH?Zp?k X`쵆/JݣA|2|49æꁎF-Ogm j )r1 ,'&IOdA"D]wR9w=l;Чypimǽ w)K5d6yB%c+}J7rvoAԔš}PjP@Fר q5I_J%d60s'ټҨΟ|yQjUy 3˶ i[42DQ'U!7S?< X}F-wǗƫPvNc9K&jӂZ|ۥPyzARK8z`a+N6) Lxbs퍾~kpF 0,sWhM^vsŽrcZV U, tMZQΠD.Tmw޷&nʣ'cNx`exXwŰЎ!_ J+ mSjژ k1~gB Лg~ 04O6we 鲢Jy`\7n9麾Z#OP͚oj{ДA&/s(GVDYg3W-2o MxV\D|L61ؚlMd0\VJ7RitLe9j܅NA (YĊԇ*s 6B(Dê2oMALk'V^X^m^{wG_GW_! 7TWz-}K8:ڶ>ͺ\ endstream endobj 9 0 obj 2049 endobj 11 0 obj <> stream xXK#7ϯsJ0؇r9,^S*V{a.Iz_MjRfw4SpN4}o@D%~ _:)Xy|c?AOpo's[Iş^r0'Zɸ4|^I@45͆_JCz+-x_` _e@Ldb)!xЫ~ =dg|3}d< $ ?iHA u 2-+,a=s2aPÒVo5WWdOM"kZAV,DY0A@)mvRN)M4sXB0,YU\YAņK^׆z\*9Ș\2^8ƌ mF6t,EW•uԣ1N>>RfWsd+dkT³deñV U#Y@0)>p3[!fI/H/w6$?b>/BmpRm"BA'Bba>g<[>m>% W20M>~%N Lw4gN;suNa.{*# `hFYG޵Qfݢ"BM،L46'V}ݙc k8Ѭ,ev ZxCRĦavRɑR&?uIb 4\wb:ҜRW[jz:]?Z/Z&94MAIr>sԯM빶ێ}-c KȃZS+BaBcy6F,7̬2OKS9k9snUfo6L*?y(Tf-R\d 00ػkg~gB2`"\V<D@Q(:: XE(Og'#ǪiGJcu _d(ƉoT}bbcEZ*$~dVU\Al/m$Kj$*h6)&=s*?t5F7~ͪ[ޘK0]+^h)ui ZgV2LtT} s*+t[a3̭M_pnp8Xs&9==OPժ|01칅ꏡNPa6Lٻc-H Wd2sg?Fc }ȺEgn͵W+9YZQ?uRQ7nS6c%mfg OrXxR'}FtCM!jr۟ޅ{X?;d m/cFs]F]_P\ endstream endobj 12 0 obj 1429 endobj 14 0 obj <> stream xXˊ6Wx^d0Ev&E wO$-N[/:u1W;`o<^÷? }6N41߆_vboˈOy ֋_[}~kW?Ҷi1չ2/ x|N8:ӓua8 {ǴKBk{qೖΣﺸNqmD F%@ww"E5Ȁ O_.a3';_WP<ĚW nc$'ς!pG q2ejlԝiragk]#+OJ^w* 2A$i-VSw(,Yv`۷sERMB[$E⹳8B/f'P&U6@U:hЅ]t/Uא^IRh͜BڨEZ&wỉ#Å$:[m5x˖j, kiV] YXЏ/kG#SnN.~"R[8> stream x|{\\յy1́B`!"!4ZksfL~_kzI  oؽPWH4*o j]pgh*ރk0`tO; yQݏ}7jE~֛B~_u7oAwԇ9<Ґo0pÏzP$z'qlxN6FNԴJRI~`ga0KEҶrǕ[}N8 p^o`18;0lCK0|*?:<W! ^Wa+6w+I=ءpߒ2dCl'O]"se3]|!j`-sRj{qq[7_Tm΂#iZ T:')$n?w{;}׹~{g[5v>c(ϗgRCk»ŸUz-U_Uz[ jQ}z_}zZS ٨\I-ha cW7_39[ar'16ni2ߓQ2 #'%DTMa;ஷ_uqE+kW,ZV]^V*YR'9rsegm KzY4 VV 6;[XQWL(rYSFN"|I41I )=H JLIPQR)^mrJdF/779;Y1X(bVlobKjO4w5xFgc &SYÓĺ06@k@bYΦDY;؆켼i;c\3 4ibƘM#r&iāi\=vou9.)fs6_[f[PՉR{3[uZ3A^P 9xQ[Tdju%[u )՜J<@z.ƳM1p@FKì5"}Z ujBuĵG+lsc;[Z=LϝP`REOk9e=O~ʭO5FgZkww"mP画7*,5]ed~g:L-}5xRj/.`{˳E4WզdgŻ*%ӲDHW67IAhAHs5vf^T|`̔4EL^0FؚՆζom8Bi3dg oUO+ޤ)~Vo Bz)bw{ ץ[/!x@xb_/zppF` 06Uu+8S3,|e[ܭPFCݨ"QqrU֞cjC& C+ۆصNj^yW}+{۝xk46i\b&]J}O;Of}KN}n#O>mU7j?kT#|r2cV]JoA◔p\I ȒXe9'7,EHLiitBn)tT=H]MG'*&?,&]"BΥO#GJ"8DpbIڅ%N4km3X`2P㧁AxV<iuW'Xn=7o/ >cQ[o=utSlj{PĮ+z{Kwʹsl-յ*O̦7lPX4Cœ*\aږӤZ,f r+F3DL<ѐQk&]bDIS%,{y8t'p=j _}wva# WbLh@9!N< :x L(N8&Mvf$qv/ՏeBvilʁO ʕl@@ RӸ4ArjӦ/{-ș#0c6%FNYH粏Zi.{6trUux4wGiG1В ePoM_k/P`9fYz LTrnnko͹浍SWY Knyyqs/<@TW=0s|8SubܨȄ\ԐbD_y3MFҪx!O4# T}*͙NPCQ Wʧ^0=j"ҢLt'Mi^>~G0>g637PgwQ1*CQaY&(UܲJ*gya[7_}9ځv4k[[/&Lp1,k'a_nWTӽ:>S919) iNV5M4!A'i m8>u?ߩ#U-A֣̣TM\d;?lZq z$ /߹"UR|f sS:$ˑQ9s$H()LGjha%\T%U)froʑmΙ3kW")ZK4a6ae:K4-Z\TF:7˙an ʰhk]P8ƦCaR7rEYկWokNwIU%5{+kxkeeQVcz嗣lCWrxֳ2RRw$[[\^_PUZEbnH*vJS CfҦtG(kBLyrݒ$Wt;9\nj'\17~ 5P%;;CANtU"(қnf&(=Jάiɓt4YQIy#ۏmbҌmyO#^E22]\{:vƜKT:{excuFu΀el1($Tc\ !0\";ɽ|A0!YԄ Kr@3Z fȔfeVUd,f`w|?1K'=dS/܆z5 4w,67~HA!V 7|N|"id}=G.<0o@|ͪu\@YDBG^jV7Q̽\-Di!~MmVOu]pPu:Wv{OfFg<47lAD}5=}CHRXgRVyV`oa)#(CA= n-ЫQ` l i_cP ́ZBy{XTk B(N) tsټ\S8yai;c%U 6Kz7rB*u bgYeKa _ C)~'uTkV~~w)0߬e ZtFf*07{ W`ԯKF)0ꗾC8ʤSQ&Z_x+eJ- %-~[{" Q` D)*%D-я(0_W`v6 L!9ĬH_`/W`o`pCq>0 L2FGXZ&Lb0[WߤpLgFK`W^\Kq@/O Ż!;PIMCF>_PGr'8`3 H&[ xU@U2l&ӇmyOܞvIʵdD tA+2Niʨ[P_l`%(bae!=Q6XO:Zyx AQQ1U_bޠbeL!V^ZadƵVV'Q&ȋT>Ve 20 69Jֿ_x=و~(K_b\|~Er :(O?xðMY| #l6͐U\T6>OJbcs񲴣DFΡ& > fIZԼMgDX)+>Uf *+2<;.^ v^AE!e%AF?jZ0+`ܝ&7XK}":4nT)()^Ya +6’z"myt%[dWdZ`4dkb=$[w0aYw+dPU|K; >Ymzر"X_0$ݳ6 qR'Vl[b66.')ﲿG!{SD)2`/sMyKgaf^2XE|!3iI"A}Hbs} qŶq\z3[΢ R3_@h!EKhTbfD>6J v(QUbiwb7cX": $l:GT^'RFsQv@j,2\w+RF>U-ϵsg6|,W#J f>Ύe$\r1dJYt.)8H$LEIti:d{ߗnЂƘw2m&8OBZ9Ca'#l݃JD/{հbw Zs5ϽP24y5rgZŸҌGهFYn4xa% *geqQ|gcq>!y);~!G%O@> c_5x\2* .+"RI^|Al RȠoٗϏJu$lq  ttA>/GX00 FȈch0~Fth4/:Mm B'  #2^qNDR#@$F,`pQC;qXd}}!>֏2( 0>i! PvCA?(!'’q1q Ac xcEأ; DФ4F(#~*7KqQ(\z8zi"(2fXp@_* #q:= 5$AC!6Zy4:+T tG܃Qo݃>r .ַmYоv:i}tuK6575k7RQqQS (y\-2]s4=P̏dD`6EBr__8X.u`~A.`Z5*.@%^<_T#a*NCՠvDqhd3ő8Sh Q$:SkF}#n0_-$wex|&%rypĠs%66VfQL̻?@p0H0PxgD6Rf À:=yp,Y܃h?jx\W‰XNtP^EWR-p(^QUDYBҊȊKYV#T/]^kHHkn=xQ^Hk-;Ym=naΤ^ROIOGd2O>A\qąO>A\qąO>A\qąO>A\'V"MBi~($OU+5X.[<ά|Tr ]/YaE *[?–?Hwg2 C}a/A |V[2vF^Gx/;I.v+aVֳJ:;+O VYY ѓx׻xƓD,%xJANOU9n&zOM\jtTLQOWqW!8.ZZQ5ifg<~~ITeY ':]5_[* ;HcSMS8dg4GٱŠ3j#5j6h^9X9\sBsЭ9,XiZQkԦjSZZ+h9-h-6EP ,r-B,oZ7&~hb&)T$ miܦX5pw[:n&&v>\'PoΦϹoz[}*smKy.LǦGeQb V7c U[N7s:bhݾY=AǛNoG_J4oxUP#tC=z@d:'C2%p2:g.|ҕY߂\Fk}+n򤳹i錏uќNJ1I]Hc$-$e IyēyLc4:3] I-h.?3ULOwAꈥ8WP_osuĭNR_gۛ}RNEAi*k(kMhH8ɶIDH3ؚM?7<+߸;4<]M2u NSQO/%YpE(Y&wh endstream endobj 19 0 obj 10559 endobj 20 0 obj <> endobj 21 0 obj <> stream x]n0 yCE-m%"q 1]xqI;~`;scO^$[|F9{jҌ+-=o9v%.1T,y ٻNj%/NWUf`<,!ys7B]F:X  #?ȻL[Ikҳ O-~V͹x7ܘ6{S;YtDݐ endstream endobj 22 0 obj <> endobj 23 0 obj <> stream x{|8>3mf\gsې͍܃H  w$@"_T1ZUXeIj [EEoVewf'!x{~߿~73gf̜9̙sل&dAƶ_}ag^eϪs>x5m3Bk>_ڿ~8!&knjXۑn#0FQ3T8r Eֻ{Z;c5liftWxʙ5 swv7u~?3Y@,2xA Fbe3x}q J 9%#G,=4PY}EZY Z?WWq{'؉vDz35% }AR$"/ZvjPC-E1!:3t@y86&0dTKX'GMd7 GD_Ai{d D3@_)!u6Ԁ6b!D / -yWkO`֩ %B BsPjCGj hAih?NG[)_)9P>*@+Q ݃~ OOalBף[ڰ%gZr|?,=Xht-z 8>I?S(JG3GסS4nfp07!ˁzrsF_rGO`%1 {V 4^? a= h+ڋ=[='9 $2t0O¹"{#UbxJj<kt^tY菢OF112"+P2Q ֵ8 A7Лmh /ƭow=Y{b"KI YCn&G1<_7 y3WM!_Nq8Hsd]?-:!m~4׀O<kt'm n셟x 5_7@/^<¿/e:~?gG|OI d#L$?%@OUrp2p%3MppXܮ* Ab!S~ 5D&77/"zV>??\dvÓtq^Cp-ތa+ނk]d?dG(Xʇi=r.ct OE@NЮLt/wJ f?K9ؤW[x#7==?$O|!`onGEc; y ѥtWAdJQp :iWJݤ w\:OP C?D{ \ŘƁ5۸z~btiSriRDոM=p:h d.} wrG=OB)r2X4'?6Q S)9z .o+FЃ`WriwFEx/.;ҁ~7`Q;܊,v ~@>~8osw"Ոg3ϰCypf`/_=n0#NoFO EjK\2 ?oRnNvVf(cbz0-5%9)'$&w+6l2$Q98"^ ՇYh9*Uԇ'34bL0W S01L,+SДL"Y T /Z%< X @z(r%땊p-0niF&SV&m2h(I܍=S1bn V*\^%S\jEêpe@mVfhL^FCA34aqFXb(-t9̃[neU\C-yÞNz/apeǷs[*- -nٲY l|k>kka KR+TԷQ.zsJ>] ZS6&OOnre=$nK- ũoP,Z'6'v- |⻸%+sиfu<4 NcĔ٠aQJ%BJ裩mi,4b^bh go'z?,ʖO=y45b U1Q8 32^H3@@TV.\7L$w d>T NT?VJ(7_2~90-G[bӖM-cA}gulؐ6.c*'[U/_Tly[袒^2֦CXkTdи/OHLh; h XœZ " vȴBSE-JeX=kM7 : G^,M_Rxr%/βz4R-[LUڲ2YRa8ie"'o-A|ZXD3 MU|˗0MeѲA6gOݝm)Z2VKK -* bXS>Mg83a8L:' !B5p|8O0D"C&#A \xސ|n)S枟Ǥ܀#HFNO)IwեbΔ|\Dr{4YXd#.w~^q`/&r6xip ]?иڧ%KfoNO?ȮȩW#ޔ'_{_G6>,-(D?B|A.xkqA19"p$ݫ$v&lO8`B ؄L`7>}qTGIܬŶEնUqH8"?y~-LB='H16gygYVNyw7==oxN7_ )P(RM)Ͷ}lo2\/hS :4).]C8LSIqQqL Ii+o͙75>}%9rvB w'iЕ==˦f7>sữ-~ N :[[oh116q 8ubcN`"o?mk;j|WdLNDd^ iu*isV/Z07iP:mL!-NԿ |:zf &5+cљG уC4Wc} j ڀA6(30LfN1h11M%#Vܜ{Sr ]PR75B]gGPy0D:qG]Zd{Y~jAݡɲU蘨BD$!;J;g)YJ%^W;uwJtSAXɨZJm(}jq ДX@[y=1 J5rA#+kko>l͝cL|`_ wպTj*0޲".-K*J8UR G)nGaakN+&I?񋥻%8e8 +;݊lvq?y CJviae3 FBu(6IDںˁhyڎ[eg?ه݈su'Gsu'dz|ЍYf{Qۅm tvw D >ZBw:=9K2*#i7[/F;|S.g4;pRT9bs³k^+#rƒNiy{~DD,lu'֑uz?f3j 5`4v *f -BPj$bӌ/3n9$<6N&]T 5(.If`~rr$*gj&t& U0m)WRi@.H8L-8`{s]kk8:Kv)zA(cK~yu#2*-N2+Jm(@mFʹnXoa@[h-NRкq}3Ri8zbTHӭvb%K. ĸ=$cIN#x¬xde_w+}n\ ܃_ӕWG=lN IuILg2(3:fj&><pm\RN=u"KH:SS&QTd/rM0ϴtΌ9ay}ifrVeSh!C·cߩ*+kyȺ׾7~p|s %>8q8oļZ›[2Nc?HaL"Y6Č l2KJ&\Yp&>!AIJL32rBHv83B&Oɔ1!dY5-qDajNXM$qiB`{_up}WB$5I\(Ϲ#sI^L6r[8I4^7q !ɲqpBwFtw7 8C<>4>}OJ&Ǧ; w2cwI$I ~qX+&ҌȊM`8WJfvs>΍$oFxca2Kf3'g"π ƘGTQy8*ᰄ'r p,6T9evts'r}-[?FN*AA9g2WaN] А4Dv0GUPSy1ũ\;ŒDܛy[2=wWfΗQsY֜ylI濲+@􊽯yng B~a?=Q}^I>2tm|Nc18=7oO+%PdWi,Z[daW;Ǵײ~G;_C[^%x#DljBh*6 *8h1qaL8\d029l6؎N8-Vfx} <ՂTk5a Rw[3Yq~ VAl`A8 u[Zp_] ;꯻;Ȼ7N/5}IofܵAMb7/`S f'|W82 Πos&a5wLYLQ9Iaͷ lMՌQY(c"Y!!"O].3 * OpGAg /~\pnwcnV|P&=Q 3)- kLSsoݧ߫{j>0w+"ߊD"lxW77~ ԂNQzYIj|57R㝓!A4;9~Yl̈́MB;݇SO_&[)=vs)`lƙI@,}T(M¿R6w}M ['8 ʸ[n {>n;s*DOr>5&;k-fվ}艸7+W}> -ݶ̇'$pl@4 c L8p"AH@ed3Y8KߟYz̙ǜL82+2T#Vtvubnyhi(p<+?@')βtډڣvNxS{<Ƒb{3=jY cw<Ǘ7vuU;rkgG 4T"/jB!zA3N-~UG-f^*cT aQpkGJM)X'wGQqQ!aj[5RTT?=Kȇ쁅7T3{n-qק̺dZO˻us[e 'Oz{8SREĸK*[)Y?Wd}(9zB5 y<%v'ax<v=AJ4TA5(fe0U=Rvc4OR-2eP7 ?05]d4"Ә.Dﱻ^w^kugh&} -{.LP]-뭺' XUfB]6Ťٱ.GSi5GH RrP4P,Nm_򒉱Sw&/46Gt-/\e3'=neI޼kbݛ''K/Y??HC`%dK#V-XtZՖ~EH2tn'&hD٨JcP-"2%l2 Iv#qI"h&D a <% 0^5+FHHDz"#HjIN UcGFHOdzʧzM"RLiVuk7lN;a/]mJLRG<^/h2b`6+ *׫Cf393-'XmY8`-Q Q,,nɱY8ŲB,O.a8ڹTpDKKmmƓ&]ysۂy-ғ}fVf~tpSQRj1m䯒66n*|Cqi-iBTOJM%2[Q)fIbP*riYjG #Ln3KD%wT͚2`$$AXMf|ŒDQ=& pc¦V;`gǿc!_bQ<-򰑗 j7pB &Χ!:8ԍtݮѻ38l /g-)zb)WbO@NxWhd)N :C5yJ ^g$;0m 81qGAȹspRl/Η#4h,QtSnbT,u.y!tvq{܁ L0}$)N `%a?E~$a朂Drj ]vu_pO3U[,֫P#9G1{Ir-y?x0;g﹵>㩵W5)i_04m>at'Ƕ'YZvСC7Zx?!EI<.n RX]ig$E 18caa/<y8N.(`9"D5d>zKX2.N7DG~2‚=^:*'II*+xc;?W<_]>yV;wIIxs) 1Z:z@y·`+ . _:eb%R21*;9z#nI%mnG%kI^!i/knm7U/%]j@}4CW1HPap\8!魴za)I%FGauw ʙ׊҄~G΀enA@dj}+E[; -p8z ^>==0aG ]MFfslDvhvsøZa6vKQI|F{]b6+ɑ #'G!7}>_ZFsN<^vv*;C!]~LRL)nb@Fq\f$\C.#L/'x8d]Ao.1?C@Vh5NW=(x0ɠ*D |YY7Kttϥ шˡ;pv\(EIJg=K⮻_ckO]N7.^`>mOF}Gο]~ͭkN^T󞉾/| # ը6K'd BYB}k\]nhg~(XUAe`9D|P57|joc:{:6b{QM'&$'t>^~!~]u]u ueQh "ZC9e"*[t䟑?1N㽵o\}#rq9. o{;v¦{"OG=q/cziTW \p/WkԨ^"UXq| `DS"T@ F&WŐr]i(s! CN]7X)cRn#(\L"H9"F#hZ3,[KrW[wNq= G81&d*!}洳` fc;-9f 2܁1bj| UqDwH^y2= [MtȳJѭKQʹ$쩈cŏpңOENjg-b?(.}h{bk>mU'# RU,f E1wڢbAw1chY ,Q}_jxÉfF݁z%SaɠqdLUXg"l)f\O< l'Ltkqv! EI9`N8~-q7`1^&ViX<,&oM擅cX$-wwKJ8+On wNӜ% ÑS"!sa a.UK2~1K+j.e$q!(w}ZJoğC SqF/;~]]a䋁ߤzL@?W "Q*.Ua :NSgYWc*" gN ^m1^j`){1u:_RszJq% ?#p~?AVN*4 [=Γr@l ?Yw/]8%2pycn|YnHl8y~8ag,GIE2;PUU jeS(}&τXQ\srPp$7'Ȇt"Or,LHm0ev%P`AfnuhHbmq9PbPG"ry>%tǵtryqwH;zSGc'c;=kU.1|EŔɋ{1z H1S] N/W@eBl uiǛ.u1n5)% dJ2z]{B_8}"rl"&8_&R#oo͝weմ]?rÜ񉯞 ٳ`A O1EB!+lvcw4s;_v͖qJ1'YrQ\)iΥt [p9Seȱ6.Adt:8ȅ1tB(mf2ѫ# hv.#^a5rV#7BDUtg,~Tq^W_ b9ұ8~vH?d;k@Bq$y+kov՟\zmY7,[:o-)Gمwdoun*A|ĪFGV05@M:NގI œj F17R|;o%[{dt txJ/ǥQ2T#9B4?SJR1(vf)S*8Lƣ~CxGO P5¾I U;m53 V*63>ZFPow|sȾ2<eQR q¤2MK>G'=Cn<6W?H"*J!%ϳV%<鹓P>}4Lfzǟ)l*z4{G_S> Ӆ3+'\쒘_iHȊGهdZ}`-}扶8+M L|'~. ڋvbRͅ>$IGJ4d19Y14s9vdϪE8mMKA١88x{ft[la_.ߦgUxLR]׾}K[{!_:}='D]AkNgByIs&̘|E8grnӕI:5檇}/n[Pu{U5sPJ2s) S7]%;m;C_^ٵ媍+/jB"ﯹui)|+hw9FéGQ=yOfg4^!hAD4r+)h6ى%/,A }9,pCZm~5~uFP9@rw܋~~P*Жț\ #dSFTom1_ȏ:J[^g󑘊c~㶹=g+iT`l)QO0gP6fOը)ohy=y6P66h^#|lb\i\QcuA;=٠[^F)gktF>kRm.pa5`Ѵ |mѹۡ0-me}NZ䞱ж66ޅ1%YS۠JEߥ<[^jt2lfSבxN6…3JQ_ Z+d{OvS[xn,7icPi.hoα/Qc%qzEXgn7p5mwcD:]コvSe$Ҁb5鸍ibdls3I'9ҸR<:z'ӡ6f7Gif'f/M8ƥ? kf֩ 0^j v&&VA+hߝa= i,/3 < WC-=*yI*Veb01m]S}qSN ȣr^Zol1ۦh,;f{z i&ZFw:ݖ;9{3sujw\ӘNw3ѫպ>~Fw!XӸQ.ηJ?dQz.v}䯓PbNiZՙGmb ̃mY[un6_ 5lWdѤ{}.z70:g[tOߑb86:/$[Ɲ"<1qz{vNQzqx2iCG<>q:~z4kwnQ5kS׏ b]Џl_ܨEϜ&CV{L_A}aa֣,uE΋5n]X٘_ǣkWQ{_bt/Ξh|2 i@:"3.fAU);ŨJǤpp1ʇD{Bhu'h[Η7v.lZؤ<,jnRvwB2]lmVz:(ۡߤ,xe+Z[-k{{M=MVMnihѺJ8:d֠kN]miX;+K!,ڨPu7jjk^tE)MkZzzV)-J/.^4*iʢJJC*i}3eX?I)nXҾmg) :VZ;Zz2-- †UbIތަ6J[w VV5iT4F4VC 4ut7)}m @ˀBKc]~H', j}(&e}Ko3cC[G*ڛ@v/L]؍ug+ P6h@zdTM݌}2Za}U_O/[jOokxNPE4u30li\Ұo+MeM˺&vD Pښw-llolI4vPf)M`1mM RНV:F[K+coz&TqH%È^'&{/Xm kjiz35AU-= t ڻi}OgC'(ޖ:0Eh`e7vNY~}vٍm9ͽm9m$h ϦfMPĺ̫^4rifWS+fϨB6sAE܊y&iQ3ukT&@(qk[ UdJGH LGAaMwSl57tz^D T@pMM tQvib(Lc@4+zah vԸ{FEcXgmʺ־a =!{g+֤ۙ[.PWWۙѾ VPf;Vw3޲%Z[Z`{mLYez0}+[[z<06PTDٯhʫs?f8jz4`tt3>8ֵ4WO@M`V]0qckam c_?,#y`aipOT'd2wҤx+EV7o݌!DMԫ{]}2M|;f/V*>*41k}7_^ߵ(w}}nq)vIJ~ wF{7ݻލ|nw#߽wF{7ݻލ|nw#߽ݻ3;Ǽ rM;ՙ7vhLfy~4}o|=7a@aM8[6Iw>g!kk>ܡ<NgŊZ/ײM1>59]Zn٧rsFH!q Ր#Nˆpi UҸC3fmy0s4#^:|`ƭмHf̯̀0a0N43ND-GAPydYpǃ#{fT?63~r%sϴjly@ߝ7 ?(0!x Ct~Bk[NSu WddfA/Ғ*|>̌&AOKg#0VN/f\⟔}ҟQOj/aI) tKi GIi@40AH\A6 `0@ ࢿI%4y,aT-. U KPUPsŲoჍj>0y_㰳 U- [1Z v)n=^kkg,6ڍpO-r+9:J+˿Q?C>qpǎ!_$Aq!hqừ. L Q X[u|>%}Ce!X@*1à x(fg3 !f`x O</f} 1ݢTVP iIFp(RR4x+Sp  JvdqC)QV`(]@P(N@ /|W,j63k[4`~27dՆMd8˼!y Ω1ei h$:%yw,Pm՛eMMFcR{%x$C%zW|-ֿAފrWO0|K=SQzQU8caUHIP=ZqnyCym DU'52/,)&ppzptpnphpbofbvmc68> ^ .  n Ǻ t=16SBb =գB?/ endstream endobj 24 0 obj 18264 endobj 25 0 obj <> endobj 26 0 obj <> stream x]n0 Um˺w% h-Y:Mӂm ,re \.U eX1rHGW19!VrgDGO%#3@}' K2 2)2GSn 2'2'dO\%?o?_ѹQOH,{%G+bOSm)]vsx8{?##ڻn\h@iNpB 3l&U| endstream endobj 27 0 obj <> endobj 28 0 obj <> stream xy|8~}yfٞ2YHH&@$@X%h$C2!d! * UVŭZZ۷X7-򖶈T;OBPo}y˹9{νwBg{WQZn[6 !l_שnw&5l_w!$ $r͆?^R3g*klX}WA aS @&;sXǣ( e$7! # )ȏVN^^(a#*Yh jAh+z qpL86~( B\xc|Jt%:~AJ~pe"PeD?_ۇ8,Hd̅vVKuW71D TP]%ד빷8m- B#978;p2 w#i oppy? D@N:W ,@­x~'3o⇄@xȃ|rt GwYlq~3" 21cn.w'__ʯ ,*cw~{3~(&Ȏ*A*C/@2|5ҁ{S%b 2LV[I;r7ZGwsN2 Zar|Ǐ8pH!,^Nb&~, mPc(@J=rx B3w³| G x3 G0A2,$a!fG]rL.ȍfq˸+C'w= ({'w;\si| Ͽ)\.4EaPxS8/SqI&H-um8Cϕڂxa߈OAB*F>,YwTŀ/f}s/D1EN*?CE&揣>[r)밗õ ~4hmy'd yC#}=i| ORM\B !<,|Atւ }!oim>>O/ ( Z6z06|Y#E*נHԥIOƢ?Kca,COkB3`|Ri*z%E02Ԁwg7`x+%~/nQ~;V3w@ Og"u6)aWx&H@0z&}u/B߉h ^@؇`TIrPA/8 z*t C:g6y9~8x#0n3H:=jZk['vk ix 5@ P58@N蝅R:fʄ?b'(1qH W2^X`Cȉ硒[SS.)-A}fMHXq ^0BYL{9 WW'K3aL+2mS8+Z't+d[3#S]Rl爂TNFD `7?T <>Nac mV چk&~[T"=& Z܇Ԃ`M/994g8g.$y?s?Օ4iR/vH"-Uoh;{EDđ< M\% "j0,5OdBˁPTZf&5z HQHд^N ^|Qr_>@f/Zu*P@[Ve*U[붆=+2kdٳmz0CGnMф'tLe>oYla+xo[-#T]Z/ SDed$C1zѱ*B=,g ,^?K aT?@iV`P U_B'8&JBMB^cyu#8d0v=-*k=S>gUl=~ߖ / y< +^?KBz<0T,$KrnIHTcj?|!W_`J *DFIR1gLD'cN/˼$c0$' :AU_=mK ljB%dEpu'43=[LZi[+眲 ʇ¸^?SI'I Wd\WXpV Ǐ9nU縤'HuBsh9 *: jA8x܊+wscjF>BV#?Yd9k]{6!j+CkˁbNRꀬH@\6(ffrJ] Jl?ޒ]`?m_}=W[,y!;t9Y^^6I>]]<3eVo *F́wN~d(.5nr3y\< *_ o%YEmcLYjp\(Kȅ75Ԛu>dURA*4[BbjMMG*:#R-(د*j^_?@:ѤBf!%TaHɹt.#I78PZ5BF߼dc\_R~,w98:5!k:T-l0;xr ]La_A*^[s*9⃇SCHm3Ckq΄ E.s@N 1$4aB"EIt:4G_l.9;*q3}%˫[g/WO4t˧[ Cn<ԫ۲S'~m/O^R(͊UgՁ7e;[sdt#6 :{\M5{KpP'IU2ixN\OyE|o֯KG՟כ8^dW|}1_e'Oկ2(vOt4B ::$8r 9LA q";`вO0U7dHm'Q'$ >X@5"LLMɤ@oE *E12񀨜a*H2xQ\;ers@~6>Q*5xmUAa%qF1v'We؞cL~bЛxV;`[Q _71if2SYR(y74+iZ?%}}k&dFT 9r :_[N͖ՊpjhC=В7"19Un5\ڳsN>8_* rjjQ{MkkPmIgYUfRbU1?yu{n_xojfPhdnzbL7;q#03V$ #=6}.r&o},ov+ EH VqϱR b" kˊbu5P>}D ,+&enY JBiu5W̸d>cM}*WTiсR#kZe(OߴGi9L2CK{tP<{Mscs&S%ũZTͶ 'k%f7bWc8Mb;T%ŒD=),T-pN(% /re8+H[֚+OuySu/Hl-\UP5QQ,CWej>T AadN@ ; k2 ^d&C@a/sӠ_Oaѩ v5'ZY˚7@%3mL7@,*ea;؆VL9+("s,0[K؟ob[]R—./?|a^pݭ3k6VVvP=za%V0O6Ź`PpGQwgj\M.=!ys}vnƈ$ٳ-V7g/8'I=~ o+HZuگ_0AC;i!jv("ew:$~3@)2Cu[8sҙ,r@8x9v?ܸ~v~:}Ϟz`LGzAkJ0A*ޔe#ʃQ/.ݐ p׭_Q%^O懵)}C&ۋ lqB&Lد._}RnKeTU+I%җ8j+@V|BX :hpb's>٧@c  |U0= 5d|CM2lFc2``DG&*^V H"e&I LBjM$YyzN?@ UO |?#xj1 pTp, jGbqF>+|e@=Z: njJRPl$hc@?;IM-(u٢pqJ]Xl&%[ն JO-LKmKIRS *) LSfް\Ê`;ЄLߋ jŎ^鑽*Y[8n恨9rn܊M&=m (h3YV8!$PkG80ڄ#jC8#P{<ӈQQ ?~װ0*(Н\f`T t5 (Wx 5QQQ222u^S):ѧ }3JOҧdy|+/xL~0ԧRJ٩襤O])u[껩:XP*->eVtv,~DL7B$A>rye_嘵xz9a_ur"~֞)h`-S쩠me}fk :]R0`$azC][PTkg_JG)Ək^{m- v1Eʞ$is?IpRfi.^}܌9ű3\X}uWGV]/>}34l)b/*Ku`0u[bXGŞ?'jfNrmʭ)qIa wD8;?pMz;O7Y癰jDL&D'$$ʜǓ0D*dSq8htYmL#}WӅұyY8tswcț?S VBX{Nѵ2i P9@t[jX,;a06Al.s_Mj7UxӔ)!jSJg$;>XO6MN*I6N|t7AўU`AaʚFu|Ω?}ëb?U%|*Lkל*g}ߌ7 rjP{㦕#C#v:5zUb=}:^#֌x;axd-'LBIΐ2n24}`C6БfdkFg6i t~0HrlN DzQ1:ڋK vIB.}5u߲Cb/݀CiׄlZٰ+kpX}f콇XϷ=uyczz0^+xeuP͝Ӿӱ#|YrT99ak2ϙfyŦ^Fij5-2!پqsƍYri`Xe4R4C K%%%Ylc1fdddJYz纼-M;ߟ?ԃp/1R!Jw]UWgߑMUOj(G7T7Xrcp\0IZ`+XE/XPfvŨdkޝBF/1 2&pGg g$5T*Itd]|eٟ$Œ,?ޟ{},&ڄ'dTe4ݓJ?hyP1c+rxFvj(\FW5p>9<+䂒s@q/O!TUV^ ՒҐz,99=9Qr s9|7æbAm,kki3Lu .AEFvQ܁t#az:ظꑫML͙?i\dZńMcc'O.Zx!8|cT=lLզ;Jg,̗k,׉<ˉ$vۉ{8YKF"usu 9~c@_P^!Ps=\m_prupu6QiV(toab-]8w2;qR~>[x)vEO |貎6n*[2KKmACNJe߻2c8[tC0%ߋ8֣[ސ L@ 7@äl N(Ɓ j0Y5Z*Ҹ4~f0\=?" zlu k#(j"4QPotbe[6ka03e_3<Bw%U3Ѕv)ɝLפx s:M7U)gRm$ X dcJs0@m6i{LgddQۈO.ڴ%0g;#(ۘȧ'_;5lVgVI3՛b|M/ A}mmɢW,'d$,t6Bzá$GD 1x]8a=fY0U |8ғ;;.3wW?yG&:bgpԋKRcq5Y:U{w=>IyNL4y2W5J쥮R-t[6 7[n>a:l?lo19DvG\L2i!Zl!̃tvPPo!KqKyQ`),m^-SAFԞ:xĶXlJM(4#lnFP23$g:G䳢|l-8 PEgX.ԧ-8bRl_j=%%d&1IrI`&7$ޅAL`d9.8i'vsQ`KAYu'ĔH[^?82I0?5mCw{L``_[ïٱTZj/'!SQrf,EזSuNwF_aZT-I}\x9 цt ΄ #YL4{p?`1FK_zœ?;\׎k7&EQoc*FHp] ]nVtm1;}SC-bkk-@u"ʇh#{xJ|:׊TseG@ يpt oDQߍ(|!~cSCgN͐ ^e%3@JIJ q:nt%oYyIIflIO@+/ތ]ߏƞxzR=9$G {fIY[i}گƾЉ;4+ mniRoyqǞKg?sv7~K;_bgb_=I! ċ%$KV%͐+%\{\9?ϊшdA1{ܪfu\[rO2Q w'&ɘ-z9/x}}}A?ZD[ƹ;w}~س~zGp^ygXk,,`|2jW+t/ ْ+ԽPN8pH'UD".}@ -KڞI:9,%H4@Xa)֙Bb4L!j  T080HGKzvkq)ۧhB@|:ZQx"wpO z}G$P g 1,ҩǦ~zȎNM. E*m HDDHB( D<9Ak[}^ڡ>u(뉵(qUQXҴ[}I ŏ3(0}4t+5v'~{>v*c5}eWd!X EDUK8h%}ΐvS_ͩn437drT\I*+-5%yK5-lMŮɹcffNs85M|)r;ǚn.f{wf;L7an~@fv"J\*rqc5gpJgAK8c<N耪GY~pdKKVmcFbc;TFO$|SuDW5쎐[po•0Svk%aK]Rd~V`z4;bV޾)rcUDg5>9p;؀}?珬*?|CokbjN-u7nߏw˕'@X @`^Xh U ,2{o>k'vzBum=E%t>OG)4r`R֟wO9UUf%41vղӹl[bw3 3V9zKU\m{6}܃g*|}InHY뿞Q˖.qo:2k+ wɶ'ƾ:?ǝOU^+4ڦ^. DY `ى92Ssyteg6ˮL= f]XP}e{|,ؗDUpͷY~~|O!+s_~mny92,**S̃c^ԉz0U* aqX''XfXo u[-ޛSE名BsŷY1&btܮ$9v;Á?lv"9d59^qP<*Ld;G,c|KYqx1̮Jl5_g}۴NCiKI~n̴.NZN/]?w]XwVϛyR&tЃܬ^v!R0?QJxx f)(ѫ8Q'##AnT "B:s u}@t 5}_vx^ X zm=Ai8{MЕPd7묯m [G\C'/>"Qnd>[_S9D|(NX i6Ww&bsJc>K?Re^sDgsH$Ltœ>SĵzLNݦAo" ;lj3oؤGW  6w;pn̦/6˜d"'"s0)$Ex,9Mo3A.(fʸ2q&7Sn~̌ C6yc2.!{N19X9WcJ)rAf3Yr7Zw 01h Yl|Ͽ#;Oѧ ؘ'@ 礳?gcAɓB|^`~bz3!$j!РKf˗,_u`Pi rp2DY{M_62/ 9\-Q,H/_9AodLIx~b$LnO7Uf͛qؼ_^+/q3 CЪ}YtGH'<t"*= F|DEASA5Ҕ}FB޴62m6?iM/[9zCز{:CL2@> O-)'\h@-|^*#=e3'Y՜8dŀb^6Kb_YaFbC/Wsr6b'&sR8ݮAq{`^I4A3eY'eE=fJ*?"t;3abez,k}Gr%%u|M ^͟YTs], sD1ҹLD_"} .HvD7̢$OStuVl{Ub*0"YsrtBlO՞r eW2sT*2LiN)8g oz.`pm0 !zxF =̬TMjgZ4>ފāW8+f6LUVdMO B>'Ida[fÙ[*+X=ҒW{Aod~kꨡ z;oT2X^έ:B :34@>i\sz`m#<@~O8H|ޫU Ն:f1݆AIdR]Z0$]4>;Vc k ~߰ꔄ;xH0WbWR= %C %q!Bx +TnmNp+tBdPwqt^E!C:D-f?; BD/Q);@m EbKG$C84HI4Ud$;H4L~I'?!JCEz1.=Կ Yb v,֗UQ?a[ʫɵVܷ匃WFF=V5 Oyރwa^>Ch~MJ&dslmz<:t0qj27` `bY' }_O\L4<Ȝ^^n)\ձFG t/]k@H*/Aנ#|#!\͐6=,%^oXKE/R)B~'>DP mlć) C 1C|'@&夑Ͻu_υUsRDΦ;!s^KziݦfӐ9üoWZ hkϲ=i7NwOgmۜ\2=~FT \V&AVTCZ[Y5q? ㄞ( 3i0bȁ4X@= G% ~Fu(@4XF[v /s lDil`3rl`k[h0X/`-, uo` n`JMe4&hmiOzz/R'VM2Eh; =/fv`܏1XtE :EHj0,Q`;`=I#'2寧T z `ӻK~ z_5ۣ_߯4|k5se* I\(-7`#K, gJ~nDy`+N I/i0<5;hr`OI;!ݑ5GJ.Z>D|^%|kLe N {?y4wL˿,*yh0@ Χ7i0'?ϱTi0? G`>W| )lLߠ4}3_`hڀP50PAO³51xjE-tjX%ZQ;(+@4XSHr֠26 D{Q| X *bSc g%a-:iG!? %/em4|FQFJMBKX-#.V ᫠\# }kxoqQZ4*YFYJvhk{+jEOoF iNU3|X{s=ndCyZ)&mܷ)Vh n"Lhn֫#F5˸܊VhrЛ1#}og9Q& zHB&,Ut2*ӭ@& 270 2z0lf5~7Aͬ0k^F"CG1aQM4Fm:4&F7̡.֚ZݫaSx7i4вD jwj$:JDZJ4 2fn;O{J٬a PiF&#$-zQH|]j5w.úcd,4w/Vk kgZOf0X+Yjΰ&64i74j'jÌW P Gְ2ml%a&F2Z#Egz3ͬ7T6is+w֌.HoV^kcQ"ٌ>LY*##ld0XhsD$NH̦M.hDn3H]ֳ hQ͒ #nLfhڠs(AN?ۘ 539ܷql넼I@;a1 %\ZP3@-C@˙ $8>n-t3Ije.hEWS GyJW*x_ҧCBxSٜ+ta ),b-'Im/迷]̰F wY?|a=-Mߨ3;9щthٽNӥ+FVD2ú{D;Ev?:ܨkxREFramiDWhij6Q]LFT|aFX٢ahuFM)C=hVh+ìGmQwxh2J K5Itt*>V3R}^X5hYrzQ}݌7GۡBV(PiM#Ikt7k5AĬjXՈ.,6ornkNDI{-_A}fv1?cQ7m]߹?\_fE5۬o1A k=xcѺ Tf (Y @( B)_EwGZB9! .oaM@% Ї?[+p^ר7.i G'EMeNkKk'$)mhkҶ~2-*) [tєeV /++ q5kѕMʂHG}]aj{45 uNb) M$A.WXΉַv6v](2KZ'EHs}/{GVF;:#%ڢtB pPQ56S- JdMG  ܺ=ִatRDQ XeA znuMc =Z + ]- 0 Ģ֖H3[# TBEHGte%1z(Bfsk{Dij@p{h}#ܢ@:( ttBst@aIjUwDhg#CskkŦ0t:RDN쎴tF#P Fu0=l,P<Q>FY֬onF- ]lDFSJkm%ma%[WCa}4``C4w7͕Ț6H2. 0+kJshᶶ>$R"a0͑5[ZGst #o6:cEDbԌW[aP# =|6uɘxB92|Mt֏I mkh%nAbgVL65uvM*(׬ 悦5͝o(hXGMH0ͪU9uѬysyU*]8]:cs]dқ􋚀T$<:EePAc^AE1면-hFbZZmkA;ISaȝ*SJO[*,ų!pPޥťJ鄒2̺9i@F4#:Y.D]'ڈ.V*mctm^^^wlݱw|wlݱw|wlݱw|wlݱw>6?ȹ„~3wNB@|5: ?w.Z K4L"e&c_S]kertoMJV>O+ D^/geKkoѹZ$RfeF]H٦Q؆eIwߤͿ]߿+<з|~q# oou}"uUCP/7 CP+w'Ǝ/:L~ oE <=ph71'h7Yl ھPz:setz 0\h Ob-*x5M\i%b]}D;]}ES\%aE, Q:㤾t9\*_6m:^n$R=PʝnyӣxH˦mS"" K:G/bok郊\ rAj.9!qwbwZ)}bESe(~;km[`brQ!< VkkB/"8 e kP׍ `t3 +0<@ s@; ~L{'b~̓@;ݞ|61d't/Ey¥1J2 NM8F.a rREޡm. LArZQȯix|j y9!ϑRN> }rU@x #}~\t} Hw]ES%Ua/Aዄt2H:!<@Jdk+y*9kf:3.I4'>U?O%O#q_O-A}f-|SJ2JnG&,ް>xTx[ީC0&:.zཛAuncu$4*Mh<}x{\R:邧G`F`16h6hcm.x(F`F`1::cuQ00aTF5`TF5èjf*`0TPC a0 0 aF!`F!(B(d `(0PC a(0a +`X0a +ð2tC1q8q88883@9 (G(C9 (G(e(G(ՆɈA@lg#<=PAAdLࡸ 0z0zaF/`2݀0vn0vn0v3킇bυ}T+y,܈>c CX=8 E7Tn`!N}饖.PYO+< ϋH zቓ5H]^EI+E'/^H(kwFxXD] vCgK"!vJK>~#;T+QE"7fKv)Om.UwI hm~NSk{>ϯv isyv(}ₖK;=BQ9 $ ^뙺^hQ,6K􊟭&v&\>kO(tA uUBqՂ CA4b Mi$4w%ॢ1Pyj੪΁Np`ƀoKKS,hhذPLP`D FE2>vJћʤFO9, sck%oxumO^Ԋ+ Ѳzk۩VxU[)5z-h /;޾RǭTp'\'f0+r+keE}R> endobj 31 0 obj <> stream x]͎0<lc"4?Rӎ8)R!i.&0^\a{%Sw:cmΫ cnIO]9cq[0*w%<ӺNKxQO6|㢊iTϱ[;k>C_9 |^yT/>[EV}K%s 1c(JD6lɲ^ /`G.3pMރ_1W;ZHW[7̼;a'=Bآفo-5+ӿuגO[p w8%{ѿƹt>$OwonopC>%no%O'L%$L} KO{0w@){%I n5jm܉M}m_i8{sC#.6znfTO endstream endobj 32 0 obj <> endobj 33 0 obj <> stream xԼy`T~}6f_d2 H yʢ. (EPРh] _SK).*mQъRBf~7_&y˼w߹9}W.jQ+5k%o;;лaWS>wyKW\l.[9w9Zsfʉе<\c|@ `l+W,ffˮ55u]5B6\d:vul.x]ۣJvˮUz:F/Y:g~-T؏0|H $+r{>  GE%xi,*Uݧo5 <ᬳs:ly(?a/ 7,g/Xv'x2>[#)4n_G$'Ijs 9=J47k+UpExJxVxM8& 2=hWeקYݐ;#۞3A %Z?> ۆ:.+x4pf^[ Z|?~2pfDY\2>9l&wv!8sr>;ps+\. w >9^KR>ŧU///;*.׉J)#.ޗA:v{y|[ vH "!yfscH*y o q;)VC<Sr Qx"ZHW3j/óBuv`Dឿi1yQ$7la*s"Ac7π^X:Fq݃gmB_'`T.+E~,7nGaN8/|Bx}=?@^DŽ |:Ԓ[V SySP?mןz*Aѽ9 r14E~IB; Ѵţ0"כl$3A5|^Fh"jm}]>t)p>׉jcn ҕ*SɲDi|s慱6%qnbƅ5m•ᰵ'w6N5FM3E{ W YЙGzWm7]6c;yB7zs1NQvs%F@fŠ%SLb q 8 0m6Ȃ6ehFs0O&$DlH@7g#&!JR958^J*"PShl{@$Xb`Cぷ3WqtXRhk0ގK#;Unj#Hgo2=Z8Hr;694a9Q&L9Qز>G^eO{ _2edϹݮA*R!L*I5 so*i*4KQ)6I$y2YZ"J%I1i&uJ%Q"GY q&@42W.R☥QJ"-li(n{ZZ?l6w׻jj̷ ɀ(Mj\u'fxtåU]s.O-s!6a쭛~6*Lyt A]-kH?8QhGT}YDY8&p^YYXp }9=͖tD&cS= rڒA-{-e0QTTA#zǬ~B>b<^܁ji {_-eٱ~ݎ7.fm˳p16}A#rG*Pl=H0CLR/N#9,os}'={[C%II:o /)\"!eF`2E##Syq}C3($R}B5%]Τitae].ui ^ zֽ`hX'6堜wQMCc\%+eJϤėH8b&AoLHt&!a&Xxa<9u2- Q04wQe2lUS9/nМ}polzgW칫?Ե+^M'݂!FoGuύgh<ۃ /PKbj6eǯc_20̬kՀ0@*h5,j2YԀNGLZT2'CGiX, o sa>'n`Ĕ!W *NVq һ*L)̚*[:o|O&: cF3̛iQEYtz+ᬬ\U97@-W}pɣL]s]>amCl?ȝ];owބo '?stbON(tj;S-ǻAQ^$3ۢVWY:SL7b$:34031i<@73 RB*}j$ c_3DY+ NY*e ?V>cS4ڇu8giK3ǁohoovI:Ibh/,֣I+HJf+h2S >\io?:Y12\> 8"`Uq8Oc"Cp7(l#B Әv̚u2pL"߄~>L@O0%eKՐ7鞿T__{{{ۄoi$Ϸڒ"`hQODoBzҩ!BC`pj0:02&'6qcYsy`8*Q0D3S2UO /"OuMMN+RrQ\ߢԵۢS*#H=}kPz`_I_@bB7PV\\V,)'H)x <;n%i7x. Xek%b<P5kz/]$EGjץ_ZٗoG<{yO-~vWw| igVg;pr7CB Ja{GrNoɼJ㫭# '#NIGA^joie(a4lM$4[HTqWWct8ݤbJF2 JmJ;H4&ңcL 1 Ը1_=o?,yW[{j'SކqvװG(Ќ|P,˒8`*z.2ݵ$36x%F},?OB'  VPFrqOEXPHcN#/@_4GSҧ> {6>5caଞńJʋKx-%,'b3舠^ e;\ c;Kk]t̯5΢}7kz DqADmztqt±yyytz\NSWU2 ]*?hp x)SE:)E*9D>-)k-Jg 'uJY/1䩞:C &|򽘆c n}jsHYl9`{0jUڃOpUwaER/|K_ ׇ Ȑyaq߻׼ޘɣs_|E<+?,J*ۂ4HjV7/"5/-+9~/w2-|](T:qz XS|/Rv|q <lj" E)WU5g%&b udG Z\h*Q;.4= ǁ!'Qy O#0_Öwiֳ JnpюuׯNЯ>AZطo Qmڢe]ǃ௉SU/ Oh6uKG܅k0X:XȐwϽG"Y̍ɎXjfή1_ u u` íu~ZIBELKV!'C@[Mc'E@\a!˟)$dqEl`,X vTrZ[:X@V6tN*6emg^ %0 D?Vtu6]n,* ՅB}ўj/wz ,6iS+L\ JgT1i*v~WFiHQa9HQ`I]ñSbqPch\hFh[@HtJBW> %C$ FX^z-LL|(61?ZӋ.+"EQf0ߑݿ<>ZIB'X۟P^!~/C1!?uwHe]ޅ+m'RGavxyemskϭ {u2J(K5p|?{q cWe V-#k_gʂW]tΰdkƞ$}N.-e5笚>mE,ɋ| ";i D֑b0߮Lqanlw.'\V]F(XtH5t&ʻT*]+7O六FGl|X~WTrbm.c@z}y7&\)%Z3 H[/xĈr T˩ag*v^:P;'0?.f{j4,(t9z!)U( *kUS\yAz^K>u`ެ. {3z]ыV;;8racΡSh8nmsrwyQ%X /WG9Ls\Q2^F}}zpyCk}20P'r]Qh\l9-2STԶPϴ3@h݌GY8w֓adUHJF1`.L`~^GQ"bA=cGMq!nJ9SEKu[ 1bnjI2L$PIg|)NI\= |޲,xEm޼(}9t/^0TэG<{5c#\T/}VSKQ 8vO*fŘ/w`;B'J|4^ Y6)E ȥĽԝŪW{E^`db NOUAFIG_7_wכF+o 7pEBeBlUJ:c*8:4ZK;c;iKfx%oC+h^6#vEX5*-KY4>THjs`#ދ!DkBe/:o  $4rg.\Jثj6">פ^ YYZ>.?6rW/:Gby63,[+ YmQ:4~_MFM X@kO&W1e`@w;R?;F)v֝Oک \W:q<̙s%F8'1.̜RܱuޥcJW]) 4jGY'haPtB-(~S4O\x`@z0ݦz A^c֗yb=zS_⩩ յ݂>MZ݁r|_+ߣCPhJPG&s!Lp+9죖;.TQ. ?xO~~scD'.t/όWNAitGͭ&1M>U%׎'0` hQ.Oba'dDJ|Ϡ+ཷC2U[*(4(%L*k  Q (KXgWOØk'X ha|4t4v>FB &f+ř3%{U:i֦}ДW=m%:~ތm;ߵn'c.7f,lBsXU9گ/7 +.eqonT/nY(oHI(_tnђ<808rAH|>=0=P^/0E:cy? ~~pX.Oi36GϵeMg]CCPA6*c+1+aGP`!7*|z8+GRaIDϕSCj#ىfc/x0o1y5a?L,=OOenP4Q*9.{lov?|zp%u-pj5vBq1?6.k>y+'Lؔ[F:=;iÉ| OysbM@ɬ:bE"n, Ջ48>T?y7|~g)vJ8sgxߦ&I߫ޫH:7s(5h~ #44b9(1i6Q"\Q$YQ(*4lo}Naj)8TE'quIxR8bC>s 8UBDc]G87v4KULQR;pEK/AZw)Z -2ǏRO+Dtl/aE!;EVT9ze6}4^XB%ĊS?k4N_8؉f}UɝށoٯH~^skNf x8XoAFy)RNN![Df鱼OA2b'} 6 :$Vѷ֤ IW~#.rc>ϥU+#Oצ9&9M_PLvV{ NK/>.>/!uh65 ljf4 X؁N,/žZ!Ql ziUW$k$!9-ĸ A GP}FP%,(ᵃ՝Qz:(N8,A۰D<&s`Mb3QNG%p'ۗnt[+//"XW-N߳>~u-9:s_q T/h/P}diN/ Q3h'5t3rV^Ynϓ_Ȋ' sJ_FǀN,ӣpzit,m e7E'ߣs007o7yUZd FA3HtQps2.ppOi3FG QzٮDX3HT=Mqɯ7]G]/[{G']x˾G1O}(: ^ql)9؋>lg/1L9 ([{94dzO?ȷk/Tw5=z5bgsDםc.[ ڗomfa=g◲]]qxoޝ]{4&!dYШB6X<3,23123+\Z +ًi#}Y@>SĉyjCFy 9D:鴜V'_̒d9Yٝ$s$ӟYڼt|; ՒFtt~h˧c+LJQ񙙱07Aq`W~|*YUL~%+޻-tş[m˯z4C>Xښ~=x7Wrd'ٍ>BR! <w Diu97{<]7Y%Z6N4*u ,Ǡ1s\VK{F3aZ}ǹcXpM!FcAN{b++ļޔ+Δl8${&MSp :ZuKלsHks~r1:Csq@ZKS8C qE d"/IU"MtmEZłmrj-~_ٯw 3qV2RpY4#APaRO%[I3K|o \/1 {Ma'm]錡wͅ6<߈#ݥ[؁[)5Kb:ipCI!{V裭Z޿d/.4d: dvQ-Ƅf^ @ 6bPߐZz@xڐF !ڳ"tgT>zx|-0s$yp~ hIfCA jNWy<Ͻy]9W^dh02ދVQaNHwN}4cO ]t$"MA.6f NduR-[<apojYT;"CK7 :q"Љ(d#vE0@}ŢPQ66:N}ĶnQu r W8c5(Wc Ǯc~V?c@D_,vC3; Y>zUt'-ie{W WP2|L}WPh5^_)hKkxN^uqJh,LWX5](b-QqЌ}pN/{UYfzӊ;Hk:߱pYdގe~ot4Èe'C ni]?jij tu==kQ8o/\rv~h['>({K-smcA-܂QZ1׹# ;tU1ml]/LDzwz؂N?f{>-&ZcY%׆vWمO_/=2n.MJ^l/GrDEs:V"j]fɁT @4uabL +f:+\Rd)P&O@.b؃y1 ΰj{?'F@88bJ[miHiz;?;+7e;7|=}>W4}OfO~ÿzW>GAo[N5H yj-?xYqq+y]fOԟ7tR~{v{z8;~=y/}OezO쿳p-ϲCEHtX*9\46AKv.*u\Vt;9a"+ Q5;̇>ͼSl-M2NNZ̒,4*7Vޕ'%ǖ<[ +31鼶_9]r;j XZ'[:CC2(ОbvޞIXFQdqONeya/lG){ID7H}'*Tb~±ސ5"@82&Y\z/[[~{Rph"Y+@ J"wkpݭnKBC=g,z k{!X#k \bbLy1&4ӈS;]4;> Ͱ8AA;03य़NIeGp1rmwtozGUT쮫wcްwA/mav Dg+C ,-;U{w?#wNn*ahcsYP}wF~'H_KR l?t}Ǽpp[m_.GMy*w]; ҹo(]=GӛSC7?wQ<V㫅WԭA! 8;"=&"fc29G횇 ZϿ"f1ޠx*̆!Hj?,{k] 2dghb.{IoG%2wHYV%X(vpSɲǁ] wƤPaq{E&%YZˋKLSCY7t l_C]3w鄣(ƔJRrO%A(NONzbl 8j`.X+8*`t-U x@%=(H} JiMߞ=-;?nԶ鵫cru&CKC}^.i3a [ekY]d 6<4!@mD[dLb[@~YU i]thx!-&GEAKҹlXl/zNy`F[Tq{vG[ =^NMlL1 R(1~$i0=e'H7|w\kUvik,K-m%4;pNrI[tG\mP''lO)○z~3fkV9Nx~u`ƻ_z%[q9^A*L&Fn@iG[K7Q@{#Jg89wT~NOP9`:$]k@HK*f~ydfs_V%>|7_] NT>:).^2lDDI^tQGDHT(/ m"Y RFPH2<9Y^=-6%19yXU>8WW-K6j77ݘӸy8zSH*zBn2rsD~wqy'@]W[).sLi=B2@}Qz'&GȒsDɲR' őa8|ԏz3cx7ihxsL?}H ]?:a?zͺ}^ta%3uι◳qmk.WSbȮWXvWT7˳$kYXD=NgP*teQ+Z[/<=nڍ7p?\w+\XyE)O{_Wq$zsHsydْ, ˒e{dK6F5=Ich䙑0+@`!$W6 KͮYl !NXؐ|͆ z=3IvÖ^wuwuUuzgsOGgflVvqj1ZVOzWV3/t_|7x5U2M|O^n~V!2Ǔ- !]  \ ?y|OO'?s]pGRs~4<#~Vnn)\~ԯ5ċK?ZevS.l~$sZN&U%=XZ qJfjyKj4(Sh[g5bC6ES)QoYdm0T%A>dOnjģ x{'&N;lZftۓ6Z~Y,k'P%  z#Z/5df%:^L%zZHHt <_z봃?NYZEe4чu}çt?D80XpMb7d{22 TtrV0̰\;9//99i[inB>Ce+VCj+5<4*"F%SX. V2 f-d]sE¶m97zpNo!iиz㽦oKoߴc/H7awyqZ^6xxR˫tc9L[N tg :zJ}Y^΁'z_phbzcG+Ks=_cSoONNxgƙ(t3ު8j9<C'޶+7w_6C~3×\]:Ǔ;lry)/gq23&U?/wH3#4iKg+6o.̝o\pWq[9}=wx*Σ#xoUffJ|ft+&QST]7yswL×ܸ֕_[o|po>;}p|gnך?>h-]ah>1i=ln<wc?W^k5ZLh,:LrŮ 2wN(qA|W鞸 XiM+*- lպ1w䇚m#؏ ھܻtdڥ~N'!=+Ómйn$cXOQ&xhqރl%/O:x5獗}UEtx_t5XnN)Y)Օ%mdc= Y'?.ѝt'J>Ҩ0ņ##嗊Lm^[g浮kns=z³gBGc0YfF Y8ddQAvQQ\TrA.+ 9s0K6KM7 iW ~^fn-[pczӧuR^w;sm~(/y1x_z'~|c>rk`>XJԿp݊??— un^ \5}ؤ;2]VmeM|ͪ@VY-feg2'lVdC,dȖ$P*sUSYzw̡ke;%~fNŰ Uv235 ҭcVfk{`C[O*?֔4.m}/[F2>Q'gʀl!-1k;ץƿP5q?55r2ހZ&Ÿ^%ѮGC\*3W9ye5_)W96Mj^w|;  T/x\a79g9\n_ `HR¥l%.!- QtSUEmRM nQO7Hfe/A]RfIOFYgP(JmahO;_g rn":WO-R6@An˸7lr3sʤG[&:'濹['ر-s>h//ʙYBgk{5[\Z®vnq]v+k ƿ +rj fC5fNC7'aH 9-%3.Q{=bBG Y69#neg\1s+\N[sdw})ڞ{A=9f6{r\0Vl2dwtؘ,tnCڦ/].'L Mf~ 6pszZWq~Arx.=1Q?}_Mb8ܟ<Ħ;ШШ]7Lմ^s-]|Ȅ1Tcۓsi~>`uE>81wdGɗ ?]lݻnR\~w|\擠Yurqejͺt~b?}l-3ܡ1Az~M=ήNA5x 򏍹r1]|(dl_-fb%h_-0THz.`dL?.5aS ì&M#&i\_:c8}%Z߁'+F a瑙MQn5Af?/jOO9Q^gyOّ5#fqd8jMg1I7ͯ#*7\@s+ zyVvޟ]b~ԁ?ʐQoNO3979&)}qMD>WדKd:~;.+W:'375ߘtkيsW>Q}l1v+ů/[!0㇦-KuGF\?z9/={~ooʙͪ׳W->ZKG,0V,TS\߼}ŕUV5R}]߯i_Uk̷IhJm9X oG%[[$WG,T\l2!p`7~'̾"}Mq[Vaz[6%7 <36`8w: ; cU%MXfs pp|Y2r| p3kq|"pp.z + ^xnkN2o;p(u[P#y H%Dc˄ ܌:{]#? t~G#8(*C tTXࠣAG8AG]#e@ࠣr-Xқb]JN"c2Nx!Ҕi@2/^+Mu!y26".v"n{ 66ʺXWأm503H*z(nCD@HWLfNU)bl EkgW B E xHP _ T1%tCax]m4J<0x jS}j !6 QrOR)րO? :!e0.kBF!$AlxFuAa)|TpA]$c:rE)RJ̭"@ҬC!EC0SӬRj5nݡea˿Fh&BܠmmKw)>"y#QEITOJm;aٶB6p 6NvH'֑w'DtFH#v-׸|4NV?T-eQDLmHb'9NO6~3[%y k ſJVRjKa"Tzd+SK$hi +_8J omPhȚ5%MBiFf=rR;2Mx4zt?ߐ3MwS.jO.JֽWH+39II-NMth]/&d+DrI # Z`B3}"ijuBd߆X(5,}g!~v]b1}Υ⨟$3?G犰ži}[\I:IҡiHlyn:6ncK PI 鿗9}ӔQf$q̿'U=&U H(mj.91G346|/HZ;O9NUtqh/͍՟~2ĻfqQVzk%v 5v*>%6* ŧQuuU*NE  Lv=CӃT9 ucv!Y {@|. Cec`bZT"ڗP#[lH@ PҩC}sM.A 2J@$+@,jC(z@PA5Q(+=JHdSPF;15v PɰĠڗ@d 6T{XtD0ApP{jX%^H uTxb(NZjKQcPQĢm@A;C(̕5*ݡ*0C P*/B!C(,E*QC -<"07!Q\2"i{ف _B!GT"vU)"#H;pmV yg( aO5 8fh$JU$ UUah' WE}Z `+1L0!T$k׵^zESuku++WhYEiZeMڶ KĚuB $ы41 2ֹcH` Zșڑf`d_h~}@莩*Zbz`lF2q3hhN*(NEI`rL*vDB*NՀv $ k`3 -jZJISH%FkS@,dzJeSPP'syx AsabY tv&*c#ɖZyLCV !h7)#FC=X䥉; x-䱺+]9 q*5 8wBR#hR3ťlQLu .-J ڽ $`&֕+uͫ67B`-S^VY}3Z6F|Q;W(_цx a!Mqi/8iݧ;;QCú_Zҿ.-_ZҿiIҒ%KK/-_ZҿiIҒ%sx/Ҩ Ъg& [K??+fjGC:F\OeS7Mty yXN.B78K1~] Np =mqv_s74Zpr/a-5ǚruUK3;Ig!~kl恣:=:IAީc:>iHSb^##t?̇U>|=7|a#|b<'|8·}| K3GW/ &lW/YZcgDgYτfWD,8߃9˴ʆh Hxp@ :ft2vp8p` Գ;ɵ[ `' gEOcUu$Y7S(rT8.Y3X.Op9e8x?2d&f"{G}GM9̣K_|+ѯeE- 죾<S=_K-e\G?=}6KU2<VP"'Fo{=zO{P[D#O~worȯCO{6jTaBfˋben֙jLsM3M^ S)[v9SY^d&g <]mtgԣ'!+iM$.K 6kZ7.#ǂCqnj눡x9qֶ#*ZMSF*ZGLjAο#ҭ㜵mStSk wBnj{;s]^Z_|gprߺqc3Gj:rFeۖCc~-z[[6`nis{{8LtL:a 1Ehtit%ftf3+!g4=h`I4ȶm9ͯ6./n)4Z_[wNYʪ]cfX֪Da*,˪òVWQYl|2[޾bIV ™sKxt__x&$}V|$5k(hS v~r@x9H %Ԭ?J 5"Y eh'kudU[4 tVi!fO+!u!5b,/@!h~v݈Mm+u-aC*<̃G07  9$$8RPJ& endstream endobj 34 0 obj 27045 endobj 35 0 obj <> endobj 36 0 obj <> stream x]ˎ0<|f)E/j@ M9dEs|;vqXa~Qa샿Myua̴Q-Jk;gy{|=im C0^ӯ1^~\T59ګe󡏷+x^T/>[EV}^]r}!XZl7ؑ d\fM ~ZHp)#K7 9]S'8_?RCjNR_5kY "Mu r0/1߮ɿӿ³[o 7CZ֥%ހuoqK,+̵ww![KFj'/_̥A%_;qR2N ]GF8?ٺ?r)Ox.GMv#+Γ?ǀ!#@K4c|~a endstream endobj 37 0 obj <> endobj 38 0 obj <> stream xSMOQ=oURA7dj1aa-DtM;54&ƽ+5#1,tAhظt#t{ع njـWoj >> endobj 41 0 obj <> stream x]j >,o; Y}ThT&fm 9pCYR#f}p["L Z|SIB2;[usZ7L\NrH>,pG24sLz6+JǶǙTd, 4˥?O]i8rRՍ*FeBO3;{uJwU)B ,o endstream endobj 42 0 obj <> endobj 43 0 obj <> stream xԽwE?^U3ӓ{bOγv6¦ ,Jp% S̘0܉ò.wb<@=u}vTl{T'|]v@ .dYD^,9]Pއ3讜m,B3R}x‹| dnDgϛ}]r3|GpOcjً]}@ƅζ\]z/}ђd P;{<ӏ[x(Gh2z|ytyTm6B7}XMaUj FDfw8%P8T:S":j4>"7>f!T[|x `zO#MdG:p 3Mb; h= mEϣ]C9، .ޣB};; 'hF]3abߡߨ#EXX~"_A6xOǽaȍ( uB~pG@[񩨞\ON$h ~q;ZH??L%wh C m(DJl= s!g"1h_tƫP[T1>ҋ72ǣ0::a^Ѭ!<2b pf#I< G|Y㻘4c1FlHV0U^f xBٽ+iy9XVgLO%0:ǃt[ t<x"[ cB<~Rp`[p#OW?ڷ]^͞(y ݍ^mV$@QPtkC<RLt.{zm 5t8Lڗ]]2 yɵer>F322>acQM:%?w}]r./|]xH.oUD_[GL[TWUVd3T2QE#P0y=ntmV(fѠi9Z2YجN6> gC! :4>YJ=ey1=bOy'1:tBQi^c;{, 0H'xu@sĩzqw!9If#/MGV8}V(ybP:[F='N>50zլ؎|Tx~XiiʸID܌rδ2FORi14]0_]8@RJ9`ǁmqۨƜVA؊:u,@C7w6! a?t RodwJ"pN!)pizz{IJwĉQK%NQj ֞~K~RS*ؔ4RuXVvX/*7z'xgz{U^iN% ۰9qȵ^H S.q ò|dӣ=^'CiC)w!' cʭH,Ij {6924|6a?܍)5mvNo|-ϧd^3yg𡁳ڨ&nFsMuw.hGʅU>E|",uOl4i-&unJZ%s IP 4ט!JfZ l\,݅xk3\6B!I&8* j+THBB` iP:|Ejv?].)?̖"X?K 3|nңr&(:xXUpNh׀e<wXbsU6 4$Fs49Tg3&_@mnqx@dȋȈcLh6lQ?£"1P Ek+|5ȆjȴqV:Un ej_vZ Ɓ t4@u r0D ?܉q"7lE 6|_ࢌA9w,tV&ظԒe; .?FENWv4}`:+|Xh o}pz:p4 \bN r pF 8Z8PwT#Q{q_]~1JqBe&Ԫ4FbfΔnjp-ɝUʷMQP6 [)o*uDrRU6Ƭ5Lp.!' ';xˋ4A)hfkO#)NBp(Wo܂OLwO2.E6+ @ؠx\o0]@0S\/I[營NYDُu $$;^]4B(W&6s珞w?^a~/6֝*fW͒ Ub`uX7P>|0M^fib:}MJm#OɲD(1l|, &jRi؂&^6ZY 0cά9!WYs-"|sx]@X}7Jv q26  zaذ!(IL_Iilb좧_Nc[m vƋc~`+$d HuqoCSfΞۦsY$%욺!_CECْU䁞Gk-D< MCG=xoY^6kKO͗#X4R[vUvbۚ#Wnn֟j^?~A%7\W]Ã.Ɔ-~2K%±J4460TSUfk&C 545تƹLw;dO6D )Â|3}}5rr!a ʠdYj-N4UècET/C^D>Ԏ PeŢYU_7R xG a~\D U{ӏF?v~d!( [4Askl (|FjQ7z_ӊƚ Z7 VHꡫ@Q( DonYi2s)QfYv.R{Q"E[\F-BhJ]?i T\Ԩ3y *М]~IW=iϚ'(f.5뇥res\'|mKFf5g7.\Ns A*1ȃɐT%$iL=PjjvJ2=6[üLmO{Fx&OP3*``S;}Ehr d` ,nlGTG'awv hFD=rzaT׼W/yd;[`\(̳lA2zDљ9Xi4\'+,nRvA 2Yޡޥާ>VgVk 2"%ގ셃Z8mϐlJO /Pf Beʻ[4-f_ DCRLC,B=MVl@8 :P;G˜8a+a Y)ޗvΗeʧ}J?,}{AJ.;SǑyRwqLf՜fq?&7̈́ ,!>@dm6FٜRHLd}>"V^nȄMct&^BE)GI`4 h172 U5ԫ6\ŗ(+L2 `uBv!٠!w4/߲|~EB8 ڣyĩ"! .NF";::ۋY"G[,ǪM|͚P?C=> :E'_1S1˿̒]|ڨo } p+3֫?W2"7Dp7Iv"fD f1+,yJNT0C(;ũQ5Bn2yF8d<̼qH@6TYG@ͺz'ˆC%T툐7qTp9=K"}ې 1*pRA* &1$,tT_9\KB̗O0jD]I6 jiݲMlsZ6(2{d-o0-*hJE\iQ#H g=TZ vr#YB<#K@}S]MWQa ~܁l疡JQ5uufsԧ俵j͒؟6` VYo>c0(3iVC΢@}eE(r'S"mhs/U4j$$]x[ve-@j /d+iIkLd['~2d9PyL~SH\<"*q16tJT&4?n* &(JI9sJ.$R{^wx,%cZoΠ1L,$DdR]2N2ʰYA%Hb $TV^+P*C_T!EjG@' e qGC"!qZ4[F(AX}Ab%/eKP0[~zxA_;)8.^@9젾bS Zucb'^Umv@iQ}rkR*v ZSβa_mw?\֐ tݘЭ,{a4*k5Du'mT]G}}_5[>*0.:.>%_`^ ͏^'@ru||7M'z8x0>'(37;e+KR!zD8:siЪT6D/U &ߚ`@ 51 @X˼x:m1k'hgjҪ\yz ;»lXI>ʉ BP-e* vA@v8v % մ1cv* vpZ5&stHF:A/Sq.9m?¸}{O>{+߼7޸7kw+ueQ#lxco{56H.coE8y~p~CI tGGZ=aح_GP{=@fPZ^1YAM(3 T oR&15uZqeyo"Lc3&@<oՆ>1 *8:ɋ˵74KOeh{iw& v+N4D!BB x 89ezjsOcZ%c 8NcRy|ޏИ_Np}/A˧Raۗ ꌹfVƛq J xX$T4M1E#1$cZ &POt7nӑjŐ;&mu}n{1W7xrb(xEU >}`fjH F6% ߂-[>Ycw8,WH/v~PmDZrʀ@KE$vz=~0Ae Xˑ._*BAQT (^[*sjjQMm:W9owswOݛy?Bvֽ\ JkP^'."\w?mmKAW]PBB1U&sDBmMjc$󉄝51Zy4񟦛R1̰  T|b@F+r UL~ pIʨ \VAaSLxnMi.W V9rB v*mVC mFl(; \(GYuCQ:2};giq _/~+VE0ibq}G1>(OPyXRÞD2L\ׂRt kMYhC0'!! RPVZV(.#L2r3Q LУR[5VkHV anѹ*~vKN6®`| zJ]\VDRUԚ̚1\ V*O3c _V< ݛ?{6߇s]{臼ᗕr)gD}{ˮ]ܲ{7©WEGZGôc sqikGOux?Ik7nt={.`7>뤡3}zupC`A)Jw$y@o5 *Qlq$ohAd']Ƈ菺s)]Rw]w8ָnY@`PWKRPkzSQo`luŘ$a䋊HKD"NQ{\ T~"*ES6Iǚ#^lZ3$zs E%YE^Pz~X75GJB :J'v\ض }{x_~&^wY&|Q?P;}pY: ,3oƷux=ěACͪ-W4j4.Np ~+Zΐp:!+#68/B|qPa8-.@dee#VI{IE^YQ V*++{PQ¯:?\#]nFu$?vi7MK2 9&AZ 9431M.\zV u'[4Ϛ6Z74鰄[E.-_U~Oc /WWy%W{W4[{kq$j6j6]Kcҧkː46H KL:`0Y^ =`D@Κ8l N |*#7]*jz|~^5Nۯ(bb*i:mp1F8J3i ?T8IʹrG)8=}Rxߏ(!aR̋bY0S}c>~+l hy4޶NߟY/1o jЛrT6V2\Qe؜z)'s$3FVkQ%& Ʋ좑'^ĀTq.ԍu(]sv٘ɶ%6&ߊ*)~rs'1iRZqFm(Tz% ًzGvlLd 6Oܪ)A CT 9̹K@XTuC0QqPUfV82SchJOcO2_CN}4ܧ׿Ńݻٳ=̜3N[-3yu?b}-w!^4 Pj#屯IXp ũdB;m9&p $.WQ1sPg+un̏5˚i.4ׁRgFiQVO=0)$s Pb59ӊ5ehxm}+4J<'!P,JM exX$-#PkAc.F=$ 90$QK1ZU֎ =&OmF!c-c|CT ~ +};/ h\:qR'9dJdt&N l.΅'/[v2|vASKy_x]N.;yˊ*@<֧Tn#d1@i,{Kk?t<@R\oCicр㏈N{42;VH(iunu[0k&{nVk\{0cK}LRk u}f\p e/'-|vF+᳗֟.G*c7/gꕈK/_N4 42  +ͦM6ù,v\7~i 鋁IvMd_@3eAlyXJmx r.QvXi97RX=9C~HSUˮi\49nԦ=4*2dsϹ9W(? ]a(q]`t\R۱I-z=0b|9*Xk; 3a<4σI{`7j C'*ɢjw-fjVkYg 0K O eG&D9bkEΫp:\4\z]{Q# \,'jHiad/^K!W:>~7jPiZފto%Ag%',Y&dMYnX%ڔhY`]֟iaKE?&Mnxtx͂Ȃ놰: Qp({6-<~2M=j⫨SSQQ]^Rt;lIhqiD" h$Xs"Z( 6,Uƥ?XC!I u!a;ۆס(Ԭ!Y5L (u@8[]%6Pk>ALQZ٢;m"^ɖZ {6[,tkKUܑQ.kY)}^Ε/?3Z/uט~Rطi,X yi1.|e4쮦phPЫMQ&п/Rxe9P6(| ٗx^JFjwg+!' jЦ=.6?QQWU(Xsk=JnlwzAq%$^}4U\(etYY*XhXƫsY#eq8+P ވ` ,B f¾)..(a !|B*[ DZ#MG<=}գE+΢41*~c %֥%]D33r g+wH;a)1Z_:%)) b_ld+a+ŧ%=-ŸӢ=^)m [|%7[via 6/g@ṫDuʲf"F=߼pC`Ioϟq_Wu+w~eO?.{i)f1S<6ȞvS7\ՠ:=ܖAu[QS6gܙW2+V. ,K_!`]|1mhEҷߐ~-zp^ Gy@2T2鰿$I9I[N}3%Z-KPnWG=(cݸ}rM^\B-.;t Ć誥Yy$O\8dB iQxv w*8$0uPUv{!Ǻ AA Tء(G$V89u>+nimɽM8&OJQϐ G}Ixn=qqm[qj ?DzQMGGRDCUb~6a4\, Y,>ttq<8MѸ]*W> vqfֳlq]]"~@qN%oאX'̲} gl*L['kVU*Oo [eX_{jG^Wڒ$e]8100!{ڂ_z >?ߍqЄ-Gsr[15v#y׊Y^oS`UMI  8iHL̮.t)sx;,"Eܶz\Hl&l0ͬ:Gˢ(VѤ.Rp9S8$FED2,9%@E.fjnW+jt(bXw.x|B{s7*9rv)22rűZ?sˮaH:!^ZyWK2EiOvD!M.3L~r\dvYn(>k; uZʶ)skL:wmS1ek2{1nʺA?]AbB&&nH "M0oYH |'V:R5u}G}@ʂ0vCc~ l q sOU fK>"_Ta|U׭)^Ҁ9Ա,mD>"^7,q}ŃUGG)j\KNU?C>Qգ7opUz 3mW㪵|Xm$eQ1j:YKt:;$ ,۟r>&qZ&۝[uіѶ'II"p7ZlÜ'ENqnK㖸 Yb6H㈲Z!cLQ Ѕ֨Fj):mK;W;}!byC -vdu؝vo&ZN衯h.?P h-9j_)?( |-`->H0 H-RNhZ IIK36Abү=Jٴo%4EఋB7QCdѵ]fM{osc̓}K'Ґl-mB6Y;@QӦHū%}*JNnSϣǞ yHO,1ʪ?g{55*NAܿW;F%e+')s}s"|= !iS4ڴJh FQxgg@6bKGjymwd[BSp-o|ud9 ޷ 蟲D9aT T|)_ ɦc)tN7PCJt:hHHeYZ㒖gXX.\k:ݲ%ckEU&IH 8xq쒊M \1`m>!NcE>YRf˸&T9&cJ-bZ0y!MVUIkt~n@"&#o*T gBM&l*>_g0th:'YV,7uM8` QfC1]DFH)UFA1.&> [qW"J)|@4]hP w^\mkKź.\ F1)%7{z#,=w;}'k?/dDΚE/OW=~rp)Wcaz& #'DN֟˃5ʙ{%!  B76 6&6$8 JR$aӭͫmb7Nw7<c;ƸmҴ4_6M9u~Im{0bf=s̙3gܹZ36Yпm9?6On MwJK6j? UӡVsmh&r<!,Oe7ؚқ4y X /06VSM~ jjE9Zۃ^ VhPKNgî;PÝo-kʼn{DKbe9=?Pj|.L_HZ1~kN /*a5]gn`S6Mv4o;w_נzN h冽 .C]^][]_zoMY{{wwVu UW﨑 u57Z^S{c5\}XGҫZ,ߛ.>BX(#.҅]c* 9{bE.bzDe1_ /juBFfkj-DVO2[qYiSXH,ҊGC}B]MS@GjH;OVj-ZϡBnW=?Ej|>B]a$:qɨ$.̣fG<#%7sq;wF&SԂ0<#ob1#|n˕KW{%B6k9^L4Ko‚\WC\[ WFbP_wAW|`|Ϝ<_*bw5;el0(@l?a7nZ-T ;hSyA3weS4b2fxi&*| WfA$WK!y-5&o5c_o6sjxpA8_=ޞpeF}cc|3LƷ/!KO*.d\%oX3:6]xD̘N#琼[_JN]&]ή2լ4U-ҝRf)Uu6]e*R/NO[ ZM9GL?6%V_m=Rt=,}eq>X^RQꞯ|j^U}AXZG?hFkF]7} ?~McM,WNǮx* k%GB !ӷ*T_T,~S Jp*霙{I3PP D# V?%Y/sˢ-|I1P$C K"2 Je*$8e)TUU V N?Hp:Ve%8թ_)Vm`%/$8 Ud$29Fr4 Nax+S`F(gCi$H`#mHߗ`#y :Ars$(C顎r,PGC`#o$r\1-={AMRID,L_"nMIJkM7s[c;ldihDLq[MQ1,]e7_ż~LLseih= oD!4.&Q"S B ^@"MpyP#*WA [ (c( 0a G&( Wd䫮jT$T2%F & n^pYJ-nlM-2S8+k%Ř T)z_S&#JRQp9Ai̔{d'ZR~V\X1I a墖 KM-臙LS4KԦ:mrt1 L!I T5B׸Ϭv໤Yi@7g 1kc &0˛Z`#Ib-Jbd0/>%UX^xi%N"sHc[9$i\\%43 TCj&VҜWA~W#Q Vq ~ h+~ɂ1Y6)f)"& mln >u{o# %Jg؊?0R{^7>_M^@s'4j2˴8L@'=cEֆ"P &H88TA1APpbsy+]T_0HFbQE d$ D&aj0:GW%E-D4JXi$ [7HW/XG ,hL$0AHOD XE+BCxlz}h&]B,"mB40:Q't*z$!I\) d8⟚ 7 'HG49JS V!( CG!GA2 2 bCcd_NƩ cJ'a VĐmQ a"&$ 'cLʊEI?HL@oL` &DžiX,^vOMMUK bAxl?.ǣC:& 9SM A ,ɦΎεMԹ}v[}ce2g,eEcAap$zqe NFZCӡIr(Y0]G)?  F*B1nIQm/Z5ؑ@0@*<8MF"\P ШH2n6kV}RJqvU8@u?8 ѨKN]AMh$50?X犒D,01.N"?(-[.T00訽EEbɐ!h:` :F^䇪 OS%44#ΑDI!ʲam$2! "͈c0aS:I!}Xcn duL 旤6[&b!18#VQm[}E 5બLKJzR_WXۨLNHܒxRb)!AJvnWlЊme0Ea''+9pg[7xva0ôn?+kJϩt_:o0 S w,|6`}O=g~7ؽ 18H0I*[И-nQpMM|' 7Xx v]6v mk;,0\CQ|2(f3L?{goZx/x{5if|+cP5ANM&ӄR& _*ym7N|!]9U9.d^VaHۏsfחƝD ;9'V@Gi cEfp-\ u2MMU,fU|TARtJ9p;*Q(@F>wFTYj 8wuWHZ`σY  sR\!3Bfu p}g^Ճ޻A$wyvZGbZ$p3+_ +~~Pj f=pvZh;ڮ H~ұD3$ٯum9wWM]oko;Ӡw{-~O[oAV0:D("\=+Hgft%tǛmǭ8M3i^J3fьJ4HcMIY54AStM$m +OJ3h~=킭}.ݿ{0{ !gZ"| <~&ͮC7ڎ==; msmeGdP> endobj 46 0 obj <> stream x]͎0<60"L2rmfA"䐷_WwWCPTζaM%͓N;y6ӷ3z>tu Q ] endstream endobj 47 0 obj <> endobj 48 0 obj <> endobj 49 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 50 0 obj <> endobj 51 0 obj < /Dest[1 0 R/XYZ 56.7 628.1 0]/Parent 50 0 R/Next 52 0 R>> endobj 52 0 obj < /Dest[1 0 R/XYZ 56.7 358.9 0]/Parent 50 0 R/Prev 51 0 R/Next 60 0 R>> endobj 53 0 obj < /Dest[1 0 R/XYZ 56.7 276.3 0]/Parent 52 0 R/Next 54 0 R>> endobj 54 0 obj < /Dest[1 0 R/XYZ 56.7 224.7 0]/Parent 52 0 R/Prev 53 0 R/Next 55 0 R>> endobj 55 0 obj < /Dest[4 0 R/XYZ 56.7 785.3 0]/Parent 52 0 R/Prev 54 0 R>> endobj 56 0 obj < /Dest[4 0 R/XYZ 56.7 716.7 0]/Parent 55 0 R/Next 57 0 R>> endobj 57 0 obj < /Dest[4 0 R/XYZ 56.7 488.5 0]/Parent 55 0 R/Prev 56 0 R/Next 58 0 R>> endobj 58 0 obj < /Dest[4 0 R/XYZ 56.7 374.2 0]/Parent 55 0 R/Prev 57 0 R/Next 59 0 R>> endobj 59 0 obj < /Dest[7 0 R/XYZ 56.7 486.5 0]/Parent 55 0 R/Prev 58 0 R>> endobj 60 0 obj < /Dest[7 0 R/XYZ 56.7 303.6 0]/Parent 50 0 R/Prev 52 0 R/Next 64 0 R>> endobj 61 0 obj < /Dest[7 0 R/XYZ 56.7 249.5 0]/Parent 60 0 R/Next 62 0 R>> endobj 62 0 obj < /Dest[7 0 R/XYZ 56.7 197.9 0]/Parent 60 0 R/Prev 61 0 R/Next 63 0 R>> endobj 63 0 obj < /Dest[7 0 R/XYZ 56.7 129.3 0]/Parent 60 0 R/Prev 62 0 R>> endobj 64 0 obj < /Dest[10 0 R/XYZ 56.7 633.3 0]/Parent 50 0 R/Prev 60 0 R/Next 68 0 R>> endobj 65 0 obj < /Dest[10 0 R/XYZ 56.7 567.7 0]/Parent 64 0 R/Next 66 0 R>> endobj 66 0 obj < /Dest[10 0 R/XYZ 56.7 516.1 0]/Parent 64 0 R/Prev 65 0 R/Next 67 0 R>> endobj 67 0 obj < /Dest[10 0 R/XYZ 56.7 436 0]/Parent 64 0 R/Prev 66 0 R>> endobj 68 0 obj < /Dest[13 0 R/XYZ 56.7 773.3 0]/Parent 50 0 R/Prev 64 0 R>> endobj 17 0 obj <> endobj 16 0 obj <> >> endobj 69 0 obj <> endobj 70 0 obj < /Creator /Producer /CreationDate(D:20080202113058+01'00')>> endobj xref 0 71 0000000000 65535 f 0000119328 00000 n 0000000019 00000 n 0000003253 00000 n 0000119472 00000 n 0000003274 00000 n 0000005098 00000 n 0000119634 00000 n 0000005119 00000 n 0000007239 00000 n 0000119778 00000 n 0000007260 00000 n 0000008762 00000 n 0000119924 00000 n 0000008784 00000 n 0000010110 00000 n 0000123588 00000 n 0000123462 00000 n 0000010132 00000 n 0000020778 00000 n 0000020801 00000 n 0000020998 00000 n 0000021364 00000 n 0000021590 00000 n 0000039941 00000 n 0000039964 00000 n 0000040167 00000 n 0000040621 00000 n 0000040931 00000 n 0000061082 00000 n 0000061105 00000 n 0000061299 00000 n 0000061819 00000 n 0000062183 00000 n 0000089315 00000 n 0000089338 00000 n 0000089527 00000 n 0000090139 00000 n 0000090594 00000 n 0000091321 00000 n 0000091342 00000 n 0000091532 00000 n 0000091831 00000 n 0000091996 00000 n 0000117942 00000 n 0000117965 00000 n 0000118159 00000 n 0000118752 00000 n 0000119190 00000 n 0000119273 00000 n 0000120070 00000 n 0000120127 00000 n 0000120273 00000 n 0000120441 00000 n 0000120587 00000 n 0000120765 00000 n 0000120937 00000 n 0000121195 00000 n 0000121425 00000 n 0000121727 00000 n 0000121925 00000 n 0000122117 00000 n 0000122263 00000 n 0000122441 00000 n 0000122587 00000 n 0000122792 00000 n 0000122939 00000 n 0000123118 00000 n 0000123263 00000 n 0000123769 00000 n 0000123871 00000 n trailer < <2D510E761CBCEA5CF7C4C703B7C7B8EB> ] /DocChecksum /792374D95B9BE2E5C550532D57B3AABB >> startxref 124128 %%EOF AjaXplorer/AjaXplorer/client/js/0000777000000000000000000000000011300346042017746 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/ajaxplorer/0000777000000000000000000000000011300346042022115 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/ajaxplorer/class.Editor.js0000766000000000000000000001514611122202530025010 0ustar adminadministratorsEditor = Class.create({ initialize: function(oFormObject) { this.oForm = $(oFormObject); this.actionBar = this.oForm.select('.action_bar')[0]; this.closeButton = oFormObject.select('a[id="closeButton"]')[0]; this.saveButton = oFormObject.select('a[id="saveButton"]')[0]; this.downloadButton = oFormObject.select('a[id="downloadFileButton"]')[0]; this.ficInput = oFormObject.select('input[name="file"]')[0]; this.repInput = oFormObject.select('input[name="dir"]')[0]; this.fsButton = oFormObject.select('a[id="fsButton"]')[0]; this.nofsButton = oFormObject.select('a[id="nofsButton"]')[0]; this.fsButton.onclick = function(){ this.setFullScreen(); this.fsButton.hide(); this.nofsButton.show(); return false; }.bind(this); this.nofsButton.onclick = function(){ this.exitFullScreen(); this.nofsButton.hide(); this.fsButton.show(); return false; }.bind(this); this.closeButton.observe('click', function(){ if(this.modified && !window.confirm(MessageHash[201])){ return false; } if(this.fullscreenMode) this.exitFullScreen(); this.close(); hideLightBox(true); return false; }.bind(this)); this.saveButton.observe('click', function(){ this.saveFile(); return false; }.bind(this)); this.downloadButton.observe('click', function(){ if(!this.currentFile) return; document.location.href = 'content.php?action=download&file='+this.currentFile; return false; }.bind(this)); modal.setCloseAction(function(){this.close();}.bind(this)); }, createEditor : function(fileName){ var cpStyle = editWithCodePress(getBaseName(fileName)); var textarea; this.textareaContainer = document.createElement('div'); this.textarea = $(document.createElement('textarea')); if(cpStyle != "") { var hidden = document.createElement('input'); hidden.type = 'hidden'; hidden.name = hidden.id = 'code'; this.oForm.appendChild(hidden); this.textarea.name = this.textarea.id = 'cpCode'; $(this.textarea).addClassName('codepress'); $(this.textarea).addClassName(cpStyle); $(this.textarea).addClassName('linenumbers-on'); this.currentUseCp = true; this.fsButton.setStyle({display:"none"}); } else { this.textarea.name = this.textarea.id = 'code'; this.textarea.addClassName('dialogFocus'); this.textarea.addClassName('editor'); this.currentUseCp = false; } this.textarea.setStyle({width:'100%'}); this.textarea.setAttribute('wrap', 'off'); this.oForm.appendChild(this.textareaContainer); this.textareaContainer.appendChild(this.textarea); fitHeightToBottom($(this.textarea), $(modal.elementName), 5, true); }, loadFile : function(fileName){ this.currentFile = fileName; var connexion = new Connexion(); connexion.addParameter('get_action', 'edit'); connexion.addParameter('file', fileName); connexion.onComplete = function(transp){this.parseTxt(transp);}.bind(this); this.changeModifiedStatus(false); this.setOnLoad(); connexion.sendAsync(); }, saveFile : function(){ var connexion = new Connexion(); connexion.addParameter('get_action', 'edit'); connexion.addParameter('save', '1'); var value; if(this.currentUseCp) value = this.oForm.select('iframe')[0].getCode(); else value = this.textarea.value; connexion.addParameter('code', value); connexion.addParameter('file', this.ficInput.value); connexion.addParameter('dir', this.repInput.value); connexion.onComplete = function(transp){this.parseXml(transp);}.bind(this); this.setOnLoad(); connexion.setMethod('put'); connexion.sendAsync(); }, parseXml : function(transport){ //alert(transport.responseText); this.changeModifiedStatus(false); this.removeOnLoad(); }, parseTxt : function(transport){ this.textarea.value = transport.responseText; var contentObserver = function(el, value){ this.changeModifiedStatus(true); }.bind(this); if(this.currentUseCp) { this.textarea.id = 'cpCode_cp'; code = new CodePress(this.textarea, contentObserver); this.cpCodeObject = code; this.textarea.parentNode.insertBefore(code, this.textarea); } else{ new Form.Element.Observer(this.textarea, 0.2, contentObserver); } this.removeOnLoad(); }, changeModifiedStatus : function(bModified){ this.modified = bModified; var crtTitle = modal.dialogTitle.select('span.titleString')[0]; if(this.modified){ this.saveButton.removeClassName('disabled'); if(crtTitle.innerHTML.charAt(crtTitle.innerHTML.length - 1) != "*"){ crtTitle.innerHTML = crtTitle.innerHTML + '*'; } }else{ this.saveButton.addClassName('disabled'); if(crtTitle.innerHTML.charAt(crtTitle.innerHTML.length - 1) == "*"){ crtTitle.innerHTML = crtTitle.innerHTML.substring(0, crtTitle.innerHTML.length - 1); } } // ADD / REMOVE STAR AT THE END OF THE FILENAME }, setOnLoad : function(){ addLightboxMarkupToElement(this.textareaContainer); var img = document.createElement("img"); img.src = ajxpResourcesFolder+"/images/loadingImage.gif"; $(this.textareaContainer).select("#element_overlay")[0].appendChild(img); this.loading = true; }, removeOnLoad : function(){ removeLightboxFromElement(this.textareaContainer); this.loading = false; }, close : function(){ if(this.currentUseCp){ this.cpCodeObject.close(); modal.clearContent(modal.dialogContent); } }, setFullScreen: function(){ this.oForm.absolutize(); $(document.body).insert(this.oForm); this.oForm.setStyle({ top:0, left:0, backgroundColor:'#fff', width:'100%', height:document.viewport.getHeight(), zIndex:3000}); this.actionBar.setStyle({marginTop: 0}); if(!this.currentUseCp){ this.origContainerHeight = this.textarea.getHeight(); this.heightObserver = fitHeightToBottom(this.textarea, this.oForm, 0, true); }else{ } var listener = this.fullScreenListener.bind(this); Event.observe(window, "resize", listener); this.oForm.observe("fullscreen:exit", function(e){ Event.stopObserving(window, "resize", listener); //Event.stopObserving(window, "resize", this.heightObserver); }.bind(this)); this.fullscreenMode = true; }, exitFullScreen: function(){ this.oForm.relativize(); $$('.dialogContent')[0].insert(this.oForm); this.oForm.setStyle({top:0,left:0,zIndex:100}); this.actionBar.setStyle({marginTop: -10}); this.oForm.fire("fullscreen:exit"); if(!this.currentUseCp){ this.textarea.setStyle({height:this.origContainerHeight}); }else{ } this.fullscreenMode = false; }, fullScreenListener : function(){ this.oForm.setStyle({ height:document.viewport.getHeight() }); if(!this.currentUseCp) {fitHeightToBottom(this.textarea, this.oForm, 0, true);} } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.Connexion.js0000766000000000000000000000743711122202530025526 0ustar adminadministratorsConnexion = Class.create({ initialize: function(baseUrl) { this._baseUrl = ajxpServerAccessPath; if(baseUrl) this._baseUrl = baseUrl; this._libUrl = ajxpResourcesFolder+'/js'; this._parameters = new Hash(); this._method = 'get'; this.addParameter('get_action', 'ls'); }, addParameter : function (paramName, paramValue){ this._parameters.set(paramName, paramValue); }, setParameters : function(hParameters){ this._parameters = $H(hParameters); }, setMethod : function(method){ this._method = 'put'; }, sendAsync : function(){ // WARNING, FINALLY PAS PAREMETERS AS AN OBJECT, PROTOTYPE 1.6.0 BUG Hash.toQueryString(); new Ajax.Request(this._baseUrl, { method:this._method, onComplete:this.onComplete, parameters:this._parameters.toObject() }); }, sendSync : function(){ // WARNING, FINALLY PAS PAREMETERS AS AN OBJECT, PROTOTYPE 1.6.0 BUG Hash.toQueryString(); new Ajax.Request(this._baseUrl, { method:this._method, asynchronous: false, onComplete:this.onComplete, parameters:this._parameters.toObject() }); }, loadLibrary : function(fileName, onLoadedCode){ new Ajax.Request(this._libUrl+'/'+fileName, { method:'get', asynchronous: false, onComplete:function(transport){ if(transport.responseText) { try { var script = transport.responseText; if (window.execScript){ //alert('execScript for'+fileName); window.execScript( script ); } else{ //alert('eval for'+fileName); //window.eval( script ); // TO TEST, THIS SEEM TO WORK ON SAFARI window.my_code = script; var script_tag = document.createElement('script'); script_tag.type = 'text/javascript'; script_tag.innerHTML = 'eval(window.my_code)'; document.getElementsByTagName('head')[0].appendChild(script_tag) } if(onLoadedCode != null) onLoadedCode(); } catch(e) { alert('error loading '+fileName+':'+e); //errorWindow=window.open("", "", "height=500, width=600,toolbar=no,scrollbars=yes,menubar=no,resizable=yes"); //errorWindow.document.write(transport.responseText); } } } }); }, loadLibraries : function(){ if(!dynamicLibLoading) {return;} var toLoad = $A([ "lib/webfx/slider/js/timer.js", "lib/webfx/slider/js/range.js", "lib/webfx/slider/js/slider.js", "lib/leightbox/lightbox.js", "lib/ufo/ufo.js", "lib/prototype/proto.menu.js", "lib/codepress/codepress.js", "lib/webfx/selectableelements.js", "lib/webfx/selectabletablerows.js", "lib/webfx/sortabletable.js", "lib/webfx/numberksorttype.js", "lib/webfx/slider/js/timer.js", "lib/webfx/slider/js/range.js", "lib/webfx/slider/js/slider.js", "lib/xloadtree/xtree.js", "lib/xloadtree/xloadtree.js", "lib/xloadtree/xmlextras.js", "ajaxplorer/ajxp_multifile.js", "ajaxplorer/ajxp_utils.js", "ajaxplorer/class.User.js", "ajaxplorer/class.AjxpDraggable.js", "ajaxplorer/class.AjxpAutoCompleter.js", "ajaxplorer/class.Diaporama.js", "ajaxplorer/class.Editor.js", "ajaxplorer/class.ActionsManager.js", "ajaxplorer/class.FilesList.js", "ajaxplorer/class.FoldersTree.js", "ajaxplorer/class.SearchEngine.js", "ajaxplorer/class.InfoPanel.js", "ajaxplorer/class.ResizeableBar.js", "ajaxplorer/class.UserSelection.js"]); modal.incrementStepCounts(toLoad.size()); toLoad.each(function(fileName){ var onLoad = function(){modal.updateLoadingProgress(fileName);}; if(fileName == toLoad.last()) onLoad = function(){modal.updateLoadingProgress(fileName);}; this.loadLibrary(fileName, onLoad); }.bind(this)); } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.ResizeableBar.js0000766000000000000000000000717511122202530026277 0ustar adminadministratorsResizeableBar = Class.create({ hasExpandButton : false, initialize: function(containerName, widthReferenceName, elementsSelector, titleElementName, buttonElementName) { this.containerElement = $(containerName); this.titleElementName = titleElementName; this.elementsSelector = elementsSelector; this.buttonElementName = buttonElementName; this.widthReferenceElement = $(widthReferenceName); this.hiddenElements = new Array(); this.buttonImage = new Element('img', { src:ajxpResourcesFolder+'/images/crystal/lower.png', style:'cursor:pointer', align:'absmiddle' }); this.buttonImage.observe('click', function(){ this.toggleExtension(); }.bind(this)); Event.observe(window, "resize", function(){ this.toggleExtension(true); this.updateUI(); }.bind(this) ); }, updateUI: function(){ var totalWidth = this.widthReferenceElement.getWidth()-43; if(this.titleElementName && $(this.titleElementName)) { totalWidth -= $(this.titleElementName).getWidth(); } var currentWidth = 0; var elements = this.containerElement.getElementsByClassName(this.elementsSelector); this.hiddenElements = new Array(); elements.each(function(element){ if(element.readAttribute("extendedMenu") == "true") return; currentWidth += element.getWidth(); if(currentWidth >= totalWidth){ element.hide(); this.hiddenElements.push(element); } else{ element.show(); } }.bind(this)); if(this.hiddenElements.length && !this.hasExpandButton) { if(this.buttonElementName && $(this.buttonElementName)) { $(this.buttonElementName).appendChild(this.buttonImage); } else { this.containerElement.appendChild(this.buttonImage); } this.hasExpandButton = true; } else if(!this.hiddenElements.length && this.hasExpandButton) { if(this.buttonElementName && $(this.buttonElementName) && this.buttonImage) { $(this.buttonElementName).removeChild(this.buttonImage); } else { if(this.buttonImage) this.containerElement.removeChild(this.buttonImage); } this.hasExpandButton = false; } }, toggleExtension: function(hideOnly){ if(!this.hiddenElements.length) return; body = document.getElementsByTagName('body')[0]; if(this.menuIsVisible) { while(this.menu.firstChild) { $(this.menu.firstChild).setStyle({cssFloat:"right"}); $(this.menu.firstChild).setAttribute("extendedMenu", "false"); this.containerElement.appendChild(this.menu.firstChild.hide()); } body.removeChild(this.menu); this.menu = null; this.menuIsVisible = false; } else if(!hideOnly) { // build menu and show next to button. this.menu = $(document.createElement("div")); this.menu.setStyle({ position:"absolute", zIndex:1500, border:"1px solid black", backgroundColor:"white", textAlign:"left"}); this.hiddenElements.each(function(element){ $(element).setStyle({cssFloat:"none", textAlign:"left"}); $(element).setAttribute("extendedMenu", "true"); this.menu.appendChild(element.show()); }.bind(this)); body.appendChild(this.menu); this.menuIsVisible = true; var buttonPosition = Position.cumulativeOffset($(this.buttonImage)); var topPos = buttonPosition[1] + $(this.buttonImage).getHeight(); var leftPos = buttonPosition[0] + $(this.buttonImage).getWidth() - this.menu.getWidth(); this.menu.style.top = topPos + "px"; this.menu.style.left = leftPos + "px"; var closeHandler = function(){this.toggleExtension(true); Event.stopObserving(body,"click", closeHandler); return true;}.bind(this); window.setTimeout(function(){ Event.observe(body,"click", closeHandler);}, 100); } } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.SearchEngine.js0000766000000000000000000001423311122202530026111 0ustar adminadministratorsSearchEngine = Class.create({ htmlElement:undefined, _inputBox:undefined, _resultsBox:undefined, _searchButtonName:undefined, state: 'idle', _runningQueries:undefined, _queriesIndex:0, initialize: function(mainElementName) { this.htmlElement = $(mainElementName); this.initGUI(); }, initGUI : function(){ this.htmlElement.update('
    '); this._inputBox = $("search_txt"); this._resultsBox = $("search_results"); this._searchButtonName = "search_button"; this._runningQueries = new Array(); $('stop_'+this._searchButtonName).addClassName("disabled"); this.htmlElement.select('a', 'div[id="search_results"]').each(function(element){ disableTextSelection(element); }); this._inputBox.onkeypress = function(e){ if (e==null) e = window.event; if(e.keyCode == 13) this.search(); if(e.keyCode == 9) return false; }.bind(this); this._inputBox.onkeydown = function(e){ if(e == null) e = window.event; if(e.keyCode == 9) return false; return true; }; this._inputBox.onfocus = function(e){ ajaxplorer.disableShortcuts(); this.hasFocus = true; this._inputBox.select(); return false; }.bind(this); this._inputBox.onblur = function(e){ ajaxplorer.enableShortcuts(); this.hasFocus = false; }.bind(this); $(this._searchButtonName).onclick = function(){ this.search(); return false; }.bind(this); $('stop_'+this._searchButtonName).onclick = function(){ this.interrupt(); return false; }.bind(this); this.resize(); }, resize: function(){ fitHeightToBottom(this._resultsBox, null, 10, true); }, focus : function(){ if(this.htmlElement.visible()){ this._inputBox.activate(); this.hasFocus = true; } }, blur : function(){ this._inputBox.blur(); this.hasFocus = false; }, search : function(){ var text = this._inputBox.value; if(text == '') return; this.updateStateSearching(); this.clearResults(); var folder = ajaxplorer.getActionBar().getLocationBarValue(); if(folder == "/") folder = ""; this.searchFolderContent(text, folder); }, interrupt : function(){ // Interrupt current search if(this._state == 'idle') return; this._state = 'interrupt'; }, updateStateSearching : function (){ this._state = 'searching'; //try{this._inputBox.disabled = true;}catch(e){} $(this._searchButtonName).addClassName("disabled"); $('stop_'+this._searchButtonName).removeClassName("disabled"); }, updateStateFinished : function (interrupt){ this._state = 'idle'; this._inputBox.disabled = false; $(this._searchButtonName).removeClassName("disabled"); $('stop_'+this._searchButtonName).addClassName("disabled"); }, registerQuery : function(queryId){ this._runningQueries.push(''+queryId); }, unregisterQuery : function(queryId){ // USES PROTOTYPE WITHOUT() FUNCTION this._runningQueries = this._runningQueries.without(''+queryId); if(this._runningQueries.length == 0) { if(this._state == 'searching') this.updateStateFinished(false); else if(this._state == 'interrupt') this.updateStateFinished(true); } }, clear: function(){ this.clearResults(); this._inputBox.value = ""; }, clearResults : function(){ // Clear the results while(this._resultsBox.childNodes.length) { this._resultsBox.removeChild(this._resultsBox.childNodes[0]); } }, addResult : function(folderName, fileName, icon){ // Display the result in the results box. if(folderName == "") folderName = "/"; var divElement = document.createElement('div'); var isFolder = false; if(icon == null) // FOLDER CASE { isFolder = true; icon = 'folder.png'; if(folderName != "/") folderName += "/"; folderName += fileName; } var imageString = ' '; var stringToDisplay = fileName; divElement.innerHTML = imageString+stringToDisplay; divElement.title = MessageHash[224]+' '+ folderName; if(isFolder) { divElement.onclick = function(e){ajaxplorer.goTo(folderName);} } else { divElement.onclick = function(e){ajaxplorer.goTo(folderName, fileName);} } this._resultsBox.appendChild(divElement); }, searchFolderContent : function(text, currentFolder){ if(this._state == 'interrupt') return; this._queriesIndex ++; var queryIndex = this._queriesIndex; this.registerQuery(this._queriesIndex); var connexion = new Connexion(); connexion.addParameter('mode', 'search'); connexion.addParameter('dir', currentFolder); connexion.onComplete = function(transport){ this._parseXmlAndSearchString(transport.responseXML, text, currentFolder, queryIndex); }.bind(this); connexion.sendAsync(); }, _parseXmlAndSearchString : function(oXmlDoc, text, currentFolder, queryIndex){ if(this._state == 'interrupt') { this.unregisterQuery(queryIndex); return; } if( oXmlDoc == null || oXmlDoc.documentElement == null) { //alert(currentFolder); } else { var root = oXmlDoc.documentElement; // loop through all tree children var cs = root.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i].tagName == "tree") { var icon = cs[i].getAttribute('icon'); if(cs[i].getAttribute('text').toLowerCase().indexOf(text.toLowerCase()) != -1) { this.addResult(currentFolder, cs[i].getAttribute('text'), icon); } if(cs[i].getAttribute('is_file') == null) { this.searchFolderContent(text, currentFolder+"/"+cs[i].getAttribute('text')); } } } } this.unregisterQuery(queryIndex); } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.Ajaxplorer.js0000766000000000000000000004350011122202530025664 0ustar adminadministratorsif(dynamicLibLoading) { document.write(''); } Ajaxplorer = Class.create({ initialize: function(loadRep, usersEnabled, loggedUser, rootDirId, rootDirsList, rootDirsSettings, defaultDisplay) { this._initLoadRep = loadRep; this._initObj = true ; this.usersEnabled = usersEnabled; this._initLoggedUser = loggedUser; this._initRootDirsList = rootDirsList; this._initRootDirsSettings = rootDirsSettings; this._initRootDirId = rootDirId; this._initDefaultDisp = ((defaultDisplay && defaultDisplay!='')?defaultDisplay:'list'); this.histCount=0; if(!this.usersEnabled) this.rootDirId = rootDirId; modal.setLoadingStepCounts(this.usersEnabled?7:6); this.initTemplates(); modal.initForms(); this.initObjects(); }, initTemplates:function(){ var connexion = new Connexion(); connexion.addParameter('get_action', 'get_template'); connexion.onComplete = function(transport){ $(document.body).insert({top:transport.responseText}); }; connexion.addParameter('template_name', 'gui_tpl.html'); connexion.sendSync(); modal.updateLoadingProgress('Main template loaded'); }, loadI18NMessages: function(newLanguage){ var connexion = new Connexion(); connexion.addParameter('get_action', 'get_i18n_messages'); connexion.onComplete = function(transport){ if(transport.responseText){ var result = transport.responseText.evalScripts(); MessageHash = result[0]; this.updateI18nTags(); if(this.infoPanel) this.infoPanel.update(); if(this.actionBar) this.actionBar.loadActions(); if(this.filesList) this.filesList.reload(); this.currentLanguage = newLanguage; } }.bind(this); connexion.sendSync(); }, updateI18nTags: function(){ $$('[ajxp_message_id]').each(function(tag){ tag.update(MessageHash[tag.readAttribute("ajxp_message_id")]); }); $$('[ajxp_message_title_id]').each(function(tag){ tag.writeAttribute('title', MessageHash[tag.readAttribute("ajxp_message_title_id")]); }); }, initObjects: function(){ loadRep = this._initLoadRep; crtUser = this._initCrtUser; rootDirName = this._initRootDir; this.infoPanel = new InfoPanel("info_panel"); //modal.updateLoadingProgress('Libraries loaded'); if(!this.usersEnabled) { var fakeUser = new User("shared"); fakeUser.setActiveRepository(this._initRootDirId, 1, 1); fakeUser.setRepositoriesList(this._initRootDirsList); this.actionBar = new ActionsManager($("action_bar"), this.usersEnabled, fakeUser, this); this.foldersTree = new FoldersTree('tree_container', this._initRootDirsList.get(this._initRootDirId), ajxpServerAccessPath+'?action=ls', this); this.refreshRootDirMenu(this._initRootDirsList, this._initRootDirId); this.actionBar.loadActions(); this.infoPanel.load(); } else { this.actionBar = new ActionsManager($("action_bar"), this.usersEnabled, null, this); this.foldersTree = new FoldersTree('tree_container', 'No Repository', ajxpServerAccessPath+'?action=ls', this); if(this._initLoggedUser) { this.getLoggedUserFromServer(); }else{ this.tryLogUserFromCookie(); } } this.actionBar.init(); modal.updateLoadingProgress('ActionBar Initialized'); this.contextMenu = new Proto.Menu({ selector: '', // context menu will be shown when element with class name of "contextmenu" is clicked className: 'menu desktop', // this is a class which will be attached to menu container (used for css styling) menuItems: [], fade:true, zIndex:2000 }); var protoMenu = this.contextMenu; protoMenu.options.beforeShow = function(e){setTimeout(function(){ this.options.menuItems = ajaxplorer.actionBar.getContextActions(Event.element(e)); this.refreshList(); }.bind(protoMenu),0);}; this.foldersTree.setContextualMenu(this.contextMenu); this.actionBar.setContextualMenu(this.contextMenu); this.sEngine = new SearchEngine("search_container"); this.messageBox = $('message_div'); this.initGUI(); this.filesList = new FilesList($("selectable_div"), true, ["StringDirFile", "NumberKo", "String", "MyDate"], null, this, this._initDefaultDisp) ; this.filesList.setContextualMenu(this.contextMenu); modal.updateLoadingProgress('GUI Initialized'); this.initFocusBehaviours(); this.initTabNavigation(); modal.updateLoadingProgress('Navigation loaded'); this.focusOn(this.foldersTree); this.blockShortcuts = false; this.blockNavigation = false; new AjxpAutocompleter("current_path", "autocomplete_choices"); if(Prototype.Browser.Gecko){ this.history = new Proto.History(function(hash){ this.goTo(this.historyHashToPath(hash)); }.bind(this)); } this.goTo(loadRep); }, tryLogUserFromCookie : function(){ var connexion = new Connexion(); var rememberData = retrieveRememberData(); if(rememberData!=null){ connexion.addParameter('get_action', 'login'); connexion.addParameter('userid', rememberData.user); connexion.addParameter('password', rememberData.pass); connexion.addParameter('cookie_login', 'true'); connexion.onComplete = function(transport){this.actionBar.parseXmlMessage(transport.responseXML);}.bind(this); }else{ connexion.addParameter('get_action', 'logged_user'); connexion.onComplete = function(transport){this.logXmlUser(transport.responseXML);}.bind(this); } connexion.sendAsync(); }, getLoggedUserFromServer: function(){ var connexion = new Connexion(); var rememberData = retrieveRememberData(); connexion.addParameter('get_action', 'logged_user'); connexion.onComplete = function(transport){this.logXmlUser(transport.responseXML);}.bind(this); connexion.sendAsync(); }, logXmlUser: function(xmlResponse){ this.user = null; try{ var childs = xmlResponse.documentElement.childNodes; for(var i=0; i 1){ rootDirsList.each(function(pair){ var value = pair.value; var key = pair.key; var selected = (key == rootDirId ? true:false); var repoImage = null; if(this.usersEnabled){ repoImage = (this.user?this.user.getRepositoryIcon(key):null); }else{ repoImage = this._initRootDirsSettings.get(key).get('icon') || null; } actions[actions.length] = { name:value, alt:value, image:repoImage || ajxpResourcesFolder+'/images/foldericon.png', className:"edit", disabled:selected, callback:function(e){ ajaxplorer.triggerRootDirChange(''+key); } } }.bind(this)); } if(this.rootMenu){ this.rootMenu.options.menuItems = actions; this.rootMenu.refreshList(); }else{ this.rootMenu = new Proto.Menu({ className: 'menu rootDirChooser', mouseClick:'left', //anchor:'root_dir_button', anchor:'goto_repo_button', createAnchor:false, anchorContainer:$('dir_chooser'), anchorSrc:ajxpResourcesFolder+'/images/crystal/lower.png', anchorTitle:MessageHash[200], topOffset:6, leftOffset:-107, menuTitle:MessageHash[200], menuItems: actions, fade:true, zIndex:1500 }); } if(actions.length) $('goto_repo_button').removeClassName('disabled'); }, triggerRootDirChange: function(rootDirId){ this.actionBar.updateLocationBar('/'); var connexion = new Connexion(); connexion.addParameter('get_action', 'switch_root_dir'); connexion.addParameter('root_dir_index', rootDirId); oThis = this; connexion.onComplete = function(transport){ if(this.usersEnabled) { this.getLoggedUserFromServer(); } else { this.actionBar.parseXmlMessage(transport.responseXML); this.loadRepository(rootDirId, this._initRootDirsList.get(rootDirId)); } }.bind(this); connexion.sendAsync(); }, updateHistory: function(path){ if(this.history) this.history.historyLoad(this.pathToHistoryHash(path)); }, pathToHistoryHash: function(path){ document.title = 'AjaXplorer - '+(getBaseName(path)?getBaseName(path):'/'); if(!this.pathesHash){ this.pathesHash = new Hash(); this.histCount = -1; } var foundKey; this.pathesHash.each(function(pair){ if(pair.value == path) foundKey = pair.key; }); if(foundKey != undefined) return foundKey; this.histCount++; this.pathesHash.set(this.histCount, path); return this.histCount; }, historyHashToPath: function(hash){ if(!this.pathesHash) return "/"; var path = this.pathesHash.get(hash); if(path == undefined) return "/"; return path; }, cancelCopyOrMove: function(){ this.foldersTree.setTreeInNormalMode(); this.foldersTree.selectCurrentNodeName(); this.actionBar.treeCopyActive = false; hideLightBox(); return false; }, disableShortcuts: function(){ this.blockShortcuts = true; }, enableShortcuts: function(){ this.blockShortcuts = false; }, disableNavigation: function(){ this.blockNavigation = true; }, enableNavigation: function(){ this.blockNavigation = false; }, getActionBar: function(){ return this.actionBar; }, getFilesList: function(){ return this.filesList; }, getFoldersTree: function(){ return this.foldersTree; }, closeMessageDiv: function(){ if(this.messageDivOpen) { new Effect.Fade(this.messageBox); this.messageDivOpen = false; } }, tempoMessageDivClosing: function(){ this.messageDivOpen = true; setTimeout('ajaxplorer.closeMessageDiv()', 3000); }, displayMessage: function(messageType, message){ message = message.replace(new RegExp("(\\n)", "g"), "
    "); if(messageType == "ERROR"){ this.messageBox.removeClassName('logMessage'); this.messageBox.addClassName('errorMessage');} else { this.messageBox.removeClassName('errorMessage'); this.messageBox.addClassName('logMessage');} $('message_content').innerHTML = message; // appear at bottom of content panel var containerOffset = Position.cumulativeOffset($('content_pane')); var containerDimensions = $('content_pane').getDimensions(); var boxHeight = $(this.messageBox).getHeight(); var topPosition = containerOffset[1] + containerDimensions.height - boxHeight - 20; var boxWidth = parseInt(containerDimensions.width * 90/100); var leftPosition = containerOffset[0] + parseInt(containerDimensions.width*5/100); this.messageBox.style.top = topPosition+'px'; this.messageBox.style.left = leftPosition+'px'; this.messageBox.style.width = boxWidth+'px'; new Effect.Corner(this.messageBox,"round"); new Effect.Appear(this.messageBox); this.tempoMessageDivClosing(); }, initFocusBehaviours: function(){ $('topPane').observe("click", function(){ ajaxplorer.focusOn(ajaxplorer.foldersTree); }); $('content_pane').observe("click", function(){ ajaxplorer.focusOn(ajaxplorer.filesList); }); $('action_bar').observe("click", function(){ ajaxplorer.focusOn(ajaxplorer.actionBar); }); $('search_div').observe("click", function(){ ajaxplorer.focusOn(ajaxplorer.sEngine); }); }, focusOn : function(object){ var objects = [this.foldersTree, this.sEngine, this.filesList, this.actionBar]; objects.each(function(obj){ if(obj != object) obj.blur(); }); object.focus(); }, initTabNavigation: function(){ var objects = [this.foldersTree, this.filesList, this.actionBar]; // ASSIGN OBSERVER Event.observe(document, "keydown", function(e) { if(e.keyCode == Event.KEY_TAB) { if(this.blockNavigation) return; var shiftKey = e['shiftKey']; for(i=0; i0) nextIndex=i-1; else nextIndex = (objects.length) - 1; } else { if(i 90 || e.keyCode < 65) return; else return this.actionBar.fireActionByKey(e, String.fromCharCode(e.keyCode).toLowerCase()); }.bind(this)); }, initGUI: function(){ try{ var marginBottom = (Prototype.Browser.IE?18:15); if($('optional_bottom_div') && $('optional_bottom_div').getHeight()>15 ){ marginBottom = $('optional_bottom_div').getHeight(); } fitHeightToBottom($("browser"), window, marginBottom); fitHeightToBottom($("verticalSplitter"), $('browser'), 8); var s1 = new Splitter('sidebarSplitter',{ direction: "horizontal", initB: 150, minB: 24, maxB: 500, onDrag:function(){ fitHeightToBottom($('tree_container'), null, (Prototype.Browser.IE?0:4), true); fitHeightToBottom($('bottomSplitPane'), null, (Prototype.Browser.IE?-1:1), true); this.sEngine.resize(); }.bind(this) }); this.splitter = new Splitter('verticalSplitter', { direction: "vertical", initA: 200, maxA:400, minA:50, onDrag: function(){ s1.resizeGroup(null, null, true); if(this.filesList)this.filesList.applyHeadersWidth(); }.bind(this) }); this.currentSideToggle = 'search'; this.toggleSidePanel('info'); new Effect.Fade(this.messageBox); $(this.actionBar._htmlElement).getElementsBySelector('a', 'input[type="image"]').each(function(element){ disableTextSelection(element); }); disableTextSelection($('tree_container')); disableTextSelection($('bookmarks_bar')); disableTextSelection($('panelsToggle')); disableTextSelection($('info_panel')); disableTextSelection($('dir_chooser')); }catch(e){alert(e);} }, toggleSidePanel: function(srcName){ if(srcName == 'info' && this.currentSideToggle != 'info'){ $(this.sEngine.htmlElement).hide(); $('search_header').addClassName("toggleInactive"); $('search_header').getElementsBySelector("img")[0].hide(); $(this.infoPanel.htmlElement).show(); $('info_panel_header').removeClassName("toggleInactive"); $('info_panel_header').getElementsBySelector("img")[0].show(); } else if(srcName == 'search' && this.currentSideToggle != 'search'){ $(this.sEngine.htmlElement).show(); $('search_header').removeClassName("toggleInactive"); $('search_header').getElementsBySelector("img")[0].show(); $(this.infoPanel.htmlElement).hide(); $('info_panel_header').addClassName("toggleInactive"); $('info_panel_header').getElementsBySelector("img")[0].hide(); this.sEngine.resize(); } this.currentSideToggle = srcName; }, loadLibraries: function(){ if(!dynamicLibLoading) {this.init(); return;} var connexion = new Connexion(); var toLoad = $A([]); modal.incrementStepCounts(toLoad.size()); toLoad.each(function(fileName){ var onLoad = function(){modal.updateLoadingProgress(fileName);}; if(fileName == toLoad.last()) onLoad = function(){modal.updateLoadingProgress(fileName);this.init();}.bind(this); connexion.loadLibrary(fileName, onLoad); }); }, libLoaded: function(fileName){ modal.updateLoadingProgress('Loaded : ' + fileName); } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.SQLEditor.js0000766000000000000000000003206311122202530025365 0ustar adminadministratorsSQLEditor = Class.create({ initialize: function(oFormObject) { this.oForm = $(oFormObject); modal.setCloseAction(function(){this.close();}.bind(this)); }, createEditor : function(){ var userSelection = ajaxplorer.filesList.getUserSelection(); if(userSelection.hasFile()){ this.createRecordEditor(userSelection); }else{ this.createTableEditor(userSelection); } }, createRecordEditor: function(userSelection){ var columns = ajaxplorer.filesList.getColumnsDef(); var crtTableName = getBaseName(ajaxplorer.filesList.getCurrentRep()); this.oForm.insert(new Element('input', {type:'hidden',name:'table_name', value:crtTableName})); var table = new Element('table', {width:'96%', className:'sqlRecordForm'}); var tBody = new Element('tbody'); table.insert(tBody); this.fields = $A([]); $A(columns).each(function(col){ this.fields.push(col.attributeName); var disable = false; var auto_inc = false; if(col.field_pk == "1"){ this.oForm.insert(new Element('input', {type:'hidden',name:'pk_name', value:col.attributeName})); if(userSelection && !userSelection.isEmpty()){ disable = true; }else if(col.field_flags.search('auto_increment') > -1){ disable = true; auto_inc = true; } } var tr= new Element('tr'); var labelTD = new Element('td', {className:'sqlLabelTd'}).update(col.attributeName + ' :'); var typeTD = new Element('td', {className:'sqlTypeTd'}).update('('+col.field_type+(auto_inc?',auto':'')+')'); var inputTD = new Element('td', {className:'sqlInputTd'}); var input; var type = col.field_type.toLowerCase(); switch(type){ case "enum": case "set": input = new Element('select', {name:col.attributeName}); var setString = col.field_size; while(setString.search('\'')>-1) setString = setString.replace('\'', ''); var arr = $A(setString.split(',')); arr.each(function(setValue){ input.insert(new Element('option', {value:setValue}).update(setValue) ); }); break; case "varchar": case "char": case "string": case "tinyblob": case "tinytext": case "longblob": case "longtext": case "mediumblob": case "mediumtext": case "blob": case "text": if(parseInt(col.field_size) > 70){ input = new Element('textarea', {name:col.attributeName}); }else{ input = new Element('input', {name:col.attributeName}); } break; default : input = new Element('input', {name:col.attributeName}); break; } if(disable) input.disable(); inputTD.update(input); tr.insert(labelTD); tr.insert(inputTD); tr.insert(typeTD); tBody.insert(tr); }.bind(this)); var crtElement = this.oForm.select('div[id="mysql_edit_record"]')[0]; crtElement.insert({top:table}); var newRec = new Element('input', {type:'hidden',name:'record_is_new', value:'true'}); this.oForm.insert(newRec); if(userSelection && !userSelection.isEmpty()){ newRec.value = 'false'; var item = userSelection.getUniqueItem(); var value = new Hash(); this.fields.each(function(fName){ if(Prototype.Browser.IE && fName == "ID"){ value.set(fName, item.getAttribute("ajxp_sql_"+fName)); }else{ value.set(fName, item.getAttribute(fName)); } }); var formManager = new FormManager(); formManager.fetchValueToForm(this.oForm, this.fields, value.toObject()); } modal.refreshDialogPosition(true, $('mysql_edit_record')); }, submitRecordForm : function(){ var oForm = modal.getForm(); oForm.getElements().each(function(el){ if($A(this.fields).include(el.getAttribute('name'))){ el.setAttribute('name', 'ajxp_mysql_'+el.getAttribute('name')); } }.bind(this)); ajaxplorer.actionBar.submitForm(oForm, true); hideLightBox(); }, createTableEditor: function(tableName){ if(!tableName){ this.displayReplicationChooser(); }else{ var columns = ajaxplorer.filesList.getColumnsDef(); var fields = $A(["field_name", "field_origname", "field_type", "field_size", "field_flags", "field_default", "field_pk", "field_null"]); columns.each(function(col){ col['field_origname'] = col['field_name']; }); this.oForm.insert(new Element('input', {type:'hidden',name:'current_table',value:getBaseName(tableName)})); this.displayTableEditorForm(columns.length, fields, columns); } }, displayReplicationChooser : function(){ var chooser = $('replication_chooser').cloneNode(true).setStyle({display:'block'}); this.oForm.insert(chooser); var button = chooser.select('input[id="toNext"]')[0]; button.observe('click', function(e){ Event.stop(e); this.newTableName = chooser.select('input[id="table_name"]')[0].value; var fieldsNumber = parseInt(chooser.select('input[id="fields_number"]')[0].value); if(this.newTableName && fieldsNumber){ chooser.remove(); this.displayTableEditorForm(fieldsNumber); }else{ alert('Missing parameters!'); } }.bind(this)); cancelButton = chooser.select('input[id="can"]')[0]; cancelButton.observe('click', function(e){ hideLightBox(); modal.close(); }.bind(this) ); }, displayTableEditorForm : function(numberReplicates, fields, values){ var templateTable = $('create_table_template').cloneNode(true).setStyle({display:'block'}); var templateRow = templateTable.select('tbody > tr')[0]; if(values){ // MAKE "ADD COLUMN" var addTable = $('create_table_template').cloneNode(true).setStyle({display:'block'}); addTable.select('input', 'select', 'textarea').each(function(fElem){ fElem.name = 'add_'+fElem.name; }); //addTable.select('td[edit="false"]').invoke('remove'); addTable.select('td[new="false"]')[0].setStyle({width:'40px'}); addRow = addTable.select('tbody tr')[0]; var addButton = new Element('input', {type:'button', value:'Add', className:'dialogButton'}); var submitDiv = new Element('div', {className:'dialogButtons'}).insert(addButton); var submitRow = new Element('tr').insert(new Element('td', {colspan:"9"}).insert(submitDiv)); addRow.insert({after:submitRow}); addButton.observe('click', function(e){ this.triggerAddColumn(); }.bind(this)); // MAKE ACTIONS templateTable.select('td[edit="false"]').invoke('remove'); templateRow.select('input', 'textarea', 'select').invoke('disable'); templateRow.setAttribute('enabled', 'false'); var activator = new Element('img', { src:ajxpResourcesFolder+'/images/crystal/actions/16/encrypted.png', height:'16', width:'16', border:'0', className:'enableRow', style:'cursor:pointer;' }); templateRow.select('td[new="false"]')[0].update(activator); // Additionnal actions var deleteCol = new Element('img', { src:ajxpResourcesFolder+'/images/crystal/actions/16/button_cancel.png', height:'16', width:'16', hspace:'5', border:'0', className:'deleteRow', style:'cursor:pointer;' }); activator.insert({before:deleteCol}); templateTable.observe('click', function(e){ if(e.findElement('img') && e.findElement('img').hasClassName('enableRow')){ var row = e.findElement('tr'); if(row.getAttribute('enabled') && row.getAttribute('enabled') == "true"){ row.select('input', 'textarea', 'select').invoke('disable'); row.setAttribute('enabled', 'false'); e.findElement('img').src=ajxpResourcesFolder+'/images/crystal/actions/16/encrypted.png'; }else{ row.select('input', 'textarea', 'select').invoke('enable'); row.setAttribute('enabled', 'true'); e.findElement('img').src=ajxpResourcesFolder+'/images/crystal/actions/16/decrypted.png'; } Event.stop(e); }else if(e.findElement('img') && e.findElement('img').hasClassName('deleteRow')){ var row = e.findElement('tr'); var origName = ''; row.select('input').each(function(input){ if(input.name.search('field_origname') > -1){ origName = input.value; return; } }); if(origName != ''){ var confirm = window.confirm('Are you sure you want to delete the column '+origName+'?'); if(confirm){ this.triggerDeleteColumn(origName); } } } }.bind(this)); }else{ templateTable.select('td[new="false"]').invoke('remove'); } if(addTable){ this.oForm.insert(this.createFieldSet('Add column', addTable)); this.oForm.insert(this.createFieldSet('Change columns (unlock to edit)', templateTable)); }else{ this.oForm.insert(this.createFieldSet('Step 2: Edit columns for table \"'+this.newTableName+'"', templateTable)); } var fManager = new FormManager(); fManager.replicateRow(templateRow, numberReplicates, this.oForm); if(fields && values){ fManager.fetchMultipleValueToForm(this.oForm, fields, values); } if(this.newTableName){ this.oForm.insert(new Element('input', {type:'hidden',name:'new_table',value:this.newTableName})); } modal.addSubmitCancel(this.oForm); this.oForm.onsubmit = function(){ var rows = this.oForm.select('tbody tr'); rows.each(function(row){ if(row.getAttribute('enabled')=='false') row.remove(); }); ajaxplorer.actionBar.submitForm(this.oForm); hideLightBox(); return false; }.bind(this); modal.refreshDialogPosition(true, templateTable); }, triggerDeleteColumn : function(columnName){ var currentTable = this.oForm.select('input[name="current_table"]')[0].value; var parameters = new Hash(); parameters.set('get_action', 'edit_table'); parameters.set('delete_column', columnName); parameters.set('current_table', currentTable); var connexion = new Connexion(); connexion.setParameters(parameters); connexion.onComplete = function(transport){ajaxplorer.actionBar.parseXmlMessage(transport.responseXML);}; connexion.sendAsync(); hideLightBox(); }, triggerAddColumn : function(){ var params = new Hash(); var currentTable = this.oForm.select('input[name="current_table"]')[0].value; params.set('get_action', 'edit_table'); params.set('add_column', 'true'); params.set('current_table', currentTable); this.oForm.select('input', 'textarea', 'select').each(function(elem){ if(elem.name.search("add_") == 0){ params.set(elem.name, elem.getValue()); } }); var connexion = new Connexion(); connexion.setParameters(params); connexion.onComplete = function(transport){ajaxplorer.actionBar.parseXmlMessage(transport.responseXML);}; connexion.sendAsync(); hideLightBox(); }, createFieldSet:function(legend, content){ var fSet = new Element('fieldset').insert(new Element('legend').update(legend)).insert(content); return fSet; }, parseXml : function(transport){ //alert(transport.responseText); this.changeModifiedStatus(false); this.removeOnLoad(); }, parseTxt : function(transport){ }, changeModifiedStatus : function(bModified){ this.modified = bModified; var crtTitle = modal.dialogTitle.select('span.titleString')[0]; if(this.modified){ this.saveButton.removeClassName('disabled'); if(crtTitle.innerHTML.charAt(crtTitle.innerHTML.length - 1) != "*"){ crtTitle.innerHTML = crtTitle.innerHTML + '*'; } }else{ this.saveButton.addClassName('disabled'); if(crtTitle.innerHTML.charAt(crtTitle.innerHTML.length - 1) == "*"){ crtTitle.innerHTML = crtTitle.innerHTML.substring(0, crtTitle.innerHTML.length - 1); } } // ADD / REMOVE STAR AT THE END OF THE FILENAME }, setOnLoad : function(){ addLightboxMarkupToElement(this.textareaContainer); var img = document.createElement("img"); img.src = ajxpResourcesFolder+"/images/loadingImage.gif"; $(this.textareaContainer).select("#element_overlay")[0].appendChild(img); this.loading = true; }, removeOnLoad : function(){ removeLightboxFromElement(this.textareaContainer); this.loading = false; }, close : function(){ if(this.currentUseCp){ this.cpCodeObject.close(); modal.clearContent(modal.dialogContent); } }, setFullScreen: function(){ this.oForm.absolutize(); $(document.body).insert(this.oForm); this.oForm.setStyle({ top:0, left:0, backgroundColor:'#fff', width:'100%', height:document.viewport.getHeight(), zIndex:3000}); this.actionBar.setStyle({marginTop: 0}); if(!this.currentUseCp){ this.origContainerHeight = this.textarea.getHeight(); this.heightObserver = fitHeightToBottom(this.textarea, this.oForm, 0, true); }else{ } var listener = this.fullScreenListener.bind(this); Event.observe(window, "resize", listener); this.oForm.observe("fullscreen:exit", function(e){ Event.stopObserving(window, "resize", listener); //Event.stopObserving(window, "resize", this.heightObserver); }.bind(this)); this.fullscreenMode = true; }, exitFullScreen: function(){ this.oForm.relativize(); $$('.dialogContent')[0].insert(this.oForm); this.oForm.setStyle({top:0,left:0,zIndex:100}); this.actionBar.setStyle({marginTop: -10}); this.oForm.fire("fullscreen:exit"); if(!this.currentUseCp){ this.textarea.setStyle({height:this.origContainerHeight}); }else{ } this.fullscreenMode = false; }, fullScreenListener : function(){ this.oForm.setStyle({ height:document.viewport.getHeight() }); if(!this.currentUseCp) {fitHeightToBottom(this.textarea, this.oForm, 0, true);} } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.Diaporama.js0000766000000000000000000002270011122202530025451 0ustar adminadministratorsvar DiaporamaFirstOccurence = true; Diaporama = Class.create({ fullscreenMode: false, initialize: function(div) { this.element = div; this.fullBox = this.element.select('div[id="diaporama_box"]')[0]; this.actionBar = this.fullBox.select('.action_bar')[0]; this.nextButton = div.select('a[id="nextButton"]')[0]; this.previousButton = div.select('a[id="prevButton"]')[0]; this.closeButton = div.select('a[id="closeButton"]')[0]; this.downloadButton = div.select('a[id="downloadDiapoButton"]')[0]; this.playButton = div.select('a[id="playButton"]')[0]; this.stopButton = div.select('a[id="stopButton"]')[0]; this.fsButton = div.select('a[id="fsButton"]')[0]; this.nofsButton = div.select('a[id="nofsButton"]')[0]; this.actualSizeButton = div.select('img[id="actualSizeButton"]')[0]; this.fitToScreenButton = div.select('img[id="fitToScreenButton"]')[0]; this.imgTag = div.select('img[id="mainImage"]')[0]; this.imgContainer = div.select('div[id="imageContainer"]')[0]; fitHeightToBottom(this.imgContainer, null, 5); this.zoomInput = div.select('input[id="zoomValue"]')[0]; this.timeInput = div.select('input[id="time"]')[0]; this.baseUrl = 'content.php?action=image_proxy&file='; this.nextButton.onclick = function(){ this.next(); this.updateButtons(); return false; }.bind(this); this.previousButton.onclick = function(){ this.previous(); this.updateButtons(); return false; }.bind(this); this.closeButton.onclick = function(){ if(this.fullscreenMode) this.exitFullScreen(); this.close(); hideLightBox(true); return false; }.bind(this); this.downloadButton.onclick = function(){ if(!this.currentFile) return; document.location.href = 'content.php?action=download&file='+this.currentFile; return false; }.bind(this); this.actualSizeButton.onclick = function(){ this.slider.setValue(100); this.resizeImage(true); }.bind(this); this.fitToScreenButton.onclick = function(){ this.toggleFitToScreen(); }.bind(this); this.playButton.onclick = function(){ this.play(); this.updateButtons(); return false; }.bind(this); this.stopButton.onclick = function(){ this.stop(); this.updateButtons(); return false; }.bind(this); this.fsButton.onclick = function(){ this.setFullScreen(); this.fsButton.hide(); this.nofsButton.show(); return false; }.bind(this); this.nofsButton.onclick = function(){ this.exitFullScreen(); this.nofsButton.hide(); this.fsButton.show(); return false; }.bind(this); modal.setCloseAction(this.close.bind(this)); this.imgTag.onload = function(){ this.resizeImage(true); this.downloadButton.removeClassName("disabled"); this.updateModalTitle(); }.bind(this); Event.observe(this.zoomInput, "keypress", function(e){ if(e == null) e = window.event; if(e.keyCode == Event.KEY_RETURN || e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN){ if(e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN) { var crtValue = parseInt(this.zoomInput.value); var value = (e.keyCode == Event.KEY_UP?(e.shiftKey?crtValue+10:crtValue+1):(e.shiftKey?crtValue-10:crtValue-1)); this.zoomInput.value = value; } this.slider.setValue(this.zoomInput.value); this.resizeImage(false); Event.stop(e); } return true; }.bind(this)); this.timeInput.observe('change', function(e){ if(this.slideShowPlaying && this.pe){ this.stop(); this.play(); } }.bind(this)); this.containerDim = $(this.imgContainer).getDimensions(); }, open : function(aFilesList, sCurrentFile) { var allItems = aFilesList; this.items = new Array(); this.sizes = new Hash(); $A(allItems).each(function(rowItem){ if(rowItem.getAttribute('is_image')=='1'){ this.items.push(rowItem.getAttribute('filename')); this.sizes.set(rowItem.getAttribute('filename'), {height:rowItem.getAttribute('image_height'), width:rowItem.getAttribute('image_width')}); } }.bind(this)); if(!sCurrentFile && this.items.length) sCurrentFile = this.items[0]; this.currentFile = sCurrentFile; var sliderDiv = this.element.select('div[id="slider-2"]')[0]; var sliderInput = this.element.select('input[id="slider-input-2"]')[0]; this.slider = new Slider(sliderDiv, sliderInput); this.slider.setMaximum(200); this.slider.setMinimum(10); this.slider.setValue(100); this.zoomInput.value = '100'; this.slider.recalculate(); this.slider.onchange = function(){ this.resizeImage(false); }.bind(this); this.updateImage(); this.updateButtons(); if(DiaporamaFirstOccurence){ /* $$(".action_bar a").each(function(el){ new Effect.Corner(el, "round 8px"); }); */ DiaporamaFirstOccurence = false; } }, updateModalTitle : function(){ var titleDiv = $(modal.dialogTitle); var crtTitle = titleDiv.select('span.titleString')[0]; var filenameSpans = crtTitle.select('span'); var text = ' - '+getBaseName(this.currentFile) + ' ('+this.sizes.get(this.currentFile).width+' X '+this.sizes.get(this.currentFile).height+')'; if(filenameSpans.length) filenameSpans[0].innerHTML = text; else { newSpan = document.createElement('span'); newSpan.appendChild(document.createTextNode(text)); crtTitle.appendChild(newSpan); } }, resizeImage : function(morph){ if(this.autoFit){ this.computeFitToScreenFactor(); } var nPercent = this.slider.getValue(); this.zoomInput.value = nPercent; var height = parseInt(nPercent*this.crtHeight / 100); var width = parseInt(nPercent*this.crtWidth / 100); // Center vertically var margin=0; if (height < this.containerDim.height){ var margin = parseInt((this.containerDim.height - height) / 2)-5; } if(morph){ new Effect.Morph(this.imgTag,{ style:{height:height+'px', width:width+'px',margin:margin+'px'}, duration:0.5 }); }else{ this.imgTag.setStyle({height:height+'px', width:width+'px',margin:margin+'px'}); } }, setFullScreen: function(){ this.fullBox.absolutize(); $(document.body).insert(this.fullBox); this.fullBox.setStyle({ top:0, left:0, backgroundColor:'#fff', width:'100%', height:document.viewport.getHeight(), zIndex:3000}); this.actionBar.setStyle({marginTop: 0}); this.origContainerHeight = this.imgContainer.getHeight(); var listener = this.fullScreenListener.bind(this); Event.observe(window, "resize", listener); this.fullBox.observe("fullscreen:exit", function(e){ Event.stopObserving(window, "resize", listener); }); fitHeightToBottom(this.imgContainer, this.fullBox); this.fullscreenMode = true; this.resizeImage(); }, exitFullScreen: function(){ this.fullBox.relativize(); $(this.element).insert(this.fullBox); this.fullBox.setStyle({top:0,left:0,zIndex:100}); this.actionBar.setStyle({marginTop: -10}); this.fullBox.fire("fullscreen:exit"); this.imgContainer.setStyle({height:this.origContainerHeight}); this.fullscreenMode = false; this.resizeImage(); }, fullScreenListener : function(){ this.fullBox.setStyle({ height:document.viewport.getHeight() }); }, updateImage : function(){ var dimObject = this.sizes.get(this.currentFile); this.crtHeight = dimObject.height; this.crtWidth = dimObject.width; this.crtRatio = this.crtHeight / this.crtWidth; this.downloadButton.addClassName("disabled"); this.imgTag.src = this.baseUrl + this.currentFile; }, fitToScreen : function(){ this.computeFitToScreenFactor(); this.resizeImage(true); }, computeFitToScreenFactor: function(){ zoomFactor1 = parseInt(this.imgContainer.getHeight() / this.crtHeight * 100); zoomFactor2 = parseInt(this.imgContainer.getWidth() / this.crtWidth * 100); this.slider.setValue(Math.min(zoomFactor1, zoomFactor2)-1); }, toggleFitToScreen:function(){ if(this.autoFit){ this.autoFit = false; this.fitToScreenButton.removeClassName('diaporamaButtonActive'); }else{ this.autoFit = true; this.fitToScreenButton.addClassName('diaporamaButtonActive'); this.fitToScreen(); } }, close : function(){ this.currentFile = null; this.items = null; this.imgTag.src = ''; this.stop(); if(this.fullscreenMode) this.exitFullScreen(); }, play: function(){ if(!this.timeInput.value) this.timeInput.value = 3; this.pe = new PeriodicalExecuter(this.next.bind(this), parseInt(this.timeInput.value)); this.slideShowPlaying = true; }, stop: function(){ if(this.pe) this.pe.stop(); this.slideShowPlaying = false; }, next : function(){ if(this.currentFile != this.items.last()) { this.currentFile = this.items[this.items.indexOf(this.currentFile)+1]; this.updateImage(); } else if(this.slideShowPlaying){ this.currentFile = this.items[0]; this.updateImage(); } }, previous : function(){ if(this.currentFile != this.items.first()) { this.currentFile = this.items[this.items.indexOf(this.currentFile)-1]; this.updateImage(); } }, updateButtons : function(){ if(this.slideShowPlaying){ this.previousButton.addClassName("disabled"); this.nextButton.addClassName("disabled"); this.playButton.addClassName("disabled"); this.stopButton.removeClassName("disabled"); }else{ if(this.currentFile == this.items.first()) this.previousButton.addClassName("disabled"); else this.previousButton.removeClassName("disabled"); if(this.currentFile == this.items.last()) this.nextButton.addClassName("disabled"); else this.nextButton.removeClassName("disabled"); this.playButton.removeClassName("disabled"); this.stopButton.addClassName("disabled"); } } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.AjxpAutoCompleter.js0000766000000000000000000000423111122202530027161 0ustar adminadministratorsAjxpAutocompleter = Class.create(Autocompleter.Base, { initialize: function(element, update, url, options) { this.baseInitialize(element, update, options); this.options.asynchronous = true; this.options.onComplete = this.onComplete.bind(this); this.options.defaultParams = this.options.parameters || null; this.url = ajxpServerAccessPath+"?get_action=ls&mode=complete"; this.options.paramName = "dir"; this.options.minChars = 1; //this.options.callback = this.parseValueBeforeSending.bind(this); }, getUpdatedChoices: function() { this.startIndicator(); var value = this.getToken(); var entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(value.substring(0, value.lastIndexOf("/")+1)); this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry; if(this.options.defaultParams) this.options.parameters += '&' + this.options.defaultParams; new Ajax.Request(this.url, this.options); }, onComplete: function(request) { var oXmlDoc = request.responseXML; var token = this.getToken(); var dirs = new Array(); if( oXmlDoc == null || oXmlDoc.documentElement == null) { this.updateChoices(''); return; } var root = oXmlDoc.documentElement; // loop through all tree children var cs = root.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i].tagName == "tree") { var text = cs[i].getAttribute("text"); var hasCharAfterSlash = (token.lastIndexOf("/")'; }); responseText += ''; this.updateChoices(responseText); } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.InfoPanel.js0000766000000000000000000001561611122202530025437 0ustar adminadministratorsInfoPanel = Class.create({ initialize: function(htmlElement){ this.htmlElement = $(htmlElement); this.setContent('

    '+MessageHash[132]+'
    '); this.mimesTemplates = new Hash(); this.registeredMimes = new Hash(); }, setTemplateForMime: function(mimeType, templateString, attributes, messages){ var tId = this.mimesTemplate.size(); this.registeredMimes.set(mimeType, tId); this.mimesTemplates.push($A([templateString,attributes, messages])); }, clearPanels:function(){ this.mimesTemplates = new Hash(); this.registeredMimes = new Hash(); }, update : function(){ var filesList = ajaxplorer.getFilesList(); var userSelection = filesList.getUserSelection(); if(userSelection.isEmpty()) { var currentRep = getBaseName(filesList.getCurrentRep()); if(currentRep == ""){ currentRep = $('repo_path').value; } var items = filesList.getItems(); var size = 0; var folderNumber = 0; var filesNumber = 0; for(var i=0;i
    '+ userSelection.getFileNames().length + ' '+MessageHash[128]+'


    '); this.addActions('multiple'); return; } var uniqItem = userSelection.getUniqueItem(); if(uniqItem.getAttribute('is_file')=='0'){ this.evalTemplateForMime('generic_dir', uniqItem); } else{ var extension = getFileExtension(uniqItem.getAttribute('filename')); if(this.registeredMimes.get(extension)){ this.evalTemplateForMime(extension, uniqItem); } else{ this.evalTemplateForMime('generic_file', uniqItem); } } }, setContent : function(sHtml){ this.htmlElement.update(sHtml); }, evalTemplateForMime: function(mimeType, fileData, tArgs){ if(!this.registeredMimes.get(mimeType)) return; var templateData = this.mimesTemplates.get(this.registeredMimes.get(mimeType)); var tString = templateData[0]; var tAttributes = templateData[1]; var tMessages = templateData[2]; if(!tArgs){ tArgs = new Object(); } if(fileData){ tAttributes.each(function(attName){ if(attName == 'basename' && fileData.getAttribute('filename')){ this[attName] = getBaseName(fileData.getAttribute('filename')); } else if(attName == 'compute_image_dimensions'){ if(fileData.getAttribute('image_width') && fileData.getAttribute('image_height')){ var width = fileData.getAttribute('image_width'); var height = fileData.getAttribute('image_height'); var newHeight = 150; if(height < newHeight) newHeight = height; var newWidth = newHeight*width/height; var dimAttr = 'height="'+newHeight+'"'; if(newWidth > $('info_panel').getWidth() - 16) dimAttr = 'width="100%"'; }else{ dimAttr = 'height="64" width="64"'; } this[attName] = dimAttr; } else if(attName == 'encoded_filename' && fileData.getAttribute('filename')){ this[attName] = escape(encodeURI(fileData.getAttribute('filename'))); } else if(attName == 'uri'){ var url = document.location.href; if(url.indexOf('/#') > -1){ url = url.substr(0, url.indexOf('#')); } if(url[(url.length-1)] == '/'){ url = url.substr(0, url.length-1); } this[attName] = url; } else if(fileData.getAttribute(attName)){ this[attName] = fileData.getAttribute(attName); } else{ this[attName] = ''; } }.bind(tArgs)); } tMessages.each(function(pair){ this[pair.key] = MessageHash[pair.value]; }.bind(tArgs)); var template = new Template(tString); this.setContent(template.evaluate(tArgs)); this.addActions('unique'); }, addActions: function(selectionType){ var actions = ajaxplorer.actionBar.getInfoPanelActions(); var actionString = '
    '; var count = 0; actions.each(function(action){ if(selectionType == 'multiple' && action.selectionContext.unique) return; if(selectionType == 'unique' && (!action.context.selection || action.selectionContext.multipleOnly)) return; //if(count > 0) actionString += ' | '; actionString += ' '+action.options.title+''; count++; }.bind(this)); actionString += '
    '; this.htmlElement.insert(actionString); }, load: function(){ var connexion = new Connexion(); connexion.addParameter('get_action', 'get_driver_info_panels'); connexion.onComplete = function(transport){ this.parseXML(transport.responseXML); }.bind(this); this.clearPanels(); connexion.sendSync(); }, parseXML: function(xmlResponse){ if(xmlResponse == null || xmlResponse.documentElement == null) return; var childs = xmlResponse.documentElement.childNodes; if(!childs.length) return; var panels = childs[0].childNodes; for(var i = 0; i '+title+''; this.currentCount++; }, clear: function(){ this.currentCount = 0; this.bookmarks = $A([]); $('bm_goto_button').addClassName('disabled'); }, setContextualMenu:function(oMenu){ this.contextMenu = oMenu; }, findBookmarkEventSource:function(srcElement){ for(var i=0; i'+ oUser.id+' '; if(oUser.getPreference('lang') != null && oUser.getPreference('lang') != "" && oUser.getPreference('lang') != ajaxplorer.currentLanguage) { ajaxplorer.loadI18NMessages(oUser.getPreference('lang')); } } else { logging_string = ''+MessageHash[143]+''; } } else { logging_string = ''+MessageHash[144]+''; } $('logging_string').innerHTML = logging_string; if(oUser != null) { disp = oUser.getPreference("display"); if(disp && (disp == 'thumb' || disp == 'list')) { if(disp != ajaxplorer.filesList._displayMode) ajaxplorer.filesList.switchDisplayMode(disp); } } this.loadBookmarks(); }, displayUserPrefs: function() { if(ajaxplorer.user == null) return; var userLang = ajaxplorer.user.getPreference("lang"); var userDisp = ajaxplorer.user.getPreference("display"); var onLoad = function(){ var elements = $('user_pref_form').getElementsBySelector('input[type="radio"]'); elements.each(function(elem){ elem.checked = false; if(elem.id == 'display_'+userDisp || elem.id == 'lang_'+userLang) { elem.checked = true; } }); $('user_change_ownpass_old').value = $('user_change_ownpass1').value = $('user_change_ownpass2').value = ''; }; var onComplete = function(){ var elements = $('user_pref_form').getElementsBySelector('input[type="radio"]'); elements.each(function(elem){ if(elem.checked){ ajaxplorer.user.setPreference(elem.name, elem.value); } }); var userOldPass = null; var userPass = null; if($('user_change_ownpass1') && $('user_change_ownpass1').value != "" && $('user_change_ownpass2').value != "") { if($('user_change_ownpass1').value != $('user_change_ownpass2').value){ alert(MessageHash[238]); return false; } if($('user_change_ownpass_old').value == ''){ alert(MessageHash[239]); return false; } userPass = $('user_change_ownpass1').value; userOldPass = $('user_change_ownpass_old').value; } var onComplete = function(transport){ var oUser = ajaxplorer.user; if(oUser.getPreference('lang') != null && oUser.getPreference('lang') != "" && oUser.getPreference('lang') != ajaxplorer.currentLanguage) { ajaxplorer.loadI18NMessages(oUser.getPreference('lang')); } if(userPass != null){ if(transport.responseText == 'PASS_ERROR'){ alert(MessageHash[240]); }else if(transport.responseText == 'SUCCESS'){ ajaxplorer.displayMessage('SUCCESS', MessageHash[197]); hideLightBox(true); } }else{ ajaxplorer.displayMessage('SUCCESS', MessageHash[241]); hideLightBox(true); } }; ajaxplorer.user.savePreferences(userOldPass, userPass, onComplete); return false; }; modal.prepareHeader(MessageHash[195], ajxpResourcesFolder+'/images/crystal/actions/16/configure.png'); modal.showDialogForm('Preferences', 'user_pref_form', onLoad, onComplete); }, getContextActions: function(srcElement) { var actionsSelectorAtt = 'selectionContext'; if(srcElement.id && (srcElement.id == 'table_rows_container' || srcElement.id == 'selectable_div')) { actionsSelectorAtt = 'genericContext'; } else if(srcElement.id.substring(0,5)=='webfx') { actionsSelectorAtt = 'directoryContext'; } else { // find the bookmark origin var bm = this.bookmarksBar.findBookmarkEventSource(srcElement); if(bm != null){ return this.bookmarksBar.getContextActions(bm); } }; var contextActions = new Array(); var crtGroup; this.actions.each(function(pair){ var action = pair.value; if(!action.context.contextMenu) return; if(actionsSelectorAtt == 'selectionContext' && !action.context.selection) return; if(actionsSelectorAtt == 'directoryContext' && !action.context.dir) return; if(actionsSelectorAtt == 'genericContext' && action.context.selection) return; if(action.contextHidden || action.deny) return; if(crtGroup && crtGroup != action.context.actionBarGroup){ contextActions.push({separator:true}); } var isDefault = false; if(actionsSelectorAtt == 'selectionContext'){ // set default in bold var userSelection = ajaxplorer.getFilesList().getUserSelection(); if(!userSelection.isEmpty()){ var defaultAction = 'file'; if(userSelection.isUnique() && userSelection.hasDir()){ defaultAction = 'dir'; } if(this.defaultActions.get(defaultAction) && action.options.name == this.defaultActions.get(defaultAction)){ isDefault = true; } } } contextActions.push({ name:action.getKeyedText(), alt:action.options.title, image:ajxpResourcesFolder+'/images/crystal/actions/16/'+action.options.src, isDefault:isDefault, callback:function(e){this.apply()}.bind(action) }); crtGroup = action.context.actionBarGroup; }.bind(this)); return contextActions; }, getInfoPanelActions:function(){ var actions = $A([]); this.actions.each(function(pair){ var action = pair.value; if(action.context.infoPanel && !action.deny) actions.push(action); }); return actions; }, fireDefaultAction: function(defaultName){ var actionName = this.defaultActions.get(defaultName); if(actionName != null){ arguments[0] = actionName; if(actionName == "ls"){ var action = this.actions.get(actionName); if(action) action.enable(); // Force enable on default action } this.fireAction.apply(this, arguments); } }, fireAction: function (buttonAction) { var action = this.actions.get(buttonAction); if(action != null) { var args = $A(arguments); args.shift(); action.apply(args); return; } }, registerKey: function(key, actionName){ this._registeredKeys.set(key.toLowerCase(), actionName); }, clearRegisteredKeys: function(){ this._registeredKeys = new Hash(); }, fireActionByKey: function(event, keyName) { if(this._registeredKeys.get(keyName) && !ajaxplorer.blockShortcuts) { this.fireAction(this._registeredKeys.get(keyName)); Event.stop(event); } return; }, applyDragMove: function(fileName, destDir, destNodeName, copy) { if((!copy && !this.defaultActions.get('dragndrop')) || (copy && (!this.defaultActions.get('ctrldragndrop')||this.getDefaultAction('ctrldragndrop').deny))){ return; } if(fileName == null) fileNames = ajaxplorer.filesList.getUserSelection().getFileNames(); else fileNames = [fileName]; if(destNodeName != null) { // Check that dest is not a child of the source if(this.checkDestIsChildOfSource(fileNames, destNodeName)){ ajaxplorer.displayMessage('ERROR', MessageHash[202]); return; } // Check that dest is not the source it self for(var i=0; i'; this.panel.update(imgString+' '+actionDef.get('messageId')); this.panel.show(); new Effect.Corner(this.panel, "round 8px bl"); new Effect.Corner(this.panel, "round 8px tl"); this.queue.shift(); this.working = true; }, parseAnswer:function(xmlResponse){ var childs = xmlResponse.documentElement.childNodes; for(var i=0; i 0){ this.openCurrentAndGoToNext(this.currentDeepPath[0]); } return false; }, cleanPathToArray: function(url){ var splitPath = url.split("/"); var path = new Array(); var j = 0; for(i=0; i 1) return split[split.length-1].toLowerCase(); return ''; } function editWithCodePress(fileName) { if(Prototype.Browser.WebKit) return ""; if(fileName.search('\.php$|\.php3$|\.php5$|\.phtml$') > -1) return "php"; else if (fileName.search("\.js$") > -1) return "javascript"; else if (fileName.search("\.java$") > -1) return "java"; else if (fileName.search("\.pl$") > -1) return "perl"; else if (fileName.search("\.sql$") > -1) return "sql"; else if (fileName.search("\.htm$|\.html$|\.xml$") > -1) return "html"; else if (fileName.search("\.css$") > -1) return "css"; else return ""; } function roundSize(filesize, size_unit){ if (filesize >= 1073741824) {filesize = Math.round(filesize / 1073741824 * 100) / 100 + " G"+size_unit;} else if (filesize >= 1048576) {filesize = Math.round(filesize / 1048576 * 100) / 100 + " M"+size_unit;} else if (filesize >= 1024) {filesize = Math.round(filesize / 1024 * 100) / 100 + " K"+size_unit;} else {filesize = filesize + " "+size_unit;} return filesize; } function storeRememberData(user, pass){ var cookieJar = new CookieJar({ expire: 3600*24*10, path: '', secure: true }); cookieJar.put('ajxp_remember', {user:user, pass:pass}); } function retrieveRememberData(){ var cookieJar = new CookieJar({}); return cookieJar.get('ajxp_remember'); } function clearRememberData(){ var cookieJar = new CookieJar({}); cookieJar.remove('ajxp_remember'); } function refreshPNGImages(element){ if(element.getAttribute('is_image') && element.getAttribute('is_image')=='1'){ return element; } var imgs = $(element).getElementsBySelector('img'); if(imgs.length) imgs.each(function(img){ if(img.original_src) img.src = img.original_src; }); return element; } var messageDivOpen = false; function closeMessageDiv() { if(messageDivOpen) { new Effect.BlindUp('message_div'); messageDivOpen = false; } } function tempoMessageDivClosing() { messageDivOpen = true; setTimeout('closeMessageDiv()', 10000); } function disableTextSelection(target) { if (typeof target.onselectstart!="undefined") { //IE route target.onselectstart=function(){return false;} } else if (typeof target.style.MozUserSelect!="undefined") { //Firefox route var defaultValue = target.style.MozUserSelect; target.style.MozUserSelect="none"; } if($(target).getElementsBySelector('input[type="text"]').length) { $(target).getElementsBySelector('input[type="text"]').each(function(element) { if (typeof element.onselectstart!="undefined") { //IE route element.onselectstart=function(){return true;} } else if (typeof element.style.MozUserSelect!="undefined") { //Firefox route element.style.MozUserSelect=defaultValue; } }); } } function fitHeightToBottom(element, parentElement, addMarginBottom, skipListener) { element = $(element); if(typeof(parentElement) == "undefined" || parentElement == null){ parentElement = Position.offsetParent($(element)); }else{ parentElement = $(parentElement); } if(typeof(addMarginBottom) == "undefined" || addMarginBottom == null){ addMarginBottom = 0; } var observer = function(){ if(!element) return; var top =0; if(parentElement == window){ offset = element.cumulativeOffset(); top = offset.top; }else{ offset1 = parentElement.cumulativeOffset(); offset2 = element.cumulativeOffset(); top = offset2.top - offset1.top; } var wh; if(parentElement == window){ wh = document.viewport.getHeight(); }else{ wh = parentElement.getHeight(); if(Prototype.Browser.IE && parentElement.getStyle('height')){ wh = parseInt(parentElement.getStyle('height')); } } var mrg = parseInt(element.getStyle('marginBottom')) ||0; var brd = parseInt(element.getStyle('borderWidth'))||0; var pad = parseInt((parentElement!=window?parentElement.getStyle('paddingBottom'):0))||0; element.setStyle({height:(Math.max(0,wh-top-mrg-brd-addMarginBottom))+'px'}); element.fire("resize"); }; observer(); if(!skipListener){ Event.observe(window, 'resize', observer); } return observer; } function ajxpCorners(oElement, cornersString) { var tr, tl, bl, br; if(cornersString == null) { tr = tl = bl = br; } else { tr = (cornersString=='top'||cornersString=='tr'); tl = (cornersString=='top'||cornersString=='tl'); bl = (cornersString=='bottom'||cornersString=='bl'); br = (cornersString=='bottom'||cornersString=='br'); } if(br || bl) { var botDiv = new Element('div'); botDiv.setStyle({marginTop:'-5px', zoom:1, width:'100%'}); botDiv.innerHTML = (bl?'
    ':'')+(br?'
    ':''); oElement.appendChild(botDiv); } if(tr || tl) { var topDiv = new Element('div'); topDiv.setStyle({marginBottom:'-5px', zoom:1, width:'100%'}); topDiv.innerHTML = (tl?'
    ':'')+(tr?'
    ':''); if(oElement.firstChild) { oElement.insertBefore(topDiv, oElement.firstChild); } else { oElement.appendChild(topDiv); } } }AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.AjxpDraggable.js0000766000000000000000000001703211122202530026251 0ustar adminadministrators// TO ADD GLOBALLY var timerClearObserver = { onEnd:function(){ if(WebFXtimer) clearTimeout(WebFXtimer); } } ; Event.observe(window, "load", function(){ Draggables.addObserver(timerClearObserver); Draggables.addObserver({onDrag:function(eventName,element,event){ if(element.updateCtrlKey){ element.updateCtrlKey(event); } }}); }); Event.observe(window, "unload", function(){ Draggables.removeObserver(timerClearObserver); if(ajaxplorer){ ajaxplorer.filesList.allDraggables.each(function(el){ el.destroy(); }); ajaxplorer.filesList.allDroppables.each(function(el){ Droppables.remove(el); }); } }); var AjxpDraggable = Class.create(Draggable, { initialize: function($super, element, options){ $(element).addClassName('ajxp_draggable'); $super(element, options); }, startDrag : function(event){ if(!this.delta) this.delta = this.currentDelta(); this.dragging = true; this._draggingMultiple = false; if(this.options.zindex) { this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); this.element.style.zIndex = this.options.zindex; } if(this.options.ghosting) { var selection = ajaxplorer.filesList.getUserSelection(); //console.log(selection); if(selection.isMultiple()){ // Move all selection // Make new div for element, clone all others. this._draggingMultiple = true; this._clone = document.createElement('div'); $(this._clone).addClassName("ajxp_draggable"); if(ajaxplorer.filesList._displayMode == 'thumb'){ $(this._clone).addClassName('multiple_thumbnails_draggable'); }else{ $(this._clone).addClassName('multiple_selection_draggable'); } this._clone.setAttribute('user_selection', 'true'); if (Prototype.Browser.IE || Prototype.Browser.Opera){ $('browser').appendChild(this._clone); $(this._clone).setStyle({width:$(this.element).getWidth()+'px'}); }else{ this.element.parentNode.appendChild(this._clone); } this.original = this.element; this.element = this._clone; var selectedItems = ajaxplorer.filesList.getSelectedItems(); for(var i=0; i'+dOpt.get('label') + ' : ' + dOpt.get('description')+'
    '); dOpt.get('params').each(function(param){ var label = param.get('label'); var name = param.get('name'); var type = param.get('type'); var desc = param.get('description'); var mandatory = false; if(param.get('mandatory') && param.get('mandatory')=='true') mandatory = true; var defaultValue = param.get('default') || ""; var element; if(type == 'string'){ element = ''; }else if(type == 'boolean'){ var selectTrue, selectFalse; if(defaultValue){ if(defaultValue == "true") selectTrue = true; if(defaultValue == "false") selectFalse = true; } element = ' Yes'; element = element + ' No'; } var div = new Element('div', {style:"padding:2px; clear:left"}).update('
    '+label+(mandatory?'*':'')+' : 
    '+element+'  '+desc+'
    '); $('driver_form').insert({'bottom':div}); }); var buttons = '
    '; $('driver_form').insert({'bottom':buttons}); }, repoButtonClick : function(validate){ if(!validate) { $('driver_label').value = ''; $('drivers_selector').selectedIndex = 0; this.driverSelectorChange(); return false; } var toSubmit = new Hash(); var missingMandatory = false; if($('driver_label').value == ''){ missingMandatory = true; }else{ toSubmit.set('DISPLAY', $('driver_label').value); } toSubmit.set('DRIVER', $('drivers_selector').options[$('drivers_selector').selectedIndex].value); $('driver_form').select('input').each(function(el){ if(el.type == "text"){ if(el.getAttribute('ajxp_mandatory') == 'true' && el.value == ''){ missingMandatory = true; } toSubmit.set('DRIVER_OPTION_'+el.name, el.value); } else if(el.type=="radio" && el.checked){ toSubmit.set('DRIVER_OPTION_'+el.name, el.value) }; }); if(missingMandatory){ this.displayMessage("ERROR", "Mandatory fields are missing!"); return false; } this.submitForm('create_repository', toSubmit, null, function(){ this.repoButtonClick(false); this.loadRepList(); this.loadUsers(); }.bind(this)); return false; }, loadRepList : function(){ this.submitForm('repository_list', new Hash()); }, updateRepList : function(){ if(!this.repositories) return; $('repo_list').update(''); this.repositories.each(function(pair){ var deleteButton = ''; if(pair.value){ deleteButton = ''; } $('repo_list').insert({"bottom":'
    Repository '+pair.key+''+deleteButton+'
    '}); }); }, deleteRepository : function(repLabel){ var params = new Hash(); params.set('repo_label', repLabel); this.submitForm('delete_repository', params, null, function(){ this.loadRepList(); this.loadUsers(); }.bind(this)); }, loadLogList : function(){ this.submitForm('list_logs', new Hash()); }, updateLogsSelector : function(){ var selector = $('log_selector'); if(!this.logFiles || !selector) return; this.logFiles.each(function(pair){ var option = new Element('option'); option.setAttribute('value', pair.key); option.update(pair.value); selector.insert({'top':option}); }); selector.onchange = this.logSelectorChange.bind(this); // Select first selector.selectedIndex = 0; this.logSelectorChange(); }, logSelectorChange : function(){ if($('log_selector').getValue()) this.loadLogs($('log_selector').getValue()); }, loadLogs : function(date){ var param = new Hash(); param.set('date', date); this.submitForm('read_log', param, null, this.updateLogBrowser.bind(this)); }, updateLogBrowser : function(xmlResponse){ if(xmlResponse == null || xmlResponse.documentElement == null) return; browser = $('log_browser'); var childs = xmlResponse.documentElement.childNodes; this.even = true; var table = new Element('table', {width:'100%', className:'logs_table',cellPadding:'0',cellSpacing:'1'}); browser.update(table); this.insertRow(table, ["Date","IP","Level","User", "Action", "Parameters"], true); for(var i=0;i1 && i%8==0){ this.insertRow(table, ["Date","IP","Level","User", "Action", "Parameters"], true); } } var transp = new Element('div'); browser.insert({'bottom':transp}); browser.scrollTop = transp.offsetTop; }, insertRow : function(table, values, isHeader){ var tdSt = ''; var className=""; if(!isHeader && !this.even){className="odd"}; this.even = !this.even; values.each(function(cell){ if(cell){ while(cell.indexOf(';')>-1) cell = cell.replace(';', '
    '); while(cell.indexOf(',')>-1) cell = cell.replace(',', '
    '); tdSt = tdSt + ''+cell+''; } }); tsSt = tdSt+''; table.insert({'bottom':tdSt}); }, changeUserRight: function(oChckBox, userId, repositoryId, rightName){ var changedBox = rightName; var newState = oChckBox.checked; oChckBox.checked = !oChckBox.checked; oChckBox.disabled = true; var rightString; if(rightName == 'read') { $('chck_'+userId+'_'+repositoryId+'_write').disabled = true; rightString = (newState?'r':''); } else { $('chck_'+userId+'_'+repositoryId+'_read').disabled = true; rightString = (newState?'rw':($('chck_'+userId+'_'+repositoryId+'_read').checked?'r':'')); } var parameters = new Hash(); parameters.set('user_id', userId); parameters.set('repository_id', repositoryId); parameters.set('right', rightString); this.submitForm('update_user_right', parameters, null); }, changePassword: function(userId){ var newPass = $('new_pass_'+userId); var newPassConf = $('new_pass_confirm_'+userId); if(newPass.value == '') return; if(newPass.value != newPassConf.value){ this.displayMessage('ERROR', 'Warning, password and confirmation differ!'); return; } parameters = new Hash(); parameters.set('user_id', userId); parameters.set('user_pwd', newPass.value); this.submitForm('update_user_pwd', parameters, null); newPass.value = ''; newPassConf.value = ''; }, createUser: function (){ var login = $('new_user_login'); var pass = $('new_user_pwd'); var passConf = $('new_user_pwd_conf'); if(login.value == ''){ this.displayMessage("ERROR", "Please fill the login field!"); return; } if(pass.value == '' || passConf.value == ''){ this.displayMessage("ERROR", "Please fill both password fields!"); return; } if(pass.value != passConf.value){ this.displayMessage("ERROR", "Password and confirmation differ!"); return; } var parameters = new Hash(); parameters.set('new_login', login.value); parameters.set('new_pwd', pass.value); this.submitForm('create_user', parameters, null); login.value = pass.value = passConf.value = ''; return; }, deleteUser: function(userId){ var chck = $('delete_confirm_'+userId); if(!chck.checked){ this.displayMessage("ERROR", "Please check the box to confirm!"); return; } parameters = new Hash(); parameters.set('user_id', userId); this.submitForm('delete_user', parameters, null); chck.checked = false; }, toggleUser: function (userId){ var color; if($('user_data_'+userId).visible()) { // closing color = "#fff"; border = "#fff"; } else { // opening $$('div.user').each(function(element){ element.setStyle({ backgroundColor:"#fff", borderColor: "#fff" }); }); $$('div.user_data').each(function(element){ element.hide(); }); color = "#ddd"; border = "#bbb"; } $('user_block_'+userId).setStyle({ backgroundColor:color, borderColor: border }); //$('user_data_'+userId).toggle(); $('users_detail_panel').insert({top:$('user_data_'+userId)}); $('user_data_'+userId).toggle(); }, submitForm: function(action, parameters, formName, callback){ var connexion = new Connexion('admin.php'); if(formName) { $(formName).getElements().each(function(fElement){ connexion.addParameter(fElement.name, fElement.getValue()); }); } if(parameters) { parameters.set('get_action', action); connexion.setParameters(parameters); } if(!callback){ connexion.onComplete = function(transport){this.parseXmlMessage(transport.responseXML);}.bind(this); }else{ connexion.onComplete = function(transport){ this.parseXmlMessage(transport.responseXML); callback(transport.responseXML); }.bind(this); } connexion.sendAsync(); }, loadHtmlToDiv: function(div, parameters, completeFunc){ var connexion = new Connexion('admin.php'); parameters.each(function(pair){ connexion.addParameter(pair.key, pair.value); }); connexion.onComplete = function(transport){ $(div).update(transport.responseText); if(completeFunc) completeFunc(); }; connexion.sendAsync(); }, parseXmlMessage: function(xmlResponse){ //var messageBox = ajaxplorer.messageBox; if(xmlResponse == null || xmlResponse.documentElement == null) return; var childs = xmlResponse.documentElement.childNodes; var driversList = false; var driversAtts = $A(['name', 'type', 'label', 'description', 'default', 'mandatory']); var repList = false; var logFilesList = false; var logsList = false; for(var i=0; i"); if(messageType == "ERROR"){ this.messageBox.removeClassName('logMessage'); this.messageBox.addClassName('errorMessage');} else { this.messageBox.removeClassName('errorMessage'); this.messageBox.addClassName('logMessage');} $('message_content').innerHTML = message; this.messageBox.style.top = '80%'; this.messageBox.style.left = '60%'; this.messageBox.style.width = '30%'; new Effect.Corner(this.messageBox,"round"); new Effect.Appear(this.messageBox); this.tempoMessageDivClosing(); } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.Modal.js0000766000000000000000000002202511122202530024610 0ustar adminadministratorsModal = Class.create({ pageLoading: true, initialize: function(){ }, initForms: function(){ this.elementName = 'generic_dialog_box'; this.htmlElement = $(this.elementName); this.dialogTitle = this.htmlElement.getElementsBySelector(".dialogTitle")[0]; this.dialogContent = this.htmlElement.getElementsBySelector(".dialogContent")[0]; this.currentForm; this.cachedForms = new Hash(); this.iframeIndex = 0; }, prepareHeader: function(sTitle, sIconSrc){ var hString = ""; if(sIconSrc != "") hString = " "; hString += sTitle + ''; this.dialogTitle.innerHTML = hString; }, showDialogForm: function(sTitle, sFormId, fOnLoad, fOnComplete, fOnCancel, bOkButtonOnly, skipButtons){ this.clearContent(this.dialogContent); //this.dialogTitle.innerHTML = sTitle; var newForm; if($(sFormId).tagName == 'FORM') // WE PASSED A PREFETCHED HIDDEN FORM { newForm = $(sFormId); newForm.show(); } else { var formDiv = $(sFormId); //var formDiv = $('all_forms').select('[id="'+sFormId+'"]')[0]; var newForm = document.createElement('form'); newForm.id = 'modal_action_form'; newForm.setAttribute('name','modal_action_form'); newForm.setAttribute('action', 'cont.php'); newForm.appendChild(formDiv.cloneNode(true)); var reloadIFrame = null; if($(newForm).getElementsByTagName("iframe")[0]) { reloadIFrame = $(newForm).getElementsByTagName("iframe")[0]; reloadIFrameSrc = $(newForm).getElementsByTagName("iframe")[0].getAttribute("src"); } if(formDiv.getAttribute('action')) { var actionField = document.createElement('input'); actionField.setAttribute('type', 'hidden'); actionField.setAttribute('name', 'get_action'); actionField.setAttribute('value', formDiv.getAttribute('action')); newForm.appendChild(actionField); } } if(!this.cachedForms.get(sFormId) && !skipButtons){ this.addSubmitCancel(newForm, fOnCancel, bOkButtonOnly); } this.dialogContent.appendChild(newForm); if(fOnComplete) { newForm.onsubmit = function(){ try{ fOnComplete(); }catch(e){ alert('Unexpected Error : please report!\n'+e); } return false; } } else { newForm.onsubmit = function(){ ajaxplorer.actionBar.submitForm(modal.getForm()); hideLightBox(); return false; }; } this.showContent(this.elementName, $(sFormId).getAttribute("box_width"), $(sFormId).getAttribute("box_height")); if($(newForm).getElementsBySelector(".dialogFocus").length) { objToFocus = $(newForm).getElementsBySelector(".dialogFocus")[0]; setTimeout('objToFocus.focus()', 500); } if($(newForm).getElementsBySelector(".replace_rep").length) { repDisplay = $(newForm).getElementsBySelector(".replace_rep")[0]; repDisplay.innerHTML = ajaxplorer.filesList.getCurrentRep(); } if($(newForm).getElementsBySelector(".replace_file").length) { repDisplay = $(newForm).getElementsBySelector(".replace_file")[0]; repDisplay.innerHTML = getBaseName(ajaxplorer.filesList.getUserSelection().getUniqueFileName()); } this.currentForm = newForm; if(fOnLoad != null) { fOnLoad(this.currentForm); } // SAFARI => FORCE IFRAME RELOADING if(Prototype.Browser.WebKit && reloadIFrame && reloadIFrameSrc) reloadIFrame.src = reloadIFrameSrc; }, showContent: function(elementName, boxWidth, boxHeight){ ajaxplorer.disableShortcuts(); ajaxplorer.disableNavigation(); ajaxplorer.filesList.blur(); var winWidth = $(document.body).getWidth(); var winHeight = $(document.body).getHeight(); // WIDTH / HEIGHT if(boxWidth != null){ if(boxWidth.indexOf('%') > -1){ percentWidth = parseInt(boxWidth); boxWidth = parseInt((winWidth * percentWidth) / 100); } $(elementName).setStyle({width:boxWidth+'px'}); } if(boxHeight != null){ if(boxHeight.indexOf('%') > -1){ percentHeight = parseInt(boxHeight); boxHeight = parseInt((winHeight * percentHeight) / 100); } $(elementName).setStyle({height:boxHeight+'px'}); }else{ if (Prototype.Browser.IE){ $(elementName).setStyle({height:'1%'}); }else{ $(elementName).setStyle({height:'auto'}); } } this.refreshDialogPosition(); displayLightBoxById(elementName); // FORCE ABSOLUTE FOR SAFARI $(elementName).style.position = 'absolute'; // FORCE FIXED FOR FIREFOX if (Prototype.Browser.Gecko){ $(elementName).style.position = 'fixed'; } else if(Prototype.Browser.IE){ $$('select').invoke('show'); // REFRESH PNG IMAGES FOR IE! refreshPNGImages(this.dialogContent); } Shadower.shadow($(elementName), { distance: 4, angle: 130, opacity: 0.5, nestedShadows: 3, color: '#000000', shadowStyle:{display:'block'} }, true); }, getForm: function() { return this.currentForm; }, refreshDialogPosition: function(checkHeight, elementToScroll){ var winWidth = $(document.body).getWidth(); var winHeight = $(document.body).getHeight(); boxWidth = $(this.elementName).getWidth(); var boxHeight = $(this.elementName).getHeight(); if(checkHeight && boxHeight > parseInt(winHeight*90/100)){ var maxHeight = parseInt(winHeight*90/100); var crtScrollHeight = elementToScroll.getHeight(); var crtOffset = boxHeight - crtScrollHeight; if(maxHeight > crtOffset){ elementToScroll.setStyle({ overflow:'auto', height:(maxHeight-crtOffset)+'px' }); boxHeight = $(this.elementName).getHeight(); } } // POSITION HORIZONTAL var offsetLeft = parseInt((winWidth - parseInt(boxWidth)) / 2); $(this.elementName).setStyle({left:offsetLeft+'px'}); // POSITION VERTICAL var offsetTop = parseInt(((winHeight - boxHeight)/3)); $(this.elementName).setStyle({top:offsetTop+'px'}); }, clearContent: function(object){ // REMOVE CURRENT FORM, IF ANY if(object.getElementsBySelector("form").length) { var oThis = this; object.getElementsBySelector("form").each(function(currentForm){ if(currentForm.target == 'hidden_iframe' || currentForm.id=='login_form' || currentForm.id=='user_pref_form'){ currentForm.hide(); oThis.cachedForms.set(currentForm.id,true); } else{ object.removeChild(currentForm); } }); } }, addSubmitCancel: function(oForm, fOnCancel, bOkButtonOnly){ var contDiv = document.createElement('div'); contDiv.className = 'dialogButtons'; var okButton = document.createElement('input'); okButton.setAttribute('type', 'submit'); okButton.setAttribute('name', 'sub'); okButton.setAttribute('value', MessageHash[48]); $(okButton).addClassName('dialogButton'); $(okButton).addClassName('dialogFocus'); contDiv.appendChild(okButton); if(!bOkButtonOnly) { var caButton = document.createElement('input'); caButton.setAttribute('type', 'button'); caButton.setAttribute('name', 'can'); caButton.setAttribute('value', MessageHash[49]); $(caButton).addClassName('dialogButton'); if(fOnCancel){ caButton.onclick = function(){fOnCancel();hideLightBox();return false;}; } else{ caButton.onclick = function(){hideLightBox();return false;}; } contDiv.appendChild(caButton); } oForm.appendChild(contDiv); oForm.hasButtons = true; }, setLoadingStepCounts: function(count){ this.loadingStepsCount = count; this.loadingStep = count; }, incrementStepCounts: function(add){ this.loadingStepsCount += add; this.loadingStep += add; }, updateLoadingProgress: function(state){ this.loadingStep --; var percent = (1 - (this.loadingStep / this.loadingStepsCount)); var width = parseInt(parseInt($('progressBarBorder').getWidth()) * percent); /* var command = "if($('progressBar')) $('progressBar').style.width = '"+width+"px';"; setTimeout(command, 0); */ if(state){ $('progressState').update(state); } if($('progressBar')){ /* $('progressBar').style.width = width+'px'; */ var afterFinishFunc; if(parseInt(percent)==1){ afterFinishFunc = function(effect){ new Effect.Opacity('loading_overlay', { from:1.0, to:0, duration:0.3, afterFinish:function(effect){ $('loading_overlay').remove(); //if(ajaxplorer) ajaxplorer.actionBar.update(); } }); } } new Effect.Morph('progressBar',{ style:'width:'+width + 'px', duration:0.8, afterFinish:afterFinishFunc }); } if(this.loadingStep == 0){ //$('loading_overlay').remove(); this.pageLoading = false; } }, setCloseAction: function(func){ this.closeFunction = func; }, close: function(){ Shadower.deshadow($(this.elementName)); if(this.closeFunction){ this.closeFunction(); //this.closeFunction = null; } } }); var modal = new Modal(); AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.SVNLogger.js0000766000000000000000000000607211122202530025366 0ustar adminadministratorsSVNLogger = Class.create({ initialize:function(form){ this.element = form.select('[id="svnlog_box"]')[0]; this.container = new Element('div', { style:"height:250px;overflow:auto;border:1px solid #ddd;" }); this.element.insert(this.container); this.template = new Template('
    #{revString} : #{revision} #{downloadLink}
    #{authString} : #{author}
    #{dateString} : #{date}
    #{messString} : #{message}
    '); this.downloadTemplate = new Template('(#{downloadString})'); this.revMessage = MessageHash[243]; this.authorMessage = MessageHash[244]; this.dateMessage = MessageHash[245]; this.messMessage = MessageHash[246]; this.downMessage = MessageHash[88]; }, open: function(fileName){ this.fileName = fileName; var connexion = new Connexion(); connexion.addParameter('get_action', 'svnlog'); connexion.addParameter('file', fileName); connexion.onComplete = this.displayResponse.bind(this); this.setOnLoad(); connexion.sendAsync(); }, addEntry:function(revision,author,date,message, isFile, isLast){ var dLink = (isFile?this.downloadTemplate.evaluate({ fileName:this.fileName, revision:revision, downloadString:this.downMessage }):""); this.container.insert(this.template.evaluate({ revision:revision, author:author, date:date, message:message, downloadLink:dLink, cssStyle:(isLast?"padding:5px":"padding:5px;border-bottom:1px solid #79f"), revString:this.revMessage, authString:this.authorMessage, dateString:this.dateMessage, messString:this.messMessage })); }, displayResponse: function(transport){ //alert('received XML!'); var oXmlDoc = transport.responseXML; if(oXmlDoc == null || oXmlDoc.documentElement == null) return; if(!oXmlDoc.childNodes.length)return; var root = oXmlDoc.childNodes[0]; if(!root.childNodes.length) return; var log = root.childNodes[0]; for(var i=0; iType your SQL query here :
    '); this.sqlQuery = $('sql_query'); this.sqlQuery.observe("focus", function(e){ ajaxplorer.disableShortcuts(); this.hasFocus = true; //this.sqlQuery.select(); Event.stop(e); }.bind(this)); this.sqlQuery.observe("blur", function(e){ ajaxplorer.enableShortcuts(); this.hasFocus = false; }.bind(this) ); this.sqlQuery.observe("keydown", function(e){ if(e.keyCode == Event.KEY_RETURN && e["ctrlKey"]){ this.performSearch(this.sqlQuery.getValue()); Event.stop(e); } }.bind(this)); this.searchButton = $('search_button'); this.searchButton.observe('click', function(e){ this.performSearch(this.sqlQuery.getValue()); }.bind(this)); this.clearButton = $('clear_button'); this.clearButton.observe('click', function(e){ this.sqlQuery.update(""); this.sqlQuery.value = ""; }.bind(this)); this.resize(); }, performSearch:function(query){ if(query == '') return; var connexion = new Connexion(); var params = new Hash(); params.set('get_action', 'set_query'); params.set('query', query); connexion.setParameters(params); var res = connexion.sendSync(); var path = "/ajxpmysqldriver_searchresults"; ajaxplorer.getFoldersTree().goToDeepPath(path); ajaxplorer.filesList.loadXmlList(path); ajaxplorer.getActionBar().updateLocationBar(path); }, resize:function(){ fitHeightToBottom(this.sqlQuery, null, 43, true); }, focus:function(){ if(this.htmlElement.visible()){ this.sqlQuery.focus(); this.hasFocus = true; } }, blur: function(){ this.sqlQuery.blur(); this.hasFocus = false; } });AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.UserSelection.js0000766000000000000000000000637711122202530026354 0ustar adminadministratorsUserSelection = Class.create({ _currentRep: undefined, _selectedItems: undefined, _bEmpty: undefined, _bUnique: false, _bFile: false, _bDir: false, _isRecycle: false, initialize: function(aSelectedItems, sCurrentRep){ this._currentRep = sCurrentRep; this._selectedItems = aSelectedItems; this._bEmpty = ((aSelectedItems && aSelectedItems.length)?false:true); if(!this._bEmpty) { this._bUnique = ((aSelectedItems.length == 1)?true:false); for(var i=0; i 1) return true; return false; }, hasMime : function(mimeTypes){ var has = false; var selectedItems = $A(this._selectedItems); mimeTypes.each(function(mime){ if(has) return; has = selectedItems.any(function(item){ return (getFileExtension(item.getAttribute('filename')) == mime); }); }); return has; }, getFileNames : function(){ if(!this._selectedItems.length) { alert('Please select a file!'); return; } var tmp = new Array(this._selectedItems.length); for(i=0;i * * 2. Create a DIV for the output to be written to * eg.
    * * 3. Instantiate a MultiSelector object, passing in the DIV and an (optional) maximum number of files * eg. var multi_selector = new MultiSelector( document.getElementById( 'files_list' ), 3 ); * * 4. Add the first element * eg. multi_selector.addElement( document.getElementById( 'first_file_element' ) ); * * 5. That's it. * * You might (will) want to play around with the addListRow() method to make the output prettier. * * You might also want to change the line * element.name = 'file_' + this.count; * ...to a naming convention that makes more sense to you. * * Licence: * Use this however/wherever you like, just don't blame me if it breaks anything. * * Credit: * If you're nice, you'll leave this bit: * * Class by Stickman -- http://www.the-stickman.com * with thanks to: * [for Safari fixes] * Luis Torrefranca -- http://www.law.pitt.edu * and * Shawn Parker & John Pennypacker -- http://www.fuzzycoconut.com * [for duplicate name bug] * 'neal' */ function MultiSelector( formObject, list_target, max ){ // Main form this.mainForm = formObject; // Where to write the list this.list_target = list_target; // How many elements? this.count = 0; // Current index this.id = 0; // Is there a maximum? if( max ){ this.max = max; } else { this.max = -1; }; this.crtList = ajaxplorer.getFilesList(); // Clear list_target if(list_target.childNodes.length){ $A(list_target.childNodes).each(function(node){ list_target.removeChild(node); }); } if($(formObject).getElementsBySelector('input[type="file"]').length > 1){ var index = 0; $(formObject).getElementsBySelector('input[type="file"]').each(function(element){ if(index > 0) formObject.removeChild(element); index++; }); } /** * Add a new file input element */ this.addElement = function( element ){ // Make sure it's a file input element if( element.tagName == 'INPUT' && element.type == 'file' ){ // Element name -- what number am I? element.name = 'userfile_' + this.id++; element.multi_index = this.id; element.id = element.name; $(element).addClassName("dialogFocus"); // Add reference to this object element.multi_selector = this; // What to do when a file is selected element.onchange = function(){ // New file input var new_element = document.createElement( 'input' ); new_element.type = 'file'; new_element.name = 'toto'; // Add new element this.parentNode.insertBefore( new_element, this ); //this.multi_selector.mainForm.appendChild( element ); // Apply 'update' to element this.multi_selector.addElement( new_element ); // Update list this.multi_selector.addListRow( this ); // Hide this: we can't use display:none because Safari doesn't like it this.style.position = 'absolute'; this.style.left = '-1000px'; }; // If we've reached maximum number, disable input element if( this.max != -1 && this.count >= this.max ){ element.disabled = true; }else{ element.disabled = false; } // File element counter this.count++; // Most recent element this.current_element = element; } else { // This can only be applied to file input elements! alert( 'Error: not a file input element' ); }; }; /** * Add a new row to the list of files */ this.addListRow = function( element ){ // Row div var new_row = document.createElement( 'div' ); // Delete button var new_row_button = document.createElement( 'img' ); //new_row_button.appendChild(document.createTextNode('remove')); new_row_button.src = ajxpResourcesFolder+'/images/recyclebin.png'; new_row_button.align = 'absmiddle'; new_row_button.setAttribute("style", "border:0px;cursor:pointer;"); // References new_row.element = element; new_row_button.element = element; new_row.multi_index = element.multi_index; // Delete function new_row_button.onclick= function(){ // Remove element from form this.element.parentNode.removeChild( this.parentNode.element ); // Remove this row from the list this.parentNode.parentNode.removeChild( this.parentNode ); // Decrement counter this.element.multi_selector.count--; // Re-enable input element (if it's disabled) this.element.multi_selector.current_element.disabled = false; // Appease Safari // without it Safari wants to reload the browser window // which nixes your already queued uploads return false; }; // Set row value //new_row.innerHTML = element.value; var value = element.value; var maxLength = 63; if(value.length > maxLength) { value = value.substr(0,20) + '[...]' + value.substr(value.length-(maxLength-20), value.length); } // Add button new_row.appendChild( new_row_button ); // Add Text new_row.appendChild(document.createTextNode(value)); // Add it to the list this.list_target.appendChild( new_row ); }; this.getFileNames = function(){ var fileNames = new Array(); for(var i=0; i '+getBaseName(fileName)); new_row_button.multidownloader = this; // Delete function new_row_button.onclick= function() { // Remove this row from the list this.parentNode.parentNode.removeChild( this.parentNode ); this.multidownloader.count --; if(this.multidownloader.count == 0 && this.multidownloader.triggerEnd) { this.multidownloader.triggerEnd(); } }; new_row.insert(new_row_button); // Add it to the list $(this.list_target).insert( new_row ); }; this.emptyList = function() { }; }; AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.FilesList.js0000766000000000000000000010244311122202530025455 0ustar adminadministratorsFilesList = Class.create(SelectableElements, { initialize: function($super, oElement, bSelectMultiple, oSortTypes, sCurrentRep, oAjaxplorer, sDefaultDisplay) { $super(oElement, bSelectMultiple); this._displayMode = sDefaultDisplay; this._thumbSize = 64; this._crtImageIndex = 0; this._bSelection = false; this._bUnique = false; this._bFile = false; this._bDir = false; this._bEditable = false; this._oSortTypes = oSortTypes; this._ajaxplorer = oAjaxplorer; this._pendingFile = null; this._currentRep = sCurrentRep; this.allDraggables = new Array(); this.allDroppables = new Array(); // List mode style : file list or tableur mode ? this.gridStyle = "grid"; this.paginationData = null; this.even = true; // Default headersDef this.columnsDef = $A([]); this.columnsDef.push({messageId:1,attributeName:'text'}); this.columnsDef.push({messageId:2,attributeName:'filesize'}); this.columnsDef.push({messageId:3,attributeName:'mimestring'}); this.columnsDef.push({messageId:4,attributeName:'modiftime'}); // Associated Defaults this.defaultSortTypes = ["StringDirFile", "NumberKo", "String", "MyDate"]; this._oSortTypes = this.defaultSortTypes; this.initGUI(); Event.observe(document, "keydown", function(e){ if (e == null) e = $('content_pane').ownerDocument.parentWindow.event; return this.keydown(e); }.bind(this)); if(this._currentRep != null){ this.loadXmlList(this._currentRep); } }, initGUI: function() { if(this._displayMode == "list") { var buffer = ''; if(this.gridStyle == "grid"){ buffer = buffer + '
    '; } buffer = buffer + ''; this.columnsDef.each(function(column){buffer = buffer + '';}); buffer = buffer + ''; for(var i=0; i'+(column.messageId?MessageHash[column.messageId]:column.messageString)+''; } buffer = buffer + '
    '; if(this.gridStyle == "grid"){ buffer = buffer + '
    '; } buffer = buffer + '
    '; $('content_pane').innerHTML = buffer; oElement = $('selectable_div'); if(this.paginationData && parseInt(this.paginationData.get('total')) > 1 ){ $('table_rows_container').insert({before:this.createPaginator()}); } this.initSelectableItems(oElement, true, $('table_rows_container')); this._sortableTable = new AjxpSortable(oElement, this._oSortTypes, $('selectable_div_header')); if(this.gridStyle == "grid"){ this._sortableTable.onsort = this.redistributeBackgrounds.bind(this); } fitHeightToBottom($('table_rows_container'), $('content_pane'), (!Prototype.Browser.IE?2:0)); this.disableTextSelection($('selectable_div_header')); this.disableTextSelection($('table_rows_container')); } else if(this._displayMode == "thumb") { var buffer = ''; buffer = buffer + ''; buffer = buffer + ''; buffer = buffer + ''; buffer = buffer + '
    '+MessageHash[126]+'
    '; $('content_pane').innerHTML = buffer; fitHeightToBottom($('selectable_div'), $('content_pane'), (!Prototype.Browser.IE?3:0)); this.slider = new Slider($("slider-1"), $("slider-input-1")); this.slider.setMaximum(200); this.slider.setMinimum(30); this.slider.recalculate(); this.slider.setValue(this._thumbSize); this.slider.onchange = function() { this._thumbSize = this.slider.getValue(); this.resizeThumbnails(); }.bind(this); this.disableTextSelection($('selectable_div')); this.initSelectableItems($('selectable_div'), true); } }, createPaginator: function(){ var current = parseInt(this.paginationData.get('current')); var total = parseInt(this.paginationData.get('total')); var div = new Element('div').setStyle({height: '20px', backgroundColor:'#FFFFC1', borderBottom: '1px solid #ddd',fontFamily:'Trebuchet MS', fontSize:'11px', textAlign:'center', paddingTop: '2px'}); div.update('Page '+current+'/'+total); if(current>1){ div.insert({top:this.createPaginatorLink(current-1, '<   ', 'Previous')}); if(current > 2){ div.insert({top:this.createPaginatorLink(1, '<<   ', 'First')}); } } if(total > 1 && current < total){ div.insert({bottom:this.createPaginatorLink(current+1, '   >', 'Next')}); if(current < (total-1)){ div.insert({bottom:this.createPaginatorLink(total, '   >>', 'Last')}); } } return div; }, createPaginatorLink:function(page, text, title){ return new Element('a', {href:'#', style:'font-size:12px;', title:title}).update(text).observe('click', function(e){ this.loadXmlList(this._currentRep, null, null, $H({page:page})); Event.stop(e); }.bind(this)); }, setColumnsDef:function(aColumns){ this.columnsDef = aColumns; if(this._displayMode == "list"){ this.initGUI(); } }, getColumnsDef:function(){ return this.columnsDef; }, setContextualMenu: function(protoMenu){ this.protoMenu = protoMenu; }, switchDisplayMode: function(mode){ if(mode) { this._displayMode = mode; } else { if(this._displayMode == "thumb") this._displayMode = "list"; else this._displayMode = "thumb"; } var currentSelection = this.getSelectedFileNames(); this.initGUI(); this.reload(currentSelection); this.fireChange(); return this._displayMode; }, getDisplayMode: function(){ return this._displayMode; }, getHeadersWidth: function(){ if(this._displayMode == 'thumb') return; var tds = $('selectable_div_header').getElementsBySelector('td'); this.headersWidth = new Hash(); var index = 0; tds.each(function(cell){ this.headersWidth.set(index, cell.getWidth() - 8); index++; }.bind(this)); //alert(this.headersWidth[0]); }, applyHeadersWidth: function(){ if(this.gridStyle == "grid"){ window.setTimeout(function(){ // Reverse! var allItems = this.getItems(); if(!allItems.length) return; var tds = $(allItems[0]).getElementsBySelector('td'); var headerCells = $('selectable_div_header').getElementsBySelector('td'); var divDim = $('selectable_div').getDimensions(); var contDim = $('table_rows_container').getDimensions(); if(divDim.height > contDim.height && !(divDim.width > contDim.width) ){ $('selectable_div_header').setStyle({width:($('selectable_div_header').getWidth()-17)+'px'}); } var index = 0; headerCells.each(function(cell){ cell.setStyle({padding:0}); var div = new Element('div').update(' '+cell.innerHTML); div.setStyle({height: cell.getHeight(), overflow: 'hidden'}); div.setStyle({width:tds[index].getWidth()-4+'px'}); div.setAttribute("title", new String(cell.innerHTML).stripTags()); cell.update(div); cell.setStyle({width:tds[index].getWidth()+'px'}); index++; }); }.bind(this), 10); return; } this.getHeadersWidth(); var allItems = this.getItems(); for(var i=0; i 1){ this.loadXmlList(this._currentRep, pendingFileToSelect, url, $H({page:this.paginationData.get('current')})); }else{ this.loadXmlList(this._currentRep, pendingFileToSelect, url); } } }, setPendingSelection: function(pendingFilesToSelect){ this._pendingFile = pendingFilesToSelect; }, loadXmlList: function(repToLoad, pendingFileToSelect, url, additionnalParameters){ // TODO : THIS SHOULD BE SET ONCOMPLETE! this._currentRep = repToLoad; var connexion = new Connexion(url); connexion.addParameter('mode', 'file_list'); connexion.addParameter('dir', repToLoad); if(additionnalParameters){ additionnalParameters.each(function(pair){ connexion.addParameter(pair.key,pair.value); }); } this._pendingFile = pendingFileToSelect; this.setOnLoad(); connexion.onComplete = function (transport){ try{ this.parseXmlAndLoad(transport.responseXML); }catch(e){ alert('Erreur au chargement :'+ e.message); }finally{ this.removeOnLoad(); } }.bind(this); connexion.sendAsync(); }, parseXmlAndLoad: function(oXmlDoc){ if( oXmlDoc == null || oXmlDoc.documentElement == null) { return; } this.loading = false; this.imagesHash = new Hash(); this.allDroppables.each(function(el){ Droppables.remove(el); }); this.allDroppables = new Array(); this.allDraggables.each(function(el){ el.destroy(); }); this.allDraggables = new Array(); if(this.protoMenu){ this.protoMenu.removeElements('.ajxp_draggable'); this.protoMenu.removeElements('#selectable_div'); } var root = oXmlDoc.documentElement; // loop through all tree children var cs = root.childNodes; var l = cs.length; // FIRST PASS FOR REQUIRE AUTH for (var i = 0; i < l; i++) { if(cs[i].tagName == "require_auth") { if(modal.pageLoading) modal.updateLoadingProgress('List Loaded'); ajaxplorer.actionBar.fireAction('login'); this.removeCurrentLines(); this.fireChange(); return; } } // SECOND PASS FOR ERRORS CHECK AND COLUMNS DECLARATION var refreshGUI = false; this.gridStyle = 'file'; this._oSortTypes = this.defaultSortTypes; if(this.paginationData){ this.paginationData = null; refreshGUI = true; } for (var i = 0; i < l; i++) { if(cs[i].nodeName == "error" || cs[i].nodeName == "message") { var type = "ERROR"; if(cs[i].nodeName == "message") type = cs[i].getAttribute('type'); if(modal.pageLoading){ alert(type+':'+cs[i].firstChild.nodeValue); this.fireChange(); }else{ ajaxplorer.displayMessage(type, cs[i].firstChild.nodeValue); this.fireChange(); return; } } else if(cs[i].nodeName == "columns") { //Dynamically redefine columns! if(cs[i].getAttribute('switchGridMode')){ this.gridStyle = cs[i].getAttribute('switchGridMode'); } if(cs[i].getAttribute('switchDisplayMode')){ var dispMode = cs[i].getAttribute('switchDisplayMode'); if(dispMode != this._displayMode){ this.switchDisplayMode(dispMode); } } var newCols = $A([]); var sortTypes = $A([]); for(var j=0;j " + xmlNode.getAttribute(s); innerSpan.innerHTML = imgString; tableCell.appendChild(innerSpan); $(innerSpan).setStyle({display:'block'}); $(innerSpan).setAttribute('filename', newRow.getAttribute('filename')); if(!xmlNode.getAttribute("is_recycle") || xmlNode.getAttribute("is_recycle") != "1"){ var newDrag = new AjxpDraggable(innerSpan, {revert:true,ghosting:true,scroll:'tree_container'}); this.allDraggables[this.allDraggables.length] = newDrag; } if(xmlNode.getAttribute("is_file") == "0") { AjxpDroppables.add(innerSpan); this.allDroppables[this.allDroppables.length] = innerSpan; } } else { tableCell.innerHTML = xmlNode.getAttribute(s); } if(this.gridStyle == "grid"){ $(tableCell).setAttribute('valign', 'top'); $(tableCell).setStyle({ verticalAlign:'top', borderRight:'1px solid #eee' }); if(this.even){ $(tableCell).setStyle({borderRightColor: '#fff'}); } if (tableCell.innerHTML == '') tableCell.innerHTML = ' '; } newRow.appendChild(tableCell); }.bind(this)); tBody.appendChild(newRow); if(this.even){ $(newRow).setStyle({backgroundColor: '#eee'}); } this.even = !this.even; }, xmlNodeToDiv: function(xmlNode){ var newRow = new Element('div', {className:"thumbnail_selectable_cell"}); var tmpAtts = new Hash(); for(i=0;i= height){ newWidth = 64; newHeight = parseInt(height / width * 64); marginTop = parseInt((64 - newHeight)/2) + 5; marginBottom = 64+10-newHeight-marginTop-1; } else { newHeight = 64; newWidth = parseInt(width / height * 64); marginTop = 5; marginBottom = 5; } var crtIndex = this._crtImageIndex; innerSpan.insert({"bottom":img}); innerSpan.insert({"bottom":label}); newRow.insert({"bottom": innerSpan}); newRow.IMAGE_ELEMENT = img; newRow.LABEL_ELEMENT = label; this._htmlElement.appendChild(newRow); var fileName = tmpAtts.get('filename'); var oImageToLoad = { index:"ajxp_image_"+crtIndex, filename:fileName, rowObject:newRow, height: newHeight, width: newWidth, marginTop: marginTop, marginBottom: marginBottom }; this.imagesHash.set(oImageToLoad.index, oImageToLoad); } else { // Add icon //if(xmlNode.getAttribute("is_file") == "0") src = "images/crystal/mimes/64/folder.png"; //else src = ajxpResourcesFolder+'/images/crystal/mimes/64/'+tmpAtts.get('icon'); var imgString = "
    " + tmpAtts.get("text")+"
    "; innerSpan.innerHTML = imgString; newRow.appendChild(innerSpan); this._htmlElement.appendChild(newRow); } try{ var newDrag = new AjxpDraggable(newRow, {revert:true,ghosting:true}); this.allDraggables[this.allDraggables.length] = newDrag; }catch(e){alert(e);} if(tmpAtts.get("is_file") == "0") { AjxpDroppables.add(newRow); this.allDroppables[this.allDroppables.length] = newRow; } delete(tmpAtts); delete(xmlNode); }, resizeThumbnails: function(one_element){ var defaultMargin = 5; var elList; if(one_element) elList = [one_element]; else elList = this._htmlElement.getElementsBySelector('.thumbnail_selectable_cell'); elList.each(function(element){ var is_image = (element.getAttribute('is_image')=='1'?true:false); var image_element = element.IMAGE_ELEMENT || element.getElementsBySelector('img')[0]; var label_element = element.LABEL_ELEMENT || element.getElementsBySelector('.thumbLabel')[0]; var tSize = this._thumbSize; var tW, tH, mT, mB; if(is_image && image_element.getAttribute("is_loaded") == "true") { imgW = parseInt(element.getAttribute("image_width")); imgH = parseInt(element.getAttribute("image_height")); if(imgW > imgH) { tW = tSize; tH = parseInt(imgH / imgW * tW); mT = parseInt((tW - tH)/2) + defaultMargin; mB = tW+(defaultMargin*2)-tH-mT-1; } else { tH = tSize; tW = parseInt(imgW / imgH * tH); mT = mB = defaultMargin; } } else { if(tSize >= 64) { tW = tH = 64; mT = parseInt((tSize - 64)/2) + defaultMargin; mB = tSize+(defaultMargin*2)-tH-mT-1; } else { tW = tH = tSize; mT = mB = defaultMargin; } } image_element.setStyle({width:tW+'px', height:tH+'px', marginTop:mT+'px', marginBottom:mB+'px'}); element.setStyle({width:tSize+25+'px', height:tSize+30+'px'}); //var el_width = element.getWidth(); var el_width = tSize + 25; var charRatio = 6; var nbChar = parseInt(el_width/charRatio); var label = new String(label_element.getAttribute('title')); //alert(element.getAttribute('text')); label_element.innerHTML = label.truncate(nbChar, '...'); }.bind(this)); }, redistributeBackgrounds: function(){ var allItems = this.getItems(); for(var i=0;i= currentItemIndex) { for(var i=currentItemIndex+1; i-1; i--){ if(Position.within($(allItems[i]), searchingPosX, searchingPosY)) { return i; } } return null; } }, isItem: function (node) { if(this._displayMode == "list") { return node != null && ( node.tagName == "TR" || node.tagName == "tr") && ( node.parentNode.tagName == "TBODY" || node.parentNode.tagName == "tbody" )&& node.parentNode.parentNode == this._htmlElement; } if(this._displayMode == "thumb") { return node != null && ( node.tagName == "DIV" || node.tagName == "div") && node.parentNode == this._htmlElement; } }, /* Indexable Collection Interface */ getItems: function () { if(this._displayMode == "list") { return this._htmlElement.rows; } if(this._displayMode == "thumb") { var tmp = []; var j = 0; var cs = this._htmlElement.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i].nodeType == 1) tmp[j++] = cs[i] } return tmp; } }, getItemIndex: function (el) { if(this._displayMode == "list") { return el.rowIndex; } if(this._displayMode == "thumb") { var j = 0; var cs = this._htmlElement.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i] == el) return j; if (cs[i].nodeType == 1) j++; } return -1; } }, getItem: function (nIndex) { if(this._displayMode == "list") { return this._htmlElement.rows[nIndex]; } if(this._displayMode == "thumb") { var j = 0; var cs = this._htmlElement.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i].nodeType == 1) { if (j == nIndex) return cs[i]; j++; } } return null; } } /* End Indexable Collection Interface */ }); AjaXplorer/AjaXplorer/client/js/ajaxplorer/class.Action.js0000766000000000000000000002670411122202530025001 0ustar adminadministratorsAction = Class.create({ initialize:function(){ this.options = Object.extend({ name:'', src:'', text:'', title:'', hasAccessKey:false, accessKey:'', callbackCode:'', callback:Prototype.emptyFunction, displayAction:false, prepareModal:false, formId:undefined, formCode:undefined }, arguments[0] || { }); this.context = Object.extend({ selection:true, dir:false, root:true, inZip:true, recycle:false, behaviour:'hidden', actionBar:false, actionBarGroup:'default', contextMenu:false, infoPanel:false }, arguments[1] || { }); this.selectionContext = Object.extend({ dir:false, file:true, recycle:false, behaviour:'disabled', allowedMimes:$A([]), unique:true, multipleOnly:false }, arguments[2] || { }); this.rightsContext = Object.extend({ noUser:true, userLogged:true, guestLogged:false, read:true, write:false, adminOnly:false }, arguments[3] || { }); this.elements = new Array(); this.contextHidden = false; this.deny = false; }, apply: function(){ if(this.deny) return; if(this.options.prepareModal){ modal.prepareHeader(this.options.title, ajxpResourcesFolder+'/images/crystal/actions/16/'+this.options.src); } window.actionArguments = $A([]); if(arguments[0]) window.actionArguments = $A(arguments[0]); if(this.options.callbackCode) this.options.callbackCode.evalScripts(); window.actionArguments = null; }, fireContextChange: function(){ if(arguments.length < 5) return; var usersEnabled = arguments[0]; var crtUser = arguments[1]; var crtIsRecycle = arguments[2]; var crtDisplayMode = arguments[3]; var crtInZip = arguments[4]; var crtIsRoot = arguments[5]; if(this.options.listeners && this.options.listeners["contextChange"]){ this.options.listeners["contextChange"].evalScripts(); } var rightsContext = this.rightsContext; if(!rightsContext.noUser && !usersEnabled){ return this.hideForContext(); } if((rightsContext.userLogged == 'only' && crtUser == null) || (rightsContext.guestLogged && rightsContext.guestLogged=='hidden' & crtUser!=null && crtUser.id=='guest')){ return this.hideForContext(); } if(rightsContext.userLogged == 'hidden' && crtUser != null && !(crtUser.id=='guest' && rightsContext.guestLogged && rightsContext.guestLogged=='show') ){ return this.hideForContext(); } if(rightsContext.adminOnly && (crtUser == null || crtUser.id != 'admin')){ return this.hideForContext(); } if(rightsContext.read && crtUser != null && !crtUser.canRead()){ return this.hideForContext(); } if(rightsContext.write && crtUser != null && !crtUser.canWrite()){ return this.hideForContext(); } if(this.context.recycle){ if(this.context.recycle == 'only' && !crtIsRecycle){ return this.hideForContext(); } if(this.context.recycle == 'hidden' && crtIsRecycle){ return this.hideForContext(); } } if(!this.context.inZip && crtInZip){ return this.hideForContext(); } if(!this.context.root && crtIsRoot){ return this.hideForContext(); } if(this.options.displayAction && this.options.displayAction == crtDisplayMode){ return this.hideForContext(); } this.showForContext(); }, fireSelectionChange: function(){ if(this.options.listeners && this.options.listeners["selectionChange"]){ this.options.listeners["selectionChange"].evalScripts(); } if(arguments.length < 1 || this.contextHidden || !this.context.selection) { return; } var userSelection = arguments[0]; var bSelection = false; if(userSelection != null) { bSelection = !userSelection.isEmpty(); var bUnique = userSelection.isUnique(); var bFile = userSelection.hasFile(); var bDir = userSelection.hasDir(); var bRecycle = userSelection.isRecycle(); } var selectionContext = this.selectionContext; if(selectionContext.allowedMimes.size()){ if(selectionContext.behaviour == 'hidden') this.hide(); else this.disable(); } if(selectionContext.unique && !bUnique){ return this.disable(); } if((selectionContext.file || selectionContext.dir) && !bFile && !bDir){ return this.disable(); } if((selectionContext.dir && !selectionContext.file && bFile) || (!selectionContext.dir && selectionContext.file && bDir)){ return this.disable(); } if(!selectionContext.recycle && bRecycle){ return this.disable(); } if((selectionContext.allowedMimes.size() && userSelection && !userSelection.hasMime(selectionContext.allowedMimes)) && !(selectionContext.dir && bDir)){ if(selectionContext.behaviour == 'hidden') return this.hide(); else return this.disable(); } this.show(); this.enable(); }, createFromXML:function(xmlNode){ this.options.name = xmlNode.getAttribute('name'); for(var i=0; i'; if(processNode.getAttribute('prepareModal') && processNode.getAttribute('prepareModal') == "true"){ this.options.prepareModal = true; } if(processNode.getAttribute('displayModeButton') && processNode.getAttribute('displayModeButton') != ''){ this.options.displayAction = processNode.getAttribute('displayModeButton'); } }else if(processNode.nodeName == "clientListener" && processNode.firstChild){ if(!this.options.listeners) this.options.listeners = []; this.options.listeners[processNode.getAttribute('name')] = ''; } } }else if(node.nodeName == "gui"){ this.options.text = MessageHash[node.getAttribute('text')]; this.options.title = MessageHash[node.getAttribute('title')]; this.options.src = node.getAttribute('src'); if(node.getAttribute('hasAccessKey') && node.getAttribute('hasAccessKey') == "true"){ this.options.accessKey = node.getAttribute('accessKey'); this.options.hasAccessKey = true; } for(var j=0; j 0 || (!this.context.actionBar && this.context.infoPanel)) this.deny = true; this.elements.each(function(elem){ elem.hide(); }); }, show: function(){ if(this.elements.size() > 0 || (!this.context.actionBar && this.context.infoPanel)) this.deny = false; this.elements.each(function(elem){ elem.show(); }); }, disable: function(){ if(this.elements.size() > 0 || (!this.context.actionBar && this.context.infoPanel)) this.deny = true; this.elements.each(function(elem){ elem.addClassName('disabled'); }); }, enable: function(){ if(this.elements.size() > 0 || (!this.context.actionBar && this.context.infoPanel)) this.deny = false; this.elements.each(function(elem){ elem.removeClassName('disabled'); }); }, remove: function(){ // Remove all elements and forms from html this.elements.each(function(el){ $(el).remove(); }); if(this.options.formId && $('all_forms').select('[id="'+this.options.formId+'"]').length){ $('all_forms').select('[id="'+this.options.formId+'"]')[0].remove(); } }, getKeyedText: function(){ var displayString = this.options.text; if(!this.options.hasAccessKey) return displayString; var accessKey = this.options.accessKey; var keyPos = displayString.toLowerCase().indexOf(accessKey.toLowerCase()); if(keyPos==-1){ return displayString + ' (' + accessKey + ')'; } if(displayString.charAt(keyPos) != accessKey){ // case differ accessKey = displayString.charAt(keyPos); } returnString = displayString.substring(0,displayString.indexOf(accessKey)); returnString += ''+accessKey+''; returnString += displayString.substring(displayString.indexOf(accessKey)+1, displayString.length); return returnString; }, insertForm: function(){ if(!this.options.formCode || !this.options.formId) return; if($('all_forms').select('[id="'+this.options.formId+'"]').length) return; $('all_forms').insert(this.options.formCode); }, attributesToObject: function(object, node){ Object.keys(object).each(function(key){ if(node.getAttribute(key)){ value = node.getAttribute(key); if(value == 'true') value = true; else if(value == 'false') value = false; if(key == 'allowedMimes'){ if(value && value.split(',').length){ value = $A(value.split(',')); }else{ value = $A([]); } } this[key] = value; } }.bind(object)); } }); AjaXplorer/AjaXplorer/client/js/lib/0000777000000000000000000000000011300346053020516 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/leightbox/0000777000000000000000000000000011300346042022501 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/leightbox/screen.css0000766000000000000000000000267511122202530024500 0ustar adminadministrators#container { width: 50%; margin: 0 auto; text-align: left; } .footer { background-color: #000; padding: 0.5em; } .leightbox { color: #333; display: none; position: absolute; top: 45%; left: 45%; width: 50%; height: 50%; padding: 1em; border: 1em solid #B8B8B8; background-color: white; text-align: left; z-index:1001; overflow: auto; } #overlay, #loading_overlay{ display:none; position:absolute; top:0; left:0; width:100%; height:100%; z-index:1000; background-color:#eee; -moz-opacity: 0.3; opacity:.30; filter: alpha(opacity=30); } #loading_overlay{ display:block; /* background-color:#333; z-index:2000; -moz-opacity: 0.9; opacity:.90; filter: alpha(opacity=90); */ background-color:#666; z-index:2000; -moz-opacity:1; opacity:1; filter: alpha(opacity=100); } #element_overlay{ position:absolute; width:100%; height:100%; z-index:1000; background-color:#eee; -moz-opacity: 0.5; opacity:.50; filter: alpha(opacity=50); text-align:center; padding-top: 10%; } #element_iframe{ position:absolute; width:80%; height:80%; z-index:1010; background-color:#eee; border:1px solid black; } .lightbox[id]{ /* IE6 and below Can't See This */ position:fixed; }#overlay[id]{ /* IE6 and below Can't See This */ position:fixed; }#element_overlay[id]{ /* IE6 and below Can't See This */ position:fixed;}AjaXplorer/AjaXplorer/client/js/lib/leightbox/lightbox.js0000766000000000000000000002017311122202530024656 0ustar adminadministrators/* Created By: Chris Campbell Website: http://particletree.com Date: 2/1/2006 Adapted By: Simon de Haan Website: http://blog.eight.nl Date: 21/2/2006 Inspired by the lightbox implementation found at http://www.huddletogether.com/projects/lightbox/ And the lightbox gone wild by ParticleTree at http://particletree.com/features/lightbox-gone-wild/ */ /*-------------------------------GLOBAL VARIABLES------------------------------------*/ var detect = navigator.userAgent.toLowerCase(); var OS,browser,version,total,thestring; var currentLightBox, currentDraggable; /*-----------------------------------------------------------------------------------------------*/ //Browser detect script origionally created by Peter Paul Koch at http://www.quirksmode.org/ function getBrowserInfo() { if (checkIt('konqueror')) { browser = "Konqueror"; OS = "Linux"; } else if (checkIt('safari')) browser = "Safari" ; else if (checkIt('omniweb')) browser = "OmniWeb" ; else if (checkIt('opera')) browser = "Opera" ; else if (checkIt('webtv')) browser = "WebTV"; else if (checkIt('icab')) browser = "iCab" ; else if (checkIt('msie')) browser = "Internet Explorer" ; else if (!checkIt('compatible')) { browser = "Netscape Navigator" ; version = detect.charAt(8); } else browser = "An unknown browser"; if (!version) version = detect.charAt(place + thestring.length); if (!OS) { if (checkIt('linux')) OS = "Linux"; else if (checkIt('x11')) OS = "Unix"; else if (checkIt('mac')) OS = "Mac" ; else if (checkIt('win')) OS = "Windows" ; else OS = "an unknown operating system"; } } function checkIt(string) { place = detect.indexOf(string) + 1; thestring = string; return place; } /*-----------------------------------------------------------------------------------------------*/ Event.observe(window, 'load', initialize, false); Event.observe(window, 'load', getBrowserInfo, false); Event.observe(window, 'unload', Event.unloadCache, false); var lightbox = Class.create(); lightbox.prototype = { yPos : 0, xPos : 0, /* initialize: function(ctrl) { this.content = ctrl.rel; Event.observe(ctrl, 'click', this.activate.bindAsEventListener(this), false); ctrl.onclick = function(){return false;}; }, */ initialize: function(id) { this.content = id; }, // Turn everything on - mainly the IE fixes activate: function(){ if (browser == 'Internet Explorer'){ this.getScroll(); //this.prepareIE('100%', 'hidden'); this.setScroll(0,0); //this.hideSelects('hidden'); } this.displayLightbox("block"); }, // Ie requires height to 100% and overflow hidden or else you can scroll down past the lightbox prepareIE: function(height, overflow){ bod = document.getElementsByTagName('body')[0]; bod.style.overflow = overflow; bod.style.height = height; htm = document.getElementsByTagName('html')[0]; htm.style.overflow = overflow; htm.style.height = height; }, // In IE, select elements hover on top of the lightbox hideSelects: function(visibility){ selects = document.getElementsByTagName('select'); for(i = 0; i < selects.length; i++) { selects[i].style.visibility = visibility; } }, // Taken from lightbox implementation found at http://www.huddletogether.com/projects/lightbox/ getScroll: function(){ if (self.pageYOffset) { this.yPos = self.pageYOffset; } else if (document.documentElement && document.documentElement.scrollTop){ this.yPos = document.documentElement.scrollTop; } else if (document.body) { this.yPos = document.body.scrollTop; } }, setScroll: function(x, y){ window.scrollTo(x, y); }, displayLightbox: function(display){ if(display == 'none'){ $('overlay').fade({duration:0.5}); }else{ $('overlay').style.display = display; } if(this.content != null) { $(this.content).style.display = display; currentDraggable = new Draggable(this.content, { handle:"dialogTitle", zindex:1050, starteffect : function(element){ if(element.shadows) { Shadower.deshadow(element); element.hadShadow = true; } }, endeffect : function(element){ if(element.hadShadow){ Shadower.shadow(element,{ distance: 4, angle: 130, opacity: 0.5, nestedShadows: 3, color: '#000000', shadowStyle:{display:'block'} }); } } }); } //if(display != 'none') this.actions(); }, // Search through new links within the lightbox, and attach click event // WARNING : QUITE LONG IN I.E. actions: function(){ lbActions = document.getElementsByClassName('lbAction'); for(i = 0; i < lbActions.length; i++) { Event.observe(lbActions[i], 'click', this[lbActions[i].rel].bindAsEventListener(this), false); lbActions[i].onclick = function(){return false;}; } }, // Example of creating your own functionality once lightbox is initiated deactivate: function(){ if (browser == "Internet Explorer"){ this.setScroll(0,this.yPos); //this.prepareIE("auto", "hidden"); //this.hideSelects("visible"); } this.displayLightbox("none"); } }; /*-----------------------------------------------------------------------------------------------*/ // Onload, make all links that need to trigger a lightbox active function initialize(){ addLightboxMarkup(); /* lbox = document.getElementsByClassName('lbOn'); for(i = 0; i < lbox.length; i++) { valid = new lightbox(lbox[i]); } */ Event.observe(document, "keydown", function(e){ if(e==null)e=window.event; if(e.keyCode == 27) { ajaxplorer.cancelCopyOrMove(); //modal.close(); hideLightBox(); } if(e.keyCode == 9) return false; return true; }); } function displayLightBoxById(id) { valid = new lightbox(id); valid.activate(); currentLightBox = valid; if(id != 'copymove_div') { } } function hideLightBox(onFormSubmit) { if(currentLightBox) { currentLightBox.deactivate(); hideOverlay(); if(!onFormSubmit) { currentLightBox = null; } ajaxplorer.getActionBar().fireContextChange(); ajaxplorer.getActionBar().fireSelectionChange(); ajaxplorer.getFilesList().focus(); ajaxplorer.enableNavigation(); ajaxplorer.focusOn(ajaxplorer.filesList); ajaxplorer.enableShortcuts(); } if(currentDraggable) currentDraggable.destroy(); if(modal.closeFunction){ modal.closeFunction(); modal.closeFunction = null; } Shadower.deshadow($(modal.elementName)); } function setOverlay() { currentLightBox = new lightbox(null); currentLightBox.activate(); } function hideOverlay() { if(currentLightBox) { currentLightBox.deactivate(); currentLightBox = null; } } // Add in markup necessary to make this work. Basically two divs: // Overlay holds the shadow // Lightbox is the centered square that the content is put into. function addLightboxMarkup() { bod = document.getElementsByTagName('body')[0]; overlay = document.createElement('div'); overlay.id = 'overlay'; bod.appendChild(overlay); } function addLightboxMarkupToElement(element, skipElement) { overlay = document.createElement('div'); overlay.id = 'element_overlay'; if (Prototype.Browser.IE){ var position = Position.positionedOffset($(element)); // IE CASE //Position.offsetParent(element); overlay.style.top = position[1]; overlay.style.left = 0; } else { var position = Position.cumulativeOffset($(element)); overlay.style.top = position[1]; overlay.style.left = position[0]; } overlay.style.width = element.getWidth(); overlay.style.height = element.getHeight(); if(skipElement) { var addTop = parseInt(overlay.style.top) + parseInt(skipElement.getHeight()); var addHeight = parseInt(overlay.style.height) + parseInt(skipElement.getHeight()); overlay.style.top = addTop + 'px'; overlay.style.height = addHeight + 'px'; } element.appendChild(overlay); } function removeLightboxFromElement(element) { var tmp = $(element).select('#element_overlay'); if(tmp.length){ tmp[0].remove(); } } AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/0000777000000000000000000000000011300346043023415 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/0000777000000000000000000000000011300346045024206 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/sound.js0000766000000000000000000000360011122202526025671 0ustar adminadministrators// script.aculo.us sound.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // Based on code created by Jules Gravinese (http://www.webveteran.com/) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ Sound = { tracks: {}, _enabled: true, template: new Template(''), enable: function(){ Sound._enabled = true; }, disable: function(){ Sound._enabled = false; }, play: function(url){ if(!Sound._enabled) return; var options = Object.extend({ track: 'global', url: url, replace: false }, arguments[1] || {}); if(options.replace && this.tracks[options.track]) { $R(0, this.tracks[options.track].id).each(function(id){ var sound = $('sound_'+options.track+'_'+id); sound.Stop && sound.Stop(); sound.remove(); }) this.tracks[options.track] = null; } if(!this.tracks[options.track]) this.tracks[options.track] = { id: 0 } else this.tracks[options.track].id++; options.id = this.tracks[options.track].id; $$('body')[0].insert( Prototype.Browser.IE ? new Element('bgsound',{ id: 'sound_'+options.track+'_'+options.id, src: options.url, loop: 1, autostart: true }) : Sound.template.evaluate(options)); } }; if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 })) Sound.template = new Template('') else Sound.play = function(){} } AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/slider.js0000766000000000000000000002407011122202526026027 0ustar adminadministrators// script.aculo.us slider.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ if (!Control) var Control = { }; // options: // axis: 'vertical', or 'horizontal' (default) // // callbacks: // onChange(value) // onSlide(value) Control.Slider = Class.create({ initialize: function(handle, track, options) { var slider = this; if (Object.isArray(handle)) { this.handles = handle.collect( function(e) { return $(e) }); } else { this.handles = [$(handle)]; } this.track = $(track); this.options = options || { }; this.axis = this.options.axis || 'horizontal'; this.increment = this.options.increment || 1; this.step = parseInt(this.options.step || '1'); this.range = this.options.range || $R(0,1); this.value = 0; // assure backwards compat this.values = this.handles.map( function() { return 0 }); this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false; this.options.startSpan = $(this.options.startSpan || null); this.options.endSpan = $(this.options.endSpan || null); this.restricted = this.options.restricted || false; this.maximum = this.options.maximum || this.range.end; this.minimum = this.options.minimum || this.range.start; // Will be used to align the handle onto the track, if necessary this.alignX = parseInt(this.options.alignX || '0'); this.alignY = parseInt(this.options.alignY || '0'); this.trackLength = this.maximumOffset() - this.minimumOffset(); this.handleLength = this.isVertical() ? (this.handles[0].offsetHeight != 0 ? this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : this.handles[0].style.width.replace(/px$/,"")); this.active = false; this.dragging = false; this.disabled = false; if (this.options.disabled) this.setDisabled(); // Allowed values array this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false; if (this.allowedValues) { this.minimum = this.allowedValues.min(); this.maximum = this.allowedValues.max(); } this.eventMouseDown = this.startDrag.bindAsEventListener(this); this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.update.bindAsEventListener(this); // Initialize handles in reverse (make sure first handle is active) this.handles.each( function(h,i) { i = slider.handles.length-1-i; slider.setValue(parseFloat( (Object.isArray(slider.options.sliderValue) ? slider.options.sliderValue[i] : slider.options.sliderValue) || slider.range.start), i); h.makePositioned().observe("mousedown", slider.eventMouseDown); }); this.track.observe("mousedown", this.eventMouseDown); document.observe("mouseup", this.eventMouseUp); document.observe("mousemove", this.eventMouseMove); this.initialized = true; }, dispose: function() { var slider = this; Event.stopObserving(this.track, "mousedown", this.eventMouseDown); Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); this.handles.each( function(h) { Event.stopObserving(h, "mousedown", slider.eventMouseDown); }); }, setDisabled: function(){ this.disabled = true; }, setEnabled: function(){ this.disabled = false; }, getNearestValue: function(value){ if (this.allowedValues){ if (value >= this.allowedValues.max()) return(this.allowedValues.max()); if (value <= this.allowedValues.min()) return(this.allowedValues.min()); var offset = Math.abs(this.allowedValues[0] - value); var newValue = this.allowedValues[0]; this.allowedValues.each( function(v) { var currentOffset = Math.abs(v - value); if (currentOffset <= offset){ newValue = v; offset = currentOffset; } }); return newValue; } if (value > this.range.end) return this.range.end; if (value < this.range.start) return this.range.start; return value; }, setValue: function(sliderValue, handleIdx){ if (!this.active) { this.activeHandleIdx = handleIdx || 0; this.activeHandle = this.handles[this.activeHandleIdx]; this.updateStyles(); } handleIdx = handleIdx || this.activeHandleIdx || 0; if (this.initialized && this.restricted) { if ((handleIdx>0) && (sliderValuethis.values[handleIdx+1])) sliderValue = this.values[handleIdx+1]; } sliderValue = this.getNearestValue(sliderValue); this.values[handleIdx] = sliderValue; this.value = this.values[0]; // assure backwards compat this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = this.translateToPx(sliderValue); this.drawSpans(); if (!this.dragging || !this.event) this.updateFinished(); }, setValueBy: function(delta, handleIdx) { this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, handleIdx || this.activeHandleIdx || 0); }, translateToPx: function(value) { return Math.round( ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * (value - this.range.start)) + "px"; }, translateToValue: function(offset) { return ((offset/(this.trackLength-this.handleLength) * (this.range.end-this.range.start)) + this.range.start); }, getRange: function(range) { var v = this.values.sortBy(Prototype.K); range = range || 0; return $R(v[range],v[range+1]); }, minimumOffset: function(){ return(this.isVertical() ? this.alignY : this.alignX); }, maximumOffset: function(){ return(this.isVertical() ? (this.track.offsetHeight != 0 ? this.track.offsetHeight : this.track.style.height.replace(/px$/,"")) - this.alignY : (this.track.offsetWidth != 0 ? this.track.offsetWidth : this.track.style.width.replace(/px$/,"")) - this.alignX); }, isVertical: function(){ return (this.axis == 'vertical'); }, drawSpans: function() { var slider = this; if (this.spans) $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) }); if (this.options.startSpan) this.setSpan(this.options.startSpan, $R(0, this.values.length>1 ? this.getRange(0).min() : this.value )); if (this.options.endSpan) this.setSpan(this.options.endSpan, $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum)); }, setSpan: function(span, range) { if (this.isVertical()) { span.style.top = this.translateToPx(range.start); span.style.height = this.translateToPx(range.end - range.start + this.range.start); } else { span.style.left = this.translateToPx(range.start); span.style.width = this.translateToPx(range.end - range.start + this.range.start); } }, updateStyles: function() { this.handles.each( function(h){ Element.removeClassName(h, 'selected') }); Element.addClassName(this.activeHandle, 'selected'); }, startDrag: function(event) { if (Event.isLeftClick(event)) { if (!this.disabled){ this.active = true; var handle = Event.element(event); var pointer = [Event.pointerX(event), Event.pointerY(event)]; var track = handle; if (track==this.track) { var offsets = Position.cumulativeOffset(this.track); this.event = event; this.setValue(this.translateToValue( (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2) )); var offsets = Position.cumulativeOffset(this.activeHandle); this.offsetX = (pointer[0] - offsets[0]); this.offsetY = (pointer[1] - offsets[1]); } else { // find the handle (prevents issues with Safari) while((this.handles.indexOf(handle) == -1) && handle.parentNode) handle = handle.parentNode; if (this.handles.indexOf(handle)!=-1) { this.activeHandle = handle; this.activeHandleIdx = this.handles.indexOf(this.activeHandle); this.updateStyles(); var offsets = Position.cumulativeOffset(this.activeHandle); this.offsetX = (pointer[0] - offsets[0]); this.offsetY = (pointer[1] - offsets[1]); } } } Event.stop(event); } }, update: function(event) { if (this.active) { if (!this.dragging) this.dragging = true; this.draw(event); if (Prototype.Browser.WebKit) window.scrollBy(0,0); Event.stop(event); } }, draw: function(event) { var pointer = [Event.pointerX(event), Event.pointerY(event)]; var offsets = Position.cumulativeOffset(this.track); pointer[0] -= this.offsetX + offsets[0]; pointer[1] -= this.offsetY + offsets[1]; this.event = event; this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] )); if (this.initialized && this.options.onSlide) this.options.onSlide(this.values.length>1 ? this.values : this.value, this); }, endDrag: function(event) { if (this.active && this.dragging) { this.finishDrag(event, true); Event.stop(event); } this.active = false; this.dragging = false; }, finishDrag: function(event, success) { this.active = false; this.dragging = false; this.updateFinished(); }, updateFinished: function() { if (this.initialized && this.options.onChange) this.options.onChange(this.values.length>1 ? this.values : this.value, this); this.event = null; } }); AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/unittest.js0000766000000000000000000004734511122202526026436 0ustar adminadministrators// script.aculo.us unittest.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) // (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ // experimental, Firefox-only Event.simulateMouse = function(element, eventName) { var options = Object.extend({ pointerX: 0, pointerY: 0, buttons: 0, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false }, arguments[2] || {}); var oEvent = document.createEvent("MouseEvents"); oEvent.initMouseEvent(eventName, true, true, document.defaultView, options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element)); if(this.mark) Element.remove(this.mark); this.mark = document.createElement('div'); this.mark.appendChild(document.createTextNode(" ")); document.body.appendChild(this.mark); this.mark.style.position = 'absolute'; this.mark.style.top = options.pointerY + "px"; this.mark.style.left = options.pointerX + "px"; this.mark.style.width = "5px"; this.mark.style.height = "5px;"; this.mark.style.borderTop = "1px solid red;" this.mark.style.borderLeft = "1px solid red;" if(this.step) alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options)); $(element).dispatchEvent(oEvent); }; // Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2. // You need to downgrade to 1.0.4 for now to get this working // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much Event.simulateKey = function(element, eventName) { var options = Object.extend({ ctrlKey: false, altKey: false, shiftKey: false, metaKey: false, keyCode: 0, charCode: 0 }, arguments[2] || {}); var oEvent = document.createEvent("KeyEvents"); oEvent.initKeyEvent(eventName, true, true, window, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.keyCode, options.charCode ); $(element).dispatchEvent(oEvent); }; Event.simulateKeys = function(element, command) { for(var i=0; i' + 'StatusTestMessage' + '' + ''; this.logsummary = $('logsummary') this.loglines = $('loglines'); }, _toHTML: function(txt) { return txt.escapeHTML().replace(/\n/g,"
    "); }, addLinksToResults: function(){ $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log td.title = "Run only this test" Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;}); }); $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log td.title = "Run all tests" Event.observe(td, 'click', function(){ window.location.search = "";}); }); } } Test.Unit.Runner = Class.create(); Test.Unit.Runner.prototype = { initialize: function(testcases) { this.options = Object.extend({ testLog: 'testlog' }, arguments[1] || {}); this.options.resultsURL = this.parseResultsURLQueryParameter(); this.options.tests = this.parseTestsQueryParameter(); if (this.options.testLog) { this.options.testLog = $(this.options.testLog) || null; } if(this.options.tests) { this.tests = []; for(var i = 0; i < this.options.tests.length; i++) { if(/^test/.test(this.options.tests[i])) { this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"])); } } } else { if (this.options.test) { this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])]; } else { this.tests = []; for(var testcase in testcases) { if(/^test/.test(testcase)) { this.tests.push( new Test.Unit.Testcase( this.options.context ? ' -> ' + this.options.titles[testcase] : testcase, testcases[testcase], testcases["setup"], testcases["teardown"] )); } } } } this.currentTest = 0; this.logger = new Test.Unit.Logger(this.options.testLog); setTimeout(this.runTests.bind(this), 1000); }, parseResultsURLQueryParameter: function() { return window.location.search.parseQuery()["resultsURL"]; }, parseTestsQueryParameter: function(){ if (window.location.search.parseQuery()["tests"]){ return window.location.search.parseQuery()["tests"].split(','); }; }, // Returns: // "ERROR" if there was an error, // "FAILURE" if there was a failure, or // "SUCCESS" if there was neither getResult: function() { var hasFailure = false; for(var i=0;i 0) { return "ERROR"; } if (this.tests[i].failures > 0) { hasFailure = true; } } if (hasFailure) { return "FAILURE"; } else { return "SUCCESS"; } }, postResults: function() { if (this.options.resultsURL) { new Ajax.Request(this.options.resultsURL, { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false }); } }, runTests: function() { var test = this.tests[this.currentTest]; if (!test) { // finished! this.postResults(); this.logger.summary(this.summary()); return; } if(!test.isWaiting) { this.logger.start(test.name); } test.run(); if(test.isWaiting) { this.logger.message("Waiting for " + test.timeToWait + "ms"); setTimeout(this.runTests.bind(this), test.timeToWait || 1000); } else { this.logger.finish(test.status(), test.summary()); this.currentTest++; // tail recursive, hopefully the browser will skip the stackframe this.runTests(); } }, summary: function() { var assertions = 0; var failures = 0; var errors = 0; var messages = []; for(var i=0;i 0) return 'failed'; if (this.errors > 0) return 'error'; return 'passed'; }, assert: function(expression) { var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"'; try { expression ? this.pass() : this.fail(message); } catch(e) { this.error(e); } }, assertEqual: function(expected, actual) { var message = arguments[2] || "assertEqual"; try { (expected == actual) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertInspect: function(expected, actual) { var message = arguments[2] || "assertInspect"; try { (expected == actual.inspect()) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertEnumEqual: function(expected, actual) { var message = arguments[2] || "assertEnumEqual"; try { $A(expected).length == $A(actual).length && expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ? this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + ', actual ' + Test.Unit.inspect(actual)); } catch(e) { this.error(e); } }, assertNotEqual: function(expected, actual) { var message = arguments[2] || "assertNotEqual"; try { (expected != actual) ? this.pass() : this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertIdentical: function(expected, actual) { var message = arguments[2] || "assertIdentical"; try { (expected === actual) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertNotIdentical: function(expected, actual) { var message = arguments[2] || "assertNotIdentical"; try { !(expected === actual) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertNull: function(obj) { var message = arguments[1] || 'assertNull' try { (obj==null) ? this.pass() : this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); } catch(e) { this.error(e); } }, assertMatch: function(expected, actual) { var message = arguments[2] || 'assertMatch'; var regex = new RegExp(expected); try { (regex.exec(actual)) ? this.pass() : this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); } catch(e) { this.error(e); } }, assertHidden: function(element) { var message = arguments[1] || 'assertHidden'; this.assertEqual("none", element.style.display, message); }, assertNotNull: function(object) { var message = arguments[1] || 'assertNotNull'; this.assert(object != null, message); }, assertType: function(expected, actual) { var message = arguments[2] || 'assertType'; try { (actual.constructor == expected) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + (actual.constructor) + '"'); } catch(e) { this.error(e); } }, assertNotOfType: function(expected, actual) { var message = arguments[2] || 'assertNotOfType'; try { (actual.constructor != expected) ? this.pass() : this.fail(message + ': expected "' + Test.Unit.inspect(expected) + '", actual "' + (actual.constructor) + '"'); } catch(e) { this.error(e); } }, assertInstanceOf: function(expected, actual) { var message = arguments[2] || 'assertInstanceOf'; try { (actual instanceof expected) ? this.pass() : this.fail(message + ": object was not an instance of the expected type"); } catch(e) { this.error(e); } }, assertNotInstanceOf: function(expected, actual) { var message = arguments[2] || 'assertNotInstanceOf'; try { !(actual instanceof expected) ? this.pass() : this.fail(message + ": object was an instance of the not expected type"); } catch(e) { this.error(e); } }, assertRespondsTo: function(method, obj) { var message = arguments[2] || 'assertRespondsTo'; try { (obj[method] && typeof obj[method] == 'function') ? this.pass() : this.fail(message + ": object doesn't respond to [" + method + "]"); } catch(e) { this.error(e); } }, assertReturnsTrue: function(method, obj) { var message = arguments[2] || 'assertReturnsTrue'; try { var m = obj[method]; if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)]; m() ? this.pass() : this.fail(message + ": method returned false"); } catch(e) { this.error(e); } }, assertReturnsFalse: function(method, obj) { var message = arguments[2] || 'assertReturnsFalse'; try { var m = obj[method]; if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)]; !m() ? this.pass() : this.fail(message + ": method returned true"); } catch(e) { this.error(e); } }, assertRaise: function(exceptionName, method) { var message = arguments[2] || 'assertRaise'; try { method(); this.fail(message + ": exception expected but none was raised"); } catch(e) { ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e); } }, assertElementsMatch: function() { var expressions = $A(arguments), elements = $A(expressions.shift()); if (elements.length != expressions.length) { this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions'); return false; } elements.zip(expressions).all(function(pair, index) { var element = $(pair.first()), expression = pair.last(); if (element.match(expression)) return true; this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect()); }.bind(this)) && this.pass(); }, assertElementMatches: function(element, expression) { this.assertElementsMatch([element], expression); }, benchmark: function(operation, iterations) { var startAt = new Date(); (iterations || 1).times(operation); var timeTaken = ((new Date())-startAt); this.info((arguments[2] || 'Operation') + ' finished ' + iterations + ' iterations in ' + (timeTaken/1000)+'s' ); return timeTaken; }, _isVisible: function(element) { element = $(element); if(!element.parentNode) return true; this.assertNotNull(element); if(element.style && Element.getStyle(element, 'display') == 'none') return false; return this._isVisible(element.parentNode); }, assertNotVisible: function(element) { this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1])); }, assertVisible: function(element) { this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1])); }, benchmark: function(operation, iterations) { var startAt = new Date(); (iterations || 1).times(operation); var timeTaken = ((new Date())-startAt); this.info((arguments[2] || 'Operation') + ' finished ' + iterations + ' iterations in ' + (timeTaken/1000)+'s' ); return timeTaken; } } Test.Unit.Testcase = Class.create(); Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), { initialize: function(name, test, setup, teardown) { Test.Unit.Assertions.prototype.initialize.bind(this)(); this.name = name; if(typeof test == 'string') { test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,'); test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)'); this.test = function() { eval('with(this){'+test+'}'); } } else { this.test = test || function() {}; } this.setup = setup || function() {}; this.teardown = teardown || function() {}; this.isWaiting = false; this.timeToWait = 1000; }, wait: function(time, nextPart) { this.isWaiting = true; this.test = nextPart; this.timeToWait = time; }, run: function() { try { try { if (!this.isWaiting) this.setup.bind(this)(); this.isWaiting = false; this.test.bind(this)(); } finally { if(!this.isWaiting) { this.teardown.bind(this)(); } } } catch(e) { this.error(e); } } }); // *EXPERIMENTAL* BDD-style testing to please non-technical folk // This draws many ideas from RSpec http://rspec.rubyforge.org/ Test.setupBDDExtensionMethods = function(){ var METHODMAP = { shouldEqual: 'assertEqual', shouldNotEqual: 'assertNotEqual', shouldEqualEnum: 'assertEnumEqual', shouldBeA: 'assertType', shouldNotBeA: 'assertNotOfType', shouldBeAn: 'assertType', shouldNotBeAn: 'assertNotOfType', shouldBeNull: 'assertNull', shouldNotBeNull: 'assertNotNull', shouldBe: 'assertReturnsTrue', shouldNotBe: 'assertReturnsFalse', shouldRespondTo: 'assertRespondsTo' }; var makeAssertion = function(assertion, args, object) { this[assertion].apply(this,(args || []).concat([object])); } Test.BDDMethods = {}; $H(METHODMAP).each(function(pair) { Test.BDDMethods[pair.key] = function() { var args = $A(arguments); var scope = args.shift(); makeAssertion.apply(scope, [pair.value, args, this]); }; }); [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each( function(p){ Object.extend(p, Test.BDDMethods) } ); } Test.context = function(name, spec, log){ Test.setupBDDExtensionMethods(); var compiledSpec = {}; var titles = {}; for(specName in spec) { switch(specName){ case "setup": case "teardown": compiledSpec[specName] = spec[specName]; break; default: var testName = 'test'+specName.gsub(/\s+/,'-').camelize(); var body = spec[specName].toString().split('\n').slice(1); if(/^\{/.test(body[0])) body = body.slice(1); body.pop(); body = body.map(function(statement){ return statement.strip() }); compiledSpec[testName] = body.join('\n'); titles[testName] = specName; } } new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name }); };AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/dragdrop.js0000766000000000000000000007627111122202526026361 0ustar adminadministrators// script.aculo.us dragdrop.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ if(Object.isUndefined(Effect)) throw("dragdrop.js requires including script.aculo.us' effects.js library"); var Droppables = { drops: [], remove: function(element) { this.drops = this.drops.reject(function(d) { return d.element==$(element) }); }, add: function(element) { element = $(element); var options = Object.extend({ greedy: true, hoverclass: null, tree: false }, arguments[1] || { }); // cache containers if(options.containment) { options._containers = []; var containment = options.containment; if(Object.isArray(containment)) { containment.each( function(c) { options._containers.push($(c)) }); } else { options._containers.push($(containment)); } } if(options.accept) options.accept = [options.accept].flatten(); Element.makePositioned(element); // fix IE options.element = element; this.drops.push(options); }, findDeepestChild: function(drops) { deepest = drops[0]; for (i = 1; i < drops.length; ++i) if (Element.isParent(drops[i].element, deepest.element)) deepest = drops[i]; return deepest; }, isContained: function(element, drop) { var containmentNode; if(drop.tree) { containmentNode = element.treeNode; } else { containmentNode = element.parentNode; } return drop._containers.detect(function(c) { return containmentNode == c }); }, isAffected: function(point, element, drop) { return ( (drop.element!=element) && ((!drop._containers) || this.isContained(element, drop)) && ((!drop.accept) || (Element.classNames(element).detect( function(v) { return drop.accept.include(v) } ) )) && Position.within(drop.element, point[0], point[1]) ); }, deactivate: function(drop) { if(drop.hoverclass) Element.removeClassName(drop.element, drop.hoverclass); // // WARNING PROTOTYPE HACK! "onOut" OPTION IS NOT STANDARD! // if(drop.onOut){ drop.onOut(drop.element); } this.last_active = null; }, activate: function(drop) { if(drop.hoverclass) Element.addClassName(drop.element, drop.hoverclass); this.last_active = drop; }, show: function(point, element) { if(!this.drops.length) return; var drop, affected = []; this.drops.each( function(drop) { if(Droppables.isAffected(point, element, drop)) affected.push(drop); }); if(affected.length>0) drop = Droppables.findDeepestChild(affected); if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); if (drop) { Position.within(drop.element, point[0], point[1]); if(drop.onHover) drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); if (drop != this.last_active) Droppables.activate(drop); } }, fire: function(event, element) { if(!this.last_active) return; Position.prepare(); Position.includeScrollOffsets = true; if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) if (this.last_active.onDrop) { this.last_active.onDrop(element, this.last_active.element, event); return true; } }, reset: function() { if(this.last_active) this.deactivate(this.last_active); } }; var Draggables = { drags: [], observers: [], register: function(draggable) { if(this.drags.length == 0) { this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.updateDrag.bindAsEventListener(this); this.eventKeypress = this.keyPress.bindAsEventListener(this); Event.observe(document, "mouseup", this.eventMouseUp); Event.observe(document, "mousemove", this.eventMouseMove); Event.observe(document, "keypress", this.eventKeypress); } this.drags.push(draggable); }, unregister: function(draggable) { this.drags = this.drags.reject(function(d) { return d==draggable }); if(this.drags.length == 0) { Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); Event.stopObserving(document, "keypress", this.eventKeypress); } }, activate: function(draggable) { if(draggable.options.delay) { this._timeout = setTimeout(function() { Draggables._timeout = null; window.focus(); Draggables.activeDraggable = draggable; }.bind(this), draggable.options.delay); } else { window.focus(); // allows keypress events if window isn't currently focused, fails for Safari this.activeDraggable = draggable; } }, deactivate: function() { this.activeDraggable = null; }, updateDrag: function(event) { if(!this.activeDraggable) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; // Mozilla-based browsers fire successive mousemove events with // the same coordinates, prevent needless redrawing (moz bug?) if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; this._lastPointer = pointer; this.activeDraggable.updateDrag(event, pointer); }, endDrag: function(event) { if(this._timeout) { clearTimeout(this._timeout); this._timeout = null; } if(!this.activeDraggable) return; this._lastPointer = null; this.activeDraggable.endDrag(event); this.activeDraggable = null; }, keyPress: function(event) { if(this.activeDraggable) this.activeDraggable.keyPress(event); }, addObserver: function(observer) { this.observers.push(observer); this._cacheObserverCallbacks(); }, removeObserver: function(element) { // element instead of observer fixes mem leaks this.observers = this.observers.reject( function(o) { return o.element==element }); this._cacheObserverCallbacks(); }, notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' if(this[eventName+'Count'] > 0) this.observers.each( function(o) { if(o[eventName]) o[eventName](eventName, draggable, event); }); if(draggable.options[eventName]) draggable.options[eventName](draggable, event); }, _cacheObserverCallbacks: function() { ['onStart','onEnd','onDrag'].each( function(eventName) { Draggables[eventName+'Count'] = Draggables.observers.select( function(o) { return o[eventName]; } ).length; }); } }; /*--------------------------------------------------------------------------*/ var Draggable = Class.create({ initialize: function(element) { var defaults = { handle: false, reverteffect: function(element, top_offset, left_offset) { var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, queue: {scope:'_draggable', position:'end'} }); }, endeffect: function(element) { var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, queue: {scope:'_draggable', position:'end'}, afterFinish: function(){ Draggable._dragging[element] = false } }); }, zindex: 1000, revert: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } delay: 0 }; if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) Object.extend(defaults, { starteffect: function(element) { element._opacity = Element.getOpacity(element); Draggable._dragging[element] = true; new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); } }); var options = Object.extend(defaults, arguments[1] || { }); this.element = $(element); if(options.handle && Object.isString(options.handle)) this.handle = this.element.down('.'+options.handle, 0); if(!this.handle) this.handle = $(options.handle); if(!this.handle) this.handle = this.element; if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { options.scroll = $(options.scroll); this._isScrollChild = Element.childOf(this.element, options.scroll); } Element.makePositioned(this.element); // fix IE this.options = options; this.dragging = false; this.eventMouseDown = this.initDrag.bindAsEventListener(this); Event.observe(this.handle, "mousedown", this.eventMouseDown); Draggables.register(this); }, destroy: function() { Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); Draggables.unregister(this); }, currentDelta: function() { return([ parseInt(Element.getStyle(this.element,'left') || '0'), parseInt(Element.getStyle(this.element,'top') || '0')]); }, initDrag: function(event) { if(!Object.isUndefined(Draggable._dragging[this.element]) && Draggable._dragging[this.element]) return; if(Event.isLeftClick(event)) { // abort on form elements, fixes a Firefox issue var src = Event.element(event); if((tag_name = src.tagName.toUpperCase()) && ( tag_name=='INPUT' || tag_name=='SELECT' || tag_name=='OPTION' || tag_name=='BUTTON' || tag_name=='TEXTAREA')) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; var pos = Position.cumulativeOffset(this.element); this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); Draggables.activate(this); Event.stop(event); } }, startDrag: function(event) { this.dragging = true; if(!this.delta) this.delta = this.currentDelta(); if(this.options.zindex) { this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); this.element.style.zIndex = this.options.zindex; } if(this.options.ghosting) { this._clone = this.element.cloneNode(true); this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); if (!this.element._originallyAbsolute) Position.absolutize(this.element); this.element.parentNode.insertBefore(this._clone, this.element); } if(this.options.scroll) { if (this.options.scroll == window) { var where = this._getWindowScroll(this.options.scroll); this.originalScrollLeft = where.left; this.originalScrollTop = where.top; } else { this.originalScrollLeft = this.options.scroll.scrollLeft; this.originalScrollTop = this.options.scroll.scrollTop; } } Draggables.notify('onStart', this, event); if(this.options.starteffect) this.options.starteffect(this.element); }, updateDrag: function(event, pointer) { if(!this.dragging) this.startDrag(event); if(!this.options.quiet){ Position.prepare(); Position.includeScrollOffsets = true; Droppables.show(pointer, this.element); } Draggables.notify('onDrag', this, event); this.draw(pointer); if(this.options.change) this.options.change(this); if(this.options.scroll) { this.stopScrolling(); var p; if (this.options.scroll == window) { with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } } else { p = Position.page(this.options.scroll); p[0] += this.options.scroll.scrollLeft + Position.deltaX; p[1] += this.options.scroll.scrollTop + Position.deltaY; p.push(p[0]+this.options.scroll.offsetWidth); p.push(p[1]+this.options.scroll.offsetHeight); } var speed = [0,0]; if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); this.startScrolling(speed); } // fix AppleWebKit rendering if(Prototype.Browser.WebKit) window.scrollBy(0,0); Event.stop(event); }, finishDrag: function(event, success) { this.dragging = false; if(this.options.quiet){ Position.prepare(); Position.includeScrollOffsets = true; var pointer = [Event.pointerX(event), Event.pointerY(event)]; Droppables.show(pointer, this.element); } if(this.options.ghosting) { if (!this.element._originallyAbsolute) Position.relativize(this.element); delete this.element._originallyAbsolute; Element.remove(this._clone); this._clone = null; } var dropped = false; if(success) { dropped = Droppables.fire(event, this.element); if (!dropped) dropped = false; } if(dropped && this.options.onDropped) this.options.onDropped(this.element); Draggables.notify('onEnd', this, event); var revert = this.options.revert; if(revert && Object.isFunction(revert)) revert = revert(this.element); var d = this.currentDelta(); if(revert && this.options.reverteffect) { if (dropped == 0 || revert != 'failure') this.options.reverteffect(this.element, d[1]-this.delta[1], d[0]-this.delta[0]); } else { this.delta = d; } if(this.options.zindex) this.element.style.zIndex = this.originalZ; if(this.options.endeffect) this.options.endeffect(this.element); Draggables.deactivate(this); Droppables.reset(); }, keyPress: function(event) { if(event.keyCode!=Event.KEY_ESC) return; this.finishDrag(event, false); Event.stop(event); }, endDrag: function(event) { if(!this.dragging) return; this.stopScrolling(); this.finishDrag(event, true); Event.stop(event); }, draw: function(point) { var pos = Position.cumulativeOffset(this.element); if(this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; } var d = this.currentDelta(); pos[0] -= d[0]; pos[1] -= d[1]; if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; } var p = [0,1].map(function(i){ return (point[i]-pos[i]-this.offset[i]) }.bind(this)); if(this.options.snap) { if(Object.isFunction(this.options.snap)) { p = this.options.snap(p[0],p[1],this); } else { if(Object.isArray(this.options.snap)) { p = p.map( function(v, i) { return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)) } else { p = p.map( function(v) { return (v/this.options.snap).round()*this.options.snap }.bind(this)) } }} var style = this.element.style; if((!this.options.constraint) || (this.options.constraint=='horizontal')) style.left = p[0] + "px"; if((!this.options.constraint) || (this.options.constraint=='vertical')) style.top = p[1] + "px"; if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering }, stopScrolling: function() { if(this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; Draggables._lastScrollPointer = null; } }, startScrolling: function(speed) { if(!(speed[0] || speed[1])) return; this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; this.lastScrolled = new Date(); this.scrollInterval = setInterval(this.scroll.bind(this), 10); }, scroll: function() { var current = new Date(); var delta = current - this.lastScrolled; this.lastScrolled = current; if(this.options.scroll == window) { with (this._getWindowScroll(this.options.scroll)) { if (this.scrollSpeed[0] || this.scrollSpeed[1]) { var d = delta / 1000; this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); } } } else { this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; } Position.prepare(); Position.includeScrollOffsets = true; Droppables.show(Draggables._lastPointer, this.element); Draggables.notify('onDrag', this); if (this._isScrollChild) { Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; if (Draggables._lastScrollPointer[0] < 0) Draggables._lastScrollPointer[0] = 0; if (Draggables._lastScrollPointer[1] < 0) Draggables._lastScrollPointer[1] = 0; this.draw(Draggables._lastScrollPointer); } if(this.options.change) this.options.change(this); }, _getWindowScroll: function(w) { var T, L, W, H; with (w.document) { if (w.document.documentElement && documentElement.scrollTop) { T = documentElement.scrollTop; L = documentElement.scrollLeft; } else if (w.document.body) { T = body.scrollTop; L = body.scrollLeft; } if (w.innerWidth) { W = w.innerWidth; H = w.innerHeight; } else if (w.document.documentElement && documentElement.clientWidth) { W = documentElement.clientWidth; H = documentElement.clientHeight; } else { W = body.offsetWidth; H = body.offsetHeight } } return { top: T, left: L, width: W, height: H }; } }); Draggable._dragging = { }; /*--------------------------------------------------------------------------*/ var SortableObserver = Class.create({ initialize: function(element, observer) { this.element = $(element); this.observer = observer; this.lastValue = Sortable.serialize(this.element); }, onStart: function() { this.lastValue = Sortable.serialize(this.element); }, onEnd: function() { Sortable.unmark(); if(this.lastValue != Sortable.serialize(this.element)) this.observer(this.element) } }); var Sortable = { SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, sortables: { }, _findRootElement: function(element) { while (element.tagName.toUpperCase() != "BODY") { if(element.id && Sortable.sortables[element.id]) return element; element = element.parentNode; } }, options: function(element) { element = Sortable._findRootElement($(element)); if(!element) return; return Sortable.sortables[element.id]; }, destroy: function(element){ var s = Sortable.options(element); if(s) { Draggables.removeObserver(s.element); s.droppables.each(function(d){ Droppables.remove(d) }); s.draggables.invoke('destroy'); delete Sortable.sortables[s.element.id]; } }, create: function(element) { element = $(element); var options = Object.extend({ element: element, tag: 'li', // assumes li children, override with tag: 'tagname' dropOnEmpty: false, tree: false, treeTag: 'ul', overlap: 'vertical', // one of 'vertical', 'horizontal' constraint: 'vertical', // one of 'vertical', 'horizontal', false containment: element, // also takes array of elements (or id's); or false handle: false, // or a CSS class only: false, delay: 0, hoverclass: null, ghosting: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, format: this.SERIALIZE_RULE, // these take arrays of elements or ids and can be // used for better initialization performance elements: false, handles: false, onChange: Prototype.emptyFunction, onUpdate: Prototype.emptyFunction }, arguments[1] || { }); // clear any old sortable with same element this.destroy(element); // build options for the draggables var options_for_draggable = { revert: true, quiet: options.quiet, scroll: options.scroll, scrollSpeed: options.scrollSpeed, scrollSensitivity: options.scrollSensitivity, delay: options.delay, ghosting: options.ghosting, constraint: options.constraint, handle: options.handle }; if(options.starteffect) options_for_draggable.starteffect = options.starteffect; if(options.reverteffect) options_for_draggable.reverteffect = options.reverteffect; else if(options.ghosting) options_for_draggable.reverteffect = function(element) { element.style.top = 0; element.style.left = 0; }; if(options.endeffect) options_for_draggable.endeffect = options.endeffect; if(options.zindex) options_for_draggable.zindex = options.zindex; // build options for the droppables var options_for_droppable = { overlap: options.overlap, containment: options.containment, tree: options.tree, hoverclass: options.hoverclass, onHover: Sortable.onHover }; var options_for_tree = { onHover: Sortable.onEmptyHover, overlap: options.overlap, containment: options.containment, hoverclass: options.hoverclass }; // fix for gecko engine Element.cleanWhitespace(element); options.draggables = []; options.droppables = []; // drop on empty handling if(options.dropOnEmpty || options.tree) { Droppables.add(element, options_for_tree); options.droppables.push(element); } (options.elements || this.findElements(element, options) || []).each( function(e,i) { var handle = options.handles ? $(options.handles[i]) : (options.handle ? $(e).select('.' + options.handle)[0] : e); options.draggables.push( new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); Droppables.add(e, options_for_droppable); if(options.tree) e.treeNode = element; options.droppables.push(e); }); if(options.tree) { (Sortable.findTreeElements(element, options) || []).each( function(e) { Droppables.add(e, options_for_tree); e.treeNode = element; options.droppables.push(e); }); } // keep reference this.sortables[element.id] = options; // for onupdate Draggables.addObserver(new SortableObserver(element, options.onUpdate)); }, // return all suitable-for-sortable elements in a guaranteed order findElements: function(element, options) { return Element.findChildren( element, options.only, options.tree ? true : false, options.tag); }, findTreeElements: function(element, options) { return Element.findChildren( element, options.only, options.tree ? true : false, options.treeTag); }, onHover: function(element, dropon, overlap) { if(Element.isParent(dropon, element)) return; if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { return; } else if(overlap>0.5) { Sortable.mark(dropon, 'before'); if(dropon.previousSibling != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; // fix gecko rendering dropon.parentNode.insertBefore(element, dropon); if(dropon.parentNode!=oldParentNode) Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element); } } else { Sortable.mark(dropon, 'after'); var nextElement = dropon.nextSibling || null; if(nextElement != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; // fix gecko rendering dropon.parentNode.insertBefore(element, nextElement); if(dropon.parentNode!=oldParentNode) Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element); } } }, onEmptyHover: function(element, dropon, overlap) { var oldParentNode = element.parentNode; var droponOptions = Sortable.options(dropon); if(!Element.isParent(dropon, element)) { var index; var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); var child = null; if(children) { var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); for (index = 0; index < children.length; index += 1) { if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { offset -= Element.offsetSize (children[index], droponOptions.overlap); } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { child = index + 1 < children.length ? children[index + 1] : null; break; } else { child = children[index]; break; } } } dropon.insertBefore(element, child); Sortable.options(oldParentNode).onChange(element); droponOptions.onChange(element); } }, unmark: function() { if(Sortable._marker) Sortable._marker.hide(); }, mark: function(dropon, position) { // mark on ghosting only var sortable = Sortable.options(dropon.parentNode); if(sortable && !sortable.ghosting) return; if(!Sortable._marker) { Sortable._marker = ($('dropmarker') || Element.extend(document.createElement('DIV'))). hide().addClassName('dropmarker').setStyle({position:'absolute'}); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); } var offsets = Position.cumulativeOffset(dropon); Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); if(position=='after') if(sortable.overlap == 'horizontal') Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); else Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); Sortable._marker.show(); }, _tree: function(element, options, parent) { var children = Sortable.findElements(element, options) || []; for (var i = 0; i < children.length; ++i) { var match = children[i].id.match(options.format); if (!match) continue; var child = { id: encodeURIComponent(match ? match[1] : null), element: element, parent: parent, children: [], position: parent.children.length, container: $(children[i]).down(options.treeTag) }; /* Get the element containing the children and recurse over it */ if (child.container) this._tree(child.container, options, child); parent.children.push (child); } return parent; }, tree: function(element) { element = $(element); var sortableOptions = this.options(element); var options = Object.extend({ tag: sortableOptions.tag, treeTag: sortableOptions.treeTag, only: sortableOptions.only, name: element.id, format: sortableOptions.format }, arguments[1] || { }); var root = { id: null, parent: null, children: [], container: element, position: 0 }; return Sortable._tree(element, options, root); }, /* Construct a [i] index for a particular node */ _constructIndex: function(node) { var index = ''; do { if (node.id) index = '[' + node.position + ']' + index; } while ((node = node.parent) != null); return index; }, sequence: function(element) { element = $(element); var options = Object.extend(this.options(element), arguments[1] || { }); return $(this.findElements(element, options) || []).map( function(item) { return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; }); }, setSequence: function(element, new_sequence) { element = $(element); var options = Object.extend(this.options(element), arguments[2] || { }); var nodeMap = { }; this.findElements(element, options).each( function(n) { if (n.id.match(options.format)) nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; n.parentNode.removeChild(n); }); new_sequence.each(function(ident) { var n = nodeMap[ident]; if (n) { n[1].appendChild(n[0]); delete nodeMap[ident]; } }); }, serialize: function(element) { element = $(element); var options = Object.extend(Sortable.options(element), arguments[1] || { }); var name = encodeURIComponent( (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); if (options.tree) { return Sortable.tree(element, arguments[1]).children.map( function (item) { return [name + Sortable._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); }).flatten().join('&'); } else { return Sortable.sequence(element, arguments[1]).map( function(item) { return name + "[]=" + encodeURIComponent(item); }).join('&'); } } }; // Returns true if child is contained within element Element.isParent = function(child, element) { if (!child.parentNode || child == element) return false; if (child.parentNode == element) return true; return Element.isParent(child.parentNode, element); }; Element.findChildren = function(element, only, recursive, tagName) { if(!element.hasChildNodes()) return null; tagName = tagName.toUpperCase(); if(only) only = [only].flatten(); var elements = []; $A(element.childNodes).each( function(e) { if(e.tagName && e.tagName.toUpperCase()==tagName && (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) elements.push(e); if(recursive) { var grandchildren = Element.findChildren(e, only, recursive, tagName); if(grandchildren) elements.push(grandchildren); } }); return (elements.length>0 ? elements.flatten() : []); }; Element.offsetSize = function (element, type) { return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; }; AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/effects.js0000766000000000000000000011411311122202526026162 0ustar adminadministrators// script.aculo.us effects.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) // Martin Bialasinki // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ // converts rgb() and #xxx to #xxxxxx format, // returns self (or first argument) if not convertable String.prototype.parseColor = function() { var color = '#'; if (this.slice(0,4) == 'rgb(') { var cols = this.slice(4,this.length-1).split(','); var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); } else { if (this.slice(0,1) == '#') { if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); if (this.length==7) color = this.toLowerCase(); } } return (color.length==7 ? color : (arguments[0] || this)); }; /*--------------------------------------------------------------------------*/ Element.collectTextNodes = function(element) { return $A($(element).childNodes).collect( function(node) { return (node.nodeType==3 ? node.nodeValue : (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); }).flatten().join(''); }; Element.collectTextNodesIgnoreClass = function(element, className) { return $A($(element).childNodes).collect( function(node) { return (node.nodeType==3 ? node.nodeValue : ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? Element.collectTextNodesIgnoreClass(node, className) : '')); }).flatten().join(''); }; Element.setContentZoom = function(element, percent) { element = $(element); element.setStyle({fontSize: (percent/100) + 'em'}); if (Prototype.Browser.WebKit) window.scrollBy(0,0); return element; }; Element.getInlineOpacity = function(element){ return $(element).style.opacity || ''; }; Element.forceRerendering = function(element) { try { element = $(element); var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch(e) { } }; /*--------------------------------------------------------------------------*/ var Effect = { _elementDoesNotExistError: { name: 'ElementDoesNotExistError', message: 'The specified DOM element does not exist, but is required for this effect to operate' }, Transitions: { linear: Prototype.K, sinoidal: function(pos) { return (-Math.cos(pos*Math.PI)/2) + 0.5; }, reverse: function(pos) { return 1-pos; }, flicker: function(pos) { var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; return pos > 1 ? 1 : pos; }, wobble: function(pos) { return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; }, pulse: function(pos, pulses) { pulses = pulses || 5; return ( ((pos % (1/pulses)) * pulses).round() == 0 ? ((pos * pulses * 2) - (pos * pulses * 2).floor()) : 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) ); }, spring: function(pos) { return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); }, none: function(pos) { return 0; }, full: function(pos) { return 1; } }, DefaultOptions: { duration: 1.0, // seconds fps: 100, // 100= assume 66fps max. sync: false, // true for combining from: 0.0, to: 1.0, delay: 0.0, queue: 'parallel' }, tagifyText: function(element) { var tagifyStyle = 'position:relative'; if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { if (child.nodeType==3) { child.nodeValue.toArray().each( function(character) { element.insertBefore( new Element('span', {style: tagifyStyle}).update( character == ' ' ? String.fromCharCode(160) : character), child); }); Element.remove(child); } }); }, multiple: function(element, effect) { var elements; if (((typeof element == 'object') || Object.isFunction(element)) && (element.length)) elements = element; else elements = $(element).childNodes; var options = Object.extend({ speed: 0.1, delay: 0.0 }, arguments[2] || { }); var masterDelay = options.delay; $A(elements).each( function(element, index) { new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); }); }, PAIRS: { 'slide': ['SlideDown','SlideUp'], 'blind': ['BlindDown','BlindUp'], 'appear': ['Appear','Fade'] }, toggle: function(element, effect) { element = $(element); effect = (effect || 'appear').toLowerCase(); var options = Object.extend({ queue: { position:'end', scope:(element.id || 'global'), limit: 1 } }, arguments[2] || { }); Effect[element.visible() ? Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); } }; Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; /* ------------- core effects ------------- */ Effect.ScopedQueue = Class.create(Enumerable, { initialize: function() { this.effects = []; this.interval = null; }, _each: function(iterator) { this.effects._each(iterator); }, add: function(effect) { var timestamp = new Date().getTime(); var position = Object.isString(effect.options.queue) ? effect.options.queue : effect.options.queue.position; switch(position) { case 'front': // move unstarted effects after this effect this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { e.startOn += effect.finishOn; e.finishOn += effect.finishOn; }); break; case 'with-last': timestamp = this.effects.pluck('startOn').max() || timestamp; break; case 'end': // start effect after last queued effect has finished timestamp = this.effects.pluck('finishOn').max() || timestamp; break; } effect.startOn += timestamp; effect.finishOn += timestamp; if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect); if (!this.interval) this.interval = setInterval(this.loop.bind(this), 15); }, remove: function(effect) { this.effects = this.effects.reject(function(e) { return e==effect }); if (this.effects.length == 0) { clearInterval(this.interval); this.interval = null; } }, loop: function() { var timePos = new Date().getTime(); for(var i=0, len=this.effects.length;i= this.startOn) { if (timePos >= this.finishOn) { this.render(1.0); this.cancel(); this.event('beforeFinish'); if (this.finish) this.finish(); this.event('afterFinish'); return; } var pos = (timePos - this.startOn) / this.totalTime, frame = (pos * this.totalFrames).round(); if (frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, cancel: function() { if (!this.options.sync) Effect.Queues.get(Object.isString(this.options.queue) ? 'global' : this.options.queue.scope).remove(this); this.state = 'finished'; }, event: function(eventName) { if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); if (this.options[eventName]) this.options[eventName](this); }, inspect: function() { var data = $H(); for(property in this) if (!Object.isFunction(this[property])) data.set(property, this[property]); return '#'; } }); Effect.Parallel = Class.create(Effect.Base, { initialize: function(effects) { this.effects = effects || []; this.start(arguments[1]); }, update: function(position) { this.effects.invoke('render', position); }, finish: function(position) { this.effects.each( function(effect) { effect.render(1.0); effect.cancel(); effect.event('beforeFinish'); if (effect.finish) effect.finish(position); effect.event('afterFinish'); }); } }); Effect.Tween = Class.create(Effect.Base, { initialize: function(object, from, to) { object = Object.isString(object) ? $(object) : object; var args = $A(arguments), method = args.last(), options = args.length == 5 ? args[3] : null; this.method = Object.isFunction(method) ? method.bind(object) : Object.isFunction(object[method]) ? object[method].bind(object) : function(value) { object[method] = value }; this.start(Object.extend({ from: from, to: to }, options || { })); }, update: function(position) { this.method(position); } }); Effect.Event = Class.create(Effect.Base, { initialize: function() { this.start(Object.extend({ duration: 0 }, arguments[0] || { })); }, update: Prototype.emptyFunction }); Effect.Opacity = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); // make this work on IE on elements without 'layout' if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, to: 1.0 }, arguments[1] || { }); this.start(options); }, update: function(position) { this.element.setOpacity(position); } }); Effect.Move = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ x: 0, y: 0, mode: 'relative' }, arguments[1] || { }); this.start(options); }, setup: function() { this.element.makePositioned(); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); if (this.options.mode == 'absolute') { this.options.x = this.options.x - this.originalLeft; this.options.y = this.options.y - this.originalTop; } }, update: function(position) { this.element.setStyle({ left: (this.options.x * position + this.originalLeft).round() + 'px', top: (this.options.y * position + this.originalTop).round() + 'px' }); } }); // for backwards compatibility Effect.MoveBy = function(element, toTop, toLeft) { return new Effect.Move(element, Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); }; Effect.Scale = Class.create(Effect.Base, { initialize: function(element, percent) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: 'box', // 'box' or 'contents' or { } with provided values scaleFrom: 100.0, scaleTo: percent }, arguments[2] || { }); this.start(options); }, setup: function() { this.restoreAfterFinish = this.options.restoreAfterFinish || false; this.elementPositioning = this.element.getStyle('position'); this.originalStyle = { }; ['top','left','width','height','fontSize'].each( function(k) { this.originalStyle[k] = this.element.style[k]; }.bind(this)); this.originalTop = this.element.offsetTop; this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; ['em','px','%','pt'].each( function(fontSizeType) { if (fontSize.indexOf(fontSizeType)>0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType; } }.bind(this)); this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; this.dims = null; if (this.options.scaleMode=='box') this.dims = [this.element.offsetHeight, this.element.offsetWidth]; if (/^content/.test(this.options.scaleMode)) this.dims = [this.element.scrollHeight, this.element.scrollWidth]; if (!this.dims) this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth]; }, update: function(position) { var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); if (this.options.scaleContent && this.fontSize) this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); }, finish: function(position) { if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); }, setDimensions: function(height, width) { var d = { }; if (this.options.scaleX) d.width = width.round() + 'px'; if (this.options.scaleY) d.height = height.round() + 'px'; if (this.options.scaleFromCenter) { var topd = (height - this.dims[0])/2; var leftd = (width - this.dims[1])/2; if (this.elementPositioning == 'absolute') { if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; } else { if (this.options.scaleY) d.top = -topd + 'px'; if (this.options.scaleX) d.left = -leftd + 'px'; } } this.element.setStyle(d); } }); Effect.Highlight = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); this.start(options); }, setup: function() { // Prevent executing on elements not in the layout flow if (this.element.getStyle('display')=='none') { this.cancel(); return; } // Disable background image during the effect this.oldStyle = { }; if (!this.options.keepBackgroundImage) { this.oldStyle.backgroundImage = this.element.getStyle('background-image'); this.element.setStyle({backgroundImage: 'none'}); } if (!this.options.endcolor) this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); if (!this.options.restorecolor) this.options.restorecolor = this.element.getStyle('background-color'); // init color calculations this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); }, update: function(position) { this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); }, finish: function() { this.element.setStyle(Object.extend(this.oldStyle, { backgroundColor: this.options.restorecolor })); } }); Effect.ScrollTo = function(element) { var options = arguments[1] || { }, scrollOffsets = document.viewport.getScrollOffsets(), elementOffsets = $(element).cumulativeOffset(), max = (window.height || document.body.scrollHeight) - document.viewport.getHeight(); if (options.offset) elementOffsets[1] += options.offset; return new Effect.Tween(null, scrollOffsets.top, elementOffsets[1] > max ? max : elementOffsets[1], options, function(p){ scrollTo(scrollOffsets.left, p.round()) } ); }; /* ------------- combination effects ------------- */ Effect.Fade = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); var options = Object.extend({ from: element.getOpacity() || 1.0, to: 0.0, afterFinishInternal: function(effect) { if (effect.options.to!=0) return; effect.element.hide().setStyle({opacity: oldOpacity}); } }, arguments[1] || { }); return new Effect.Opacity(element,options); }; Effect.Appear = function(element) { element = $(element); var options = Object.extend({ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), to: 1.0, // force Safari to render floated elements properly afterFinishInternal: function(effect) { effect.element.forceRerendering(); }, beforeSetup: function(effect) { effect.element.setOpacity(effect.options.from).show(); }}, arguments[1] || { }); return new Effect.Opacity(element,options); }; Effect.Puff = function(element) { element = $(element); var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position'), top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; return new Effect.Parallel( [ new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], Object.extend({ duration: 1.0, beforeSetupInternal: function(effect) { Position.absolutize(effect.effects[0].element) }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().setStyle(oldStyle); } }, arguments[1] || { }) ); }; Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, afterFinishInternal: function(effect) { effect.element.hide().undoClipping(); } }, arguments[1] || { }) ); }; Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makeClipping().setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { effect.element.undoClipping(); } }, arguments[1] || { })); }; Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, afterFinishInternal: function(effect) { new Effect.Scale(effect.element, 1, { duration: 0.3, scaleFromCenter: true, scaleX: false, scaleContent: false, restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); } }) } }, arguments[1] || { })); }; Effect.DropOut = function(element) { element = $(element); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left'), opacity: element.getInlineOpacity() }; return new Effect.Parallel( [ new Effect.Move(element, {x: 0, y: 100, sync: true }), new Effect.Opacity(element, { sync: true, to: 0.0 }) ], Object.extend( { duration: 0.5, beforeSetup: function(effect) { effect.effects[0].element.makePositioned(); }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); } }, arguments[1] || { })); }; Effect.Shake = function(element) { element = $(element); var options = Object.extend({ distance: 20, duration: 0.5 }, arguments[1] || {}); var distance = parseFloat(options.distance); var split = parseFloat(options.duration) / 10.0; var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { effect.element.undoPositioned().setStyle(oldStyle); }}) }}) }}) }}) }}) }}); }; Effect.SlideDown = function(element) { element = $(element).cleanWhitespace(); // SlideDown need to have the content of the element wrapped in a container element with fixed height! var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: window.opera ? 0 : 1, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().setStyle({height: '0px'}).show(); }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { effect.element.undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } }, arguments[1] || { }) ); }; Effect.SlideUp = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', scaleFrom: 100, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({top: ''}); effect.element.makeClipping().show(); }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } }, arguments[1] || { }) ); }; // Bug in opera makes the TD containing this element expand for a instance after finish Effect.Squish = function(element) { return new Effect.Scale(element, window.opera ? 1 : 0, { restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makeClipping(); }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping(); } }); }; Effect.Grow = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.full }, arguments[1] || { }); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var initialMoveX, initialMoveY; var moveX, moveY; switch (options.direction) { case 'top-left': initialMoveX = initialMoveY = moveX = moveY = 0; break; case 'top-right': initialMoveX = dims.width; initialMoveY = moveY = 0; moveX = -dims.width; break; case 'bottom-left': initialMoveX = moveX = 0; initialMoveY = dims.height; moveY = -dims.height; break; case 'bottom-right': initialMoveX = dims.width; initialMoveY = dims.height; moveX = -dims.width; moveY = -dims.height; break; case 'center': initialMoveX = dims.width / 2; initialMoveY = dims.height / 2; moveX = -dims.width / 2; moveY = -dims.height / 2; break; } return new Effect.Move(element, { x: initialMoveX, y: initialMoveY, duration: 0.01, beforeSetup: function(effect) { effect.element.hide().makeClipping().makePositioned(); }, afterFinishInternal: function(effect) { new Effect.Parallel( [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), new Effect.Scale(effect.element, 100, { scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) ], Object.extend({ beforeSetup: function(effect) { effect.effects[0].element.setStyle({height: '0px'}).show(); }, afterFinishInternal: function(effect) { effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ) } }); }; Effect.Shrink = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.none }, arguments[1] || { }); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var moveX, moveY; switch (options.direction) { case 'top-left': moveX = moveY = 0; break; case 'top-right': moveX = dims.width; moveY = 0; break; case 'bottom-left': moveX = 0; moveY = dims.height; break; case 'bottom-right': moveX = dims.width; moveY = dims.height; break; case 'center': moveX = dims.width / 2; moveY = dims.height / 2; break; } return new Effect.Parallel( [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) ], Object.extend({ beforeStartInternal: function(effect) { effect.effects[0].element.makePositioned().makeClipping(); }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } }, options) ); }; Effect.Pulsate = function(element) { element = $(element); var options = arguments[1] || { }; var oldOpacity = element.getInlineOpacity(); var transition = options.transition || Effect.Transitions.sinoidal; var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; reverser.bind(transition); return new Effect.Opacity(element, Object.extend(Object.extend({ duration: 2.0, from: 0, afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } }, options), {transition: reverser})); }; Effect.Fold = function(element) { element = $(element); var oldStyle = { top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; element.makeClipping(); return new Effect.Scale(element, 5, Object.extend({ scaleContent: false, scaleX: false, afterFinishInternal: function(effect) { new Effect.Scale(element, 1, { scaleContent: false, scaleY: false, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().setStyle(oldStyle); } }); }}, arguments[1] || { })); }; Effect.Morph = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw(Effect._elementDoesNotExistError); var options = Object.extend({ style: { } }, arguments[1] || { }); if (!Object.isString(options.style)) this.style = $H(options.style); else { if (options.style.include(':')) this.style = options.style.parseStyle(); else { this.element.addClassName(options.style); this.style = $H(this.element.getStyles()); this.element.removeClassName(options.style); var css = this.element.getStyles(); this.style = this.style.reject(function(style) { return style.value == css[style.key]; }); options.afterFinishInternal = function(effect) { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { effect.element.style[transform.style] = ''; }); } } } this.start(options); }, setup: function(){ function parseColor(color){ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; color = color.parseColor(); return $R(0,2).map(function(i){ return parseInt( color.slice(i*2+1,i*2+3), 16 ) }); } this.transforms = this.style.map(function(pair){ var property = pair[0], value = pair[1], unit = null; if (value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color'; } else if (property == 'opacity') { value = parseFloat(value); if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); } else if (Element.CSS_LENGTH.test(value)) { var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); value = parseFloat(components[1]); unit = (components.length == 3) ? components[2] : null; } var originalValue = this.element.getStyle(property); return { style: property.camelize(), originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit=='color' ? parseColor(value) : value, unit: unit }; }.bind(this)).reject(function(transform){ return ( (transform.originalValue == transform.targetValue) || ( transform.unit != 'color' && (isNaN(transform.originalValue) || isNaN(transform.targetValue)) ) ) }); }, update: function(position) { var style = { }, transform, i = this.transforms.length; while(i--) style[(transform = this.transforms[i]).style] = transform.unit=='color' ? '#'+ (Math.round(transform.originalValue[0]+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + (Math.round(transform.originalValue[1]+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + (Math.round(transform.originalValue[2]+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : (transform.originalValue + (transform.targetValue - transform.originalValue) * position).toFixed(3) + (transform.unit === null ? '' : transform.unit); this.element.setStyle(style, true); } }); Effect.Transform = Class.create({ initialize: function(tracks){ this.tracks = []; this.options = arguments[1] || { }; this.addTracks(tracks); }, addTracks: function(tracks){ tracks.each(function(track){ track = $H(track); var data = track.values().first(); this.tracks.push($H({ ids: track.keys().first(), effect: Effect.Morph, options: { style: data } })); }.bind(this)); return this; }, play: function(){ return new Effect.Parallel( this.tracks.map(function(track){ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); var elements = [$(ids) || $$(ids)].flatten(); return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); }).flatten(), this.options ); } }); Element.CSS_PROPERTIES = $w( 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 'fontSize fontWeight height left letterSpacing lineHeight ' + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 'right textIndent top width wordSpacing zIndex'); Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.__parseStyleElement = document.createElement('div'); String.prototype.parseStyle = function(){ var style, styleRules = $H(); if (Prototype.Browser.WebKit) style = new Element('div',{style:this}).style; else { String.__parseStyleElement.innerHTML = '
    '; style = String.__parseStyleElement.childNodes[0].style; } Element.CSS_PROPERTIES.each(function(property){ if (style[property]) styleRules.set(property, style[property]); }); if (Prototype.Browser.IE && this.include('opacity')) styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); return styleRules; }; if (document.defaultView && document.defaultView.getComputedStyle) { Element.getStyles = function(element) { var css = document.defaultView.getComputedStyle($(element), null); return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { styles[property] = css[property]; return styles; }); }; } else { Element.getStyles = function(element) { element = $(element); var css = element.currentStyle, styles; styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) { hash.set(property, css[property]); return hash; }); if (!styles.opacity) styles.set('opacity', element.getOpacity()); return styles; }; }; Effect.Methods = { morph: function(element, style) { element = $(element); new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); return element; }, visualEffect: function(element, effect, options) { element = $(element); var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); new Effect[klass](element, options); return element; }, highlight: function(element, options) { element = $(element); new Effect.Highlight(element, options); return element; } }; $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ 'pulsate shake puff squish switchOff dropOut').each( function(effect) { Effect.Methods[effect] = function(element, options){ element = $(element); Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); return element; } } ); $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( function(f) { Effect.Methods[f] = Element[f]; } ); Element.addMethods(Effect.Methods); AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/controls.js0000766000000000000000000010416511122202526026414 0ustar adminadministrators// script.aculo.us controls.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) // Contributors: // Richard Livsey // Rahul Bhargava // Rob Wills // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ // Autocompleter.Base handles all the autocompletion functionality // that's independent of the data source for autocompletion. This // includes drawing the autocompletion menu, observing keyboard // and mouse events, and similar. // // Specific autocompleters need to provide, at the very least, // a getUpdatedChoices function that will be invoked every time // the text inside the monitored textbox changes. This method // should get the text for which to provide autocompletion by // invoking this.getToken(), NOT by directly accessing // this.element.value. This is to allow incremental tokenized // autocompletion. Specific auto-completion logic (AJAX, etc) // belongs in getUpdatedChoices. // // Tokenized incremental autocompletion is enabled automatically // when an autocompleter is instantiated with the 'tokens' option // in the options parameter, e.g.: // new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); // will incrementally autocomplete with a comma as the token. // Additionally, ',' in the above example can be replaced with // a token array, e.g. { tokens: [',', '\n'] } which // enables autocompletion on multiple tokens. This is most // useful when one of the tokens is \n (a newline), as it // allows smart autocompletion after linebreaks. if(typeof Effect == 'undefined') throw("controls.js requires including script.aculo.us' effects.js library"); var Autocompleter = { }; Autocompleter.Base = Class.create({ baseInitialize: function(element, update, options) { element = $(element); this.element = element; this.update = $(update); this.hasFocus = false; this.changed = false; this.active = false; this.index = 0; this.entryCount = 0; this.oldElementValue = this.element.value; if(this.setOptions) this.setOptions(options); else this.options = options || { }; this.options.paramName = this.options.paramName || this.element.name; this.options.tokens = this.options.tokens || []; this.options.frequency = this.options.frequency || 0.4; this.options.minChars = this.options.minChars || 1; this.options.onShow = this.options.onShow || function(element, update){ if(!update.style.position || update.style.position=='absolute') { update.style.position = 'absolute'; Position.clone(element, update, { setHeight: false, offsetTop: element.offsetHeight }); } Effect.Appear(update,{duration:0.15}); }; this.options.onHide = this.options.onHide || function(element, update){ new Effect.Fade(update,{duration:0.15}) }; if(typeof(this.options.tokens) == 'string') this.options.tokens = new Array(this.options.tokens); // Force carriage returns as token delimiters anyway if (!this.options.tokens.include('\n')) this.options.tokens.push('\n'); this.observer = null; this.element.setAttribute('autocomplete','off'); Element.hide(this.update); Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this)); }, show: function() { if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); if(!this.iefix && (Prototype.Browser.IE) && (Element.getStyle(this.update, 'position')=='absolute')) { new Insertion.After(this.update, ''); this.iefix = $(this.update.id+'_iefix'); } if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); }, fixIEOverlapping: function() { Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); this.iefix.style.zIndex = 1; this.update.style.zIndex = 2; Element.show(this.iefix); }, hide: function() { this.stopIndicator(); if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); if(this.iefix) Element.hide(this.iefix); }, startIndicator: function() { if(this.options.indicator) Element.show(this.options.indicator); }, stopIndicator: function() { if(this.options.indicator) Element.hide(this.options.indicator); }, onKeyPress: function(event) { if(this.active) switch(event.keyCode) { case Event.KEY_TAB: case Event.KEY_RETURN: this.selectEntry(); Event.stop(event); case Event.KEY_ESC: this.hide(); this.active = false; Event.stop(event); return; case Event.KEY_LEFT: case Event.KEY_RIGHT: return; case Event.KEY_UP: this.markPrevious(); this.render(); if(Prototype.Browser.WebKit) Event.stop(event); return; case Event.KEY_DOWN: this.markNext(); this.render(); if(Prototype.Browser.WebKit) Event.stop(event); return; } else if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; this.changed = true; this.hasFocus = true; if(this.observer) clearTimeout(this.observer); this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); }, activate: function() { this.changed = false; this.hasFocus = true; this.getUpdatedChoices(); }, onHover: function(event) { var element = Event.findElement(event, 'LI'); if(this.index != element.autocompleteIndex) { this.index = element.autocompleteIndex; this.render(); } Event.stop(event); }, onClick: function(event) { var element = Event.findElement(event, 'LI'); this.index = element.autocompleteIndex; this.selectEntry(); this.hide(); }, onBlur: function(event) { // needed to make click events working setTimeout(this.hide.bind(this), 250); this.hasFocus = false; this.active = false; }, render: function() { if(this.entryCount > 0) { for (var i = 0; i < this.entryCount; i++) this.index==i ? Element.addClassName(this.getEntry(i),"selected") : Element.removeClassName(this.getEntry(i),"selected"); if(this.hasFocus) { this.show(); this.active = true; } } else { this.active = false; this.hide(); } }, markPrevious: function() { if(this.index > 0) this.index--; else this.index = this.entryCount-1; this.getEntry(this.index).scrollIntoView(true); }, markNext: function() { if(this.index < this.entryCount-1) this.index++; else this.index = 0; this.getEntry(this.index).scrollIntoView(false); }, getEntry: function(index) { return this.update.firstChild.childNodes[index]; }, getCurrentEntry: function() { return this.getEntry(this.index); }, selectEntry: function() { this.active = false; this.updateElement(this.getCurrentEntry()); }, updateElement: function(selectedElement) { if (this.options.updateElement) { this.options.updateElement(selectedElement); return; } var value = ''; if (this.options.select) { var nodes = $(selectedElement).select('.' + this.options.select) || []; if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); } else value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); var bounds = this.getTokenBounds(); if (bounds[0] != -1) { var newValue = this.element.value.substr(0, bounds[0]); var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); if (whitespace) newValue += whitespace[0]; this.element.value = newValue + value + this.element.value.substr(bounds[1]); } else { this.element.value = value; } this.oldElementValue = this.element.value; this.element.focus(); if (this.options.afterUpdateElement) this.options.afterUpdateElement(this.element, selectedElement); }, updateChoices: function(choices) { if(!this.changed && this.hasFocus) { this.update.innerHTML = choices; Element.cleanWhitespace(this.update); Element.cleanWhitespace(this.update.down()); if(this.update.firstChild && this.update.down().childNodes) { this.entryCount = this.update.down().childNodes.length; for (var i = 0; i < this.entryCount; i++) { var entry = this.getEntry(i); entry.autocompleteIndex = i; this.addObservers(entry); } } else { this.entryCount = 0; } this.stopIndicator(); this.index = 0; if(this.entryCount==1 && this.options.autoSelect) { this.selectEntry(); this.hide(); } else { this.render(); } } }, addObservers: function(element) { Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); Event.observe(element, "click", this.onClick.bindAsEventListener(this)); }, onObserverEvent: function() { this.changed = false; this.tokenBounds = null; if(this.getToken().length>=this.options.minChars) { this.getUpdatedChoices(); } else { this.active = false; this.hide(); } this.oldElementValue = this.element.value; }, getToken: function() { var bounds = this.getTokenBounds(); return this.element.value.substring(bounds[0], bounds[1]).strip(); }, getTokenBounds: function() { if (null != this.tokenBounds) return this.tokenBounds; var value = this.element.value; if (value.strip().empty()) return [-1, 0]; var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); var offset = (diff == this.oldElementValue.length ? 1 : 0); var prevTokenPos = -1, nextTokenPos = value.length; var tp; for (var index = 0, l = this.options.tokens.length; index < l; ++index) { tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); if (tp > prevTokenPos) prevTokenPos = tp; tp = value.indexOf(this.options.tokens[index], diff + offset); if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; } return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); } }); Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { var boundary = Math.min(newS.length, oldS.length); for (var index = 0; index < boundary; ++index) if (newS[index] != oldS[index]) return index; return boundary; }; Ajax.Autocompleter = Class.create(Autocompleter.Base, { initialize: function(element, update, url, options) { this.baseInitialize(element, update, options); this.options.asynchronous = true; this.options.onComplete = this.onComplete.bind(this); this.options.defaultParams = this.options.parameters || null; this.url = url; }, getUpdatedChoices: function() { this.startIndicator(); var entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(this.getToken()); this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry; if(this.options.defaultParams) this.options.parameters += '&' + this.options.defaultParams; new Ajax.Request(this.url, this.options); }, onComplete: function(request) { this.updateChoices(request.responseText); } }); // The local array autocompleter. Used when you'd prefer to // inject an array of autocompletion options into the page, rather // than sending out Ajax queries, which can be quite slow sometimes. // // The constructor takes four parameters. The first two are, as usual, // the id of the monitored textbox, and id of the autocompletion menu. // The third is the array you want to autocomplete from, and the fourth // is the options block. // // Extra local autocompletion options: // - choices - How many autocompletion choices to offer // // - partialSearch - If false, the autocompleter will match entered // text only at the beginning of strings in the // autocomplete array. Defaults to true, which will // match text at the beginning of any *word* in the // strings in the autocomplete array. If you want to // search anywhere in the string, additionally set // the option fullSearch to true (default: off). // // - fullSsearch - Search anywhere in autocomplete array strings. // // - partialChars - How many characters to enter before triggering // a partial match (unlike minChars, which defines // how many characters are required to do any match // at all). Defaults to 2. // // - ignoreCase - Whether to ignore case when autocompleting. // Defaults to true. // // It's possible to pass in a custom function as the 'selector' // option, if you prefer to write your own autocompletion logic. // In that case, the other options above will not apply unless // you support them. Autocompleter.Local = Class.create(Autocompleter.Base, { initialize: function(element, update, array, options) { this.baseInitialize(element, update, options); this.options.array = array; }, getUpdatedChoices: function() { this.updateChoices(this.options.selector(this)); }, setOptions: function(options) { this.options = Object.extend({ choices: 10, partialSearch: true, partialChars: 2, ignoreCase: true, fullSearch: false, selector: function(instance) { var ret = []; // Beginning matches var partial = []; // Inside matches var entry = instance.getToken(); var count = 0; for (var i = 0; i < instance.options.array.length && ret.length < instance.options.choices ; i++) { var elem = instance.options.array[i]; var foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase()) : elem.indexOf(entry); while (foundPos != -1) { if (foundPos == 0 && elem.length != entry.length) { ret.push("
  • " + elem.substr(0, entry.length) + "" + elem.substr(entry.length) + "
  • "); break; } else if (entry.length >= instance.options.partialChars && instance.options.partialSearch && foundPos != -1) { if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { partial.push("
  • " + elem.substr(0, foundPos) + "" + elem.substr(foundPos, entry.length) + "" + elem.substr( foundPos + entry.length) + "
  • "); break; } } foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : elem.indexOf(entry, foundPos + 1); } } if (partial.length) ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); return "
      " + ret.join('') + "
    "; } }, options || { }); } }); // AJAX in-place editor and collection editor // Full rewrite by Christophe Porteneuve (April 2007). // Use this if you notice weird scrolling problems on some browsers, // the DOM might be a bit confused when this gets called so do this // waits 1 ms (with setTimeout) until it does the activation Field.scrollFreeActivate = function(field) { setTimeout(function() { Field.activate(field); }, 1); }; Ajax.InPlaceEditor = Class.create({ initialize: function(element, url, options) { this.url = url; this.element = element = $(element); this.prepareOptions(); this._controls = { }; arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! Object.extend(this.options, options || { }); if (!this.options.formId && this.element.id) { this.options.formId = this.element.id + '-inplaceeditor'; if ($(this.options.formId)) this.options.formId = ''; } if (this.options.externalControl) this.options.externalControl = $(this.options.externalControl); if (!this.options.externalControl) this.options.externalControlOnly = false; this._originalBackground = this.element.getStyle('background-color') || 'transparent'; this.element.title = this.options.clickToEditText; this._boundCancelHandler = this.handleFormCancellation.bind(this); this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); this._boundFailureHandler = this.handleAJAXFailure.bind(this); this._boundSubmitHandler = this.handleFormSubmission.bind(this); this._boundWrapperHandler = this.wrapUp.bind(this); this.registerListeners(); }, checkForEscapeOrReturn: function(e) { if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; if (Event.KEY_ESC == e.keyCode) this.handleFormCancellation(e); else if (Event.KEY_RETURN == e.keyCode) this.handleFormSubmission(e); }, createControl: function(mode, handler, extraClasses) { var control = this.options[mode + 'Control']; var text = this.options[mode + 'Text']; if ('button' == control) { var btn = document.createElement('input'); btn.type = 'submit'; btn.value = text; btn.className = 'editor_' + mode + '_button'; if ('cancel' == mode) btn.onclick = this._boundCancelHandler; this._form.appendChild(btn); this._controls[mode] = btn; } else if ('link' == control) { var link = document.createElement('a'); link.href = '#'; link.appendChild(document.createTextNode(text)); link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; link.className = 'editor_' + mode + '_link'; if (extraClasses) link.className += ' ' + extraClasses; this._form.appendChild(link); this._controls[mode] = link; } }, createEditField: function() { var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); var fld; if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { fld = document.createElement('input'); fld.type = 'text'; var size = this.options.size || this.options.cols || 0; if (0 < size) fld.size = size; } else { fld = document.createElement('textarea'); fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); fld.cols = this.options.cols || 40; } fld.name = this.options.paramName; fld.value = text; // No HTML breaks conversion anymore fld.className = 'editor_field'; if (this.options.submitOnBlur) fld.onblur = this._boundSubmitHandler; this._controls.editor = fld; if (this.options.loadTextURL) this.loadExternalText(); this._form.appendChild(this._controls.editor); }, createForm: function() { var ipe = this; function addText(mode, condition) { var text = ipe.options['text' + mode + 'Controls']; if (!text || condition === false) return; ipe._form.appendChild(document.createTextNode(text)); }; this._form = $(document.createElement('form')); this._form.id = this.options.formId; this._form.addClassName(this.options.formClassName); this._form.onsubmit = this._boundSubmitHandler; this.createEditField(); if ('textarea' == this._controls.editor.tagName.toLowerCase()) this._form.appendChild(document.createElement('br')); if (this.options.onFormCustomization) this.options.onFormCustomization(this, this._form); addText('Before', this.options.okControl || this.options.cancelControl); this.createControl('ok', this._boundSubmitHandler); addText('Between', this.options.okControl && this.options.cancelControl); this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); addText('After', this.options.okControl || this.options.cancelControl); }, destroy: function() { if (this._oldInnerHTML) this.element.innerHTML = this._oldInnerHTML; this.leaveEditMode(); this.unregisterListeners(); }, enterEditMode: function(e) { if (this._saving || this._editing) return; this._editing = true; this.triggerCallback('onEnterEditMode'); if (this.options.externalControl) this.options.externalControl.hide(); this.element.hide(); this.createForm(); this.element.parentNode.insertBefore(this._form, this.element); if (!this.options.loadTextURL) this.postProcessEditField(); if (e) Event.stop(e); }, enterHover: function(e) { if (this.options.hoverClassName) this.element.addClassName(this.options.hoverClassName); if (this._saving) return; this.triggerCallback('onEnterHover'); }, getText: function() { return this.element.innerHTML; }, handleAJAXFailure: function(transport) { this.triggerCallback('onFailure', transport); if (this._oldInnerHTML) { this.element.innerHTML = this._oldInnerHTML; this._oldInnerHTML = null; } }, handleFormCancellation: function(e) { this.wrapUp(); if (e) Event.stop(e); }, handleFormSubmission: function(e) { var form = this._form; var value = $F(this._controls.editor); this.prepareSubmission(); var params = this.options.callback(form, value) || ''; if (Object.isString(params)) params = params.toQueryParams(); params.editorId = this.element.id; if (this.options.htmlResponse) { var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); Object.extend(options, { parameters: params, onComplete: this._boundWrapperHandler, onFailure: this._boundFailureHandler }); new Ajax.Updater({ success: this.element }, this.url, options); } else { var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: params, onComplete: this._boundWrapperHandler, onFailure: this._boundFailureHandler }); new Ajax.Request(this.url, options); } if (e) Event.stop(e); }, leaveEditMode: function() { this.element.removeClassName(this.options.savingClassName); this.removeForm(); this.leaveHover(); this.element.style.backgroundColor = this._originalBackground; this.element.show(); if (this.options.externalControl) this.options.externalControl.show(); this._saving = false; this._editing = false; this._oldInnerHTML = null; this.triggerCallback('onLeaveEditMode'); }, leaveHover: function(e) { if (this.options.hoverClassName) this.element.removeClassName(this.options.hoverClassName); if (this._saving) return; this.triggerCallback('onLeaveHover'); }, loadExternalText: function() { this._form.addClassName(this.options.loadingClassName); this._controls.editor.disabled = true; var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { this._form.removeClassName(this.options.loadingClassName); var text = transport.responseText; if (this.options.stripLoadedTextTags) text = text.stripTags(); this._controls.editor.value = text; this._controls.editor.disabled = false; this.postProcessEditField(); }.bind(this), onFailure: this._boundFailureHandler }); new Ajax.Request(this.options.loadTextURL, options); }, postProcessEditField: function() { var fpc = this.options.fieldPostCreation; if (fpc) $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); }, prepareOptions: function() { this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); [this._extraDefaultOptions].flatten().compact().each(function(defs) { Object.extend(this.options, defs); }.bind(this)); }, prepareSubmission: function() { this._saving = true; this.removeForm(); this.leaveHover(); this.showSaving(); }, registerListeners: function() { this._listeners = { }; var listener; $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { listener = this[pair.value].bind(this); this._listeners[pair.key] = listener; if (!this.options.externalControlOnly) this.element.observe(pair.key, listener); if (this.options.externalControl) this.options.externalControl.observe(pair.key, listener); }.bind(this)); }, removeForm: function() { if (!this._form) return; this._form.remove(); this._form = null; this._controls = { }; }, showSaving: function() { this._oldInnerHTML = this.element.innerHTML; this.element.innerHTML = this.options.savingText; this.element.addClassName(this.options.savingClassName); this.element.style.backgroundColor = this._originalBackground; this.element.show(); }, triggerCallback: function(cbName, arg) { if ('function' == typeof this.options[cbName]) { this.options[cbName](this, arg); } }, unregisterListeners: function() { $H(this._listeners).each(function(pair) { if (!this.options.externalControlOnly) this.element.stopObserving(pair.key, pair.value); if (this.options.externalControl) this.options.externalControl.stopObserving(pair.key, pair.value); }.bind(this)); }, wrapUp: function(transport) { this.leaveEditMode(); // Can't use triggerCallback due to backward compatibility: requires // binding + direct element this._boundComplete(transport, this.element); } }); Object.extend(Ajax.InPlaceEditor.prototype, { dispose: Ajax.InPlaceEditor.prototype.destroy }); Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { initialize: function($super, element, url, options) { this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; $super(element, url, options); }, createEditField: function() { var list = document.createElement('select'); list.name = this.options.paramName; list.size = 1; this._controls.editor = list; this._collection = this.options.collection || []; if (this.options.loadCollectionURL) this.loadCollection(); else this.checkForExternalText(); this._form.appendChild(this._controls.editor); }, loadCollection: function() { this._form.addClassName(this.options.loadingClassName); this.showLoadingText(this.options.loadingCollectionText); var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { var js = transport.responseText.strip(); if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check throw 'Server returned an invalid collection representation.'; this._collection = eval(js); this.checkForExternalText(); }.bind(this), onFailure: this.onFailure }); new Ajax.Request(this.options.loadCollectionURL, options); }, showLoadingText: function(text) { this._controls.editor.disabled = true; var tempOption = this._controls.editor.firstChild; if (!tempOption) { tempOption = document.createElement('option'); tempOption.value = ''; this._controls.editor.appendChild(tempOption); tempOption.selected = true; } tempOption.update((text || '').stripScripts().stripTags()); }, checkForExternalText: function() { this._text = this.getText(); if (this.options.loadTextURL) this.loadExternalText(); else this.buildOptionList(); }, loadExternalText: function() { this.showLoadingText(this.options.loadingText); var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { this._text = transport.responseText.strip(); this.buildOptionList(); }.bind(this), onFailure: this.onFailure }); new Ajax.Request(this.options.loadTextURL, options); }, buildOptionList: function() { this._form.removeClassName(this.options.loadingClassName); this._collection = this._collection.map(function(entry) { return 2 === entry.length ? entry : [entry, entry].flatten(); }); var marker = ('value' in this.options) ? this.options.value : this._text; var textFound = this._collection.any(function(entry) { return entry[0] == marker; }.bind(this)); this._controls.editor.update(''); var option; this._collection.each(function(entry, index) { option = document.createElement('option'); option.value = entry[0]; option.selected = textFound ? entry[0] == marker : 0 == index; option.appendChild(document.createTextNode(entry[1])); this._controls.editor.appendChild(option); }.bind(this)); this._controls.editor.disabled = false; Field.scrollFreeActivate(this._controls.editor); } }); //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** //**** This only exists for a while, in order to let **** //**** users adapt to the new API. Read up on the new **** //**** API and convert your code to it ASAP! **** Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { if (!options) return; function fallback(name, expr) { if (name in options || expr === undefined) return; options[name] = expr; }; fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : options.cancelLink == options.cancelButton == false ? false : undefined))); fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : options.okLink == options.okButton == false ? false : undefined))); fallback('highlightColor', options.highlightcolor); fallback('highlightEndColor', options.highlightendcolor); }; Object.extend(Ajax.InPlaceEditor, { DefaultOptions: { ajaxOptions: { }, autoRows: 3, // Use when multi-line w/ rows == 1 cancelControl: 'link', // 'link'|'button'|false cancelText: 'cancel', clickToEditText: 'Click to edit', externalControl: null, // id|elt externalControlOnly: false, fieldPostCreation: 'activate', // 'activate'|'focus'|false formClassName: 'inplaceeditor-form', formId: null, // id|elt highlightColor: '#ffff99', highlightEndColor: '#ffffff', hoverClassName: '', htmlResponse: true, loadingClassName: 'inplaceeditor-loading', loadingText: 'Loading...', okControl: 'button', // 'link'|'button'|false okText: 'ok', paramName: 'value', rows: 1, // If 1 and multi-line, uses autoRows savingClassName: 'inplaceeditor-saving', savingText: 'Saving...', size: 0, stripLoadedTextTags: false, submitOnBlur: false, textAfterControls: '', textBeforeControls: '', textBetweenControls: '' }, DefaultCallbacks: { callback: function(form) { return Form.serialize(form); }, onComplete: function(transport, element) { // For backward compatibility, this one is bound to the IPE, and passes // the element directly. It was too often customized, so we don't break it. new Effect.Highlight(element, { startcolor: this.options.highlightColor, keepBackgroundImage: true }); }, onEnterEditMode: null, onEnterHover: function(ipe) { ipe.element.style.backgroundColor = ipe.options.highlightColor; if (ipe._effect) ipe._effect.cancel(); }, onFailure: function(transport, ipe) { alert('Error communication with the server: ' + transport.responseText.stripTags()); }, onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. onLeaveEditMode: null, onLeaveHover: function(ipe) { ipe._effect = new Effect.Highlight(ipe.element, { startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, restorecolor: ipe._originalBackground, keepBackgroundImage: true }); } }, Listeners: { click: 'enterEditMode', keydown: 'checkForEscapeOrReturn', mouseover: 'enterHover', mouseout: 'leaveHover' } }); Ajax.InPlaceCollectionEditor.DefaultOptions = { loadingCollectionText: 'Loading options...' }; // Delayed observer, like Form.Element.Observer, // but waits for delay after last key input // Ideal for live-search fields Form.Element.DelayedObserver = Class.create({ initialize: function(element, delay, callback) { this.delay = delay || 0.5; this.element = $(element); this.callback = callback; this.timer = null; this.lastValue = $F(this.element); Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); }, delayedListener: function(event) { if(this.lastValue == $F(this.element)) return; if(this.timer) clearTimeout(this.timer); this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); this.lastValue = $F(this.element); }, onTimerEvent: function() { this.timer = null; this.callback(this.element, $F(this.element)); } }); AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/builder.js0000766000000000000000000001124411122202526026172 0ustar adminadministrators// script.aculo.us builder.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ var Builder = { NODEMAP: { AREA: 'map', CAPTION: 'table', COL: 'table', COLGROUP: 'table', LEGEND: 'fieldset', OPTGROUP: 'select', OPTION: 'select', PARAM: 'object', TBODY: 'table', TD: 'table', TFOOT: 'table', TH: 'table', THEAD: 'table', TR: 'table' }, // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, // due to a Firefox bug node: function(elementName) { elementName = elementName.toUpperCase(); // try innerHTML approach var parentTag = this.NODEMAP[elementName] || 'div'; var parentElement = document.createElement(parentTag); try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 parentElement.innerHTML = "<" + elementName + ">"; } catch(e) {} var element = parentElement.firstChild || null; // see if browser added wrapping tags if(element && (element.tagName.toUpperCase() != elementName)) element = element.getElementsByTagName(elementName)[0]; // fallback to createElement approach if(!element) element = document.createElement(elementName); // abort if nothing could be created if(!element) return; // attributes (or text) if(arguments[1]) if(this._isStringOrNumber(arguments[1]) || (arguments[1] instanceof Array) || arguments[1].tagName) { this._children(element, arguments[1]); } else { var attrs = this._attributes(arguments[1]); if(attrs.length) { try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 parentElement.innerHTML = "<" +elementName + " " + attrs + ">"; } catch(e) {} element = parentElement.firstChild || null; // workaround firefox 1.0.X bug if(!element) { element = document.createElement(elementName); for(attr in arguments[1]) element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; } if(element.tagName.toUpperCase() != elementName) element = parentElement.getElementsByTagName(elementName)[0]; } } // text, or array of children if(arguments[2]) this._children(element, arguments[2]); return element; }, _text: function(text) { return document.createTextNode(text); }, ATTR_MAP: { 'className': 'class', 'htmlFor': 'for' }, _attributes: function(attributes) { var attrs = []; for(attribute in attributes) attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); return attrs.join(" "); }, _children: function(element, children) { if(children.tagName) { element.appendChild(children); return; } if(typeof children=='object') { // array can hold nodes and text children.flatten().each( function(e) { if(typeof e=='object') element.appendChild(e); else if(Builder._isStringOrNumber(e)) element.appendChild(Builder._text(e)); }); } else if(Builder._isStringOrNumber(children)) element.appendChild(Builder._text(children)); }, _isStringOrNumber: function(param) { return(typeof param=='string' || typeof param=='number'); }, build: function(html) { var element = this.node('div'); $(element).update(html.strip()); return element.down(); }, dump: function(scope) { if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); tags.each( function(tag){ scope[tag] = function() { return Builder.node.apply(Builder, [tag].concat($A(arguments))); } }); } }; AjaXplorer/AjaXplorer/client/js/lib/scriptaculous/src/scriptaculous.js0000766000000000000000000000514011122202526027442 0ustar adminadministrators// script.aculo.us scriptaculous.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // For details, see the script.aculo.us web site: http://script.aculo.us/ var Scriptaculous = { Version: '1.8.0', require: function(libraryName) { // inserting via DOM fails in Safari 2.0, so brute force approach document.write(' AjaXplorer/AjaXplorer/client/js/lib/webfx/slider/css/bluecurve/0000777000000000000000000000000011300346050025674 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/webfx/slider/css/bluecurve/bluecurve.css0000766000000000000000000000312611122202530030401 0ustar adminadministrators/* back: rgb(230,230,230) dark: rgb(90,97,90) medium rgb(189,190,189) */ .dynamic-slider-control { position: relative; background-color: transparent; -moz-user-focus: normal; -moz-user-select: none; cursor: default; } .horizontal { width: 150px; height: 18px; } .vertical { width: 29px; height: 200px; } .dynamic-slider-control input { display: none; } .dynamic-slider-control .handle { position: absolute; font-size: 1px; overflow: hidden; -moz-user-select: none; cursor: pointer; } .dynamic-slider-control.horizontal .handle { width: 31px; height: 14px; background-image: url("handle.horizontal.png"); } .dynamic-slider-control.horizontal .handle div {} .dynamic-slider-control.horizontal .handle.hover {} .dynamic-slider-control.vertical .handle { width: 15px; height: 31px; background-image: url("handle.vertical.png"); } .dynamic-slider-control.vertical .handle.hover {} .dynamic-slider-control .line { position: absolute; font-size: 0.01mm; overflow: hidden; border: 1px solid rgb(90,97,90); background: rgb(189,190,189); behavior: url("css/boxsizing.htc"); /* ie path bug */ box-sizing: content-box; -moz-box-sizing: content-box; } .dynamic-slider-control.vertical .line { width: 3px; } .dynamic-slider-control.horizontal .line { height: 3px; } .dynamic-slider-control .line div { width: 1px; height: 1px; border: 1px solid; border-color: rgb(230,230,230) rgb(189,190,189) rgb(189,190,189) rgb(230,230,230); }AjaXplorer/AjaXplorer/client/js/lib/webfx/slider/css/bluecurve/horizontal.gif0000766000000000000000000000233211122202530030551 0ustar adminadministratorsGIF87a9潺ս141 101޴A@AADA½bib $ jej ZaZjmj)()989{}{sysJHJ{y{9<9babRPR)$)ZYZA@@p>@0>3@P>2 V@I?@H|a @|B:  t>@X-~ |5IENDB`AjaXplorer/AjaXplorer/client/js/lib/webfx/xtree.css0000766000000000000000000000206711122202530023471 0ustar adminadministrators.webfx-tree-container { margin: 0px; padding: 0px; font-family: Trebuchet MS, sans-serif; white-space: nowrap; font-size: 11px; } .webfx-tree-item { padding: 0px; margin: 0px; font-family: Trebuchet MS, sans-serif; font-size: 11px; color: WindowText; white-space: nowrap; height: 16px; } .webfx-tree-item a, .webfx-tree-item a:active, .webfx-tree-item a:hover { margin-left: 3px; padding: 0px 2px 1px 2px; } .webfx-tree-item a { color: black; text-decoration: none; } .webfx-tree-item a:hover { color: blue; text-decoration: underline; } .webfx-tree-item a:active { background: highlight; color: white; text-decoration: none; } .webfx-tree-item a.selected-focus{ color: white; } .webfx-tree-item a.selected-inactive { border: 1px solid #ddd; background: #ddd; text-decoration: none; } .webfx-tree-item img { vertical-align: middle; border: 0px; } .webfx-tree-icon { width: 16px; height: 16px; } .selected { background: #ddd; color: white; text-decoration: none; } AjaXplorer/AjaXplorer/client/js/lib/webfx/xloadtree.js0000766000000000000000000002341711122202530024157 0ustar adminadministrators/*----------------------------------------------------------------------------\ | XLoadTree 1.11 | |-----------------------------------------------------------------------------| | Created by Erik Arvidsson | | (http://webfx.eae.net/contact.html#erik) | | For WebFX (http://webfx.eae.net/) | |-----------------------------------------------------------------------------| | An extension to xTree that allows sub trees to be loaded at runtime by | | reading XML files from the server. Works with IE5+ and Mozilla 1.0+ | |-----------------------------------------------------------------------------| | Copyright (c) 2001, 2002, 2003, 2006 Erik Arvidsson | |-----------------------------------------------------------------------------| | Licensed under the Apache License, Version 2.0 (the "License"); you may not | | use this file except in compliance with the License. You may obtain a copy | | of the License at http://www.apache.org/licenses/LICENSE-2.0 | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | | Unless required by applicable law or agreed to in writing, software | | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | | License for the specific language governing permissions and limitations | | under the License. | |-----------------------------------------------------------------------------| | Dependencies: xtree.js - original xtree library | | xtree.css - simple css styling of xtree | | xmlextras.js - provides xml http objects and xml document | | objects | |-----------------------------------------------------------------------------| | 2001-09-27 | Original Version Posted. | | 2002-01-19 | Added some simple error handling and string templates for | | | reporting the errors. | | 2002-01-28 | Fixed loading issues in IE50 and IE55 that made the tree load | | | twice. | | 2002-10-10 | (1.1) Added reload method that reloads the XML file from the | | | server. | | 2003-05-06 | Added support for target attribute | | 2006-05-28 | Changed license to Apache Software License 2.0. | |-----------------------------------------------------------------------------| | Created 2001-09-27 | All changes are in the log above. | Updated 2006-05-28 | \----------------------------------------------------------------------------*/ webFXTreeConfig.loadingText = "Loading..."; webFXTreeConfig.loadErrorTextTemplate = "Error loading \"%1%\""; webFXTreeConfig.emptyErrorTextTemplate = "Error \"%1%\" does not contain any tree items"; /* * WebFXLoadTree class */ function WebFXLoadTree(sText, sXmlSrc, sAction, sBehavior, sIcon, sOpenIcon) { // call super this.WebFXTree = WebFXTree; this.WebFXTree(sText, sAction, sBehavior, sIcon, sOpenIcon); // setup default property values this.src = sXmlSrc; this.loading = false; this.loaded = false; this.errorText = ""; // check start state and load if open if (this.open) _startLoadXmlTree(this.src, this); else { // and create loading item if not this._loadingItem = new WebFXTreeItem(webFXTreeConfig.loadingText); this.add(this._loadingItem); } } WebFXLoadTree.prototype = new WebFXTree; // override the expand method to load the xml file WebFXLoadTree.prototype._webfxtree_expand = WebFXTree.prototype.expand; WebFXLoadTree.prototype.expand = function() { if (!this.loaded && !this.loading) { // load _startLoadXmlTree(this.src, this); } this._webfxtree_expand(); }; /* * WebFXLoadTreeItem class */ function WebFXLoadTreeItem(sText, sXmlSrc, sAction, eParent, sIcon, sOpenIcon) { // call super this.WebFXTreeItem = WebFXTreeItem; this.WebFXTreeItem(sText, sAction, eParent, sIcon, sOpenIcon); // setup default property values this.src = sXmlSrc; this.loading = false; this.loaded = false; this.errorText = ""; // check start state and load if open if (this.open) _startLoadXmlTree(this.src, this); else { // and create loading item if not this._loadingItem = new WebFXTreeItem(webFXTreeConfig.loadingText); this.add(this._loadingItem); } } WebFXLoadTreeItem.prototype = new WebFXTreeItem; // override the expand method to load the xml file WebFXLoadTreeItem.prototype._webfxtreeitem_expand = WebFXTreeItem.prototype.expand; WebFXLoadTreeItem.prototype.expand = function() { if (!this.loaded && !this.loading) { // load _startLoadXmlTree(this.src, this); } this._webfxtreeitem_expand(); }; // reloads the src file if already loaded WebFXLoadTree.prototype.reload = WebFXLoadTreeItem.prototype.reload = function () { // if loading do nothing if (this.loaded) { var open = this.open; // remove while (this.childNodes.length > 0) this.childNodes[this.childNodes.length - 1].remove(); this.loaded = false; this._loadingItem = new WebFXTreeItem(webFXTreeConfig.loadingText); this.add(this._loadingItem); if (open) this.expand(); } else if (this.open && !this.loading) _startLoadXmlTree(this.src, this); if(!this.open && !this.loading) this.toggle(); }; /* * Helper functions */ // creates the xmlhttp object and starts the load of the xml document function _startLoadXmlTree(sSrc, jsNode) { if (jsNode.loading || jsNode.loaded) return; jsNode.loading = true; var connexion = new Connexion(encodeURI(decodeURIComponent(sSrc))); connexion.onComplete = function(transport){ _xmlFileLoaded(transport.responseXML, jsNode); }; connexion.sendAsync(); } // Converts an xml tree to a js tree. See article about xml tree format function _xmlTreeToJsTree(oNode) { // retreive attributes var text = oNode.getAttribute("text"); var action = oNode.getAttribute("action"); if(!action){ action = "javascript:ajaxplorer.getFoldersTree().clickNode(CURRENT_ID)"; } var parent = null; var icon = oNode.getAttribute("icon"); var openIcon = oNode.getAttribute("openicon"); var src = oNode.getAttribute("src"); var target = oNode.getAttribute("target"); var preloaded = oNode.getAttribute("preloaded"); var recycle = oNode.getAttribute("is_recycle"); var folderFullName = oNode.getAttribute("filename"); // create jsNode var jsNode; if (src != null && src != "") jsNode = new WebFXLoadTreeItem(text, src, action, parent, icon, openIcon); else jsNode = new WebFXTreeItem(text, action, parent, icon, openIcon); if (target != "") jsNode.target = target; if (recycle != null && !(ajaxplorer && ajaxplorer.actionBar && ajaxplorer.actionBar.treeCopyActive)){ webFXTreeHandler.recycleNode = jsNode.id; jsNode.isRecycle = true; } if(oNode.getAttribute('ajxp_node') && oNode.getAttribute('ajxp_node')=="true"){ jsNode.ajxpNode = true; webFXTreeHandler.ajxpNodes[getBaseName(folderFullName)] = jsNode.id; } if(src != null && src != "" && preloaded != null && preloaded == 'true') { jsNode.loaded = true; } jsNode.filename = folderFullName; // go through childNOdes var cs = oNode.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i].tagName == "tree") jsNode.add( _xmlTreeToJsTree(cs[i]), true ); } return jsNode; } // Inserts an xml document as a subtree to the provided node function _xmlFileLoaded(oXmlDoc, jsParentNode) { if (jsParentNode.loaded) return; var bIndent = false; var bAnyChildren = false; jsParentNode.loaded = true; jsParentNode.loading = false; // check that the load of the xml file went well if( oXmlDoc == null || oXmlDoc.documentElement == null) { alert(oXmlDoc.xml); jsParentNode.errorText = parseTemplateString(webFXTreeConfig.loadErrorTextTemplate, jsParentNode.src); } else { // there is one extra level of tree elements var root = oXmlDoc.documentElement; // loop through all tree children var cs = root.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { if (cs[i].tagName == "tree") { bAnyChildren = true; bIndent = true; jsParentNode.add( _xmlTreeToJsTree(cs[i]), true); } else if(cs[i].tagName == "error") { jsParentNode.errorText = cs[i].firstChild.nodeValue; } } // if no children we got an error //if (!bAnyChildren) //jsParentNode.errorText = parseTemplateString(webFXTreeConfig.emptyErrorTextTemplate, // jsParentNode.src); } // remove dummy if (jsParentNode._loadingItem != null) { jsParentNode._loadingItem.remove(); bIndent = true; } if (bIndent) { // indent now that all items are added jsParentNode.indent(); } // show error in status bar if (jsParentNode.errorText != ""){ window.status = jsParentNode.errorText; } if(ajaxplorer) ajaxplorer.foldersTree.asyncExpandAndSelect(); if(modal.pageLoading) modal.updateLoadingProgress('Tree Loaded'); } // parses a string and replaces %n% with argument nr n function parseTemplateString(sTemplate) { var args = arguments; var s = sTemplate; s = s.replace(/\%\%/g, "%"); for (var i = 1; i < args.length; i++) s = s.replace( new RegExp("\%" + i + "\%", "g"), args[i] ) ; return s; } AjaXplorer/AjaXplorer/client/js/lib/ufo/0000777000000000000000000000000011300346051021305 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/ufo/ufo.js0000766000000000000000000002541711122202530022441 0ustar adminadministrators/* Unobtrusive Flash Objects (UFO) v3.21 Copyright 2005, 2006 Bobby van der Sluis This software is licensed under the CC-GNU LGPL */ var UFO = { req: ["movie", "width", "height", "majorversion", "build"], opt: ["play", "loop", "menu", "quality", "scale", "salign", "wmode", "bgcolor", "base", "flashvars", "devicefont", "allowscriptaccess", "seamlesstabbing", "allowfullscreen"], optAtt: ["id", "name", "align"], optExc: ["swliveconnect"], ximovie: "ufo.swf", xiwidth: "215", xiheight: "138", ua: navigator.userAgent.toLowerCase(), pluginType: "", fv: [0,0], foList: [], create: function(FO, id) { if (!UFO.uaHas("w3cdom") || UFO.uaHas("ieMac")) return; UFO.getFlashVersion(); UFO.foList[id] = UFO.updateFO(FO); UFO.createCSS("#" + id, "visibility:hidden;"); UFO.domLoad(id); }, updateFO: function(FO) { if (typeof FO.xi != "undefined" && FO.xi == "true") { if (typeof FO.ximovie == "undefined") FO.ximovie = UFO.ximovie; if (typeof FO.xiwidth == "undefined") FO.xiwidth = UFO.xiwidth; if (typeof FO.xiheight == "undefined") FO.xiheight = UFO.xiheight; } FO.mainCalled = false; return FO; }, domLoad: function(id) { var _t = setInterval(function() { if ((document.getElementsByTagName("body")[0] != null || document.body != null) && document.getElementById(id) != null) { UFO.main(id); clearInterval(_t); } }, 250); if (typeof document.addEventListener != "undefined") { document.addEventListener("DOMContentLoaded", function() { UFO.main(id); clearInterval(_t); } , null); // Gecko, Opera 9+ } }, main: function(id) { var _fo = UFO.foList[id]; if (_fo.mainCalled) return; UFO.foList[id].mainCalled = true; document.getElementById(id).style.visibility = "hidden"; if (UFO.hasRequired(id)) { if (UFO.hasFlashVersion(parseInt(_fo.majorversion, 10), parseInt(_fo.build, 10))) { if (typeof _fo.setcontainercss != "undefined" && _fo.setcontainercss == "true") UFO.setContainerCSS(id); UFO.writeSWF(id); } else if (_fo.xi == "true" && UFO.hasFlashVersion(6, 65)) { UFO.createDialog(id); } } document.getElementById(id).style.visibility = "visible"; }, createCSS: function(selector, declaration) { var _h = document.getElementsByTagName("head")[0]; var _s = UFO.createElement("style"); if (!UFO.uaHas("ieWin")) _s.appendChild(document.createTextNode(selector + " {" + declaration + "}")); // bugs in IE/Win _s.setAttribute("type", "text/css"); _s.setAttribute("media", "screen"); _h.appendChild(_s); if (UFO.uaHas("ieWin") && document.styleSheets && document.styleSheets.length > 0) { var _ls = document.styleSheets[document.styleSheets.length - 1]; if (typeof _ls.addRule == "object") _ls.addRule(selector, declaration); } }, setContainerCSS: function(id) { var _fo = UFO.foList[id]; var _w = /%/.test(_fo.width) ? "" : "px"; var _h = /%/.test(_fo.height) ? "" : "px"; UFO.createCSS("#" + id, "width:" + _fo.width + _w +"; height:" + _fo.height + _h +";"); if (_fo.width == "100%") { UFO.createCSS("body", "margin-left:0; margin-right:0; padding-left:0; padding-right:0;"); } if (_fo.height == "100%") { UFO.createCSS("html", "height:100%; overflow:hidden;"); UFO.createCSS("body", "margin-top:0; margin-bottom:0; padding-top:0; padding-bottom:0; height:100%;"); } }, createElement: function(el) { return (UFO.uaHas("xml") && typeof document.createElementNS != "undefined") ? document.createElementNS("http://www.w3.org/1999/xhtml", el) : document.createElement(el); }, createObjParam: function(el, aName, aValue) { var _p = UFO.createElement("param"); _p.setAttribute("name", aName); _p.setAttribute("value", aValue); el.appendChild(_p); }, uaHas: function(ft) { var _u = UFO.ua; switch(ft) { case "w3cdom": return (typeof document.getElementById != "undefined" && typeof document.getElementsByTagName != "undefined" && (typeof document.createElement != "undefined" || typeof document.createElementNS != "undefined")); case "xml": var _m = document.getElementsByTagName("meta"); var _l = _m.length; for (var i = 0; i < _l; i++) { if (/content-type/i.test(_m[i].getAttribute("http-equiv")) && /xml/i.test(_m[i].getAttribute("content"))) return true; } return false; case "ieMac": return /msie/.test(_u) && !/opera/.test(_u) && /mac/.test(_u); case "ieWin": return /msie/.test(_u) && !/opera/.test(_u) && /win/.test(_u); case "gecko": return /gecko/.test(_u) && !/applewebkit/.test(_u); case "opera": return /opera/.test(_u); case "safari": return /applewebkit/.test(_u); default: return false; } }, getFlashVersion: function() { if (UFO.fv[0] != 0) return; if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") { UFO.pluginType = "npapi"; var _d = navigator.plugins["Shockwave Flash"].description; if (typeof _d != "undefined") { _d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10); var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0; UFO.fv = [_m, _r]; } } else if (window.ActiveXObject) { UFO.pluginType = "ax"; try { // avoid fp 6 crashes var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); } catch(e) { try { var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); UFO.fv = [6, 0]; _a.AllowScriptAccess = "always"; // throws if fp < 6.47 } catch(e) { if (UFO.fv[0] == 6) return; } try { var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); } catch(e) {} } if (typeof _a == "object") { var _d = _a.GetVariable("$version"); // bugs in fp 6.21/6.23 if (typeof _d != "undefined") { _d = _d.replace(/^\S+\s+(.*)$/, "$1").split(","); UFO.fv = [parseInt(_d[0], 10), parseInt(_d[2], 10)]; } } } }, hasRequired: function(id) { var _l = UFO.req.length; for (var i = 0; i < _l; i++) { if (typeof UFO.foList[id][UFO.req[i]] == "undefined") return false; } return true; }, hasFlashVersion: function(major, release) { return (UFO.fv[0] > major || (UFO.fv[0] == major && UFO.fv[1] >= release)) ? true : false; }, writeSWF: function(id) { var _fo = UFO.foList[id]; var _e = document.getElementById(id); if (UFO.pluginType == "npapi") { if (UFO.uaHas("gecko") || UFO.uaHas("xml")) { while(_e.hasChildNodes()) { _e.removeChild(_e.firstChild); } var _obj = UFO.createElement("object"); _obj.setAttribute("type", "application/x-shockwave-flash"); _obj.setAttribute("data", _fo.movie); _obj.setAttribute("width", _fo.width); _obj.setAttribute("height", _fo.height); var _l = UFO.optAtt.length; for (var i = 0; i < _l; i++) { if (typeof _fo[UFO.optAtt[i]] != "undefined") _obj.setAttribute(UFO.optAtt[i], _fo[UFO.optAtt[i]]); } var _o = UFO.opt.concat(UFO.optExc); var _l = _o.length; for (var i = 0; i < _l; i++) { if (typeof _fo[_o[i]] != "undefined") UFO.createObjParam(_obj, _o[i], _fo[_o[i]]); } _e.appendChild(_obj); } else { var _emb = ""; var _o = UFO.opt.concat(UFO.optAtt).concat(UFO.optExc); var _l = _o.length; for (var i = 0; i < _l; i++) { if (typeof _fo[_o[i]] != "undefined") _emb += ' ' + _o[i] + '="' + _fo[_o[i]] + '"'; } _e.innerHTML = ''; } } else if (UFO.pluginType == "ax") { var _objAtt = ""; var _l = UFO.optAtt.length; for (var i = 0; i < _l; i++) { if (typeof _fo[UFO.optAtt[i]] != "undefined") _objAtt += ' ' + UFO.optAtt[i] + '="' + _fo[UFO.optAtt[i]] + '"'; } var _objPar = ""; var _l = UFO.opt.length; for (var i = 0; i < _l; i++) { if (typeof _fo[UFO.opt[i]] != "undefined") _objPar += ''; } var _p = window.location.protocol == "https:" ? "https:" : "http:"; _e.innerHTML = '' + _objPar + ''; } }, createDialog: function(id) { var _fo = UFO.foList[id]; UFO.createCSS("html", "height:100%; overflow:hidden;"); UFO.createCSS("body", "height:100%; overflow:hidden;"); UFO.createCSS("#xi-con", "position:absolute; left:0; top:0; z-index:1000; width:100%; height:100%; background-color:#fff; filter:alpha(opacity:75); opacity:0.75;"); UFO.createCSS("#xi-dia", "position:absolute; left:50%; top:50%; margin-left: -" + Math.round(parseInt(_fo.xiwidth, 10) / 2) + "px; margin-top: -" + Math.round(parseInt(_fo.xiheight, 10) / 2) + "px; width:" + _fo.xiwidth + "px; height:" + _fo.xiheight + "px;"); var _b = document.getElementsByTagName("body")[0]; var _c = UFO.createElement("div"); _c.setAttribute("id", "xi-con"); var _d = UFO.createElement("div"); _d.setAttribute("id", "xi-dia"); _c.appendChild(_d); _b.appendChild(_c); var _mmu = window.location; if (UFO.uaHas("xml") && UFO.uaHas("safari")) { var _mmd = document.getElementsByTagName("title")[0].firstChild.nodeValue = document.getElementsByTagName("title")[0].firstChild.nodeValue.slice(0, 47) + " - Flash Player Installation"; } else { var _mmd = document.title = document.title.slice(0, 47) + " - Flash Player Installation"; } var _mmp = UFO.pluginType == "ax" ? "ActiveX" : "PlugIn"; var _uc = typeof _fo.xiurlcancel != "undefined" ? "&xiUrlCancel=" + _fo.xiurlcancel : ""; var _uf = typeof _fo.xiurlfailed != "undefined" ? "&xiUrlFailed=" + _fo.xiurlfailed : ""; UFO.foList["xi-dia"] = { movie:_fo.ximovie, width:_fo.xiwidth, height:_fo.xiheight, majorversion:"6", build:"65", flashvars:"MMredirectURL=" + _mmu + "&MMplayerType=" + _mmp + "&MMdoctitle=" + _mmd + _uc + _uf }; UFO.writeSWF("xi-dia"); }, expressInstallCallback: function() { var _b = document.getElementsByTagName("body")[0]; var _c = document.getElementById("xi-con"); _b.removeChild(_c); UFO.createCSS("body", "height:auto; overflow:auto;"); UFO.createCSS("html", "height:auto; overflow:auto;"); }, cleanupIELeaks: function() { var _o = document.getElementsByTagName("object"); var _l = _o.length ; for (var i = 0; i < _l; i++) { _o[i].style.display = "none"; for (var x in _o[i]) { if (typeof _o[i][x] == "function") { _o[i][x] = null; } } } } }; if (typeof window.attachEvent != "undefined" && UFO.uaHas("ieWin")) { window.attachEvent("onunload", UFO.cleanupIELeaks); } AjaXplorer/AjaXplorer/client/js/lib/prototype/0000777000000000000000000000000011300346053022563 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/prototype/webfx.sortable.js0000766000000000000000000004004411122202530026042 0ustar adminadministrators/*----------------------------------------------------------------------------\ | Sortable Table 1.12 | |-----------------------------------------------------------------------------| | Created by Erik Arvidsson | | (http://webfx.eae.net/contact.html#erik) | | For WebFX (http://webfx.eae.net/) | | Prototypized by Charles du Jeu | |-----------------------------------------------------------------------------| | A DOM 1 based script that allows an ordinary HTML table to be sortable. | |-----------------------------------------------------------------------------| | Copyright (c) 1998 - 2004 Erik Arvidsson | |-----------------------------------------------------------------------------| | This software is provided "as is", without warranty of any kind, express or | | implied, including but not limited to the warranties of merchantability, | | fitness for a particular purpose and noninfringement. In no event shall the | | authors or copyright holders be liable for any claim, damages or other | | liability, whether in an action of contract, tort or otherwise, arising | | from, out of or in connection with the software or the use or other | | dealings in the software. | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | | This software is available under the three different licenses mentioned | | below. To use this software you must chose, and qualify, for one of those. | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | | The WebFX Non-Commercial License http://webfx.eae.net/license.html | | Permits anyone the right to use the software in a non-commercial context | | free of charge. | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | | The WebFX Commercial license http://webfx.eae.net/commercial.html | | Permits the license holder the right to use the software in a commercial | | context. Such license must be specifically obtained, however it's valid for | | any number of implementations of the licensed software. | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | | GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt | | Permits anyone the right to use and modify the software without limitations | | as long as proper credits are given and the original and modified source | | code are included. Requires that the final product, software derivate from | | the original source or any software utilizing a GPL component, such as | | this, is also licensed under the GPL license. | |-----------------------------------------------------------------------------| | 2003-01-10 | First version | | 2003-01-19 | Minor changes to the date parsing | | 2003-01-28 | JScript 5.0 fixes (no support for 'in' operator) | | 2003-02-01 | Sloppy typo like error fixed in getInnerText | | 2003-07-04 | Added workaround for IE cellIndex bug. | | 2003-11-09 | The bDescending argument to sort was not correctly working | | | Using onclick DOM0 event if no support for addEventListener | | | or attachEvent | | 2004-01-13 | Adding addSortType and removeSortType which makes it a lot | | | easier to add new, custom sort types. | | 2004-01-27 | Switch to use descending = false as the default sort order. | | | Change defaultDescending to suit your needs. | | 2004-03-14 | Improved sort type None look and feel a bit | | 2004-08-26 | Made the handling of tBody and tHead more flexible. Now you | | | can use another tHead or no tHead, and you can chose some | | | other tBody. | | 2007-12-24 | Prototypized by Charles du Jeu | |-----------------------------------------------------------------------------| | Created 2003-01-10 | All changes are in the log above. | Updated 2004-08-26 | \----------------------------------------------------------------------------*/ SortableTable = Class.create({ initialize: function(oTable, oSortTypes, oTHead) { this.gecko = Prototype.Browser.Gecko; this.msie = Prototype.Browser.IE; this.removeBeforeSort = this.gecko; this.sortTypes = oSortTypes || []; this.sortColumn = null; this.descending = null; this._headerOnclick = function (e) { this.headerOnclick(e); }.bind(this); if (oTable) { this.setTable( oTable, oTHead ); this.document = oTable.ownerDocument || oTable.document; } else { this.document = document; } // only IE needs this var win = this.document.defaultView || this.document.parentWindow; this._onunload = function () { this.destroy(); }.bind(this); if (win && typeof win.attachEvent != "undefined") { win.attachEvent("onunload", this._onunload); } // add sort types this.addSortType("Number", Number); this.addSortType("CaseInsensitiveString", this.toUpperCase); this.addSortType("Date", this.toDate); this.addSortType("String"); }, onsort: function () {}, // default sort order. true -> descending, false -> ascending defaultDescending: false, // shared between all instances. This is intentional to allow external files // to modify the prototype _sortTypeInfo: {}, setTable: function (oTable, oTHead) { if ( this.tHead ) this.uninitHeader(); this.element = oTable; this.setTHead( (oTHead?oTHead:oTable.tHead) ); this.setTBody( oTable.tBodies[0] ); }, setTHead: function (oTHead) { if (this.tHead && this.tHead != oTHead ) this.uninitHeader(); this.tHead = oTHead; this.initHeader( this.sortTypes ); }, setTBody: function (oTBody) { this.tBody = oTBody; }, setSortTypes: function ( oSortTypes ) { if ( this.tHead ) this.uninitHeader(); this.sortTypes = oSortTypes || []; if ( this.tHead ) this.initHeader( this.sortTypes ); }, // adds arrow containers and events // also binds sort type to the header cells so that reordering columns does // not break the sort types initHeader: function (oSortTypes) { if (!this.tHead) return; var cells = this.tHead.rows[0].cells; var doc = this.tHead.ownerDocument || this.tHead.document; this.sortTypes = oSortTypes || []; var l = cells.length; var img, c; for (var i = 0; i < l; i++) { c = cells[i]; if (this.sortTypes[i] != null && this.sortTypes[i] != "None") { img = doc.createElement("IMG"); img.src = ajxpResourcesFolder+'/images/blank.png'; c.appendChild(img); if (this.sortTypes[i] != null) c._sortType = this.sortTypes[i]; if (typeof c.addEventListener != "undefined") c.addEventListener("click", this._headerOnclick, false); else if (typeof c.attachEvent != "undefined") c.attachEvent("onclick", this._headerOnclick); else c.onclick = this._headerOnclick; } else { c.setAttribute( "_sortType", oSortTypes[i] ); c._sortType = "None"; } /* var resizeDiv = document.createElement("div"); resizeDiv.innerHtml = "t"; resizeDiv.setAttribute("style", "float:right; height:20px; width:3px; background-color:black;"); resizeDiv.setAttribute("id", "header_resize_"+i); c.appendChild(resizeDiv); new Draggable("header_resize_"+i, {constraint:'horizontal', snap: function(x,y,draggable) { var parent_dimensions = Element.getDimensions(draggable.element.parentNode); var element_dimensions = Element.getDimensions(draggable.element); var xMin = 0 var xMax = parent_dimensions.width - element_dimensions.width; var yMin = 0; var yMax = parent_dimensions.height - element_dimensions.height; xMin = -xMax; xMax = 0; x = xxMax ? xMax : x; y = yyMax ? yMax : y; return [x,y]; }}); */ } this.updateHeaderArrows(); }, // remove arrows and events uninitHeader: function () { if (!this.tHead || !this.tHead.rows || !this.tHead.rows[0]) return; try{ var cells = this.tHead.rows[0].cells; }catch(e){ return; } var l = cells.length; var c; for (var i = 0; i < l; i++) { c = cells[i]; if (c._sortType != null && c._sortType != "None") { c.removeChild(c.lastChild); if (typeof c.removeEventListener != "undefined") c.removeEventListener("click", this._headerOnclick, false); else if (typeof c.detachEvent != "undefined") c.detachEvent("onclick", this._headerOnclick); c._sortType = null; c.removeAttribute( "_sortType" ); } } }, updateHeaderArrows: function () { if (!this.tHead) return; var cells = this.tHead.rows[0].cells; var l = cells.length; var img; for (var i = 0; i < l; i++) { if (cells[i]._sortType != null && cells[i]._sortType != "None") { img = cells[i].lastChild; if (i == this.sortColumn) { //img.className = "sort-arrow " + (this.descending ? "descending" : "ascending"); img.className = "sort-arrow"; $(cells[i]).className = (this.descending ? "desc" : "asc"); } else { img.className = "sort-arrow"; $(cells[i]).className = ""; } } } }, headerOnclick: function (e) { // find TD element var el = e.target || e.srcElement; while (el.tagName != "TD") el = el.parentNode; this.sort(this.msie ? this.getCellIndex(el) : el.cellIndex); }, // IE returns wrong cellIndex when columns are hidden getCellIndex: function (oTd) { var cells = oTd.parentNode.childNodes ; var l = cells.length; var i; for (i = 0; cells[i] != oTd && i < l; i++) ; return i; }, getSortType: function (nColumn) { return this.sortTypes[nColumn] || "String"; }, // only nColumn is required // if bDescending is left out the old value is taken into account // if sSortType is left out the sort type is found from the sortTypes array sort: function (nColumn, bDescending, sSortType) { if (!this.tBody) return; if (sSortType == null) sSortType = this.getSortType(nColumn); // exit if None if (sSortType == "None") return; if (bDescending == null) { if (this.sortColumn != nColumn) this.descending = this.defaultDescending; else this.descending = !this.descending; } else this.descending = bDescending; this.sortColumn = nColumn; if (typeof this.onbeforesort == "function") this.onbeforesort(); var f = this.getSortFunction(sSortType, nColumn); var a = this.getCache(sSortType, nColumn); var tBody = this.tBody; a.sort(f); if (this.descending) a.reverse(); if (this.removeBeforeSort) { // remove from doc var nextSibling = tBody.nextSibling; var p = tBody.parentNode; p.removeChild(tBody); } // insert in the new order var l = a.length; for (var i = 0; i < l; i++) tBody.appendChild(a[i].element); if (this.removeBeforeSort) { // insert into doc p.insertBefore(tBody, nextSibling); } this.updateHeaderArrows(); this.destroyCache(a); if (typeof this.onsort == "function") this.onsort(); }, asyncSort: function (nColumn, bDescending, sSortType) { var oThis = this; this._asyncsort = function () { oThis.sort(nColumn, bDescending, sSortType); }; window.setTimeout(this._asyncsort, 1); }, getCache: function (sType, nColumn) { if (!this.tBody) return []; var rows = this.tBody.rows; var l = rows.length; var a = new Array(l); var r; for (var i = 0; i < l; i++) { r = rows[i]; a[i] = { value: this.getRowValue(r, sType, nColumn), element: r }; }; return a; }, destroyCache: function (oArray) { var l = oArray.length; for (var i = 0; i < l; i++) { oArray[i].value = null; oArray[i].element = null; oArray[i] = null; } }, getRowValue: function (oRow, sType, nColumn) { // if we have defined a custom getRowValue use that if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue) return this._sortTypeInfo[sType].getRowValue(oRow, nColumn); var s; var c = oRow.cells[nColumn]; if (typeof c.innerText != "undefined") s = c.innerText; else s = this.getInnerText(c); return this.getValueFromString(s, sType); }, getInnerText: function (oNode) { var s = ""; var cs = oNode.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { switch (cs[i].nodeType) { case 1: //ELEMENT_NODE s += this.getInnerText(cs[i]); break; case 3: //TEXT_NODE s += cs[i].nodeValue; break; } } return s; }, getValueFromString: function (sText, sType) { if (this._sortTypeInfo[sType]) return this._sortTypeInfo[sType].getValueFromString( sText ); return sText; /* switch (sType) { case "Number": return Number(sText); case "CaseInsensitiveString": return sText.toUpperCase(); case "Date": var parts = sText.split("-"); var d = new Date(0); d.setFullYear(parts[0]); d.setDate(parts[2]); d.setMonth(parts[1] - 1); return d.valueOf(); } return sText; */ }, getSortFunction: function (sType, nColumn) { if (this._sortTypeInfo[sType]) return this._sortTypeInfo[sType].compare; return this.basicCompare; }, destroy: function () { this.uninitHeader(); var win = this.document.parentWindow; if (win && typeof win.detachEvent != "undefined") { // only IE needs this win.detachEvent("onunload", this._onunload); } this._onunload = null; this.element = null; this.tHead = null; this.tBody = null; this.document = null; this._headerOnclick = null; this.sortTypes = null; this._asyncsort = null; this.onsort = null; }, // Adds a sort type to all instance of SortableTable // sType : String - the identifier of the sort type // fGetValueFromString : function ( s : string ) : T - A function that takes a // string and casts it to a desired format. If left out the string is just // returned // fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort // compare function. Takes two values and compares them. If left out less than, // <, compare is used // fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A function // that takes the row and the column index and returns the value used to compare. // If left out then the innerText is first taken for the cell and then the // fGetValueFromString is used to convert that string the desired value and type addSortType: function (sType, fGetValueFromString, fCompareFunction, fGetRowValue) { this._sortTypeInfo[sType] = { type: sType, getValueFromString: fGetValueFromString || this.idFunction, compare: fCompareFunction || this.basicCompare, getRowValue: fGetRowValue }; }, // this removes the sort type from all instances of SortableTable removeSortType: function (sType) { delete this._sortTypeInfo[sType]; }, basicCompare: function compare(n1, n2) { if (n1.value < n2.value) return -1; if (n2.value < n1.value) return 1; return 0; }, idFunction: function (x) { return x; }, toUpperCase: function (s) { return s.toUpperCase(); }, toDate: function (s) { var parts = s.split("-"); var d = new Date(0); d.setFullYear(parts[0]); d.setDate(parts[2]); d.setMonth(parts[1] - 1); return d.valueOf(); } }); AjaXplorer/AjaXplorer/client/js/lib/prototype/cookiejar.js0000766000000000000000000000757211122202530025074 0ustar adminadministrators/** * Javascript code to store data as JSON strings in cookies. * It uses prototype.js 1.5.1 (http://www.prototypejs.org) * * Author : Lalit Patel * Website: http://www.lalit.org/lab/jsoncookies * License: Creative Commons Attribution-ShareAlike 2.5 * http://creativecommons.org/licenses/by-sa/2.5/ * Version: 0.4 * Updated: Aug 11, 2007 10:09am * * Chnage Log: * v 0.4 * - Removed a extra comma in options (was breaking in IE and Opera). (Thanks Jason) * - Removed the parameter name from the initialize function * - Changed the way expires date was being calculated. (Thanks David) * v 0.3 * - Removed dependancy on json.js (http://www.json.org/json.js) * - empty() function only deletes the cookies set by CookieJar */ var CookieJar = Class.create(); CookieJar.prototype = { /** * Append before all cookie names to differntiate them. */ appendString: "__CJ_", /** * Initializes the cookie jar with the options. */ initialize: function(options) { this.options = { expires: 3600, // seconds (1 hr) path: '', // cookie path domain: '', // cookie domain secure: '' // secure ? }; Object.extend(this.options, options || {}); if (this.options.expires != '') { var date = new Date(); date = new Date(date.getTime() + (this.options.expires * 1000)); this.options.expires = '; expires=' + date.toGMTString(); } if (this.options.path != '') { this.options.path = '; path=' + escape(this.options.path); } if (this.options.domain != '') { this.options.domain = '; domain=' + escape(this.options.domain); } if (this.options.secure == 'secure') { this.options.secure = '; secure'; } else { this.options.secure = ''; } }, /** * Adds a name values pair. */ put: function(name, value) { name = this.appendString + name; cookie = this.options; var type = typeof value; switch(type) { case 'undefined': case 'function' : case 'unknown' : return false; case 'boolean' : case 'string' : case 'number' : value = String(value.toString()); } var cookie_str = name + "=" + escape(Object.toJSON(value)); try { document.cookie = cookie_str + cookie.expires + cookie.path + cookie.domain + cookie.secure; } catch (e) { return false; } return true; }, /** * Removes a particular cookie (name value pair) form the Cookie Jar. */ remove: function(name) { name = this.appendString + name; cookie = this.options; try { var date = new Date(); date.setTime(date.getTime() - (3600 * 1000)); var expires = '; expires=' + date.toGMTString(); document.cookie = name + "=" + expires + cookie.path + cookie.domain + cookie.secure; } catch (e) { return false; } return true; }, /** * Return a particular cookie by name; */ get: function(name) { name = this.appendString + name; var cookies = document.cookie.match(name + '=(.*?)(;|$)'); if (cookies) { return (unescape(cookies[1])).evalJSON(); } else { return null; } }, /** * Empties the Cookie Jar. Deletes all the cookies. */ empty: function() { keys = this.getKeys(); size = keys.size(); for(i=0; i -1, Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) }, BrowserFeatures: { XPath: !!document.evaluate, ElementExtensions: !!window.HTMLElement, SpecificElementExtensions: document.createElement('div').__proto__ && document.createElement('div').__proto__ !== document.createElement('form').__proto__ }, ScriptFragment: ']*>([\\S\\s]*?)<\/script>', JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, emptyFunction: function() { }, K: function(x) { return x } }; if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false; if (Prototype.Browser.WebKit) Prototype.BrowserFeatures.XPath = false; /* Based on Alex Arnell's inheritance implementation. */ var Class = { create: function() { var parent = null, properties = $A(arguments); if (Object.isFunction(properties[0])) parent = properties.shift(); function klass() { this.initialize.apply(this, arguments); } Object.extend(klass, Class.Methods); klass.superclass = parent; klass.subclasses = []; if (parent) { var subclass = function() { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } for (var i = 0; i < properties.length; i++) klass.addMethods(properties[i]); if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction; klass.prototype.constructor = klass; return klass; } }; Class.Methods = { addMethods: function(source) { var ancestor = this.superclass && this.superclass.prototype; var properties = Object.keys(source); if (!Object.keys({ toString: true }).length) properties.push("toString", "valueOf"); for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; if (ancestor && Object.isFunction(value) && value.argumentNames().first() == "$super") { var method = value, value = Object.extend((function(m) { return function() { return ancestor[m].apply(this, arguments) }; })(property).wrap(method), { valueOf: function() { return method }, toString: function() { return method.toString() } }); } this.prototype[property] = value; } return this; } }; var Abstract = { }; Object.extend = function(destination, source) { for (var property in source) destination[property] = source[property]; return destination; }; Object.extend(Object, { inspect: function(object) { try { if (object === undefined) return 'undefined'; if (object === null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } }, toJSON: function(object) { var type = typeof object; switch (type) { case 'undefined': case 'function': case 'unknown': return; case 'boolean': return object.toString(); } if (object === null) return 'null'; if (object.toJSON) return object.toJSON(); if (Object.isElement(object)) return; var results = []; for (var property in object) { var value = Object.toJSON(object[property]); if (value !== undefined) results.push(property.toJSON() + ': ' + value); } return '{' + results.join(', ') + '}'; }, toQueryString: function(object) { return $H(object).toQueryString(); }, toHTML: function(object) { return object && object.toHTML ? object.toHTML() : String.interpret(object); }, keys: function(object) { var keys = []; for (var property in object) keys.push(property); return keys; }, values: function(object) { var values = []; for (var property in object) values.push(object[property]); return values; }, clone: function(object) { return Object.extend({ }, object); }, isElement: function(object) { return object && object.nodeType == 1; }, isArray: function(object) { return object && object.constructor === Array; }, isHash: function(object) { return object instanceof Hash; }, isFunction: function(object) { return typeof object == "function"; }, isString: function(object) { return typeof object == "string"; }, isNumber: function(object) { return typeof object == "number"; }, isUndefined: function(object) { return typeof object == "undefined"; } }); Object.extend(Function.prototype, { argumentNames: function() { var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); return names.length == 1 && !names[0] ? [] : names; }, bind: function() { if (arguments.length < 2 && arguments[0] === undefined) return this; var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); } }, bindAsEventListener: function() { var __method = this, args = $A(arguments), object = args.shift(); return function(event) { return __method.apply(object, [event || window.event].concat(args)); } }, curry: function() { if (!arguments.length) return this; var __method = this, args = $A(arguments); return function() { return __method.apply(this, args.concat($A(arguments))); } }, delay: function() { var __method = this, args = $A(arguments), timeout = args.shift() * 1000; return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); }, wrap: function(wrapper) { var __method = this; return function() { return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); } }, methodize: function() { if (this._methodized) return this._methodized; var __method = this; return this._methodized = function() { return __method.apply(null, [this].concat($A(arguments))); }; } }); Function.prototype.defer = Function.prototype.delay.curry(0.01); Date.prototype.toJSON = function() { return '"' + this.getUTCFullYear() + '-' + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + this.getUTCDate().toPaddedString(2) + 'T' + this.getUTCHours().toPaddedString(2) + ':' + this.getUTCMinutes().toPaddedString(2) + ':' + this.getUTCSeconds().toPaddedString(2) + 'Z"'; }; var Try = { these: function() { var returnValue; for (var i = 0, length = arguments.length; i < length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) { } } return returnValue; } }; RegExp.prototype.match = RegExp.prototype.test; RegExp.escape = function(str) { return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; /*--------------------------------------------------------------------------*/ var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, execute: function() { this.callback(this); }, stop: function() { if (!this.timer) return; clearInterval(this.timer); this.timer = null; }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.execute(); } finally { this.currentlyExecuting = false; } } } }); Object.extend(String, { interpret: function(value) { return value == null ? '' : String(value); }, specialChar: { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' } }); Object.extend(String.prototype, { gsub: function(pattern, replacement) { var result = '', source = this, match; replacement = arguments.callee.prepareReplacement(replacement); while (source.length > 0) { if (match = source.match(pattern)) { result += source.slice(0, match.index); result += String.interpret(replacement(match)); source = source.slice(match.index + match[0].length); } else { result += source, source = ''; } } return result; }, sub: function(pattern, replacement, count) { replacement = this.gsub.prepareReplacement(replacement); count = count === undefined ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; return replacement(match); }); }, scan: function(pattern, iterator) { this.gsub(pattern, iterator); return String(this); }, truncate: function(length, truncation) { length = length || 30; truncation = truncation === undefined ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); }, strip: function() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); }, stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(function(script) { return eval(script) }); }, escapeHTML: function() { var self = arguments.callee; self.text.data = this; return self.div.innerHTML; }, unescapeHTML: function() { var div = new Element('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? (div.childNodes.length > 1 ? $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : div.childNodes[0].nodeValue) : ''; }, toQueryParams: function(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); if (!match) return { }; return match[1].split(separator || '&').inject({ }, function(hash, pair) { if ((pair = pair.split('='))[0]) { var key = decodeURIComponent(pair.shift()); var value = pair.length > 1 ? pair.join('=') : pair[0]; if (value != undefined) value = decodeURIComponent(value); if (key in hash) { if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value); } else hash[key] = value; } return hash; }); }, toArray: function() { return this.split(''); }, succ: function() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); }, times: function(count) { return count < 1 ? '' : new Array(count + 1).join(this); }, camelize: function() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0]; for (var i = 1; i < len; i++) camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); return camelized; }, capitalize: function() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); }, underscore: function() { return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); }, dasherize: function() { return this.gsub(/_/,'-'); }, inspect: function(useDoubleQuotes) { var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { var character = String.specialChar[match[0]]; return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); }); if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; return "'" + escapedString.replace(/'/g, '\\\'') + "'"; }, toJSON: function() { return this.inspect(true); }, unfilterJSON: function(filter) { return this.sub(filter || Prototype.JSONFilter, '#{1}'); }, isJSON: function() { var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); }, evalJSON: function(sanitize) { var json = this.unfilterJSON(); try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); }, include: function(pattern) { return this.indexOf(pattern) > -1; }, startsWith: function(pattern) { return this.indexOf(pattern) === 0; }, endsWith: function(pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; }, empty: function() { return this == ''; }, blank: function() { return /^\s*$/.test(this); }, interpolate: function(object, pattern) { return new Template(this, pattern).evaluate(object); } }); if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { escapeHTML: function() { return this.replace(/&/g,'&').replace(//g,'>'); }, unescapeHTML: function() { return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } }); String.prototype.gsub.prepareReplacement = function(replacement) { if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) }; }; String.prototype.parseQuery = String.prototype.toQueryParams; Object.extend(String.prototype.escapeHTML, { div: document.createElement('div'), text: document.createTextNode('') }); with (String.prototype.escapeHTML) div.appendChild(text); var Template = Class.create({ initialize: function(template, pattern) { this.template = template.toString(); this.pattern = pattern || Template.Pattern; }, evaluate: function(object) { if (Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { if (object == null) return ''; var before = match[1] || ''; if (before == '\\') return match[2]; var ctx = object, expr = match[3]; var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); if (match == null) return before; while (match != null) { var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); match = pattern.exec(expr); } return before + String.interpret(ctx); }.bind(this)); } }); Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; var $break = { }; var Enumerable = { each: function(iterator, context) { var index = 0; iterator = iterator.bind(context); try { this._each(function(value) { iterator(value, index++); }); } catch (e) { if (e != $break) throw e; } return this; }, eachSlice: function(number, iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var index = -number, slices = [], array = this.toArray(); while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); }, all: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result = true; this.each(function(value, index) { result = result && !!iterator(value, index); if (!result) throw $break; }); return result; }, any: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result = false; this.each(function(value, index) { if (result = !!iterator(value, index)) throw $break; }); return result; }, collect: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function(iterator, context) { iterator = iterator.bind(context); var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator, context) { iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; }, grep: function(filter, iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; if (Object.isString(filter)) filter = new RegExp(filter); this.each(function(value, index) { if (filter.match(value)) results.push(iterator(value, index)); }); return results; }, include: function(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inGroupsOf: function(number, fillWith) { fillWith = fillWith === undefined ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); }, inject: function(memo, iterator, context) { iterator = iterator.bind(context); this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; }, invoke: function(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args); }); }, max: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { value = iterator(value, index); if (result == undefined || value >= result) result = value; }); return result; }, min: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { value = iterator(value, index); if (result == undefined || value < result) result = value; }); return result; }, partition: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var trues = [], falses = []; this.each(function(value, index) { (iterator(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; }, reject: function(iterator, context) { iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; }, sortBy: function(iterator, context) { iterator = iterator.bind(context); return this.map(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, toArray: function() { return this.map(); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { return iterator(collections.pluck(index)); }); }, size: function() { return this.toArray().length; }, inspect: function() { return '#'; } }; Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, filter: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray, every: Enumerable.all, some: Enumerable.any }); function $A(iterable) { if (!iterable) return []; if (iterable.toArray) return iterable.toArray(); var length = iterable.length, results = new Array(length); while (length--) results[length] = iterable[length]; return results; } if (Prototype.Browser.WebKit) { function $A(iterable) { if (!iterable) return []; if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && iterable.toArray) return iterable.toArray(); var length = iterable.length, results = new Array(length); while (length--) results[length] = iterable[length]; return results; } } Array.from = $A; Object.extend(Array.prototype, Enumerable); if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(Object.isArray(value) ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, reduce: function() { return this.length > 1 ? this : this[0]; }, uniq: function(sorted) { return this.inject([], function(array, value, index) { if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value); return array; }); }, intersect: function(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }); }); }, clone: function() { return [].concat(this); }, size: function() { return this.length; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }, toJSON: function() { var results = []; this.each(function(object) { var value = Object.toJSON(object); if (value !== undefined) results.push(value); }); return '[' + results.join(', ') + ']'; } }); // use native browser JS 1.6 implementation if available if (Object.isFunction(Array.prototype.forEach)) Array.prototype._each = Array.prototype.forEach; if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { i || (i = 0); var length = this.length; if (i < 0) i = length + i; for (; i < length; i++) if (this[i] === item) return i; return -1; }; if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; var n = this.slice(0, i).reverse().indexOf(item); return (n < 0) ? n : i - n - 1; }; Array.prototype.toArray = Array.prototype.clone; function $w(string) { if (!Object.isString(string)) return []; string = string.strip(); return string ? string.split(/\s+/) : []; } if (Prototype.Browser.Opera){ Array.prototype.concat = function() { var array = []; for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); for (var i = 0, length = arguments.length; i < length; i++) { if (Object.isArray(arguments[i])) { for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) array.push(arguments[i][j]); } else { array.push(arguments[i]); } } return array; }; } Object.extend(Number.prototype, { toColorPart: function() { return this.toPaddedString(2, 16); }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }, toPaddedString: function(length, radix) { var string = this.toString(radix || 10); return '0'.times(length - string.length) + string; }, toJSON: function() { return isFinite(this) ? this.toString() : 'null'; } }); $w('abs round ceil floor').each(function(method){ Number.prototype[method] = Math[method].methodize(); }); function $H(object) { return new Hash(object); }; var Hash = Class.create(Enumerable, (function() { if (function() { var i = 0, Test = function(value) { this.key = value }; Test.prototype.key = 'foo'; for (var property in new Test('bar')) i++; return i > 1; }()) { function each(iterator) { var cache = []; for (var key in this._object) { var value = this._object[key]; if (cache.include(key)) continue; cache.push(key); var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } } } else { function each(iterator) { for (var key in this._object) { var value = this._object[key], pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } } } function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)); } return { initialize: function(object) { this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); }, _each: each, set: function(key, value) { return this._object[key] = value; }, get: function(key) { return this._object[key]; }, unset: function(key) { var value = this._object[key]; delete this._object[key]; return value; }, toObject: function() { return Object.clone(this._object); }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, index: function(value) { var match = this.detect(function(pair) { return pair.value === value; }); return match && match.key; }, merge: function(object) { return this.clone().update(object); }, update: function(object) { return new Hash(object).inject(this, function(result, pair) { result.set(pair.key, pair.value); return result; }); }, toQueryString: function() { return this.map(function(pair) { var key = encodeURIComponent(pair.key), values = pair.value; if (values && typeof values == 'object') { if (Object.isArray(values)) return values.map(toQueryPair.curry(key)).join('&'); } return toQueryPair(key, values); }).join('&'); }, inspect: function() { return '#'; }, toJSON: function() { return Object.toJSON(this.toObject()); }, clone: function() { return new Hash(this); } } })()); Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; Hash.from = $H; var ObjectRange = Class.create(Enumerable, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ(); } }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } }); var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive); }; var Ajax = { getTransport: function() { return Try.these( function() {return new XMLHttpRequest()}, function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')} ) || false; }, activeRequestCount: 0 }; Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responder) { if (!this.include(responder)) this.responders.push(responder); }, unregister: function(responder) { this.responders = this.responders.without(responder); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (Object.isFunction(responder[callback])) { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) { } } }); } }; Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++ }, onComplete: function() { Ajax.activeRequestCount-- } }); Ajax.Base = Class.create({ initialize: function(options) { this.options = { method: 'post', asynchronous: true, contentType: 'application/x-www-form-urlencoded', encoding: 'UTF-8', parameters: '', evalJSON: true, evalJS: true }; Object.extend(this.options, options || { }); this.options.method = this.options.method.toLowerCase(); if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams(); } }); Ajax.Request = Class.create(Ajax.Base, { _complete: false, initialize: function($super, url, options) { $super(options); this.transport = Ajax.getTransport(); this.request(url); }, request: function(url) { this.url = url; this.method = this.options.method; var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { // simulate other verbs over post params['_method'] = this.method; this.method = 'post'; } this.parameters = params; if (params = Object.toQueryString(params)) { // when GET, append parameters to URL if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='; } try { var response = new Ajax.Response(this); if (this.options.onCreate) this.options.onCreate(response); Ajax.Responders.dispatch('onCreate', this, response); this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); this.body = this.method == 'post' ? (this.options.postBody || params) : null; this.transport.send(this.body); /* Force Firefox to handle ready state 4 for synchronous requests */ if (!this.options.asynchronous && this.transport.overrideMimeType) this.onStateChange(); } catch (e) { this.dispatchException(e); } }, onStateChange: function() { var readyState = this.transport.readyState; if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState); }, setRequestHeaders: function() { var headers = { 'X-Requested-With': 'XMLHttpRequest', 'X-Prototype-Version': Prototype.Version, 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' }; if (this.method == 'post') { headers['Content-type'] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : ''); /* Force "Connection: close" for older Mozilla browsers to work * around a bug where XMLHttpRequest sends an incorrect * Content-length header. See Mozilla Bugzilla #246651. */ if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) headers['Connection'] = 'close'; } // user-defined headers if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i+1]; else $H(extras).each(function(pair) { headers[pair.key] = pair.value }); } for (var name in headers) this.transport.setRequestHeader(name, headers[name]); }, success: function() { var status = this.getStatus(); return !status || (status >= 200 && status < 300); }, getStatus: function() { try { return this.transport.status || 0; } catch (e) { return 0 } }, respondToReadyState: function(readyState) { var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); if (state == 'Complete') { try { this._complete = true; (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(response, response.headerJSON); } catch (e) { this.dispatchException(e); } var contentType = response.getHeader('Content-type'); if (this.options.evalJS == 'force' || (this.options.evalJS && contentType && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) this.evalResponse(); } try { (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); } catch (e) { this.dispatchException(e); } if (state == 'Complete') { // avoid memory leak in MSIE: clean up this.transport.onreadystatechange = Prototype.emptyFunction; } }, getHeader: function(name) { try { return this.transport.getResponseHeader(name); } catch (e) { return null } }, evalResponse: function() { try { return eval((this.transport.responseText || '').unfilterJSON()); } catch (e) { this.dispatchException(e); } }, dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception); } }); Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Response = Class.create({ initialize: function(request){ this.request = request; var transport = this.transport = request.transport, readyState = this.readyState = transport.readyState; if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { this.status = this.getStatus(); this.statusText = this.getStatusText(); this.responseText = String.interpret(transport.responseText); this.headerJSON = this._getHeaderJSON(); } if(readyState == 4) { var xml = transport.responseXML; this.responseXML = xml === undefined ? null : xml; this.responseJSON = this._getResponseJSON(); } }, status: 0, statusText: '', getStatus: Ajax.Request.prototype.getStatus, getStatusText: function() { try { return this.transport.statusText || ''; } catch (e) { return '' } }, getHeader: Ajax.Request.prototype.getHeader, getAllHeaders: function() { try { return this.getAllResponseHeaders(); } catch (e) { return null } }, getResponseHeader: function(name) { return this.transport.getResponseHeader(name); }, getAllResponseHeaders: function() { return this.transport.getAllResponseHeaders(); }, _getHeaderJSON: function() { var json = this.getHeader('X-JSON'); if (!json) return null; json = decodeURIComponent(escape(json)); try { return json.evalJSON(this.request.options.sanitizeJSON); } catch (e) { this.request.dispatchException(e); } }, _getResponseJSON: function() { var options = this.request.options; if (!options.evalJSON || (options.evalJSON != 'force' && !(this.getHeader('Content-type') || '').include('application/json'))) return null; try { return this.transport.responseText.evalJSON(options.sanitizeJSON); } catch (e) { this.request.dispatchException(e); } } }); Ajax.Updater = Class.create(Ajax.Request, { initialize: function($super, container, url, options) { this.container = { success: (container.success || container), failure: (container.failure || (container.success ? null : container)) }; options = options || { }; var onComplete = options.onComplete; options.onComplete = (function(response, param) { this.updateContent(response.responseText); if (Object.isFunction(onComplete)) onComplete(response, param); }).bind(this); $super(url, options); }, updateContent: function(responseText) { var receiver = this.container[this.success() ? 'success' : 'failure'], options = this.options; if (!options.evalScripts) responseText = responseText.stripScripts(); if (receiver = $(receiver)) { if (options.insertion) { if (Object.isString(options.insertion)) { var insertion = { }; insertion[options.insertion] = responseText; receiver.insert(insertion); } else options.insertion(receiver, responseText); } else receiver.update(responseText); } if (this.success()) { if (this.onComplete) this.onComplete.bind(this).defer(); } } }); Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { initialize: function($super, container, url, options) { $super(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); this.updater = { }; this.container = container; this.url = url; this.start(); }, start: function() { this.options.onComplete = this.updateComplete.bind(this); this.onTimerEvent(); }, stop: function() { this.updater.options.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, updateComplete: function(response) { if (this.options.decay) { this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1); this.lastText = response.responseText; } this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); }, onTimerEvent: function() { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); return elements; } if (Object.isString(element)) element = document.getElementById(element); return Element.extend(element); } if (Prototype.BrowserFeatures.XPath) { document._getElementsByXPath = function(expression, parentElement) { var results = []; var query = document.evaluate(expression, $(parentElement) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0, length = query.snapshotLength; i < length; i++) results.push(Element.extend(query.snapshotItem(i))); return results; }; } /*--------------------------------------------------------------------------*/ if (!window.Node) var Node = { }; if (!Node.ELEMENT_NODE) { // DOM level 2 ECMAScript Language Binding Object.extend(Node, { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12 }); } (function() { var element = this.Element; this.Element = function(tagName, attributes) { attributes = attributes || { }; tagName = tagName.toLowerCase(); var cache = Element.cache; if (Prototype.Browser.IE && attributes.name) { tagName = '<' + tagName + ' name="' + attributes.name + '">'; delete attributes.name; return Element.writeAttribute(document.createElement(tagName), attributes); } if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); }; Object.extend(this.Element, element || { }); }).call(window); Element.cache = { }; Element.Methods = { visible: function(element) { return $(element).style.display != 'none'; }, toggle: function(element) { element = $(element); Element[Element.visible(element) ? 'hide' : 'show'](element); return element; }, hide: function(element) { $(element).style.display = 'none'; return element; }, show: function(element) { $(element).style.display = ''; return element; }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); return element; }, update: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); element.innerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }, replace: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); else if (!Object.isElement(content)) { content = Object.toHTML(content); var range = element.ownerDocument.createRange(); range.selectNode(element); content.evalScripts.bind(content).defer(); content = range.createContextualFragment(content.stripScripts()); } element.parentNode.replaceChild(content, element); return element; }, insert: function(element, insertions) { element = $(element); if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = {bottom:insertions}; var content, t, range; for (position in insertions) { content = insertions[position]; position = position.toLowerCase(); t = Element._insertionTranslations[position]; if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { t.insert(element, content); continue; } content = Object.toHTML(content); range = element.ownerDocument.createRange(); t.initializeRange(element, range); t.insert(element, range.createContextualFragment(content.stripScripts())); content.evalScripts.bind(content).defer(); } return element; }, wrap: function(element, wrapper, attributes) { element = $(element); if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || { }); else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); else wrapper = new Element('div', wrapper); if (element.parentNode) element.parentNode.replaceChild(wrapper, element); wrapper.appendChild(element); return wrapper; }, inspect: function(element) { element = $(element); var result = '<' + element.tagName.toLowerCase(); $H({'id': 'id', 'className': 'class'}).each(function(pair) { var property = pair.first(), attribute = pair.last(); var value = (element[property] || '').toString(); if (value) result += ' ' + attribute + '=' + value.inspect(true); }); return result + '>'; }, recursivelyCollect: function(element, property) { element = $(element); var elements = []; while (element = element[property]) if (element.nodeType == 1) elements.push(Element.extend(element)); return elements; }, ancestors: function(element) { return $(element).recursivelyCollect('parentNode'); }, descendants: function(element) { return $A($(element).getElementsByTagName('*')).each(Element.extend); }, firstDescendant: function(element) { element = $(element).firstChild; while (element && element.nodeType != 1) element = element.nextSibling; return $(element); }, immediateDescendants: function(element) { if (!(element = $(element).firstChild)) return []; while (element && element.nodeType != 1) element = element.nextSibling; if (element) return [element].concat($(element).nextSiblings()); return []; }, previousSiblings: function(element) { return $(element).recursivelyCollect('previousSibling'); }, nextSiblings: function(element) { return $(element).recursivelyCollect('nextSibling'); }, siblings: function(element) { element = $(element); return element.previousSiblings().reverse().concat(element.nextSiblings()); }, match: function(element, selector) { if (Object.isString(selector)) selector = new Selector(selector); return selector.match($(element)); }, up: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(element.parentNode); var ancestors = element.ancestors(); return expression ? Selector.findElement(ancestors, expression, index) : ancestors[index || 0]; }, down: function(element, expression, index) { element = $(element); if (arguments.length == 1) return element.firstDescendant(); var descendants = element.descendants(); return expression ? Selector.findElement(descendants, expression, index) : descendants[index || 0]; }, previous: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); var previousSiblings = element.previousSiblings(); return expression ? Selector.findElement(previousSiblings, expression, index) : previousSiblings[index || 0]; }, next: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); var nextSiblings = element.nextSiblings(); return expression ? Selector.findElement(nextSiblings, expression, index) : nextSiblings[index || 0]; }, select: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element, args); }, adjacent: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element.parentNode, args).without(element); }, identify: function(element) { element = $(element); var id = element.readAttribute('id'), self = arguments.callee; if (id) return id; do { id = 'anonymous_element_' + self.counter++ } while ($(id)); element.writeAttribute('id', id); return id; }, readAttribute: function(element, name) { element = $(element); if (Prototype.Browser.IE) { var t = Element._attributeTranslations.read; if (t.values[name]) return t.values[name](element, name); if (t.names[name]) name = t.names[name]; if (name.include(':')) { return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value; } } return element.getAttribute(name); }, writeAttribute: function(element, name, value) { element = $(element); var attributes = { }, t = Element._attributeTranslations.write; if (typeof name == 'object') attributes = name; else attributes[name] = value === undefined ? true : value; for (var attr in attributes) { var name = t.names[attr] || attr, value = attributes[attr]; if (t.values[attr]) name = t.values[attr](element, value); if (value === false || value === null) element.removeAttribute(name); else if (value === true) element.setAttribute(name, name); else element.setAttribute(name, value); } return element; }, getHeight: function(element) { return $(element).getDimensions().height; }, getWidth: function(element) { return $(element).getDimensions().width; }, classNames: function(element) { return new Element.ClassNames(element); }, hasClassName: function(element, className) { if (!(element = $(element))) return; var elementClassName = element.className; return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); }, addClassName: function(element, className) { if (!(element = $(element))) return; if (!element.hasClassName(className)) element.className += (element.className ? ' ' : '') + className; return element; }, removeClassName: function(element, className) { if (!(element = $(element))) return; element.className = element.className.replace( new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); return element; }, toggleClassName: function(element, className) { if (!(element = $(element))) return; return element[element.hasClassName(className) ? 'removeClassName' : 'addClassName'](className); }, // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); var node = element.firstChild; while (node) { var nextNode = node.nextSibling; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) element.removeChild(node); node = nextNode; } return element; }, empty: function(element) { return $(element).innerHTML.blank(); }, descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); if (element.compareDocumentPosition) return (element.compareDocumentPosition(ancestor) & 8) === 8; if (element.sourceIndex && !Prototype.Browser.Opera) { var e = element.sourceIndex, a = ancestor.sourceIndex, nextAncestor = ancestor.nextSibling; if (!nextAncestor) { do { ancestor = ancestor.parentNode; } while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); } if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); } while (element = element.parentNode) if (element == ancestor) return true; return false; }, scrollTo: function(element) { element = $(element); var pos = element.cumulativeOffset(); window.scrollTo(pos[0], pos[1]); return element; }, getStyle: function(element, style) { element = $(element); style = style == 'float' ? 'cssFloat' : style.camelize(); var value = element.style[style]; if (!value) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css[style] : null; } if (style == 'opacity') return value ? parseFloat(value) : 1.0; return value == 'auto' ? null : value; }, getOpacity: function(element) { return $(element).getStyle('opacity'); }, setStyle: function(element, styles) { element = $(element); var elementStyle = element.style, match; if (Object.isString(styles)) { element.style.cssText += ';' + styles; return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; } for (var property in styles) if (property == 'opacity') element.setOpacity(styles[property]); else elementStyle[(property == 'float' || property == 'cssFloat') ? (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : property] = styles[property]; return element; }, setOpacity: function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; return element; }, getDimensions: function(element) { element = $(element); var display = $(element).getStyle('display'); if (display != 'none' && display != null) // Safari bug return {width: element.offsetWidth, height: element.offsetHeight}; // All *Width and *Height properties give 0 on elements with display none, // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = originalDisplay; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; // Opera returns the offset relative to the positioning context, when an // element is position relative but top and left have not been defined if (window.opera) { element.style.top = 0; element.style.left = 0; } } return element; }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } return element; }, makeClipping: function(element) { element = $(element); if (element._overflow) return element; element._overflow = Element.getStyle(element, 'overflow') || 'auto'; if (element._overflow !== 'hidden') element.style.overflow = 'hidden'; return element; }, undoClipping: function(element) { element = $(element); if (!element._overflow) return element; element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; element._overflow = null; return element; }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; try { element.offsetParent } catch(e) { return Element._returnOffset(0,0) } element = element.offsetParent; } while (element); return Element._returnOffset(valueL, valueT); }, positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { if (element.tagName == 'BODY') break; var p = Element.getStyle(element, 'position'); if (p == 'relative' || p == 'absolute') break; } } while (element); return Element._returnOffset(valueL, valueT); }, absolutize: function(element) { element = $(element); if (element.getStyle('position') == 'absolute') return; // Position.prepare(); // To be done manually by Scripty when it needs it. var offsets = element.positionedOffset(); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; var height = element.clientHeight; element._originalLeft = left - parseFloat(element.style.left || 0); element._originalTop = top - parseFloat(element.style.top || 0); element._originalWidth = element.style.width; element._originalHeight = element.style.height; element.style.position = 'absolute'; element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.width = width + 'px'; element.style.height = height + 'px'; return element; }, relativize: function(element) { element = $(element); if (element.getStyle('position') == 'relative') return; // Position.prepare(); // To be done manually by Scripty when it needs it. element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.height = element._originalHeight; element.style.width = element._originalWidth; return element; }, cumulativeScrollOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return Element._returnOffset(valueL, valueT); }, getOffsetParent: function(element) { if (element.offsetParent) return $(element.offsetParent); if (element == document.body) return $(element); while ((element = element.parentNode) && element != document.body) if (Element.getStyle(element, 'position') != 'static') return $(element); return $(document.body); }, viewportOffset: function(forElement) { var valueT = 0, valueL = 0; var element = forElement; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; // Safari fix if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break; } while (element = element.offsetParent); element = forElement; do { if (!Prototype.Browser.Opera || element.tagName == 'BODY') { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0; } } while (element = element.parentNode); return Element._returnOffset(valueL, valueT); }, clonePosition: function(element, source) { var options = Object.extend({ setLeft: true, setTop: true, setWidth: true, setHeight: true, offsetTop: 0, offsetLeft: 0 }, arguments[2] || { }); // find page position of source source = $(source); var p = source.viewportOffset(); // find coordinate system to use element = $(element); var delta = [0, 0]; var parent = null; // delta [0,0] will do fine with position: fixed elements, // position:absolute needs offsetParent deltas if (Element.getStyle(element, 'position') == 'absolute') { parent = element.getOffsetParent(); delta = parent.viewportOffset(); } // correct by body offsets (fixes Safari) if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } // set position if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if (options.setWidth) element.style.width = source.offsetWidth + 'px'; if (options.setHeight) element.style.height = source.offsetHeight + 'px'; return element; } }; Element.Methods.identify.counter = 1; Object.extend(Element.Methods, { getElementsBySelector: Element.Methods.select, childElements: Element.Methods.immediateDescendants }); Element._attributeTranslations = { write: { names: { className: 'class', htmlFor: 'for' }, values: { } } }; if (!document.createRange || Prototype.Browser.Opera) { Element.Methods.insert = function(element, insertions) { element = $(element); if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = { bottom: insertions }; var t = Element._insertionTranslations, content, position, pos, tagName; for (position in insertions) { content = insertions[position]; position = position.toLowerCase(); pos = t[position]; if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { pos.insert(element, content); continue; } content = Object.toHTML(content); tagName = ((position == 'before' || position == 'after') ? element.parentNode : element).tagName.toUpperCase(); if (t.tags[tagName]) { var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); if (position == 'top' || position == 'after') fragments.reverse(); fragments.each(pos.insert.curry(element)); } else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); content.evalScripts.bind(content).defer(); } return element; }; } if (Prototype.Browser.Opera) { Element.Methods._getStyle = Element.Methods.getStyle; Element.Methods.getStyle = function(element, style) { switch(style) { case 'left': case 'top': case 'right': case 'bottom': if (Element._getStyle(element, 'position') == 'static') return null; default: return Element._getStyle(element, style); } }; Element.Methods._readAttribute = Element.Methods.readAttribute; Element.Methods.readAttribute = function(element, attribute) { if (attribute == 'title') return element.title; return Element._readAttribute(element, attribute); }; } else if (Prototype.Browser.IE) { $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { Element.Methods[method] = Element.Methods[method].wrap( function(proceed, element) { element = $(element); var position = element.getStyle('position'); if (position != 'static') return proceed(element); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value; } ); }); Element.Methods.getStyle = function(element, style) { element = $(element); style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); var value = element.style[style]; if (!value && element.currentStyle) value = element.currentStyle[style]; if (style == 'opacity') { if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) if (value[1]) return parseFloat(value[1]) / 100; return 1.0; } if (value == 'auto') { if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) return element['offset' + style.capitalize()] + 'px'; return null; } return value; }; Element.Methods.setOpacity = function(element, value) { function stripAlpha(filter){ return filter.replace(/alpha\([^\)]*\)/gi,''); } element = $(element); var currentStyle = element.currentStyle; if ((currentStyle && !currentStyle.hasLayout) || (!currentStyle && element.style.zoom == 'normal')) element.style.zoom = 1; var filter = element.getStyle('filter'), style = element.style; if (value == 1 || value === '') { (filter = stripAlpha(filter)) ? style.filter = filter : style.removeAttribute('filter'); return element; } else if (value < 0.00001) value = 0; style.filter = stripAlpha(filter) + 'alpha(opacity=' + (value * 100) + ')'; return element; }; Element._attributeTranslations = { read: { names: { 'class': 'className', 'for': 'htmlFor' }, values: { _getAttr: function(element, attribute) { return element.getAttribute(attribute, 2); }, _getAttrNode: function(element, attribute) { var node = element.getAttributeNode(attribute); return node ? node.value : ""; }, _getEv: function(element, attribute) { var attribute = element.getAttribute(attribute); return attribute ? attribute.toString().slice(23, -2) : null; }, _flag: function(element, attribute) { return $(element).hasAttribute(attribute) ? attribute : null; }, style: function(element) { return element.style.cssText.toLowerCase(); }, title: function(element) { return element.title; } } } }; Element._attributeTranslations.write = { names: Object.clone(Element._attributeTranslations.read.names), values: { checked: function(element, value) { element.checked = !!value; }, style: function(element, value) { element.style.cssText = value ? value : ''; } } }; Element._attributeTranslations.has = {}; $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 'encType maxLength readOnly longDesc').each(function(attr) { Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; Element._attributeTranslations.has[attr.toLowerCase()] = attr; }); (function(v) { Object.extend(v, { href: v._getAttr, src: v._getAttr, type: v._getAttr, action: v._getAttrNode, disabled: v._flag, checked: v._flag, readonly: v._flag, multiple: v._flag, onload: v._getEv, onunload: v._getEv, onclick: v._getEv, ondblclick: v._getEv, onmousedown: v._getEv, onmouseup: v._getEv, onmouseover: v._getEv, onmousemove: v._getEv, onmouseout: v._getEv, onfocus: v._getEv, onblur: v._getEv, onkeypress: v._getEv, onkeydown: v._getEv, onkeyup: v._getEv, onsubmit: v._getEv, onreset: v._getEv, onselect: v._getEv, onchange: v._getEv }); })(Element._attributeTranslations.read.values); } else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1) ? 0.999999 : (value === '') ? '' : (value < 0.00001) ? 0 : value; return element; }; } else if (Prototype.Browser.WebKit) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; if (value == 1) if(element.tagName == 'IMG' && element.width) { element.width++; element.width--; } else try { var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch (e) { } return element; }; // Safari returns margins on body which is incorrect if the child is absolutely // positioned. For performance reasons, redefine Position.cumulativeOffset for // KHTML/WebKit only. Element.Methods.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break; element = element.offsetParent; } while (element); return Element._returnOffset(valueL, valueT); }; } if (Prototype.Browser.IE || Prototype.Browser.Opera) { // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements Element.Methods.update = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); var tagName = element.tagName.toUpperCase(); if (tagName in Element._insertionTranslations.tags) { $A(element.childNodes).each(function(node) { element.removeChild(node) }); Element._getContentFromAnonymousElement(tagName, content.stripScripts()) .each(function(node) { element.appendChild(node) }); } else element.innerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }; } if (document.createElement('div').outerHTML) { Element.Methods.replace = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { element.parentNode.replaceChild(content, element); return element; } content = Object.toHTML(content); var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); if (Element._insertionTranslations.tags[tagName]) { var nextSibling = element.next(); var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); parent.removeChild(element); if (nextSibling) fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); else fragments.each(function(node) { parent.appendChild(node) }); } else element.outerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }; } Element._returnOffset = function(l, t) { var result = [l, t]; result.left = l; result.top = t; return result; }; Element._getContentFromAnonymousElement = function(tagName, html) { var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; div.innerHTML = t[0] + html + t[1]; t[2].times(function() { div = div.firstChild }); return $A(div.childNodes); }; Element._insertionTranslations = { before: { adjacency: 'beforeBegin', insert: function(element, node) { element.parentNode.insertBefore(node, element); }, initializeRange: function(element, range) { range.setStartBefore(element); } }, top: { adjacency: 'afterBegin', insert: function(element, node) { element.insertBefore(node, element.firstChild); }, initializeRange: function(element, range) { range.selectNodeContents(element); range.collapse(true); } }, bottom: { adjacency: 'beforeEnd', insert: function(element, node) { element.appendChild(node); } }, after: { adjacency: 'afterEnd', insert: function(element, node) { element.parentNode.insertBefore(node, element.nextSibling); }, initializeRange: function(element, range) { range.setStartAfter(element); } }, tags: { TABLE: ['', '
    ', 1], TBODY: ['', '
    ', 2], TR: ['', '
    ', 3], TD: ['
    ', '
    ', 4], SELECT: ['', 1] } }; (function() { this.bottom.initializeRange = this.top.initializeRange; Object.extend(this.tags, { THEAD: this.tags.TBODY, TFOOT: this.tags.TBODY, TH: this.tags.TD }); }).call(Element._insertionTranslations); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { attribute = Element._attributeTranslations.has[attribute] || attribute; var node = $(element).getAttributeNode(attribute); return node && node.specified; } }; Element.Methods.ByTag = { }; Object.extend(Element, Element.Methods); if (!Prototype.BrowserFeatures.ElementExtensions && document.createElement('div').__proto__) { window.HTMLElement = { }; window.HTMLElement.prototype = document.createElement('div').__proto__; Prototype.BrowserFeatures.ElementExtensions = true; } Element.extend = (function() { if (Prototype.BrowserFeatures.SpecificElementExtensions) return Prototype.K; var Methods = { }, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { if (!element || element._extendedByPrototype || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), tagName = element.tagName, property, value; // extend methods for specific tags if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); for (property in methods) { value = methods[property]; if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize(); } element._extendedByPrototype = Prototype.emptyFunction; return element; }, { refresh: function() { // extend methods for all tags (Safari doesn't need this) if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); } } }); extend.refresh(); return extend; })(); Element.hasAttribute = function(element, attribute) { if (element.hasAttribute) return element.hasAttribute(attribute); return Element.Methods.Simulated.hasAttribute(element, attribute); }; Element.addMethods = function(methods) { var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; if (!methods) { Object.extend(Form, Form.Methods); Object.extend(Form.Element, Form.Element.Methods); Object.extend(Element.Methods.ByTag, { "FORM": Object.clone(Form.Methods), "INPUT": Object.clone(Form.Element.Methods), "SELECT": Object.clone(Form.Element.Methods), "TEXTAREA": Object.clone(Form.Element.Methods) }); } if (arguments.length == 2) { var tagName = methods; methods = arguments[1]; } if (!tagName) Object.extend(Element.Methods, methods || { }); else { if (Object.isArray(tagName)) tagName.each(extend); else extend(tagName); } function extend(tagName) { tagName = tagName.toUpperCase(); if (!Element.Methods.ByTag[tagName]) Element.Methods.ByTag[tagName] = { }; Object.extend(Element.Methods.ByTag[tagName], methods); } function copy(methods, destination, onlyIfAbsent) { onlyIfAbsent = onlyIfAbsent || false; for (var property in methods) { var value = methods[property]; if (!Object.isFunction(value)) continue; if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize(); } } function findDOMClass(tagName) { var klass; var trans = { "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": "FrameSet", "IFRAME": "IFrame" }; if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; window[klass] = { }; window[klass].prototype = document.createElement(tagName).__proto__; return window[klass]; } if (F.ElementExtensions) { copy(Element.Methods, HTMLElement.prototype); copy(Element.Methods.Simulated, HTMLElement.prototype, true); } if (F.SpecificElementExtensions) { for (var tag in Element.Methods.ByTag) { var klass = findDOMClass(tag); if (Object.isUndefined(klass)) continue; copy(T[tag], klass.prototype); } } Object.extend(Element, Element.Methods); delete Element.ByTag; if (Element.extend.refresh) Element.extend.refresh(); Element.cache = { }; }; document.viewport = { getDimensions: function() { var dimensions = { }; $w('width height').each(function(d) { var D = d.capitalize(); dimensions[d] = self['inner' + D] || (document.documentElement['client' + D] || document.body['client' + D]); }); return dimensions; }, getWidth: function() { return this.getDimensions().width; }, getHeight: function() { return this.getDimensions().height; }, getScrollOffsets: function() { return Element._returnOffset( window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); } }; /* Portions of the Selector class are derived from Jack Slocum’s DomQuery, * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style * license. Please see http://www.yui-ext.com/ for more information. */ var Selector = Class.create({ initialize: function(expression) { this.expression = expression.strip(); this.compileMatcher(); }, compileMatcher: function() { // Selectors with namespaced attributes can't use the XPath version if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression)) return this.compileXPathMatcher(); var e = this.expression, ps = Selector.patterns, h = Selector.handlers, c = Selector.criteria, le, p, m; if (Selector._cache[e]) { this.matcher = Selector._cache[e]; return; } this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"]; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in ps) { p = ps[i]; if (m = e.match(p)) { this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : new Template(c[i]).evaluate(m)); e = e.replace(m[0], ''); break; } } } this.matcher.push("return h.unique(n);\n}"); eval(this.matcher.join('\n')); Selector._cache[this.expression] = this.matcher; }, compileXPathMatcher: function() { var e = this.expression, ps = Selector.patterns, x = Selector.xpath, le, m; if (Selector._cache[e]) { this.xpath = Selector._cache[e]; return; } this.matcher = ['.//*']; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in ps) { if (m = e.match(ps[i])) { this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m)); e = e.replace(m[0], ''); break; } } } this.xpath = this.matcher.join(''); Selector._cache[this.expression] = this.xpath; }, findElements: function(root) { root = root || document; if (this.xpath) return document._getElementsByXPath(this.xpath, root); return this.matcher(root); }, match: function(element) { this.tokens = []; var e = this.expression, ps = Selector.patterns, as = Selector.assertions; var le, p, m; while (e && le !== e && (/\S/).test(e)) { le = e; for (var i in ps) { p = ps[i]; if (m = e.match(p)) { // use the Selector.assertions methods unless the selector // is too complex. if (as[i]) { this.tokens.push([i, Object.clone(m)]); e = e.replace(m[0], ''); } else { // reluctantly do a document-wide search // and look for a match in the array return this.findElements(document).include(element); } } } } var match = true, name, matches; for (var i = 0, token; token = this.tokens[i]; i++) { name = token[0], matches = token[1]; if (!Selector.assertions[name](element, matches)) { match = false; break; } } return match; }, toString: function() { return this.expression; }, inspect: function() { return "#"; } }); Object.extend(Selector, { _cache: { }, xpath: { descendant: "//*", child: "/*", adjacent: "/following-sibling::*[1]", laterSibling: '/following-sibling::*', tagName: function(m) { if (m[1] == '*') return ''; return "[local-name()='" + m[1].toLowerCase() + "' or local-name()='" + m[1].toUpperCase() + "']"; }, className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", id: "[@id='#{1}']", attrPresence: "[@#{1}]", attr: function(m) { m[3] = m[5] || m[6]; return new Template(Selector.xpath.operators[m[2]]).evaluate(m); }, pseudo: function(m) { var h = Selector.xpath.pseudos[m[1]]; if (!h) return ''; if (Object.isFunction(h)) return h(m); return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); }, operators: { '=': "[@#{1}='#{3}']", '!=': "[@#{1}!='#{3}']", '^=': "[starts-with(@#{1}, '#{3}')]", '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", '*=': "[contains(@#{1}, '#{3}')]", '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" }, pseudos: { 'first-child': '[not(preceding-sibling::*)]', 'last-child': '[not(following-sibling::*)]', 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", 'checked': "[@checked]", 'disabled': "[@disabled]", 'enabled': "[not(@disabled)]", 'not': function(m) { var e = m[6], p = Selector.patterns, x = Selector.xpath, le, m, v; var exclusion = []; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in p) { if (m = e.match(p[i])) { v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); exclusion.push("(" + v.substring(1, v.length - 1) + ")"); e = e.replace(m[0], ''); break; } } } return "[not(" + exclusion.join(" and ") + ")]"; }, 'nth-child': function(m) { return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); }, 'nth-last-child': function(m) { return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); }, 'nth-of-type': function(m) { return Selector.xpath.pseudos.nth("position() ", m); }, 'nth-last-of-type': function(m) { return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); }, 'first-of-type': function(m) { m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); }, 'last-of-type': function(m) { m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); }, 'only-of-type': function(m) { var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); }, nth: function(fragment, m) { var mm, formula = m[6], predicate; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; if (mm = formula.match(/^(\d+)$/)) // digit only return '[' + fragment + "= " + mm[1] + ']'; if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b if (mm[1] == "-") mm[1] = -1; var a = mm[1] ? Number(mm[1]) : 1; var b = mm[2] ? Number(mm[2]) : 0; predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + "((#{fragment} - #{b}) div #{a} >= 0)]"; return new Template(predicate).evaluate({ fragment: fragment, a: a, b: b }); } } } }, criteria: { tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', className: 'n = h.className(n, r, "#{1}", c); c = false;', id: 'n = h.id(n, r, "#{1}", c); c = false;', attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', attr: function(m) { m[3] = (m[5] || m[6]); return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); }, pseudo: function(m) { if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); }, descendant: 'c = "descendant";', child: 'c = "child";', adjacent: 'c = "adjacent";', laterSibling: 'c = "laterSibling";' }, patterns: { // combinators must be listed first // (and descendant needs to be last combinator) laterSibling: /^\s*~\s*/, child: /^\s*>\s*/, adjacent: /^\s*\+\s*/, descendant: /^\s/, // selectors follow tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, id: /^#([\w\-\*]+)(\b|$)/, className: /^\.([\w\-\*]+)(\b|$)/, pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/, attrPresence: /^\[([\w]+)\]/, attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }, // for Selector.match and Element#match assertions: { tagName: function(element, matches) { return matches[1].toUpperCase() == element.tagName.toUpperCase(); }, className: function(element, matches) { return Element.hasClassName(element, matches[1]); }, id: function(element, matches) { return element.id === matches[1]; }, attrPresence: function(element, matches) { return Element.hasAttribute(element, matches[1]); }, attr: function(element, matches) { var nodeValue = Element.readAttribute(element, matches[1]); return Selector.operators[matches[2]](nodeValue, matches[3]); } }, handlers: { // UTILITY FUNCTIONS // joins two collections concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) a.push(node); return a; }, // marks an array of nodes for counting mark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node._counted = true; return nodes; }, unmark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node._counted = undefined; return nodes; }, // mark each child node with its position (for nth calls) // "ofType" flag indicates whether we're indexing for nth-of-type // rather than nth-child index: function(parentNode, reverse, ofType) { parentNode._counted = true; if (reverse) { for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { var node = nodes[i]; if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; } } else { for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; } }, // filters out duplicates and extends all nodes unique: function(nodes) { if (nodes.length == 0) return nodes; var results = [], n; for (var i = 0, l = nodes.length; i < l; i++) if (!(n = nodes[i])._counted) { n._counted = true; results.push(Element.extend(n)); } return Selector.handlers.unmark(results); }, // COMBINATOR FUNCTIONS descendant: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName('*')); return results; }, child: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) { for (var j = 0, children = [], child; child = node.childNodes[j]; j++) if (child.nodeType == 1 && child.tagName != '!') results.push(child); } return results; }, adjacent: function(nodes) { for (var i = 0, results = [], node; node = nodes[i]; i++) { var next = this.nextElementSibling(node); if (next) results.push(next); } return results; }, laterSibling: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, Element.nextSiblings(node)); return results; }, nextElementSibling: function(node) { while (node = node.nextSibling) if (node.nodeType == 1) return node; return null; }, previousElementSibling: function(node) { while (node = node.previousSibling) if (node.nodeType == 1) return node; return null; }, // TOKEN FUNCTIONS tagName: function(nodes, root, tagName, combinator) { tagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { // fastlane for ordinary descendant combinators if (combinator == "descendant") { for (var i = 0, node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName(tagName)); return results; } else nodes = this[combinator](nodes); if (tagName == "*") return nodes; } for (var i = 0, node; node = nodes[i]; i++) if (node.tagName.toUpperCase() == tagName) results.push(node); return results; } else return root.getElementsByTagName(tagName); }, id: function(nodes, root, id, combinator) { var targetNode = $(id), h = Selector.handlers; if (!targetNode) return []; if (!nodes && root == document) return [targetNode]; if (nodes) { if (combinator) { if (combinator == 'child') { for (var i = 0, node; node = nodes[i]; i++) if (targetNode.parentNode == node) return [targetNode]; } else if (combinator == 'descendant') { for (var i = 0, node; node = nodes[i]; i++) if (Element.descendantOf(targetNode, node)) return [targetNode]; } else if (combinator == 'adjacent') { for (var i = 0, node; node = nodes[i]; i++) if (Selector.handlers.previousElementSibling(targetNode) == node) return [targetNode]; } else nodes = h[combinator](nodes); } for (var i = 0, node; node = nodes[i]; i++) if (node == targetNode) return [targetNode]; return []; } return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; }, className: function(nodes, root, className, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); return Selector.handlers.byClassName(nodes, root, className); }, byClassName: function(nodes, root, className) { if (!nodes) nodes = Selector.handlers.descendant([root]); var needle = ' ' + className + ' '; for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { nodeClassName = node.className; if (nodeClassName.length == 0) continue; if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) results.push(node); } return results; }, attrPresence: function(nodes, root, attr) { if (!nodes) nodes = root.getElementsByTagName("*"); var results = []; for (var i = 0, node; node = nodes[i]; i++) if (Element.hasAttribute(node, attr)) results.push(node); return results; }, attr: function(nodes, root, attr, value, operator) { if (!nodes) nodes = root.getElementsByTagName("*"); var handler = Selector.operators[operator], results = []; for (var i = 0, node; node = nodes[i]; i++) { var nodeValue = Element.readAttribute(node, attr); if (nodeValue === null) continue; if (handler(nodeValue, value)) results.push(node); } return results; }, pseudo: function(nodes, name, value, root, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); if (!nodes) nodes = root.getElementsByTagName("*"); return Selector.pseudos[name](nodes, value, root); } }, pseudos: { 'first-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.previousElementSibling(node)) continue; results.push(node); } return results; }, 'last-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.nextElementSibling(node)) continue; results.push(node); } return results; }, 'only-child': function(nodes, value, root) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) results.push(node); return results; }, 'nth-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root); }, 'nth-last-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true); }, 'nth-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, false, true); }, 'nth-last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true, true); }, 'first-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, false, true); }, 'last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, true, true); }, 'only-of-type': function(nodes, formula, root) { var p = Selector.pseudos; return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); }, // handles the an+b logic getIndices: function(a, b, total) { if (a == 0) return b > 0 ? [b] : []; return $R(1, total).inject([], function(memo, i) { if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); return memo; }); }, // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type nth: function(nodes, formula, root, reverse, ofType) { if (nodes.length == 0) return []; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; var h = Selector.handlers, results = [], indexed = [], m; h.mark(nodes); for (var i = 0, node; node = nodes[i]; i++) { if (!node.parentNode._counted) { h.index(node.parentNode, reverse, ofType); indexed.push(node.parentNode); } } if (formula.match(/^\d+$/)) { // just a number formula = Number(formula); for (var i = 0, node; node = nodes[i]; i++) if (node.nodeIndex == formula) results.push(node); } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b if (m[1] == "-") m[1] = -1; var a = m[1] ? Number(m[1]) : 1; var b = m[2] ? Number(m[2]) : 0; var indices = Selector.pseudos.getIndices(a, b, nodes.length); for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { for (var j = 0; j < l; j++) if (node.nodeIndex == indices[j]) results.push(node); } } h.unmark(nodes); h.unmark(indexed); return results; }, 'empty': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { // IE treats comments as element nodes if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; results.push(node); } return results; }, 'not': function(nodes, selector, root) { var h = Selector.handlers, selectorType, m; var exclusions = new Selector(selector).findElements(root); h.mark(exclusions); for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node._counted) results.push(node); h.unmark(exclusions); return results; }, 'enabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node.disabled) results.push(node); return results; }, 'disabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.disabled) results.push(node); return results; }, 'checked': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.checked) results.push(node); return results; } }, operators: { '=': function(nv, v) { return nv == v; }, '!=': function(nv, v) { return nv != v; }, '^=': function(nv, v) { return nv.startsWith(v); }, '$=': function(nv, v) { return nv.endsWith(v); }, '*=': function(nv, v) { return nv.include(v); }, '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } }, matchElements: function(elements, expression) { var matches = new Selector(expression).findElements(), h = Selector.handlers; h.mark(matches); for (var i = 0, results = [], element; element = elements[i]; i++) if (element._counted) results.push(element); h.unmark(matches); return results; }, findElement: function(elements, expression, index) { if (Object.isNumber(expression)) { index = expression; expression = false; } return Selector.matchElements(elements, expression || '*')[index || 0]; }, findChildElements: function(element, expressions) { var exprs = expressions.join(','), expressions = []; exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { expressions.push(m[1].strip()); }); var results = [], h = Selector.handlers; for (var i = 0, l = expressions.length, selector; i < l; i++) { selector = new Selector(expressions[i].strip()); h.concat(results, selector.findElements(element)); } return (l > 1) ? h.unique(results) : results; } }); function $$() { return Selector.findChildElements(document, $A(arguments)); } var Form = { reset: function(form) { $(form).reset(); return form; }, serializeElements: function(elements, options) { if (typeof options != 'object') options = { hash: !!options }; else if (options.hash === undefined) options.hash = true; var key, value, submitted = false, submit = options.submit; var data = elements.inject({ }, function(result, element) { if (!element.disabled && element.name) { key = element.name; value = $(element).getValue(); if (value != null && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) { if (key in result) { // a key is already present; construct an array of values if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value); } else result[key] = value; } } return result; }); return options.hash ? data : Object.toQueryString(data); } }; Form.Methods = { serialize: function(form, options) { return Form.serializeElements(Form.getElements(form), options); }, getElements: function(form) { return $A($(form).getElementsByTagName('*')).inject([], function(elements, child) { if (Form.Element.Serializers[child.tagName.toLowerCase()]) elements.push(Element.extend(child)); return elements; } ); }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); if (!typeName && !name) return $A(inputs).map(Element.extend); for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { var input = inputs[i]; if ((typeName && input.type != typeName) || (name && input.name != name)) continue; matchingInputs.push(Element.extend(input)); } return matchingInputs; }, disable: function(form) { form = $(form); Form.getElements(form).invoke('disable'); return form; }, enable: function(form) { form = $(form); Form.getElements(form).invoke('enable'); return form; }, findFirstElement: function(form) { var elements = $(form).getElements().findAll(function(element) { return 'hidden' != element.type && !element.disabled; }); var firstByIndex = elements.findAll(function(element) { return element.hasAttribute('tabIndex') && element.tabIndex >= 0; }).sortBy(function(element) { return element.tabIndex }).first(); return firstByIndex ? firstByIndex : elements.find(function(element) { return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); }); }, focusFirstElement: function(form) { form = $(form); form.findFirstElement().activate(); return form; }, request: function(form, options) { form = $(form), options = Object.clone(options || { }); var params = options.parameters, action = form.readAttribute('action') || ''; if (action.blank()) action = window.location.href; options.parameters = form.serialize(true); if (params) { if (Object.isString(params)) params = params.toQueryParams(); Object.extend(options.parameters, params); } if (form.hasAttribute('method') && !options.method) options.method = form.method; return new Ajax.Request(action, options); } }; /*--------------------------------------------------------------------------*/ Form.Element = { focus: function(element) { $(element).focus(); return element; }, select: function(element) { $(element).select(); return element; } }; Form.Element.Methods = { serialize: function(element) { element = $(element); if (!element.disabled && element.name) { var value = element.getValue(); if (value != undefined) { var pair = { }; pair[element.name] = value; return Object.toQueryString(pair); } } return ''; }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); return Form.Element.Serializers[method](element); }, setValue: function(element, value) { element = $(element); var method = element.tagName.toLowerCase(); Form.Element.Serializers[method](element, value); return element; }, clear: function(element) { $(element).value = ''; return element; }, present: function(element) { return $(element).value != ''; }, activate: function(element) { element = $(element); try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || !['button', 'reset', 'submit'].include(element.type))) element.select(); } catch (e) { } return element; }, disable: function(element) { element = $(element); try{element.blur();}catch(e){} element.disabled = true; return element; }, enable: function(element) { element = $(element); element.disabled = false; return element; } }; /*--------------------------------------------------------------------------*/ var Field = Form.Element; var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ Form.Element.Serializers = { input: function(element, value) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element, value); default: return Form.Element.Serializers.textarea(element, value); } }, inputSelector: function(element, value) { if (value === undefined) return element.checked ? element.value : null; else element.checked = !!value; }, textarea: function(element, value) { if (value === undefined) return element.value; else element.value = value; }, select: function(element, index) { if (index === undefined) return this[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); else { var opt, value, single = !Object.isArray(index); for (var i = 0, length = element.length; i < length; i++) { opt = element.options[i]; value = this.optionValue(opt); if (single) { if (value == index) { opt.selected = true; return; } } else opt.selected = index.include(value); } } }, selectOne: function(element) { var index = element.selectedIndex; return index >= 0 ? this.optionValue(element.options[index]) : null; }, selectMany: function(element) { var values, length = element.length; if (!length) return null; for (var i = 0, values = []; i < length; i++) { var opt = element.options[i]; if (opt.selected) values.push(this.optionValue(opt)); } return values; }, optionValue: function(opt) { // extend element because hasAttribute may not be native return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; } }; /*--------------------------------------------------------------------------*/ Abstract.TimedObserver = Class.create(PeriodicalExecuter, { initialize: function($super, element, frequency, callback) { $super(callback, frequency); this.element = $(element); this.lastValue = this.getValue(); }, execute: function() { var value = this.getValue(); if (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)) { this.callback(this.element, value); this.lastValue = value; } } }); Form.Element.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); Form.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.serialize(this.element); } }); /*--------------------------------------------------------------------------*/ Abstract.EventObserver = Class.create({ initialize: function(element, callback) { this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else this.registerCallback(this.element); }, onElementEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } }, registerFormCallbacks: function() { Form.getElements(this.element).each(this.registerCallback, this); }, registerCallback: function(element) { if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; default: Event.observe(element, 'change', this.onElementEvent.bind(this)); break; } } } }); Form.Element.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); Form.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.serialize(this.element); } }); if (!window.Event) var Event = { }; Object.extend(Event, { KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, KEY_HOME: 36, KEY_END: 35, KEY_PAGEUP: 33, KEY_PAGEDOWN: 34, KEY_INSERT: 45, cache: { }, relatedTarget: function(event) { var element; switch(event.type) { case 'mouseover': element = event.fromElement; break; case 'mouseout': element = event.toElement; break; default: return null; } return Element.extend(element); } }); Event.Methods = (function() { var isButton; if (Prototype.Browser.IE) { var buttonMap = { 0: 1, 1: 4, 2: 2 }; isButton = function(event, code) { return event.button == buttonMap[code]; }; } else if (Prototype.Browser.WebKit) { isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false; } }; } else { isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code); }; } return { isLeftClick: function(event) { return isButton(event, 0) }, isMiddleClick: function(event) { return isButton(event, 1) }, isRightClick: function(event) { return isButton(event, 2) }, element: function(event) { var node = Event.extend(event).target; return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); }, findElement: function(event, expression) { var element = Event.element(event); return element.match(expression) ? element : element.up(expression); }, pointer: function(event) { return { x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)), y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)) }; }, pointerX: function(event) { return Event.pointer(event).x }, pointerY: function(event) { return Event.pointer(event).y }, stop: function(event) { Event.extend(event); event.preventDefault(); event.stopPropagation(); event.stopped = true; } }; })(); Event.extend = (function() { var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { m[name] = Event.Methods[name].methodize(); return m; }); if (Prototype.Browser.IE) { Object.extend(methods, { stopPropagation: function() { this.cancelBubble = true }, preventDefault: function() { this.returnValue = false }, inspect: function() { return "[object Event]" } }); return function(event) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); Object.extend(event, { target: event.srcElement, relatedTarget: Event.relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); return Object.extend(event, methods); }; } else { Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; Object.extend(Event.prototype, methods); return Prototype.K; } })(); Object.extend(Event, (function() { var cache = Event.cache; function getEventID(element) { if (element._eventID) return element._eventID; arguments.callee.id = arguments.callee.id || 1; return element._eventID = ++arguments.callee.id; } function getDOMEventName(eventName) { if (eventName && eventName.include(':')) return "dataavailable"; return eventName; } function getCacheForID(id) { return cache[id] = cache[id] || { }; } function getWrappersForEventName(id, eventName) { var c = getCacheForID(id); return c[eventName] = c[eventName] || []; } function createWrapper(element, eventName, handler) { var id = getEventID(element); var c = getWrappersForEventName(id, eventName); if (c.pluck("handler").include(handler)) return false; var wrapper = function(event) { if (!Event || !Event.extend || (event.eventName && event.eventName != eventName)) return false; Event.extend(event); if(handler!=null){ handler.call(element, event); } }; wrapper.handler = handler; c.push(wrapper); return wrapper; } function findWrapper(id, eventName, handler) { var c = getWrappersForEventName(id, eventName); return c.find(function(wrapper) { return wrapper.handler == handler }); } function destroyWrapper(id, eventName, handler) { var c = getCacheForID(id); if (!c[eventName]) return false; c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); } function destroyCache() { for (var id in cache) for (var eventName in cache[id]) cache[id][eventName] = null; } if (window.attachEvent) { window.attachEvent("onunload", destroyCache); } return { observe: function(element, eventName, handler) { element = $(element); var name = getDOMEventName(eventName); var wrapper = createWrapper(element, eventName, handler); if (!wrapper) return element; if (element.addEventListener) { element.addEventListener(name, wrapper, false); } else { element.attachEvent("on" + name, wrapper); } return element; }, stopObserving: function(element, eventName, handler) { element = $(element); var id = getEventID(element), name = getDOMEventName(eventName); if (!handler && eventName) { getWrappersForEventName(id, eventName).each(function(wrapper) { element.stopObserving(eventName, wrapper.handler); }); return element; } else if (!eventName) { Object.keys(getCacheForID(id)).each(function(eventName) { element.stopObserving(eventName); }); return element; } var wrapper = findWrapper(id, eventName, handler); if (!wrapper) return element; if (element.removeEventListener) { element.removeEventListener(name, wrapper, false); } else { element.detachEvent("on" + name, wrapper); } destroyWrapper(id, eventName, handler); return element; }, fire: function(element, eventName, memo) { element = $(element); if (element == document && document.createEvent && !element.dispatchEvent) element = document.documentElement; var event; if (document.createEvent) { event = document.createEvent("HTMLEvents"); event.initEvent("dataavailable", true, true); } else { event = document.createEventObject(); event.eventType = "ondataavailable"; } event.eventName = eventName; event.memo = memo || { }; if (document.createEvent) { element.dispatchEvent(event); } else { try{ element.fireEvent(event.eventType, event); }catch(e){} } return event; } }; })()); Object.extend(Event, Event.Methods); Element.addMethods({ fire: Event.fire, observe: Event.observe, stopObserving: Event.stopObserving }); Object.extend(document, { fire: Element.Methods.fire.methodize(), observe: Element.Methods.observe.methodize(), stopObserving: Element.Methods.stopObserving.methodize() }); (function() { /* Support for the DOMContentLoaded event is based on work by Dan Webb, Matthias Miller, Dean Edwards and John Resig. */ var timer, fired = false; function fireContentLoadedEvent() { if (fired) return; if (timer) window.clearInterval(timer); document.fire("dom:loaded"); fired = true; } if (document.addEventListener) { if (Prototype.Browser.WebKit) { timer = window.setInterval(function() { if (/loaded|complete/.test(document.readyState)) fireContentLoadedEvent(); }, 0); Event.observe(window, "load", fireContentLoadedEvent); } else { document.addEventListener("DOMContentLoaded", fireContentLoadedEvent, false); } } else { document.write(" AjaXplorer/AjaXplorer/client/js/lib/codepress/license.txt0000766000000000000000000006040511122202530024667 0ustar adminadministrators GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/0000777000000000000000000000000011300346057024457 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/codepress/languages/sql.js0000766000000000000000000000435211122202530025606 0ustar adminadministrators/* * CodePress regular expressions for SQL syntax highlighting * By Merlin Moncure */ // SQL Language.syntax = [ { input : /\'(.*?)(\')/g, output : '\'$1$2' }, // strings single quote { input : /\b(add|after|aggregate|alias|all|and|as|authorization|between|by|cascade|cache|cache|called|case|check|column|comment|constraint|createdb|createuser|cycle|database|default|deferrable|deferred|diagnostics|distinct|domain|each|else|elseif|elsif|encrypted|except|exception|for|foreign|from|from|full|function|get|group|having|if|immediate|immutable|in|increment|initially|increment|index|inherits|inner|input|intersect|into|invoker|is|join|key|language|left|limit|local|loop|match|maxvalue|minvalue|natural|nextval|no|nocreatedb|nocreateuser|not|null|of|offset|oids|on|only|operator|or|order|outer|owner|partial|password|perform|plpgsql|primary|record|references|replace|restrict|return|returns|right|row|rule|schema|security|sequence|session|sql|stable|statistics|table|temp|temporary|then|time|to|transaction|trigger|type|unencrypted|union|unique|user|using|valid|value|values|view|volatile|when|where|with|without|zone)\b/gi, output : '$1' }, // reserved words { input : /\b(bigint|bigserial|bit|boolean|box|bytea|char|character|cidr|circle|date|decimal|double|float4|float8|inet|int2|int4|int8|integer|interval|line|lseg|macaddr|money|numeric|oid|path|point|polygon|precision|real|refcursor|serial|serial4|serial8|smallint|text|timestamp|varbit|varchar)\b/gi, output : '$1' }, // types { input : /\b(abort|alter|analyze|begin|checkpoint|close|cluster|comment|commit|copy|create|deallocate|declare|delete|drop|end|execute|explain|fetch|grant|insert|listen|load|lock|move|notify|prepare|reindex|reset|restart|revoke|rollback|select|set|show|start|truncate|unlisten|update)\b/gi, output : '$1' }, // commands { input : /([^:]|^)\-\-(.*?)(--$2$3' } // comments // ] Language.snippets = [ { input : 'select', output : 'select $0 from where ' } ] Language.complete = [ { input : '\'', output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/css.css0000766000000000000000000000042511122202530025750 0ustar adminadministrators/* * CodePress color styles for CSS syntax highlighting */ b, b a, b u {color:#000080;} /* tags, ids, classes */ i, i b, i s, i a, i u {color:gray;} /* comments */ s, s b {color:#a0a0dd;} /* parameters */ a {color:#0000ff;} /* keys */ u {color:red;} /* values */ AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/generic.css0000766000000000000000000000055511122202530026600 0ustar adminadministrators/* * CodePress color styles for generic syntax highlighting */ b {color:#7F0055;font-weight:bold;} /* reserved words */ u {color:darkblue;font-weight:bold;} /* special words */ i, i b, i s, i u, i em {color:green;font-weight:normal;} /* comments */ s, s b, s em {color:#2A00FF;font-weight:normal;} /* strings */ em {font-weight:bold;} /* special chars */AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/perl.css0000766000000000000000000000067711122202530026133 0ustar adminadministrators/* * CodePress color styles for Perl syntax highlighting * By J. Nick Koston */ b {color:#7F0055;font-weight:bold;} /* reserved words */ i, i b, i s, i em, i a, i u {color:gray;font-weight:normal;} /* comments */ s, s b, s a, s em, s u {color:#2A00FF;font-weight:normal;} /* strings */ a {color:#006700;font-weight:bold;} /* variables */ em {color:darkblue;font-weight:bold;} /* functions */ u {font-weight:bold;} /* special chars */AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/css.js0000766000000000000000000000124011122202530025570 0ustar adminadministrators/* * CodePress regular expressions for CSS syntax highlighting */ // CSS Language.syntax = [ { input : /(.*?){(.*?)}/g,output : '$1{$2}' }, // tags, ids, classes, values { input : /([\w-]*?):([^\/])/g,output : '$1:$2' }, // keys { input : /\((.*?)\)/g,output : '($1)' }, // parameters { input : /\/\*(.*?)\*\//g,output : '/*$1*/'} // comments ] Language.snippets = [] Language.complete = [ { input : '\'',output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/html.js0000766000000000000000000000674611122202530025764 0ustar adminadministrators/* * CodePress regular expressions for HTML syntax highlighting */ // HTML Language.syntax = [ { input : /(<[^!]*?>)/g, output : '$1' }, // all tags { input : /(<a .*?>|<\/a>)/g, output : '$1' }, // links { input : /(<img .*?>)/g, output : '$1' }, // images { input : /(<\/?(button|textarea|form|input|select|option|label).*?>)/g, output : '$1' }, // forms { input : /(<style.*?>)(.*?)(<\/style>)/g, output : '$1$2$3' }, // style tags { input : /(<script.*?>)(.*?)(<\/script>)/g, output : '$1$2$3' }, // script tags { input : /=(".*?")/g, output : '=$1' }, // atributes double quote { input : /=('.*?')/g, output : '=$1' }, // atributes single quote { input : /(<!--.*?-->.)/g, output : '$1' }, // comments { input : /\b(alert|window|document|break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g, output : '$1' } // script reserved words ] Language.snippets = [ { input : 'aref', output : '' }, { input : 'h1', output : '

    $0

    ' }, { input : 'h2', output : '

    $0

    ' }, { input : 'h3', output : '

    $0

    ' }, { input : 'h4', output : '

    $0

    ' }, { input : 'h5', output : '
    $0
    ' }, { input : 'h6', output : '
    $0
    ' }, { input : 'html', output : '\n\t$0\n' }, { input : 'head', output : '\n\t\n\t$0\n\t\n' }, { input : 'img', output : '' }, { input : 'input', output : '' }, { input : 'label', output : '' }, { input : 'legend', output : '\n\t$0\n' }, { input : 'link', output : '' }, { input : 'base', output : '' }, { input : 'body', output : '\n\t$0\n' }, { input : 'css', output : '' }, { input : 'div', output : '
    \n\t$0\n
    ' }, { input : 'divid', output : '
    \n\t\n
    ' }, { input : 'dl', output : '
    \n\t
    \n\t\t$0\n\t
    \n\t
    \n
    ' }, { input : 'fieldset', output : '
    \n\t$0\n
    ' }, { input : 'form', output : '
    \n\t\n
    ' }, { input : 'meta', output : '' }, { input : 'p', output : '

    $0

    ' }, { input : 'script', output : '' }, { input : 'scriptsrc', output : '' }, { input : 'span', output : '$0' }, { input : 'table', output : '\n\t\n\t\n
    ' }, { input : 'style', output : '' } ] Language.complete = [ { input : '\'',output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/php.css0000766000000000000000000000121511122202530025745 0ustar adminadministrators/* * CodePress color styles for PHP syntax highlighting */ b {color:#000080;} /* tags */ big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {color:gray;font-weight:normal;} /* comments */ s, s b, strong s u, strong s cite {color:#5656fa;font-weight:normal;} /* attributes and strings */ strong a, strong a u {color:#006700;font-weight:bold;} /* variables */ em {color:#800080;font-style:normal;} /* style */ ins {color:#800000;} /* script */ strong u {color:#7F0055;font-weight:bold;} /* reserved words */ cite, s cite {color:red;font-weight:bold;} /* */ AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/html.css0000766000000000000000000000067511122202530026133 0ustar adminadministrators/* * CodePress color styles for HTML syntax highlighting */ b {color:#000080;} /* tags */ ins, ins b, ins s, ins em {color:gray;} /* comments */ s, s b {color:#7777e4;} /* attribute values */ a {color:green;} /* links */ u {color:#E67300;} /* forms */ big {color:#db0000;} /* images */ em, em b {color:#800080;} /* style */ strong {color:#800000;} /* script */ tt i {color:darkblue;font-weight:bold;} /* script reserved words */ AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/ruby.css0000766000000000000000000000065111122202530026142 0ustar adminadministrators/* * CodePress color styles for Ruby syntax highlighting */ b {color:#7F0055;font-weight:bold;} /* reserved words */ i, i b, i s, i em, i a, i u {color:gray;font-weight:normal;} /* comments */ s, s b, s a, s em, s u {color:#2A00FF;font-weight:normal;} /* strings */ a {color:#006700;font-weight:bold;} /* variables */ em {color:darkblue;font-weight:bold;} /* functions */ u {font-weight:bold;} /* special chars */AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/php.js0000766000000000000000000000633511122202530025601 0ustar adminadministrators/* * CodePress regular expressions for PHP syntax highlighting */ // PHP Language.syntax = [ { input : /(<[^!\?]*?>)/g, output : '$1' }, // all tags { input : /(<style.*?>)(.*?)(<\/style>)/g, output : '$1$2$3' }, // style tags { input : /(<script.*?>)(.*?)(<\/script>)/g, output : '$1$2$3' }, // script tags { input : /\"(.*?)(\"|
    |<\/P>)/g, output : '"$1$2' }, // strings double quote { input : /\'(.*?)(\'|
    |<\/P>)/g, output : '\'$1$2'}, // strings single quote { input : /(<\?)/g, output : '$1' }, // ' }, // .*?> { input : /(<\?php|<\?=|<\?|\?>)/g, output : '$1' }, // php tags { input : /(\$[\w\.]*)/g, output : '$1' }, // vars { input : /\b(false|true|and|or|xor|__FILE__|exception|__LINE__|array|as|break|case|class|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|for|foreach|function|global|if|include|include_once|isset|list|new|print|require|require_once|return|static|switch|unset|use|while|__FUNCTION__|__CLASS__|__METHOD__|final|php_user_filter|interface|implements|extends|public|private|protected|abstract|clone|try|catch|throw|this)\b/g, output : '$1' }, // reserved words { input : /([^:])\/\/(.*?)(//$2$3' }, // php comments // { input : /\/\*(.*?)\*\//g, output : '/*$1*/' }, // php comments /* */ { input : /(<!--.*?-->.)/g, output : '$1' } // html comments ] Language.snippets = [ { input : 'if', output : 'if($0){\n\t\n}' }, { input : 'ifelse', output : 'if($0){\n\t\n}\nelse{\n\t\n}' }, { input : 'else', output : '}\nelse {\n\t' }, { input : 'elseif', output : '}\nelseif($0) {\n\t' }, { input : 'do', output : 'do{\n\t$0\n}\nwhile();' }, { input : 'inc', output : 'include_once("$0");' }, { input : 'fun', output : 'function $0(){\n\t\n}' }, { input : 'func', output : 'function $0(){\n\t\n}' }, { input : 'while', output : 'while($0){\n\t\n}' }, { input : 'for', output : 'for($0,,){\n\t\n}' }, { input : 'fore', output : 'foreach($0 as ){\n\t\n}' }, { input : 'foreach', output : 'foreach($0 as ){\n\t\n}' }, { input : 'echo', output : 'echo \'$0\';' }, { input : 'switch', output : 'switch($0) {\n\tcase "": break;\n\tdefault: ;\n}' }, { input : 'case', output : 'case "$0" : break;' }, { input : 'ret0', output : 'return false;' }, { input : 'retf', output : 'return false;' }, { input : 'ret1', output : 'return true;' }, { input : 'rett', output : 'return true;' }, { input : 'ret', output : 'return $0;' }, { input : 'def', output : 'define(\'$0\',\'\');' }, { input : '' } ] Language.complete = [ { input : '\'', output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [ { input : '[space]', output : ' ' }, { input : '[enter]', output : '
    ' } , { input : '[j]', output : 'testing' }, { input : '[7]', output : '&' } ]AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/javascript.js0000766000000000000000000000307511122202530027156 0ustar adminadministrators/* * CodePress regular expressions for JavaScript syntax highlighting */ // JavaScript Language.syntax = [ { input : /\"(.*?)(\"|
    |<\/P>)/g, output : '"$1$2' }, // strings double quote { input : /\'(.*?)(\'|
    |<\/P>)/g, output : '\'$1$2' }, // strings single quote { input : /\b(break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g, output : '$1' }, // reserved words { input : /\b(alert|isNaN|parent|Array|parseFloat|parseInt|blur|clearTimeout|prompt|prototype|close|confirm|length|Date|location|Math|document|element|name|self|elements|setTimeout|navigator|status|String|escape|Number|submit|eval|Object|event|onblur|focus|onerror|onfocus|onclick|top|onload|toString|onunload|unescape|open|valueOf|window|onmouseover)\b/g, output : '$1' }, // special words { input : /([^:]|^)\/\/(.*?)(//$2$3' }, // comments // { input : /\/\*(.*?)\*\//g, output : '/*$1*/' } // comments /* */ ] Language.snippets = [ { input : 'dw', output : 'document.write(\'$0\');' }, { input : 'getid', output : 'document.getElementById(\'$0\')' }, { input : 'fun', output : 'function $0(){\n\t\n}' }, { input : 'func', output : 'function $0(){\n\t\n}' } ] Language.complete = [ { input : '\'',output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/javascript.css0000766000000000000000000000047711122202530027335 0ustar adminadministrators/* * CodePress color styles for JavaScript syntax highlighting */ b {color:#7F0055;font-weight:bold;} /* reserved words */ u {color:darkblue;font-weight:bold;} /* special words */ i, i b, i s, i u {color:green;font-weight:normal;} /* comments */ s, s b, s u {color:#2A00FF;font-weight:normal;} /* strings */ AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/java.js0000766000000000000000000000214611122202530025727 0ustar adminadministrators/* * CodePress regular expressions for Java syntax highlighting */ // Java Language.syntax = [ { input : /\"(.*?)(\"|
    |<\/P>)/g, output : '"$1$2'}, // strings double quote { input : /\'(.*?)(\'|
    |<\/P>)/g, output : '\'$1$2'}, // strings single quote { input : /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g, output : '$1'}, // reserved words { input : /([^:]|^)\/\/(.*?)(//$2$3'}, // comments // { input : /\/\*(.*?)\*\//g, output : '/*$1*/' }// comments /* */ ] Language.snippets = [] Language.complete = [ { input : '\'',output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/ruby.js0000766000000000000000000000213611122202530025766 0ustar adminadministrators/* * CodePress regular expressions for Perl syntax highlighting */ // Ruby Language.syntax = [ { input : /\"(.*?)(\"|
    |<\/P>)/g, output : '"$1$2' }, // strings double quote { input : /\'(.*?)(\'|
    |<\/P>)/g, output : '\'$1$2' }, // strings single quote { input : /([\$\@\%]+)([\w\.]*)/g, output : '$1$2' }, // vars { input : /(def\s+)([\w\.]*)/g, output : '$1$2' }, // functions { input : /\b(alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|false|for|if|in|module|next|nil|not|or|redo|rescue|retry|return|self|super|then|true|undef|unless|until|when|while|yield)\b/g, output : '$1' }, // reserved words { input : /([\(\){}])/g, output : '$1' }, // special chars { input : /#(.*?)(
    |<\/P>)/g, output : '#$1$2' } // comments ]; Language.snippets = [] Language.complete = [ { input : '\'',output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/java.css0000766000000000000000000000040711122202530026101 0ustar adminadministrators/* * CodePress color styles for Java syntax highlighting */ b {color:#7F0055;font-weight:bold;font-style:normal;} /* reserved words */ i, i b, i s {color:#3F7F5F;font-weight:bold;} /* comments */ s, s b {color:#2A00FF;font-weight:normal;} /* strings */ AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/generic.js0000766000000000000000000000216111122202530026417 0ustar adminadministrators/* * CodePress regular expressions for generic syntax highlighting */ // generic languages Language.syntax = [ { input : /\"(.*?)(\"|
    |<\/P>)/g, output : '"$1$2' }, // strings double quote { input : /\'(.*?)(\'|
    |<\/P>)/g, output : '\'$1$2' }, // strings single quote { input : /\b(abstract|continue|for|new|switch|default|goto|boolean|do|if|private|this|break|double|protected|throw|byte|else|import|public|throws|case|return|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|const|float|while|function|label)\b/g, output : '$1' }, // reserved words { input : /([\(\){}])/g, output : '$1' }, // special chars; { input : /([^:]|^)\/\/(.*?)(//$2$3' }, // comments // { input : /\/\*(.*?)\*\//g, output : '/*$1*/' } // comments /* */ ] Language.snippets = [] Language.complete = [ { input : '\'', output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/perl.js0000766000000000000000000000461411122202530025752 0ustar adminadministrators/* * CodePress regular expressions for Perl syntax highlighting * By J. Nick Koston */ // Perl Language.syntax = [ { input : /\"(.*?)(\"|
    |<\/P>)/g, output : '"$1$2' }, // strings double quote { input : /\'(.*?)(\'|
    |<\/P>)/g, output : '\'$1$2' }, // strings single quote { input : /([\$\@\%][\w\.]*)/g, output : '$1' }, // vars { input : /(sub\s+)([\w\.]*)/g, output : '$1$2' }, // functions { input : /\b(abs|accept|alarm|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|connect|continue|cos|crypt|dbmclose|dbmopen|defined|delete|die|do|dump|each|else|elsif|endgrent|endhostent|endnetent|endprotoent|endpwent|eof|eval|exec|exists|exit|fcntl|fileno|find|flock|for|foreach|fork|format|formlinegetc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyaddr|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|goto|grep|hex|hostname|if|import|index|int|ioctl|join|keys|kill|last|lc|lcfirst|length|link|listen|LoadExternals|local|localtime|log|lstat|map|mkdir|msgctl|msgget|msgrcv|msgsnd|my|next|no|oct|open|opendir|ordpack|package|pipe|pop|pos|print|printf|push|pwd|qq|quotemeta|qw|rand|read|readdir|readlink|recv|redo|ref|rename|require|reset|return|reverse|rewinddir|rindex|rmdir|scalar|seek|seekdir|select|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|stty|study|sub|substr|symlink|syscall|sysopen|sysread|system|syswritetell|telldir|tie|tied|time|times|tr|truncate|uc|ucfirst|umask|undef|unless|unlink|until|unpack|unshift|untie|use|utime|values|vec|waitpid|wantarray|warn|while|write)\b/g, output : '$1' }, // reserved words { input : /([\(\){}])/g, output : '$1' }, // special chars { input : /#(.*?)(
    |<\/P>)/g, output : '#$1$2' } // comments ] Language.snippets = [] Language.complete = [ { input : '\'',output : '\'$0\'' }, { input : '"', output : '"$0"' }, { input : '(', output : '\($0\)' }, { input : '[', output : '\[$0\]' }, { input : '{', output : '{\n\t$0\n}' } ] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/text.css0000766000000000000000000000014111122202530026137 0ustar adminadministrators/* * CodePress color styles for Text syntax highlighting */ /* do nothing as expected */ AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/text.js0000766000000000000000000000027011122202530025766 0ustar adminadministrators/* * CodePress regular expressions for Text syntax highlighting */ // plain text Language.syntax = [] Language.snippets = [] Language.complete = [] Language.shortcuts = [] AjaXplorer/AjaXplorer/client/js/lib/codepress/languages/sql.css0000766000000000000000000000070311122202530025756 0ustar adminadministrators/* * CodePress color styles for SQL syntax highlighting * By Merlin Moncure */ b {color:#0000FF;font-style:normal;font-weight:bold;} /* reserved words */ u {color:#FF0000;font-style:normal;} /* types */ a {color:#CD6600;font-style:normal;font-weight:bold;} /* commands */ i, i b, i u, i a, i s {color:#A9A9A9;font-weight:normal;font-style:italic;} /* comments */ s, s b, s u, s a, s i {color:#2A00FF;font-weight:normal;} /* strings */ AjaXplorer/AjaXplorer/client/js/lib/codepress/images/0000777000000000000000000000000011300346060023750 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/codepress/images/line-numbers.png0000766000000000000000000004025411122202530027057 0ustar adminadministratorsPNG  IHDR]Ψ(gAMA7tEXtSoftwareAdobe ImageReadyqe< PLTE@)IDATxr8D1] !7){+$&xG&|dOGI( ?f}Dx eeNW߼}IYv/F=J5t=2xu?wRͦR=B_#倾u0S^!|ffG붾<72͋Wo)þmaƥ`7vWFvYaa?/KVQT ?-=5_Vn=2Soöu`ö2Z /犗Xzk۔c|5Wy򊊊xo eXXM0W(C/X_F_S/~^;)mb j߀4^8K꧲OXjJK!/yF;^D_+WWoX 7b K4K}_NJxyﰢ. [ .ǏJI7]o)\_IeҥH; eXXM/ i0q֗%Χ~VxQD_j⛬77_q^/ xg` ?|WvfDlo$N@_;b~czhr=1/52\>-'xY/͈7=_/3˛mj }=ū|Jߨ=xJ_o>OZΧe5>,>z>oC/Nzkn(O#)RO>>*k -fWܳмE?!F_y=/z:U|_WEI54}ͭKyY/?/=B__拢rk(#Z7\^B7=:Wb~cz4:_rb~}5oΫ*}ͪKy5o\sob~o,ͣ c~/yY/u c%Zߠ>|otC/7YowG&S:Csӯw#xom=:#Z))s'>\%/+mR'#G*^5oޛyiaa?/Ku(C/Nzkn|7uj͋27OGvX{/UkP;P ěGIw72͋i~ceM,>:qYoo d/4/7L˜OY_yY/Õ)kb S/s> xc^V:O]6mmWoX)cV}%yK"`^z(yYi 72KGe})^a<5>,>eBJ+@_/ xpfs ?|WoVkV#11j7ܙXCeGxj䅾Շ%^ԇ,W/jr(47z _f~x;)sop¼?eztJie5>IO)ܟl)_e&XGHT)g*^:d6CDKj՗{T'Ĉk EYz(yYijU/K^kZ}XE}}JhyG1z0_}[E5>_z? =s}ƫx11x=lp/z1񈾚7\U^~fՇ%^ԇ7971ke7ubֆX|Ƃ,:q }-oP7: 7׻e{ؿ;~@=k\:wR[n[;l~vթ\"[^b c0/Kzzhr=z(yox+kċ%:fV7z ׹G_/헏xcl<9)葹zd&7NOu~Q`ͽ_f}u˵`b4/n^1e+7Bc/+7)m״ċ%} G+7߀P?=FTyDͫq~c(K;W/n}QI c0/Kzz2٥ WoD!e~SeXW7/Χo\B_ԇ7,|ʚ@_96}|q`Ο?o0?olqEb97v_Dļ31%b=|`=4J^VڿoKS*ykn}XE}})zcho| Qcgjy̫߈ 7ZS7b~czhr=10_tC״ċ% E/g~c_/3`KvJj7?ea^ܟ2x=l?opʴSJ2\r$^ OY_/oďOGv\ȷLJy޹߹ o!kը/E?!F_y=/z&CJWch}I^"Cq }MKyY/Ozch`(/k}n2/p|Qyo՗k}9/i~u#jpWy }MKy5o5/Ʋ_f~c)^ye97oLoX%b=\߸޿7V7.y wYFG17 eex%*wOH=a_^WOoY+"x=}oۿ%OqZߠ>|a77_;d5yD۟B.Oy}uD_џϮso\˳SAuR#yYrVoXqooCL/q?lpVxQD_~뱚{zcdUkڏJyQ*::jb 2kL' +{Q'i^e~KCD!Fy~hċWHz1z_ܥ,񣘏Z߰d)˗8 /Kzqq>e-Zߠ>|aSz].^_7t4 $/2~X7"^OyF_F"^b^ԙ}>\%/+_|7bKS*ykn}XE}})zcho| QW8q[y>+;3"V6o7BV\%/+_o,>e7#oC/7~MF//oσ-"w)%Syq)O)kr})x5ߟR7?eS~M?1z{r||xÕ&\Z}5˵|O@^勲P'|RDVxQD_kI}XB__拢rk(&Ro5W\}֗32^o ^7\^_o< yW״ċW|Qo,1ke7╝'[F_+Yߘ/ /Kzqoo\B_Kԇ7zchoGINa &l ]r+^Nʤzviuxu+S^n}>\%/+_{#5v롣/cO$囼״ċ%:~'usRwobtCc^/2}^?Oy7ݨGOt{@i{^v&r층cW\+7Ex1i^ݼ"\(7R"k}}-QxQD_%nh1 ~975ԏrGtJ~x5oĆ~YGYwoeA^p%j|Z/A}.Ò Χ ~)]vUqFyqFryE~ 1՜B4=B_ro}5#,P%ΧHC=RJ[xQD_|J%:~߱ٹZy>+7l€Wo}=ߧo z(yYib~})^ayiaa?/K޸77_o~^^ޞ[E~SJW) a)%SݟRS&j?opʲ~%~Tj:%6?2i*ngW'_T>B_r/._bD5czhr=5G\_q\B_/~^KoS=/˭zK?6:_d^%sZ_x11x=lp/z1񈾚7\U^B_/~^EM2lƯ闙XWvB_+Yc^|Ƃ,:q }-oP7: W<^/om'm~+k7WIyOH9:uIg}>\%/+_{c:RĐ7nkċ%:3F1 䀾/Jx9T|%oM^lp(:䗧³KN^i:,lg㰫^x@_r7&`^yvMڊQCھ< ^kZ}XE}}ExK`+7߀P?ʵT\lhxuoPW/GQCDwo߈\zmxo eXX[7>Ta 0Dto7~}MKyoߨC/o˱i,񣘏Z߰d)˗8 /Kzqq>e-Zߠ>|aSz].^㼍eD壋%y8PyE +Wo8SWRyQYo|~^xY/CeKO?/KO9aa?/K%ΧT7: W^/)G)^ y>+7v,^F3o|1CeGx;m״ċ% EKzchƯ闙y%^N?op\}ܟ0/O6ݟR7?e)~}M?eSJ,qʯ7zxYGq;<>OGk̻7EG]_~Bz,_0^M|RDVxQD_"Cߟ|Q5_n|d^ &*ߘ/r7^Ƌa|G4:VxQjЕe~c_/3<ZY ^ D_J%/A}.#77_zaQ%Fkj܃G뾿a,~#[kT_F_Kԇ%^ԇ,F1'V7x*> o&Uz|¿kogXS/l{|Bծ/JqqiyN_߄c0/ӼXyE&mJ601t6 :VxQD_~zQQ77_ ^(צ7F\ĉ.Wɺ=z/'v}8 ^D_-]5ZtJ}5o|E;ZxQjpQ77_~;}-/k0/K(7,9^|ɋ) D_+WS7.x w ip>eKo˜O~grަr4*Cx*yWbJ[\7{%*+S^p^z(yYiS>B_8Rs@_s/~^KOotCG_/xhf 1^ٙ(_twno}=ߧo z(yYib~})^aNem״ċ% EoL_/3`KvJj7?ea^ܟ2x=l?opʴSJ2\r$^ OY_/oď O)UʷLJJ̒ m!|jח{T'Ĉk EYP'J^VڿEGK&Ʈk䅾Շ%^ԇ,їߨwCE~5_^CF;$ ׿9r/g~e6oܿxD_M*/D_/~^so,1ke7u}-o\lm7xo,}o\_+R,z}_ߨ=Mڜކ>2/<2+urNj?h?H|~\(ex/,롄bqm$/+'. áeWI7B}˽1cH("W7D_&CJ8"RJ[xQD_|J%:~l]y>KmR?Zo}o,ˋP#R|6^kZ}XE}}&B1ke7zyy{lO)ܟ2W_,̋SM OvJ_F_COī)_ܟke^QqIHtDx8Џ& U_V}gyOS5cz(e1_4~(JzC aa?/Kzch`(/k}jUGxoߘ/r7^Ƌa|G4:L5>,><Ы|Q752K@7.67eX7/K^k)]FQoo d/omml&N ~'ڿ=o}|BUЗk}'>i9qڭ5潙VxQD_uQQ77_B5_NJx]9T|̻5ڮ%/&ʢGo\¶G/D_DQO1i^ݼ"se+7BO1"kK^kZ}XE}}Ejzch%~!z_,Jx <2^A%]4 w9Aޙ Zoy_;^Q(/Kzz2٥ Wo瀾և%^ԇ,ї-otCG_/xhf 1^ٙyL}=ߧo z(yYib~})^ayiaa?/Kf1ke7zyy{lO)ܟ2W_,̋SM OvJ_F_COī)_ܟke^QŸ]bSʷ d~\Zh}˵|O@^勲롄b:5ƏWEIO9ċ%JǤ>|,_4~E_s|Qx MNp/z ߘ/`7^ŋa|G4:VxQj߸.xSƯ闙XWv?o}odyzVcV|Ƃ,:q }-oP7: @_7u7.67oX%b=\߸oo䅾7o$CM]2FCg/ڏ(9Nn(Y4c.Sv}gQklo ea7/q?߰ %,*^~sM^kZ}XE}}8h77_/'YUGyHۄ.WHJh j7*y_a"eXX[7>Tajj7e5>,>:#o 7|Qx e|z%OY_yY/Õ)kb K78f7eΧtz:!v_瀾և%^ԇ,ї-otC8}_VSu׏qxü3#QQ5?W} `^o ^M/7їnVxQD_a9x<_o~^^ޞ[E~SJW) a)%SݟRS&j?opʲ~%~Tcܮy '^*3I2ԉ0o7i+^Vڤ"#Dy^+7/"tD_s/~^+7~JQQ77_ roktJyTLhxuo_>FY=}wѫve: c0/Kzz2٥ WoBD!Fy~h.ċWF-^oo /ďb>j=)˗8 /Kzqq>e-Zߠ>|aɐSz].^_7t4*Cx*yWbJ[\7}%ѫ2OyRD̋:yY/CeKOGѣKS*ykn}XE}})zcho| Qaoޛy>+7~Rt=o$>@_F)y11x=4J^VڿxD_W/VxQD_aɡ77_o~^^ޞ[E~SJW) a)%SݟRS&j?opʲ~%~!ĺCJ6?;M&Zg"Z=?WM_YhS#e=Ce1_^|S<VxQD_"ZQoo E_s|Qx ןZ7\^[oїk}9/i~u#jpWyU&UxQjЕe~c_/3 k1bkX_ cA^pzX߸䅾7odM]2Fwlޡ{y]tRG^[44#Z))s'x^z(yYiwPog:&EdRԇ%^ԇ,櫱U)*J7F_~yW«שu^g[ȎGf\R~D>}UNC~BLb=u7veMoAqUƶ0)"׿KyY߿*EEC_峿~'x-0\=:%kݙ[~XFbt^5}W\O9%k/Kzz2٥ W4CWaVxQjp77_n@_ xeQ eΧ,/_|ʂ,J ^k1]i)_@_9{1/+'. M+7u2OyR\=}>\%/+_Ffp+6Sh=Tև%^ԇ,WoX)r<~u9lv߯8ȏ^&1j7zŐP#R|5B_/~^+59=_/3`KvJj7?ea^ܟ2x=l?opʴSJ2\r$^ OY_/oď:&CJ6?SA ;Oq7Rh^%}gyO~Bz,_0^M|yOykn}XE}}JhyG1z0_}[E5>_z? =s}ƫx11x=lp/z1񈾚7\U^~fՇ%^ԇ7971ke7ubֆX|Ƃ,:q }-oP7: 7׻e£{#;eKo˜O~yJ牾Kp>JS`" -Wo8Sї{cu7D_&CJ8"#x)߰R[xQD_|J%:~u楘D /x7 ?{Yk7bWV\%/+_o,>e|Q3=_/3`KvJj7?ea^ܟ2x=l?opʴSJ2\r$^ OY_/oď:$14Y'G~ux o!G˵|O@^勲P՘/z~/q>)q }MKyY/Ozch`(/k}n2/p|Qyo՗k}9/i~u#jpWy }MKy5o5/Ʋ_f~c)^ye9nzߘ/ /Kzqoo\B_Kԇ7zcho2K%0z0/]ϒ 1z_kWoĽCVk/Kzqo?!-^k]i ~oD'>2H|¿|2|30Bs==2ȹI}Wo+W\o ^yv 7_<|B}%nB_/~^Kz=p[WI_硈\=4/n^_#^Vڿ"%Q_Wo|m_Q| }MKyYٿ77_/QR R>ߗkϫq~]o E7o(0k c0/Kzz2.7E!Fy~&VxQj5o 7߀4^QGoX2K^OY%b=\߸ڿ8q }-oP߰d~)k_j~}_|J]xth7vsx ^B x5o#(/W#\=}>\%/+_|7NΧHJykn}XE}})zcho| Qaf]js 1^ʂm~911j7zŐP#R|5B_/~^+.7z _f~x;)sop¼?eztJie5>IO)ܟl)_euH>ٯZ:6ɷ Ko(# =?WM_~Bz,_0^M|#x).O> ^kZ}XE}} }JPTCE~5_^Cuy)7\狚̫d~c\˙x/7ME//7W+^kZ}XE}ϫy~u|Q752K_k%#s81_ cA^pzX߸䅾7od+@_/76^ ^9(Om?0^`(ˉIENDB`AjaXplorer/AjaXplorer/client/js/lib/codepress/engines/0000777000000000000000000000000011300346061024134 5ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/codepress/engines/older.js0000766000000000000000000000000011122202530025560 0ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/codepress/engines/msie.js0000766000000000000000000002077611122202530025436 0ustar adminadministrators/* * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/ * * Copyright (C) 2007 Fernando M.A.d.S. * * Contributors : * * Michael Hurni * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation. * * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php */ CodePress = { scrolling : false, autocomplete : true, // set initial vars and start sh initialize : function() { if(typeof(editor)=='undefined' && !arguments[0]) return; chars = '|32|46|62|'; // charcodes that trigger syntax highlighting cc = '\u2009'; // control char editor = document.getElementsByTagName('pre')[0]; editor.contentEditable = 'true'; document.getElementsByTagName('body')[0].onfocus = function() {editor.focus();} document.attachEvent('onkeydown', this.metaHandler); document.attachEvent('onkeypress', this.keyHandler); window.attachEvent('onscroll', function() { if(!CodePress.scrolling) setTimeout(function(){CodePress.syntaxHighlight('scroll')},1)}); completeChars = this.getCompleteChars(); // CodePress.syntaxHighlight('init'); setTimeout(function() { window.scroll(0,0) },50); // scroll IE to top }, // treat key bindings keyHandler : function(evt) { charCode = evt.keyCode; if(completeChars.indexOf('|'+String.fromCharCode(charCode)+'|')!=-1 && CodePress.autocomplete) { // auto complete CodePress.complete(String.fromCharCode(charCode)) } else if(chars.indexOf('|'+charCode+'|')!=-1||charCode==13) { // syntax highlighting CodePress.syntaxHighlight('generic'); } }, metaHandler : function(evt) { keyCode = evt.keyCode; if(keyCode==9 || evt.tabKey) { CodePress.snippets(); } else if((keyCode==122||keyCode==121||keyCode==90) && evt.ctrlKey) { // undo and redo (keyCode==121||evt.shiftKey) ? CodePress.actions.redo() : CodePress.actions.undo(); evt.returnValue = false; } else if(keyCode==34||keyCode==33) { // handle page up/down for IE self.scrollBy(0, (keyCode==34) ? 200 : -200); evt.returnValue = false; } else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML; } else if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && keyCode!=90) { // shortcuts = ctrl||appleKey+shift+key!=z(undo) CodePress.shortcuts(keyCode); evt.returnValue = false; } else if(keyCode==86 && evt.ctrlKey) { // paste // TODO: pasted text should be parsed and highlighted } }, // put cursor back to its original position after every parsing findString : function() { range = self.document.body.createTextRange(); if(range.findText(cc)){ range.select(); range.text = ''; } }, // split big files, highlighting parts of it split : function(code,flag) { if(flag=='scroll') { this.scrolling = true; return code; } else { this.scrolling = false; mid = code.indexOf(cc); if(mid-2000<0) {ini=0;end=4000;} else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;} else {ini=mid-2000;end=mid+2000;} code = code.substring(ini,end); return code.substring(code.indexOf('

    '),code.lastIndexOf('

    ')+4); } }, // syntax highlighting parser syntaxHighlight : function(flag) { if(flag!='init') document.selection.createRange().text = cc; o = editor.innerHTML; o = o.replace(/

    /g,'\n'); o = o.replace(/<\/P>/g,'\r'); o = o.replace(/<.*?>/g,''); o = o.replace(/ /g,''); o = '

    '+o+'

    '; o = o.replace(/\n\r/g,'

    '); o = o.replace(/\n/g,'

    '); o = o.replace(/\r/g,'<\/P>'); o = o.replace(/

    (

    )+/,'

    '); o = o.replace(/<\/P>(<\/P>)+/,'

    '); o = o.replace(/

    <\/P>/g,'


    '); x = z = this.split(o,flag); if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]); for(i=0;i/g,'>'); if(content.indexOf('$0')<0) content += cc; else content = content.replace(/\$0/,cc); content = content.replace(/\n/g,'

    '); var pattern = new RegExp(trigger+cc); this.syntaxHighlight('snippets',pattern,content); } } }, readOnly : function() { editor.contentEditable = (arguments[0]) ? 'false' : 'true'; }, complete : function(trigger) { var complete = Language.complete; for (var i=0; i/g,'\n'); code = code.replace(/<\/p>/gi,'\r'); code = code.replace(/

    /i,''); // IE first line fix code = code.replace(/

    /gi,'\n'); code = code.replace(/ /gi,''); code = code.replace(/\u2009/g,''); code = code.replace(/<.*?>/g,''); code = code.replace(/</g,'<'); code = code.replace(/>/g,'>'); code = code.replace(/&/gi,'&'); return code; }, // put code inside editor setCode : function() { var code = arguments[0]; code = code.replace(/\u2009/gi,''); code = code.replace(/&/gi,'&'); code = code.replace(//g,'>'); editor.innerHTML = '

    '+code+'
    '; }, // undo and redo methods actions : { pos : -1, // actual history position history : [], // history vector undo : function() { if(editor.innerHTML.indexOf(cc)==-1){ document.selection.createRange().text = cc; this.history[this.pos] = editor.innerHTML; } this.pos--; if(typeof(this.history[this.pos])=='undefined') this.pos++; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, redo : function() { this.pos++; if(typeof(this.history[this.pos])=='undefined') this.pos--; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, next : function() { // get next vector position and clean old ones if(this.pos>20) this.history[this.pos-21] = undefined; return ++this.pos; } } } Language={}; window.attachEvent('onload', function() { CodePress.initialize('new');});AjaXplorer/AjaXplorer/client/js/lib/codepress/engines/gecko.js0000766000000000000000000001754411122202530025570 0ustar adminadministrators/* * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/ * * Copyright (C) 2007 Fernando M.A.d.S. * * Contributors : * * Michael Hurni * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation. * * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php */ CodePress = { scrolling : false, autocomplete : true, // set initial vars and start sh initialize : function() { if(typeof(editor)=='undefined' && !arguments[0]) return; chars = '|32|46|62|'; // charcodes that trigger syntax highlighting cc = '\u2009'; // control char editor = document.getElementsByTagName('body')[0]; document.designMode = 'on'; document.addEventListener('keypress', this.keyHandler, true); window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false); completeChars = this.getCompleteChars(); // CodePress.syntaxHighlight('init'); }, // treat key bindings keyHandler : function(evt) { keyCode = evt.keyCode; charCode = evt.charCode; if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90) { // shortcuts = ctrl||appleKey+shift+key!=z(undo) CodePress.shortcuts(charCode?charCode:keyCode); } else if(completeChars.indexOf('|'+String.fromCharCode(charCode)+'|')!=-1 && CodePress.autocomplete) { // auto complete CodePress.complete(String.fromCharCode(charCode)); } else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting CodePress.syntaxHighlight('generic'); } else if(keyCode==9 || evt.tabKey) { // snippets activation (tab) CodePress.snippets(evt); } else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML; } else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo (charCode==121||evt.shiftKey) ? CodePress.actions.redo() : CodePress.actions.undo(); evt.preventDefault(); } else if(keyCode==86 && evt.ctrlKey) { // paste // TODO: pasted text should be parsed and highlighted } }, // put cursor back to its original position after every parsing findString : function() { if(self.find(cc)) window.getSelection().getRangeAt(0).deleteContents(); }, // split big files, highlighting parts of it split : function(code,flag) { if(flag=='scroll') { this.scrolling = true; return code; } else { this.scrolling = false; mid = code.indexOf(cc); if(mid-2000<0) {ini=0;end=4000;} else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;} else {ini=mid-2000;end=mid+2000;} code = code.substring(ini,end); return code; } }, // syntax highlighting parser syntaxHighlight : function(flag) { //if(document.designMode=='off') document.designMode='on' if(flag!='init') window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc)); o = editor.innerHTML; o = o.replace(/
    /g,'\n'); o = o.replace(/<.*?>/g,''); x = z = this.split(o,flag); x = x.replace(/\n/g,'
    '); if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]); for(i=0;i/g,'>'); if(content.indexOf('$0')<0) content += cc; else content = content.replace(/\$0/,cc); content = content.replace(/\n/g,'
    '); var pattern = new RegExp(trigger+cc,'g'); evt.preventDefault(); // prevent the tab key from being added this.syntaxHighlight('snippets',pattern,content); } } }, readOnly : function() { document.designMode = (arguments[0]) ? 'off' : 'on'; }, complete : function(trigger) { window.getSelection().getRangeAt(0).deleteContents(); var complete = Language.complete; for (var i=0; i/g,'\n'); code = code.replace(/\u2009/g,''); code = code.replace(/<.*?>/g,''); code = code.replace(/</g,'<'); code = code.replace(/>/g,'>'); code = code.replace(/&/gi,'&'); return code; }, // put code inside editor setCode : function() { var code = arguments[0]; code = code.replace(/\u2009/gi,''); code = code.replace(/&/gi,'&'); code = code.replace(//g,'>'); editor.innerHTML = code; }, // undo and redo methods actions : { pos : -1, // actual history position history : [], // history vector undo : function() { if(editor.innerHTML.indexOf(cc)==-1){ window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc)); this.history[this.pos] = editor.innerHTML; } this.pos--; if(typeof(this.history[this.pos])=='undefined') this.pos++; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, redo : function() { this.pos++; if(typeof(this.history[this.pos])=='undefined') this.pos--; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, next : function() { // get next vector position and clean old ones if(this.pos>20) this.history[this.pos-21] = undefined; return ++this.pos; } } } Language={}; window.addEventListener('load', function() { CodePress.initialize('new'); }, true);AjaXplorer/AjaXplorer/client/js/lib/codepress/engines/opera.js0000766000000000000000000002052611122202530025600 0ustar adminadministrators/* * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/ * * Copyright (C) 2007 Fernando M.A.d.S. * * Contributors : * * Michael Hurni * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation. * * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php */ CodePress = { scrolling : false, autocomplete : true, // set initial vars and start sh initialize : function() { if(typeof(editor)=='undefined' && !arguments[0]) return; chars = '|32|46|62|'; // charcodes that trigger syntax highlighting cc = '\u2009'; // control char editor = document.getElementsByTagName('body')[0]; document.designMode = 'on'; document.addEventListener('keyup', this.keyHandler, true); window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false); completeChars = this.getCompleteChars(); // CodePress.syntaxHighlight('init'); }, // treat key bindings keyHandler : function(evt) { keyCode = evt.keyCode; charCode = evt.charCode; if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90) { // shortcuts = ctrl||appleKey+shift+key!=z(undo) CodePress.shortcuts(charCode?charCode:keyCode); } else if(completeChars.indexOf('|'+String.fromCharCode(charCode)+'|')!=-1 && CodePress.autocomplete) { // auto complete CodePress.complete(String.fromCharCode(charCode)); } else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting CodePress.syntaxHighlight('generic'); } else if(keyCode==9 || evt.tabKey) { // snippets activation (tab) CodePress.snippets(evt); } else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML; } else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo (charCode==121||evt.shiftKey) ? CodePress.actions.redo() : CodePress.actions.undo(); evt.preventDefault(); } else if(keyCode==86 && evt.ctrlKey) { // paste // TODO: pasted text should be parsed and highlighted } }, // put cursor back to its original position after every parsing findString : function() { var sel = window.getSelection(); var range = window.document.createRange(); var span = window.document.getElementsByTagName('span')[0]; range.selectNode(span); sel.removeAllRanges(); sel.addRange(range); span.parentNode.removeChild(span); //if(self.find(cc)) //window.getSelection().getRangeAt(0).deleteContents(); }, // split big files, highlighting parts of it split : function(code,flag) { if(flag=='scroll') { this.scrolling = true; return code; } else { this.scrolling = false; mid = code.indexOf(''); if(mid-2000<0) {ini=0;end=4000;} else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;} else {ini=mid-2000;end=mid+2000;} code = code.substring(ini,end); return code; } }, // syntax highlighting parser syntaxHighlight : function(flag) { //if(document.designMode=='off') document.designMode='on' if(flag!='init') { var span = document.createElement('span'); window.getSelection().getRangeAt(0).insertNode(span); } o = editor.innerHTML; // o = o.replace(/
    /g,'\r\n'); // o = o.replace(/<(b|i|s|u|a|em|tt|ins|big|cite|strong)?>/g,''); //alert(o) o = o.replace(/<(?!span|\/span|br).*?>/gi,''); // alert(o) // x = o; x = z = this.split(o,flag); //alert(z) // x = x.replace(/\r\n/g,'
    '); x = x.replace(/\t/g, ' '); if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]); for(i=0;i/g,'>'); if(content.indexOf('$0')<0) content += cc; else content = content.replace(/\$0/,cc); content = content.replace(/\n/g,'
    '); var pattern = new RegExp(trigger+cc,'g'); evt.preventDefault(); // prevent the tab key from being added this.syntaxHighlight('snippets',pattern,content); } } }, readOnly : function() { document.designMode = (arguments[0]) ? 'off' : 'on'; }, complete : function(trigger) { window.getSelection().getRangeAt(0).deleteContents(); var complete = Language.complete; for (var i=0; i/g,'\n'); code = code.replace(/\u2009/g,''); code = code.replace(/<.*?>/g,''); code = code.replace(/</g,'<'); code = code.replace(/>/g,'>'); code = code.replace(/&/gi,'&'); return code; }, // put code inside editor setCode : function() { var code = arguments[0]; code = code.replace(/\u2009/gi,''); code = code.replace(/&/gi,'&'); code = code.replace(//g,'>'); editor.innerHTML = code; }, // undo and redo methods actions : { pos : -1, // actual history position history : [], // history vector undo : function() { if(editor.innerHTML.indexOf(cc)==-1){ window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc)); this.history[this.pos] = editor.innerHTML; } this.pos--; if(typeof(this.history[this.pos])=='undefined') this.pos++; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, redo : function() { this.pos++; if(typeof(this.history[this.pos])=='undefined') this.pos--; editor.innerHTML = this.history[this.pos]; CodePress.findString(); }, next : function() { // get next vector position and clean old ones if(this.pos>20) this.history[this.pos-21] = undefined; return ++this.pos; } } } Language={}; window.addEventListener('load', function() { CodePress.initialize('new'); }, true); AjaXplorer/AjaXplorer/client/js/lib/codepress/engines/khtml.js0000766000000000000000000000000011122202530025572 0ustar adminadministratorsAjaXplorer/AjaXplorer/client/js/lib/codepress/index.html0000766000000000000000000003372511122202530024506 0ustar adminadministrators CodePress - Real Time Syntax Highlighting Editor written in JavaScript

    CodePress is web-based source code editor with syntax highlighting written in JavaScript that colors text in real time while it's being typed in the browser.

    Go to http://codepress.org/ for updates.

    Demo

    choose example in:


    Installation

    1. Download and uncompress CodePress under a directory inside your webserver.
      Example: http://yourserver/codepress/
      Since CodePress is pure JavaScript and HTML, you can also test it without a webserver.

    2. Insert CodePress script somewhere in your page inside the <head> or above the </body> tag.

      <script src="/codepress/codepress.js" type="text/javascript"></script>

    3. Add the <textarea> tag to the place on your page you want CodePress to appear. CodePress will inherit the width and height of your textarea. When the page loads, it will automatically replace your textarea with a CodePress window.

      <textarea id="myCpWindow" class="codepress javascript linenumbers-off">
         // your code here
      </textarea>

      • The javascript portion of the class="" means that the language being edited is JavaScript.
      • The codepress portion of the class="" is mandatory and indicates a textarea to be replaced for a CodePress window.
      • Other class options are linenumbers-off, autocomplete-off and readonly-on.
      • Careful not to use the same id for two different CodePress windows (<textarea id="xx"...>)

    You also can...

    1. Open/edit code from a different textarea.
      Example: textarea_id.edit('other_textarea_id','language')
    2. Get code from CodePress window.
      Example: textarea_id.getCode()
    3. Turn on/off CodePress editor and return to the regular textarea.
      Example: textarea_id.toggleEditor()
    4. Turn on/off line numbers.
      Example: textarea_id.toggleLineNumbers()
    5. Turn on/off read only.
      Example: textarea_id.toggleReadOnly()
    6. Turn on/off auto-complete.
      Example: textarea_id.toggleAutoComplete()

    License

    CodePress is distributed under the LGPL. If your software is compatible with this licence or it is under Creative Commons, you can use it as you want. Just keep the credits somewhere around.

    AjaXplorer/AjaXplorer/client/js/lib/codepress/codepress.js0000766000000000000000000001142411122202530025026 0ustar adminadministrators/* * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/ * * Copyright (C) 2006 Fernando M.A.d.S. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation. * * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php */ CodePress = function(obj, contentObserver) { var self = document.createElement('iframe'); self.textarea = obj; self.textarea.disabled = true; self.textarea.style.overflow = 'hidden'; self.style.height = self.textarea.clientHeight +'px'; self.style.width = self.textarea.clientWidth +'px'; self.textarea.style.overflow = 'auto'; self.style.border = '1px solid gray'; self.frameBorder = 0; // remove IE internal iframe border self.style.visibility = 'hidden'; self.style.position = 'absolute'; self.options = self.textarea.className; self.contentObserver = contentObserver; self.initialize = function() { self.editor = self.contentWindow.CodePress; self.editor.body = self.contentWindow.document.getElementsByTagName('body')[0]; self.editor.setCode(self.textarea.value); self.setOptions(); self.editor.syntaxHighlight('init'); self.textarea.style.display = 'none'; self.style.position = 'static'; self.style.visibility = 'visible'; self.style.display = 'inline'; if(self.contentObserver){ self.pe = new PeriodicalExecuter(function(pe){ if(self.interrupt){pe.stop();return;} var crtCode = self.getCode(); if(!self.prevCode){ self.prevCode = crtCode; return;} if(self.prevCode != crtCode) self.contentObserver(); self.prevCode = crtCode; return; }, 0.2); } } ; self.close = function(){ self.interrupt = true; } ; self.edit = function(id,language) { if(id) self.textarea.value = document.getElementById(id).value; if(!self.textarea.disabled) return; self.language = language ? language : self.options.replace(/ ?codepress ?| ?readonly-on ?| ?autocomplete-off ?| ?linenumbers-off ?/g,''); if(!CodePress.languages[self.language]) self.language = 'generic'; self.src = CodePress.path+'codepress.html?language='+self.language+'&ts='+(new Date).getTime(); if(self.attachEvent) self.attachEvent('onload',self.initialize); else self.addEventListener('load',self.initialize,false); } ; self.setOptions = function() { if(self.options.match('autocomplete-off')) self.toggleAutoComplete(); if(self.options.match('readonly-on')) self.toggleReadOnly(); if(self.options.match('linenumbers-off')) self.toggleLineNumbers(); }; self.getCode = function() { return self.textarea.disabled ? self.editor.getCode() : self.textarea.value; }; self.setCode = function(code) { self.textarea.disabled ? self.editor.setCode(code) : self.textarea.value = code; }; self.toggleAutoComplete = function() { self.editor.autocomplete = (self.editor.autocomplete) ? false : true; }; self.toggleReadOnly = function() { self.textarea.readOnly = (self.textarea.readOnly) ? false : true; if(self.style.display != 'none') // prevent exception on FF + iframe with display:none self.editor.readOnly(self.textarea.readOnly ? true : false); }; self.toggleLineNumbers = function() { var cn = self.editor.body.className; self.editor.body.className = (cn==''||cn=='show-line-numbers') ? 'hide-line-numbers' : 'show-line-numbers'; }; self.toggleEditor = function() { if(self.textarea.disabled) { self.textarea.value = self.getCode(); self.textarea.disabled = false; self.style.display = 'none'; self.textarea.style.display = 'inline'; } else { self.textarea.disabled = true; self.setCode(self.textarea.value); self.editor.syntaxHighlight('init'); self.style.display = 'inline'; self.textarea.style.display = 'none'; } }; self.edit(); return self; }; CodePress.languages = { css : 'CSS', generic : 'Generic', html : 'HTML', java : 'Java', javascript : 'JavaScript', perl : 'Perl', ruby : 'Ruby', php : 'PHP', text : 'Text', sql : 'SQL' }; CodePress.run = function() { s = document.getElementsByTagName('script'); for(var i=0,n=s.length;i35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('J 1B={pd:\'1.6.0\',2j:{IE:!!(1L.7w&&!1L.8l),9y:!!1L.8l,6D:7y.bs.3R(\'T2/\')>-1,gp:7y.bs.3R(\'gp\')>-1&&7y.bs.3R(\'Gl\')==-1,Qj:!!7y.bs.1Z(/Te.*S7.*zq/)},bS:{om:!!1f.7S,m4:!!1L.mG,rb:1f.2w(\'1x\').hW&&1f.2w(\'1x\').hW!==1f.2w(\'2D\').hW},uw:\'<5j[^>]*>([\\\\S\\\\s]*?)<\\/5j>\',Mp:/^\\/\\*-dd-([\\s\\S]*)\\*\\/\\s*$/,79:C(){},K:C(x){N x}};if(1B.2j.Qj)1B.bS.rb=1a;if(1B.2j.6D)1B.bS.om=1a;J 2q={2r:C(){J 3Y=1d,eg=$A(1D);if(1i.5w(eg[0]))3Y=eg.ay();C 4K(){q.2y.7D(q,1D)}1i.1u(4K,2q.2m);4K.vH=3Y;4K.Qg=[];if(3Y){J vr=C(){};vr.1w=3Y.1w;4K.1w=1c vr;3Y.Qg.1N(4K)}1j(J i=0;i0){if(1Z=5Q.1Z(5R)){2W+=5Q.6i(0,1Z.1y);2W+=4c.k7(ak(1Z));5Q=5Q.6i(1Z.1y+1Z[0].Y)}14{2W+=5Q,5Q=\'\'}}N 2W},zC:C(5R,ak,5a){ak=q.8G.vk(ak);5a=5a===1R?1:5a;N q.8G(5R,C(1Z){if(--5a<0)N 1Z[0];N ak(1Z)})},Ku:C(5R,2b){q.8G(5R,2b);N 4c(q)},Fz:C(Y,jC){Y=Y||30;jC=jC===1R?\'...\':jC;N q.Y>Y?q.6i(0,Y-jC.Y)+jC:4c(q)},5h:C(){N q.2V(/^\\s+/,\'\').2V(/\\s+$/,\'\')},jv:C(){N q.2V(/<\\/?[^>]+>/gi,\'\')},ap:C(){N q.2V(1c 8x(1B.uw,\'2e\'),\'\')},NS:C(){J LA=1c 8x(1B.uw,\'2e\');J NC=1c 8x(1B.uw,\'im\');N(q.1Z(LA)||[]).4G(C(Nh){N(Nh.1Z(NC)||[\'\',\'\'])[1]})},9K:C(){N q.NS().4G(C(5j){N 8y(5j)})},ox:C(){J f7=1D.eh;f7.26.c9=q;N f7.1x.2C},Ow:C(){J 1x=1c 1e(\'1x\');1x.2C=q.jv();N 1x.1o[0]?(1x.1o.Y>1?$A(1x.1o).9N(\'\',C(aJ,1h){N aJ+1h.4i}):1x.1o[0].4i):\'\'},lB:C(7n){J 1Z=q.5h().1Z(/([^?#]*)(#.*)?$/);if(!1Z)N{};N 1Z[1].3Z(7n||\'&\').9N({},C(4e,2k){if((2k=2k.3Z(\'=\'))[0]){J 1Y=qz(2k.ay());J V=2k.Y>1?2k.57(\'=\'):2k[0];if(V!=1R)V=qz(V);if(1Y in 4e){if(!1i.cD(4e[1Y]))4e[1Y]=[4e[1Y]];4e[1Y].1N(V)}14 4e[1Y]=V}N 4e})},9f:C(){N q.3Z(\'\')},wo:C(){N q.6i(0,q.Y-1)+4c.tv(q.NH(q.Y-1)+1)},s2:C(5a){N 5a<1?\'\':1c 3r(5a+1).57(q)},o8:C(){J 83=q.3Z(\'-\'),p0=83.Y;if(p0==1)N 83[0];J vp=q.7u(0)==\'-\'?83[0].7u(0).4F()+83[0].5Y(1):83[0];1j(J i=1;i-1},wf:C(5R){N q.3R(5R)===0},IW:C(5R){J d=q.Y-5R.Y;N d>=0&&q.ah(5R)===d},gg:C(){N q==\'\'},i9:C(){N/^\\s*$/.3n(q)},Qy:C(1F,5R){N 1c 7T(q,5R).7S(1F)}});if(1B.2j.6D||1B.2j.IE)1i.1u(4c.1w,{ox:C(){N q.2V(/&/g,\'&Ob;\').2V(//g,\'>\')},Ow:C(){N q.2V(/&Ob;/g,\'&\').2V(/</g,\'<\').2V(/>/g,\'>\')}});4c.1w.8G.vk=C(ak){if(1i.5w(ak))N ak;J bK=1c 7T(ak);N C(1Z){N bK.7S(1Z)}};4c.1w.QW=4c.1w.lB;1i.1u(4c.1w.ox,{1x:1f.2w(\'1x\'),26:1f.aN(\'\')});hm(4c.1w.ox)1x.1X(26);J 7T=2q.2r({2y:C(bK,5R){q.bK=bK.55();q.5R=5R||7T.Pq},7S:C(1F){if(1i.5w(1F.wl))1F=1F.wl();N q.bK.8G(q.5R,C(1Z){if(1F==1d)N\'\';J cJ=1Z[1]||\'\';if(cJ==\'\\\\\')N 1Z[2];J lc=1F,eX=1Z[3];J 5R=/^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/,1Z=5R.zu(eX);if(1Z==1d)N cJ;2S(1Z!=1d){J OX=1Z[1].wf(\'[\')?1Z[2].8G(\'\\\\\\\\]\',\']\'):1Z[1];lc=lc[OX];if(1d==lc||\'\'==1Z[3])2A;eX=eX.5Y(\'[\'==1Z[3]?1Z[1].Y:1Z[0].Y);1Z=5R.zu(eX)}N cJ+4c.k7(lc)}.1k(q))}});7T.Pq=/(^|.|\\r|\\n)(#\\{(.*?)\\})/;J $2A={};J 7E={1t:C(2b,2H){J 1y=0;2b=2b.1k(2H);3C{q.b5(C(V){2b(V,1y++)})}3P(e){if(e!=$2A)73 e}N q},On:C(9w,2b,2H){2b=2b?2b.1k(2H):1B.K;J 1y=-9w,vl=[],5N=q.9f();2S((1y+=9w)<5N.Y)vl.1N(5N.6i(1y,1y+9w));N vl.ko(2b,2H)},4l:C(2b,2H){2b=2b?2b.1k(2H):1B.K;J 2W=1b;q.1t(C(V,1y){2W=2W&&!!2b(V,1y);if(!2W)73 $2A});N 2W},l4:C(2b,2H){2b=2b?2b.1k(2H):1B.K;J 2W=1a;q.1t(C(V,1y){if(2W=!!2b(V,1y))73 $2A});N 2W},ko:C(2b,2H){2b=2b?2b.1k(2H):1B.K;J 1S=[];q.1t(C(V,1y){1S.1N(2b(V,1y))});N 1S},bF:C(2b,2H){2b=2b.1k(2H);J 2W;q.1t(C(V,1y){if(2b(V,1y)){2W=V;73 $2A}});N 2W},gv:C(2b,2H){2b=2b.1k(2H);J 1S=[];q.1t(C(V,1y){if(2b(V,1y))1S.1N(V)});N 1S},10h:C(5t,2b,2H){2b=2b?2b.1k(2H):1B.K;J 1S=[];if(1i.5S(5t))5t=1c 8x(5t);q.1t(C(V,1y){if(5t.1Z(V))1S.1N(2b(V,1y))});N 1S},4j:C(1F){if(1i.5w(q.3R))if(q.3R(1F)!=-1)N 1b;J ai=1a;q.1t(C(V){if(V==1F){ai=1b;73 $2A}});N ai},10i:C(9w,lb){lb=lb===1R?1d:lb;N q.On(9w,C(6i){2S(6i.Y<9w)6i.1N(lb);N 6i})},9N:C(aJ,2b,2H){2b=2b.1k(2H);q.1t(C(V,1y){aJ=2b(aJ,V,1y)});N aJ},8n:C(3e){J 4u=$A(1D).6i(1);N q.4G(C(V){N V[3e].7D(V,4u)})},4X:C(2b,2H){2b=2b?2b.1k(2H):1B.K;J 2W;q.1t(C(V,1y){V=2b(V,1y);if(2W==1R||V>=2W)2W=V});N 2W},cR:C(2b,2H){2b=2b?2b.1k(2H):1B.K;J 2W;q.1t(C(V,1y){V=2b(V,1y);if(2W==1R||V<2W)2W=V});N 2W},10v:C(2b,2H){2b=2b?2b.1k(2H):1B.K;J wt=[],wv=[];q.1t(C(V,1y){(2b(V,1y)?wt:wv).1N(V)});N[wt,wv]},eQ:C(2L){J 1S=[];q.1t(C(V){1S.1N(V[2L])});N 1S},gZ:C(2b,2H){2b=2b.1k(2H);J 1S=[];q.1t(C(V,1y){if(!2b(V,1y))1S.1N(V)});N 1S},Kz:C(2b,2H){2b=2b.1k(2H);N q.4G(C(V,1y){N{V:V,nV:2b(V,1y)}}).cw(C(1T,6C){J a=1T.nV,b=6C.nV;N ab?1:0}).eQ(\'V\')},9f:C(){N q.4G()},NY:C(){J 2b=1B.K,4u=$A(1D);if(1i.5w(4u.4o()))2b=4u.JD();J N5=[q].4W(4u).4G($A);N q.4G(C(V,1y){N 2b(N5.eQ(1y))})},3s:C(){N q.9f().Y},5T:C(){N\'#<7E:\'+q.9f().5T()+\'>\'}};1i.1u(7E,{4G:7E.ko,wx:7E.bF,1C:7E.gv,5t:7E.gv,11t:7E.4j,11u:7E.9f,11r:7E.4l,11k:7E.l4});C $A(8U){if(!8U)N[];if(8U.9f)N 8U.9f();J Y=8U.Y,1S=1c 3r(Y);2S(Y--)1S[Y]=8U[Y];N 1S}if(1B.2j.6D){C $A(8U){if(!8U)N[];if(!(1i.5w(8U)&&8U==\'[1F WC]\')&&8U.9f)N 8U.9f();J Y=8U.Y,1S=1c 3r(Y);2S(Y--)1S[Y]=8U[Y];N 1S}}3r.6M=$A;1i.1u(3r.1w,7E);if(!3r.1w.ww)3r.1w.ww=3r.1w.b2;1i.1u(3r.1w,{b5:C(2b){1j(J i=0,Y=q.Y;i1?q:q[0]},Q1:C(LJ){N q.9N([],C(5N,V,1y){if(0==1y||(LJ?5N.4o()!=V:!5N.4j(V)))5N.1N(V);N 5N})},Wf:C(5N){N q.Q1().gv(C(2X){N 5N.bF(C(V){N 2X===V})})},4Z:C(){N[].4W(q)},3s:C(){N q.Y},5T:C(){N\'[\'+q.4G(1i.5T).57(\', \')+\']\'},9U:C(){J 1S=[];q.1t(C(1F){J V=1i.9U(1F);if(V!==1R)1S.1N(V)});N\'[\'+1S.57(\', \')+\']\'}});if(1i.5w(3r.1w.Q8))3r.1w.b5=3r.1w.Q8;if(!3r.1w.3R)3r.1w.3R=C(2X,i){i||(i=0);J Y=q.Y;if(i<0)i=Y+i;1j(;i1}()){C 1t(2b){J 7e=[];1j(J 1Y in q.co){J V=q.co[1Y];if(7e.4j(1Y))6o;7e.1N(1Y);J 2k=[1Y,V];2k.1Y=1Y;2k.V=V;2b(2k)}}}14{C 1t(2b){1j(J 1Y in q.co){J V=q.co[1Y],2k=[1Y,V];2k.1Y=1Y;2k.V=V;2b(2k)}}}C vP(1Y,V){if(1i.f6(V))N 1Y;N 1Y+\'=\'+9n(4c.k7(V))}N{2y:C(1F){q.co=1i.Pf(1F)?1F.gy():1i.4Z(1F)},b5:1t,2u:C(1Y,V){N q.co[1Y]=V},2d:C(1Y){N q.co[1Y]},OB:C(1Y){J V=q.co[1Y];bH q.co[1Y];N V},gy:C(){N 1i.4Z(q.co)},5L:C(){N q.eQ(\'1Y\')},4y:C(){N q.eQ(\'V\')},1y:C(V){J 1Z=q.bF(C(2k){N 2k.V===V});N 1Z&&1Z.1Y},XS:C(1F){N q.4Z().29(1F)},29:C(1F){N 1c 3a(1F).9N(q,C(2W,2k){2W.2u(2k.1Y,2k.V);N 2W})},fz:C(){N q.4G(C(2k){J 1Y=9n(2k.1Y),4y=2k.V;if(4y&&28 4y==\'1F\'){if(1i.cD(4y))N 4y.4G(vP.uA(1Y)).57(\'&\')}N vP(1Y,4y)}).57(\'&\')},5T:C(){N\'#<3a:{\'+q.4G(C(2k){N 2k.4G(1i.5T).57(\': \')}).57(\', \')+\'}>\'},9U:C(){N 1i.9U(q.gy())},4Z:C(){N 1c 3a(q)}}})());3a.1w.wl=3a.1w.gy;3a.6M=$H;J ON=2q.2r(7E,{2y:C(5f,7M,iw){q.5f=5f;q.7M=7M;q.iw=iw},b5:C(2b){J V=q.5f;2S(q.4j(V)){2b(V);V=V.wo()}},4j:C(V){if(V1&&!((8o==4)&&q.wz))q.wA(q.1W.8o)},GF:C(){J hi={\'X-Yc-VZ\':\'Gh\',\'X-1B-pd\':1B.pd,\'VB\':\'26/68, 26/8L, jz/aB, 26/aB, */*\'};if(q.3e==\'h2\'){hi[\'w7-1V\']=q.O.nW+(q.O.wK?\'; VQ=\'+q.O.wK:\'\');if(q.1W.EU&&(7y.bs.1Z(/gp\\/(\\d{4})/)||[0,ED])[1]=eI&&dJ2&&!1B.2j.IE)||8o==4){q.dJ=q.oI();q.vU=q.J2();q.4B=4c.k7(1W.4B);q.tY=q.Jh()}if(8o==4){J aB=1W.6s;q.6s=aB===1R?1d:aB;q.10P=q.KA()}},dJ:0,vU:\'\',oI:3c.8i.1w.oI,J2:C(){3C{N q.1W.vU||\'\'}3P(e){N\'\'}},kL:3c.8i.1w.kL,Zb:C(){3C{N q.wd()}3P(e){N 1d}},w5:C(1m){N q.1W.w5(1m)},wd:C(){N q.1W.wd()},Jh:C(){J bu=q.kL(\'X-Kq\');if(!bu)N 1d;bu=qz(hn(bu));3C{N bu.hN(q.7l.O.JU)}3P(e){q.7l.h7(e)}},KA:C(){J O=q.7l.O;if(!O.hN||(O.hN!=\'KK\'&&!(q.kL(\'w7-1V\')||\'\').4j(\'jz/bu\')))N 1d;3C{N q.1W.4B.hN(O.JU)}3P(e){q.7l.h7(e)}}});3c.y6=2q.2r(3c.8i,{2y:C($7a,3j,2o,O){q.3j={9t:(3j.9t||3j),nL:(3j.nL||(3j.9t?1d:3j))};O=O||{};J 2G=O.2G;O.2G=(C(7j,c3){q.HC(7j.4B);if(1i.5w(2G))2G(7j,c3)}).1k(q);$7a(2o,O)},HC:C(4B){J kw=q.3j[q.9t()?\'9t\':\'nL\'],O=q.O;if(!O.9K)4B=4B.ap();if(kw=$(kw)){if(O.ha){if(1i.5S(O.ha)){J ha={};ha[O.ha]=4B;kw.2g(ha)}14 O.ha(kw,4B)}14 kw.29(4B)}if(q.9t()){if(q.2G)q.2G.1k(q).cF()}}});3c.QA=2q.2r(3c.7d,{2y:C($7a,3j,2o,O){$7a(O);q.2G=q.O.2G;q.aE=(q.O.aE||2);q.he=(q.O.he||1);q.w8={};q.3j=3j;q.2o=2o;q.5f()},5f:C(){q.O.2G=q.HE.1k(q);q.gh()},3L:C(){q.w8.O.2G=1R;9J(q.7p);(q.2G||1B.79).7D(q,1D)},HE:C(7j){if(q.O.he){q.he=(7j.4B==q.HJ?q.he*q.O.he:1);q.HJ=7j.4B}q.7p=q.gh.1k(q).74(q.he*q.aE)},gh:C(){q.w8=1c 3c.y6(q.3j,q.2o,q.O)}});C $(E){if(1D.Y>1){1j(J i=0,2T=[],Y=1D.Y;i\';bH 3M.1m;N 1e.cS(1f.2w(1E),3M)}if(!7e[1E])7e[1E]=1e.1u(1f.2w(1E));N 1e.cS(7e[1E].9b(1a),3M)};1i.1u(q.1e,E||{})}).wF(1L);1e.7e={};1e.2m={fT:C(E){N $(E).1g.3v!=\'4s\'},bk:C(E){E=$(E);1e[1e.fT(E)?\'2M\':\'3o\'](E);N E},2M:C(E){$(E).1g.3v=\'4s\';N E},3o:C(E){$(E).1g.3v=\'\';N E},42:C(E){E=$(E);E.1v.5B(E);N E},29:C(E,1O){E=$(E);if(1O&&1O.8A)1O=1O.8A();if(1i.bA(1O))N E.29().2g(1O);1O=1i.bI(1O);E.2C=1O.ap();1O.9K.1k(1O).cF();N E},2V:C(E,1O){E=$(E);if(1O&&1O.8A)1O=1O.8A();14 if(!1i.bA(1O)){1O=1i.bI(1O);J 7L=E.c0.qN();7L.UZ(E);1O.9K.1k(1O).cF();1O=7L.zj(1O.ap())}E.1v.wL(1O,E);N E},2g:C(E,5Z){E=$(E);if(1i.5S(5Z)||1i.lg(5Z)||1i.bA(5Z)||(5Z&&(5Z.8A||5Z.bI)))5Z={4A:5Z};J 1O,t,7L;1j(1K in 5Z){1O=5Z[1K];1K=1K.3t();t=1e.hs[1K];if(1O&&1O.8A)1O=1O.8A();if(1i.bA(1O)){t.2g(E,1O);6o}1O=1i.bI(1O);7L=E.c0.qN();t.jS(E,7L);t.2g(E,7L.zj(1O.ap()));1O.9K.1k(1O).cF()}N E},oA:C(E,4P,3M){E=$(E);if(1i.bA(4P))$(4P).cS(3M||{});14 if(1i.5S(4P))4P=1c 1e(4P,3M);14 4P=1c 1e(\'1x\',4P);if(E.1v)E.1v.wL(4P,E);4P.1X(E);N 4P},5T:C(E){E=$(E);J 2W=\'<\'+E.1E.3t();$H({\'id\':\'id\',\'1G\':\'3w\'}).1t(C(2k){J 2L=2k.8E(),4J=2k.4o();J V=(E[2L]||\'\').55();if(V)2W+=\' \'+4J+\'=\'+V.5T(1b)});N 2W+\'>\'},uZ:C(E,2L){E=$(E);J 2T=[];2S(E=E[2L])if(E.5s==1)2T.1N(1e.1u(E));N 2T},lX:C(E){N $(E).uZ(\'1v\')},m8:C(E){N $A($(E).4q(\'*\')).1t(1e.1u)},IX:C(E){E=$(E).3z;2S(E&&E.5s!=1)E=E.6e;N $(E)},FC:C(E){if(!(E=$(E).3z))N[];2S(E&&E.5s!=1)E=E.6e;if(E)N[E].4W($(E).eN());N[]},je:C(E){N $(E).uZ(\'tE\')},eN:C(E){N $(E).uZ(\'6e\')},UK:C(E){E=$(E);N E.je().b2().4W(E.eN())},1Z:C(E,5x){if(1i.5S(5x))5x=1c 2p(5x);N 5x.1Z($(E))},up:C(E,4h,1y){E=$(E);if(1D.Y==1)N $(E.1v);J lX=E.lX();N 4h?2p.87(lX,4h,1y):lX[1y||0]},8r:C(E,4h,1y){E=$(E);if(1D.Y==1)N E.IX();J m8=E.m8();N 4h?2p.87(m8,4h,1y):m8[1y||0]},BU:C(E,4h,1y){E=$(E);if(1D.Y==1)N $(2p.61.oh(E));J je=E.je();N 4h?2p.87(je,4h,1y):je[1y||0]},7t:C(E,4h,1y){E=$(E);if(1D.Y==1)N $(2p.61.os(E));J eN=E.eN();N 4h?2p.87(eN,4h,1y):eN[1y||0]},1C:C(){J 4u=$A(1D),E=$(4u.ay());N 2p.rx(E,4u)},gV:C(){J 4u=$A(1D),E=$(4u.ay());N 2p.rx(E.1v,4u).iQ(E)},Ft:C(E){E=$(E);J id=E.cO(\'id\'),f7=1D.eh;if(id)N id;do{id=\'So\'+f7.FB++}2S($(id));E.cS(\'id\',id);N id},cO:C(E,1m){E=$(E);if(1B.2j.IE){J t=1e.bB.al;if(t.4y[1m])N t.4y[1m](E,1m);if(t.ae[1m])1m=t.ae[1m];if(1m.4j(\':\')){N(!E.3M||!E.3M[1m])?1d:E.3M[1m].V}}N E.1r(1m)},cS:C(E,1m,V){E=$(E);J 3M={},t=1e.bB.9h;if(28 1m==\'1F\')3M=1m;14 3M[1m]=V===1R?1b:V;1j(J 5d in 3M){J 1m=t.ae[5d]||5d,V=3M[5d];if(t.4y[5d])1m=t.4y[5d](E,V);if(V===1a||V===1d)E.pS(1m);14 if(V===1b)E.3p(1m,1m);14 E.3p(1m,V)}N E},3H:C(E){N $(E).5U().1p},5D:C(E){N $(E).5U().1l},i0:C(E){N 1c 1e.sh(E)},g2:C(E,1G){if(!(E=$(E)))N;J uP=E.1G;N(uP.Y>0&&(uP==1G||1c 8x("(^|\\\\s)"+1G+"(\\\\s|$)").3n(uP)))},2F:C(E,1G){if(!(E=$(E)))N;if(!E.g2(1G))E.1G+=(E.1G?\' \':\'\')+1G;N E},4n:C(E,1G){if(!(E=$(E)))N;E.1G=E.1G.2V(1c 8x("(^|\\\\s+)"+1G+"(\\\\s+|$)"),\' \').5h();N E},S0:C(E,1G){if(!(E=$(E)))N;N E[E.g2(1G)?\'4n\':\'2F\'](1G)},j1:C(E){E=$(E);J 1h=E.3z;2S(1h){J DF=1h.6e;if(1h.5s==3&&!/\\S/.3n(1h.4i))E.5B(1h);1h=DF}N E},gg:C(E){N $(E).2C.i9()},mN:C(E,8X){E=$(E),8X=$(8X);if(E.Ds)N(E.Ds(8X)&8)===8;if(E.uQ&&!1B.2j.9y){J e=E.uQ,a=8X.uQ,nl=8X.6e;if(!nl){do{8X=8X.1v}2S(!(nl=8X.6e)&&8X.1v)}if(nl)N(e>a&&e\',\'\',1],gs:[\'<4M><8a>\',\'\',2],TR:[\'<4M><8a>\',\'\',3],TD:[\'<4M><8a>\',\'\',4],uy:[\'<1C>\',\'\',1]}};(C(){q.4A.jS=q.1H.jS;1i.1u(q.aZ,{s0:q.aZ.gs,rZ:q.aZ.gs,TH:q.aZ.TD})}).wF(1e.hs);1e.2m.rB={9D:C(E,4J){4J=1e.bB.gJ[4J]||4J;J 1h=$(E).Gv(4J);N 1h&&1h.E7}};1e.2m.ag={};1i.1u(1e,1e.2m);if(!1B.bS.m4&&1f.2w(\'1x\').hW){1L.mG={};1L.mG.1w=1f.2w(\'1x\').hW;1B.bS.m4=1b}1e.1u=(C(){if(1B.bS.rb)N 1B.K;J 2m={},ag=1e.2m.ag;J 1u=1i.1u(C(E){if(!E||E.t3||E.5s!=1||E==1L)N E;J 7I=1i.4Z(2m),1E=E.1E,2L,V;if(ag[1E])1i.1u(7I,ag[1E]);1j(2L in 7I){V=7I[2L];if(1i.5w(V)&&!(2L in E))E[2L]=V.g0()}E.t3=1B.79;N E},{rg:C(){if(!1B.bS.m4){1i.1u(2m,1e.2m);1i.1u(2m,1e.2m.rB)}}});1u.rg();N 1u})();1e.9D=C(E,4J){if(E.9D)N E.9D(4J);N 1e.2m.rB.9D(E,4J)};1e.iG=C(7I){J F=1B.bS,T=1e.2m.ag;if(!7I){1i.1u(4d,4d.2m);1i.1u(4d.1e,4d.1e.2m);1i.1u(1e.2m.ag,{"A7":1i.4Z(4d.2m),"pF":1i.4Z(4d.1e.2m),"uy":1i.4Z(4d.1e.2m),"tP":1i.4Z(4d.1e.2m)})}if(1D.Y==2){J 1E=7I;7I=1D[1]}if(!1E)1i.1u(1e.2m,7I||{});14{if(1i.cD(1E))1E.1t(1u);14 1u(1E)}C 1u(1E){1E=1E.4F();if(!1e.2m.ag[1E])1e.2m.ag[1E]={};1i.1u(1e.2m.ag[1E],7I)}C fQ(7I,jM,rW){rW=rW||1a;1j(J 2L in 7I){J V=7I[2L];if(!1i.5w(V))6o;if(!rW||!(2L in jM))jM[2L]=V.g0()}}C FS(1E){J 4K;J wI={"z6":"Th","tP":"Tm","P":"Tl","Eg":"Tk","UL":"Ti","OL":"Tj","DL":"SJ","Ea":"SI","H1":"jp","H2":"jp","H3":"jp","H4":"jp","H5":"jp","H6":"jp","Q":"Sa","ET":"Gx","Eb":"Gx","A":"S8","r9":"OC","zc":"S6","za":"Gy","z9":"Gy","s0":"wH","rZ":"wH","gs":"wH","TR":"Sb","TH":"Gz","TD":"Gz","Ev":"Sg","EJ":"Sf"};if(wI[1E])4K=\'rc\'+wI[1E]+\'1e\';if(1L[4K])N 1L[4K];4K=\'rc\'+1E+\'1e\';if(1L[4K])N 1L[4K];4K=\'rc\'+1E.rf()+\'1e\';if(1L[4K])N 1L[4K];1L[4K]={};1L[4K].1w=1f.2w(1E).hW;N 1L[4K]}if(F.m4){fQ(1e.2m,mG.1w);fQ(1e.2m.rB,mG.1w,1b)}if(F.rb){1j(J 6Z in 1e.2m.ag){J 4K=FS(6Z);if(1i.f6(4K))6o;fQ(T[6Z],4K.1w)}}1i.1u(1e,1e.2m);bH 1e.ag;if(1e.1u.rg)1e.1u.rg();1e.7e={}};1f.aC={5U:C(){J vV={};$w(\'1l 1p\').1t(C(d){J D=d.rf();vV[d]=f7[\'RU\'+D]||(1f.3G[\'q1\'+D]||1f.2B[\'q1\'+D])});N vV},5D:C(){N q.5U().1l},3H:C(){N q.5U().1p},xr:C(){N 1e.f0(1L.Id||1f.3G.8u||1f.2B.8u,1L.rs||1f.3G.5E||1f.2B.5E)}};J 2p=2q.2r({2y:C(4h){q.4h=4h.5h();q.DU()},DU:C(){if(1B.bS.om&&!(/(\\[[\\w-]*?:|:8D)/).3n(q.4h))N q.E5();J e=q.4h,ps=2p.nR,h=2p.61,c=2p.nV,le,p,m;if(2p.hP[e]){q.bD=2p.hP[e];N}q.bD=["q.bD = C(2l) {","J r = 2l, h = 2p.61, c = 1a, n;"];2S(e&&le!=e&&(/\\S/).3n(e)){le=e;1j(J i in ps){p=ps[i];if(m=e.1Z(p)){q.bD.1N(1i.5w(c[i])?c[i](m):1c 7T(c[i]).7S(m));e=e.2V(m[0],\'\');2A}}}q.bD.1N("N h.fa(n);\\n}");8y(q.bD.57(\'\\n\'));2p.hP[q.4h]=q.bD},E5:C(){J e=q.4h,ps=2p.nR,x=2p.7g,le,m;if(2p.hP[e]){q.7g=2p.hP[e];N}q.bD=[\'.//*\'];2S(e&&le!=e&&(/\\S/).3n(e)){le=e;1j(J i in ps){if(m=e.1Z(ps[i])){q.bD.1N(1i.5w(x[i])?x[i](m):1c 7T(x[i]).7S(m));e=e.2V(m[0],\'\');2A}}}q.7g=q.bD.57(\'\');2p.hP[q.4h]=q.7g},bJ:C(2l){2l=2l||1f;if(q.7g)N 1f.vd(q.7g,2l);N q.bD(2l)},1Z:C(E){q.9M=[];J e=q.4h,ps=2p.nR,as=2p.wa;J le,p,m;2S(e&&le!==e&&(/\\S/).3n(e)){le=e;1j(J i in ps){p=ps[i];if(m=e.1Z(p)){if(as[i]){q.9M.1N([i,1i.4Z(m)]);e=e.2V(m[0],\'\')}14{N q.bJ(1f).4j(E)}}}}J 1Z=1b,1m,71;1j(J i=0,aG;aG=q.9M[i];i++){1m=aG[0],71=aG[1];if(!2p.wa[1m](E,71)){1Z=1a;2A}}N 1Z},55:C(){N q.4h},5T:C(){N"#<2p:"+q.4h.5T()+">"}});1i.1u(2p,{hP:{},7g:{eP:"//*",2P:"/*",gV:"/oW-fb::*[1]",nG:\'/oW-fb::*\',1E:C(m){if(m[1]==\'*\')N\'\';N"[Dp-1m()=\'"+m[1].3t()+"\' or Dp-1m()=\'"+m[1].4F()+"\']"},1G:"[ot(4W(\' \', @3w, \' \'), \' #{1} \')]",id:"[@id=\'#{1}\']",kO:"[@#{1}]",5d:C(m){m[3]=m[5]||m[6];N 1c 7T(2p.7g.nQ[m[2]]).7S(m)},oa:C(m){J h=2p.7g.6z[m[1]];if(!h)N\'\';if(1i.5w(h))N h(m);N 1c 7T(2p.7g.6z[m[1]]).7S(m)},nQ:{\'=\':"[@#{1}=\'#{3}\']",\'!=\':"[@#{1}!=\'#{3}\']",\'^=\':"[S3-hm(@#{1}, \'#{3}\')]",\'$=\':"[5Y(@#{1}, (56-Y(@#{1}) - 56-Y(\'#{3}\') + 1))=\'#{3}\']",\'*=\':"[ot(@#{1}, \'#{3}\')]",\'~=\':"[ot(4W(\' \', @#{1}, \' \'), \' #{3} \')]",\'|=\':"[ot(4W(\'-\', @#{1}, \'-\'), \'-#{3}-\')]"},6z:{\'8E-2P\':\'[9B(w6-fb::*)]\',\'4o-2P\':\'[9B(oW-fb::*)]\',\'69-2P\':\'[9B(w6-fb::* or oW-fb::*)]\',\'gg\':"[5a(*) = 0 w9 (5a(26()) = 0 or S1(26(), \' \\t\\r\\n\', \'\') = \'\')]",\'8D\':"[@8D]",\'2K\':"[@2K]",\'bN\':"[9B(@2K)]",\'9B\':C(m){J e=m[6],p=2p.nR,x=2p.7g,le,m,v;J wc=[];2S(e&&le!=e&&(/\\S/).3n(e)){le=e;1j(J i in p){if(m=e.1Z(p[i])){v=1i.5w(x[i])?x[i](m):1c 7T(x[i]).7S(m);wc.1N("("+v.5Y(1,v.Y-1)+")");e=e.2V(m[0],\'\');2A}}}N"[9B("+wc.57(" w9 ")+")]"},\'5o-2P\':C(m){N 2p.7g.6z.5o("(5a(./w6-fb::*) + 1) ",m)},\'5o-4o-2P\':C(m){N 2p.7g.6z.5o("(5a(./oW-fb::*) + 1) ",m)},\'5o-of-1V\':C(m){N 2p.7g.6z.5o("1K() ",m)},\'5o-4o-of-1V\':C(m){N 2p.7g.6z.5o("(4o() + 1 - 1K()) ",m)},\'8E-of-1V\':C(m){m[6]="1";N 2p.7g.6z[\'5o-of-1V\'](m)},\'4o-of-1V\':C(m){m[6]="1";N 2p.7g.6z[\'5o-4o-of-1V\'](m)},\'69-of-1V\':C(m){J p=2p.7g.6z;N p[\'8E-of-1V\'](m)+p[\'4o-of-1V\'](m)},5o:C(k0,m){J mm,4I=m[6],wm;if(4I==\'ca\')4I=\'2n+0\';if(4I==\'GN\')4I=\'2n+1\';if(mm=4I.1Z(/^(\\d+)$/))N\'[\'+k0+"= "+mm[1]+\']\';if(mm=4I.1Z(/^(-?\\d*)?n(([+-])(\\d+))?/)){if(mm[1]=="-")mm[1]=-1;J a=mm[1]?ad(mm[1]):1;J b=mm[2]?ad(mm[2]):0;wm="[((#{k0} - #{b}) Sz #{a} = 0) w9 "+"((#{k0} - #{b}) 1x #{a} >= 0)]";N 1c 7T(wm).7S({k0:k0,a:a,b:b})}}}},nV:{1E:\'n = h.1E(n, r, "#{1}", c); c = 1a;\',1G:\'n = h.1G(n, r, "#{1}", c); c = 1a;\',id:\'n = h.id(n, r, "#{1}", c); c = 1a;\',kO:\'n = h.kO(n, r, "#{1}"); c = 1a;\',5d:C(m){m[3]=(m[5]||m[6]);N 1c 7T(\'n = h.5d(n, r, "#{1}", "#{3}", "#{2}"); c = 1a;\').7S(m)},oa:C(m){if(m[6])m[6]=m[6].2V(/"/g,\'\\\\"\');N 1c 7T(\'n = h.oa(n, "#{1}", "#{6}", r, c); c = 1a;\').7S(m)},eP:\'c = "eP";\',2P:\'c = "2P";\',gV:\'c = "gV";\',nG:\'c = "nG";\'},nR:{nG:/^\\s*~\\s*/,2P:/^\\s*>\\s*/,gV:/^\\s*\\+\\s*/,eP:/^\\s/,1E:/^\\s*(\\*|[\\w\\-]+)(\\b|$)?/,id:/^#([\\w\\-\\*]+)(\\b|$)/,1G:/^\\.([\\w\\-\\*]+)(\\b|$)/,oa:/^:((8E|4o|5o|5o-4o|69)(-2P|-of-1V)|gg|8D|(en|SH)SG|9B)(\\((.*?)\\))?(\\b|$|(?=\\s)|(?=:))/,kO:/^\\[([\\w]+)\\]/,5d:/\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*(([\'"])([^\\4]*?)\\4|([^\'"][^\\]]*?)))?\\]/},wa:{1E:C(E,71){N 71[1].4F()==E.1E.4F()},1G:C(E,71){N 1e.g2(E,71[1])},id:C(E,71){N E.id===71[1]},kO:C(E,71){N 1e.9D(E,71[1])},5d:C(E,71){J 4i=1e.cO(E,71[1]);N 2p.nQ[71[2]](4i,71[3])}},61:{4W:C(a,b){1j(J i=0,1h;1h=b[i];i++)a.1N(1h);N a},gT:C(1M){1j(J i=0,1h;1h=1M[i];i++)1h.d9=1b;N 1M},fD:C(1M){1j(J i=0,1h;1h=1M[i];i++)1h.d9=1R;N 1M},1y:C(1v,b2,oo){1v.d9=1b;if(b2){1j(J 1M=1v.1o,i=1M.Y-1,j=1;i>=0;i--){J 1h=1M[i];if(1h.5s==1&&(!oo||1h.d9))1h.rt=j++}}14{1j(J i=0,j=1,1M=1v.1o;1h=1M[i];i++)if(1h.5s==1&&(!oo||1h.d9))1h.rt=j++}},fa:C(1M){if(1M.Y==0)N 1M;J 1S=[],n;1j(J i=0,l=1M.Y;i0?[b]:[];N $R(1,bV).9N([],C(aJ,i){if(0==(i-b)%a&&(i-b)/a>=0)aJ.1N(i);N aJ})},5o:C(1M,4I,2l,b2,oo){if(1M.Y==0)N[];if(4I==\'ca\')4I=\'2n+0\';if(4I==\'GN\')4I=\'2n+1\';J h=2p.61,1S=[],wi=[],m;h.gT(1M);1j(J i=0,1h;1h=1M[i];i++){if(!1h.1v.d9){h.1y(1h.1v,b2,oo);wi.1N(1h.1v)}}if(4I.1Z(/^\\d+$/)){4I=ad(4I);1j(J i=0,1h;1h=1M[i];i++)if(1h.rt==4I)1S.1N(1h)}14 if(m=4I.1Z(/^(-?\\d*)?n(([+-])(\\d+))?/)){if(m[1]=="-")m[1]=-1;J a=m[1]?ad(m[1]):1;J b=m[2]?ad(m[2]):0;J wb=2p.6z.JN(a,b,1M.Y);1j(J i=0,1h,l=wb.Y;1h=1M[i];i++){1j(J j=0;j+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)/,C(m){k3.1N(m[1].5h())});J 1S=[],h=2p.61;1j(J i=0,l=k3.Y,5x;i1)?h.fa(1S):1S}});C $$(){N 2p.rx(1f,$A(1D))}J 4d={cT:C(2D){$(2D).cT();N 2D},Km:C(2T,O){if(28 O!=\'1F\')O={4e:!!O};14 if(O.4e===1R)O.4e=1b;J 1Y,V,we=1a,b8=O.b8;J c9=2T.9N({},C(2W,E){if(!E.2K&&E.1m){1Y=E.1m;V=$(E).3T();if(V!=1d&&(E.1V!=\'b8\'||(!we&&b8!==1a&&(!b8||1Y==b8)&&(we=1b)))){if(1Y in 2W){if(!1i.cD(2W[1Y]))2W[1Y]=[2W[1Y]];2W[1Y].1N(V)}14 2W[1Y]=V}}N 2W});N O.4e?c9:1i.fz(c9)}};4d.2m={cd:C(2D,O){N 4d.Km(4d.fh(2D),O)},fh:C(2D){N $A($(2D).4q(\'*\')).9N([],C(2T,2P){if(4d.1e.kT[2P.1E.3t()])2T.1N(1e.1u(2P));N 2T})},UV:C(2D,rz,1m){2D=$(2D);J e1=2D.4q(\'21\');if(!rz&&!1m)N $A(e1).4G(1e.1u);1j(J i=0,w4=[],Y=e1.Y;i=0}).Kz(C(E){N E.rr}).8E();N vS?vS:2T.wx(C(E){N[\'21\',\'1C\',\'3i\'].4j(E.1E.3t())})},UN:C(2D){2D=$(2D);2D.KD().8v();N 2D},7l:C(2D,O){2D=$(2D),O=1i.4Z(O||{});J 4C=O.2Q,2i=2D.cO(\'2i\')||\'\';if(2i.i9())2i=1L.7Z.6G;O.2Q=2D.cd(1b);if(4C){if(1i.5S(4C))4C=4C.lB();1i.1u(O.2Q,4C)}if(2D.9D(\'3e\')&&!O.3e)O.3e=2D.3e;N 1c 3c.8i(2i,O)}};4d.1e={3F:C(E){$(E).3F();N E},1C:C(E){$(E).1C();N E}};4d.1e.2m={cd:C(E){E=$(E);if(!E.2K&&E.1m){J V=E.3T();if(V!=1R){J 2k={};2k[E.1m]=V;N 1i.fz(2k)}}N\'\'},3T:C(E){E=$(E);J 3e=E.1E.3t();N 4d.1e.kT[3e](E)},4Q:C(E,V){E=$(E);J 3e=E.1E.3t();4d.1e.kT[3e](E,V);N E},jN:C(E){$(E).V=\'\';N E},UD:C(E){N $(E).V!=\'\'},8v:C(E){E=$(E);3C{E.3F();if(E.1C&&(E.1E.3t()!=\'21\'||![\'7x\',\'cT\',\'b8\'].4j(E.1V)))E.1C()}3P(e){}N E},7v:C(E){E=$(E);3C{E.5b()}3P(e){}E.2K=1b;N E},hU:C(E){E=$(E);E.2K=1a;N E}};J pZ=4d.1e;J $F=4d.1e.2m.3T;4d.1e.kT={21:C(E,V){7G(E.1V.3t()){1U\'AV\':1U\'pV\':N 4d.1e.kT.KE(E,V);9v:N 4d.1e.kT.3i(E,V)}},KE:C(E,V){if(V===1R)N E.8D?E.V:1d;14 E.8D=!!V},3i:C(E,V){if(V===1R)N E.V;14 E.V=V},1C:C(E,1y){if(1y===1R)N q[E.1V==\'1C-Uz\'?\'JV\':\'JX\'](E);14{J 6K,V,K4=!1i.cD(1y);1j(J i=0,Y=E.Y;i=0?q.rl(E.O[1y]):1d},JX:C(E){J 4y,Y=E.Y;if(!Y)N 1d;1j(J i=0,4y=[];i<\\/5j>");$("I9").tb=C(){if(q.8o=="Ar"){q.tb=1d;oB()}}}})();3a.fz=1i.fz;J U0={3v:1e.bk};1e.2m.FH=1e.2m.mN;J PL={Lh:C(E,1O){N 1e.2g(E,{cJ:1O})},yn:C(E,1O){N 1e.2g(E,{1H:1O})},yo:C(E,1O){N 1e.2g(E,{4A:1O})},xD:C(E,1O){N 1e.2g(E,{fC:1O})}};J $6o=1c f3(\'"73 $6o" is U1, U5 "N" U4\');J 2Z={kD:1a,c7:C(){q.tQ=1L.Id||1f.3G.8u||1f.2B.8u||0;q.tR=1L.rs||1f.3G.5E||1f.2B.5E||0},lO:C(E,x,y){if(q.kD)N q.Ie(E,x,y);q.oe=x;q.o4=y;q.51=1e.6c(E);N(y>=q.51[1]&&y=q.51[0]&&x=q.51[1]&&q.o4=q.51[0]&&q.oe0}).b5(2b)},2u:C(1G){q.E.1G=1G},5G:C(vg){if(q.4j(vg))N;q.2u($A(q).4W(vg).57(\' \'))},42:C(vI){if(!q.4j(vI))N;q.2u($A(q).iQ(vI).57(\' \'))},55:C(){N $A(q).57(\' \')}};1i.1u(1e.sh.1w,7E);1e.iG();J 2a={vv:["jx","1l","1p","sC","oU"],6K:["p7","p2","7h","TP","TO","TM","TN","U6","m5","Hg","U7","Uq","Up","Uo"],cW:["id","1m","6A"],vf:["Um"],oN:"vj.Un",hV:"Ur",gC:"Us",ua:7y.bs.3t(),jy:"",fv:[0,0],dL:[],2r:C(FO,id){if(!2a.b1("IK")||2a.b1("IH"))N;2a.BT();2a.dL[id]=2a.I7(FO);2a.a7("#"+id,"8P:3N;");2a.HY(id)},I7:C(FO){if(28 FO.xi!="1R"&&FO.xi=="1b"){if(28 FO.oN=="1R")FO.oN=2a.oN;if(28 FO.hV=="1R")FO.hV=2a.hV;if(28 FO.gC=="1R")FO.gC=2a.gC}FO.vK=1a;N FO},HY:C(id){J vG=ld(C(){if((1f.4q("2B")[0]!=1d||1f.2B!=1d)&&1f.3Q(id)!=1d){2a.vu(id);kB(vG)}},PT);if(28 1f.9P!="1R"){1f.9P("HZ",C(){2a.vu(id);kB(vG)},1d)}},vu:C(id){J 3d=2a.dL[id];if(3d.vK)N;2a.dL[id].vK=1b;1f.3Q(id).1g.8P="3N";if(2a.IM(id)){if(2a.vx(2f(3d.sC,10),2f(3d.oU,10))){if(28 3d.HU!="1R"&&3d.HU=="1b")2a.I5(id);2a.yH(id)}14 if(3d.xi=="1b"&&2a.vx(6,65)){2a.Iy(id)}}1f.3Q(id).1g.8P="fT"},a7:C(5x,vA){J sI=1f.4q("O5")[0];J nS=2a.2w("1g");if(!2a.b1("sA"))nS.1X(1f.aN(5x+" {"+vA+"}"));nS.3p("1V","26/aj");nS.3p("Ut","Ul");sI.1X(nS);if(2a.b1("sA")&&1f.si&&1f.si.Y>0){J vL=1f.si[1f.si.Y-1];if(28 vL.I1=="1F")vL.I1(5x,vA)}},I5:C(id){J 3d=2a.dL[id];J I2=/%/.3n(3d.1l)?"":"px";J sI=/%/.3n(3d.1p)?"":"px";2a.a7("#"+id,"1l:"+3d.1l+I2+"; 1p:"+3d.1p+sI+";");if(3d.1l=="100%"){2a.a7("2B","6U-1T:0; 6U-6C:0; 9j-1T:0; 9j-6C:0;")}if(3d.1p=="100%"){2a.a7("8L","1p:100%; 5c:3N;");2a.a7("2B","6U-1H:0; 6U-4A:0; 9j-1H:0; 9j-4A:0; 1p:100%;")}},2w:C(el){N(2a.b1("aB")&&28 1f.vJ!="1R")?1f.vJ("o5://vh.w3.U8/U9/Ud",el):1f.2w(el)},IN:C(el,I3,IJ){J jt=2a.2w("c3");jt.3p("1m",I3);jt.3p("V",IJ);el.1X(jt)},b1:C(ft){J bP=2a.ua;7G(ft){1U"IK":N(28 1f.3Q!="1R"&&28 1f.4q!="1R"&&(28 1f.2w!="1R"||28 1f.vJ!="1R"));1U"aB":J jF=1f.4q("Uh");J 86=jF.Y;1j(J i=0;i<86;i++){if(/1O-1V/i.3n(jF[i].1r("o5-Uf"))&&/aB/i.3n(jF[i].1r("1O")))N 1b}N 1a;1U"IH":N/nF/.3n(bP)&&!/8l/.3n(bP)&&/Dq/.3n(bP);1U"sA":N/nF/.3n(bP)&&!/8l/.3n(bP)&&/cq/.3n(bP);1U"mY":N/mY/.3n(bP)&&!/IF/.3n(bP);1U"8l":N/8l/.3n(bP);1U"zt":N/IF/.3n(bP);9v:N 1a}},BT:C(){if(2a.fv[0]!=0)N;if(7y.lL&&28 7y.lL["BX l7"]=="1F"){2a.jy="IP";J 89=7y.lL["BX l7"].BY;if(28 89!="1R"){89=89.2V(/^.*\\s+(\\S+\\s+\\S+$)/,"$1");J jF=2f(89.2V(/^(.*)\\..*$/,"$1"),10);J IG=/r/.3n(89)?2f(89.2V(/^.*r(.*)$/,"$1"),10):0;2a.fv=[jF,IG]}}14 if(1L.ge){2a.jy="ax";3C{J jA=1c ge("g1.g1.7")}3P(e){3C{J jA=1c ge("g1.g1.6");2a.fv=[6,0];jA.QP="QQ"}3P(e){if(2a.fv[0]==6)N}3C{J jA=1c ge("g1.g1")}3P(e){}}if(28 jA=="1F"){J 89=jA.NQ("$gb");if(28 89!="1R"){89=89.2V(/^\\S+\\s+(.*)$/,"$1").3Z(",");2a.fv=[2f(89[0],10),2f(89[2],10)]}}}},IM:C(id){J 86=2a.vv.Y;1j(J i=0;i<86;i++){if(28 2a.dL[id][2a.vv[i]]=="1R")N 1a}N 1b},vx:C(vO,IQ){N(2a.fv[0]>vO||(2a.fv[0]==vO&&2a.fv[1]>=IQ))?1b:1a},yH:C(id){J 3d=2a.dL[id];J h0=1f.3Q(id);if(2a.jy=="IP"){if(2a.b1("mY")||2a.b1("aB")){2S(h0.un()){h0.5B(h0.3z)}J fA=2a.2w("1F");fA.3p("1V","jz/x-ve-zy");fA.3p("c9",3d.jx);fA.3p("1l",3d.1l);fA.3p("1p",3d.1p);J 86=2a.cW.Y;1j(J i=0;i<86;i++){if(28 3d[2a.cW[i]]!="1R")fA.3p(2a.cW[i],3d[2a.cW[i]])}J 85=2a.6K.4W(2a.vf);J 86=85.Y;1j(J i=0;i<86;i++){if(28 3d[85[i]]!="1R")2a.IN(fA,85[i],3d[85[i]])}h0.1X(fA)}14{J vq="";J 85=2a.6K.4W(2a.cW).4W(2a.vf);J 86=85.Y;1j(J i=0;i<86;i++){if(28 3d[85[i]]!="1R")vq+=\' \'+85[i]+\'="\'+3d[85[i]]+\'"\'}h0.2C=\'\'}}14 if(2a.jy=="ax"){J vn="";J 86=2a.cW.Y;1j(J i=0;i<86;i++){if(28 3d[2a.cW[i]]!="1R")vn+=\' \'+2a.cW[i]+\'="\'+3d[2a.cW[i]]+\'"\'}J yF="";J 86=2a.6K.Y;1j(J i=0;i<86;i++){if(28 3d[2a.6K[i]]!="1R")yF+=\'\'}J jt=1L.7Z.RH=="Io:"?"Io:":"o5:";h0.2C=\'<1F Rc="Rh:Rp-Rn-Rl-Rm-RE"\'+vn+\' 1l="\'+3d.1l+\'" 1p="\'+3d.1p+\'" Rs="\'+jt+\'//BV.Iv.IA/Rg/ve/Qw/zy/QD.QB#gb=\'+3d.sC+\',0,\'+3d.oU+\',0">\'+yF+\'\'}},Iy:C(id){J 3d=2a.dL[id];2a.a7("8L","1p:100%; 5c:3N;");2a.a7("2B","1p:100%; 5c:3N;");2a.a7("#xi-yE","1K:4Y; 1T:0; 1H:0; z-1y:6F; 1l:100%; 1p:100%; 7z-4b:#oH; 5t:n6(3W:75); 3W:0.75;");2a.a7("#xi-sD","1K:4Y; 1T:50%; 1H:50%; 6U-1T: -"+2c.3X(2f(3d.hV,10)/2)+"px; 6U-1H: -"+2c.3X(2f(3d.gC,10)/2)+"px; 1l:"+3d.hV+"px; 1p:"+3d.gC+"px;");J sB=1f.4q("2B")[0];J jU=2a.2w("1x");jU.3p("id","xi-yE");J 89=2a.2w("1x");89.3p("id","xi-sD");jU.1X(89);sB.1X(jU);J Hh=1L.7Z;if(2a.b1("aB")&&2a.b1("zt")){J yG=1f.4q("3k")[0].3z.4i=1f.4q("3k")[0].3z.4i.6i(0,47)+" - l7 Iw Ix"}14{J yG=1f.3k=1f.3k.6i(0,47)+" - l7 Iw Ix"}J Hm=2a.jy=="ax"?"Re":"Ra";J Hi=28 3d.HS!="1R"?"&Rq="+3d.HS:"";J Hj=28 3d.He!="1R"?"&Ri="+3d.He:"";2a.dL["xi-sD"]={jx:3d.oN,1l:3d.hV,1p:3d.gC,sC:"6",oU:"65",Hg:"Qq="+Hh+"&QY="+Hm+"&QI="+yG+Hi+Hj};2a.yH("xi-sD")},RI:C(){J sB=1f.4q("2B")[0];J jU=1f.3Q("xi-yE");sB.5B(jU);2a.a7("2B","1p:8g; 5c:8g;");2a.a7("8L","1p:8g; 5c:8g;")},GS:C(){J 85=1f.4q("1F");J 86=85.Y;1j(J i=0;i<86;i++){85[i].1g.3v="4s";1j(J x in 85[i]){if(28 85[i][x]=="C"){85[i][x]=1d}}}}};if(28 1L.7w!="1R"&&2a.b1("sA")){1L.7w("nD",2a.GS)}C gQ(m9){q.sy=28 m9=="1R"?6F:m9;q.g7=1d;q.sx=1a}gQ.1w.5f=C(){if(q.GR())q.3L();J 6B=q;q.g7=1L.5C(C(){if(28 6B.kd=="C")6B.kd()},q.sy);q.sx=1a};gQ.1w.3L=C(){if(q.g7!=1d)1L.9J(q.g7);q.sx=1a};gQ.1w.GR=C(){N q.sx};gQ.1w.Ru=C(){N q.sy};gQ.1w.Rr=C(m9){q.sy=m9};C cP(){q.ac=0;q.d3=0;q.8J=100;q.7J=0;q.aW=1a}cP.1w.4Q=C(V){V=2c.3X(82(V));if(v2(V))N;if(q.ac!=V){if(V+q.7J>q.8J)q.ac=q.8J-q.7J;14 if(Vq.8J)q.7J=q.8J-q.ac;14 q.7J=n3;if(!q.aW&&28 q.6k=="C")q.6k()}};cP.1w.RO=C(){N q.7J};cP.1w.kg=C(ee){if(q.d3!=ee){J sz=q.aW;q.aW=1b;q.d3=ee;if(ee>q.ac)q.4Q(ee);if(ee>q.8J){q.7J=0;q.kf(ee);q.4Q(ee)}if(ee+q.7J>q.8J)q.7J=q.8J-q.d3;q.aW=sz;if(!q.aW&&28 q.6k=="C")q.6k()}};cP.1w.bn=C(){N q.d3};cP.1w.kf=C(eq){if(q.8J!=eq){J sz=q.aW;q.aW=1b;q.8J=eq;if(eq1)N;if(1B.2j.6D)N;q.44(e)}.1k(q));q.GW=C(e){if(e==1d)e=3q.c0.ku.1n;q.HN(e)}.1k(q);if(3q.9P){3q.9P("44",q.j5,1a)}14 if(3q.7w){3q.7w("3V",q.j5);3q.7w("cN",q.GW)}q.iF=q.HL.9g(q);q.la=q.H7.9g(q);q.iu=q.GZ.9g(q);q.n0=1a;if(a1){q.a1=$(a1)}14{q.a1=$(3q)}1q.2h(q.a1,"v1",q.la)},H7:C(e){J 3q=q.4k;q.sG=e.yD;q.yI=e.yz;q.sL=2Z.6c(q.a1);q.sM=1e.5U(q.a1);J h=2f(q.a1.2s(\'1p\'));if(q.a1.xs>h){if(q.sG>(q.sL[0]+q.sM.1l)-18)N}1q.2h(1f,"fW",q.iu);1q.2h(1f,"g3",q.iF);if(!q.n9){q.n9=1c 1e(\'1x\',{1g:"52 : fS RA #GE; 7z-4b:#A4; 5t:n6(3W=50);3W: 0.5;-Rf-3W:0.5;z-1y:Rj;1K:4Y;1H:ce;1T:ce;1p:ce;1l:ce;"})}$(q.a1).1I({9X:"Rk"})},GZ:C(e){if(!q.n0){q.2B=1f.4q(\'2B\')[0];q.2B.1X(q.n9);q.n0=1b}J gR=e.yD;J h1=e.yz;J yA=q.sL[0];J yB=q.sL[1];J Ho=yA+q.sM.1l;J HI=yB+q.sM.1p;gR=2c.4X(gR,yA);h1=2c.4X(h1,yB);gR=2c.cR(gR,Ho);h1=2c.cR(h1,HI);J 1H,1T,1l,1p;1T=2c.cR(q.sG,gR);1l=2c.f1((q.sG-gR));1H=2c.cR(q.yI,h1);1p=2c.f1((q.yI-h1));q.n9.1I({1H:1H+\'px\',1T:1T+\'px\',1l:1l+\'px\',1p:1p+\'px\'});J 3g=q.8c();J sw=1T;J sv=1T+1l;J sk=1H;J sl=1H+1p;1j(J i=0;i<3g.Y;i++){J E=$(3g[i]);J 2t=2Z.6c(E);J 3I=1e.5U(E);J x1=2t[0];J x2=2t[0]+3I.1l;J y1=2t[1];J y2=2t[1]+3I.1p;if(((x1>=sw&&x1<=sv)||(x2>=sw&&x2<=sv)||(sw>=x1&&sv<=x2))&&((y1>=sk&&y1<=sl)||(y2>=sk&&y2<=sl)||(sk>=y1&&sl<=y2))){q.6O(3g[i],1b)}14{if(!e[\'7o\']&&!e[\'Qs\']){q.6O(3g[i],1a)}}}},HL:C(e){1q.60(1f,"fW",q.iu);1q.60(1f,"g3",q.iF);if(q.n0){q.2B.5B(q.n9);q.n0=1a}$(q.a1).1I({9X:"9v"})},6O:C(5P,fw){if(!q.d1){if(fw){J sf=q.3A[0];if(5P==sf)N;if(sf!=1d)q.fs(sf,1a);q.fs(5P,1b);q.3A=[5P];q.d2()}14{if(q.3A[0]==5P){q.fs(5P,1a);q.3A=[]}}}14{if(sm(5P.aY)==sm(fw))N;q.fs(5P,fw);if(fw)q.3A[q.3A.Y]=5P;14{J 4z=[];J j=0;1j(J i=0;i(3Y.3H()+3Y.5E)){3Y.5E=mQ-3Y.3H()+$(5P).3H()}14 if(mQ<(3Y.5E)){3Y.5E=mQ-$(5P).3H()}}14{$(5P).4n("4D");$(5P).4n("4D-3F")}5P.aY=fw},3F:C(){q.4r=1b;q.HO();1j(J i=0;i1){q.ll()}J gN=q.8F;q.8F=1a;J eG=q.f8();J el=e.3B!=1d?e.3B:e.6q;2S(el!=1d&&!q.gA(el))el=el.1v;if(el==1d){q.8F=gN;N}J g8=el;J j4=q.st;if(q.3A.Y==0||(e.b4&&!e.7o&&q.d1)){j4=q.st=g8}if(!e.b4&&!e.7o||!q.d1){J 3b=q.3A;1j(J i=3b.Y-1;i>=0;i--){if(3b[i].aY&&3b[i]!=el)q.fs(3b[i],1a)}q.st=g8;if(!el.aY){q.fs(el,1b)}q.3A=[el]}14 if(q.d1&&e.b4&&!e.7o){q.6O(el,!el.aY);q.st=g8}14 if(q.d1&&e.b4&&e.7o){J ss=q.yM(g8,j4);J 2X=j4;2S(2X!=1d&&2X!=g8){if(!2X.aY&&2X!=el)q.6O(2X,1b);2X=ss?q.k8(2X):q.eM(2X)}if(!el.aY)q.6O(el,1b)}14 if(q.d1&&!e.b4&&e.7o){J ss=q.yM(g8,j4);J 3b=q.3A;1j(J i=3b.Y-1;i>=0;i--)q.fs(3b[i],1a);q.3A=[];J 2X=j4;2S(2X!=1d){q.6O(2X,1b);if(2X==g8)2A;2X=ss?q.k8(2X):q.eM(2X)}}J ai;J 9o=eG.Y!=q.3A.Y;if(!9o){1j(J i=0;i\'))});t8.2g(yi)}t8.2g(2X.7n?\'\':1i.1u(1c 1e(\'a\',{6G:\'#\',3k:2X.a9,1G:(2X.1G||\'\')+(2X.2K?\' 2K\':\' bN\'),1g:(2X.nH?\'vc-10r:10q\':\'\')}),{yh:2X.4g}).cS(\'3V\',\'N 1a;\').2h(\'44\',q.u6.1k(q)).2h(\'fg\',1q.3L).29(\'<2e 1P="\'+2X.7W+\'" 52="0" 1p="16" 1l="16" 6A="aS"> \'+2X.1m));54.2g(t8)}.1k(q));q.3j.2g(54);3C{aK.59(q.3j,q.O.t9,1b)}3P(e){}},3o:C(e){q.O.Dl(e);q.mV();if(!q.O.fB.Y)N;J hq={};fy=q.3j.5U();if(q.O.4L==\'tj\'){hq=q.KG(e)}14{hq=q.KM()}q.3j.1I(hq);q.3j.1I({4N:q.O.4N});if(q.ie){q.mf.1I(1i.1u(1i.1u(fy,hq),{4N:q.O.4N-1})).3o()}if(q.O.e8){1z.kM(q.3j,{4U:0.25,jb:C(e){aK.xb(q.3j,q.O.t9)}.1k(q)})}14{q.3j.3o();aK.xb(q.3j,q.O.t9)}q.1n=e},KG:C(e){J x=1q.4f(e).x,y=1q.4f(e).y,tf=1f.aC.5U(),yf=1f.aC.xr(),fy=q.3j.5U(),hq={1T:((x+fy.1l+q.O.ye)>tf.1l?(tf.1l-fy.1l-q.O.ye):x)+\'px\',1H:((y-yf.1H+fy.1p)>tf.1p&&(y-yf.1H)>fy.1p?(y-fy.1p):y)+\'px\'};N hq},KM:C(){if(q.tk)N q.tk;J tm=2Z.6c($(q.O.4L));J sN=tm[1]+$(q.O.4L).3H()+q.O.fq;J sq=tm[0]+q.O.g5;q.tk={1H:sN+\'px\',1T:sq+\'px\'};N q.tk},gm:C(){if(!q.O.gm||q.O.4L==\'tj\')N;q.O.4L=1c 1e(\'2e\',{id:q.O.4L,1P:q.O.CC,a9:q.O.CE,6A:\'aS\'}).1I({9X:\'4f\'});q.O.CB.1X(q.O.4L);q.O.5x=\'[id="\'+q.O.4L.id+\'"]\'},u6:C(e){if(e.3B.yh&&!e.3B.g2(\'2K\')){q.O.KJ(e);if(q.ie)q.mf.2M();aK.hC(q.3j);q.3j.2M();e.3B.yh(q.1n)}}});BB=2q.2r({2y:C(3j,O){q.O=1i.1u({fc:\'fk\',ys:\'ep\',dh:1B.Zh},1D[1]||{});J Ks={9X:\'e-6w\',yv:\'Zg\',sQ:1q.hD,2u:\'1T\',hv:\'1l\',sV:q.5D,ek:\'5V\',mK:\'Ko\',mI:\'Kn\',m3:\'1p\',yw:q.3H,Kp:\'5y\',my:\'yn\',mr:\'yo\'};J Kt={9X:\'n-6w\',yv:\'Ze\',sQ:1q.hk,2u:\'1H\',hv:\'1p\',sV:q.3H,ek:\'5y\',mK:\'yn\',mI:\'yo\',m3:\'1l\',yw:q.5D,Kp:\'5V\',my:\'Ko\',mr:\'Kn\'};if(q.O.fc==\'fk\')1i.1u(q.O,Ks);14 1i.1u(q.O,Kt);q.5H=$(3j).1I({1K:\'ef\'});J ti=q.5H.Ky();ti.1t(C(1x){1x.1I({1K:\'4Y\',6U:0})});q.6E=ti[0];q.6n=ti[1];q.t1=2f(q.6n.2s(\'Di\'))||0;q.7N=1c 1e(\'1x\',{lk:\'on\'});q.7N.2F(q.O.yv).1I({1K:\'4Y\',9X:q.O.9X,ao:\'fS\'});q.6E.2g({fC:q.7N});q.7N.2h("v1",q.JQ.1k(q));q.IV();q.6E.hZ=(q.O.Bj==1b?2f(q.O.sV(q.6E)):q.O.Bj)||0;q.6n.hZ=(q.O.tz==1b?2f(q.O.sV(q.6n)):q.O.tz)||0;if(q.6n.hZ){q.6n.hZ=q.5H[q.O.ek]-q.5H.rp-q.6n.hZ-q.7N.9O}1q.2h(1L,"6w",C(e){q.tZ(e)}.1k(q));q.tZ(1d,q.6n.hZ||q.6E.hZ||2c.3X((q.5H[q.O.ek]-q.5H.rp-q.7N.9O)/2))},tZ:C(1n,3s,Zd){q.5H.lY=q.O.yw(q.5H)-q.5H.J1;q.5H.9O=q.5H[q.O.ek]-q.5H.rp;if(q.5H.lY<=0||q.5H.9O<=0)N;J sP=q.O.m3;q.6E.1I(q.f2(sP,q.5H.lY-q.6E.rm+\'px\'));J mD=(!1B.2j.IE?(q.t1*2):0);q.6n.1I(q.f2(sP,q.5H.lY-q.6n.rm-mD+\'px\'));q.7N.1I(q.f2(sP,q.5H.lY+\'px\'));q.yr(3s||(!q.O.tz?q.6E[q.O.ek]:q.5H.9O-q.6n[q.O.ek]-q.7N.9O))},JQ:C(1n){q.7N.2F(q.O.ys);q.6E.Je=q.6E[q.O.ek]-q.O.sQ(1n);if(!q.sX){q.sX=q.Jd.1k(q);q.yp=q.Jb.1k(q)}1q.2h(1f,"fW",q.sX);1q.2h(1f,"g3",q.yp)},Jd:C(1n){q.yr(q.6E.Je+q.O.sQ(1n))},Jb:C(1n){q.7N.4n(q.O.ys);1q.60(1f,"fW",q.sX);1q.60(1f,"g3",q.yp)},yr:C(np){np=2c.4X(q.6E.yS+q.6E.kv,q.5H.9O-(q.6n.zm||Jk),16,2c.cR(np,q.6E.zm||Jk,q.5H.9O-q.7N.9O-2c.4X(q.6n.yS+q.6n.kv,16)));J Z1=q.O.2u;J YZ=q.O.hv;q.7N.1I(q.f2(q.O.2u,np+\'px\'));q.6E.1I(q.f2(q.O.hv,np-q.6E.kv+\'px\'));q.6n.1I(q.f2(q.O.2u,np+q.7N.9O+\'px\'));J mD=0;if(!1B.2j.IE&&q.t1){mD=q.t1*2}q.6n.1I(q.f2(q.O.hv,q.5H.9O-q.7N.9O-q.6n.kv-np-mD+"px"));if(!1B.2j.IE){q.6E.8q("6w");q.6n.8q("6w")}if(q.O.dh)q.O.dh()},hA:C(jq,n,pf,m1,m2){J Ji=(!1B.2j.IE||1f.Z4=="Z5");jq[n]=Ji?(2f(jq.2s(pf+m1))||0)+(2f(jq.2s(pf+m2))||0):0},zg:C(jq,zn){jq.yS=2c.4X(0,q.O["cR"+zn]||2f(jq.2s("cR-"+q.O.hv))||0);jq.zm=2c.4X(0,q.O["4X"+zn]||2f(jq.2s("4X-"+q.O.hv))||0)},IV:C(){q.7N.9O=q.7N[q.O.ek];q.hA(q.5H,"rp","52",q.O.mK,q.O.mI);q.hA(q.5H,"J1","52",q.O.my,q.O.mr);q.hA(q.6E,"kv","9j",q.O.mK,q.O.mI);q.hA(q.6E,"rm","9j",q.O.my,q.O.mr);q.hA(q.6n,"kv","9j",q.O.mK,q.O.mI);q.hA(q.6n,"rm","9j",q.O.my,q.O.mr);q.zg(q.6E,\'A\');q.zg(q.6n,\'B\')},5D:C(el){N el.5V},3H:C(el){if(el.5y){N 2f(el.5y)}14{J h=el.3H();if(!h){h=$(el.1v).3H();if(!1B.2j.IE)h-=2f($(el.1v).ZO*2)}N h}},f2:C(JH,JI){J zi={};zi[JH]=JI;N zi}});fF.EF=2q.2r({cx:1R,i4:1R,2y:C(4g){q.i4=4g;J 9A=7Z.4e;q.cx=9A;if(1B.2j.IE){if(q.cx==\'\'){q.cx=\'#\'}gj=1f.4q(\'2B\')[0];J 6a=1c 1e(\'6a\');6a.cS(\'id\',\'mv\').cS("1g","3v:4s;");gj.1X(6a);6a=$("mv").zp.1f;6a.3O();6a.7P();6a.7Z.4e=9A}14 if(1B.2j.6D){q.cE=[];q.cE.Y=nr.Y;q.rq=[];q.mw=1b}1c r8(C(){q.JG()}.1k(q),0.2)},Jq:C(4e){q.cE.1N(4e);q.rq.Y=0;q.mw=1b},JG:C(){if(1B.2j.IE){J 6a=$(\'mv\').ZE||$(\'mv\').zp.1f;J 9A=6a.7Z.4e;if(9A!=q.cx){7Z.4e=9A;q.cx=9A;q.i4(9A.2V(/^#/,\'\'))}}14 if(1B.2j.6D){if(!q.zv){J ms=nr.Y-q.cE.Y;if(ms){q.mw=1a;if(ms<0){1j(J i=0;i<2c.f1(ms);i++)q.rq.Zw(q.cE.JD())}14{1j(J i=0;i=0){q.i4(1f.JO.3Z(\'#\')[1])}14{J 9A=7Z.4e;q.i4(\'\')}q.mw=1b}}}14{J 9A=7Z.4e;if(9A!=q.cx){q.cx=9A;q.i4(9A.2V(/^#/,\'\'))}}},FF:C(4e){J i7;if(1B.2j.6D){i7=4e}14{i7=\'#\'+4e;7Z.4e=i7}q.cx=i7;if(1B.2j.IE){J 6a=$("mv").zp.1f;6a.3O();6a.7P();6a.7Z.4e=i7}14 if(1B.2j.6D){q.zv=1b;q.Jq(4e);J fn=C(){q.zv=1a}.1k(q);1L.5C(fn,eI);7Z.4e=i7}14{}}});J lZ=2q.2r();lZ.1w={kN:"ZC",2y:C(O){q.O={dr:D3,3m:\'\',hX:\'\',dd:\'\'};1i.1u(q.O,O||{});if(q.O.dr!=\'\'){J 7U=1c ba();7U=1c ba(7U.nB()+(q.O.dr*6F));q.O.dr=\'; dr=\'+7U.Jz()}if(q.O.3m!=\'\'){q.O.3m=\'; 3m=\'+hn(q.O.3m)}if(q.O.hX!=\'\'){q.O.hX=\'; hX=\'+hn(q.O.hX)}if(q.O.dd==\'dd\'){q.O.dd=\'; dd\'}14{q.O.dd=\'\'}},oS:C(1m,V){1m=q.kN+1m;6d=q.O;J 1V=28 V;7G(1V){1U\'1R\':1U\'C\':1U\'rw\':N 1a;1U\'Ju\':1U\'56\':1U\'9w\':V=4c(V.55())}J JA=1m+"="+hn(1i.9U(V));3C{1f.6d=JA+6d.dr+6d.3m+6d.hX+6d.dd}3P(e){N 1a}N 1b},42:C(1m){1m=q.kN+1m;6d=q.O;3C{J 7U=1c ba();7U.ZB(7U.nB()-(D3*6F));J dr=\'; dr=\'+7U.Jz();1f.6d=1m+"="+dr+6d.3m+6d.hX+6d.dd}3P(e){N 1a}N 1b},2d:C(1m){1m=q.kN+1m;J 95=1f.6d.1Z(1m+\'=(.*?)(;|$)\');if(95){N(LB(95[1])).hN()}14{N 1d}},gg:C(){5L=q.zx();3s=5L.3s();1j(i=0;i<3s;i++){q.42(5L[i])}},Zz:C(){zw={};5L=q.zx();3s=5L.3s();1j(i=0;i<3s;i++){zw[5L[i]]=q.2d(5L[i])}N zw},zx:C(){5L=$A();DS=/[^=; ]+(?=\\=)/g;6X=1f.6d;E1=1c 8x("^"+q.kN);2S((1Z=DS.zu(6X))!=1R){if(E1.3n(1Z[0].5h())){5L.1N(1Z[0].5h().8G("^"+q.kN,""))}}N 5L}};J bF=7y.bs.3t();J OS,7A,gb,bV,zr;J b3,r3;C DB(){if(9Z(\'12l\')){7A="DG";OS="DZ"}14 if(9Z(\'zt\'))7A="zq";14 if(9Z(\'127\'))7A="11N";14 if(9Z(\'8l\'))7A="9y";14 if(9Z(\'11M\'))7A="11R";14 if(9Z(\'11Z\'))7A="122";14 if(9Z(\'nF\'))7A="ze z3";14 if(!9Z(\'11V\')){7A="125 11W";gb=bF.7u(8)}14 7A="An rw 7A";if(!gb)gb=bF.7u(zs+zr.Y);if(!OS){if(9Z(\'11X\'))OS="DZ";14 if(9Z(\'123\'))OS="121";14 if(9Z(\'Dq\'))OS="11S";14 if(9Z(\'cq\'))OS="11I";14 OS="an rw 11H 11L"}}C 9Z(56){zs=bF.3R(56)+1;zr=56;N zs}1q.2h(1L,\'9u\',2y,1a);1q.2h(1L,\'9u\',DB,1a);1q.2h(1L,\'Lt\',1q.11P,1a);J kP=2q.2r();kP.1w={oQ:0,11O:0,2y:C(id){q.1O=id},8v:C(){if(7A==\'ze z3\'){q.Dx();q.yZ(0,0)}q.yU("bM")},12m:C(1p,5c){gj=1f.4q(\'2B\')[0];gj.1g.5c=5c;gj.1g.1p=1p;q0=1f.4q(\'8L\')[0];q0.1g.5c=5c;q0.1g.1p=1p},12p:C(8P){zf=1f.4q(\'1C\');1j(i=0;i"}3P(e){}J E=5A.3z||1d;if(E&&(E.1E.4F()!=4p))E=E.4q(4p)[0];if(!E)E=1f.2w(4p);if(!E)N;if(1D[1])if(q.r7(1D[1])||(1D[1]yX 3r)||1D[1].1E){q.zb(E,1D[1])}14{J kb=q.Ep(1D[1]);if(kb.Y){3C{5A.2C="<"+4p+" "+kb+">"}3P(e){}E=5A.3z||1d;if(!E){E=1f.2w(4p);1j(5d in 1D[1])E[5d==\'3w\'?\'1G\':5d]=1D[1][5d]}if(E.1E.4F()!=4p)E=5A.4q(4p)[0]}}if(1D[2])q.zb(E,1D[2]);N E},kz:C(26){N 1f.aN(26)},z5:{\'1G\':\'3w\',\'z4\':\'1j\'},Ep:C(3M){J kb=[];1j(4J in 3M)kb.1N((4J in q.z5?q.z5[4J]:4J)+\'="\'+3M[4J].55().ox().8G(/"/,\'&112;\')+\'"\');N kb.57(" ")},zb:C(E,4V){if(4V.1E){E.1X(4V);N}if(28 4V==\'1F\'){4V.9L().1t(C(e){if(28 e==\'1F\')E.1X(e);14 if(gU.r7(e))E.1X(gU.kz(e))})}14 if(gU.r7(4V))E.1X(gU.kz(4V))},r7:C(c3){N(28 c3==\'56\'||28 c3==\'9w\')},oU:C(8L){J E=q.1h(\'1x\');$(E).29(8L.5h());N E.8r()},10S:C(cM){if(28 cM!=\'1F\'&&28 cM!=\'C\')cM=1L;J aZ=("A 10Q 10R 10V 10W El B 110 10Z 10Y 10X 11e tu "+"BR FL zc 11f 11x 11w za z9 DD Eb 11v Ea gw DL DT EM Eg "+"11y A7 11z Ev H1 H2 H3 H4 H5 H6 11A HR rc I EJ r9 pF ET 11i "+"11g 11h ES LI 11l 11m 11q 11p 11o 11n YX OL z6 wY P "+"EH WA Q S WD WE uy WJ WI WH WF WG Wx Ww u4 gs TD "+"tP rZ TH s0 Wm TR TT U UL Wq").3Z(/\\s+/);aZ.1t(C(6Z){cM[6Z]=C(){N gU.1h.7D(gU,[6Z].4W($A(1D)))}})}};4c.1w.fL=C(){J 4b=\'#\';if(q.6i(0,4)==\'bY(\'){J kX=q.6i(4,q.Y-1).3Z(\',\');J i=0;do{4b+=2f(kX[i]).ic()}2S(++i<3)}14{if(q.6i(0,1)==\'#\'){if(q.Y==4)1j(J i=1;i<4;i++)4b+=(q.7u(i)+q.7u(i)).3t();if(q.Y==7)4b=q.3t()}}N(4b.Y==7?4b:(1D[0]||q))};1e.ur=C(E){N $A($(E).1o).ko(C(1h){N(1h.5s==3?1h.4i:(1h.un()?1e.ur(1h):\'\'))}).9L().57(\'\')};1e.ux=C(E,1G){N $A($(E).1o).ko(C(1h){N(1h.5s==3?1h.4i:((1h.un()&&!1e.g2(1h,1G))?1e.ux(1h,1G):\'\'))}).9L().57(\'\')};1e.Fc=C(E,hz){E=$(E);E.1I({ao:(hz/100)+\'em\'});if(1B.2j.6D)1L.Fu(0,0);N E};1e.ea=C(E){N $(E).1g.3W||\'\'};1e.wS=C(E){3C{E=$(E);J n=1f.aN(\' \');E.1X(n);E.5B(n)}3P(e){}};J 1z={iM:{1m:\'Wu\',6T:\'Wt E7 Wr E Ae 9B Ws, WK is X4 1j q 1A to X3\'},a6:{E6:1B.K,i8:C(2t){N(-2c.bo(2t*2c.PI)/2)+0.5},b2:C(2t){N 1-2t},Ge:C(2t){J 2t=((-2c.bo(2t*2c.PI)/4)+0.75)+2c.X2()/4;N 2t>1?1:2t},X0:C(2t){N(-2c.bo(2t*2c.PI*(9*2t))/2)+0.5},G3:C(2t,cK){cK=cK||5;N(((2t%(1/cK))*cK).3X()==0?((2t*cK*2)-(2t*cK*2).yd()):1-((2t*cK*2)-(2t*cK*2).yd()))},X5:C(2t){N 1-(2c.bo(2t*4.5*2c.PI)*2c.X6(-2t*6))},4s:C(2t){N 0},FX:C(2t){N 1}},hE:{4U:1.0,DY:100,8S:1a,6M:0.0,to:1.0,74:0.0,6v:\'Xa\'},X9:C(E){J yc=\'1K:ef\';if(1B.2j.IE)yc+=\';fm:1\';E=$(E);$A(E.1o).1t(C(2P){if(2P.5s==3){2P.4i.9f().1t(C(km){E.6S(1c 1e(\'9Q\',{1g:yc}).29(km==\' \'?4c.tv(L8):km),2P)});1e.42(2P)}})},iy:C(E,1A){J 2T;if(((28 E==\'1F\')||1i.5w(E))&&(E.Y))2T=E;14 2T=$(E).1o;J O=1i.1u({9S:0.1,74:0.0},1D[2]||{});J Dw=O.74;$A(2T).1t(C(E,1y){1c 1A(E,1i.1u(O,{74:1y*O.9S+Dw}))})},xg:{\'yY\':[\'Gf\',\'G6\'],\'WZ\':[\'Gg\',\'D0\'],\'wV\':[\'kM\',\'lr\']},bk:C(E,1A){E=$(E);1A=(1A||\'wV\').3t();J O=1i.1u({6v:{1K:\'7M\',cM:(E.id||\'s8\'),xj:1}},1D[2]||{});1z[E.fT()?1z.xg[1A][1]:1z.xg[1A][0]](E,O)}};1z.hE.8b=1z.a6.i8;1z.Dt=2q.2r(7E,{2y:C(){q.4O=[];q.oZ=1d},b5:C(2b){q.4O.b5(2b)},5G:C(1A){J gH=1c ba().nB();J 1K=1i.5S(1A.O.6v)?1A.O.6v:1A.O.6v.1K;7G(1K){1U\'WM\':q.4O.gv(C(e){N e.5W==\'iK\'}).1t(C(e){e.eT+=1A.eS;e.eS+=1A.eS});2A;1U\'hm-4o\':gH=q.4O.eQ(\'eT\').4X()||gH;2A;1U\'7M\':gH=q.4O.eQ(\'eS\').4X()||gH;2A}1A.eT+=gH;1A.eS+=gH;if(!1A.O.6v.xj||(q.4O.Y<1A.O.6v.xj))q.4O.1N(1A);if(!q.oZ)q.oZ=ld(q.p2.1k(q),15)},42:C(1A){q.4O=q.4O.gZ(C(e){N e==1A});if(q.4O.Y==0){kB(q.oZ);q.oZ=1d}},p2:C(){J io=1c ba().nB();1j(J i=0,p0=q.4O.Y;i=q.eT){if(io>=q.eS){q.cv(1.0);q.dZ();q.1n(\'DK\');if(q.hJ)q.hJ();q.1n(\'jb\');N}J 2t=(io-q.eT)/q.E3,xa=(2t*q.E2).3X();if(xa>q.xe){q.cv(2t);q.xe=xa}}},dZ:C(){if(!q.O.8S)1z.sa.2d(1i.5S(q.O.6v)?\'s8\':q.O.6v.cM).42(q);q.5W=\'BH\'},1n:C(2E){if(q.O[2E+\'ts\'])q.O[2E+\'ts\'](q);if(q.O[2E])q.O[2E](q)},5T:C(){J c9=$H();1j(2L in q)if(!1i.5w(q[2L]))c9.2u(2L,q[2L]);N\'#<1z:\'+c9.5T()+\',O:\'+$H(q.O).5T()+\'>\'}});1z.iO=2q.2r(1z.7d,{2y:C(4O){q.4O=4O||[];q.5f(1D[1])},29:C(1K){q.4O.8n(\'cv\',1K)},hJ:C(1K){q.4O.1t(C(1A){1A.cv(1.0);1A.dZ();1A.1n(\'DK\');if(1A.hJ)1A.hJ(1K);1A.1n(\'jb\')})}});1z.Gi=2q.2r(1z.7d,{2y:C(1F,6M,to){1F=1i.5S(1F)?$(1F):1F;J 4u=$A(1D),3e=4u.4o(),O=4u.Y==5?4u[3]:1d;q.3e=1i.5w(3e)?3e.1k(1F):1i.5w(1F[3e])?1F[3e].1k(1F):C(V){1F[3e]=V};q.5f(1i.1u({6M:6M,to:to},O||{}))},29:C(1K){q.3e(1K)}});1z.1q=2q.2r(1z.7d,{2y:C(){q.5f(1i.1u({4U:0},1D[0]||{}))},29:1B.79});1z.bh=2q.2r(1z.7d,{2y:C(E){q.E=$(E);if(!q.E)73(1z.iM);if(1B.2j.IE&&(!q.E.c6.x9))q.E.1I({fm:1});J O=1i.1u({6M:q.E.iP()||0.0,to:1.0},1D[1]||{});q.5f(O)},29:C(1K){q.E.e5(1K)}});1z.9C=2q.2r(1z.7d,{2y:C(E){q.E=$(E);if(!q.E)73(1z.iM);J O=1i.1u({x:0,y:0,5r:\'ef\'},1D[1]||{});q.5f(O)},iI:C(){q.E.aR();q.o0=82(q.E.2s(\'1T\')||\'0\');q.o1=82(q.E.2s(\'1H\')||\'0\');if(q.O.5r==\'4Y\'){q.O.x=q.O.x-q.o0;q.O.y=q.O.y-q.o1}},29:C(1K){q.E.1I({1T:(q.O.x*1K+q.o0).3X()+\'px\',1H:(q.O.y*1K+q.o1).3X()+\'px\'})}});1z.VM=C(E,DH,DJ){N 1c 1z.9C(E,1i.1u({x:DJ,y:DH},1D[3]||{}))};1z.ab=2q.2r(1z.7d,{2y:C(E,hz){q.E=$(E);if(!q.E)73(1z.iM);J O=1i.1u({bX:1b,o3:1b,cj:1b,rJ:1a,ck:\'xn\',h5:100.0,DI:hz},1D[2]||{});q.5f(O)},iI:C(){q.aQ=q.O.aQ||1a;q.GM=q.E.2s(\'1K\');q.xc={};[\'1H\',\'1T\',\'1l\',\'1p\',\'ao\'].1t(C(k){q.xc[k]=q.E.1g[k]}.1k(q));q.o1=q.E.8j;q.o0=q.E.8Q;J ao=q.E.2s(\'vc-3s\')||\'100%\';[\'em\',\'px\',\'%\',\'pt\'].1t(C(nY){if(ao.3R(nY)>0){q.ao=82(ao);q.nY=nY}}.1k(q));q.DN=(q.O.DI-q.O.h5)/100;q.3I=1d;if(q.O.ck==\'xn\')q.3I=[q.E.5y,q.E.5V];if(/^1O/.3n(q.O.ck))q.3I=[q.E.xs,q.E.Vv];if(!q.3I)q.3I=[q.O.ck.h8,q.O.ck.h4]},29:C(1K){J s7=(q.O.h5/100.0)+(q.DN*1K);if(q.O.cj&&q.ao)q.E.1I({ao:q.ao*s7+q.nY});q.Ew(q.3I[0]*s7,q.3I[1]*s7)},hJ:C(1K){if(q.aQ)q.E.1I(q.xc)},Ew:C(1p,1l){J d={};if(q.O.bX)d.1l=1l.3X()+\'px\';if(q.O.o3)d.1p=1p.3X()+\'px\';if(q.O.rJ){J xd=(1p-q.3I[0])/2;J xk=(1l-q.3I[1])/2;if(q.GM==\'4Y\'){if(q.O.o3)d.1H=q.o1-xd+\'px\';if(q.O.bX)d.1T=q.o0-xk+\'px\'}14{if(q.O.o3)d.1H=-xd+\'px\';if(q.O.bX)d.1T=-xk+\'px\'}}q.E.1I(d)}});1z.qb=2q.2r(1z.7d,{2y:C(E){q.E=$(E);if(!q.E)73(1z.iM);J O=1i.1u({q9:\'#Ni\'},1D[1]||{});q.5f(O)},iI:C(){if(q.E.2s(\'3v\')==\'4s\'){q.dZ();N}q.8m={};if(!q.O.xm){q.8m.G9=q.E.2s(\'7z-7W\');q.E.1I({G9:\'4s\'})}if(!q.O.qg)q.O.qg=q.E.2s(\'7z-4b\').fL(\'#pY\');if(!q.O.qm)q.O.qm=q.E.2s(\'7z-4b\');q.xl=$R(0,2).4G(C(i){N 2f(q.O.q9.6i(i*2+1,i*2+3),16)}.1k(q));q.G8=$R(0,2).4G(C(i){N 2f(q.O.qg.6i(i*2+1,i*2+3),16)-q.xl[i]}.1k(q))},29:C(1K){q.E.1I({7C:$R(0,2).9N(\'#\',C(m,v,i){N m+((q.xl[i]+(q.G8[i]*1K)).3X().ic())}.1k(q))})},hJ:C(){q.E.1I(1i.1u(q.8m,{7C:q.O.qm}))}});1z.Vy=C(E){J O=1D[1]||{},xq=1f.aC.xr(),rF=$(E).6c(),4X=(1L.1p||1f.2B.xs)-1f.aC.3H();if(O.51)rF[1]+=O.51;N 1c 1z.Gi(1d,xq.1H,rF[1]>4X?4X:rF[1],O,C(p){kH(xq.1T,p.3X())})};1z.lr=C(E){E=$(E);J iD=E.ea();J O=1i.1u({6M:E.iP()||1.0,to:0.0,5n:C(1A){if(1A.O.to!=0)N;1A.E.2M().1I({3W:iD})}},1D[1]||{});N 1c 1z.bh(E,O)};1z.kM=C(E){E=$(E);J O=1i.1u({6M:(E.2s(\'3v\')==\'4s\'?0.0:E.iP()||0.0),to:1.0,5n:C(1A){1A.E.wS()},hc:C(1A){1A.E.e5(1A.O.6M).3o()}},1D[1]||{});N 1c 1z.bh(E,O)};1z.W9=C(E){E=$(E);J 8m={3W:E.ea(),1K:E.2s(\'1K\'),1H:E.1g.1H,1T:E.1g.1T,1l:E.1g.1l,1p:E.1g.1p};N 1c 1z.iO([1c 1z.ab(E,eI,{8S:1b,rJ:1b,cj:1b,aQ:1b}),1c 1z.bh(E,{8S:1b,to:0.0})],1i.1u({4U:1.0,W7:C(1A){2Z.bT(1A.4O[0].E)},5n:C(1A){1A.4O[0].E.2M().1I(8m)}},1D[1]||{}))};1z.D0=C(E){E=$(E);E.c2();N 1c 1z.ab(E,0,1i.1u({cj:1a,bX:1a,aQ:1b,5n:C(1A){1A.E.2M().cb()}},1D[1]||{}))};1z.Gg=C(E){E=$(E);J dq=E.5U();N 1c 1z.ab(E,100,1i.1u({cj:1a,bX:1a,h5:0,ck:{h8:dq.1p,h4:dq.1l},aQ:1b,rQ:C(1A){1A.E.c2().1I({1p:\'ce\'}).3o()},5n:C(1A){1A.E.cb()}},1D[1]||{}))};1z.Wc=C(E){E=$(E);J iD=E.ea();N 1c 1z.kM(E,1i.1u({4U:0.4,6M:0,8b:1z.a6.Ge,5n:C(1A){1c 1z.ab(1A.E,1,{4U:0.3,rJ:1b,bX:1a,cj:1a,aQ:1b,hc:C(1A){1A.E.aR().c2()},5n:C(1A){1A.E.2M().cb().ct().1I({3W:iD})}})}},1D[1]||{}))};1z.Wh=C(E){E=$(E);J 8m={1H:E.2s(\'1H\'),1T:E.2s(\'1T\'),3W:E.ea()};N 1c 1z.iO([1c 1z.9C(E,{x:0,y:100,8S:1b}),1c 1z.bh(E,{8S:1b,to:0.0})],1i.1u({4U:0.5,hc:C(1A){1A.4O[0].E.aR()},5n:C(1A){1A.4O[0].E.2M().ct().1I(8m)}},1D[1]||{}))};1z.Wg=C(E){E=$(E);J O=1i.1u({7F:20,4U:0.5},1D[1]||{});J 7F=82(O.7F);J 3Z=82(O.4U)/10.0;J 8m={1H:E.2s(\'1H\'),1T:E.2s(\'1T\')};N 1c 1z.9C(E,{x:7F,y:0,4U:3Z,5n:C(1A){1c 1z.9C(1A.E,{x:-7F*2,y:0,4U:3Z*2,5n:C(1A){1c 1z.9C(1A.E,{x:7F*2,y:0,4U:3Z*2,5n:C(1A){1c 1z.9C(1A.E,{x:-7F*2,y:0,4U:3Z*2,5n:C(1A){1c 1z.9C(1A.E,{x:7F*2,y:0,4U:3Z*2,5n:C(1A){1c 1z.9C(1A.E,{x:-7F,y:0,4U:3Z,5n:C(1A){1A.E.ct().1I(8m)}})}})}})}})}})}})};1z.Gf=C(E){E=$(E).j1();J rR=E.8r().2s(\'4A\');J dq=E.5U();N 1c 1z.ab(E,100,1i.1u({cj:1a,bX:1a,h5:1L.8l?0:1,ck:{h8:dq.1p,h4:dq.1l},aQ:1b,rQ:C(1A){1A.E.aR();1A.E.8r().aR();if(1L.8l)1A.E.1I({1H:\'\'});1A.E.c2().1I({1p:\'ce\'}).3o()},FW:C(1A){1A.E.8r().1I({4A:(1A.3I[0]-1A.E.jV)+\'px\'})},5n:C(1A){1A.E.cb().ct();1A.E.8r().ct().1I({4A:rR})}},1D[1]||{}))};1z.G6=C(E){E=$(E).j1();J rR=E.8r().2s(\'4A\');J dq=E.5U();N 1c 1z.ab(E,1L.8l?0:1,1i.1u({cj:1a,bX:1a,ck:\'xn\',h5:100,ck:{h8:dq.1p,h4:dq.1l},aQ:1b,rQ:C(1A){1A.E.aR();1A.E.8r().aR();if(1L.8l)1A.E.1I({1H:\'\'});1A.E.c2().3o()},FW:C(1A){1A.E.8r().1I({4A:(1A.3I[0]-1A.E.jV)+\'px\'})},5n:C(1A){1A.E.2M().cb().ct();1A.E.8r().ct().1I({4A:rR})}},1D[1]||{}))};1z.VV=C(E){N 1c 1z.ab(E,1L.8l?1:0,{aQ:1b,hc:C(1A){1A.E.c2()},5n:C(1A){1A.E.2M().cb()}})};1z.VT=C(E){E=$(E);J O=1i.1u({fc:\'du\',tq:1z.a6.i8,rN:1z.a6.i8,rM:1z.a6.FX},1D[1]||{});J 8m={1H:E.1g.1H,1T:E.1g.1T,1p:E.1g.1p,1l:E.1g.1l,3W:E.ea()};J 3I=E.5U();J hj,h6;J 9e,93;7G(O.fc){1U\'1H-1T\':hj=h6=9e=93=0;2A;1U\'1H-6C\':hj=3I.1l;h6=93=0;9e=-3I.1l;2A;1U\'4A-1T\':hj=9e=0;h6=3I.1p;93=-3I.1p;2A;1U\'4A-6C\':hj=3I.1l;h6=3I.1p;9e=-3I.1l;93=-3I.1p;2A;1U\'du\':hj=3I.1l/2;h6=3I.1p/2;9e=-3I.1l/2;93=-3I.1p/2;2A}N 1c 1z.9C(E,{x:hj,y:h6,4U:0.FU,hc:C(1A){1A.E.2M().c2().aR()},5n:C(1A){1c 1z.iO([1c 1z.bh(1A.E,{8S:1b,to:1.0,6M:0.0,8b:O.rM}),1c 1z.9C(1A.E,{x:9e,y:93,8S:1b,8b:O.tq}),1c 1z.ab(1A.E,100,{ck:{h8:3I.1p,h4:3I.1l},8S:1b,h5:1L.8l?1:0,8b:O.rN,aQ:1b})],1i.1u({hc:C(1A){1A.4O[0].E.1I({1p:\'ce\'}).3o()},5n:C(1A){1A.4O[0].E.cb().ct().1I(8m)}},O))}})};1z.W4=C(E){E=$(E);J O=1i.1u({fc:\'du\',tq:1z.a6.i8,rN:1z.a6.i8,rM:1z.a6.4s},1D[1]||{});J 8m={1H:E.1g.1H,1T:E.1g.1T,1p:E.1g.1p,1l:E.1g.1l,3W:E.ea()};J 3I=E.5U();J 9e,93;7G(O.fc){1U\'1H-1T\':9e=93=0;2A;1U\'1H-6C\':9e=3I.1l;93=0;2A;1U\'4A-1T\':9e=0;93=3I.1p;2A;1U\'4A-6C\':9e=3I.1l;93=3I.1p;2A;1U\'du\':9e=3I.1l/2;93=3I.1p/2;2A}N 1c 1z.iO([1c 1z.bh(E,{8S:1b,to:0.0,6M:1.0,8b:O.rM}),1c 1z.ab(E,1L.8l?1:0,{8S:1b,8b:O.rN,aQ:1b}),1c 1z.9C(E,{x:9e,y:93,8S:1b,8b:O.tq})],1i.1u({Xb:C(1A){1A.4O[0].E.aR().c2()},5n:C(1A){1A.4O[0].E.2M().cb().ct().1I(8m)}},O))};1z.Yo=C(E){E=$(E);J O=1D[1]||{};J iD=E.ea();J 8b=O.8b||1z.a6.i8;J xo=C(2t){N 8b(1-1z.a6.G3(2t,O.cK))};xo.1k(8b);N 1c 1z.bh(E,1i.1u(1i.1u({4U:2.0,6M:0,5n:C(1A){1A.E.1I({3W:iD})}},O),{8b:xo}))};1z.Yv=C(E){E=$(E);J 8m={1H:E.1g.1H,1T:E.1g.1T,1l:E.1g.1l,1p:E.1g.1p};E.c2();N 1c 1z.ab(E,5,1i.1u({cj:1a,bX:1a,5n:C(1A){1c 1z.ab(E,1,{cj:1a,o3:1a,5n:C(1A){1A.E.2M().cb().1I(8m)}})}},1D[1]||{}))};1z.mc=2q.2r(1z.7d,{2y:C(E){q.E=$(E);if(!q.E)73(1z.iM);J O=1i.1u({1g:{}},1D[1]||{});if(!1i.5S(O.1g))q.1g=$H(O.1g);14{if(O.1g.4j(\':\'))q.1g=O.1g.Gr();14{q.E.2F(O.1g);q.1g=$H(q.E.o9());q.E.4n(O.1g);J aj=q.E.o9();q.1g=q.1g.gZ(C(1g){N 1g.V==aj[1g.1Y]});O.5n=C(1A){1A.E.2F(1A.O.1g);1A.v6.1t(C(5i){1A.E.1g[5i.1g]=\'\'})}}}q.5f(O)},iI:C(){C fL(4b){if(!4b||[\'Y8(0, 0, 0, 0)\',\'q3\'].4j(4b))4b=\'#pY\';4b=4b.fL();N $R(0,2).4G(C(i){N 2f(4b.6i(i*2+1,i*2+3),16)})}q.v6=q.1g.4G(C(2k){J 2L=2k[0],V=2k[1],bL=1d;if(V.fL(\'#GD\')!=\'#GD\'){V=V.fL();bL=\'4b\'}14 if(2L==\'3W\'){V=82(V);if(1B.2j.IE&&(!q.E.c6.x9))q.E.1I({fm:1})}14 if(1e.Gn.3n(V)){J v5=V.1Z(/^([\\+\\-]?[0-9\\.]+)(.*)$/);V=82(v5[1]);bL=(v5.Y==3)?v5[2]:1d}J 8Y=q.E.2s(2L);N{1g:2L.o8(),8Y:bL==\'4b\'?fL(8Y):82(8Y||0),gx:bL==\'4b\'?fL(V):V,bL:bL}}.1k(q)).gZ(C(5i){N((5i.8Y==5i.gx)||(5i.bL!=\'4b\'&&(v2(5i.8Y)||v2(5i.gx))))})},29:C(1K){J 1g={},5i,i=q.v6.Y;2S(i--)1g[(5i=q.v6[i]).1g]=5i.bL==\'4b\'?\'#\'+(2c.3X(5i.8Y[0]+(5i.gx[0]-5i.8Y[0])*1K)).ic()+(2c.3X(5i.8Y[1]+(5i.gx[1]-5i.8Y[1])*1K)).ic()+(2c.3X(5i.8Y[2]+(5i.gx[2]-5i.8Y[2])*1K)).ic():(5i.8Y+(5i.gx-5i.8Y)*1K).Yg(3)+(5i.bL===1d?\'\':5i.bL);q.E.1I(1g,1b)}});1z.Yf=2q.2r({2y:C(gl){q.gl=[];q.O=1D[1]||{};q.GJ(gl)},GJ:C(gl){gl.1t(C(eb){eb=$H(eb);J c9=eb.4y().8E();q.gl.1N($H({ou:eb.5L().8E(),1A:1z.mc,O:{1g:c9}}))}.1k(q));N q},p7:C(){N 1c 1z.iO(q.gl.4G(C(eb){J ou=eb.2d(\'ou\'),1A=eb.2d(\'1A\'),O=eb.2d(\'O\');J 2T=[$(ou)||$$(ou)].9L();N 2T.4G(C(e){N 1c 1A(e,1i.1u({8S:1b},O))})}).9L(),q.O)}});1e.uD=$w(\'7C Ye Yw Yx \'+\'YQ YP YO YM \'+\'OU YN YR YS \'+\'YW YV YU 4A YT 4b \'+\'ao YL 1p 1T YK YC \'+\'9T YB YA 7H Yy sS \'+\'Yz YD YE 3W YJ YI \'+\'YH CQ OO OT Ce \'+\'6C YF 1H 1l YG 4N\');1e.Gn=/^(([\\+\\-]?[0-9\\.]+)(em|ex|px|in|cm|mm|pt|pc|\\%))|0$/;4c.wT=1f.2w(\'1x\');4c.1w.Gr=C(){J 1g,uG=$H();if(1B.2j.6D)1g=1c 1e(\'1x\',{1g:q}).1g;14{4c.wT.2C=\'<1x 1g="\'+q+\'">\';1g=4c.wT.1o[0].1g}1e.uD.1t(C(2L){if(1g[2L])uG.2u(2L,1g[2L])});if(1B.2j.IE&&q.4j(\'3W\'))uG.2u(\'3W\',q.1Z(/3W:\\s*((?:0|1)?(?:\\.\\d*)?)/)[1]);N uG};if(1f.og&&1f.og.wU){1e.o9=C(E){J aj=1f.og.wU($(E),1d);N 1e.uD.9N({},C(7O,2L){7O[2L]=aj[2L];N 7O})}}14{1e.o9=C(E){E=$(E);J aj=E.c6,7O;7O=1e.uD.9N({},C(4e,2L){4e.2u(2L,aj[2L]);N 4e});if(!7O.3W)7O.2u(\'3W\',E.iP());N 7O}};1z.2m={BI:C(E,1g){E=$(E);1c 1z.mc(E,1i.1u({1g:1g},1D[2]||{}));N E},XB:C(E,1A,O){E=$(E);J s=1A.FR().o8(),4K=s.7u(0).4F()+s.5Y(1);1c 1z[4K](E,O);N E},Xy:C(E,O){E=$(E);1c 1z.qb(E,O);N E}};$w(\'e8 wV Xz Xq Xp Xh Xg Xf Xd \'+\'Xe Xi Xj Xo Xn Xm\').1t(C(1A){1z.2m[1A]=C(E,O){E=$(E);1z[1A.7u(0).4F()+1A.5Y(1)](E,O);N E}});$w(\'ea wS Fc ur ux o9\').1t(C(f){1z.2m[f]=1e[f]});1e.iG(1z.2m);if(1i.f6(1z))73("Ki.js zd Qd 5j.Qf.us\' 4O.js Qb");J 6x={bW:[],42:C(E){q.bW=q.bW.gZ(C(d){N d.E==$(E)})},5G:C(E){E=$(E);J O=1i.1u({XX:1b,bG:1d,3S:1a},1D[1]||{});if(O.bf){O.md=[];J bf=O.bf;if(1i.cD(bf)){bf.1t(C(c){O.md.1N($(c))})}14{O.md.1N($(bf))}}if(O.jR)O.jR=[O.jR].9L();1e.aR(E);O.E=E;q.bW.1N(O)},F9:C(bW){uV=bW[0];1j(i=1;i0)4a=6x.F9(uR);if(q.9m&&q.9m!=4a)q.e4(q.9m);if(4a){2Z.lO(4a.E,dX[0],dX[1]);if(4a.dC)4a.dC(E,4a.E,2Z.6J(4a.6J,4a.E));if(4a!=q.9m)6x.8v(4a)}},8q:C(1n,E){if(!q.9m)N;2Z.c7();2Z.kD=1b;if(q.wO([1q.hD(1n),1q.hk(1n)],E,q.9m))if(q.9m.Db){q.9m.Db(E,q.9m.E,1n);N 1b}},cT:C(){if(q.9m)q.e4(q.9m)}};J 4v={ir:[],iE:[],uI:C(7B){if(q.ir.Y==0){q.iF=q.tL.9g(q);q.iu=q.tN.9g(q);q.wP=q.tK.9g(q);1q.2h(1f,"g3",q.iF);1q.2h(1f,"fW",q.iu);1q.2h(1f,"rU",q.wP)}q.ir.1N(7B)},x4:C(7B){q.ir=q.ir.gZ(C(d){N d==7B});if(q.ir.Y==0){1q.60(1f,"g3",q.iF);1q.60(1f,"fW",q.iu);1q.60(1f,"rU",q.wP)}},8v:C(7B){if(7B.O.74){q.lE=5C(C(){4v.lE=1d;1L.3F();4v.cX=7B}.1k(q),7B.O.74)}14{1L.3F();q.cX=7B}},e4:C(){q.cX=1d},tN:C(1n){if(!q.cX)N;J 4f=[1q.hD(1n),1q.hk(1n)];if(q.jh&&(q.jh.5T()==4f.5T()))N;q.jh=4f;q.cX.tN(1n,4f)},tL:C(1n){if(q.lE){9J(q.lE);q.lE=1d}if(!q.cX)N;q.jh=1d;q.cX.tL(1n);q.cX=1d},tK:C(1n){if(q.cX)q.cX.tK(1n)},pr:C(91){q.iE.1N(91);q.wW()},CY:C(E){q.iE=q.iE.gZ(C(o){N o.E==E});q.wW()},gn:C(2E,7B,1n){if(q[2E+\'EX\']>0)q.iE.1t(C(o){if(o[2E])o[2E](2E,7B,1n)});if(7B.O[2E])7B.O[2E](7B,1n)},wW:C(){[\'pE\',\'nP\',\'dh\'].1t(C(2E){4v[2E+\'EX\']=4v.iE.1C(C(o){N o[2E]}).Y})}};J dW=2q.2r({2y:C(E){J x6={2N:1a,e6:C(E,x5,wX){J F6=2c.Os(2c.f1(x5^2)+2c.f1(wX^2))*0.XR;1c 1z.9C(E,{x:-wX,y:-x5,4U:F6,6v:{cM:\'F5\',1K:\'7M\'}})},cf:C(E){J F4=1i.lg(E.uE)?E.uE:1.0;1c 1z.bh(E,{4U:0.2,6M:0.7,to:F4,6v:{cM:\'F5\',1K:\'7M\'},jb:C(){dW.lz[E]=1a}})},bQ:6F,6u:1a,hF:1a,3K:1a,aO:20,8z:15,dU:1a,74:0};if(!1D[1]||1i.f6(1D[1].cf))1i.1u(x6,{dT:C(E){E.uE=1e.iP(E);dW.lz[E]=1b;1c 1z.bh(E,{4U:0.2,6M:E.uE,to:0.7})}});J O=1i.1u(x6,1D[1]||{});q.E=$(E);if(O.2N&&1i.5S(O.2N))q.2N=q.E.8r(\'.\'+O.2N,0);if(!q.2N)q.2N=$(O.2N);if(!q.2N)q.2N=q.E;if(O.3K&&!O.3K.kH&&!O.3K.x7){O.3K=$(O.3K);q.xS=1e.FH(q.E,O.3K)}1e.aR(q.E);q.O=O;q.hx=1a;q.la=q.FJ.9g(q);1q.2h(q.2N,"v1",q.la);4v.uI(q)},a2:C(){1q.60(q.2N,"v1",q.la);4v.x4(q)},jB:C(){N([2f(1e.2s(q.E,\'1T\')||\'0\'),2f(1e.2s(q.E,\'1H\')||\'0\')])},FJ:C(1n){if(!1i.f6(dW.lz[q.E])&&dW.lz[q.E])N;if(1q.FM(1n)){J 1P=1q.E(1n);if((kK=1P.1E.4F())&&(kK==\'pF\'||kK==\'uy\'||kK==\'wY\'||kK==\'FL\'||kK==\'tP\'))N;J 4f=[1q.hD(1n),1q.hk(1n)];J 2t=2Z.6c(q.E);q.51=[0,1].4G(C(i){N(4f[i]-2t[i])});4v.8v(q);1q.3L(1n)}},CK:C(1n){q.hx=1b;if(!q.5M)q.5M=q.jB();if(q.O.bQ){q.qA=2f(1e.2s(q.E,\'z-1y\')||0);q.E.1g.4N=q.O.bQ}if(q.O.aI){q.62=q.E.9b(1b);q.E.tM=(q.E.2s(\'1K\')==\'4Y\');if(!q.E.tM)2Z.bT(q.E);q.E.1v.6S(q.62,q.E)}if(q.O.3K){if(q.O.3K==1L){J jO=q.nm(q.O.3K);q.nq=jO.1T;q.ng=jO.1H}14{q.nq=q.O.3K.8u;q.ng=q.O.3K.5E}}4v.gn(\'pE\',q,1n);if(q.O.dT)q.O.dT(q.E)},tN:C(1n,4f){if(!q.hx)q.CK(1n);if(!q.O.hF){2Z.c7();2Z.kD=1b;6x.3o(4f,q.E)}4v.gn(\'dh\',q,1n);q.xU(4f);if(q.O.gG)q.O.gG(q);if(q.O.3K){q.xv();J p;if(q.O.3K==1L){hm(q.nm(q.O.3K)){p=[1T,1H,1T+1l,1H+1p]}}14{p=2Z.jE(q.O.3K);p[0]+=q.O.3K.8u+2Z.tQ;p[1]+=q.O.3K.5E+2Z.tR;p.1N(p[0]+q.O.3K.5V);p.1N(p[1]+q.O.3K.5y)}J 9S=[0,0];if(4f[0]<(p[0]+q.O.aO))9S[0]=4f[0]-(p[0]+q.O.aO);if(4f[1]<(p[1]+q.O.aO))9S[1]=4f[1]-(p[1]+q.O.aO);if(4f[0]>(p[2]-q.O.aO))9S[0]=4f[0]-(p[2]-q.O.aO);if(4f[1]>(p[3]-q.O.aO))9S[1]=4f[1]-(p[3]-q.O.aO);q.P3(9S)}if(1B.2j.6D)1L.Fu(0,0);1q.3L(1n)},pG:C(1n,9t){q.hx=1a;if(q.O.hF){2Z.c7();2Z.kD=1b;J 4f=[1q.hD(1n),1q.hk(1n)];6x.3o(4f,q.E)}if(q.O.aI){if(!q.E.tM)2Z.eZ(q.E);bH q.E.tM;1e.42(q.62);q.62=1d}J a8=1a;if(9t){a8=6x.8q(1n,q.E);if(!a8)a8=1a}if(a8&&q.O.qB)q.O.qB(q.E);4v.gn(\'nP\',q,1n);J 6u=q.O.6u;if(6u&&1i.5w(6u))6u=6u(q.E);J d=q.jB();if(6u&&q.O.e6){if(a8==0||6u!=\'nL\')q.O.e6(q.E,d[1]-q.5M[1],d[0]-q.5M[0])}14{q.5M=d}if(q.O.bQ)q.E.1g.4N=q.qA;if(q.O.cf)q.O.cf(q.E);4v.e4(q);6x.cT()},tK:C(1n){if(1n.31!=1q.pI)N;q.pG(1n,1a);1q.3L(1n)},tL:C(1n){if(!q.hx)N;q.xv();q.pG(1n,1b);1q.3L(1n)},xU:C(dX){J 2t=2Z.6c(q.E);if(q.O.aI){J r=2Z.Fy(q.E);2t[0]+=r[0]-2Z.tQ;2t[1]+=r[1]-2Z.tR}J d=q.jB();2t[0]-=d[0];2t[1]-=d[1];if(q.O.3K&&(q.O.3K!=1L&&q.xS)){2t[0]-=q.O.3K.8u-q.nq;2t[1]-=q.O.3K.5E-q.ng}J p=[0,1].4G(C(i){N(dX[i]-2t[i]-q.51[i])}.1k(q));if(q.O.dU){if(1i.5w(q.O.dU)){p=q.O.dU(p[0],p[1],q)}14{if(1i.cD(q.O.dU)){p=p.4G(C(v,i){N(v/q.O.dU[i]).3X()*q.O.dU[i]}.1k(q))}14{p=p.4G(C(v){N(v/q.O.dU).3X()*q.O.dU}.1k(q))}}}J 1g=q.E.1g;if((!q.O.hG)||(q.O.hG==\'cy\'))1g.1T=p[0]+"px";if((!q.O.hG)||(q.O.hG==\'fk\'))1g.1H=p[1]+"px";if(1g.8P=="3N")1g.8P=""},xv:C(){if(q.tX){kB(q.tX);q.tX=1d;4v.c4=1d}},P3:C(9S){if(!(9S[0]||9S[1]))N;q.8z=[9S[0]*q.O.8z,9S[1]*q.O.8z];q.xV=1c ba();q.tX=ld(q.3K.1k(q),10)},3K:C(){J 98=1c ba();J 5M=98-q.xV;q.xV=98;if(q.O.3K==1L){hm(q.nm(q.O.3K)){if(q.8z[0]||q.8z[1]){J d=5M/6F;q.O.3K.kH(1T+d*q.8z[0],1H+d*q.8z[1])}}}14{q.O.3K.8u+=q.8z[0]*5M/6F;q.O.3K.5E+=q.8z[1]*5M/6F}2Z.c7();2Z.kD=1b;6x.3o(4v.jh,q.E);4v.gn(\'dh\',q);if(q.xS){4v.c4=4v.c4||$A(4v.jh);4v.c4[0]+=q.8z[0]*5M/6F;4v.c4[1]+=q.8z[1]*5M/6F;if(4v.c4[0]<0)4v.c4[0]=0;if(4v.c4[1]<0)4v.c4[1]=0;q.xU(4v.c4)}if(q.O.gG)q.O.gG(q)},nm:C(w){J T,L,W,H;hm(w.1f){if(w.1f.3G&&3G.5E){T=3G.5E;L=3G.8u}14 if(w.1f.2B){T=2B.5E;L=2B.8u}if(w.OW){W=w.OW;H=w.XP}14 if(w.1f.3G&&3G.lA){W=3G.lA;H=3G.jV}14{W=2B.5V;H=2B.5y}}N{1H:T,1T:L,1l:W,1p:H}}});dW.lz={};J Pt=2q.2r({2y:C(E,91){q.E=$(E);q.91=91;q.97=3U.cd(q.E)},pE:C(){q.97=3U.cd(q.E)},nP:C(){3U.fD();if(q.97!=3U.cd(q.E))q.91(q.E)}});J 3U={OQ:/^[^bt\\-](?:[A-Za-z0-9\\-\\bt]*)[bt](.*)$/,lS:{},OP:C(E){2S(E.1E.4F()!="tu"){if(E.id&&3U.lS[E.id])N E;E=E.1v}},O:C(E){E=3U.OP($(E));if(!E)N;N 3U.lS[E.id]},a2:C(E){J s=3U.O(E);if(s){4v.CY(s.E);s.lP.1t(C(d){6x.42(d)});s.ya.8n(\'a2\');bH 3U.lS[s.E.id]}},2r:C(E){E=$(E);J O=1i.1u({E:E,6Z:\'li\',OR:1a,3S:1a,lI:\'ul\',6J:\'fk\',hG:\'fk\',bf:E,2N:1a,69:1a,74:0,bG:1d,aI:1a,hF:1a,3K:1a,aO:20,8z:15,fu:q.OQ,2T:1a,y3:1a,gP:1B.79,Pr:1B.79},1D[1]||{});q.a2(E);J hK={6u:1b,hF:O.hF,3K:O.3K,8z:O.8z,aO:O.aO,74:O.74,aI:O.aI,hG:O.hG,2N:O.2N};if(O.dT)hK.dT=O.dT;if(O.e6)hK.e6=O.e6;14 if(O.aI)hK.e6=C(E){E.1g.1H=0;E.1g.1T=0};if(O.cf)hK.cf=O.cf;if(O.bQ)hK.bQ=O.bQ;J Po={6J:O.6J,bf:O.bf,3S:O.3S,bG:O.bG,dC:3U.dC};J yb={dC:3U.Pb,6J:O.6J,bf:O.bf,bG:O.bG};1e.j1(E);O.ya=[];O.lP=[];if(O.OR||O.3S){6x.5G(E,yb);O.lP.1N(E)}(O.2T||q.bJ(E,O)||[]).1t(C(e,i){J 2N=O.y3?$(O.y3[i]):(O.2N?$(e).1C(\'.\'+O.2N)[0]:e);O.ya.1N(1c dW(e,1i.1u(hK,{2N:2N})));6x.5G(e,Po);if(O.3S)e.y7=E;O.lP.1N(e)});if(O.3S){(3U.Pk(E,O)||[]).1t(C(e){6x.5G(e,yb);e.y7=E;O.lP.1N(e)})}q.lS[E.id]=O;4v.pr(1c Pt(E,O.Pr))},bJ:C(E,O){N 1e.uo(E,O.69,O.3S?1b:1a,O.6Z)},Pk:C(E,O){N 1e.uo(E,O.69,O.3S?1b:1a,O.lI)},dC:C(E,5l,6J){if(1e.kW(5l,E))N;if(6J>.33&&6J<.66&&3U.O(5l).3S){N}14 if(6J>0.5){3U.gT(5l,\'cJ\');if(5l.tE!=E){J fZ=E.1v;E.1g.8P="3N";5l.1v.6S(E,5l);if(5l.1v!=fZ)3U.O(fZ).gP(E);3U.O(5l.1v).gP(E)}}14{3U.gT(5l,\'fC\');J y4=5l.6e||1d;if(y4!=E){J fZ=E.1v;E.1g.8P="3N";5l.1v.6S(E,y4);if(5l.1v!=fZ)3U.O(fZ).gP(E);3U.O(5l.1v).gP(E)}}},Pb:C(E,5l,6J){J fZ=E.1v;J fM=3U.O(5l);if(!1e.kW(5l,E)){J 1y;J 4V=3U.bJ(5l,{6Z:fM.6Z,69:fM.69});J 2P=1d;if(4V){J 51=1e.l3(5l,fM.6J)*(1.0-6J);1j(1y=0;1y<4V.Y;1y+=1){if(51-1e.l3(4V[1y],fM.6J)>=0){51-=1e.l3(4V[1y],fM.6J)}14 if(51-(1e.l3(4V[1y],fM.6J)/2)>=0){2P=1y+1<4V.Y?4V[1y+1]:1d;2A}14{2P=4V[1y];2A}}}5l.6S(E,2P);3U.O(fZ).gP(E);fM.gP(E)}},fD:C(){if(3U.dB)3U.dB.2M()},gT:C(5l,1K){J tC=3U.O(5l.1v);if(tC&&!tC.aI)N;if(!3U.dB){3U.dB=($(\'Pi\')||1e.1u(1f.2w(\'gw\'))).2M().2F(\'Pi\').1I({1K:\'4Y\'});1f.4q("2B").2X(0).1X(3U.dB)}J 8K=2Z.6c(5l);3U.dB.1I({1T:8K[0]+\'px\',1H:8K[1]+\'px\'});if(1K==\'fC\')if(tC.6J==\'cy\')3U.dB.1I({1T:(8K[0]+5l.lA)+\'px\'});14 3U.dB.1I({1H:(8K[1]+5l.jV)+\'px\'});3U.dB.3o()},xQ:C(E,O,3Y){J 4V=3U.bJ(E,O)||[];1j(J i=0;i<4V.Y;++i){J 1Z=4V[i].id.1Z(O.fu);if(!1Z)6o;J 2P={id:9n(1Z?1Z[1]:1d),E:E,3Y:3Y,4V:[],1K:3Y.4V.Y,3j:$(4V[i]).8r(O.lI)};if(2P.3j)q.xQ(2P.3j,O,2P);3Y.4V.1N(2P)}N 3Y},3S:C(E){E=$(E);J lH=q.O(E);J O=1i.1u({6Z:lH.6Z,lI:lH.lI,69:lH.69,1m:E.id,fu:lH.fu},1D[1]||{});J 2l={id:1d,3Y:1d,4V:[],3j:E,1K:0};N 3U.xQ(E,O,2l)},Ol:C(1h){J 1y=\'\';do{if(1h.id)1y=\'[\'+1h.1K+\']\'+1y}2S((1h=1h.3Y)!=1d);N 1y},Oz:C(E){E=$(E);J O=1i.1u(q.O(E),1D[1]||{});N $(q.bJ(E,O)||[]).4G(C(2X){N 2X.id.1Z(O.fu)?2X.id.1Z(O.fu)[1]:\'\'})},XD:C(E,O8){E=$(E);J O=1i.1u(q.O(E),1D[2]||{});J u0={};q.bJ(E,O).1t(C(n){if(n.id.1Z(O.fu))u0[n.id.1Z(O.fu)[1]]=[n,n.1v];n.1v.5B(n)});O8.1t(C(xE){J n=u0[xE];if(n){n[1].1X(n[0]);bH u0[xE]}})},cd:C(E){E=$(E);J O=1i.1u(3U.O(E),1D[1]||{});J 1m=9n((1D[1]&&1D[1].1m)?1D[1].1m:E.id);if(O.3S){N 3U.3S(E,1D[1]).4V.4G(C(2X){N[1m+3U.Ol(2X)+"[id]="+9n(2X.id)].4W(2X.4V.4G(1D.eh))}).9L().57(\'&\')}14{N 3U.Oz(E,1D[1]).4G(C(2X){N 1m+"[]="+9n(2X)}).57(\'&\')}}};1e.kW=C(2P,E){if(!2P.1v||2P==E)N 1a;if(2P.1v==E)N 1b;N 1e.kW(2P.1v,E)};1e.uo=C(E,69,xA,1E){if(!E.un())N 1d;1E=1E.4F();if(69)69=[69].9L();J 2T=[];$A(E.1o).1t(C(e){if(e.1E&&e.1E.4F()==1E&&(!69||(1e.i0(e).bF(C(v){N 69.4j(v)}))))2T.1N(e);if(xA){J xw=1e.uo(e,69,xA,1E);if(xw)2T.1N(xw)}});N(2T.Y>0?2T.9L():[])};1e.l3=C(E,1V){N E[\'51\'+((1V==\'fk\'||1V==\'1p\')?\'Xr\':\'Xt\')]};if(28 1z==\'1R\')73("Y5.js zd Qd 5j.Qf.us\' 4O.js Qb");J fK={};fK.7d=2q.2r({qR:C(E,29,O){E=$(E);q.E=E;q.29=$(29);q.4r=1a;q.9o=1a;q.ep=1a;q.1y=0;q.dO=0;q.kZ=q.E.V;if(q.yt)q.yt(O);14 q.O=O||{};q.O.c5=q.O.c5||q.E.1m;q.O.9M=q.O.9M||[];q.O.aE=q.O.aE||0.4;q.O.pO=q.O.pO||1;q.O.xy=q.O.xy||C(E,29){if(!29.1g.1K||29.1g.1K==\'4Y\'){29.1g.1K=\'4Y\';2Z.4Z(E,29,{xx:1a,8j:E.5y})}1z.kM(29,{4U:0.15})};q.O.xG=q.O.xG||C(E,29){1c 1z.lr(29,{4U:0.15})};if(28(q.O.9M)==\'56\')q.O.9M=1c 3r(q.O.9M);if(!q.O.9M.4j(\'\\n\'))q.O.9M.1N(\'\\n\');q.91=1d;q.E.3p(\'Yd\',\'Ek\');1e.2M(q.29);1q.2h(q.E,\'5b\',q.PU.9g(q));1q.2h(q.E,\'rU\',q.Q9.9g(q))},3o:C(){if(1e.2s(q.29,\'3v\')==\'4s\')q.O.xy(q.E,q.29);if(!q.fe&&(1B.2j.IE)&&(1e.2s(q.29,\'1K\')==\'4Y\')){1c PL.xD(q.29,\'<6a id="\'+q.29.id+\'PC" \'+\'1g="3v:4s;1K:4Y;5t:PP:PO.xz.PG(3W=0);" \'+\'1P="68:1a;" Pz="0" Y6="no">\');q.fe=$(q.29.id+\'PC\')}if(q.fe)5C(q.PQ.1k(q),50)},PQ:C(){2Z.4Z(q.29,q.fe,{xF:(!q.29.1g.1p)});q.fe.1g.4N=1;q.29.1g.4N=2;1e.3o(q.fe)},2M:C(){q.xL();if(1e.2s(q.29,\'3v\')!=\'4s\')q.O.xG(q.E,q.29);if(q.fe)1e.2M(q.fe)},Ak:C(){if(q.O.uj)1e.3o(q.O.uj)},xL:C(){if(q.O.uj)1e.2M(q.O.uj)},Q9:C(1n){if(q.ep)7G(1n.31){1U 1q.tS:1U 1q.de:q.u5();1q.3L(1n);1U 1q.pI:q.2M();q.ep=1a;1q.3L(1n);N;1U 1q.v8:1U 1q.uY:N;1U 1q.eR:q.PS();q.cv();if(1B.2j.6D)1q.3L(1n);N;1U 1q.gD:q.Q0();q.cv();if(1B.2j.6D)1q.3L(1n);N}14 if(1n.31==1q.tS||1n.31==1q.de||(1B.2j.6D>0&&1n.31==0))N;q.9o=1b;q.4r=1b;if(q.91)9J(q.91);q.91=5C(q.LK.1k(q),q.O.aE*6F)},8v:C(){q.9o=1a;q.4r=1b;q.me()},dC:C(1n){J E=1q.87(1n,\'LI\');if(q.1y!=E.ut){q.1y=E.ut;q.cv()}1q.3L(1n)},u6:C(1n){J E=1q.87(1n,\'LI\');q.1y=E.ut;q.u5();q.2M()},PU:C(1n){5C(q.2M.1k(q),PT);q.4r=1a;q.ep=1a},cv:C(){if(q.dO>0){1j(J i=0;i0)q.1y--;14 q.1y=q.dO-1;q.hu(q.1y).PZ(1b)},Q0:C(){if(q.1y0)V=1e.ur(1M[0],q.O.1C)}14 V=1e.ux(kV,\'W5\');J fd=q.uc();if(fd[0]!=-1){J xO=q.E.V.5p(0,fd[0]);J xN=q.E.V.5p(fd[0]).1Z(/^\\s+/);if(xN)xO+=xN[0];q.E.V=xO+V+q.E.V.5p(fd[1])}14{q.E.V=V}q.kZ=q.E.V;q.E.3F();if(q.O.LZ)q.O.LZ(q.E,kV)},kF:C(l2){if(!q.9o&&q.4r){q.29.2C=l2;1e.j1(q.29);1e.j1(q.29.8r());if(q.29.3z&&q.29.8r().1o){q.dO=q.29.8r().1o.Y;1j(J i=0;i=q.O.pO){q.me()}14{q.ep=1a;q.2M()}q.kZ=q.E.V},jf:C(){J fd=q.uc();N q.E.V.5Y(fd[0],fd[1]).5h()},uc:C(){if(1d!=q.u1)N q.u1;J V=q.E.V;if(V.5h().gg())N[-1,0];J u3=1D.eh.M4(V,q.kZ);J 51=(u3==q.kZ.Y?1:0);J u7=-1,ud=V.Y;J tp;1j(J 1y=0,l=q.O.9M.Y;1yu7)u7=tp;tp=V.3R(q.O.9M[1y],u3+51);if(-1!=tp&&tp"+4t.5p(0,3D.Y)+""+4t.5p(3D.Y)+"");2A}14 if(3D.Y>=bU.O.L6&&bU.O.L5&&bC!=-1){if(bU.O.L4||/\\s/.3n(4t.5p(bC-1,1))){pv.1N("
  • "+4t.5p(0,bC)+""+4t.5p(bC,3D.Y)+""+4t.5p(bC+3D.Y)+"
  • ");2A}}bC=bU.O.xK?4t.3t().3R(3D.3t(),bC+1):4t.3R(3D,bC+1)}}if(pv.Y)hy=hy.4W(pv.6i(0,bU.O.l2-hy.Y));N"
      "+hy.57(\'\')+"
    "}},O||{})}});pZ.Nd=C(gE){5C(C(){pZ.8v(gE)},1)};3c.dj=2q.2r({2y:C(E,2o,O){q.2o=2o;q.E=E=$(E);q.NP();q.6h={};1D.eh.NJ(O);1i.1u(q.O,O||{});if(!q.O.9V&&q.E.id){q.O.9V=q.E.id+\'-qa\';if($(q.O.9V))q.O.9V=\'\'}if(q.O.9W)q.O.9W=$(q.O.9W);if(!q.O.9W)q.O.qh=1a;q.qn=q.E.2s(\'7z-4b\')||\'q3\';q.E.3k=q.O.NB;q.pk=q.xC.1k(q);q.Mr=(q.O.2G||1B.79).1k(q);q.qq=q.Nj.1k(q);q.l1=q.xP.1k(q);q.y5=q.xW.1k(q);q.NI()},Mm:C(e){if(!q.qr||e.b4||e.WQ||e.7o)N;if(1q.pI==e.31)q.xC(e);14 if(1q.de==e.31)q.xP(e)},xB:C(5r,5O,xM){J qG=q.O[5r+\'X8\'];J 26=q.O[5r+\'X1\'];if(\'7x\'==qG){J hI=1f.2w(\'21\');hI.1V=\'b8\';hI.V=26;hI.1G=\'Lu\'+5r+\'O2\';if(\'dZ\'==5r)hI.3V=q.pk;q.6t.1X(hI);q.6h[5r]=hI}14 if(\'8M\'==qG){J 8M=1f.2w(\'a\');8M.6G=\'#\';8M.1X(1f.aN(26));8M.3V=\'dZ\'==5r?q.pk:q.l1;8M.1G=\'Lu\'+5r+\'WL\';if(xM)8M.1G+=\' \'+xM;q.6t.1X(8M);q.6h[5r]=8M}},xY:C(){J 26=(q.O.kx?q.O.gS:q.qQ());J aH;if(1>=q.O.4S&&!/\\r|\\n/.3n(q.qQ())){aH=1f.2w(\'21\');aH.1V=\'26\';J 3s=q.O.3s||q.O.kX||0;if(0<3s)aH.3s=3s}14{aH=1f.2w(\'3i\');aH.4S=(1>=q.O.4S?q.O.NV:q.O.4S);aH.kX=q.O.kX||40}aH.1m=q.O.c5;aH.V=26;aH.1G=\'Wv\';if(q.O.Lj)aH.d8=q.l1;q.6h.78=aH;if(q.O.kx)q.qJ();q.6t.1X(q.6h.78)},Nf:C(){J 8s=q;C pm(5r,Li){J 26=8s.O[\'26\'+5r+\'Wl\'];if(!26||Li===1a)N;8s.6t.1X(1f.aN(26))};q.6t=$(1f.2w(\'2D\'));q.6t.id=q.O.9V;q.6t.2F(q.O.Nn);q.6t.nA=q.l1;q.xY();if(\'3i\'==q.6h.78.1E.3t())q.6t.1X(1f.2w(\'br\'));if(q.O.wN)q.O.wN(q,q.6t);pm(\'Lh\',q.O.lJ||q.O.lo);q.xB(\'ok\',q.l1);pm(\'WB\',q.O.lJ&&q.O.lo);q.xB(\'dZ\',q.pk,\'11j\');pm(\'xD\',q.O.lJ||q.O.lo)},a2:C(){if(q.hg)q.E.2C=q.hg;q.xZ();q.MJ()},Ml:C(e){if(q.lN||q.qr)N;q.qr=1b;q.jl(\'Ld\');if(q.O.9W)q.O.9W.2M();q.E.2M();q.Nf();q.E.1v.6S(q.6t,q.E);if(!q.O.kx)q.y8();if(e)1q.3L(e)},Me:C(e){if(q.O.lf)q.E.2F(q.O.lf);if(q.lN)N;q.jl(\'KX\')},qQ:C(){N q.E.2C},Nj:C(1W){q.jl(\'dz\',1W);if(q.hg){q.E.2C=q.hg;q.hg=1d}},xC:C(e){q.xW();if(e)1q.3L(e)},xP:C(e){J 2D=q.6t;J V=$F(q.6h.78);q.NW();J 4C=q.O.4g(2D,V)||\'\';if(1i.5S(4C))4C=4C.lB();4C.qL=q.E.id;if(q.O.Ne){J O=1i.1u({9K:1b},q.O.ij);1i.1u(O,{2Q:4C,2G:q.y5,dz:q.qq});1c 3c.y6({9t:q.E},q.2o,O)}14{J O=1i.1u({3e:\'2d\'},q.O.ij);1i.1u(O,{2Q:4C,2G:q.y5,dz:q.qq});1c 3c.8i(q.2o,O)}if(e)1q.3L(e)},xZ:C(){q.E.4n(q.O.wQ);q.y0();q.qj();q.E.1g.7C=q.qn;q.E.3o();if(q.O.9W)q.O.9W.3o();q.lN=1a;q.qr=1a;q.hg=1d;q.jl(\'KT\')},qj:C(e){if(q.O.lf)q.E.4n(q.O.lf);if(q.lN)N;q.jl(\'L1\')},qJ:C(){q.6t.2F(q.O.ly);q.6h.78.2K=1b;J O=1i.1u({3e:\'2d\'},q.O.ij);1i.1u(O,{2Q:\'qL=\'+9n(q.E.id),2G:1B.79,x0:C(1W){q.6t.4n(q.O.ly);J 26=1W.4B;if(q.O.Mo)26=26.jv();q.6h.78.V=26;q.6h.78.2K=1a;q.y8()}.1k(q),dz:q.qq});1c 3c.8i(q.O.kx,O)},y8:C(){J y9=q.O.Nl;if(y9)$(q.6h.78)[\'3F\'==y9?\'3F\':\'8v\']()},NP:C(){q.O=1i.4Z(3c.dj.hE);1i.1u(q.O,3c.dj.Lx);[q.Mt].9L().NT().1t(C(NX){1i.1u(q.O,NX)}.1k(q))},NW:C(){q.lN=1b;q.y0();q.qj();q.Nc()},NI:C(){q.xR={};J 9c;$H(3c.dj.Mk).1t(C(2k){9c=q[2k.V].1k(q);q.xR[2k.1Y]=9c;if(!q.O.qh)q.E.2h(2k.1Y,9c);if(q.O.9W)q.O.9W.2h(2k.1Y,9c)}.1k(q))},y0:C(){if(!q.6t)N;q.6t.42();q.6t=1d;q.6h={}},Nc:C(){q.hg=q.E.2C;q.E.2C=q.O.Nr;q.E.2F(q.O.wQ);q.E.1g.7C=q.qn;q.E.3o()},jl:C(xT,MK){if(\'C\'==28 q.O[xT]){q.O[xT](q,MK)}},MJ:C(){$H(q.xR).1t(C(2k){if(!q.O.qh)q.E.60(2k.1Y,2k.V);if(q.O.9W)q.O.9W.60(2k.1Y,2k.V)}.1k(q))},xW:C(1W){q.xZ();q.Mr(1W,q.E)}});1i.1u(3c.dj.1w,{118:3c.dj.1w.a2});3c.xt=2q.2r(3c.dj,{2y:C($7a,E,2o,O){q.Mt=3c.xt.hE;$7a(E,2o,O)},xY:C(){J 54=1f.2w(\'1C\');54.1m=q.O.c5;54.3s=1;q.6h.78=54;q.kJ=q.O.N6||[];if(q.O.N8)q.My();14 q.xX();q.6t.1X(q.6h.78)},My:C(){q.6t.2F(q.O.ly);q.xu(q.O.LG);J O=1i.1u({3e:\'2d\'},q.O.ij);1i.1u(O,{2Q:\'qL=\'+9n(q.E.id),2G:1B.79,x0:C(1W){J js=1W.4B.5h();if(!/^\\[.*\\]$/.3n(js))73\'116 12k an 12f N6 129.\';q.kJ=8y(js);q.xX()}.1k(q),dz:q.dz});1c 3c.8i(q.O.N8,O)},xu:C(26){q.6h.78.2K=1b;J i1=q.6h.78.3z;if(!i1){i1=1f.2w(\'9p\');i1.V=\'\';q.6h.78.1X(i1);i1.4D=1b}i1.29((26||\'\').ap().jv())},xX:C(){q.kz=q.qQ();if(q.O.kx)q.qJ();14 q.wZ()},qJ:C(){q.xu(q.O.gS);J O=1i.1u({3e:\'2d\'},q.O.ij);1i.1u(O,{2Q:\'qL=\'+9n(q.E.id),2G:1B.79,x0:C(1W){q.kz=1W.4B.5h();q.wZ()}.1k(q),dz:q.dz});1c 3c.8i(q.O.kx,O)},wZ:C(){q.6t.4n(q.O.ly);q.kJ=q.kJ.4G(C(3D){N 2===3D.Y?3D:[3D,3D].9L()});J x3=(\'V\'in q.O)?q.O.V:q.kz;J MD=q.kJ.l4(C(3D){N 3D[0]==x3}.1k(q));q.6h.78.29(\'\');J 9p;q.kJ.1t(C(3D,1y){9p=1f.2w(\'9p\');9p.V=3D[0];9p.4D=MD?3D[0]==x3:0==1y;9p.1X(1f.aN(3D[1]));q.6h.78.1X(9p)}.1k(q));q.6h.78.2K=1a;pZ.Nd(q.6h.78)}});3c.dj.1w.2y.NJ=C(O){if(!O)N;C lu(1m,eX){if(1m in O||eX===1R)N;O[1m]=eX};lu(\'lo\',(O.NL?\'8M\':(O.sK?\'7x\':O.NL==O.sK==1a?1a:1R)));lu(\'lJ\',(O.NE?\'8M\':(O.e2?\'7x\':O.NE==O.e2==1a?1a:1R)));lu(\'oj\',O.ZD);lu(\'x8\',O.Zx)};1i.1u(3c.dj,{hE:{ij:{},NV:3,lo:\'8M\',Zt:\'dZ\',NB:\'Zs to ei\',9W:1d,qh:1a,Nl:\'8v\',Nn:\'qa-2D\',9V:1d,oj:\'#Ni\',x8:\'#pY\',lf:\'\',Ne:1b,ly:\'qa-5m\',gS:\'qF...\',lJ:\'7x\',ZN:\'ok\',c5:\'V\',4S:1,wQ:\'qa-ZM\',Nr:\'ZL...\',3s:0,Mo:1a,Lj:1a,ZH:\'\',ZG:\'\',ZI:\'\'},Lx:{4g:C(2D){N 4d.cd(2D)},2G:C(1W,E){1c 1z.qb(E,{q9:q.O.oj,xm:1b})},Ld:1d,KX:C(8s){8s.E.1g.7C=8s.O.oj;if(8s.wR)8s.wR.dZ()},dz:C(1W,8s){6H(\'f3 Z8 hm Cn Z9: \'+1W.4B.jv())},wN:1d,KT:1d,L1:C(8s){8s.wR=1c 1z.qb(8s.E,{q9:8s.O.oj,qg:8s.O.x8,qm:8s.qn,xm:1b})}},Mk:{44:\'Ml\',9q:\'Mm\',xp:\'Me\',Mf:\'qj\'}});3c.xt.hE={LG:\'qF O...\'};4d.1e.Zp=2q.2r({2y:C(E,74,4g){q.74=74||0.5;q.E=$(E);q.4g=4g;q.7p=1d;q.97=$F(q.E);1q.2h(q.E,\'Zk\',q.LO.9g(q))},LO:C(1n){if(q.97==$F(q.E))N;if(q.7p)9J(q.7p);q.7p=5C(q.gh.1k(q),q.74*6F);q.97=$F(q.E)},gh:C(){q.7p=1d;q.4g(q.E,$F(q.E))}});J aK={59:C(E){E=$(E);J O=1i.1u({7F:8,et:sW,3W:0.7,ev:4,4b:\'#sR\'},1D[1]||{});q.O=O;J nX=1e.2s(E,\'1K\');J 3Y=E.1v;if(!E.gB){if(nX!=\'4Y\'&&nX!=\'m3\'){J nZ=q.z8(E);nZ.id=1d;3Y.6S(nZ,E);2Z.bT(E);2Z.4Z(nZ,E);E.1g.6U=\'0\';nZ.1g.8P=\'3N\';nX=\'4Y\'}E.gB=1c ad(1e.2s(E,\'4N\')?1e.2s(E,\'4N\'):1);E.1g.4N=E.gB+O.ev}if(1D[2]){q.hC(E)}if(!E.cV){E.cV=1c 3r(O.ev);1j(J i=0;i= 1.5.0")}1z.oK=2q.2r();1i.1u(1i.1u(1z.oK.1w,1z.7d.1w),{pP:C(s){J s=2f(s).55(16);N(s.Y<2)?\'0\'+s:s},P1:C(1h){1j(;1h&&1h.2U.3t()!=\'8L\';1h=1h.1v){J v=1e.2s(1h,\'7C\');if(v.3R(\'bY\')>=0){bY=v.1Z(/\\d+/g);N\'#\'+q.pP(bY[0])+q.pP(bY[1])+q.pP(bY[2])}if(v&&v!=\'q3\')N v}N\'#pY\'},Od:C(i){7G(q.fx){1U\'3X\':N 2c.3X(q.1l*(1-2c.bo(2c.yW(i/q.1l))));1U\'OA\':N 2c.3X(q.1l*(1+2c.bo(2c.yW(i/q.1l))));1U\'Om\':N 2c.3X(q.1l*(1-2c.bo(2c.10F(i/q.1l))));1U\'OG\':N 2c.3X(q.1l*(2c.bo(2c.yW((q.1l-i-1)/q.1l))));1U\'yY\':N 2c.3X(q.1l*(2c.Ot(i,q.1l/i)));1U\'O3\':N 2c.3X(q.1l*(2c.Ot(q.1l,(q.1l-i-1))));1U\'Oi\':N 2c.3X(q.1l*(2c.10G(i)));1U\'Oj\':N 2c.3X(q.1l*(2c.bo(i)));1U\'Og\':N 2c.3X(q.1l*(2c.10m(i)));1U\'OI\':N 2c.3X(q.1l*(2c.Os(i)));1U\'Oc\':N 2c.3X(q.1l*(2c.mp((q.1l-i-1),q.1l)));1U\'Pa\':N(i&1)?(i+1):q.1l;1U\'P9\':N(i&2)?(i+1):q.1l;1U\'Pe\':N(i&3)?(i+1):q.1l;1U\'Oh\':N(i%2)*q.1l;1U\'Pv\':N q.1l;1U\'Oq\':N i+1}},2y:C(E,o){E=$(E);o=(o||"").3t();J z2=/z2/.3n(o);J cc=((o.1Z(/cc:(#[0-9a-f]+)/)||[])[1]);J sc=((o.1Z(/sc:(#[0-9a-f]+)/)||[])[1]);q.1l=2f((o.1Z(/(\\d+)px/)||[])[1])||10;J re=/3X|Oq|Pv|OG|OA|Om|yY|O3|Oi|Oj|Oh|Og|Oc|OI|Pe|P9|Pa/;q.fx=((o.1Z(re)||[\'3X\'])[0]);J z1={T:0,B:1};J cr={TL:/1H|tl/.3n(o),TR:/1H|tr/.3n(o),BL:/4A|bl/.3n(o),BR:/4A|br/.3n(o)};if(!cr.TL&&!cr.TR&&!cr.BL&&!cr.BR)cr={TL:1,TR:1,BL:1,BR:1};J 5h=1f.2w(\'1x\');5h.1g.5c=\'3N\';5h.1g.1p=\'fS\';5h.1g.7C=sc||\'q3\';5h.1g.P8=\'fO\';J cI={T:2f(1e.2s(E,\'Ce\'))||0,R:2f(1e.2s(E,\'OT\'))||0,B:2f(1e.2s(E,\'CQ\'))||0,L:2f(1e.2s(E,\'OO\'))||0};if(/Pc/.3n(7y.bs))E.1g.fm=1;if(!z2)E.1g.52=\'4s\';5h.1g.10e=cc||q.P1(E.1v);J Pm=1e.3H(E);1j(J j in z1){J mu=z1[j];5h.1g.P8=\'4s \'+(cr[j+\'R\']?\'fO\':\'4s\')+\' 4s \'+(cr[j+\'L\']?\'fO\':\'4s\');J d=1f.2w(\'1x\');J ds=d.1g;mu?E.1X(d):E.6S(d,E.3z);if(mu&&Pm!=\'8g\'){if(1e.2s(E,\'1K\')==\'oJ\')E.1g.1K=\'ef\';ds.1K=\'4Y\';ds.4A=ds.1T=ds.9j=ds.6U=\'0\';if(/Pc/.3n(7y.bs))ds.RL(\'1l\',\'q.1v.5V\');14 ds.1l=\'100%\'}14{ds.6U=!mu?\'-\'+cI.T+\'px -\'+cI.R+\'px \'+(cI.T-q.1l)+\'px -\'+cI.L+\'px\':(cI.B-q.1l)+\'px -\'+cI.R+\'px -\'+cI.B+\'px -\'+cI.L+\'px\'}1j(J i=0;i=2){q.1o[q.1o.Y-2].8B=1a}2S(2l.1v){2l=2l.1v}if(2l.yq){if(q.1o.Y>=2){1f.3Q(q.1o[q.1o.Y-2].id+\'-7m\').1P=((q.1o[q.1o.Y-2].53)?((q.1o[q.1o.Y-2].3O)?3f.n5:3f.n7):3f.yJ);q.1o[q.1o.Y-2].qs=3f.n7;q.1o[q.1o.Y-2].qx=3f.n5;q.1o[q.1o.Y-2].8B=1a}q.8B=1b;J 6p=q;2S(6p.1v){1j(J i=0;i<6p.1v.1o.Y;i++){if(6p.id==6p.1v.1o[i].id){2A}}if(i==6p.1v.1o.Y-1){6p.1v.8B=1b}14{6p.1v.8B=1a}6p=6p.1v}1Q.Lz(1f.3Q(q.id+\'-ff\'),1h.55());if(!1h.gc){l8.5G(1h.id)}if(1Q.8N){J 2i=\'\';1q.2h(1h.id+\'-4L\',\'fg\',C(e){1s.aX(1s.5e);8y(q.2i)}.1k(1h));1Q.8N.ik(\'#\'+1h.id+\'-4L\')}1q.2h(1h.id+\'-4L\',\'44\',C(e){1s.aX(1s.5e);8y(q.2i);1q.3L(e)}.1k(1h));if((!q.53)&&(!q.8k)){q.3J=3f.yO;q.8k=3f.yR}if(!q.53){q.53=1b;q.dm(1b)}if(!Nu){q.bR()}}N 1h};72.1w.bk=C(){if(q.53){if(q.3O){q.dm()}14{q.9l()}}};72.1w.1C=C(){1f.3Q(q.id+\'-4L\').3F()};72.1w.Bx=C(){1f.3Q(q.id+\'-4L\').1G=\'\';1Q.4D=1d};72.1w.3F=C(){if((1Q.4D)&&(1Q.4D!=q)){1Q.4D.Bx()}1Q.4D=q;if((q.8k)&&(1Q.a4!=\'fV\')){1f.3Q(q.id+\'-3J\').1P=q.8k}1f.3Q(q.id+\'-4L\').3F();1f.3Q(q.id+\'-4L\').1G=\'4D-3F\';if(1Q.qP){1Q.qP(q)}};72.1w.5b=C(){if((q.8k)&&(1Q.a4!=\'fV\')){1f.3Q(q.id+\'-3J\').1P=q.3J}if(1Q.4D==q){1f.3Q(q.id+\'-4L\').1G=\'4D-R8\'}14{1f.3Q(q.id+\'-4L\').1G=\'\'}if(1B.2j.IE){1f.3Q(q.id+\'-4L\').5b()}};72.1w.yg=C(){if(1Q.a4==\'fV\'){1f.3Q(q.id+\'-3J\').1P=q.8k}if(q.1o.Y){1f.3Q(q.id+\'-ff\').1g.3v=\'bM\'}q.3O=1b;if(3f.m7){1Q.95.zl(q.id.5p(18,q.id.Y-18),\'1\')}};72.1w.qU=C(){if(1Q.a4==\'fV\'){1f.3Q(q.id+\'-3J\').1P=q.3J}if(q.1o.Y){1f.3Q(q.id+\'-ff\').1g.3v=\'4s\'}q.3O=1a;if(3f.m7){1Q.95.zl(q.id.5p(18,q.id.Y-18),\'0\')}};72.1w.Nx=C(){q.Nz();if((q.53)&&(!q.3O)){q.9l()}};72.1w.Nz=C(){1j(J i=0;i=0;i--){5W=q.1o[i].bR(mA+1,qK,4o,yT);if(5W){N}}if(qK){if((yT>=q.yN)&&(1f.3Q(q.id+\'-7m\'))){if(q.53){1f.3Q(q.id+\'-7m\').1P=(q.3O)?3f.n4:3f.n8;q.qs=3f.n8;q.qx=3f.n4}14 if(MF){1f.3Q(q.id+\'-7m\').1P=3f.yP}N 1}}J 6p=1f.3Q(q.id+\'-bR-\'+mA);if(6p){if((6p.8B)||((qK)&&(4o))){6p.1P=3f.yL}14{6p.1P=3f.yK}}N 0};C 6V(9I,cY,gu,ej,dV){q.m5=72;q.m5(9I,cY);q.3J=ej||3f.Mx;q.8k=dV||3f.N3;if(3f.m7){q.3O=(1Q.95.wM(q.id.5p(18,q.id.Y-18))==\'0\')?1a:1b}14{q.3O=1b}q.53=1b;q.yq=1a;q.qP=1d;if(!1Q.a4){1Q.a4=gu||3f.Na}}6V.1w=1c 72;6V.1w.QZ=C(gu){1Q.a4=gu};6V.1w.R0=C(gu){N 1Q.a4};6V.1w.R4=C(){if(1Q.4D){N 1Q.4D}14{N 1d}};6V.1w.42=C(){};6V.1w.9l=C(){q.yg()};6V.1w.dm=C(b){if(!b){q.3F()}q.qU()};6V.1w.nC=C(){N 1d};6V.1w.qT=C(){N 1d};6V.1w.nx=C(){N 1d};6V.1w.nd=C(){N 1d};6V.1w.9q=C(1Y){if(!1Q.4r)N 1b;if(1Y==9)N 1a;if(1Y==39){if(!q.3O){q.9l()}14 if(q.1o.Y){q.1o[0].1C()}N 1a}if(1Y==37){q.dm();N 1a}if((1Y==40)&&(q.3O)&&(q.1o.Y)){q.1o[0].1C();J qu=q.1o[0];if(5X)9J(5X);J dw="68:";5X=1L.5C(C(){8y(qu.2i.5Y(dw.Y))},6F);N 1a}N 1b};6V.1w.55=C(){if(1K=q.2i.3R("it",0)>0){q.2i=q.2i.2V(1c 8x("it","g"),\'\\\'\'+q.id+\'\\\'\')}if(q.w1){1Q.ib[q.pC]=q.id}J 6X="<1x id=\\""+q.id+"\\" cN=\\"1Q.bk(q);\\" 3w=\\"76-3S-2X\\" es=\\"N 1Q.9q(q, 1n)\\" 4E=\\"/\\">"+"<2e id=\\""+q.id+"-3J\\" 3w=\\"76-3S-3J\\" 1P=\\""+((1Q.a4==\'fV\'&&q.3O)?q.8k:q.3J)+"\\" 3V=\\"1Q.1C(q);\\">"+""+q.26+""+"<1x id=\\""+q.id+"-ff\\" 3w=\\"76-3S-3j\\" 1g=\\"3v: "+((q.3O)?\'bM\':\'4s\')+";\\">";J sb=[];1j(J i=0;i"};C 67(9I,cY,p8,ej,dV){q.m5=72;q.m5(9I,cY);if(3f.m7){q.3O=(1Q.95.wM(q.id.5p(18,q.id.Y-18))==\'1\')?1b:1a}14{q.3O=1a}if(ej){q.3J=ej}if(dV){q.8k=dV}if(p8){p8.5G(q)}}67.1w=1c 72;67.1w.42=C(){if(!1f.3Q(q.id+\'-7m\'))N;J fN=1f.3Q(q.id+\'-7m\').1P;J 1v=q.1v;J 9Y=q.nd(1b);J 6e=q.nx(1b);J 53=q.1v.53;J 4o=((6e)&&(6e.1v)&&(6e.1v.id==1v.id))?1a:1b;q.nd().3F();q.yu();6x.42($(q.id));if(1Q.8N)1Q.8N.tB(\'#\'+q.id);if(1v.1o.Y==0){1f.3Q(1v.id+\'-ff\').1g.3v=\'4s\';1v.qU();1v.53=1a;1v.3O=1a}if(!6e||4o){1v.bR(1d,1b,4o,q.yN,1v.1o.Y)}if((9Y==1v)&&!(1v.1o.Y)){9Y.53=1a;9Y.3O=1a;if(1f.3Q(9Y.id+\'-7m\')){fN=1f.3Q(9Y.id+\'-7m\').1P;fN=fN.2V(\'MY\',\'\').2V(\'7m\',\'\');1f.3Q(9Y.id+\'-7m\').1P=fN;1f.3Q(9Y.id+\'-3J\').1P=(1Q.4l[9Y.id].3J?1Q.4l[9Y.id].3J:3f.yQ)}}if(1f.3Q(9Y.id+\'-7m\')){if(1v==9Y.1v){fN=fN.2V(\'MY\',\'\').2V(\'7m\',\'\');1f.3Q(9Y.id+\'-7m\').1P=fN}}};67.1w.yu=C(){1j(J i=q.1o.Y-1;i>=0;i--){q.1o[i].yu()}1j(J i=0;i"+bR;i++}q.yN=i;if(q.1o.Y){q.53=1}14{q.3O=1a}if((q.53)||(1Q.a4!=\'fV\')){if(!q.3J){q.3J=3f.yO}if(!q.8k){q.8k=3f.yR}}14 if(!q.3J){q.3J=3f.yQ}if(1K=q.2i.3R("it",0)>0){q.2i=q.2i.2V(1c 8x("it","g"),\'\\\'\'+q.id+\'\\\'\')}J eB=q.26.2V(//g,\'>\');J 6X="<1x id=\\""+q.id+"\\" cN=\\"1Q.bk(q);\\" 3w=\\"76-3S-2X\\" es=\\"N 1Q.9q(q, 1n)\\" 4E=\\""+q.4E+"\\">"+bR+"<2e 1l=\\"19\\" 1p=\\"16\\" id=\\""+q.id+"-7m\\" 1P=\\""+((q.53)?((q.3O)?((q.1v.8B)?3f.n4:3f.n5):((q.1v.8B)?3f.n8:3f.n7)):((q.1v.8B)?3f.yP:3f.yJ))+"\\" 3V=\\"1Q.bk(q);\\">"+"<2e id=\\""+q.id+"-3J\\" 3w=\\"76-3S-3J\\" 1P=\\""+((1Q.a4==\'fV\'&&q.3O)?q.8k:q.3J)+"\\" 3V=\\"1Q.1C(q);\\">"+""+eB+""+"<1x id=\\""+q.id+"-ff\\" 3w=\\"76-3S-3j\\" 1g=\\"3v: "+((q.3O)?\'bM\':\'4s\')+";\\">";J sb=[];1j(J i=0;i"};3f.gS="qF...";3f.Lr="f3 5m \\"%1%\\"";3f.TX="f3 \\"%1%\\" Ae 9B V8 l4 3S 3b";C iR(9I,qC,cY,gu,ej,dV){q.6V=6V;q.6V(9I,cY,gu,ej,dV);q.1P=qC;q.5m=1a;q.8O=1a;q.kk="";if(q.3O)jG(q.1P,q);14{q.eW=1c 67(3f.gS);q.5G(q.eW)}}iR.1w=1c 6V;iR.1w.Nt=6V.1w.9l;iR.1w.9l=C(){if(!q.8O&&!q.5m){jG(q.1P,q)}q.Nt()};C jD(9I,qC,cY,p8,ej,dV){q.67=67;q.67(9I,cY,p8,ej,dV);q.1P=qC;q.5m=1a;q.8O=1a;q.kk="";if(q.3O)jG(q.1P,q);14{q.eW=1c 67(3f.gS);q.5G(q.eW)}}jD.1w=1c 67;jD.1w.Lo=67.1w.9l;jD.1w.9l=C(){if(!q.8O&&!q.5m){jG(q.1P,q)}q.Lo()};iR.1w.e0=jD.1w.e0=C(){if(q.8O){J 3O=q.3O;2S(q.1o.Y>0)q.1o[q.1o.Y-1].42();q.8O=1a;q.eW=1c 67(3f.gS);q.5G(q.eW);if(3O)q.9l()}14 if(q.3O&&!q.5m)jG(q.1P,q);if(!q.3O&&!q.5m)q.bk()};C jG(Lg,7s){if(7s.5m||7s.8O)N;7s.5m=1b;J 1J=1c 5u(KQ(qz(Lg)));1J.2G=C(1W){Lv(1W.6s,7s)};1J.7K()}C vT(8H){J 26=8H.1r("26");J 2i=8H.1r("2i");if(!2i){2i="68:1s.D9().uL(it)"}J 3Y=1d;J 3J=8H.1r("3J");J 8k=8H.1r("V4");J 1P=8H.1r("1P");J 3B=8H.1r("3B");J pJ=8H.1r("pJ");J ez=8H.1r("lM");J pC=8H.1r("4E");J 7s;if(1P!=1d&&1P!="")7s=1c jD(26,1P,2i,3Y,3J,8k);14 7s=1c 67(26,2i,3Y,3J,8k);if(3B!="")7s.3B=3B;if(ez!=1d&&!(1s&&1s.2I&&1s.2I.CP)){1Q.da=7s.id;7s.pu=1b}if(8H.1r(\'Lq\')&&8H.1r(\'Lq\')=="1b"){7s.w1=1b;1Q.ib[5z(pC)]=7s.id}if(1P!=1d&&1P!=""&&pJ!=1d&&pJ==\'1b\'){7s.8O=1b}7s.4E=pC;J cs=8H.1o;J l=cs.Y;1j(J i=0;i100}14{3s=s.E.5y-s.2N.5y;2t=s.E.5y-s.2N.5y-(e.kQ-2z.cL.dy);cT=2c.f1(e.iX-2z.cL.iX)>100}s.4Q(cT?2z.cL.LM:s.bn()+LN*2t/3s);N 1a}14{J s=2z.qt;if(s!=1d){J jQ=2z.4R.vZ(e);s.pT=e.pM+(jQ?s.6l.8Q:0);s.pW=e.wE+(jQ?s.6l.8j:0)}}},c1:C(e){e=2z.4R.di(e,q);J s=2z.qt;J 7k=s.1f;if(7k.e3){7k.e3("fW",2z.4R.fl,1b);7k.e3("g3",2z.4R.c1,1b)}14 if(7k.bz){7k.bz("fl",2z.4R.fl);7k.bz("c1",2z.4R.c1);7k.bz("LV",2z.4R.c1);s.E.Sp()}if(2z.cL){2z.cL=1d}14{s.g7.3L();s.99=1d}2z.qt=1d},es:C(e){e=2z.4R.di(e,q);J s=q.3h;J kc=e.31;7G(kc){1U 33:s.4Q(s.3T()+s.gq());2A;1U 34:s.4Q(s.3T()-s.gq());2A;1U 35:s.4Q(s.wj()=="cy"?s.f5():s.bn());2A;1U 36:s.4Q(s.wj()=="cy"?s.bn():s.f5());2A;1U 38:1U 39:s.4Q(s.3T()+s.qS());2A;1U 37:1U 40:s.4Q(s.3T()-s.qS());2A}if(kc>=33&&kc<=40){N 1a}},Ba:C(e){e=2z.4R.di(e,q);J kc=e.31;if(kc>=33&&kc<=40){N 1a}},vF:C(e){e=2z.4R.di(e,q);J s=q.3h;if(s.qv){s.4Q(s.3T()+e.SD/120*s.qS());N 1a}}};2z.1w.Qa="Sy-3h-qG",2z.1w.4Q=C(v){q.dI.4Q(v);q.21.V=q.3T()};2z.1w.3T=C(){N q.dI.3T()};2z.1w.kg=C(v){q.dI.kg(v);q.21.V=q.3T()};2z.1w.bn=C(){N q.dI.bn()};2z.1w.kf=C(v){q.dI.kf(v);q.21.V=q.3T()};2z.1w.f5=C(){N q.dI.f5()};2z.1w.SB=C(v){q.ws=v};2z.1w.qS=C(){N q.ws};2z.1w.Si=C(v){q.wy=v};2z.1w.gq=C(){N q.wy};2z.1w.wj=C(){N q.dE};2z.1w.S2=C(kI){if(kI!=q.dE){if(2z.mC&&q.E){q.E.1G=q.E.1G.2V(q.dE,kI)}q.dE=kI;q.kl()}};2z.1w.kl=C(){if(!2z.mC||!q.E)N;J w=q.E.5V;J h=q.E.5y;J hw=q.2N.5V;J hh=q.2N.5y;J lw=q.6l.5V;J lh=q.6l.5y;if(q.dE=="cy"){q.2N.1g.1T=(w-hw)*(q.3T()-q.bn())/(q.f5()-q.bn())+"px";q.2N.1g.1H=(h-hh)/2+"px";q.6l.1g.1H=(h-lh)/2+"px";q.6l.1g.1T=hw/2+"px";q.6l.1g.1l=2c.4X(0,w-hw-2)+"px";q.6l.3z.1g.1l=2c.4X(0,w-hw-4)+"px"}14{q.2N.1g.1T=(w-hw)/2+"px";q.2N.1g.1H=h-hh-(h-hh)*(q.3T()-q.bn())/(q.f5()-q.bn())+"px";q.6l.1g.1T=(w-lw)/2+"px";q.6l.1g.1H=hh/2+"px";q.6l.1g.1p=2c.4X(0,h-hh-2)+"px";q.6l.3z.1g.1p=2c.4X(0,h-hh-4)+"px"}};2z.1w.kd=C(){J hw=q.2N.5V;J hh=q.2N.5y;J hl=q.2N.8Q;J ht=q.2N.8j;if(q.dE=="cy"){if(q.pT>hl+hw&&(q.99==1d||q.99)){q.4Q(q.3T()+q.gq());q.99=1b}14 if(q.pTht+hh&&(q.99==1d||!q.99)){q.4Q(q.3T()-q.gq());q.99=1a}14 if(q.pW1){J 1y=0;$(lT).3x(\'21[1V="4m"]\').1t(C(E){if(1y>0)lT.5B(E);1y++})}q.OM=C(E){if(E.1E==\'pF\'&&E.1V==\'4m\'){E.1m=\'T4\'+q.id++;E.hp=q.id;E.id=E.1m;$(E).2F("mg");E.l0=q;E.6k=C(){J l6=1f.2w(\'21\');l6.1V=\'4m\';l6.1m=\'T3\';q.1v.6S(l6,q);q.l0.OM(l6);q.l0.Cw(q);q.1g.1K=\'4Y\';q.1g.1T=\'-SY\'};if(q.4X!=-1&&q.5a>=q.4X){E.2K=1b}14{E.2K=1a}q.5a++;q.OZ=E}14{6H(\'f3: 9B a 4m 21 E\')}};q.Cw=C(E){J dA=1f.2w(\'1x\');J 9k=1f.2w(\'2e\');9k.1P=32+\'/2J/T0.3y\';9k.6A=\'aS\';9k.3p("1g","52:ce;9X:4f;");dA.E=E;9k.E=E;dA.hp=E.hp;9k.3V=C(){q.E.1v.5B(q.1v.E);q.1v.1v.5B(q.1v);q.E.l0.5a--;q.E.l0.OZ.2K=1a;N 1a};J V=E.V;J rY=63;if(V.Y>rY){V=V.5p(0,20)+\'[...]\'+V.5p(V.Y-(rY-20),V.Y)}dA.1X(9k);dA.1X(1f.aN(V));q.8h.1X(dA)};q.fo=C(){J 8f=1c 3r();1j(J i=0;i \'+5z(2x));9k.oi=q;9k.3V=C(){q.1v.1v.5B(q.1v);q.oi.5a--;if(q.oi.5a==0&&q.oi.Ou){q.oi.Ou()}};dA.2g(9k);$(q.8h).2g(dA)};q.S9=C(){}};C 5z(2x){if(2x==1d)N 1d;J 7n="/";if(2x.3R("\\\\")!=-1)7n="\\\\";Qh=2x.5p(2x.ah(7n)+1,2x.Y);N Qh}C Sc(2x){Qe=2x.5p(0,2x.ah("/"));N Qe}C C7(2x){if(!2x||2x=="")N"";J 3Z=5z(2x).3Z(\'.\');if(3Z.Y>1)N 3Z[3Z.Y-1].3t();N\'\'}C En(2x){if(1B.2j.6D)N"";if(2x.6N(\'\\.dv$|\\.S5$|\\.RW$|\\.RV$\')>-1)N"dv";14 if(2x.6N("\\.js$")>-1)N"68";14 if(2x.6N("\\.CN$")>-1)N"CN";14 if(2x.6N("\\.pl$")>-1)N"RS";14 if(2x.6N("\\.Py$")>-1)N"Py";14 if(2x.6N("\\.q0$|\\.8L$|\\.aB$")>-1)N"8L";14 if(2x.6N("\\.aj$")>-1)N"aj";14 N""}C FY(94,lV){if(94>=Px){94=2c.3X(94/Px*100)/100+" G"+lV}14 if(94>=PA){94=2c.3X(94/PA*100)/100+" M"+lV}14 if(94>=5K){94=2c.3X(94/5K*100)/100+" K"+lV}14{94=94+" "+lV}N 94}C Np(5I,kS){J jX=1c lZ({RY:D3*24*10,3m:\'\',dd:1b});jX.oS(\'D1\',{5I:5I,kS:kS})}C CM(){J jX=1c lZ({});N jX.2d(\'D1\')}C RZ(){J jX=1c lZ({});jX.42(\'D1\')}C lW(E){if(E.1r(\'gI\')&&E.1r(\'gI\')==\'1\'){N E}J CX=$(E).3x(\'2e\');if(CX.Y)CX.1t(C(2e){if(2e.Q3)2e.1P=2e.Q3});N E}J hY=1a;C uN(){if(hY){1c 1z.D0(\'Em\');hY=1a}}C A9(){hY=1b;5C(\'uN()\',SF)}C 9G(3B){if(28 3B.gf!="1R"){3B.gf=C(){N 1a}}14 if(28 3B.1g.kR!="1R"){J PV=3B.1g.kR;3B.1g.kR="4s"}if($(3B).3x(\'21[1V="26"]\').Y){$(3B).3x(\'21[1V="26"]\').1t(C(E){if(28 E.gf!="1R"){E.gf=C(){N 1b}}14 if(28 E.1g.kR!="1R"){E.1g.kR=PV}})}}C 7V(E,5A,nE,LW){E=$(E);if(28(5A)=="1R"||5A==1d){5A=2Z.9F($(E))}14{5A=$(5A)}if(28(nE)=="1R"||nE==1d){nE=0}J 91=C(){if(!E)N;J 1H=0;if(5A==1L){51=E.6c();1H=51.1H}14{PX=5A.6c();PW=E.6c();1H=PW.1H-PX.1H}J wh;if(5A==1L){wh=1f.aC.3H()}14{wh=5A.3H();if(1B.2j.IE&&5A.2s(\'1p\')){wh=2f(5A.2s(\'1p\'))}}J LY=2f(E.2s(\'9T\'))||0;J LX=2f(E.2s(\'Di\'))||0;J cI=2f((5A!=1L?5A.2s(\'CQ\'):0))||0;E.1I({1p:(2c.4X(0,wh-1H-LY-LX-nE))+\'px\'});E.8q("6w")};91();if(!LW){1q.2h(1L,\'6w\',91)}N 91}C Su(3q,d7){J tr,tl,bl,br;if(d7==1d){tr=tl=bl=br}14{tr=(d7==\'1H\'||d7==\'tr\');tl=(d7==\'1H\'||d7==\'tl\');bl=(d7==\'4A\'||d7==\'bl\');br=(d7==\'4A\'||d7==\'br\')}if(br||bl){J qY=1c 1e(\'1x\');qY.1I({7H:\'-7Q\',fm:1,1l:\'100%\'});qY.2C=(bl?\'<1x 1g="5c: 3N; 1l: 7Q; 7z-4b: bY(aF, aF, aF); 1p: 7Q; eo: 1T;7z-7W:2o(\'+32+\'/2J/pH/Ss.dl);">\':\'\')+(br?\'<1x 1g="52-1g: 4s; 5c: 3N; eo: 6C; 7z-4b: bY(aF, aF, aF); 1p: 7Q; 1l: 7Q;7z-7W:2o(\'+32+\'/2J/pH/TA.dl);">\':\'\');3q.1X(qY)}if(tr||tl){J mk=1c 1e(\'1x\');mk.1I({9T:\'-7Q\',fm:1,1l:\'100%\'});mk.2C=(tl?\'<1x 1g="5c: 3N; 1l: 7Q; 7z-4b: bY(aF, aF, aF); 1p: 7Q; eo: 1T;7z-7W:2o(\'+32+\'/2J/pH/US.dl);">\':\'\')+(tr?\'<1x 1g="52-1g: 4s; 5c: 3N; eo: 6C; 7z-4b: bY(aF, aF, aF); 1p: 7Q; 1l: 7Q;7z-7W:2o(\'+32+\'/2J/pH/UR.dl);">\':\'\');if(3q.3z){3q.6S(mk,3q.3z)}14{3q.1X(mk)}}}oM=2q.2r({id:1R,Ct:1R,al:1a,9h:1a,k5:1R,eF:1R,UQ:1R,pA:1R,2y:C(id,Cz){q.id=id;q.k5=1c 3a();q.eF=1c 3a();q.D5=1c 3a();q.pA=1c 3a();if(Cz)q.L0(Cz)},Dk:C(id,al,9h){q.Ct=id;q.al=(al=="1"?1b:1a);q.9h=(9h=="1"?1b:1a)},G2:C(){N q.Ct},Nb:C(){N q.al},MH:C(){N q.9h},aD:C(pL){N q.k5.2d(pL)},GC:C(){N q.eF},zS:C(pL,M1){q.k5.2u(pL,M1)},Da:C(Mg){q.eF=Mg},CF:C(pB){N q.D5.2d(pB)},Ff:C(pB){N q.pA.2d(pB)},LP:C(CU,CW,KW){J dK=1c 5u();dK.3l("5g","UW");J i=0;q.k5.1t(C(2k){dK.3l("Md"+i,2k.1Y);dK.3l("Mc"+i,2k.V);i++});if(CU&&CW){dK.3l("Md"+i,"DA");dK.3l("Mc"+i,CW);dK.3l("UJ",CU)}dK.2G=KW;dK.7K()},L0:C(aw){J eF=1c 3a();1j(J i=0;i