Version Notes
1.6.1.0
Download this release
Release Info
Developer | Magento Core Team |
Extension | Mage_Downloader |
Version | 1.6.1.0 |
Comparing to | |
See all releases |
Version 1.6.1.0
- .htaccess +186 -0
- downloader/.htaccess +11 -0
- downloader/Maged/Connect.php +467 -0
- downloader/Maged/Connect/Frontend.php +149 -0
- downloader/Maged/Controller.php +977 -0
- downloader/Maged/Exception.php +37 -0
- downloader/Maged/Model.php +99 -0
- downloader/Maged/Model/Config.php +84 -0
- downloader/Maged/Model/Config/Abstract.php +134 -0
- downloader/Maged/Model/Config/Community.php +112 -0
- downloader/Maged/Model/Config/Interface.php +90 -0
- downloader/Maged/Model/Connect.php +491 -0
- downloader/Maged/Model/Connect/Request.php +43 -0
- downloader/Maged/Model/Dowloader.php +30 -0
- downloader/Maged/Model/Session.php +224 -0
- downloader/Maged/View.php +155 -0
- downloader/config.ini +1 -0
- downloader/index.php +36 -0
- downloader/js/prototype.js +3277 -0
- downloader/lib/Mage/Archive.php +222 -0
- downloader/lib/Mage/Archive/Abstract.php +84 -0
- downloader/lib/Mage/Archive/Bz.php +79 -0
- downloader/lib/Mage/Archive/Gz.php +77 -0
- downloader/lib/Mage/Archive/Interface.php +53 -0
- downloader/lib/Mage/Archive/Tar.php +372 -0
- downloader/lib/Mage/Autoload/Simple.php +52 -0
- downloader/lib/Mage/Connect/Channel/Generator.php +63 -0
- downloader/lib/Mage/Connect/Channel/Parser.php +25 -0
- downloader/lib/Mage/Connect/Channel/VO.php +113 -0
- downloader/lib/Mage/Connect/Command.php +390 -0
- downloader/lib/Mage/Connect/Command/Channels.php +189 -0
- downloader/lib/Mage/Connect/Command/Channels_Header.php +104 -0
- downloader/lib/Mage/Connect/Command/Config.php +213 -0
- downloader/lib/Mage/Connect/Command/Config_Header.php +100 -0
- downloader/lib/Mage/Connect/Command/Install.php +567 -0
- downloader/lib/Mage/Connect/Command/Install_Header.php +237 -0
- downloader/lib/Mage/Connect/Command/Package.php +204 -0
- downloader/lib/Mage/Connect/Command/Package_Header.php +76 -0
- downloader/lib/Mage/Connect/Command/Registry.php +364 -0
- downloader/lib/Mage/Connect/Command/Registry_Header.php +84 -0
- downloader/lib/Mage/Connect/Command/Remote.php +231 -0
- downloader/lib/Mage/Connect/Command/Remote_Header.php +88 -0
- downloader/lib/Mage/Connect/Config.php +464 -0
- downloader/lib/Mage/Connect/Converter.php +336 -0
- downloader/lib/Mage/Connect/Frontend.php +251 -0
- downloader/lib/Mage/Connect/Frontend/CLI.php +456 -0
- downloader/lib/Mage/Connect/Ftp.php +523 -0
- downloader/lib/Mage/Connect/Loader.php +51 -0
- downloader/lib/Mage/Connect/Loader/Ftp.php +155 -0
- downloader/lib/Mage/Connect/Package.php +1499 -0
- downloader/lib/Mage/Connect/Package/Extension.php +1 -0
- downloader/lib/Mage/Connect/Package/Hotfix.php +137 -0
- downloader/lib/Mage/Connect/Package/Maintainer.php +1 -0
- downloader/lib/Mage/Connect/Package/Reader.php +150 -0
- downloader/lib/Mage/Connect/Package/Target.php +126 -0
- downloader/lib/Mage/Connect/Package/VO.php +96 -0
- downloader/lib/Mage/Connect/Package/Writer.php +177 -0
- downloader/lib/Mage/Connect/Packager.php +909 -0
- downloader/lib/Mage/Connect/Repository.php +1 -0
- downloader/lib/Mage/Connect/Repository/Abstract.php +1 -0
- downloader/lib/Mage/Connect/Repository/Channel.php +1 -0
- downloader/lib/Mage/Connect/Repository/Channel/Abstract.php +1 -0
- downloader/lib/Mage/Connect/Repository/Channel/Commercial.php +1 -0
- downloader/lib/Mage/Connect/Repository/Channel/Community.php +1 -0
- downloader/lib/Mage/Connect/Repository/Channel/Core.php +1 -0
- downloader/lib/Mage/Connect/Repository/Local.php +1 -0
- downloader/lib/Mage/Connect/Rest.php +366 -0
- downloader/lib/Mage/Connect/Singleconfig.php +934 -0
- downloader/lib/Mage/Connect/Structures/Graph.php +248 -0
- downloader/lib/Mage/Connect/Structures/Node.php +257 -0
- downloader/lib/Mage/Connect/Validator.php +440 -0
- downloader/lib/Mage/DB/Exception.php +36 -0
- downloader/lib/Mage/DB/Mysqli.php +532 -0
- downloader/lib/Mage/Exception.php +35 -0
- downloader/lib/Mage/HTTP/Client.php +84 -0
- downloader/lib/Mage/HTTP/Client/Curl.php +556 -0
- downloader/lib/Mage/HTTP/Client/Socket.php +537 -0
- downloader/lib/Mage/HTTP/IClient.php +145 -0
- downloader/lib/Mage/System/Args.php +102 -0
- downloader/lib/Mage/System/Dirs.php +104 -0
- downloader/lib/Mage/Xml/Generator.php +114 -0
- downloader/lib/Mage/Xml/Parser.php +115 -0
- downloader/mage.php +156 -0
- downloader/skin/boxes.css +217 -0
- downloader/skin/ie7boxes.css +27 -0
- downloader/skin/ieboxes.css +29 -0
- downloader/skin/images/Magento_Connect.jpg +0 -0
- downloader/skin/images/ajax-loader-tr.gif +0 -0
- downloader/skin/images/btn_bg.gif +0 -0
- downloader/skin/images/header_bg.gif +0 -0
- downloader/skin/images/logo.gif +0 -0
- downloader/skin/images/nav_bg.gif +0 -0
- downloader/skin/images/nav_separator.gif +0 -0
- downloader/skin/install/boxes.css +414 -0
- downloader/skin/install/clears.css +70 -0
- downloader/skin/install/ie7minus.css +40 -0
- downloader/skin/install/iestyles.css +78 -0
- downloader/skin/install/images/error_msg_icon.gif +0 -0
- downloader/skin/install/images/footer_bg.gif +0 -0
- downloader/skin/install/images/footer_container_bg.gif +0 -0
- downloader/skin/install/images/footer_info_separator.gif +0 -0
- downloader/skin/install/images/footer_informational_bg.gif +0 -0
- downloader/skin/install/images/footer_left.gif +0 -0
- downloader/skin/install/images/footer_legality_bg.gif +0 -0
- downloader/skin/install/images/footer_right.gif +0 -0
- downloader/skin/install/images/header_bg.gif +0 -0
- downloader/skin/install/images/header_nav_bg.gif +0 -0
- downloader/skin/install/images/header_top_bg.jpg +0 -0
- downloader/skin/install/images/header_top_container_bg.jpg +0 -0
- downloader/skin/install/images/logo.gif +0 -0
- downloader/skin/install/images/main_bg.gif +0 -0
- downloader/skin/install/images/main_container_bg.gif +0 -0
- downloader/skin/install/images/note_msg_icon.gif +0 -0
- downloader/skin/install/images/success_msg_icon.gif +0 -0
- downloader/skin/install/images/validation_advice_bg.gif +0 -0
- downloader/skin/install/reset.css +83 -0
- downloader/template/.htaccess +2 -0
- downloader/template/connect/iframe.phtml +121 -0
- downloader/template/connect/packages.phtml +221 -0
- downloader/template/connect/packages_prepare.phtml +78 -0
- downloader/template/exception.phtml +36 -0
- downloader/template/footer.phtml +40 -0
- downloader/template/header.phtml +73 -0
- downloader/template/index.phtml +36 -0
- downloader/template/install/download.phtml +184 -0
- downloader/template/install/footer.phtml +49 -0
- downloader/template/install/header.phtml +99 -0
- downloader/template/install/writable.phtml +40 -0
- downloader/template/login.phtml +43 -0
- downloader/template/messages.phtml +39 -0
- downloader/template/noroute.phtml +31 -0
- downloader/template/settings.phtml +166 -0
- downloader/template/writable.phtml +35 -0
- index.php +80 -0
- mage +54 -0
- package.xml +18 -0
.htaccess
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
############################################
|
2 |
+
## uncomment these lines for CGI mode
|
3 |
+
## make sure to specify the correct cgi php binary file name
|
4 |
+
## it might be /cgi-bin/php-cgi
|
5 |
+
|
6 |
+
# Action php5-cgi /cgi-bin/php5-cgi
|
7 |
+
# AddHandler php5-cgi .php
|
8 |
+
|
9 |
+
############################################
|
10 |
+
## GoDaddy specific options
|
11 |
+
|
12 |
+
# Options -MultiViews
|
13 |
+
|
14 |
+
## you might also need to add this line to php.ini
|
15 |
+
## cgi.fix_pathinfo = 1
|
16 |
+
## if it still doesn't work, rename php.ini to php5.ini
|
17 |
+
|
18 |
+
############################################
|
19 |
+
## this line is specific for 1and1 hosting
|
20 |
+
|
21 |
+
#AddType x-mapp-php5 .php
|
22 |
+
#AddHandler x-mapp-php5 .php
|
23 |
+
|
24 |
+
############################################
|
25 |
+
## default index file
|
26 |
+
|
27 |
+
DirectoryIndex index.php
|
28 |
+
|
29 |
+
<IfModule mod_php5.c>
|
30 |
+
|
31 |
+
############################################
|
32 |
+
## adjust memory limit
|
33 |
+
|
34 |
+
# php_value memory_limit 64M
|
35 |
+
php_value memory_limit 256M
|
36 |
+
php_value max_execution_time 18000
|
37 |
+
|
38 |
+
############################################
|
39 |
+
## disable magic quotes for php request vars
|
40 |
+
|
41 |
+
php_flag magic_quotes_gpc off
|
42 |
+
|
43 |
+
############################################
|
44 |
+
## disable automatic session start
|
45 |
+
## before autoload was initialized
|
46 |
+
|
47 |
+
php_flag session.auto_start off
|
48 |
+
|
49 |
+
############################################
|
50 |
+
## enable resulting html compression
|
51 |
+
|
52 |
+
#php_flag zlib.output_compression on
|
53 |
+
|
54 |
+
###########################################
|
55 |
+
# disable user agent verification to not break multiple image upload
|
56 |
+
|
57 |
+
php_flag suhosin.session.cryptua off
|
58 |
+
|
59 |
+
###########################################
|
60 |
+
# turn off compatibility with PHP4 when dealing with objects
|
61 |
+
|
62 |
+
php_flag zend.ze1_compatibility_mode Off
|
63 |
+
|
64 |
+
</IfModule>
|
65 |
+
|
66 |
+
<IfModule mod_security.c>
|
67 |
+
###########################################
|
68 |
+
# disable POST processing to not break multiple image upload
|
69 |
+
|
70 |
+
SecFilterEngine Off
|
71 |
+
SecFilterScanPOST Off
|
72 |
+
</IfModule>
|
73 |
+
|
74 |
+
<IfModule mod_deflate.c>
|
75 |
+
|
76 |
+
############################################
|
77 |
+
## enable apache served files compression
|
78 |
+
## http://developer.yahoo.com/performance/rules.html#gzip
|
79 |
+
|
80 |
+
# Insert filter on all content
|
81 |
+
###SetOutputFilter DEFLATE
|
82 |
+
# Insert filter on selected content types only
|
83 |
+
#AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
|
84 |
+
|
85 |
+
# Netscape 4.x has some problems...
|
86 |
+
#BrowserMatch ^Mozilla/4 gzip-only-text/html
|
87 |
+
|
88 |
+
# Netscape 4.06-4.08 have some more problems
|
89 |
+
#BrowserMatch ^Mozilla/4\.0[678] no-gzip
|
90 |
+
|
91 |
+
# MSIE masquerades as Netscape, but it is fine
|
92 |
+
#BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
|
93 |
+
|
94 |
+
# Don't compress images
|
95 |
+
#SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
|
96 |
+
|
97 |
+
# Make sure proxies don't deliver the wrong content
|
98 |
+
#Header append Vary User-Agent env=!dont-vary
|
99 |
+
|
100 |
+
</IfModule>
|
101 |
+
|
102 |
+
<IfModule mod_ssl.c>
|
103 |
+
|
104 |
+
############################################
|
105 |
+
## make HTTPS env vars available for CGI mode
|
106 |
+
|
107 |
+
SSLOptions StdEnvVars
|
108 |
+
|
109 |
+
</IfModule>
|
110 |
+
|
111 |
+
<IfModule mod_rewrite.c>
|
112 |
+
|
113 |
+
############################################
|
114 |
+
## enable rewrites
|
115 |
+
|
116 |
+
Options +FollowSymLinks
|
117 |
+
RewriteEngine on
|
118 |
+
|
119 |
+
############################################
|
120 |
+
## you can put here your magento root folder
|
121 |
+
## path relative to web root
|
122 |
+
|
123 |
+
#RewriteBase /magento/
|
124 |
+
|
125 |
+
############################################
|
126 |
+
## workaround for HTTP authorization
|
127 |
+
## in CGI environment
|
128 |
+
|
129 |
+
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
130 |
+
|
131 |
+
############################################
|
132 |
+
## always send 404 on missing files in these folders
|
133 |
+
|
134 |
+
RewriteCond %{REQUEST_URI} !^/(media|skin|js)/
|
135 |
+
|
136 |
+
############################################
|
137 |
+
## never rewrite for existing files, directories and links
|
138 |
+
|
139 |
+
RewriteCond %{REQUEST_FILENAME} !-f
|
140 |
+
RewriteCond %{REQUEST_FILENAME} !-d
|
141 |
+
RewriteCond %{REQUEST_FILENAME} !-l
|
142 |
+
|
143 |
+
############################################
|
144 |
+
## rewrite everything else to index.php
|
145 |
+
|
146 |
+
RewriteRule .* index.php [L]
|
147 |
+
|
148 |
+
</IfModule>
|
149 |
+
|
150 |
+
|
151 |
+
############################################
|
152 |
+
## Prevent character encoding issues from server overrides
|
153 |
+
## If you still have problems, use the second line instead
|
154 |
+
|
155 |
+
AddDefaultCharset Off
|
156 |
+
#AddDefaultCharset UTF-8
|
157 |
+
|
158 |
+
<IfModule mod_expires.c>
|
159 |
+
|
160 |
+
############################################
|
161 |
+
## Add default Expires header
|
162 |
+
## http://developer.yahoo.com/performance/rules.html#expires
|
163 |
+
|
164 |
+
ExpiresDefault "access plus 1 year"
|
165 |
+
|
166 |
+
</IfModule>
|
167 |
+
|
168 |
+
############################################
|
169 |
+
## By default allow all access
|
170 |
+
|
171 |
+
Order allow,deny
|
172 |
+
Allow from all
|
173 |
+
|
174 |
+
###########################################
|
175 |
+
## Deny access to release notes to prevent disclosure of the installed Magento version
|
176 |
+
|
177 |
+
<Files RELEASE_NOTES.txt>
|
178 |
+
order allow,deny
|
179 |
+
deny from all
|
180 |
+
</Files>
|
181 |
+
|
182 |
+
############################################
|
183 |
+
## If running in cluster environment, uncomment this
|
184 |
+
## http://developer.yahoo.com/performance/rules.html#etags
|
185 |
+
|
186 |
+
#FileETag none
|
downloader/.htaccess
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<IfModule mod_deflate.c>
|
2 |
+
|
3 |
+
RemoveOutputFilter DEFLATE
|
4 |
+
RemoveOutputFilter GZIP
|
5 |
+
|
6 |
+
</IfModule>
|
7 |
+
|
8 |
+
<Files ~ "\.(cfg|ini|xml)$">
|
9 |
+
order allow,deny
|
10 |
+
deny from all
|
11 |
+
</Files>
|
downloader/Maged/Connect.php
ADDED
@@ -0,0 +1,467 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
error_reporting(E_ALL & ~E_NOTICE);
|
28 |
+
|
29 |
+
// just a shortcut
|
30 |
+
if (!defined('DS')) {
|
31 |
+
define('DS', DIRECTORY_SEPARATOR);
|
32 |
+
}
|
33 |
+
|
34 |
+
// add Mage lib in include_path if needed
|
35 |
+
$_includePath = get_include_path();
|
36 |
+
$_libDir = dirname(dirname(__FILE__)) . DS . 'lib';
|
37 |
+
if (strpos($_includePath, $_libDir) === false) {
|
38 |
+
if (substr($_includePath, 0, 2) === '.' . PATH_SEPARATOR) {
|
39 |
+
$_includePath = '.' . PATH_SEPARATOR . $_libDir . PATH_SEPARATOR . substr($_includePath, 2);
|
40 |
+
} else {
|
41 |
+
$_includePath = $_libDir . PATH_SEPARATOR . $_includePath;
|
42 |
+
}
|
43 |
+
set_include_path($_includePath);
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Class for connect
|
48 |
+
*
|
49 |
+
* @category Mage
|
50 |
+
* @package Mage_Connect
|
51 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
52 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
53 |
+
*/
|
54 |
+
class Maged_Connect
|
55 |
+
{
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Object of config
|
59 |
+
*
|
60 |
+
* @var Mage_Connect_Config
|
61 |
+
*/
|
62 |
+
protected $_config;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Object of single config
|
66 |
+
*
|
67 |
+
* @var Mage_Connect_Singleconfig
|
68 |
+
*/
|
69 |
+
protected $_sconfig;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Object of frontend
|
73 |
+
*
|
74 |
+
* @var Mage_Connect_Frontend
|
75 |
+
*/
|
76 |
+
protected $_frontend;
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Internal cache for command objects
|
80 |
+
*
|
81 |
+
* @var array
|
82 |
+
*/
|
83 |
+
protected $_cmdCache = array();
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Instance of class
|
87 |
+
*
|
88 |
+
* @var Maged_Connect
|
89 |
+
*/
|
90 |
+
static protected $_instance;
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Constructor
|
94 |
+
*/
|
95 |
+
public function __construct()
|
96 |
+
{
|
97 |
+
$this->getConfig();
|
98 |
+
$this->getSingleConfig();
|
99 |
+
$this->getFrontend();
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Initialize instance
|
104 |
+
*
|
105 |
+
* @return Maged_Connect
|
106 |
+
*/
|
107 |
+
public static function getInstance()
|
108 |
+
{
|
109 |
+
if (!self::$_instance) {
|
110 |
+
self::$_instance = new self;
|
111 |
+
}
|
112 |
+
return self::$_instance;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Retrieve object of config and set it to Mage_Connect_Command
|
117 |
+
*
|
118 |
+
* @return Mage_Connect_Config
|
119 |
+
*/
|
120 |
+
public function getConfig()
|
121 |
+
{
|
122 |
+
if (!$this->_config) {
|
123 |
+
$this->_config = new Mage_Connect_Config();
|
124 |
+
$ftp=$this->_config->__get('remote_config');
|
125 |
+
if(!empty($ftp)){
|
126 |
+
$packager = new Mage_Connect_Packager();
|
127 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
128 |
+
$this->_config=$config;
|
129 |
+
$this->_sconfig=$cache;
|
130 |
+
}
|
131 |
+
$this->_config->magento_root = dirname(dirname(__FILE__)).DS.'..';
|
132 |
+
Mage_Connect_Command::setConfigObject($this->_config);
|
133 |
+
}
|
134 |
+
return $this->_config;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Retrieve object of single config and set it to Mage_Connect_Command
|
139 |
+
*
|
140 |
+
* @param bool $reload
|
141 |
+
* @return Mage_Connect_Singleconfig
|
142 |
+
*/
|
143 |
+
public function getSingleConfig($reload = false)
|
144 |
+
{
|
145 |
+
if(!$this->_sconfig || $reload) {
|
146 |
+
$this->_sconfig = new Mage_Connect_Singleconfig($this->getConfig()->magento_root . DIRECTORY_SEPARATOR . $this->getConfig()->downloader_path . DIRECTORY_SEPARATOR . Mage_Connect_Singleconfig::DEFAULT_SCONFIG_FILENAME);
|
147 |
+
}
|
148 |
+
Mage_Connect_Command::setSconfig($this->_sconfig);
|
149 |
+
return $this->_sconfig;
|
150 |
+
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Retrieve object of frontend and set it to Mage_Connect_Command
|
155 |
+
*
|
156 |
+
* @return Maged_Connect_Frontend
|
157 |
+
*/
|
158 |
+
public function getFrontend()
|
159 |
+
{
|
160 |
+
if (!$this->_frontend) {
|
161 |
+
$this->_frontend = new Maged_Connect_Frontend();
|
162 |
+
Mage_Connect_Command::setFrontendObject($this->_frontend);
|
163 |
+
}
|
164 |
+
return $this->_frontend;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Retrieve lof from frontend
|
169 |
+
*
|
170 |
+
* @return array
|
171 |
+
*/
|
172 |
+
public function getLog()
|
173 |
+
{
|
174 |
+
return $this->getFrontend()->getLog();
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Retrieve output from frontend
|
179 |
+
*
|
180 |
+
* @return array
|
181 |
+
*/
|
182 |
+
public function getOutput()
|
183 |
+
{
|
184 |
+
return $this->getFrontend()->getOutput();
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Clean registry
|
189 |
+
*
|
190 |
+
* @return Maged_Connect
|
191 |
+
*/
|
192 |
+
public function cleanSconfig()
|
193 |
+
{
|
194 |
+
$this->getSingleConfig()->clear();
|
195 |
+
return $this;
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Delete directory recursively
|
200 |
+
*
|
201 |
+
* @param string $path
|
202 |
+
* @return Maged_Connect
|
203 |
+
*/
|
204 |
+
public function delTree($path) {
|
205 |
+
if (@is_dir($path)) {
|
206 |
+
$entries = @scandir($path);
|
207 |
+
foreach ($entries as $entry) {
|
208 |
+
if ($entry != '.' && $entry != '..') {
|
209 |
+
$this->delTree($path.DS.$entry);
|
210 |
+
}
|
211 |
+
}
|
212 |
+
@rmdir($path);
|
213 |
+
} else {
|
214 |
+
@unlink($path);
|
215 |
+
}
|
216 |
+
return $this;
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Run commands from Mage_Connect_Command
|
221 |
+
*
|
222 |
+
* @param string $command
|
223 |
+
* @param array $options
|
224 |
+
* @param array $params
|
225 |
+
* @return
|
226 |
+
*/
|
227 |
+
public function run($command, $options=array(), $params=array())
|
228 |
+
{
|
229 |
+
@set_time_limit(0);
|
230 |
+
@ini_set('memory_limit', '256M');
|
231 |
+
|
232 |
+
if (empty($this->_cmdCache[$command])) {
|
233 |
+
Mage_Connect_Command::getCommands();
|
234 |
+
/**
|
235 |
+
* @var $cmd Mage_Connect_Command
|
236 |
+
*/
|
237 |
+
$cmd = Mage_Connect_Command::getInstance($command);
|
238 |
+
if ($cmd instanceof Mage_Connect_Error) {
|
239 |
+
return $cmd;
|
240 |
+
}
|
241 |
+
$this->_cmdCache[$command] = $cmd;
|
242 |
+
} else {
|
243 |
+
/**
|
244 |
+
* @var $cmd Mage_Connect_Command
|
245 |
+
*/
|
246 |
+
$cmd = $this->_cmdCache[$command];
|
247 |
+
}
|
248 |
+
$ftp=$this->getConfig()->remote_config;
|
249 |
+
if(strlen($ftp)>0){
|
250 |
+
$options=array_merge($options, array('ftp'=>$ftp));
|
251 |
+
}
|
252 |
+
$cmd->run($command, $options, $params);
|
253 |
+
if ($cmd->ui()->hasErrors()) {
|
254 |
+
return false;
|
255 |
+
} else {
|
256 |
+
return true;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
public function setRemoteConfig($uri) #$host, $user, $password, $path='', $port=null)
|
261 |
+
{
|
262 |
+
#$uri = 'ftp://' . $user . ':' . $password . '@' . $host . (is_numeric($port) ? ':' . $port : '') . '/' . trim($path, '/') . '/';
|
263 |
+
//$this->run('config-set', array(), array('remote_config', $uri));
|
264 |
+
//$this->run('config-set', array('ftp'=>$uri), array('remote_config', $uri));
|
265 |
+
$this->getConfig()->remote_config=$uri;
|
266 |
+
return $this;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
*
|
271 |
+
* @param array $errors Error messages
|
272 |
+
* @return Maged_Connect
|
273 |
+
*/
|
274 |
+
public function showConnectErrors($errors)
|
275 |
+
{
|
276 |
+
echo '<script type="text/javascript">';
|
277 |
+
$run = new Maged_Model_Connect_Request();
|
278 |
+
if ($callback = $run->get('failure_callback')) {
|
279 |
+
if (is_array($callback)) {
|
280 |
+
call_user_func_array($callback, array($result));
|
281 |
+
} else {
|
282 |
+
echo $callback;
|
283 |
+
}
|
284 |
+
}
|
285 |
+
echo '</script>';
|
286 |
+
|
287 |
+
return $this;
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Run Mage_Connect_Command with html output console style
|
292 |
+
*
|
293 |
+
* @param array|Maged_Model $runParams command, options, params,
|
294 |
+
* comment, success_callback, failure_callback
|
295 |
+
*/
|
296 |
+
public function runHtmlConsole($runParams)
|
297 |
+
{
|
298 |
+
if (function_exists('apache_setenv')) {
|
299 |
+
apache_setenv('no-gzip', '1');
|
300 |
+
}
|
301 |
+
@ini_set('zlib.output_compression', 0);
|
302 |
+
@ini_set('implicit_flush', 1);
|
303 |
+
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
|
304 |
+
ob_implicit_flush();
|
305 |
+
|
306 |
+
$fe = $this->getFrontend();
|
307 |
+
$oldLogStream = $fe->getLogStream();
|
308 |
+
$fe->setLogStream('stdout');
|
309 |
+
|
310 |
+
if ($runParams instanceof Maged_Model) {
|
311 |
+
$run = $runParams;
|
312 |
+
} elseif (is_array($runParams)) {
|
313 |
+
$run = new Maged_Model_Connect_Request($runParams);
|
314 |
+
} elseif (is_string($runParams)) {
|
315 |
+
$run = new Maged_Model_Connect_Request(array('comment'=>$runParams));
|
316 |
+
} else {
|
317 |
+
throw Maged_Exception("Invalid run parameters");
|
318 |
+
}
|
319 |
+
|
320 |
+
if (!$run->get('no-header')) {
|
321 |
+
?>
|
322 |
+
<html><head><style type="text/css">
|
323 |
+
body { margin:0px;
|
324 |
+
padding:3px;
|
325 |
+
background:black;
|
326 |
+
color:#2EC029;
|
327 |
+
font:normal 11px Lucida Console, Courier New, serif;
|
328 |
+
}
|
329 |
+
</style></head><body>
|
330 |
+
<script type="text/javascript">
|
331 |
+
if (parent && parent.disableInputs) {
|
332 |
+
parent.disableInputs(true);
|
333 |
+
}
|
334 |
+
if (typeof auto_scroll=='undefined') {
|
335 |
+
var auto_scroll = window.setInterval(console_scroll, 10);
|
336 |
+
}
|
337 |
+
function console_scroll()
|
338 |
+
{
|
339 |
+
if (typeof top.$ != 'function') {
|
340 |
+
return;
|
341 |
+
}
|
342 |
+
if (top.$('connect_iframe_scroll').checked) {
|
343 |
+
document.body.scrollTop+=3;
|
344 |
+
}
|
345 |
+
}
|
346 |
+
function show_message(message, newline)
|
347 |
+
{
|
348 |
+
var bodyElement = document.getElementsByTagName('body')[0];
|
349 |
+
if (typeof newline == 'undefined') {
|
350 |
+
newline = true
|
351 |
+
}
|
352 |
+
if (newline) {
|
353 |
+
bodyElement.innerHTML += '<br/>';
|
354 |
+
}
|
355 |
+
bodyElement.innerHTML += message;
|
356 |
+
}
|
357 |
+
function clear_cache(callbacks)
|
358 |
+
{
|
359 |
+
if (typeof top.Ajax != 'object') {
|
360 |
+
return;
|
361 |
+
}
|
362 |
+
var message = 'Exception during cache and session cleaning';
|
363 |
+
var url = window.location.href.split('?')[0] + '?A=cleanCache';
|
364 |
+
var intervalID = setInterval(function() {show_message('.', false); }, 500);
|
365 |
+
var clean = 0;
|
366 |
+
var maintenance = 0;
|
367 |
+
if (window.location.href.indexOf('clean_sessions') >= 0) {
|
368 |
+
clean = 1;
|
369 |
+
}
|
370 |
+
if (window.location.href.indexOf('maintenance') >= 0) {
|
371 |
+
maintenance = 1;
|
372 |
+
}
|
373 |
+
|
374 |
+
new top.Ajax.Request(url, {
|
375 |
+
method: 'post',
|
376 |
+
parameters: {clean_sessions:clean, maintenance:maintenance},
|
377 |
+
onCreate: function() {
|
378 |
+
show_message('Cleaning cache');
|
379 |
+
show_message('');
|
380 |
+
},
|
381 |
+
onSuccess: function(transport, json) {
|
382 |
+
var result = true;
|
383 |
+
try{
|
384 |
+
var response = eval('(' + transport.responseText + ')');
|
385 |
+
if (typeof response.result != 'undefined') {
|
386 |
+
result = response.result;
|
387 |
+
} else {
|
388 |
+
result = false;
|
389 |
+
}
|
390 |
+
if (typeof response.message != 'undefined') {
|
391 |
+
if (response.message.length > 0) {
|
392 |
+
message = response.message;
|
393 |
+
} else {
|
394 |
+
message = 'Cache cleaned successfully';
|
395 |
+
}
|
396 |
+
}
|
397 |
+
} catch (ex){
|
398 |
+
result = false;
|
399 |
+
}
|
400 |
+
if (result) {
|
401 |
+
callbacks.success();
|
402 |
+
} else {
|
403 |
+
callbacks.fail();
|
404 |
+
}
|
405 |
+
},
|
406 |
+
onFailure: function() {
|
407 |
+
callbacks.fail();
|
408 |
+
},
|
409 |
+
onComplete: function(transport) {
|
410 |
+
clearInterval(intervalID);
|
411 |
+
show_message(message);
|
412 |
+
}
|
413 |
+
});
|
414 |
+
}
|
415 |
+
</script>
|
416 |
+
<?php
|
417 |
+
}
|
418 |
+
echo htmlspecialchars($run->get('comment'));
|
419 |
+
|
420 |
+
if ($command = $run->get('command')) {
|
421 |
+
$result = $this->run($command, $run->get('options'), $run->get('params'));
|
422 |
+
|
423 |
+
if ($this->getFrontend()->hasErrors()) {
|
424 |
+
echo "<br/>CONNECT ERROR: ";
|
425 |
+
foreach ($this->getFrontend()->getErrors(false) as $error) {
|
426 |
+
echo nl2br($error[1]);
|
427 |
+
echo '<br/>';
|
428 |
+
}
|
429 |
+
}
|
430 |
+
echo '<script type="text/javascript">';
|
431 |
+
if ($this->getFrontend()->hasErrors()) {
|
432 |
+
if ($callback = $run->get('failure_callback')) {
|
433 |
+
if (is_array($callback)) {
|
434 |
+
call_user_func_array($callback, array($result));
|
435 |
+
} else {
|
436 |
+
echo $callback;
|
437 |
+
}
|
438 |
+
}
|
439 |
+
} else {
|
440 |
+
if (!$run->get('no-footer')) {
|
441 |
+
if ($callback = $run->get('success_callback')) {
|
442 |
+
if (is_array($callback)) {
|
443 |
+
call_user_func_array($callback, array($result));
|
444 |
+
} else {
|
445 |
+
echo $callback;
|
446 |
+
}
|
447 |
+
}
|
448 |
+
}
|
449 |
+
}
|
450 |
+
echo '</script>';
|
451 |
+
} else {
|
452 |
+
$result = false;
|
453 |
+
}
|
454 |
+
if ($this->getFrontend()->getErrors() || !$run->get('no-footer')) {
|
455 |
+
?>
|
456 |
+
<script type="text/javascript">
|
457 |
+
if (parent && parent.disableInputs) {
|
458 |
+
parent.disableInputs(false);
|
459 |
+
}
|
460 |
+
</script>
|
461 |
+
</body></html>
|
462 |
+
<?php
|
463 |
+
$fe->setLogStream($oldLogStream);
|
464 |
+
}
|
465 |
+
return $result;
|
466 |
+
}
|
467 |
+
}
|
downloader/Maged/Connect/Frontend.php
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class frontend
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Connect_Frontend extends Mage_Connect_Frontend
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Log stream or not
|
40 |
+
*
|
41 |
+
* @var string
|
42 |
+
*/
|
43 |
+
protected $_logStream = null;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Output cache
|
47 |
+
*
|
48 |
+
* @var array
|
49 |
+
*/
|
50 |
+
protected $_out = array();
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Set log stream
|
54 |
+
*
|
55 |
+
* @param string|resource $stream 'stdout' or open php stream
|
56 |
+
*/
|
57 |
+
public function setLogStream($stream)
|
58 |
+
{
|
59 |
+
$this->_logStream = $stream;
|
60 |
+
return $this;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Retrieve log stream
|
65 |
+
*
|
66 |
+
* @return string
|
67 |
+
*/
|
68 |
+
public function getLogStream()
|
69 |
+
{
|
70 |
+
return $this->_logStream;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Echo data from executed command
|
75 |
+
*/
|
76 |
+
public function output($data)
|
77 |
+
{
|
78 |
+
|
79 |
+
$this->_out = $data;
|
80 |
+
|
81 |
+
if ('stdout'===$this->_logStream) {
|
82 |
+
if (is_string($data)) {
|
83 |
+
echo $data."<br/>".str_repeat(" ", 256);
|
84 |
+
} elseif (is_array($data)) {
|
85 |
+
$data = array_pop($data);
|
86 |
+
if (!empty($data['message']) && is_string($data['message'])) {
|
87 |
+
echo $data['message']."<br/>".str_repeat(" ", 256);
|
88 |
+
} elseif (!empty($data['data'])) {
|
89 |
+
if (is_string($data['data'])) {
|
90 |
+
echo $data['data']."<br/>".str_repeat(" ", 256);
|
91 |
+
} else {
|
92 |
+
if (isset($data['title'])) {
|
93 |
+
echo $data['title']."<br/>".str_repeat(" ", 256);
|
94 |
+
}
|
95 |
+
if (is_array($data['data'])) {
|
96 |
+
foreach ($data['data'] as $row) {
|
97 |
+
foreach ($row as $msg) {
|
98 |
+
echo " ".$msg;
|
99 |
+
}
|
100 |
+
echo "<br/>".str_repeat(" ", 256);
|
101 |
+
}
|
102 |
+
} else {
|
103 |
+
echo " ".$data['data'];
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
} else {
|
108 |
+
print_r($data);
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Method for ask client about rewrite all files.
|
115 |
+
*
|
116 |
+
* @param $string
|
117 |
+
*/
|
118 |
+
public function confirm($string)
|
119 |
+
{
|
120 |
+
$formId = $_POST['form_id'];
|
121 |
+
echo <<<SCRIPT
|
122 |
+
<script type="text/javascript">
|
123 |
+
if (confirm("{$string}")) {
|
124 |
+
parent.document.getElementById('ignore_local_modification').value=1;
|
125 |
+
parent.onSuccess();
|
126 |
+
if (parent && parent.disableInputs) {
|
127 |
+
parent.disableInputs(false);
|
128 |
+
}
|
129 |
+
window.onload = function () {
|
130 |
+
parent.document.getElementById('{$formId}').submit();
|
131 |
+
parent.document.getElementById('ignore_local_modification').value='';
|
132 |
+
}
|
133 |
+
}
|
134 |
+
</script>
|
135 |
+
SCRIPT;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Retrieve output cache
|
140 |
+
*
|
141 |
+
* @return array
|
142 |
+
*/
|
143 |
+
public function getOutput()
|
144 |
+
{
|
145 |
+
return $this->_out;
|
146 |
+
}
|
147 |
+
|
148 |
+
}
|
149 |
+
|
downloader/Maged/Controller.php
ADDED
@@ -0,0 +1,977 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class Controller
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
final class Maged_Controller
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Request key of action
|
39 |
+
*/
|
40 |
+
const ACTION_KEY = 'A';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Instance of class
|
44 |
+
*
|
45 |
+
* @var Maged_Controller
|
46 |
+
*/
|
47 |
+
private static $_instance;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Current action name
|
51 |
+
*
|
52 |
+
* @var string
|
53 |
+
*/
|
54 |
+
private $_action;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Controller is dispathed flag
|
58 |
+
*
|
59 |
+
* @var bool
|
60 |
+
*/
|
61 |
+
private $_isDispatched = false;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Redirect to URL
|
65 |
+
*
|
66 |
+
* @var string
|
67 |
+
*/
|
68 |
+
private $_redirectUrl;
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Downloader dir path
|
72 |
+
*
|
73 |
+
* @var string
|
74 |
+
*/
|
75 |
+
private $_rootDir;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Magento root dir path
|
79 |
+
*
|
80 |
+
* @var string
|
81 |
+
*/
|
82 |
+
private $_mageDir;
|
83 |
+
|
84 |
+
/**
|
85 |
+
* View instance
|
86 |
+
*
|
87 |
+
* @var Maged_View
|
88 |
+
*/
|
89 |
+
private $_view;
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Connect config instance
|
93 |
+
*
|
94 |
+
* @var Mage_Connect_Config
|
95 |
+
*/
|
96 |
+
private $_config;
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Config instance
|
100 |
+
*
|
101 |
+
* @var Maged_Model_Config
|
102 |
+
*/
|
103 |
+
private $_localConfig;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Session instance
|
107 |
+
*
|
108 |
+
* @var Maged_Model_Session
|
109 |
+
*/
|
110 |
+
private $_session;
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Root dir is writable flag
|
114 |
+
*
|
115 |
+
* @var bool
|
116 |
+
*/
|
117 |
+
private $_writable;
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Use maintenance flag
|
121 |
+
*
|
122 |
+
* @var bool
|
123 |
+
*/
|
124 |
+
protected $_maintenance;
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Maintenance file path
|
128 |
+
*
|
129 |
+
* @var string
|
130 |
+
*/
|
131 |
+
protected $_maintenanceFile;
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Register array for singletons
|
135 |
+
*
|
136 |
+
* @var array
|
137 |
+
*/
|
138 |
+
protected $_singletons = array();
|
139 |
+
|
140 |
+
//////////////////////////// ACTIONS
|
141 |
+
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Get ftp string from post data
|
145 |
+
*
|
146 |
+
* @param array $post post data
|
147 |
+
* @return string FTP Url
|
148 |
+
*/
|
149 |
+
private function getFtpPost($post){
|
150 |
+
if (empty($post['ftp_host'])) {
|
151 |
+
$_POST['ftp'] = '';
|
152 |
+
return '';
|
153 |
+
}
|
154 |
+
$ftp = 'ftp://';
|
155 |
+
$post['ftp_proto'] = 'ftp://';
|
156 |
+
|
157 |
+
if (!empty($post['ftp_path']) && strlen(trim($post['ftp_path'], '\\/')) > 0) {
|
158 |
+
$post['ftp_path'] = '/' . trim($post['ftp_path'], '\\/') . '/';
|
159 |
+
} else {
|
160 |
+
$post['ftp_path'] = '/';
|
161 |
+
}
|
162 |
+
|
163 |
+
$start = stripos($post['ftp_host'],'ftp://');
|
164 |
+
if ($start !== false){
|
165 |
+
$post['ftp_proto'] = 'ftp://';
|
166 |
+
$post['ftp_host'] = substr($post['ftp_host'], $start + 6 - 1);
|
167 |
+
}
|
168 |
+
$start = stripos($post['ftp_host'],'ftps://');
|
169 |
+
if ($start !== false) {
|
170 |
+
$post['ftp_proto'] = 'ftps://';
|
171 |
+
$post['ftp_host'] = substr($post['ftp_host'], $start + 7 - 1);
|
172 |
+
}
|
173 |
+
|
174 |
+
$post['ftp_host'] = trim($post['ftp_host'], '\\/');
|
175 |
+
|
176 |
+
if (!empty($post['ftp_login']) && !empty($post['ftp_password'])){
|
177 |
+
$ftp = sprintf("%s%s:%s@%s%s",
|
178 |
+
$post['ftp_proto'],
|
179 |
+
$post['ftp_login'],
|
180 |
+
$post['ftp_password'],
|
181 |
+
$post['ftp_host'],
|
182 |
+
$post['ftp_path']
|
183 |
+
);
|
184 |
+
} elseif (!empty($post['ftp_login'])) {
|
185 |
+
$ftp = sprintf(
|
186 |
+
"%s%s@%s%s",
|
187 |
+
$post['ftp_proto'],
|
188 |
+
$post['ftp_login'],
|
189 |
+
$post['ftp_host'],
|
190 |
+
$post['ftp_path']
|
191 |
+
);
|
192 |
+
} else {
|
193 |
+
$ftp = $post['ftp_proto'] . $post['ftp_host'] . $post['ftp_path'];
|
194 |
+
}
|
195 |
+
|
196 |
+
$_POST['ftp'] = $ftp;
|
197 |
+
return $ftp;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* NoRoute
|
202 |
+
*/
|
203 |
+
public function norouteAction()
|
204 |
+
{
|
205 |
+
header("HTTP/1.0 404 Invalid Action");
|
206 |
+
echo $this->view()->template('noroute.phtml');
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Login
|
211 |
+
*/
|
212 |
+
public function loginAction()
|
213 |
+
{
|
214 |
+
$this->view()->set('username', !empty($_GET['username']) ? $_GET['username'] : '');
|
215 |
+
echo $this->view()->template('login.phtml');
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Logout
|
220 |
+
*/
|
221 |
+
public function logoutAction()
|
222 |
+
{
|
223 |
+
$this->session()->logout();
|
224 |
+
$this->redirect($this->url());
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Index
|
229 |
+
*/
|
230 |
+
public function indexAction()
|
231 |
+
{
|
232 |
+
$config = $this->config();
|
233 |
+
if (!$this->isInstalled()) {
|
234 |
+
$this->view()->set('mage_url', dirname(dirname($_SERVER['SCRIPT_NAME'])));
|
235 |
+
$this->view()->set(
|
236 |
+
'use_custom_permissions_mode',
|
237 |
+
$config->__get('use_custom_permissions_mode')
|
238 |
+
? $config->__get('use_custom_permissions_mode')
|
239 |
+
: '0'
|
240 |
+
);
|
241 |
+
$this->view()->set('mkdir_mode', decoct($config->__get('global_dir_mode')));
|
242 |
+
$this->view()->set('chmod_file_mode', decoct($config->__get('global_file_mode')));
|
243 |
+
$this->view()->set('protocol', $config->__get('protocol'));
|
244 |
+
$this->channelConfig()->setInstallView($config,$this->view());
|
245 |
+
|
246 |
+
echo $this->view()->template('install/download.phtml');
|
247 |
+
} elseif (!$config->sync_pear) {
|
248 |
+
$this->model('connect', true)->connect()->run('sync');
|
249 |
+
$this->forward('connectPackages');
|
250 |
+
} else {
|
251 |
+
$this->forward('connectPackages');
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Empty Action
|
257 |
+
*/
|
258 |
+
public function emptyAction()
|
259 |
+
{
|
260 |
+
$this->model('connect', true)
|
261 |
+
->connect()
|
262 |
+
->runHtmlConsole('Please wait, preparing for updates...');
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Install all magento
|
267 |
+
*/
|
268 |
+
public function connectInstallAllAction()
|
269 |
+
{
|
270 |
+
$p = &$_POST;
|
271 |
+
$this->getFtpPost($p);
|
272 |
+
$errors = $this->model('connect', true)->validateConfigPost($p);
|
273 |
+
/* todo show errors */
|
274 |
+
if ($errors) {
|
275 |
+
$message = "CONNECT ERROR: ";
|
276 |
+
foreach ($errors as $err) {
|
277 |
+
$message .= $err . "\n";
|
278 |
+
}
|
279 |
+
$this->model('connect', true)->connect()->runHtmlConsole($message);
|
280 |
+
$this->model('connect', true)->connect()->showConnectErrors($errors);
|
281 |
+
return;
|
282 |
+
}
|
283 |
+
|
284 |
+
if( 1 == $p['inst_protocol']){
|
285 |
+
$this->model('connect', true)->connect()->setRemoteConfig($this->getFtpPost($p));
|
286 |
+
}
|
287 |
+
|
288 |
+
$this->channelConfig()->setPostData($this->config(),$p);
|
289 |
+
|
290 |
+
$chan = $this->config()->__get('root_channel');
|
291 |
+
$this->model('connect', true)->saveConfigPost($_POST);
|
292 |
+
$this->channelConfig()->setSettingsSession($_POST, $this->session());
|
293 |
+
$this->model('connect', true)->installAll(!empty($_GET['force']), $chan);
|
294 |
+
$p = null;
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Connect packages
|
299 |
+
*/
|
300 |
+
public function connectPackagesAction()
|
301 |
+
{
|
302 |
+
$connect = $this->model('connect', true);
|
303 |
+
|
304 |
+
if (isset($_GET['loggedin'])) {
|
305 |
+
$connect->connect()->run('sync');
|
306 |
+
}
|
307 |
+
|
308 |
+
$this->view()->set('connect', $connect);
|
309 |
+
$this->view()->set('channel_config', $this->channelConfig());
|
310 |
+
$remoteConfig = $this->config()->remote_config;
|
311 |
+
if (!$this->isWritable() && empty($remoteConfig)) {
|
312 |
+
$this->view()->set('writable_warning', true);
|
313 |
+
}
|
314 |
+
|
315 |
+
echo $this->view()->template('connect/packages.phtml');
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Connect packages POST
|
320 |
+
*/
|
321 |
+
public function connectPackagesPostAction()
|
322 |
+
{
|
323 |
+
$actions = isset($_POST['actions']) ? $_POST['actions'] : array();
|
324 |
+
if (isset($_POST['ignore_local_modification'])) {
|
325 |
+
$ignoreLocalModification = $_POST['ignore_local_modification'];
|
326 |
+
} else {
|
327 |
+
$ignoreLocalModification = '';
|
328 |
+
}
|
329 |
+
$this->model('connect', true)->applyPackagesActions($actions, $ignoreLocalModification);
|
330 |
+
}
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Prepare package to install, get dependency info.
|
334 |
+
*/
|
335 |
+
public function connectPreparePackagePostAction()
|
336 |
+
{
|
337 |
+
if (!$_POST) {
|
338 |
+
echo "INVALID POST DATA";
|
339 |
+
return;
|
340 |
+
}
|
341 |
+
$prepareResult = $this->model('connect', true)->prepareToInstall($_POST['install_package_id']);
|
342 |
+
|
343 |
+
$packages = isset($prepareResult['data']) ? $prepareResult['data'] : array();
|
344 |
+
$errors = isset($prepareResult['errors']) ? $prepareResult['errors'] : array();
|
345 |
+
|
346 |
+
$this->view()->set('packages', $packages);
|
347 |
+
$this->view()->set('errors', $errors);
|
348 |
+
$this->view()->set('package_id', $_POST['install_package_id']);
|
349 |
+
|
350 |
+
echo $this->view()->template('connect/packages_prepare.phtml');
|
351 |
+
}
|
352 |
+
|
353 |
+
/**
|
354 |
+
* Install package
|
355 |
+
*/
|
356 |
+
public function connectInstallPackagePostAction()
|
357 |
+
{
|
358 |
+
if (!$_POST) {
|
359 |
+
echo "INVALID POST DATA";
|
360 |
+
return;
|
361 |
+
}
|
362 |
+
$this->model('connect', true)->installPackage($_POST['install_package_id']);
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Install uploaded package
|
367 |
+
*/
|
368 |
+
public function connectInstallPackageUploadAction()
|
369 |
+
{
|
370 |
+
if (!$_FILES) {
|
371 |
+
echo "No file was uploaded";
|
372 |
+
return;
|
373 |
+
}
|
374 |
+
|
375 |
+
if(empty($_FILES['file'])) {
|
376 |
+
echo "No file was uploaded";
|
377 |
+
return;
|
378 |
+
}
|
379 |
+
|
380 |
+
$info =& $_FILES['file'];
|
381 |
+
|
382 |
+
if(0 !== intval($info['error'])) {
|
383 |
+
echo "File upload problem";
|
384 |
+
return;
|
385 |
+
}
|
386 |
+
|
387 |
+
$target = $this->_mageDir . DS . "var/" . uniqid() . $info['name'];
|
388 |
+
$res = move_uploaded_file($info['tmp_name'], $target);
|
389 |
+
if(false === $res) {
|
390 |
+
echo "Error moving uploaded file";
|
391 |
+
return;
|
392 |
+
}
|
393 |
+
|
394 |
+
$this->model('connect', true)->installUploadedPackage($target);
|
395 |
+
@unlink($target);
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Clean cache on ajax request
|
400 |
+
*/
|
401 |
+
public function cleanCacheAction()
|
402 |
+
{
|
403 |
+
$result = $this->cleanCache();
|
404 |
+
echo json_encode($result);
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* Settings
|
409 |
+
*/
|
410 |
+
public function settingsAction()
|
411 |
+
{
|
412 |
+
$config = $this->config();
|
413 |
+
$this->view()->set('preferred_state', $config->__get('preferred_state'));
|
414 |
+
$this->view()->set('protocol', $config->__get('protocol'));
|
415 |
+
|
416 |
+
$this->view()->set('use_custom_permissions_mode', $config->__get('use_custom_permissions_mode'));
|
417 |
+
$this->view()->set('mkdir_mode', decoct($config->__get('global_dir_mode')));
|
418 |
+
$this->view()->set('chmod_file_mode', decoct($config->__get('global_file_mode')));
|
419 |
+
|
420 |
+
$this->channelConfig()->setSettingsView($this->session(), $this->view());
|
421 |
+
|
422 |
+
$fs_disabled =! $this->isWritable();
|
423 |
+
$ftpParams = $config->__get('remote_config') ? @parse_url($config->__get('remote_config')) : '';
|
424 |
+
|
425 |
+
$this->view()->set('fs_disabled', $fs_disabled);
|
426 |
+
$this->view()->set('deployment_type', ($fs_disabled || !empty($ftpParams) ? 'ftp' : 'fs'));
|
427 |
+
|
428 |
+
if (!empty($ftpParams)) {
|
429 |
+
$this->view()->set('ftp_host', sprintf("%s://%s", $ftpParams['scheme'], $ftpParams['host']));
|
430 |
+
$this->view()->set('ftp_login', $ftpParams['user']);
|
431 |
+
$this->view()->set('ftp_password', $ftpParams['pass']);
|
432 |
+
$this->view()->set('ftp_path', $ftpParams['path']);
|
433 |
+
}
|
434 |
+
echo $this->view()->template('settings.phtml');
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Settings post
|
439 |
+
*/
|
440 |
+
public function settingsPostAction()
|
441 |
+
{
|
442 |
+
if ($_POST) {
|
443 |
+
$ftp = $this->getFtpPost($_POST);
|
444 |
+
|
445 |
+
/* clear startup messages */
|
446 |
+
$this->config();
|
447 |
+
$this->session()->getMessages();
|
448 |
+
|
449 |
+
$errors = $this->model('connect', true)->validateConfigPost($_POST);
|
450 |
+
if ($errors) {
|
451 |
+
foreach ($errors as $err) {
|
452 |
+
$this->session()->addMessage('error', $err);
|
453 |
+
}
|
454 |
+
$this->redirect($this->url('settings'));
|
455 |
+
return;
|
456 |
+
}
|
457 |
+
try {
|
458 |
+
if ('ftp' == $_POST['deployment_type'] && !empty($_POST['ftp_host'])) {
|
459 |
+
$this->model('connect', true)->connect()->setRemoteConfig($ftp);
|
460 |
+
} else {
|
461 |
+
$this->model('connect', true)->connect()->setRemoteConfig('');
|
462 |
+
$_POST['ftp'] = '';
|
463 |
+
}
|
464 |
+
$this->channelConfig()->setPostData($this->config(), $_POST);
|
465 |
+
$this->model('connect', true)->saveConfigPost($_POST);
|
466 |
+
$this->channelConfig()->setSettingsSession($_POST, $this->session());
|
467 |
+
$this->model('connect', true)->connect()->run('sync');
|
468 |
+
} catch (Exception $e) {
|
469 |
+
$this->session()->addMessage('error', "Unable to save settings: " . $e->getMessage());
|
470 |
+
}
|
471 |
+
}
|
472 |
+
$this->redirect($this->url('settings'));
|
473 |
+
}
|
474 |
+
|
475 |
+
//////////////////////////// ABSTRACT
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Constructor
|
479 |
+
*/
|
480 |
+
public function __construct()
|
481 |
+
{
|
482 |
+
$this->_rootDir = dirname(dirname(__FILE__));
|
483 |
+
$this->_mageDir = dirname($this->_rootDir);
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Run
|
488 |
+
*/
|
489 |
+
public static function run()
|
490 |
+
{
|
491 |
+
try {
|
492 |
+
self::singleton()->dispatch();
|
493 |
+
} catch (Exception $e) {
|
494 |
+
echo $e->getMessage();
|
495 |
+
//echo self::singleton()->view()->set('exception', $e)->template("exception.phtml");
|
496 |
+
}
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* Initialize object of class
|
501 |
+
*
|
502 |
+
* @return Maged_Controller
|
503 |
+
*/
|
504 |
+
public static function singleton()
|
505 |
+
{
|
506 |
+
if (!self::$_instance) {
|
507 |
+
self::$_instance = new self;
|
508 |
+
|
509 |
+
if (self::$_instance->isDownloaded() && self::$_instance->isInstalled()) {
|
510 |
+
Mage::app('', 'store', array('global_ban_use_cache'=>true));
|
511 |
+
Mage::getSingleton('adminhtml/url')->turnOffSecretKey();
|
512 |
+
}
|
513 |
+
}
|
514 |
+
return self::$_instance;
|
515 |
+
}
|
516 |
+
|
517 |
+
/**
|
518 |
+
* Retrieve Downloader root dir
|
519 |
+
*
|
520 |
+
* @return string
|
521 |
+
*/
|
522 |
+
public function getRootDir()
|
523 |
+
{
|
524 |
+
return $this->_rootDir;
|
525 |
+
}
|
526 |
+
|
527 |
+
/**
|
528 |
+
* Retrieve Magento root dir
|
529 |
+
*
|
530 |
+
* @return string
|
531 |
+
*/
|
532 |
+
public function getMageDir()
|
533 |
+
{
|
534 |
+
return $this->_mageDir;
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Retrieve Mage Class file path
|
539 |
+
*
|
540 |
+
* @return string
|
541 |
+
*/
|
542 |
+
public function getMageFilename()
|
543 |
+
{
|
544 |
+
$ds = DIRECTORY_SEPARATOR;
|
545 |
+
return $this->getMageDir() . $ds . 'app' . $ds . 'Mage.php';
|
546 |
+
}
|
547 |
+
|
548 |
+
/**
|
549 |
+
* Retrieve path for Varien_Profiler
|
550 |
+
*
|
551 |
+
* @return string
|
552 |
+
*/
|
553 |
+
public function getVarFilename()
|
554 |
+
{
|
555 |
+
$ds = DIRECTORY_SEPARATOR;
|
556 |
+
return $this->getMageDir() . $ds . 'lib' . $ds . 'Varien' . $ds . 'Profiler.php';
|
557 |
+
}
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Retrieve downloader file path
|
561 |
+
*
|
562 |
+
* @param string $name
|
563 |
+
* @return string
|
564 |
+
*/
|
565 |
+
public function filepath($name = '')
|
566 |
+
{
|
567 |
+
$ds = DIRECTORY_SEPARATOR;
|
568 |
+
return rtrim($this->getRootDir() . $ds . str_replace('/', $ds, $name), $ds);
|
569 |
+
}
|
570 |
+
|
571 |
+
/**
|
572 |
+
* Retrieve object of view
|
573 |
+
*
|
574 |
+
* @return Maged_View
|
575 |
+
*/
|
576 |
+
public function view()
|
577 |
+
{
|
578 |
+
if (!$this->_view) {
|
579 |
+
$this->_view = new Maged_View;
|
580 |
+
}
|
581 |
+
return $this->_view;
|
582 |
+
}
|
583 |
+
|
584 |
+
/**
|
585 |
+
* Retrieve object of model
|
586 |
+
*
|
587 |
+
* @param string $model
|
588 |
+
* @param boolean $singleton
|
589 |
+
* @return Maged_Model
|
590 |
+
*/
|
591 |
+
public function model($model = null, $singleton = false)
|
592 |
+
{
|
593 |
+
if ($singleton && isset($this->_singletons[$model])) {
|
594 |
+
return $this->_singletons[$model];
|
595 |
+
}
|
596 |
+
|
597 |
+
if (is_null($model)) {
|
598 |
+
$class = 'Maged_Model';
|
599 |
+
} else {
|
600 |
+
$class = 'Maged_Model_'.str_replace(' ', '_', ucwords(str_replace('_', ' ', $model)));
|
601 |
+
if (!class_exists($class, false)) {
|
602 |
+
include_once str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
|
603 |
+
}
|
604 |
+
}
|
605 |
+
|
606 |
+
$object = new $class();
|
607 |
+
|
608 |
+
if ($singleton) {
|
609 |
+
$this->_singletons[$model] = $object;
|
610 |
+
}
|
611 |
+
|
612 |
+
return $object;
|
613 |
+
}
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Retrieve object of config
|
617 |
+
*
|
618 |
+
* @return Mage_Connect_Config
|
619 |
+
*/
|
620 |
+
public function config()
|
621 |
+
{
|
622 |
+
if (!$this->_config) {
|
623 |
+
$this->_config = $this->model('connect', true)->connect()->getConfig();
|
624 |
+
if (!$this->_config->isLoaded()) {
|
625 |
+
$this->session()->addMessage('error', "Settings has not been loaded. Used default settings");
|
626 |
+
if ($this->_config->getError()) {
|
627 |
+
$this->session()->addMessage('error', $this->_config->getError());
|
628 |
+
}
|
629 |
+
}
|
630 |
+
}
|
631 |
+
return $this->_config;
|
632 |
+
}
|
633 |
+
|
634 |
+
/**
|
635 |
+
* Retrieve object of channel config
|
636 |
+
*
|
637 |
+
* @return Maged_Model_Config_Interface
|
638 |
+
*/
|
639 |
+
public function channelConfig()
|
640 |
+
{
|
641 |
+
if (!$this->_localConfig) {
|
642 |
+
$this->_localConfig = $this->model('config', true)->getChannelConfig();
|
643 |
+
}
|
644 |
+
return $this->_localConfig;
|
645 |
+
}
|
646 |
+
|
647 |
+
/**
|
648 |
+
* Retrieve object of session
|
649 |
+
*
|
650 |
+
* @return Maged_Model_Session
|
651 |
+
*/
|
652 |
+
public function session()
|
653 |
+
{
|
654 |
+
if (!$this->_session) {
|
655 |
+
$this->_session = $this->model('session')->start();
|
656 |
+
}
|
657 |
+
return $this->_session;
|
658 |
+
}
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Set Controller action
|
662 |
+
*
|
663 |
+
* @param string $action
|
664 |
+
* @return Maged_Controller
|
665 |
+
*/
|
666 |
+
public function setAction($action=null)
|
667 |
+
{
|
668 |
+
if (is_null($action)) {
|
669 |
+
if (!empty($this->_action)) {
|
670 |
+
return $this;
|
671 |
+
}
|
672 |
+
$action = !empty($_GET[self::ACTION_KEY]) ? $_GET[self::ACTION_KEY] : 'index';
|
673 |
+
}
|
674 |
+
if (empty($action) || !is_string($action) || !method_exists($this, $this->getActionMethod($action))) {
|
675 |
+
//$action = 'noroute';
|
676 |
+
$action = 'index';
|
677 |
+
}
|
678 |
+
$this->_action = $action;
|
679 |
+
return $this;
|
680 |
+
}
|
681 |
+
|
682 |
+
/**
|
683 |
+
* Retrieve Controller action name
|
684 |
+
*
|
685 |
+
* @return string
|
686 |
+
*/
|
687 |
+
public function getAction()
|
688 |
+
{
|
689 |
+
return $this->_action;
|
690 |
+
}
|
691 |
+
|
692 |
+
/**
|
693 |
+
* Set Redirect to URL
|
694 |
+
*
|
695 |
+
* @param string $url
|
696 |
+
* @param bool $force
|
697 |
+
* @return Maged_Controller
|
698 |
+
*/
|
699 |
+
public function redirect($url, $force = false)
|
700 |
+
{
|
701 |
+
$this->_redirectUrl = $url;
|
702 |
+
if ($force) {
|
703 |
+
$this->processRedirect();
|
704 |
+
}
|
705 |
+
return $this;
|
706 |
+
}
|
707 |
+
|
708 |
+
/**
|
709 |
+
* Precess redirect
|
710 |
+
*
|
711 |
+
* @return Maged_Controller
|
712 |
+
*/
|
713 |
+
public function processRedirect()
|
714 |
+
{
|
715 |
+
if ($this->_redirectUrl) {
|
716 |
+
if (headers_sent()) {
|
717 |
+
echo '<script type="text/javascript">location.href="' . $this->_redirectUrl . '"</script>';
|
718 |
+
exit;
|
719 |
+
} else {
|
720 |
+
header("Location: " . $this->_redirectUrl);
|
721 |
+
exit;
|
722 |
+
}
|
723 |
+
}
|
724 |
+
return $this;
|
725 |
+
}
|
726 |
+
|
727 |
+
/**
|
728 |
+
* Forward to action
|
729 |
+
*
|
730 |
+
* @param string $action
|
731 |
+
* @return Maged_Controller
|
732 |
+
*/
|
733 |
+
public function forward($action)
|
734 |
+
{
|
735 |
+
$this->setAction($action);
|
736 |
+
$this->_isDispatched = false;
|
737 |
+
return $this;
|
738 |
+
}
|
739 |
+
|
740 |
+
/**
|
741 |
+
* Retrieve action method by action name
|
742 |
+
*
|
743 |
+
* @param string $action
|
744 |
+
* @return string
|
745 |
+
*/
|
746 |
+
public function getActionMethod($action = null)
|
747 |
+
{
|
748 |
+
$method = (!is_null($action) ? $action : $this->_action) . 'Action';
|
749 |
+
return $method;
|
750 |
+
}
|
751 |
+
|
752 |
+
/**
|
753 |
+
* Generate URL for action
|
754 |
+
*
|
755 |
+
* @param string $action
|
756 |
+
* @param array $params
|
757 |
+
*/
|
758 |
+
public function url($action = '', $params = array())
|
759 |
+
{
|
760 |
+
$args = array();
|
761 |
+
foreach ($params as $k => $v) {
|
762 |
+
$args[] = sprintf('%s=%s', rawurlencode($k), rawurlencode($v));
|
763 |
+
}
|
764 |
+
$args = $args ? join('&', $args) : '';
|
765 |
+
|
766 |
+
return sprintf('%s?%s=%s%s', $_SERVER['SCRIPT_NAME'], self::ACTION_KEY, rawurlencode($action), $args);
|
767 |
+
}
|
768 |
+
|
769 |
+
/**
|
770 |
+
* Dispatch process
|
771 |
+
*/
|
772 |
+
public function dispatch()
|
773 |
+
{
|
774 |
+
header('Content-type: text/html; charset=UTF-8');
|
775 |
+
|
776 |
+
$this->setAction();
|
777 |
+
|
778 |
+
if (!$this->isInstalled()) {
|
779 |
+
if (!in_array($this->getAction(), array('index', 'connectInstallAll', 'empty', 'cleanCache'))) {
|
780 |
+
$this->setAction('index');
|
781 |
+
}
|
782 |
+
} else {
|
783 |
+
$this->session()->authenticate();
|
784 |
+
}
|
785 |
+
|
786 |
+
while (!$this->_isDispatched) {
|
787 |
+
$this->_isDispatched = true;
|
788 |
+
|
789 |
+
$method = $this->getActionMethod();
|
790 |
+
$this->$method();
|
791 |
+
}
|
792 |
+
|
793 |
+
$this->processRedirect();
|
794 |
+
}
|
795 |
+
|
796 |
+
/**
|
797 |
+
* Check root dir is writable
|
798 |
+
*
|
799 |
+
* @return bool
|
800 |
+
*/
|
801 |
+
public function isWritable()
|
802 |
+
{
|
803 |
+
if (is_null($this->_writable)) {
|
804 |
+
$this->_writable = is_writable($this->getMageDir() . DIRECTORY_SEPARATOR)
|
805 |
+
&& is_writable($this->filepath())
|
806 |
+
&& (!file_exists($this->filepath('config.ini') || is_writable($this->filepath('config.ini'))));
|
807 |
+
}
|
808 |
+
return $this->_writable;
|
809 |
+
}
|
810 |
+
|
811 |
+
/**
|
812 |
+
* Check is Magento files downloaded
|
813 |
+
*
|
814 |
+
* @return bool
|
815 |
+
*/
|
816 |
+
public function isDownloaded()
|
817 |
+
{
|
818 |
+
return file_exists($this->getMageFilename()) && file_exists($this->getVarFilename());
|
819 |
+
}
|
820 |
+
|
821 |
+
/**
|
822 |
+
* Check is Magento installed
|
823 |
+
*
|
824 |
+
* @return bool
|
825 |
+
*/
|
826 |
+
public function isInstalled()
|
827 |
+
{
|
828 |
+
if (!$this->isDownloaded()) {
|
829 |
+
return false;
|
830 |
+
}
|
831 |
+
if (!class_exists('Mage', false)) {
|
832 |
+
if (!file_exists($this->getMageFilename())) {
|
833 |
+
return false;
|
834 |
+
}
|
835 |
+
include_once $this->getMageFilename();
|
836 |
+
Mage::setIsDownloader();
|
837 |
+
}
|
838 |
+
return Mage::isInstalled();
|
839 |
+
}
|
840 |
+
|
841 |
+
/**
|
842 |
+
* Retrieve Maintenance flag
|
843 |
+
*
|
844 |
+
* @return bool
|
845 |
+
*/
|
846 |
+
protected function _getMaintenanceFlag()
|
847 |
+
{
|
848 |
+
if (is_null($this->_maintenance)) {
|
849 |
+
$this->_maintenance = !empty($_REQUEST['maintenance']) && $_REQUEST['maintenance'] == '1' ? true : false;
|
850 |
+
}
|
851 |
+
return $this->_maintenance;
|
852 |
+
}
|
853 |
+
|
854 |
+
/**
|
855 |
+
* Retrieve Maintenance Flag file path
|
856 |
+
*
|
857 |
+
* @return string
|
858 |
+
*/
|
859 |
+
protected function _getMaintenanceFilePath()
|
860 |
+
{
|
861 |
+
if (is_null($this->_maintenanceFile)) {
|
862 |
+
$path = dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR;
|
863 |
+
$this->_maintenanceFile = $path . 'maintenance.flag';
|
864 |
+
}
|
865 |
+
return $this->_maintenanceFile;
|
866 |
+
}
|
867 |
+
|
868 |
+
/**
|
869 |
+
* Begin install package(s)
|
870 |
+
*/
|
871 |
+
public function startInstall()
|
872 |
+
{
|
873 |
+
if ($this->_getMaintenanceFlag()) {
|
874 |
+
$maintenance_filename='maintenance.flag';
|
875 |
+
$config = $this->config();
|
876 |
+
if (!$this->isWritable() || strlen($config->__get('remote_config')) > 0) {
|
877 |
+
$ftpObj = new Mage_Connect_Ftp();
|
878 |
+
$ftpObj->connect($config->__get('remote_config'));
|
879 |
+
$tempFile = tempnam(sys_get_temp_dir(),'maintenance');
|
880 |
+
@file_put_contents($tempFile, 'maintenance');
|
881 |
+
$ftpObj->upload($maintenance_filename, $tempFile);
|
882 |
+
$ftpObj->close();
|
883 |
+
} else {
|
884 |
+
@file_put_contents($this->_getMaintenanceFilePath(), 'maintenance');
|
885 |
+
}
|
886 |
+
}
|
887 |
+
}
|
888 |
+
|
889 |
+
/**
|
890 |
+
* End install package(s)
|
891 |
+
*/
|
892 |
+
public function endInstall()
|
893 |
+
{
|
894 |
+
//$connect
|
895 |
+
/** @var $connect Maged_Model_Connect */
|
896 |
+
$frontend = $this->model('connect', true)->connect()->getFrontend();
|
897 |
+
if (!($frontend instanceof Maged_Connect_Frontend)) {
|
898 |
+
$this->cleanCache();
|
899 |
+
}
|
900 |
+
}
|
901 |
+
|
902 |
+
protected function cleanCache()
|
903 |
+
{
|
904 |
+
$result = true;
|
905 |
+
$message = '';
|
906 |
+
try {
|
907 |
+
if ($this->isInstalled()) {
|
908 |
+
if (!empty($_REQUEST['clean_sessions'])) {
|
909 |
+
Mage::app()->cleanAllSessions();
|
910 |
+
$message .= 'Session cleaned successfully. ';
|
911 |
+
}
|
912 |
+
Mage::app()->cleanCache();
|
913 |
+
|
914 |
+
// reinit config and apply all updates
|
915 |
+
Mage::app()->getConfig()->reinit();
|
916 |
+
Mage_Core_Model_Resource_Setup::applyAllUpdates();
|
917 |
+
Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
|
918 |
+
$message .= 'Cache cleaned successfully';
|
919 |
+
} else {
|
920 |
+
$result = true;
|
921 |
+
}
|
922 |
+
} catch (Exception $e) {
|
923 |
+
$result = false;
|
924 |
+
$message = "Exception during cache and session cleaning: ".$e->getMessage();
|
925 |
+
$this->session()->addMessage('error', $message);
|
926 |
+
}
|
927 |
+
|
928 |
+
if ($result && $this->_getMaintenanceFlag()) {
|
929 |
+
$maintenance_filename='maintenance.flag';
|
930 |
+
$config = $this->config();
|
931 |
+
if (!$this->isWritable() && strlen($config->__get('remote_config')) > 0) {
|
932 |
+
$ftpObj = new Mage_Connect_Ftp();
|
933 |
+
$ftpObj->connect($config->__get('remote_config'));
|
934 |
+
$ftpObj->delete($maintenance_filename);
|
935 |
+
$ftpObj->close();
|
936 |
+
} else {
|
937 |
+
@unlink($this->_getMaintenanceFilePath());
|
938 |
+
}
|
939 |
+
}
|
940 |
+
return array('result' => $result, 'message' => $message);
|
941 |
+
}
|
942 |
+
|
943 |
+
/**
|
944 |
+
* Gets the current Magento Connect Manager (Downloader) version string
|
945 |
+
* @link http://www.magentocommerce.com/blog/new-community-edition-release-process/
|
946 |
+
*
|
947 |
+
* @return string
|
948 |
+
*/
|
949 |
+
public static function getVersion()
|
950 |
+
{
|
951 |
+
$i = self::getVersionInfo();
|
952 |
+
return trim(
|
953 |
+
"{$i['major']}.{$i['minor']}.{$i['revision']}"
|
954 |
+
. ($i['patch'] != '' ? ".{$i['patch']}" : "")
|
955 |
+
. "-{$i['stability']}{$i['number']}",
|
956 |
+
'.-'
|
957 |
+
);
|
958 |
+
}
|
959 |
+
|
960 |
+
/**
|
961 |
+
* Gets the detailed Magento Connect Manager (Downloader) version information
|
962 |
+
* @link http://www.magentocommerce.com/blog/new-community-edition-release-process/
|
963 |
+
*
|
964 |
+
* @return array
|
965 |
+
*/
|
966 |
+
public static function getVersionInfo()
|
967 |
+
{
|
968 |
+
return array(
|
969 |
+
'major' => '1',
|
970 |
+
'minor' => '5',
|
971 |
+
'revision' => '0',
|
972 |
+
'patch' => '0',
|
973 |
+
'stability' => '',
|
974 |
+
'number' => '',
|
975 |
+
);
|
976 |
+
}
|
977 |
+
}
|
downloader/Maged/Exception.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class Exception
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Exception extends Exception
|
36 |
+
{
|
37 |
+
}
|
downloader/Maged/Model.php
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class Model
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Model
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Internal cache
|
40 |
+
*
|
41 |
+
* @var array
|
42 |
+
*/
|
43 |
+
protected $_data;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Constructor
|
47 |
+
*/
|
48 |
+
public function __construct()
|
49 |
+
{
|
50 |
+
$args = func_get_args();
|
51 |
+
if (empty($args[0])) {
|
52 |
+
$args[0] = array();
|
53 |
+
}
|
54 |
+
$this->_data = $args[0];
|
55 |
+
|
56 |
+
$this->_construct();
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Constructor for covering
|
61 |
+
*/
|
62 |
+
protected function _construct()
|
63 |
+
{
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Retrieve controller
|
69 |
+
* @return Maged_Controller
|
70 |
+
*/
|
71 |
+
public function controller()
|
72 |
+
{
|
73 |
+
return Maged_Controller::singleton();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Set value for key
|
78 |
+
*
|
79 |
+
* @param string $key
|
80 |
+
* @param mixed $value
|
81 |
+
* @return Maged_Model
|
82 |
+
*/
|
83 |
+
public function set($key, $value)
|
84 |
+
{
|
85 |
+
$this->_data[$key] = $value;
|
86 |
+
return $this;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Get value by key
|
91 |
+
*
|
92 |
+
* @param string $key
|
93 |
+
* @return mixed
|
94 |
+
*/
|
95 |
+
public function get($key)
|
96 |
+
{
|
97 |
+
return isset($this->_data[$key]) ? $this->_data[$key] : null;
|
98 |
+
}
|
99 |
+
}
|
downloader/Maged/Model/Config.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class config
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Model_Config extends Maged_Model_Config_Abstract
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Get channel config class
|
39 |
+
* @return Maged_Model_Config_Interface
|
40 |
+
*/
|
41 |
+
public function getChannelConfig()
|
42 |
+
{
|
43 |
+
$this->load();
|
44 |
+
$channel = trim($this->get('root_channel'));
|
45 |
+
if (!empty($channel)) {
|
46 |
+
try {
|
47 |
+
return $this->controller()->model('config_'.$channel, true);
|
48 |
+
} catch (Exception $e) {
|
49 |
+
throw new Exception('Not valid config.ini file.');
|
50 |
+
}
|
51 |
+
} else {
|
52 |
+
throw new Exception('Not valid config.ini file.');
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Save post data to config
|
58 |
+
*
|
59 |
+
* @param array $p
|
60 |
+
* @return Maged_Model_Config
|
61 |
+
*/
|
62 |
+
public function saveConfigPost($p)
|
63 |
+
{
|
64 |
+
$configParams = array(
|
65 |
+
'protocol',
|
66 |
+
'preferred_state',
|
67 |
+
'use_custom_permissions_mode',
|
68 |
+
'mkdir_mode',
|
69 |
+
'chmod_file_mode',
|
70 |
+
'magento_root',
|
71 |
+
'downloader_path',
|
72 |
+
'root_channel_uri',
|
73 |
+
'root_channel',
|
74 |
+
'ftp',
|
75 |
+
);
|
76 |
+
foreach ($configParams as $paramName){
|
77 |
+
if (isset($p[$paramName])) {
|
78 |
+
$this->set($paramName, $p[$paramName]);
|
79 |
+
}
|
80 |
+
}
|
81 |
+
$this->save();
|
82 |
+
return $this;
|
83 |
+
}
|
84 |
+
}
|
downloader/Maged/Model/Config/Abstract.php
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class config
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Model_Config_Abstract extends Maged_Model
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Retrive file name
|
39 |
+
*
|
40 |
+
* @return string
|
41 |
+
*/
|
42 |
+
public function getFilename()
|
43 |
+
{
|
44 |
+
return $this->controller()->filepath('config.ini');
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Load file
|
49 |
+
*
|
50 |
+
* @return Maged_Model_Config
|
51 |
+
*/
|
52 |
+
public function load()
|
53 |
+
{
|
54 |
+
if (!file_exists($this->getFilename())) {
|
55 |
+
return $this;
|
56 |
+
}
|
57 |
+
$rows = file($this->getFilename());
|
58 |
+
if (!$rows) {
|
59 |
+
return $this;
|
60 |
+
}
|
61 |
+
foreach ($rows as $row) {
|
62 |
+
$arr = explode('=', $row, 2);
|
63 |
+
if (count($arr)!==2) {
|
64 |
+
continue;
|
65 |
+
}
|
66 |
+
$key = trim($arr[0]);
|
67 |
+
$value = trim($arr[1], " \t\"'\n\r");
|
68 |
+
if (!$key || $key[0]=='#' || $key[0]==';') {
|
69 |
+
continue;
|
70 |
+
}
|
71 |
+
$this->set($key, $value);
|
72 |
+
}
|
73 |
+
return $this;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Save file
|
78 |
+
*
|
79 |
+
* @return Maged_Model_Config
|
80 |
+
*/
|
81 |
+
public function save()
|
82 |
+
{
|
83 |
+
if ((!is_writable($this->getFilename())&&is_file($this->getFilename()))||(dirname($this->getFilename())!=''&&!is_writable(dirname($this->getFilename())))) {
|
84 |
+
if(isset($this->_data['ftp'])&&!empty($this->_data['ftp'])&&strlen($this->get('downloader_path'))>0){
|
85 |
+
$confFile=$this->get('downloader_path').DIRECTORY_SEPARATOR.basename($this->getFilename());
|
86 |
+
$ftpObj = new Mage_Connect_Ftp();
|
87 |
+
$ftpObj->connect($this->_data['ftp']);
|
88 |
+
$tempFile = tempnam(sys_get_temp_dir(),'configini');
|
89 |
+
$fp = fopen($tempFile, 'w');
|
90 |
+
foreach ($this->_data as $k=>$v) {
|
91 |
+
fwrite($fp, $k.'='.$v."\n");
|
92 |
+
}
|
93 |
+
fclose($fp);
|
94 |
+
$ret=$ftpObj->upload($confFile, $tempFile);
|
95 |
+
$ftpObj->close();
|
96 |
+
}else{
|
97 |
+
/* @TODO: show Warning message*/
|
98 |
+
$this->controller()->session()
|
99 |
+
->addMessage('warning', 'Invalid file permissions, could not save configuration.');
|
100 |
+
return $this;
|
101 |
+
}
|
102 |
+
/**/
|
103 |
+
}else{
|
104 |
+
$fp = fopen($this->getFilename(), 'w');
|
105 |
+
foreach ($this->_data as $k=>$v) {
|
106 |
+
fwrite($fp, $k.'='.$v."\n");
|
107 |
+
}
|
108 |
+
fclose($fp);
|
109 |
+
}
|
110 |
+
return $this;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Return channel label for channel name
|
115 |
+
*
|
116 |
+
* @param string $channel
|
117 |
+
* @return string
|
118 |
+
*/
|
119 |
+
public function getChannelLabel($channel)
|
120 |
+
{
|
121 |
+
$channelLabel = '';
|
122 |
+
switch($channel)
|
123 |
+
{
|
124 |
+
case 'community':
|
125 |
+
$channelLabel = 'Magento Community Edition';
|
126 |
+
break;
|
127 |
+
default:
|
128 |
+
$channelLabel = $channel;
|
129 |
+
break;
|
130 |
+
}
|
131 |
+
return $channelLabel;
|
132 |
+
}
|
133 |
+
}
|
134 |
+
?>
|
downloader/Maged/Model/Config/Community.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class config
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Model_Config_Community extends Maged_Model_Config_Abstract implements Maged_Model_Config_Interface
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Initialization
|
40 |
+
*/
|
41 |
+
protected function _construct()
|
42 |
+
{
|
43 |
+
$this->load();
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Set data for Settings View
|
48 |
+
*
|
49 |
+
* @param Mage_Connect_Config $config
|
50 |
+
* @param Maged_View $view
|
51 |
+
* @return null
|
52 |
+
*/
|
53 |
+
public function setInstallView($config, $view)
|
54 |
+
{
|
55 |
+
$view->set('channel_logo', 'logo');
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Set data for Settings View
|
60 |
+
* @param Mage_Connect_Config $config
|
61 |
+
* @param Maged_View $view
|
62 |
+
* @return null
|
63 |
+
*/
|
64 |
+
public function setSettingsView($config, $view)
|
65 |
+
{
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Set session data for Settings
|
70 |
+
* @param array $post post data
|
71 |
+
* @param mixed $session Session object
|
72 |
+
* @return null
|
73 |
+
*/
|
74 |
+
public function setSettingsSession($post, $session)
|
75 |
+
{
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get root channel URI
|
80 |
+
*
|
81 |
+
* @return string Root channel URI
|
82 |
+
*/
|
83 |
+
public function getRootChannelUri(){
|
84 |
+
if (!$this->get('root_channel_uri')) {
|
85 |
+
$this->set('root_channel_uri', 'connect20.magentocommerce.com/community');
|
86 |
+
}
|
87 |
+
return $this->get('root_channel_uri');
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Set config data from POST
|
92 |
+
*
|
93 |
+
* @param Mage_Connect_Config $config Config object
|
94 |
+
* @param array $post post data
|
95 |
+
* @return null
|
96 |
+
*/
|
97 |
+
public function setPostData($config, &$post)
|
98 |
+
{
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Set additional command options
|
103 |
+
*
|
104 |
+
* @param mixed $session Session object
|
105 |
+
* @param array $options
|
106 |
+
* @return null
|
107 |
+
*/
|
108 |
+
public function setCommandOptions($session, &$options)
|
109 |
+
{
|
110 |
+
}
|
111 |
+
}
|
112 |
+
?>
|
downloader/Maged/Model/Config/Interface.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class config
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
interface Maged_Model_Config_Interface
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Set data for Settings View
|
40 |
+
*
|
41 |
+
* @param Mage_Connect_Config $config
|
42 |
+
* @param Maged_View $view
|
43 |
+
* @return null
|
44 |
+
*/
|
45 |
+
public function setInstallView($config, $view);
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Set data for Settings View
|
49 |
+
*
|
50 |
+
* @param mixed $session Session object
|
51 |
+
* @param Maged_View $view
|
52 |
+
* @return null
|
53 |
+
*/
|
54 |
+
public function setSettingsView($session, $view);
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Set session data for Settings
|
58 |
+
*
|
59 |
+
* @param array $post post data
|
60 |
+
* @param mixed $session Session object
|
61 |
+
* @return null
|
62 |
+
*/
|
63 |
+
public function setSettingsSession($post, $session);
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Set config data from POST
|
67 |
+
*
|
68 |
+
* @param Mage_Connect_Config $config Config object
|
69 |
+
* @param array $post post data
|
70 |
+
* @return boolean
|
71 |
+
*/
|
72 |
+
public function setPostData($config, &$post);
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Get root channel URI
|
76 |
+
*
|
77 |
+
* @return string Root channel URI
|
78 |
+
*/
|
79 |
+
public function getRootChannelUri();
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Set additional command options
|
83 |
+
*
|
84 |
+
* @param mixed $session Session object
|
85 |
+
* @param array $options
|
86 |
+
* @return null
|
87 |
+
*/
|
88 |
+
public function setCommandOptions($session, &$options);
|
89 |
+
}
|
90 |
+
?>
|
downloader/Maged/Model/Connect.php
ADDED
@@ -0,0 +1,491 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
include_once "Maged/Connect.php";
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Class for initialize Mage_Connect lib
|
31 |
+
*
|
32 |
+
* @category Mage
|
33 |
+
* @package Mage_Connect
|
34 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
35 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
36 |
+
*/
|
37 |
+
|
38 |
+
class Maged_Model_Connect extends Maged_Model
|
39 |
+
{
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Constructor
|
43 |
+
*/
|
44 |
+
protected function _construct()
|
45 |
+
{
|
46 |
+
parent::_construct();
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Retrive object of Maged_Connect
|
51 |
+
*
|
52 |
+
* @return Maged_Connect
|
53 |
+
*/
|
54 |
+
public function connect()
|
55 |
+
{
|
56 |
+
return Maged_Connect::getInstance();
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Install All Magento
|
61 |
+
*
|
62 |
+
* @param boolean $force
|
63 |
+
*/
|
64 |
+
public function installAll($force=false, $chanName='')
|
65 |
+
{
|
66 |
+
$options = array('install_all'=>true);
|
67 |
+
if ($force) {
|
68 |
+
$this->connect()->cleanSconfig();
|
69 |
+
$options['force'] = 1;
|
70 |
+
}
|
71 |
+
$packages = array(
|
72 |
+
'Mage_All_Latest',
|
73 |
+
);
|
74 |
+
$connectConfig = $this->connect()->getConfig();
|
75 |
+
$ftp = $connectConfig->remote_config;
|
76 |
+
if (!empty($ftp)) {
|
77 |
+
$options['ftp'] = $ftp;
|
78 |
+
}
|
79 |
+
$params = array();
|
80 |
+
|
81 |
+
$uri = $this->controller()->channelConfig()->getRootChannelUri();
|
82 |
+
|
83 |
+
$this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
|
84 |
+
|
85 |
+
$connectConfig->root_channel = $chanName;
|
86 |
+
foreach ($packages as $package) {
|
87 |
+
$params[] = $uri;
|
88 |
+
$params[] = $package;
|
89 |
+
}
|
90 |
+
$this->connect()->runHtmlConsole(array('command'=>'install', 'options'=>$options, 'params'=>$params));
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Prepare to install package
|
95 |
+
*
|
96 |
+
* @param string $id
|
97 |
+
* @return array
|
98 |
+
*/
|
99 |
+
public function prepareToInstall($id)
|
100 |
+
{
|
101 |
+
$match = array();
|
102 |
+
if (!$this->checkExtensionKey($id, $match)) {
|
103 |
+
echo('Invalid package identifier provided: '.$id);
|
104 |
+
exit;
|
105 |
+
}
|
106 |
+
|
107 |
+
$channel = $match[1];
|
108 |
+
$package = $match[2];
|
109 |
+
$version = (!empty($match[3]) ? trim($match[3],'/\-') : '');
|
110 |
+
|
111 |
+
$connect = $this->connect();
|
112 |
+
$sconfig = $connect->getSingleConfig();
|
113 |
+
|
114 |
+
$options = array();
|
115 |
+
$params = array($channel, $package, $version, $version);
|
116 |
+
$this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
|
117 |
+
|
118 |
+
$connect->run('package-prepare', $options, $params);
|
119 |
+
$output = $connect->getOutput();
|
120 |
+
$errors = $connect->getFrontend()->getErrors();
|
121 |
+
$package_error = array();
|
122 |
+
foreach ($errors as $error){
|
123 |
+
if (isset($error[1])){
|
124 |
+
$package_error[] = $error[1];
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
$packages = array();
|
129 |
+
if (is_array($output) && isset($output['package-prepare'])){
|
130 |
+
$packages = array_merge($output['package-prepare'], array('errors'=>array('error'=>$package_error)));
|
131 |
+
} elseif (is_array($output) && !empty($package_error)) {
|
132 |
+
$packages = array('errors'=>array('error'=>$package_error));
|
133 |
+
}
|
134 |
+
return $packages;
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Retrieve all installed packages
|
140 |
+
*
|
141 |
+
* @return array
|
142 |
+
*/
|
143 |
+
public function getAllInstalledPackages()
|
144 |
+
{
|
145 |
+
$connect = $this->connect();
|
146 |
+
$sconfig = $connect->getSingleConfig(true);
|
147 |
+
$connect->run('list-installed');
|
148 |
+
$output = $connect->getOutput();
|
149 |
+
$packages = array();
|
150 |
+
if (is_array($output) && isset($output['list-installed']['data'])){
|
151 |
+
$packages = $output['list-installed']['data'];
|
152 |
+
} else {
|
153 |
+
|
154 |
+
}
|
155 |
+
foreach ($packages as $channel=>$package) {
|
156 |
+
foreach ($package as $name=>$data) {
|
157 |
+
$summary = $sconfig->getPackageObject($channel, $name)->getSummary();
|
158 |
+
$addition = array('summary'=>$summary, 'upgrade_versions'=>array(), 'upgrade_latest'=>'');
|
159 |
+
$packages[$channel][$name] = array_merge($data, $addition);
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
if (!empty($_GET['updates'])) {
|
164 |
+
$options = array();
|
165 |
+
$this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
|
166 |
+
$result = $connect->run('list-upgrades', $options);
|
167 |
+
$output = $connect->getOutput();
|
168 |
+
if (is_array($output)) {
|
169 |
+
$channelData = $output;
|
170 |
+
if (!empty($channelData['list-upgrades']['data']) && is_array($channelData['list-upgrades']['data'])) {
|
171 |
+
foreach ($channelData['list-upgrades']['data'] as $channel=>$package) {
|
172 |
+
foreach ($package as $name=>$data) {
|
173 |
+
if (!isset($packages[$channel][$name])) {
|
174 |
+
continue;
|
175 |
+
}
|
176 |
+
$packages[$channel][$name]['upgrade_latest'] = $data['to'].' ('.$data['from'].')';
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
$states = array('snapshot'=>0, 'devel'=>1, 'alpha'=>2, 'beta'=>3, 'stable'=>4);
|
184 |
+
$preferredState = $states[$this->getPreferredState()];
|
185 |
+
|
186 |
+
foreach ($packages as $channel=>&$package) {
|
187 |
+
foreach ($package as $name=>&$data) {
|
188 |
+
$actions = array();
|
189 |
+
$systemPkg = $name==='Mage_Downloader';
|
190 |
+
if (!empty($data['upgrade_latest'])) {
|
191 |
+
$status = 'upgrade-available';
|
192 |
+
$releases = array();
|
193 |
+
$connect->run('info', array(), array($channel, $name));
|
194 |
+
$output = $connect->getOutput();
|
195 |
+
if (!empty($output['info']['releases'])) {
|
196 |
+
foreach ($output['info']['releases'] as $release) {
|
197 |
+
$stability = $packages[$channel][$name]['stability'];
|
198 |
+
if ($states[$release['s']] < min($preferredState, $states[$stability])) {
|
199 |
+
continue;
|
200 |
+
}
|
201 |
+
if (version_compare($release['v'], $packages[$channel][$name]['version']) < 1) {
|
202 |
+
continue;
|
203 |
+
}
|
204 |
+
$releases[$release['v']] = $release['v'].' ('.$release['s'].')';
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
if ($releases) {
|
209 |
+
uksort($releases, 'version_compare');
|
210 |
+
foreach ($releases as $version => $release) {
|
211 |
+
$actions['upgrade|'.$version] = 'Upgrade to '.$release;
|
212 |
+
}
|
213 |
+
} else {
|
214 |
+
$a = explode(' ', $data['upgrade_latest'], 2);
|
215 |
+
$actions['upgrade|'.$a[0]] = 'Upgrade';
|
216 |
+
}
|
217 |
+
if (!$systemPkg) {
|
218 |
+
$actions['uninstall'] = 'Uninstall';
|
219 |
+
}
|
220 |
+
} else {
|
221 |
+
$status = 'installed';
|
222 |
+
$actions['reinstall'] = 'Reinstall';
|
223 |
+
if (!$systemPkg) {
|
224 |
+
$actions['uninstall'] = 'Uninstall';
|
225 |
+
}
|
226 |
+
}
|
227 |
+
$packages[$channel][$name]['actions'] = $actions;
|
228 |
+
$packages[$channel][$name]['status'] = $status;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
return $packages;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Run packages action
|
236 |
+
*
|
237 |
+
* @param mixed $packages
|
238 |
+
*/
|
239 |
+
public function applyPackagesActions($packages, $ignoreLocalModification='')
|
240 |
+
{
|
241 |
+
$actions = array();
|
242 |
+
foreach ($packages as $package=>$action) {
|
243 |
+
if ($action) {
|
244 |
+
$a = explode('|', $package);
|
245 |
+
$b = explode('|', $action);
|
246 |
+
$package = $a[1];
|
247 |
+
$channel = $a[0];
|
248 |
+
$version = '';
|
249 |
+
if ($b[0]=='upgrade') {
|
250 |
+
$version = $b[1];
|
251 |
+
}
|
252 |
+
$actions[$b[0]][] = array($channel, $package, $version, $version);
|
253 |
+
}
|
254 |
+
}
|
255 |
+
if (empty($actions)) {
|
256 |
+
$this->connect()->runHtmlConsole('No actions selected');
|
257 |
+
exit;
|
258 |
+
}
|
259 |
+
|
260 |
+
$this->controller()->startInstall();
|
261 |
+
|
262 |
+
$options = array();
|
263 |
+
if (!empty($ignoreLocalModification)) {
|
264 |
+
$options = array('ignorelocalmodification'=>1);
|
265 |
+
}
|
266 |
+
if(!$this->controller()->isWritable()||strlen($this->connect()->getConfig()->__get('remote_config'))>0){
|
267 |
+
$options['ftp'] = $this->connect()->getConfig()->__get('remote_config');
|
268 |
+
}
|
269 |
+
|
270 |
+
$this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
|
271 |
+
|
272 |
+
foreach ($actions as $action=>$packages) {
|
273 |
+
foreach ($packages as $package) {
|
274 |
+
switch ($action) {
|
275 |
+
case 'install': case 'uninstall': case 'upgrade':
|
276 |
+
$this->connect()->runHtmlConsole(array(
|
277 |
+
'command'=>$action,
|
278 |
+
'options'=>$options,
|
279 |
+
'params'=>$package
|
280 |
+
));
|
281 |
+
break;
|
282 |
+
|
283 |
+
case 'reinstall':
|
284 |
+
$package_info = $this->connect()->getSingleConfig()->getPackage($package[0], $package[1]);
|
285 |
+
if (isset($package_info['version'])) {
|
286 |
+
$package[2] = $package_info['version'];
|
287 |
+
$package[3] = $package_info['version'];
|
288 |
+
}
|
289 |
+
$this->connect()->runHtmlConsole(array(
|
290 |
+
'command'=>'install',
|
291 |
+
'options'=>array_merge($options, array('force'=>1, 'nodeps'=>1)),
|
292 |
+
'params'=>$package
|
293 |
+
));
|
294 |
+
break;
|
295 |
+
}
|
296 |
+
}
|
297 |
+
}
|
298 |
+
|
299 |
+
$this->controller()->endInstall();
|
300 |
+
}
|
301 |
+
|
302 |
+
|
303 |
+
public function installUploadedPackage($file)
|
304 |
+
{
|
305 |
+
$this->controller()->startInstall();
|
306 |
+
|
307 |
+
$options = array();
|
308 |
+
if(!$this->controller()->isWritable()||strlen($this->connect()->getConfig()->__get('remote_config'))>0){
|
309 |
+
$options['ftp'] = $this->connect()->getConfig()->__get('remote_config');
|
310 |
+
}
|
311 |
+
$this->connect()->runHtmlConsole(array(
|
312 |
+
'command'=>'install-file',
|
313 |
+
'options'=>$options,
|
314 |
+
'params'=>array($file),
|
315 |
+
));
|
316 |
+
$this->controller()->endInstall();
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Install package by id
|
321 |
+
*
|
322 |
+
* @param string $id
|
323 |
+
* @param boolean $force
|
324 |
+
*/
|
325 |
+
public function installPackage($id, $force=false)
|
326 |
+
{
|
327 |
+
$match = array();
|
328 |
+
if (!$this->checkExtensionKey($id, $match)) {
|
329 |
+
$this->connect()->runHtmlConsole('Invalid package identifier provided: '.$id);
|
330 |
+
exit;
|
331 |
+
}
|
332 |
+
|
333 |
+
$channel = $match[1];
|
334 |
+
$package = $match[2];//.(!empty($match[3]) ? $match[3] : '');
|
335 |
+
$version = (!empty($match[3]) ? trim($match[3],'/\-') : '');
|
336 |
+
|
337 |
+
$this->controller()->startInstall();
|
338 |
+
|
339 |
+
$options = array();
|
340 |
+
if ($force) {
|
341 |
+
$options['force'] = 1;
|
342 |
+
}
|
343 |
+
if(!$this->controller()->isWritable()||strlen($this->connect()->getConfig()->__get('remote_config'))>0){
|
344 |
+
$options['ftp'] = $this->connect()->getConfig()->__get('remote_config');
|
345 |
+
}
|
346 |
+
|
347 |
+
$this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
|
348 |
+
|
349 |
+
$this->connect()->runHtmlConsole(array(
|
350 |
+
'command'=>'install',
|
351 |
+
'options'=>$options,
|
352 |
+
'params'=>array(0=>$channel, 1=>$package, 2=>$version),
|
353 |
+
));
|
354 |
+
|
355 |
+
$this->controller()->endInstall();
|
356 |
+
}
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Retrieve stability choosen client
|
360 |
+
*
|
361 |
+
* @return string alpha, beta, ...
|
362 |
+
*/
|
363 |
+
public function getPreferredState()
|
364 |
+
{
|
365 |
+
if (is_null($this->get('preferred_state'))) {
|
366 |
+
$connectConfig = $this->connect()->getConfig();
|
367 |
+
$this->set('preferred_state', $connectConfig->__get('preferred_state'));
|
368 |
+
}
|
369 |
+
return $this->get('preferred_state');
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Retrieve protocol choosen client
|
374 |
+
*
|
375 |
+
* @return string http, ftp
|
376 |
+
*/
|
377 |
+
public function getProtocol()
|
378 |
+
{
|
379 |
+
if (is_null($this->get('protocol'))) {
|
380 |
+
$connectConfig = $this->connect()->getConfig();
|
381 |
+
$this->set('protocol', $connectConfig->__get('protocol'));
|
382 |
+
}
|
383 |
+
return $this->get('protocol');
|
384 |
+
}
|
385 |
+
|
386 |
+
/**
|
387 |
+
* Validate settings post data.
|
388 |
+
*
|
389 |
+
* @param array $p
|
390 |
+
*/
|
391 |
+
public function validateConfigPost($p)
|
392 |
+
{
|
393 |
+
$errors = array();
|
394 |
+
$configTestFile = 'connect.cfgt';
|
395 |
+
$configObj = $this->connect()->getConfig();
|
396 |
+
if ('ftp' == $p['deployment_type'] || '1' == $p['inst_protocol']) {
|
397 |
+
/*check ftp*/
|
398 |
+
|
399 |
+
$confFile = $configObj->downloader_path.DIRECTORY_SEPARATOR.$configTestFile;
|
400 |
+
try {
|
401 |
+
$ftpObj = new Mage_Connect_Ftp();
|
402 |
+
$ftpObj->connect($p['ftp']);
|
403 |
+
$tempFile = tempnam(sys_get_temp_dir(),'config');
|
404 |
+
$serial = md5('config test file');
|
405 |
+
$f = @fopen($tempFile, "w+");
|
406 |
+
@fwrite($f, $serial);
|
407 |
+
@fclose($f);
|
408 |
+
$ret=$ftpObj->upload($confFile, $tempFile);
|
409 |
+
|
410 |
+
//read file
|
411 |
+
if (!$errors && is_file($configTestFile)) {
|
412 |
+
$size = filesize($configTestFile);
|
413 |
+
if(!$size) {
|
414 |
+
$errors[]='Unable to read saved settings. Please check Installation Path of FTP Connection.';
|
415 |
+
}
|
416 |
+
|
417 |
+
if (!$errors) {
|
418 |
+
$f = @fopen($configTestFile, "r");
|
419 |
+
@fseek($f, 0, SEEK_SET);
|
420 |
+
|
421 |
+
$contents = @fread($f, strlen($serial));
|
422 |
+
if ($serial != $contents) {
|
423 |
+
$errors[]='Wrong Installation Path of FTP Connection.';
|
424 |
+
}
|
425 |
+
fclose($f);
|
426 |
+
}
|
427 |
+
} else {
|
428 |
+
$errors[] = 'Unable to read saved settings. Please check Installation Path of FTP Connection.';
|
429 |
+
}
|
430 |
+
$ftpObj->delete($confFile);
|
431 |
+
$ftpObj->close();
|
432 |
+
} catch (Exception $e) {
|
433 |
+
$errors[] = 'Deployment FTP Error. ' . $e->getMessage();
|
434 |
+
}
|
435 |
+
} else {
|
436 |
+
$p['ftp'] = '';
|
437 |
+
}
|
438 |
+
|
439 |
+
if ('1' == $p['use_custom_permissions_mode']) {
|
440 |
+
/*check permissions*/
|
441 |
+
if (octdec(intval($p['mkdir_mode'])) < 73 || octdec(intval($p['mkdir_mode'])) > 511) {
|
442 |
+
$errors[]='Folders permissions not valid. ';
|
443 |
+
}
|
444 |
+
if (octdec(intval($p['chmod_file_mode'])) < 73 || octdec(intval($p['chmod_file_mode'])) > 511) {
|
445 |
+
$errors[]='Files permissions not valid. ';
|
446 |
+
}
|
447 |
+
}
|
448 |
+
//$this->controller()->session()->addMessage('success', 'Settings has been successfully saved');
|
449 |
+
return $errors;
|
450 |
+
}
|
451 |
+
/**
|
452 |
+
* Save settings.
|
453 |
+
*
|
454 |
+
* @param array $p
|
455 |
+
*/
|
456 |
+
public function saveConfigPost($p)
|
457 |
+
{
|
458 |
+
$configObj = $this->connect()->getConfig();
|
459 |
+
if ('ftp' == $p['deployment_type'] || '1' == $p['inst_protocol']){
|
460 |
+
$this->set('ftp',$p['ftp']);
|
461 |
+
} else {
|
462 |
+
$p['ftp'] = '';
|
463 |
+
}
|
464 |
+
$configObj->remote_config = $p['ftp'];
|
465 |
+
$configObj->preferred_state = $p['preferred_state'];
|
466 |
+
$configObj->protocol = $p['protocol'];
|
467 |
+
$configObj->use_custom_permissions_mode = $p['use_custom_permissions_mode'];
|
468 |
+
if ('1' == $p['use_custom_permissions_mode']) {
|
469 |
+
$configObj->global_dir_mode = octdec(intval($p['mkdir_mode']));
|
470 |
+
$configObj->global_file_mode = octdec(intval($p['chmod_file_mode']));
|
471 |
+
}
|
472 |
+
if ($configObj->save()) {
|
473 |
+
$this->controller()->session()->addMessage('success', 'Settings has been successfully saved');
|
474 |
+
} else {
|
475 |
+
$this->controller()->session()->addMessage('error', 'Settings cannot be saved');
|
476 |
+
}
|
477 |
+
return $this;
|
478 |
+
}
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Check Extension Key
|
482 |
+
*
|
483 |
+
* @param string $id
|
484 |
+
* @param array $match
|
485 |
+
* @return int
|
486 |
+
*/
|
487 |
+
public function checkExtensionKey($id, &$match)
|
488 |
+
{
|
489 |
+
return preg_match('#^([^ ]+)\/([^-]+)(-.+)?$#', $id, $match);
|
490 |
+
}
|
491 |
+
}
|
downloader/Maged/Model/Connect/Request.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class request
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Model_Connect_Request extends Maged_Model
|
36 |
+
{
|
37 |
+
protected function _construct()
|
38 |
+
{
|
39 |
+
parent::_construct();
|
40 |
+
$this->set('success_callback', 'clear_cache({success:parent.onSuccess, fail:parent.onFailure})');
|
41 |
+
$this->set('failure_callback', 'parent.onFailure()');
|
42 |
+
}
|
43 |
+
}
|
downloader/Maged/Model/Dowloader.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Maged_Model_Downloader extends Maged_Model
|
28 |
+
{
|
29 |
+
|
30 |
+
}
|
downloader/Maged/Model/Session.php
ADDED
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class session
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_Model_Session extends Maged_Model
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Session
|
39 |
+
*
|
40 |
+
* @var Mage_Admin_Model_Session
|
41 |
+
*/
|
42 |
+
protected $_session;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Init session
|
46 |
+
*
|
47 |
+
* @return Maged_Model_Session
|
48 |
+
*/
|
49 |
+
public function start()
|
50 |
+
{
|
51 |
+
if (class_exists('Mage') && Mage::isInstalled()) {
|
52 |
+
// initialize Magento Config
|
53 |
+
Mage::app();
|
54 |
+
$this->_session = Mage::getSingleton('admin/session');
|
55 |
+
} else {
|
56 |
+
session_start();
|
57 |
+
}
|
58 |
+
return $this;
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Get value by key
|
63 |
+
*
|
64 |
+
* @param string $key
|
65 |
+
* @return mixed
|
66 |
+
*/
|
67 |
+
public function get($key)
|
68 |
+
{
|
69 |
+
return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Set value for key
|
74 |
+
*
|
75 |
+
* @param string $key
|
76 |
+
* @param mixed $value
|
77 |
+
*/
|
78 |
+
public function set($key, $value)
|
79 |
+
{
|
80 |
+
$_SESSION[$key] = $value;
|
81 |
+
return $this;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Authentication to downloader
|
86 |
+
*/
|
87 |
+
public function authenticate()
|
88 |
+
{
|
89 |
+
if (!$this->_session) {
|
90 |
+
return $this;
|
91 |
+
}
|
92 |
+
|
93 |
+
if (!empty($_GET['return'])) {
|
94 |
+
$this->set('return_url', $_GET['return']);
|
95 |
+
}
|
96 |
+
|
97 |
+
if ($this->_checkUserAccess()) {
|
98 |
+
return $this;
|
99 |
+
}
|
100 |
+
|
101 |
+
if (!$this->controller()->isInstalled()) {
|
102 |
+
return $this;
|
103 |
+
}
|
104 |
+
|
105 |
+
try {
|
106 |
+
if ( (isset($_POST['username']) && empty($_POST['username']))
|
107 |
+
|| (isset($_POST['password']) && empty($_POST['password']))) {
|
108 |
+
$this->addMessage('error', 'Invalid user name or password');
|
109 |
+
}
|
110 |
+
if (empty($_POST['username']) || empty($_POST['password'])) {
|
111 |
+
$this->controller()->setAction('login');
|
112 |
+
return $this;
|
113 |
+
}
|
114 |
+
$user = $this->_session->login($_POST['username'], $_POST['password']);
|
115 |
+
$this->_session->refreshAcl();
|
116 |
+
if ($this->_checkUserAccess($user)) {
|
117 |
+
return $this;
|
118 |
+
}
|
119 |
+
} catch (Exception $e) {
|
120 |
+
$this->addMessage('error', $e->getMessage());
|
121 |
+
}
|
122 |
+
|
123 |
+
$this->controller()
|
124 |
+
->redirect(
|
125 |
+
$this->controller()->url('loggedin'),
|
126 |
+
true
|
127 |
+
);
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Check is user logged in and permissions
|
132 |
+
*
|
133 |
+
* @param Mage_Admin_Model_User|null $user
|
134 |
+
* @return bool
|
135 |
+
*/
|
136 |
+
protected function _checkUserAccess($user = null)
|
137 |
+
{
|
138 |
+
if ($user && !$user->getId()) {
|
139 |
+
$this->addMessage('error', 'Invalid user name or password');
|
140 |
+
$this->controller()->setAction('login');
|
141 |
+
} elseif ($this->getUserId() || ($user && $user->getId())) {
|
142 |
+
if ($this->_session->isAllowed('all')) {
|
143 |
+
return true;
|
144 |
+
} else {
|
145 |
+
$this->logout();
|
146 |
+
$this->addMessage('error', 'Access Denied', true);
|
147 |
+
$this->controller()->setAction('login');
|
148 |
+
}
|
149 |
+
}
|
150 |
+
return false;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Log Out
|
155 |
+
*
|
156 |
+
* @return Maged_Model_Session
|
157 |
+
*/
|
158 |
+
public function logout()
|
159 |
+
{
|
160 |
+
if (!$this->_session) {
|
161 |
+
return $this;
|
162 |
+
}
|
163 |
+
$this->_session->unsUser();
|
164 |
+
return $this;
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Retrieve user
|
169 |
+
*
|
170 |
+
* @return mixed
|
171 |
+
*/
|
172 |
+
public function getUserId()
|
173 |
+
{
|
174 |
+
if (($session = $this->_session) && ($user = $session->getUser())) {
|
175 |
+
return $user->getId();
|
176 |
+
}
|
177 |
+
return false;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Add Message
|
182 |
+
*
|
183 |
+
* @param string $type
|
184 |
+
* @param string $msg
|
185 |
+
* @param string $clear
|
186 |
+
* @return Maged_Model_Session
|
187 |
+
*/
|
188 |
+
public function addMessage($type, $msg, $clear = false)
|
189 |
+
{
|
190 |
+
$msgs = $this->getMessages($clear);
|
191 |
+
$msgs[$type][] = $msg;
|
192 |
+
$this->set('messages', $msgs);
|
193 |
+
return $this;
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Retrieve messages from cache
|
198 |
+
*
|
199 |
+
* @param boolean $clear
|
200 |
+
* @return mixed
|
201 |
+
*/
|
202 |
+
public function getMessages($clear = true)
|
203 |
+
{
|
204 |
+
$msgs = $this->get('messages');
|
205 |
+
$msgs = $msgs ? $msgs : array();
|
206 |
+
if ($clear) {
|
207 |
+
unset($_SESSION['messages']);
|
208 |
+
}
|
209 |
+
return $msgs;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Retrieve url to adminhtml
|
214 |
+
*
|
215 |
+
* @return string
|
216 |
+
*/
|
217 |
+
public function getReturnUrl()
|
218 |
+
{
|
219 |
+
if (!$this->_session || !$this->_session->isLoggedIn()) {
|
220 |
+
return '';
|
221 |
+
}
|
222 |
+
return Mage::getSingleton('adminhtml/url')->getUrl('adminhtml');
|
223 |
+
}
|
224 |
+
}
|
downloader/Maged/View.php
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class for viewer
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
33 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
34 |
+
*/
|
35 |
+
class Maged_View
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Internal cache
|
39 |
+
*
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
protected $_data = array();
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Constructor
|
46 |
+
*/
|
47 |
+
public function __construct()
|
48 |
+
{
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Retrieve Controller as singleton
|
54 |
+
*
|
55 |
+
* @return Maged_Controller
|
56 |
+
*/
|
57 |
+
public function controller()
|
58 |
+
{
|
59 |
+
return Maged_Controller::singleton();
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Create url by action and params
|
64 |
+
*
|
65 |
+
* @param mixed $action
|
66 |
+
* @param mixed $params
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
public function url($action='', $params=array())
|
70 |
+
{
|
71 |
+
return $this->controller()->url($action, $params);
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Retrieve base url
|
76 |
+
*
|
77 |
+
* @return string
|
78 |
+
*/
|
79 |
+
public function baseUrl()
|
80 |
+
{
|
81 |
+
return str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']));
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Retrieve url of magento
|
86 |
+
*
|
87 |
+
* @return string
|
88 |
+
*/
|
89 |
+
public function mageUrl()
|
90 |
+
{
|
91 |
+
return str_replace('\\', '/', dirname($this->baseUrl()));
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Include template
|
96 |
+
*
|
97 |
+
* @param string $name
|
98 |
+
* @return string
|
99 |
+
*/
|
100 |
+
public function template($name)
|
101 |
+
{
|
102 |
+
ob_start();
|
103 |
+
include $this->controller()->filepath('template/'.$name);
|
104 |
+
return ob_get_clean();
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Set value for key
|
109 |
+
*
|
110 |
+
* @param string $key
|
111 |
+
* @param mixed $value
|
112 |
+
* @return Maged_Controller
|
113 |
+
*/
|
114 |
+
public function set($key, $value)
|
115 |
+
{
|
116 |
+
$this->_data[$key] = $value;
|
117 |
+
return $this;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Get value by key
|
122 |
+
*
|
123 |
+
* @param string $key
|
124 |
+
* @return mixed
|
125 |
+
*/
|
126 |
+
public function get($key)
|
127 |
+
{
|
128 |
+
return isset($this->_data[$key]) ? $this->_data[$key] : null;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Translator
|
133 |
+
*
|
134 |
+
* @param string $string
|
135 |
+
* @return string
|
136 |
+
*/
|
137 |
+
public function __($string)
|
138 |
+
{
|
139 |
+
return $string;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Retrieve link for header menu
|
144 |
+
*
|
145 |
+
* @param mixed $action
|
146 |
+
*/
|
147 |
+
public function getNavLinkParams($action)
|
148 |
+
{
|
149 |
+
$params = 'href="'.$this->url($action).'"';
|
150 |
+
if ($this->controller()->getAction()==$action) {
|
151 |
+
$params .= ' class="active"';
|
152 |
+
}
|
153 |
+
return $params;
|
154 |
+
}
|
155 |
+
}
|
downloader/config.ini
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
root_channel=community
|
downloader/index.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
if (version_compare(phpversion(), '5.2.0', '<')===true) {
|
28 |
+
echo '<div style="font:12px/1.35em arial, helvetica, sans-serif;"><div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;"><h3 style="margin:0; font-size:1.7em; font-weight:normal; text-transform:none; text-align:left; color:#2f2f2f;">Whoops, it looks like you have an invalid PHP version.</h3></div><p>Magento supports PHP 5.2.0 or newer. <a href="http://www.magentocommerce.com/install" target="">Find out</a> how to install</a> Magento using PHP-CGI as a work-around.</p></div>';
|
29 |
+
exit;
|
30 |
+
}
|
31 |
+
|
32 |
+
require_once("lib/Mage/Autoload/Simple.php");
|
33 |
+
Mage_Autoload_Simple::register();
|
34 |
+
|
35 |
+
umask(0);
|
36 |
+
Maged_Controller::run();
|
downloader/js/prototype.js
ADDED
@@ -0,0 +1,3277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Prototype JavaScript framework, version 1.5.1.1
|
2 |
+
* (c) 2005-2007 Sam Stephenson
|
3 |
+
*
|
4 |
+
* Prototype is freely distributable under the terms of an MIT-style license.
|
5 |
+
* For details, see the Prototype web site: http://www.prototypejs.org/
|
6 |
+
*
|
7 |
+
/*--------------------------------------------------------------------------*/
|
8 |
+
|
9 |
+
var Prototype = {
|
10 |
+
Version: '1.5.1.1',
|
11 |
+
|
12 |
+
Browser: {
|
13 |
+
IE: !!(window.attachEvent && !window.opera),
|
14 |
+
Opera: !!window.opera,
|
15 |
+
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
|
16 |
+
Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
|
17 |
+
},
|
18 |
+
|
19 |
+
BrowserFeatures: {
|
20 |
+
XPath: !!document.evaluate,
|
21 |
+
ElementExtensions: !!window.HTMLElement,
|
22 |
+
SpecificElementExtensions:
|
23 |
+
(document.createElement('div').__proto__ !==
|
24 |
+
document.createElement('form').__proto__)
|
25 |
+
},
|
26 |
+
|
27 |
+
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
|
28 |
+
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
|
29 |
+
|
30 |
+
emptyFunction: function() { },
|
31 |
+
K: function(x) { return x }
|
32 |
+
}
|
33 |
+
|
34 |
+
var Class = {
|
35 |
+
create: function() {
|
36 |
+
return function() {
|
37 |
+
this.initialize.apply(this, arguments);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
var Abstract = new Object();
|
43 |
+
|
44 |
+
Object.extend = function(destination, source) {
|
45 |
+
for (var property in source) {
|
46 |
+
destination[property] = source[property];
|
47 |
+
}
|
48 |
+
return destination;
|
49 |
+
}
|
50 |
+
|
51 |
+
Object.extend(Object, {
|
52 |
+
inspect: function(object) {
|
53 |
+
try {
|
54 |
+
if (object === undefined) return 'undefined';
|
55 |
+
if (object === null) return 'null';
|
56 |
+
return object.inspect ? object.inspect() : object.toString();
|
57 |
+
} catch (e) {
|
58 |
+
if (e instanceof RangeError) return '...';
|
59 |
+
throw e;
|
60 |
+
}
|
61 |
+
},
|
62 |
+
|
63 |
+
toJSON: function(object) {
|
64 |
+
var type = typeof object;
|
65 |
+
switch(type) {
|
66 |
+
case 'undefined':
|
67 |
+
case 'function':
|
68 |
+
case 'unknown': return;
|
69 |
+
case 'boolean': return object.toString();
|
70 |
+
}
|
71 |
+
if (object === null) return 'null';
|
72 |
+
if (object.toJSON) return object.toJSON();
|
73 |
+
if (object.ownerDocument === document) return;
|
74 |
+
var results = [];
|
75 |
+
for (var property in object) {
|
76 |
+
var value = Object.toJSON(object[property]);
|
77 |
+
if (value !== undefined)
|
78 |
+
results.push(property.toJSON() + ': ' + value);
|
79 |
+
}
|
80 |
+
return '{' + results.join(', ') + '}';
|
81 |
+
},
|
82 |
+
|
83 |
+
keys: function(object) {
|
84 |
+
var keys = [];
|
85 |
+
for (var property in object)
|
86 |
+
keys.push(property);
|
87 |
+
return keys;
|
88 |
+
},
|
89 |
+
|
90 |
+
values: function(object) {
|
91 |
+
var values = [];
|
92 |
+
for (var property in object)
|
93 |
+
values.push(object[property]);
|
94 |
+
return values;
|
95 |
+
},
|
96 |
+
|
97 |
+
clone: function(object) {
|
98 |
+
return Object.extend({}, object);
|
99 |
+
}
|
100 |
+
});
|
101 |
+
|
102 |
+
Function.prototype.bind = function() {
|
103 |
+
var __method = this, args = $A(arguments), object = args.shift();
|
104 |
+
return function() {
|
105 |
+
return __method.apply(object, args.concat($A(arguments)));
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
Function.prototype.bindAsEventListener = function(object) {
|
110 |
+
var __method = this, args = $A(arguments), object = args.shift();
|
111 |
+
return function(event) {
|
112 |
+
return __method.apply(object, [event || window.event].concat(args));
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
Object.extend(Number.prototype, {
|
117 |
+
toColorPart: function() {
|
118 |
+
return this.toPaddedString(2, 16);
|
119 |
+
},
|
120 |
+
|
121 |
+
succ: function() {
|
122 |
+
return this + 1;
|
123 |
+
},
|
124 |
+
|
125 |
+
times: function(iterator) {
|
126 |
+
$R(0, this, true).each(iterator);
|
127 |
+
return this;
|
128 |
+
},
|
129 |
+
|
130 |
+
toPaddedString: function(length, radix) {
|
131 |
+
var string = this.toString(radix || 10);
|
132 |
+
return '0'.times(length - string.length) + string;
|
133 |
+
},
|
134 |
+
|
135 |
+
toJSON: function() {
|
136 |
+
return isFinite(this) ? this.toString() : 'null';
|
137 |
+
}
|
138 |
+
});
|
139 |
+
|
140 |
+
Date.prototype.toJSON = function() {
|
141 |
+
return '"' + this.getFullYear() + '-' +
|
142 |
+
(this.getMonth() + 1).toPaddedString(2) + '-' +
|
143 |
+
this.getDate().toPaddedString(2) + 'T' +
|
144 |
+
this.getHours().toPaddedString(2) + ':' +
|
145 |
+
this.getMinutes().toPaddedString(2) + ':' +
|
146 |
+
this.getSeconds().toPaddedString(2) + '"';
|
147 |
+
};
|
148 |
+
|
149 |
+
var Try = {
|
150 |
+
these: function() {
|
151 |
+
var returnValue;
|
152 |
+
|
153 |
+
for (var i = 0, length = arguments.length; i < length; i++) {
|
154 |
+
var lambda = arguments[i];
|
155 |
+
try {
|
156 |
+
returnValue = lambda();
|
157 |
+
break;
|
158 |
+
} catch (e) {}
|
159 |
+
}
|
160 |
+
|
161 |
+
return returnValue;
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
/*--------------------------------------------------------------------------*/
|
166 |
+
|
167 |
+
var PeriodicalExecuter = Class.create();
|
168 |
+
PeriodicalExecuter.prototype = {
|
169 |
+
initialize: function(callback, frequency) {
|
170 |
+
this.callback = callback;
|
171 |
+
this.frequency = frequency;
|
172 |
+
this.currentlyExecuting = false;
|
173 |
+
|
174 |
+
this.registerCallback();
|
175 |
+
},
|
176 |
+
|
177 |
+
registerCallback: function() {
|
178 |
+
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
|
179 |
+
},
|
180 |
+
|
181 |
+
stop: function() {
|
182 |
+
if (!this.timer) return;
|
183 |
+
clearInterval(this.timer);
|
184 |
+
this.timer = null;
|
185 |
+
},
|
186 |
+
|
187 |
+
onTimerEvent: function() {
|
188 |
+
if (!this.currentlyExecuting) {
|
189 |
+
try {
|
190 |
+
this.currentlyExecuting = true;
|
191 |
+
this.callback(this);
|
192 |
+
} finally {
|
193 |
+
this.currentlyExecuting = false;
|
194 |
+
}
|
195 |
+
}
|
196 |
+
}
|
197 |
+
}
|
198 |
+
Object.extend(String, {
|
199 |
+
interpret: function(value) {
|
200 |
+
return value == null ? '' : String(value);
|
201 |
+
},
|
202 |
+
specialChar: {
|
203 |
+
'\b': '\\b',
|
204 |
+
'\t': '\\t',
|
205 |
+
'\n': '\\n',
|
206 |
+
'\f': '\\f',
|
207 |
+
'\r': '\\r',
|
208 |
+
'\\': '\\\\'
|
209 |
+
}
|
210 |
+
});
|
211 |
+
|
212 |
+
Object.extend(String.prototype, {
|
213 |
+
gsub: function(pattern, replacement) {
|
214 |
+
var result = '', source = this, match;
|
215 |
+
replacement = arguments.callee.prepareReplacement(replacement);
|
216 |
+
|
217 |
+
while (source.length > 0) {
|
218 |
+
if (match = source.match(pattern)) {
|
219 |
+
result += source.slice(0, match.index);
|
220 |
+
result += String.interpret(replacement(match));
|
221 |
+
source = source.slice(match.index + match[0].length);
|
222 |
+
} else {
|
223 |
+
result += source, source = '';
|
224 |
+
}
|
225 |
+
}
|
226 |
+
return result;
|
227 |
+
},
|
228 |
+
|
229 |
+
sub: function(pattern, replacement, count) {
|
230 |
+
replacement = this.gsub.prepareReplacement(replacement);
|
231 |
+
count = count === undefined ? 1 : count;
|
232 |
+
|
233 |
+
return this.gsub(pattern, function(match) {
|
234 |
+
if (--count < 0) return match[0];
|
235 |
+
return replacement(match);
|
236 |
+
});
|
237 |
+
},
|
238 |
+
|
239 |
+
scan: function(pattern, iterator) {
|
240 |
+
this.gsub(pattern, iterator);
|
241 |
+
return this;
|
242 |
+
},
|
243 |
+
|
244 |
+
truncate: function(length, truncation) {
|
245 |
+
length = length || 30;
|
246 |
+
truncation = truncation === undefined ? '...' : truncation;
|
247 |
+
return this.length > length ?
|
248 |
+
this.slice(0, length - truncation.length) + truncation : this;
|
249 |
+
},
|
250 |
+
|
251 |
+
strip: function() {
|
252 |
+
return this.replace(/^\s+/, '').replace(/\s+$/, '');
|
253 |
+
},
|
254 |
+
|
255 |
+
stripTags: function() {
|
256 |
+
return this.replace(/<\/?[^>]+>/gi, '');
|
257 |
+
},
|
258 |
+
|
259 |
+
stripScripts: function() {
|
260 |
+
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
|
261 |
+
},
|
262 |
+
|
263 |
+
extractScripts: function() {
|
264 |
+
var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
|
265 |
+
var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
|
266 |
+
return (this.match(matchAll) || []).map(function(scriptTag) {
|
267 |
+
return (scriptTag.match(matchOne) || ['', ''])[1];
|
268 |
+
});
|
269 |
+
},
|
270 |
+
|
271 |
+
evalScripts: function() {
|
272 |
+
return this.extractScripts().map(function(script) { return eval(script) });
|
273 |
+
},
|
274 |
+
|
275 |
+
escapeHTML: function() {
|
276 |
+
var self = arguments.callee;
|
277 |
+
self.text.data = this;
|
278 |
+
return self.div.innerHTML;
|
279 |
+
},
|
280 |
+
|
281 |
+
unescapeHTML: function() {
|
282 |
+
var div = document.createElement('div');
|
283 |
+
div.innerHTML = this.stripTags();
|
284 |
+
return div.childNodes[0] ? (div.childNodes.length > 1 ?
|
285 |
+
$A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
|
286 |
+
div.childNodes[0].nodeValue) : '';
|
287 |
+
},
|
288 |
+
|
289 |
+
toQueryParams: function(separator) {
|
290 |
+
var match = this.strip().match(/([^?#]*)(#.*)?$/);
|
291 |
+
if (!match) return {};
|
292 |
+
|
293 |
+
return match[1].split(separator || '&').inject({}, function(hash, pair) {
|
294 |
+
if ((pair = pair.split('='))[0]) {
|
295 |
+
var key = decodeURIComponent(pair.shift());
|
296 |
+
var value = pair.length > 1 ? pair.join('=') : pair[0];
|
297 |
+
if (value != undefined) value = decodeURIComponent(value);
|
298 |
+
|
299 |
+
if (key in hash) {
|
300 |
+
if (hash[key].constructor != Array) hash[key] = [hash[key]];
|
301 |
+
hash[key].push(value);
|
302 |
+
}
|
303 |
+
else hash[key] = value;
|
304 |
+
}
|
305 |
+
return hash;
|
306 |
+
});
|
307 |
+
},
|
308 |
+
|
309 |
+
toArray: function() {
|
310 |
+
return this.split('');
|
311 |
+
},
|
312 |
+
|
313 |
+
succ: function() {
|
314 |
+
return this.slice(0, this.length - 1) +
|
315 |
+
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
|
316 |
+
},
|
317 |
+
|
318 |
+
times: function(count) {
|
319 |
+
var result = '';
|
320 |
+
for (var i = 0; i < count; i++) result += this;
|
321 |
+
return result;
|
322 |
+
},
|
323 |
+
|
324 |
+
camelize: function() {
|
325 |
+
var parts = this.split('-'), len = parts.length;
|
326 |
+
if (len == 1) return parts[0];
|
327 |
+
|
328 |
+
var camelized = this.charAt(0) == '-'
|
329 |
+
? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
|
330 |
+
: parts[0];
|
331 |
+
|
332 |
+
for (var i = 1; i < len; i++)
|
333 |
+
camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
|
334 |
+
|
335 |
+
return camelized;
|
336 |
+
},
|
337 |
+
|
338 |
+
capitalize: function() {
|
339 |
+
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
|
340 |
+
},
|
341 |
+
|
342 |
+
underscore: function() {
|
343 |
+
return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
|
344 |
+
},
|
345 |
+
|
346 |
+
dasherize: function() {
|
347 |
+
return this.gsub(/_/,'-');
|
348 |
+
},
|
349 |
+
|
350 |
+
inspect: function(useDoubleQuotes) {
|
351 |
+
var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
|
352 |
+
var character = String.specialChar[match[0]];
|
353 |
+
return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
|
354 |
+
});
|
355 |
+
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
|
356 |
+
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
|
357 |
+
},
|
358 |
+
|
359 |
+
toJSON: function() {
|
360 |
+
return this.inspect(true);
|
361 |
+
},
|
362 |
+
|
363 |
+
unfilterJSON: function(filter) {
|
364 |
+
return this.sub(filter || Prototype.JSONFilter, '#{1}');
|
365 |
+
},
|
366 |
+
|
367 |
+
isJSON: function() {
|
368 |
+
var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
|
369 |
+
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
|
370 |
+
},
|
371 |
+
|
372 |
+
evalJSON: function(sanitize) {
|
373 |
+
var json = this.unfilterJSON();
|
374 |
+
try {
|
375 |
+
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
|
376 |
+
} catch (e) { }
|
377 |
+
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
|
378 |
+
},
|
379 |
+
|
380 |
+
include: function(pattern) {
|
381 |
+
return this.indexOf(pattern) > -1;
|
382 |
+
},
|
383 |
+
|
384 |
+
startsWith: function(pattern) {
|
385 |
+
return this.indexOf(pattern) === 0;
|
386 |
+
},
|
387 |
+
|
388 |
+
endsWith: function(pattern) {
|
389 |
+
var d = this.length - pattern.length;
|
390 |
+
return d >= 0 && this.lastIndexOf(pattern) === d;
|
391 |
+
},
|
392 |
+
|
393 |
+
empty: function() {
|
394 |
+
return this == '';
|
395 |
+
},
|
396 |
+
|
397 |
+
blank: function() {
|
398 |
+
return /^\s*$/.test(this);
|
399 |
+
}
|
400 |
+
});
|
401 |
+
|
402 |
+
if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
|
403 |
+
escapeHTML: function() {
|
404 |
+
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
405 |
+
},
|
406 |
+
unescapeHTML: function() {
|
407 |
+
return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
408 |
+
}
|
409 |
+
});
|
410 |
+
|
411 |
+
String.prototype.gsub.prepareReplacement = function(replacement) {
|
412 |
+
if (typeof replacement == 'function') return replacement;
|
413 |
+
var template = new Template(replacement);
|
414 |
+
return function(match) { return template.evaluate(match) };
|
415 |
+
}
|
416 |
+
|
417 |
+
String.prototype.parseQuery = String.prototype.toQueryParams;
|
418 |
+
|
419 |
+
Object.extend(String.prototype.escapeHTML, {
|
420 |
+
div: document.createElement('div'),
|
421 |
+
text: document.createTextNode('')
|
422 |
+
});
|
423 |
+
|
424 |
+
with (String.prototype.escapeHTML) div.appendChild(text);
|
425 |
+
|
426 |
+
var Template = Class.create();
|
427 |
+
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
|
428 |
+
Template.prototype = {
|
429 |
+
initialize: function(template, pattern) {
|
430 |
+
this.template = template.toString();
|
431 |
+
this.pattern = pattern || Template.Pattern;
|
432 |
+
},
|
433 |
+
|
434 |
+
evaluate: function(object) {
|
435 |
+
return this.template.gsub(this.pattern, function(match) {
|
436 |
+
var before = match[1];
|
437 |
+
if (before == '\\') return match[2];
|
438 |
+
return before + String.interpret(object[match[3]]);
|
439 |
+
});
|
440 |
+
}
|
441 |
+
}
|
442 |
+
|
443 |
+
var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
|
444 |
+
|
445 |
+
var Enumerable = {
|
446 |
+
each: function(iterator) {
|
447 |
+
var index = 0;
|
448 |
+
try {
|
449 |
+
this._each(function(value) {
|
450 |
+
iterator(value, index++);
|
451 |
+
});
|
452 |
+
} catch (e) {
|
453 |
+
if (e != $break) throw e;
|
454 |
+
}
|
455 |
+
return this;
|
456 |
+
},
|
457 |
+
|
458 |
+
eachSlice: function(number, iterator) {
|
459 |
+
var index = -number, slices = [], array = this.toArray();
|
460 |
+
while ((index += number) < array.length)
|
461 |
+
slices.push(array.slice(index, index+number));
|
462 |
+
return slices.map(iterator);
|
463 |
+
},
|
464 |
+
|
465 |
+
all: function(iterator) {
|
466 |
+
var result = true;
|
467 |
+
this.each(function(value, index) {
|
468 |
+
result = result && !!(iterator || Prototype.K)(value, index);
|
469 |
+
if (!result) throw $break;
|
470 |
+
});
|
471 |
+
return result;
|
472 |
+
},
|
473 |
+
|
474 |
+
any: function(iterator) {
|
475 |
+
var result = false;
|
476 |
+
this.each(function(value, index) {
|
477 |
+
if (result = !!(iterator || Prototype.K)(value, index))
|
478 |
+
throw $break;
|
479 |
+
});
|
480 |
+
return result;
|
481 |
+
},
|
482 |
+
|
483 |
+
collect: function(iterator) {
|
484 |
+
var results = [];
|
485 |
+
this.each(function(value, index) {
|
486 |
+
results.push((iterator || Prototype.K)(value, index));
|
487 |
+
});
|
488 |
+
return results;
|
489 |
+
},
|
490 |
+
|
491 |
+
detect: function(iterator) {
|
492 |
+
var result;
|
493 |
+
this.each(function(value, index) {
|
494 |
+
if (iterator(value, index)) {
|
495 |
+
result = value;
|
496 |
+
throw $break;
|
497 |
+
}
|
498 |
+
});
|
499 |
+
return result;
|
500 |
+
},
|
501 |
+
|
502 |
+
findAll: function(iterator) {
|
503 |
+
var results = [];
|
504 |
+
this.each(function(value, index) {
|
505 |
+
if (iterator(value, index))
|
506 |
+
results.push(value);
|
507 |
+
});
|
508 |
+
return results;
|
509 |
+
},
|
510 |
+
|
511 |
+
grep: function(pattern, iterator) {
|
512 |
+
var results = [];
|
513 |
+
this.each(function(value, index) {
|
514 |
+
var stringValue = value.toString();
|
515 |
+
if (stringValue.match(pattern))
|
516 |
+
results.push((iterator || Prototype.K)(value, index));
|
517 |
+
})
|
518 |
+
return results;
|
519 |
+
},
|
520 |
+
|
521 |
+
include: function(object) {
|
522 |
+
var found = false;
|
523 |
+
this.each(function(value) {
|
524 |
+
if (value == object) {
|
525 |
+
found = true;
|
526 |
+
throw $break;
|
527 |
+
}
|
528 |
+
});
|
529 |
+
return found;
|
530 |
+
},
|
531 |
+
|
532 |
+
inGroupsOf: function(number, fillWith) {
|
533 |
+
fillWith = fillWith === undefined ? null : fillWith;
|
534 |
+
return this.eachSlice(number, function(slice) {
|
535 |
+
while(slice.length < number) slice.push(fillWith);
|
536 |
+
return slice;
|
537 |
+
});
|
538 |
+
},
|
539 |
+
|
540 |
+
inject: function(memo, iterator) {
|
541 |
+
this.each(function(value, index) {
|
542 |
+
memo = iterator(memo, value, index);
|
543 |
+
});
|
544 |
+
return memo;
|
545 |
+
},
|
546 |
+
|
547 |
+
invoke: function(method) {
|
548 |
+
var args = $A(arguments).slice(1);
|
549 |
+
return this.map(function(value) {
|
550 |
+
return value[method].apply(value, args);
|
551 |
+
});
|
552 |
+
},
|
553 |
+
|
554 |
+
max: function(iterator) {
|
555 |
+
var result;
|
556 |
+
this.each(function(value, index) {
|
557 |
+
value = (iterator || Prototype.K)(value, index);
|
558 |
+
if (result == undefined || value >= result)
|
559 |
+
result = value;
|
560 |
+
});
|
561 |
+
return result;
|
562 |
+
},
|
563 |
+
|
564 |
+
min: function(iterator) {
|
565 |
+
var result;
|
566 |
+
this.each(function(value, index) {
|
567 |
+
value = (iterator || Prototype.K)(value, index);
|
568 |
+
if (result == undefined || value < result)
|
569 |
+
result = value;
|
570 |
+
});
|
571 |
+
return result;
|
572 |
+
},
|
573 |
+
|
574 |
+
partition: function(iterator) {
|
575 |
+
var trues = [], falses = [];
|
576 |
+
this.each(function(value, index) {
|
577 |
+
((iterator || Prototype.K)(value, index) ?
|
578 |
+
trues : falses).push(value);
|
579 |
+
});
|
580 |
+
return [trues, falses];
|
581 |
+
},
|
582 |
+
|
583 |
+
pluck: function(property) {
|
584 |
+
var results = [];
|
585 |
+
this.each(function(value, index) {
|
586 |
+
results.push(value[property]);
|
587 |
+
});
|
588 |
+
return results;
|
589 |
+
},
|
590 |
+
|
591 |
+
reject: function(iterator) {
|
592 |
+
var results = [];
|
593 |
+
this.each(function(value, index) {
|
594 |
+
if (!iterator(value, index))
|
595 |
+
results.push(value);
|
596 |
+
});
|
597 |
+
return results;
|
598 |
+
},
|
599 |
+
|
600 |
+
sortBy: function(iterator) {
|
601 |
+
return this.map(function(value, index) {
|
602 |
+
return {value: value, criteria: iterator(value, index)};
|
603 |
+
}).sort(function(left, right) {
|
604 |
+
var a = left.criteria, b = right.criteria;
|
605 |
+
return a < b ? -1 : a > b ? 1 : 0;
|
606 |
+
}).pluck('value');
|
607 |
+
},
|
608 |
+
|
609 |
+
toArray: function() {
|
610 |
+
return this.map();
|
611 |
+
},
|
612 |
+
|
613 |
+
zip: function() {
|
614 |
+
var iterator = Prototype.K, args = $A(arguments);
|
615 |
+
if (typeof args.last() == 'function')
|
616 |
+
iterator = args.pop();
|
617 |
+
|
618 |
+
var collections = [this].concat(args).map($A);
|
619 |
+
return this.map(function(value, index) {
|
620 |
+
return iterator(collections.pluck(index));
|
621 |
+
});
|
622 |
+
},
|
623 |
+
|
624 |
+
size: function() {
|
625 |
+
return this.toArray().length;
|
626 |
+
},
|
627 |
+
|
628 |
+
inspect: function() {
|
629 |
+
return '#<Enumerable:' + this.toArray().inspect() + '>';
|
630 |
+
}
|
631 |
+
}
|
632 |
+
|
633 |
+
Object.extend(Enumerable, {
|
634 |
+
map: Enumerable.collect,
|
635 |
+
find: Enumerable.detect,
|
636 |
+
select: Enumerable.findAll,
|
637 |
+
member: Enumerable.include,
|
638 |
+
entries: Enumerable.toArray
|
639 |
+
});
|
640 |
+
var $A = Array.from = function(iterable) {
|
641 |
+
if (!iterable) return [];
|
642 |
+
if (iterable.toArray) {
|
643 |
+
return iterable.toArray();
|
644 |
+
} else {
|
645 |
+
var results = [];
|
646 |
+
for (var i = 0, length = iterable.length; i < length; i++)
|
647 |
+
results.push(iterable[i]);
|
648 |
+
return results;
|
649 |
+
}
|
650 |
+
}
|
651 |
+
|
652 |
+
if (Prototype.Browser.WebKit) {
|
653 |
+
$A = Array.from = function(iterable) {
|
654 |
+
if (!iterable) return [];
|
655 |
+
if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
|
656 |
+
iterable.toArray) {
|
657 |
+
return iterable.toArray();
|
658 |
+
} else {
|
659 |
+
var results = [];
|
660 |
+
for (var i = 0, length = iterable.length; i < length; i++)
|
661 |
+
results.push(iterable[i]);
|
662 |
+
return results;
|
663 |
+
}
|
664 |
+
}
|
665 |
+
}
|
666 |
+
|
667 |
+
Object.extend(Array.prototype, Enumerable);
|
668 |
+
|
669 |
+
if (!Array.prototype._reverse)
|
670 |
+
Array.prototype._reverse = Array.prototype.reverse;
|
671 |
+
|
672 |
+
Object.extend(Array.prototype, {
|
673 |
+
_each: function(iterator) {
|
674 |
+
for (var i = 0, length = this.length; i < length; i++)
|
675 |
+
iterator(this[i]);
|
676 |
+
},
|
677 |
+
|
678 |
+
clear: function() {
|
679 |
+
this.length = 0;
|
680 |
+
return this;
|
681 |
+
},
|
682 |
+
|
683 |
+
first: function() {
|
684 |
+
return this[0];
|
685 |
+
},
|
686 |
+
|
687 |
+
last: function() {
|
688 |
+
return this[this.length - 1];
|
689 |
+
},
|
690 |
+
|
691 |
+
compact: function() {
|
692 |
+
return this.select(function(value) {
|
693 |
+
return value != null;
|
694 |
+
});
|
695 |
+
},
|
696 |
+
|
697 |
+
flatten: function() {
|
698 |
+
return this.inject([], function(array, value) {
|
699 |
+
return array.concat(value && value.constructor == Array ?
|
700 |
+
value.flatten() : [value]);
|
701 |
+
});
|
702 |
+
},
|
703 |
+
|
704 |
+
without: function() {
|
705 |
+
var values = $A(arguments);
|
706 |
+
return this.select(function(value) {
|
707 |
+
return !values.include(value);
|
708 |
+
});
|
709 |
+
},
|
710 |
+
|
711 |
+
indexOf: function(object) {
|
712 |
+
for (var i = 0, length = this.length; i < length; i++)
|
713 |
+
if (this[i] == object) return i;
|
714 |
+
return -1;
|
715 |
+
},
|
716 |
+
|
717 |
+
reverse: function(inline) {
|
718 |
+
return (inline !== false ? this : this.toArray())._reverse();
|
719 |
+
},
|
720 |
+
|
721 |
+
reduce: function() {
|
722 |
+
return this.length > 1 ? this : this[0];
|
723 |
+
},
|
724 |
+
|
725 |
+
uniq: function(sorted) {
|
726 |
+
return this.inject([], function(array, value, index) {
|
727 |
+
if (0 == index || (sorted ? array.last() != value : !array.include(value)))
|
728 |
+
array.push(value);
|
729 |
+
return array;
|
730 |
+
});
|
731 |
+
},
|
732 |
+
|
733 |
+
clone: function() {
|
734 |
+
return [].concat(this);
|
735 |
+
},
|
736 |
+
|
737 |
+
size: function() {
|
738 |
+
return this.length;
|
739 |
+
},
|
740 |
+
|
741 |
+
inspect: function() {
|
742 |
+
return '[' + this.map(Object.inspect).join(', ') + ']';
|
743 |
+
},
|
744 |
+
|
745 |
+
toJSON: function() {
|
746 |
+
var results = [];
|
747 |
+
this.each(function(object) {
|
748 |
+
var value = Object.toJSON(object);
|
749 |
+
if (value !== undefined) results.push(value);
|
750 |
+
});
|
751 |
+
return '[' + results.join(', ') + ']';
|
752 |
+
}
|
753 |
+
});
|
754 |
+
|
755 |
+
Array.prototype.toArray = Array.prototype.clone;
|
756 |
+
|
757 |
+
function $w(string) {
|
758 |
+
string = string.strip();
|
759 |
+
return string ? string.split(/\s+/) : [];
|
760 |
+
}
|
761 |
+
|
762 |
+
if (Prototype.Browser.Opera){
|
763 |
+
Array.prototype.concat = function() {
|
764 |
+
var array = [];
|
765 |
+
for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
|
766 |
+
for (var i = 0, length = arguments.length; i < length; i++) {
|
767 |
+
if (arguments[i].constructor == Array) {
|
768 |
+
for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
|
769 |
+
array.push(arguments[i][j]);
|
770 |
+
} else {
|
771 |
+
array.push(arguments[i]);
|
772 |
+
}
|
773 |
+
}
|
774 |
+
return array;
|
775 |
+
}
|
776 |
+
}
|
777 |
+
var Hash = function(object) {
|
778 |
+
if (object instanceof Hash) this.merge(object);
|
779 |
+
else Object.extend(this, object || {});
|
780 |
+
};
|
781 |
+
|
782 |
+
Object.extend(Hash, {
|
783 |
+
toQueryString: function(obj) {
|
784 |
+
var parts = [];
|
785 |
+
parts.add = arguments.callee.addPair;
|
786 |
+
|
787 |
+
this.prototype._each.call(obj, function(pair) {
|
788 |
+
if (!pair.key) return;
|
789 |
+
var value = pair.value;
|
790 |
+
|
791 |
+
if (value && typeof value == 'object') {
|
792 |
+
if (value.constructor == Array) value.each(function(value) {
|
793 |
+
parts.add(pair.key, value);
|
794 |
+
});
|
795 |
+
return;
|
796 |
+
}
|
797 |
+
parts.add(pair.key, value);
|
798 |
+
});
|
799 |
+
|
800 |
+
return parts.join('&');
|
801 |
+
},
|
802 |
+
|
803 |
+
toJSON: function(object) {
|
804 |
+
var results = [];
|
805 |
+
this.prototype._each.call(object, function(pair) {
|
806 |
+
var value = Object.toJSON(pair.value);
|
807 |
+
if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
|
808 |
+
});
|
809 |
+
return '{' + results.join(', ') + '}';
|
810 |
+
}
|
811 |
+
});
|
812 |
+
|
813 |
+
Hash.toQueryString.addPair = function(key, value, prefix) {
|
814 |
+
key = encodeURIComponent(key);
|
815 |
+
if (value === undefined) this.push(key);
|
816 |
+
else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
|
817 |
+
}
|
818 |
+
|
819 |
+
Object.extend(Hash.prototype, Enumerable);
|
820 |
+
Object.extend(Hash.prototype, {
|
821 |
+
_each: function(iterator) {
|
822 |
+
for (var key in this) {
|
823 |
+
var value = this[key];
|
824 |
+
if (value && value == Hash.prototype[key]) continue;
|
825 |
+
|
826 |
+
var pair = [key, value];
|
827 |
+
pair.key = key;
|
828 |
+
pair.value = value;
|
829 |
+
iterator(pair);
|
830 |
+
}
|
831 |
+
},
|
832 |
+
|
833 |
+
keys: function() {
|
834 |
+
return this.pluck('key');
|
835 |
+
},
|
836 |
+
|
837 |
+
values: function() {
|
838 |
+
return this.pluck('value');
|
839 |
+
},
|
840 |
+
|
841 |
+
merge: function(hash) {
|
842 |
+
return $H(hash).inject(this, function(mergedHash, pair) {
|
843 |
+
mergedHash[pair.key] = pair.value;
|
844 |
+
return mergedHash;
|
845 |
+
});
|
846 |
+
},
|
847 |
+
|
848 |
+
remove: function() {
|
849 |
+
var result;
|
850 |
+
for(var i = 0, length = arguments.length; i < length; i++) {
|
851 |
+
var value = this[arguments[i]];
|
852 |
+
if (value !== undefined){
|
853 |
+
if (result === undefined) result = value;
|
854 |
+
else {
|
855 |
+
if (result.constructor != Array) result = [result];
|
856 |
+
result.push(value)
|
857 |
+
}
|
858 |
+
}
|
859 |
+
delete this[arguments[i]];
|
860 |
+
}
|
861 |
+
return result;
|
862 |
+
},
|
863 |
+
|
864 |
+
toQueryString: function() {
|
865 |
+
return Hash.toQueryString(this);
|
866 |
+
},
|
867 |
+
|
868 |
+
inspect: function() {
|
869 |
+
return '#<Hash:{' + this.map(function(pair) {
|
870 |
+
return pair.map(Object.inspect).join(': ');
|
871 |
+
}).join(', ') + '}>';
|
872 |
+
},
|
873 |
+
|
874 |
+
toJSON: function() {
|
875 |
+
return Hash.toJSON(this);
|
876 |
+
}
|
877 |
+
});
|
878 |
+
|
879 |
+
function $H(object) {
|
880 |
+
if (object instanceof Hash) return object;
|
881 |
+
return new Hash(object);
|
882 |
+
};
|
883 |
+
|
884 |
+
// Safari iterates over shadowed properties
|
885 |
+
if (function() {
|
886 |
+
var i = 0, Test = function(value) { this.key = value };
|
887 |
+
Test.prototype.key = 'foo';
|
888 |
+
for (var property in new Test('bar')) i++;
|
889 |
+
return i > 1;
|
890 |
+
}()) Hash.prototype._each = function(iterator) {
|
891 |
+
var cache = [];
|
892 |
+
for (var key in this) {
|
893 |
+
var value = this[key];
|
894 |
+
if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
|
895 |
+
cache.push(key);
|
896 |
+
var pair = [key, value];
|
897 |
+
pair.key = key;
|
898 |
+
pair.value = value;
|
899 |
+
iterator(pair);
|
900 |
+
}
|
901 |
+
};
|
902 |
+
ObjectRange = Class.create();
|
903 |
+
Object.extend(ObjectRange.prototype, Enumerable);
|
904 |
+
Object.extend(ObjectRange.prototype, {
|
905 |
+
initialize: function(start, end, exclusive) {
|
906 |
+
this.start = start;
|
907 |
+
this.end = end;
|
908 |
+
this.exclusive = exclusive;
|
909 |
+
},
|
910 |
+
|
911 |
+
_each: function(iterator) {
|
912 |
+
var value = this.start;
|
913 |
+
while (this.include(value)) {
|
914 |
+
iterator(value);
|
915 |
+
value = value.succ();
|
916 |
+
}
|
917 |
+
},
|
918 |
+
|
919 |
+
include: function(value) {
|
920 |
+
if (value < this.start)
|
921 |
+
return false;
|
922 |
+
if (this.exclusive)
|
923 |
+
return value < this.end;
|
924 |
+
return value <= this.end;
|
925 |
+
}
|
926 |
+
});
|
927 |
+
|
928 |
+
var $R = function(start, end, exclusive) {
|
929 |
+
return new ObjectRange(start, end, exclusive);
|
930 |
+
}
|
931 |
+
|
932 |
+
var Ajax = {
|
933 |
+
getTransport: function() {
|
934 |
+
return Try.these(
|
935 |
+
function() {return new XMLHttpRequest()},
|
936 |
+
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
|
937 |
+
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
|
938 |
+
) || false;
|
939 |
+
},
|
940 |
+
|
941 |
+
activeRequestCount: 0
|
942 |
+
}
|
943 |
+
|
944 |
+
Ajax.Responders = {
|
945 |
+
responders: [],
|
946 |
+
|
947 |
+
_each: function(iterator) {
|
948 |
+
this.responders._each(iterator);
|
949 |
+
},
|
950 |
+
|
951 |
+
register: function(responder) {
|
952 |
+
if (!this.include(responder))
|
953 |
+
this.responders.push(responder);
|
954 |
+
},
|
955 |
+
|
956 |
+
unregister: function(responder) {
|
957 |
+
this.responders = this.responders.without(responder);
|
958 |
+
},
|
959 |
+
|
960 |
+
dispatch: function(callback, request, transport, json) {
|
961 |
+
this.each(function(responder) {
|
962 |
+
if (typeof responder[callback] == 'function') {
|
963 |
+
try {
|
964 |
+
responder[callback].apply(responder, [request, transport, json]);
|
965 |
+
} catch (e) {}
|
966 |
+
}
|
967 |
+
});
|
968 |
+
}
|
969 |
+
};
|
970 |
+
|
971 |
+
Object.extend(Ajax.Responders, Enumerable);
|
972 |
+
|
973 |
+
Ajax.Responders.register({
|
974 |
+
onCreate: function() {
|
975 |
+
Ajax.activeRequestCount++;
|
976 |
+
},
|
977 |
+
onComplete: function() {
|
978 |
+
Ajax.activeRequestCount--;
|
979 |
+
}
|
980 |
+
});
|
981 |
+
|
982 |
+
Ajax.Base = function() {};
|
983 |
+
Ajax.Base.prototype = {
|
984 |
+
setOptions: function(options) {
|
985 |
+
this.options = {
|
986 |
+
method: 'post',
|
987 |
+
asynchronous: true,
|
988 |
+
contentType: 'application/x-www-form-urlencoded',
|
989 |
+
encoding: 'UTF-8',
|
990 |
+
parameters: ''
|
991 |
+
}
|
992 |
+
Object.extend(this.options, options || {});
|
993 |
+
|
994 |
+
this.options.method = this.options.method.toLowerCase();
|
995 |
+
if (typeof this.options.parameters == 'string')
|
996 |
+
this.options.parameters = this.options.parameters.toQueryParams();
|
997 |
+
}
|
998 |
+
}
|
999 |
+
|
1000 |
+
Ajax.Request = Class.create();
|
1001 |
+
Ajax.Request.Events =
|
1002 |
+
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
|
1003 |
+
|
1004 |
+
Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
|
1005 |
+
_complete: false,
|
1006 |
+
|
1007 |
+
initialize: function(url, options) {
|
1008 |
+
this.transport = Ajax.getTransport();
|
1009 |
+
this.setOptions(options);
|
1010 |
+
this.request(url);
|
1011 |
+
},
|
1012 |
+
|
1013 |
+
request: function(url) {
|
1014 |
+
this.url = url;
|
1015 |
+
this.method = this.options.method;
|
1016 |
+
var params = Object.clone(this.options.parameters);
|
1017 |
+
|
1018 |
+
if (!['get', 'post'].include(this.method)) {
|
1019 |
+
// simulate other verbs over post
|
1020 |
+
params['_method'] = this.method;
|
1021 |
+
this.method = 'post';
|
1022 |
+
}
|
1023 |
+
|
1024 |
+
this.parameters = params;
|
1025 |
+
|
1026 |
+
if (params = Hash.toQueryString(params)) {
|
1027 |
+
// when GET, append parameters to URL
|
1028 |
+
if (this.method == 'get')
|
1029 |
+
this.url += (this.url.include('?') ? '&' : '?') + params;
|
1030 |
+
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
|
1031 |
+
params += '&_=';
|
1032 |
+
}
|
1033 |
+
|
1034 |
+
try {
|
1035 |
+
if (this.options.onCreate) this.options.onCreate(this.transport);
|
1036 |
+
Ajax.Responders.dispatch('onCreate', this, this.transport);
|
1037 |
+
|
1038 |
+
this.transport.open(this.method.toUpperCase(), this.url,
|
1039 |
+
this.options.asynchronous);
|
1040 |
+
|
1041 |
+
if (this.options.asynchronous)
|
1042 |
+
setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
|
1043 |
+
|
1044 |
+
this.transport.onreadystatechange = this.onStateChange.bind(this);
|
1045 |
+
this.setRequestHeaders();
|
1046 |
+
|
1047 |
+
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
|
1048 |
+
this.transport.send(this.body);
|
1049 |
+
|
1050 |
+
/* Force Firefox to handle ready state 4 for synchronous requests */
|
1051 |
+
if (!this.options.asynchronous && this.transport.overrideMimeType)
|
1052 |
+
this.onStateChange();
|
1053 |
+
|
1054 |
+
}
|
1055 |
+
catch (e) {
|
1056 |
+
this.dispatchException(e);
|
1057 |
+
}
|
1058 |
+
},
|
1059 |
+
|
1060 |
+
onStateChange: function() {
|
1061 |
+
var readyState = this.transport.readyState;
|
1062 |
+
if (readyState > 1 && !((readyState == 4) && this._complete))
|
1063 |
+
this.respondToReadyState(this.transport.readyState);
|
1064 |
+
},
|
1065 |
+
|
1066 |
+
setRequestHeaders: function() {
|
1067 |
+
var headers = {
|
1068 |
+
'X-Requested-With': 'XMLHttpRequest',
|
1069 |
+
'X-Prototype-Version': Prototype.Version,
|
1070 |
+
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
|
1071 |
+
};
|
1072 |
+
|
1073 |
+
if (this.method == 'post') {
|
1074 |
+
headers['Content-type'] = this.options.contentType +
|
1075 |
+
(this.options.encoding ? '; charset=' + this.options.encoding : '');
|
1076 |
+
|
1077 |
+
/* Force "Connection: close" for older Mozilla browsers to work
|
1078 |
+
* around a bug where XMLHttpRequest sends an incorrect
|
1079 |
+
* Content-length header. See Mozilla Bugzilla #246651.
|
1080 |
+
*/
|
1081 |
+
if (this.transport.overrideMimeType &&
|
1082 |
+
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
|
1083 |
+
headers['Connection'] = 'close';
|
1084 |
+
}
|
1085 |
+
|
1086 |
+
// user-defined headers
|
1087 |
+
if (typeof this.options.requestHeaders == 'object') {
|
1088 |
+
var extras = this.options.requestHeaders;
|
1089 |
+
|
1090 |
+
if (typeof extras.push == 'function')
|
1091 |
+
for (var i = 0, length = extras.length; i < length; i += 2)
|
1092 |
+
headers[extras[i]] = extras[i+1];
|
1093 |
+
else
|
1094 |
+
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
|
1095 |
+
}
|
1096 |
+
|
1097 |
+
for (var name in headers)
|
1098 |
+
this.transport.setRequestHeader(name, headers[name]);
|
1099 |
+
},
|
1100 |
+
|
1101 |
+
success: function() {
|
1102 |
+
return !this.transport.status
|
1103 |
+
|| (this.transport.status >= 200 && this.transport.status < 300);
|
1104 |
+
},
|
1105 |
+
|
1106 |
+
respondToReadyState: function(readyState) {
|
1107 |
+
var state = Ajax.Request.Events[readyState];
|
1108 |
+
var transport = this.transport, json = this.evalJSON();
|
1109 |
+
|
1110 |
+
if (state == 'Complete') {
|
1111 |
+
try {
|
1112 |
+
this._complete = true;
|
1113 |
+
(this.options['on' + this.transport.status]
|
1114 |
+
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|
1115 |
+
|| Prototype.emptyFunction)(transport, json);
|
1116 |
+
} catch (e) {
|
1117 |
+
this.dispatchException(e);
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
var contentType = this.getHeader('Content-type');
|
1121 |
+
if (contentType && contentType.strip().
|
1122 |
+
match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
|
1123 |
+
this.evalResponse();
|
1124 |
+
}
|
1125 |
+
|
1126 |
+
try {
|
1127 |
+
(this.options['on' + state] || Prototype.emptyFunction)(transport, json);
|
1128 |
+
Ajax.Responders.dispatch('on' + state, this, transport, json);
|
1129 |
+
} catch (e) {
|
1130 |
+
this.dispatchException(e);
|
1131 |
+
}
|
1132 |
+
|
1133 |
+
if (state == 'Complete') {
|
1134 |
+
// avoid memory leak in MSIE: clean up
|
1135 |
+
this.transport.onreadystatechange = Prototype.emptyFunction;
|
1136 |
+
}
|
1137 |
+
},
|
1138 |
+
|
1139 |
+
getHeader: function(name) {
|
1140 |
+
try {
|
1141 |
+
return this.transport.getResponseHeader(name);
|
1142 |
+
} catch (e) { return null }
|
1143 |
+
},
|
1144 |
+
|
1145 |
+
evalJSON: function() {
|
1146 |
+
try {
|
1147 |
+
var json = this.getHeader('X-JSON');
|
1148 |
+
return json ? json.evalJSON() : null;
|
1149 |
+
} catch (e) { return null }
|
1150 |
+
},
|
1151 |
+
|
1152 |
+
evalResponse: function() {
|
1153 |
+
try {
|
1154 |
+
return eval((this.transport.responseText || '').unfilterJSON());
|
1155 |
+
} catch (e) {
|
1156 |
+
this.dispatchException(e);
|
1157 |
+
}
|
1158 |
+
},
|
1159 |
+
|
1160 |
+
dispatchException: function(exception) {
|
1161 |
+
(this.options.onException || Prototype.emptyFunction)(this, exception);
|
1162 |
+
Ajax.Responders.dispatch('onException', this, exception);
|
1163 |
+
}
|
1164 |
+
});
|
1165 |
+
|
1166 |
+
Ajax.Updater = Class.create();
|
1167 |
+
|
1168 |
+
Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
|
1169 |
+
initialize: function(container, url, options) {
|
1170 |
+
this.container = {
|
1171 |
+
success: (container.success || container),
|
1172 |
+
failure: (container.failure || (container.success ? null : container))
|
1173 |
+
}
|
1174 |
+
|
1175 |
+
this.transport = Ajax.getTransport();
|
1176 |
+
this.setOptions(options);
|
1177 |
+
|
1178 |
+
var onComplete = this.options.onComplete || Prototype.emptyFunction;
|
1179 |
+
this.options.onComplete = (function(transport, param) {
|
1180 |
+
this.updateContent();
|
1181 |
+
onComplete(transport, param);
|
1182 |
+
}).bind(this);
|
1183 |
+
|
1184 |
+
this.request(url);
|
1185 |
+
},
|
1186 |
+
|
1187 |
+
updateContent: function() {
|
1188 |
+
var receiver = this.container[this.success() ? 'success' : 'failure'];
|
1189 |
+
var response = this.transport.responseText;
|
1190 |
+
|
1191 |
+
if (!this.options.evalScripts) response = response.stripScripts();
|
1192 |
+
|
1193 |
+
if (receiver = $(receiver)) {
|
1194 |
+
if (this.options.insertion)
|
1195 |
+
new this.options.insertion(receiver, response);
|
1196 |
+
else
|
1197 |
+
receiver.update(response);
|
1198 |
+
}
|
1199 |
+
|
1200 |
+
if (this.success()) {
|
1201 |
+
if (this.onComplete)
|
1202 |
+
setTimeout(this.onComplete.bind(this), 10);
|
1203 |
+
}
|
1204 |
+
}
|
1205 |
+
});
|
1206 |
+
|
1207 |
+
Ajax.PeriodicalUpdater = Class.create();
|
1208 |
+
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
|
1209 |
+
initialize: function(container, url, options) {
|
1210 |
+
this.setOptions(options);
|
1211 |
+
this.onComplete = this.options.onComplete;
|
1212 |
+
|
1213 |
+
this.frequency = (this.options.frequency || 2);
|
1214 |
+
this.decay = (this.options.decay || 1);
|
1215 |
+
|
1216 |
+
this.updater = {};
|
1217 |
+
this.container = container;
|
1218 |
+
this.url = url;
|
1219 |
+
|
1220 |
+
this.start();
|
1221 |
+
},
|
1222 |
+
|
1223 |
+
start: function() {
|
1224 |
+
this.options.onComplete = this.updateComplete.bind(this);
|
1225 |
+
this.onTimerEvent();
|
1226 |
+
},
|
1227 |
+
|
1228 |
+
stop: function() {
|
1229 |
+
this.updater.options.onComplete = undefined;
|
1230 |
+
clearTimeout(this.timer);
|
1231 |
+
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
|
1232 |
+
},
|
1233 |
+
|
1234 |
+
updateComplete: function(request) {
|
1235 |
+
if (this.options.decay) {
|
1236 |
+
this.decay = (request.responseText == this.lastText ?
|
1237 |
+
this.decay * this.options.decay : 1);
|
1238 |
+
|
1239 |
+
this.lastText = request.responseText;
|
1240 |
+
}
|
1241 |
+
this.timer = setTimeout(this.onTimerEvent.bind(this),
|
1242 |
+
this.decay * this.frequency * 1000);
|
1243 |
+
},
|
1244 |
+
|
1245 |
+
onTimerEvent: function() {
|
1246 |
+
this.updater = new Ajax.Updater(this.container, this.url, this.options);
|
1247 |
+
}
|
1248 |
+
});
|
1249 |
+
function $(element) {
|
1250 |
+
if (arguments.length > 1) {
|
1251 |
+
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
|
1252 |
+
elements.push($(arguments[i]));
|
1253 |
+
return elements;
|
1254 |
+
}
|
1255 |
+
if (typeof element == 'string')
|
1256 |
+
element = document.getElementById(element);
|
1257 |
+
return Element.extend(element);
|
1258 |
+
}
|
1259 |
+
|
1260 |
+
if (Prototype.BrowserFeatures.XPath) {
|
1261 |
+
document._getElementsByXPath = function(expression, parentElement) {
|
1262 |
+
var results = [];
|
1263 |
+
var query = document.evaluate(expression, $(parentElement) || document,
|
1264 |
+
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
1265 |
+
for (var i = 0, length = query.snapshotLength; i < length; i++)
|
1266 |
+
results.push(query.snapshotItem(i));
|
1267 |
+
return results;
|
1268 |
+
};
|
1269 |
+
|
1270 |
+
document.getElementsByClassName = function(className, parentElement) {
|
1271 |
+
var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
|
1272 |
+
return document._getElementsByXPath(q, parentElement);
|
1273 |
+
}
|
1274 |
+
|
1275 |
+
} else document.getElementsByClassName = function(className, parentElement) {
|
1276 |
+
var children = ($(parentElement) || document.body).getElementsByTagName('*');
|
1277 |
+
var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
|
1278 |
+
for (var i = 0, length = children.length; i < length; i++) {
|
1279 |
+
child = children[i];
|
1280 |
+
var elementClassName = child.className;
|
1281 |
+
if (elementClassName.length == 0) continue;
|
1282 |
+
if (elementClassName == className || elementClassName.match(pattern))
|
1283 |
+
elements.push(Element.extend(child));
|
1284 |
+
}
|
1285 |
+
return elements;
|
1286 |
+
};
|
1287 |
+
|
1288 |
+
/*--------------------------------------------------------------------------*/
|
1289 |
+
|
1290 |
+
if (!window.Element) var Element = {};
|
1291 |
+
|
1292 |
+
Element.extend = function(element) {
|
1293 |
+
var F = Prototype.BrowserFeatures;
|
1294 |
+
if (!element || !element.tagName || element.nodeType == 3 ||
|
1295 |
+
element._extended || F.SpecificElementExtensions || element == window)
|
1296 |
+
return element;
|
1297 |
+
|
1298 |
+
var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
|
1299 |
+
T = Element.Methods.ByTag;
|
1300 |
+
|
1301 |
+
// extend methods for all tags (Safari doesn't need this)
|
1302 |
+
if (!F.ElementExtensions) {
|
1303 |
+
Object.extend(methods, Element.Methods),
|
1304 |
+
Object.extend(methods, Element.Methods.Simulated);
|
1305 |
+
}
|
1306 |
+
|
1307 |
+
// extend methods for specific tags
|
1308 |
+
if (T[tagName]) Object.extend(methods, T[tagName]);
|
1309 |
+
|
1310 |
+
for (var property in methods) {
|
1311 |
+
var value = methods[property];
|
1312 |
+
if (typeof value == 'function' && !(property in element))
|
1313 |
+
element[property] = cache.findOrStore(value);
|
1314 |
+
}
|
1315 |
+
|
1316 |
+
element._extended = Prototype.emptyFunction;
|
1317 |
+
return element;
|
1318 |
+
};
|
1319 |
+
|
1320 |
+
Element.extend.cache = {
|
1321 |
+
findOrStore: function(value) {
|
1322 |
+
return this[value] = this[value] || function() {
|
1323 |
+
return value.apply(null, [this].concat($A(arguments)));
|
1324 |
+
}
|
1325 |
+
}
|
1326 |
+
};
|
1327 |
+
|
1328 |
+
Element.Methods = {
|
1329 |
+
visible: function(element) {
|
1330 |
+
return $(element).style.display != 'none';
|
1331 |
+
},
|
1332 |
+
|
1333 |
+
toggle: function(element) {
|
1334 |
+
element = $(element);
|
1335 |
+
Element[Element.visible(element) ? 'hide' : 'show'](element);
|
1336 |
+
return element;
|
1337 |
+
},
|
1338 |
+
|
1339 |
+
hide: function(element) {
|
1340 |
+
$(element).style.display = 'none';
|
1341 |
+
return element;
|
1342 |
+
},
|
1343 |
+
|
1344 |
+
show: function(element) {
|
1345 |
+
$(element).style.display = '';
|
1346 |
+
return element;
|
1347 |
+
},
|
1348 |
+
|
1349 |
+
remove: function(element) {
|
1350 |
+
element = $(element);
|
1351 |
+
element.parentNode.removeChild(element);
|
1352 |
+
return element;
|
1353 |
+
},
|
1354 |
+
|
1355 |
+
update: function(element, html) {
|
1356 |
+
html = typeof html == 'undefined' ? '' : html.toString();
|
1357 |
+
$(element).innerHTML = html.stripScripts();
|
1358 |
+
setTimeout(function() {html.evalScripts()}, 10);
|
1359 |
+
return element;
|
1360 |
+
},
|
1361 |
+
|
1362 |
+
replace: function(element, html) {
|
1363 |
+
element = $(element);
|
1364 |
+
html = typeof html == 'undefined' ? '' : html.toString();
|
1365 |
+
if (element.outerHTML) {
|
1366 |
+
element.outerHTML = html.stripScripts();
|
1367 |
+
} else {
|
1368 |
+
var range = element.ownerDocument.createRange();
|
1369 |
+
range.selectNodeContents(element);
|
1370 |
+
element.parentNode.replaceChild(
|
1371 |
+
range.createContextualFragment(html.stripScripts()), element);
|
1372 |
+
}
|
1373 |
+
setTimeout(function() {html.evalScripts()}, 10);
|
1374 |
+
return element;
|
1375 |
+
},
|
1376 |
+
|
1377 |
+
inspect: function(element) {
|
1378 |
+
element = $(element);
|
1379 |
+
var result = '<' + element.tagName.toLowerCase();
|
1380 |
+
$H({'id': 'id', 'className': 'class'}).each(function(pair) {
|
1381 |
+
var property = pair.first(), attribute = pair.last();
|
1382 |
+
var value = (element[property] || '').toString();
|
1383 |
+
if (value) result += ' ' + attribute + '=' + value.inspect(true);
|
1384 |
+
});
|
1385 |
+
return result + '>';
|
1386 |
+
},
|
1387 |
+
|
1388 |
+
recursivelyCollect: function(element, property) {
|
1389 |
+
element = $(element);
|
1390 |
+
var elements = [];
|
1391 |
+
while (element = element[property])
|
1392 |
+
if (element.nodeType == 1)
|
1393 |
+
elements.push(Element.extend(element));
|
1394 |
+
return elements;
|
1395 |
+
},
|
1396 |
+
|
1397 |
+
ancestors: function(element) {
|
1398 |
+
return $(element).recursivelyCollect('parentNode');
|
1399 |
+
},
|
1400 |
+
|
1401 |
+
descendants: function(element) {
|
1402 |
+
return $A($(element).getElementsByTagName('*')).each(Element.extend);
|
1403 |
+
},
|
1404 |
+
|
1405 |
+
firstDescendant: function(element) {
|
1406 |
+
element = $(element).firstChild;
|
1407 |
+
while (element && element.nodeType != 1) element = element.nextSibling;
|
1408 |
+
return $(element);
|
1409 |
+
},
|
1410 |
+
|
1411 |
+
immediateDescendants: function(element) {
|
1412 |
+
if (!(element = $(element).firstChild)) return [];
|
1413 |
+
while (element && element.nodeType != 1) element = element.nextSibling;
|
1414 |
+
if (element) return [element].concat($(element).nextSiblings());
|
1415 |
+
return [];
|
1416 |
+
},
|
1417 |
+
|
1418 |
+
previousSiblings: function(element) {
|
1419 |
+
return $(element).recursivelyCollect('previousSibling');
|
1420 |
+
},
|
1421 |
+
|
1422 |
+
nextSiblings: function(element) {
|
1423 |
+
return $(element).recursivelyCollect('nextSibling');
|
1424 |
+
},
|
1425 |
+
|
1426 |
+
siblings: function(element) {
|
1427 |
+
element = $(element);
|
1428 |
+
return element.previousSiblings().reverse().concat(element.nextSiblings());
|
1429 |
+
},
|
1430 |
+
|
1431 |
+
match: function(element, selector) {
|
1432 |
+
if (typeof selector == 'string')
|
1433 |
+
selector = new Selector(selector);
|
1434 |
+
return selector.match($(element));
|
1435 |
+
},
|
1436 |
+
|
1437 |
+
up: function(element, expression, index) {
|
1438 |
+
element = $(element);
|
1439 |
+
if (arguments.length == 1) return $(element.parentNode);
|
1440 |
+
var ancestors = element.ancestors();
|
1441 |
+
return expression ? Selector.findElement(ancestors, expression, index) :
|
1442 |
+
ancestors[index || 0];
|
1443 |
+
},
|
1444 |
+
|
1445 |
+
down: function(element, expression, index) {
|
1446 |
+
element = $(element);
|
1447 |
+
if (arguments.length == 1) return element.firstDescendant();
|
1448 |
+
var descendants = element.descendants();
|
1449 |
+
return expression ? Selector.findElement(descendants, expression, index) :
|
1450 |
+
descendants[index || 0];
|
1451 |
+
},
|
1452 |
+
|
1453 |
+
previous: function(element, expression, index) {
|
1454 |
+
element = $(element);
|
1455 |
+
if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
|
1456 |
+
var previousSiblings = element.previousSiblings();
|
1457 |
+
return expression ? Selector.findElement(previousSiblings, expression, index) :
|
1458 |
+
previousSiblings[index || 0];
|
1459 |
+
},
|
1460 |
+
|
1461 |
+
next: function(element, expression, index) {
|
1462 |
+
element = $(element);
|
1463 |
+
if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
|
1464 |
+
var nextSiblings = element.nextSiblings();
|
1465 |
+
return expression ? Selector.findElement(nextSiblings, expression, index) :
|
1466 |
+
nextSiblings[index || 0];
|
1467 |
+
},
|
1468 |
+
|
1469 |
+
getElementsBySelector: function() {
|
1470 |
+
var args = $A(arguments), element = $(args.shift());
|
1471 |
+
return Selector.findChildElements(element, args);
|
1472 |
+
},
|
1473 |
+
|
1474 |
+
getElementsByClassName: function(element, className) {
|
1475 |
+
return document.getElementsByClassName(className, element);
|
1476 |
+
},
|
1477 |
+
|
1478 |
+
readAttribute: function(element, name) {
|
1479 |
+
element = $(element);
|
1480 |
+
if (Prototype.Browser.IE) {
|
1481 |
+
if (!element.attributes) return null;
|
1482 |
+
var t = Element._attributeTranslations;
|
1483 |
+
if (t.values[name]) return t.values[name](element, name);
|
1484 |
+
if (t.names[name]) name = t.names[name];
|
1485 |
+
var attribute = element.attributes[name];
|
1486 |
+
return attribute ? attribute.nodeValue : null;
|
1487 |
+
}
|
1488 |
+
return element.getAttribute(name);
|
1489 |
+
},
|
1490 |
+
|
1491 |
+
getHeight: function(element) {
|
1492 |
+
return $(element).getDimensions().height;
|
1493 |
+
},
|
1494 |
+
|
1495 |
+
getWidth: function(element) {
|
1496 |
+
return $(element).getDimensions().width;
|
1497 |
+
},
|
1498 |
+
|
1499 |
+
classNames: function(element) {
|
1500 |
+
return new Element.ClassNames(element);
|
1501 |
+
},
|
1502 |
+
|
1503 |
+
hasClassName: function(element, className) {
|
1504 |
+
if (!(element = $(element))) return;
|
1505 |
+
var elementClassName = element.className;
|
1506 |
+
if (elementClassName.length == 0) return false;
|
1507 |
+
if (elementClassName == className ||
|
1508 |
+
elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
|
1509 |
+
return true;
|
1510 |
+
return false;
|
1511 |
+
},
|
1512 |
+
|
1513 |
+
addClassName: function(element, className) {
|
1514 |
+
if (!(element = $(element))) return;
|
1515 |
+
Element.classNames(element).add(className);
|
1516 |
+
return element;
|
1517 |
+
},
|
1518 |
+
|
1519 |
+
removeClassName: function(element, className) {
|
1520 |
+
if (!(element = $(element))) return;
|
1521 |
+
Element.classNames(element).remove(className);
|
1522 |
+
return element;
|
1523 |
+
},
|
1524 |
+
|
1525 |
+
toggleClassName: function(element, className) {
|
1526 |
+
if (!(element = $(element))) return;
|
1527 |
+
Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
|
1528 |
+
return element;
|
1529 |
+
},
|
1530 |
+
|
1531 |
+
observe: function() {
|
1532 |
+
Event.observe.apply(Event, arguments);
|
1533 |
+
return $A(arguments).first();
|
1534 |
+
},
|
1535 |
+
|
1536 |
+
stopObserving: function() {
|
1537 |
+
Event.stopObserving.apply(Event, arguments);
|
1538 |
+
return $A(arguments).first();
|
1539 |
+
},
|
1540 |
+
|
1541 |
+
// removes whitespace-only text node children
|
1542 |
+
cleanWhitespace: function(element) {
|
1543 |
+
element = $(element);
|
1544 |
+
var node = element.firstChild;
|
1545 |
+
while (node) {
|
1546 |
+
var nextNode = node.nextSibling;
|
1547 |
+
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
|
1548 |
+
element.removeChild(node);
|
1549 |
+
node = nextNode;
|
1550 |
+
}
|
1551 |
+
return element;
|
1552 |
+
},
|
1553 |
+
|
1554 |
+
empty: function(element) {
|
1555 |
+
return $(element).innerHTML.blank();
|
1556 |
+
},
|
1557 |
+
|
1558 |
+
descendantOf: function(element, ancestor) {
|
1559 |
+
element = $(element), ancestor = $(ancestor);
|
1560 |
+
while (element = element.parentNode)
|
1561 |
+
if (element == ancestor) return true;
|
1562 |
+
return false;
|
1563 |
+
},
|
1564 |
+
|
1565 |
+
scrollTo: function(element) {
|
1566 |
+
element = $(element);
|
1567 |
+
var pos = Position.cumulativeOffset(element);
|
1568 |
+
window.scrollTo(pos[0], pos[1]);
|
1569 |
+
return element;
|
1570 |
+
},
|
1571 |
+
|
1572 |
+
getStyle: function(element, style) {
|
1573 |
+
element = $(element);
|
1574 |
+
style = style == 'float' ? 'cssFloat' : style.camelize();
|
1575 |
+
var value = element.style[style];
|
1576 |
+
if (!value) {
|
1577 |
+
var css = document.defaultView.getComputedStyle(element, null);
|
1578 |
+
value = css ? css[style] : null;
|
1579 |
+
}
|
1580 |
+
if (style == 'opacity') return value ? parseFloat(value) : 1.0;
|
1581 |
+
return value == 'auto' ? null : value;
|
1582 |
+
},
|
1583 |
+
|
1584 |
+
getOpacity: function(element) {
|
1585 |
+
return $(element).getStyle('opacity');
|
1586 |
+
},
|
1587 |
+
|
1588 |
+
setStyle: function(element, styles, camelized) {
|
1589 |
+
element = $(element);
|
1590 |
+
var elementStyle = element.style;
|
1591 |
+
|
1592 |
+
for (var property in styles)
|
1593 |
+
if (property == 'opacity') element.setOpacity(styles[property])
|
1594 |
+
else
|
1595 |
+
elementStyle[(property == 'float' || property == 'cssFloat') ?
|
1596 |
+
(elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
|
1597 |
+
(camelized ? property : property.camelize())] = styles[property];
|
1598 |
+
|
1599 |
+
return element;
|
1600 |
+
},
|
1601 |
+
|
1602 |
+
setOpacity: function(element, value) {
|
1603 |
+
element = $(element);
|
1604 |
+
element.style.opacity = (value == 1 || value === '') ? '' :
|
1605 |
+
(value < 0.00001) ? 0 : value;
|
1606 |
+
return element;
|
1607 |
+
},
|
1608 |
+
|
1609 |
+
getDimensions: function(element) {
|
1610 |
+
element = $(element);
|
1611 |
+
var display = $(element).getStyle('display');
|
1612 |
+
if (display != 'none' && display != null) // Safari bug
|
1613 |
+
return {width: element.offsetWidth, height: element.offsetHeight};
|
1614 |
+
|
1615 |
+
// All *Width and *Height properties give 0 on elements with display none,
|
1616 |
+
// so enable the element temporarily
|
1617 |
+
var els = element.style;
|
1618 |
+
var originalVisibility = els.visibility;
|
1619 |
+
var originalPosition = els.position;
|
1620 |
+
var originalDisplay = els.display;
|
1621 |
+
els.visibility = 'hidden';
|
1622 |
+
els.position = 'absolute';
|
1623 |
+
els.display = 'block';
|
1624 |
+
var originalWidth = element.clientWidth;
|
1625 |
+
var originalHeight = element.clientHeight;
|
1626 |
+
els.display = originalDisplay;
|
1627 |
+
els.position = originalPosition;
|
1628 |
+
els.visibility = originalVisibility;
|
1629 |
+
return {width: originalWidth, height: originalHeight};
|
1630 |
+
},
|
1631 |
+
|
1632 |
+
makePositioned: function(element) {
|
1633 |
+
element = $(element);
|
1634 |
+
var pos = Element.getStyle(element, 'position');
|
1635 |
+
if (pos == 'static' || !pos) {
|
1636 |
+
element._madePositioned = true;
|
1637 |
+
element.style.position = 'relative';
|
1638 |
+
// Opera returns the offset relative to the positioning context, when an
|
1639 |
+
// element is position relative but top and left have not been defined
|
1640 |
+
if (window.opera) {
|
1641 |
+
element.style.top = 0;
|
1642 |
+
element.style.left = 0;
|
1643 |
+
}
|
1644 |
+
}
|
1645 |
+
return element;
|
1646 |
+
},
|
1647 |
+
|
1648 |
+
undoPositioned: function(element) {
|
1649 |
+
element = $(element);
|
1650 |
+
if (element._madePositioned) {
|
1651 |
+
element._madePositioned = undefined;
|
1652 |
+
element.style.position =
|
1653 |
+
element.style.top =
|
1654 |
+
element.style.left =
|
1655 |
+
element.style.bottom =
|
1656 |
+
element.style.right = '';
|
1657 |
+
}
|
1658 |
+
return element;
|
1659 |
+
},
|
1660 |
+
|
1661 |
+
makeClipping: function(element) {
|
1662 |
+
element = $(element);
|
1663 |
+
if (element._overflow) return element;
|
1664 |
+
element._overflow = element.style.overflow || 'auto';
|
1665 |
+
if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
|
1666 |
+
element.style.overflow = 'hidden';
|
1667 |
+
return element;
|
1668 |
+
},
|
1669 |
+
|
1670 |
+
undoClipping: function(element) {
|
1671 |
+
element = $(element);
|
1672 |
+
if (!element._overflow) return element;
|
1673 |
+
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
|
1674 |
+
element._overflow = null;
|
1675 |
+
return element;
|
1676 |
+
}
|
1677 |
+
};
|
1678 |
+
|
1679 |
+
Object.extend(Element.Methods, {
|
1680 |
+
childOf: Element.Methods.descendantOf,
|
1681 |
+
childElements: Element.Methods.immediateDescendants
|
1682 |
+
});
|
1683 |
+
|
1684 |
+
if (Prototype.Browser.Opera) {
|
1685 |
+
Element.Methods._getStyle = Element.Methods.getStyle;
|
1686 |
+
Element.Methods.getStyle = function(element, style) {
|
1687 |
+
switch(style) {
|
1688 |
+
case 'left':
|
1689 |
+
case 'top':
|
1690 |
+
case 'right':
|
1691 |
+
case 'bottom':
|
1692 |
+
if (Element._getStyle(element, 'position') == 'static') return null;
|
1693 |
+
default: return Element._getStyle(element, style);
|
1694 |
+
}
|
1695 |
+
};
|
1696 |
+
}
|
1697 |
+
else if (Prototype.Browser.IE) {
|
1698 |
+
Element.Methods.getStyle = function(element, style) {
|
1699 |
+
element = $(element);
|
1700 |
+
style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
|
1701 |
+
var value = element.style[style];
|
1702 |
+
if (!value && element.currentStyle) value = element.currentStyle[style];
|
1703 |
+
|
1704 |
+
if (style == 'opacity') {
|
1705 |
+
if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
|
1706 |
+
if (value[1]) return parseFloat(value[1]) / 100;
|
1707 |
+
return 1.0;
|
1708 |
+
}
|
1709 |
+
|
1710 |
+
if (value == 'auto') {
|
1711 |
+
if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
|
1712 |
+
return element['offset'+style.capitalize()] + 'px';
|
1713 |
+
return null;
|
1714 |
+
}
|
1715 |
+
return value;
|
1716 |
+
};
|
1717 |
+
|
1718 |
+
Element.Methods.setOpacity = function(element, value) {
|
1719 |
+
element = $(element);
|
1720 |
+
var filter = element.getStyle('filter'), style = element.style;
|
1721 |
+
if (value == 1 || value === '') {
|
1722 |
+
style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
|
1723 |
+
return element;
|
1724 |
+
} else if (value < 0.00001) value = 0;
|
1725 |
+
style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
|
1726 |
+
'alpha(opacity=' + (value * 100) + ')';
|
1727 |
+
return element;
|
1728 |
+
};
|
1729 |
+
|
1730 |
+
// IE is missing .innerHTML support for TABLE-related elements
|
1731 |
+
Element.Methods.update = function(element, html) {
|
1732 |
+
element = $(element);
|
1733 |
+
html = typeof html == 'undefined' ? '' : html.toString();
|
1734 |
+
var tagName = element.tagName.toUpperCase();
|
1735 |
+
if (['THEAD','TBODY','TR','TD'].include(tagName)) {
|
1736 |
+
var div = document.createElement('div');
|
1737 |
+
switch (tagName) {
|
1738 |
+
case 'THEAD':
|
1739 |
+
case 'TBODY':
|
1740 |
+
div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
|
1741 |
+
depth = 2;
|
1742 |
+
break;
|
1743 |
+
case 'TR':
|
1744 |
+
div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
|
1745 |
+
depth = 3;
|
1746 |
+
break;
|
1747 |
+
case 'TD':
|
1748 |
+
div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
|
1749 |
+
depth = 4;
|
1750 |
+
}
|
1751 |
+
$A(element.childNodes).each(function(node) { element.removeChild(node) });
|
1752 |
+
depth.times(function() { div = div.firstChild });
|
1753 |
+
$A(div.childNodes).each(function(node) { element.appendChild(node) });
|
1754 |
+
} else {
|
1755 |
+
element.innerHTML = html.stripScripts();
|
1756 |
+
}
|
1757 |
+
setTimeout(function() { html.evalScripts() }, 10);
|
1758 |
+
return element;
|
1759 |
+
}
|
1760 |
+
}
|
1761 |
+
else if (Prototype.Browser.Gecko) {
|
1762 |
+
Element.Methods.setOpacity = function(element, value) {
|
1763 |
+
element = $(element);
|
1764 |
+
element.style.opacity = (value == 1) ? 0.999999 :
|
1765 |
+
(value === '') ? '' : (value < 0.00001) ? 0 : value;
|
1766 |
+
return element;
|
1767 |
+
};
|
1768 |
+
}
|
1769 |
+
|
1770 |
+
Element._attributeTranslations = {
|
1771 |
+
names: {
|
1772 |
+
colspan: "colSpan",
|
1773 |
+
rowspan: "rowSpan",
|
1774 |
+
valign: "vAlign",
|
1775 |
+
datetime: "dateTime",
|
1776 |
+
accesskey: "accessKey",
|
1777 |
+
tabindex: "tabIndex",
|
1778 |
+
enctype: "encType",
|
1779 |
+
maxlength: "maxLength",
|
1780 |
+
readonly: "readOnly",
|
1781 |
+
longdesc: "longDesc"
|
1782 |
+
},
|
1783 |
+
values: {
|
1784 |
+
_getAttr: function(element, attribute) {
|
1785 |
+
return element.getAttribute(attribute, 2);
|
1786 |
+
},
|
1787 |
+
_flag: function(element, attribute) {
|
1788 |
+
return $(element).hasAttribute(attribute) ? attribute : null;
|
1789 |
+
},
|
1790 |
+
style: function(element) {
|
1791 |
+
return element.style.cssText.toLowerCase();
|
1792 |
+
},
|
1793 |
+
title: function(element) {
|
1794 |
+
var node = element.getAttributeNode('title');
|
1795 |
+
return node.specified ? node.nodeValue : null;
|
1796 |
+
}
|
1797 |
+
}
|
1798 |
+
};
|
1799 |
+
|
1800 |
+
(function() {
|
1801 |
+
Object.extend(this, {
|
1802 |
+
href: this._getAttr,
|
1803 |
+
src: this._getAttr,
|
1804 |
+
type: this._getAttr,
|
1805 |
+
disabled: this._flag,
|
1806 |
+
checked: this._flag,
|
1807 |
+
readonly: this._flag,
|
1808 |
+
multiple: this._flag
|
1809 |
+
});
|
1810 |
+
}).call(Element._attributeTranslations.values);
|
1811 |
+
|
1812 |
+
Element.Methods.Simulated = {
|
1813 |
+
hasAttribute: function(element, attribute) {
|
1814 |
+
var t = Element._attributeTranslations, node;
|
1815 |
+
attribute = t.names[attribute] || attribute;
|
1816 |
+
node = $(element).getAttributeNode(attribute);
|
1817 |
+
return node && node.specified;
|
1818 |
+
}
|
1819 |
+
};
|
1820 |
+
|
1821 |
+
Element.Methods.ByTag = {};
|
1822 |
+
|
1823 |
+
Object.extend(Element, Element.Methods);
|
1824 |
+
|
1825 |
+
if (!Prototype.BrowserFeatures.ElementExtensions &&
|
1826 |
+
document.createElement('div').__proto__) {
|
1827 |
+
window.HTMLElement = {};
|
1828 |
+
window.HTMLElement.prototype = document.createElement('div').__proto__;
|
1829 |
+
Prototype.BrowserFeatures.ElementExtensions = true;
|
1830 |
+
}
|
1831 |
+
|
1832 |
+
Element.hasAttribute = function(element, attribute) {
|
1833 |
+
if (element.hasAttribute) return element.hasAttribute(attribute);
|
1834 |
+
return Element.Methods.Simulated.hasAttribute(element, attribute);
|
1835 |
+
};
|
1836 |
+
|
1837 |
+
Element.addMethods = function(methods) {
|
1838 |
+
var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
|
1839 |
+
|
1840 |
+
if (!methods) {
|
1841 |
+
Object.extend(Form, Form.Methods);
|
1842 |
+
Object.extend(Form.Element, Form.Element.Methods);
|
1843 |
+
Object.extend(Element.Methods.ByTag, {
|
1844 |
+
"FORM": Object.clone(Form.Methods),
|
1845 |
+
"INPUT": Object.clone(Form.Element.Methods),
|
1846 |
+
"SELECT": Object.clone(Form.Element.Methods),
|
1847 |
+
"TEXTAREA": Object.clone(Form.Element.Methods)
|
1848 |
+
});
|
1849 |
+
}
|
1850 |
+
|
1851 |
+
if (arguments.length == 2) {
|
1852 |
+
var tagName = methods;
|
1853 |
+
methods = arguments[1];
|
1854 |
+
}
|
1855 |
+
|
1856 |
+
if (!tagName) Object.extend(Element.Methods, methods || {});
|
1857 |
+
else {
|
1858 |
+
if (tagName.constructor == Array) tagName.each(extend);
|
1859 |
+
else extend(tagName);
|
1860 |
+
}
|
1861 |
+
|
1862 |
+
function extend(tagName) {
|
1863 |
+
tagName = tagName.toUpperCase();
|
1864 |
+
if (!Element.Methods.ByTag[tagName])
|
1865 |
+
Element.Methods.ByTag[tagName] = {};
|
1866 |
+
Object.extend(Element.Methods.ByTag[tagName], methods);
|
1867 |
+
}
|
1868 |
+
|
1869 |
+
function copy(methods, destination, onlyIfAbsent) {
|
1870 |
+
onlyIfAbsent = onlyIfAbsent || false;
|
1871 |
+
var cache = Element.extend.cache;
|
1872 |
+
for (var property in methods) {
|
1873 |
+
var value = methods[property];
|
1874 |
+
if (!onlyIfAbsent || !(property in destination))
|
1875 |
+
destination[property] = cache.findOrStore(value);
|
1876 |
+
}
|
1877 |
+
}
|
1878 |
+
|
1879 |
+
function findDOMClass(tagName) {
|
1880 |
+
var klass;
|
1881 |
+
var trans = {
|
1882 |
+
"OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
|
1883 |
+
"FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
|
1884 |
+
"DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
|
1885 |
+
"H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
|
1886 |
+
"INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
|
1887 |
+
"TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
|
1888 |
+
"TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
|
1889 |
+
"TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
|
1890 |
+
"FrameSet", "IFRAME": "IFrame"
|
1891 |
+
};
|
1892 |
+
if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
|
1893 |
+
if (window[klass]) return window[klass];
|
1894 |
+
klass = 'HTML' + tagName + 'Element';
|
1895 |
+
if (window[klass]) return window[klass];
|
1896 |
+
klass = 'HTML' + tagName.capitalize() + 'Element';
|
1897 |
+
if (window[klass]) return window[klass];
|
1898 |
+
|
1899 |
+
window[klass] = {};
|
1900 |
+
window[klass].prototype = document.createElement(tagName).__proto__;
|
1901 |
+
return window[klass];
|
1902 |
+
}
|
1903 |
+
|
1904 |
+
if (F.ElementExtensions) {
|
1905 |
+
copy(Element.Methods, HTMLElement.prototype);
|
1906 |
+
copy(Element.Methods.Simulated, HTMLElement.prototype, true);
|
1907 |
+
}
|
1908 |
+
|
1909 |
+
if (F.SpecificElementExtensions) {
|
1910 |
+
for (var tag in Element.Methods.ByTag) {
|
1911 |
+
var klass = findDOMClass(tag);
|
1912 |
+
if (typeof klass == "undefined") continue;
|
1913 |
+
copy(T[tag], klass.prototype);
|
1914 |
+
}
|
1915 |
+
}
|
1916 |
+
|
1917 |
+
Object.extend(Element, Element.Methods);
|
1918 |
+
delete Element.ByTag;
|
1919 |
+
};
|
1920 |
+
|
1921 |
+
var Toggle = { display: Element.toggle };
|
1922 |
+
|
1923 |
+
/*--------------------------------------------------------------------------*/
|
1924 |
+
|
1925 |
+
Abstract.Insertion = function(adjacency) {
|
1926 |
+
this.adjacency = adjacency;
|
1927 |
+
}
|
1928 |
+
|
1929 |
+
Abstract.Insertion.prototype = {
|
1930 |
+
initialize: function(element, content) {
|
1931 |
+
this.element = $(element);
|
1932 |
+
this.content = content.stripScripts();
|
1933 |
+
|
1934 |
+
if (this.adjacency && this.element.insertAdjacentHTML) {
|
1935 |
+
try {
|
1936 |
+
this.element.insertAdjacentHTML(this.adjacency, this.content);
|
1937 |
+
} catch (e) {
|
1938 |
+
var tagName = this.element.tagName.toUpperCase();
|
1939 |
+
if (['TBODY', 'TR'].include(tagName)) {
|
1940 |
+
this.insertContent(this.contentFromAnonymousTable());
|
1941 |
+
} else {
|
1942 |
+
throw e;
|
1943 |
+
}
|
1944 |
+
}
|
1945 |
+
} else {
|
1946 |
+
this.range = this.element.ownerDocument.createRange();
|
1947 |
+
if (this.initializeRange) this.initializeRange();
|
1948 |
+
this.insertContent([this.range.createContextualFragment(this.content)]);
|
1949 |
+
}
|
1950 |
+
|
1951 |
+
setTimeout(function() {content.evalScripts()}, 10);
|
1952 |
+
},
|
1953 |
+
|
1954 |
+
contentFromAnonymousTable: function() {
|
1955 |
+
var div = document.createElement('div');
|
1956 |
+
div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
|
1957 |
+
return $A(div.childNodes[0].childNodes[0].childNodes);
|
1958 |
+
}
|
1959 |
+
}
|
1960 |
+
|
1961 |
+
var Insertion = new Object();
|
1962 |
+
|
1963 |
+
Insertion.Before = Class.create();
|
1964 |
+
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
|
1965 |
+
initializeRange: function() {
|
1966 |
+
this.range.setStartBefore(this.element);
|
1967 |
+
},
|
1968 |
+
|
1969 |
+
insertContent: function(fragments) {
|
1970 |
+
fragments.each((function(fragment) {
|
1971 |
+
this.element.parentNode.insertBefore(fragment, this.element);
|
1972 |
+
}).bind(this));
|
1973 |
+
}
|
1974 |
+
});
|
1975 |
+
|
1976 |
+
Insertion.Top = Class.create();
|
1977 |
+
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
|
1978 |
+
initializeRange: function() {
|
1979 |
+
this.range.selectNodeContents(this.element);
|
1980 |
+
this.range.collapse(true);
|
1981 |
+
},
|
1982 |
+
|
1983 |
+
insertContent: function(fragments) {
|
1984 |
+
fragments.reverse(false).each((function(fragment) {
|
1985 |
+
this.element.insertBefore(fragment, this.element.firstChild);
|
1986 |
+
}).bind(this));
|
1987 |
+
}
|
1988 |
+
});
|
1989 |
+
|
1990 |
+
Insertion.Bottom = Class.create();
|
1991 |
+
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
|
1992 |
+
initializeRange: function() {
|
1993 |
+
this.range.selectNodeContents(this.element);
|
1994 |
+
this.range.collapse(this.element);
|
1995 |
+
},
|
1996 |
+
|
1997 |
+
insertContent: function(fragments) {
|
1998 |
+
fragments.each((function(fragment) {
|
1999 |
+
this.element.appendChild(fragment);
|
2000 |
+
}).bind(this));
|
2001 |
+
}
|
2002 |
+
});
|
2003 |
+
|
2004 |
+
Insertion.After = Class.create();
|
2005 |
+
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
|
2006 |
+
initializeRange: function() {
|
2007 |
+
this.range.setStartAfter(this.element);
|
2008 |
+
},
|
2009 |
+
|
2010 |
+
insertContent: function(fragments) {
|
2011 |
+
fragments.each((function(fragment) {
|
2012 |
+
this.element.parentNode.insertBefore(fragment,
|
2013 |
+
this.element.nextSibling);
|
2014 |
+
}).bind(this));
|
2015 |
+
}
|
2016 |
+
});
|
2017 |
+
|
2018 |
+
/*--------------------------------------------------------------------------*/
|
2019 |
+
|
2020 |
+
Element.ClassNames = Class.create();
|
2021 |
+
Element.ClassNames.prototype = {
|
2022 |
+
initialize: function(element) {
|
2023 |
+
this.element = $(element);
|
2024 |
+
},
|
2025 |
+
|
2026 |
+
_each: function(iterator) {
|
2027 |
+
this.element.className.split(/\s+/).select(function(name) {
|
2028 |
+
return name.length > 0;
|
2029 |
+
})._each(iterator);
|
2030 |
+
},
|
2031 |
+
|
2032 |
+
set: function(className) {
|
2033 |
+
this.element.className = className;
|
2034 |
+
},
|
2035 |
+
|
2036 |
+
add: function(classNameToAdd) {
|
2037 |
+
if (this.include(classNameToAdd)) return;
|
2038 |
+
this.set($A(this).concat(classNameToAdd).join(' '));
|
2039 |
+
},
|
2040 |
+
|
2041 |
+
remove: function(classNameToRemove) {
|
2042 |
+
if (!this.include(classNameToRemove)) return;
|
2043 |
+
this.set($A(this).without(classNameToRemove).join(' '));
|
2044 |
+
},
|
2045 |
+
|
2046 |
+
toString: function() {
|
2047 |
+
return $A(this).join(' ');
|
2048 |
+
}
|
2049 |
+
};
|
2050 |
+
|
2051 |
+
Object.extend(Element.ClassNames.prototype, Enumerable);
|
2052 |
+
/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
|
2053 |
+
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
|
2054 |
+
* license. Please see http://www.yui-ext.com/ for more information. */
|
2055 |
+
|
2056 |
+
var Selector = Class.create();
|
2057 |
+
|
2058 |
+
Selector.prototype = {
|
2059 |
+
initialize: function(expression) {
|
2060 |
+
this.expression = expression.strip();
|
2061 |
+
this.compileMatcher();
|
2062 |
+
},
|
2063 |
+
|
2064 |
+
compileMatcher: function() {
|
2065 |
+
// Selectors with namespaced attributes can't use the XPath version
|
2066 |
+
if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression))
|
2067 |
+
return this.compileXPathMatcher();
|
2068 |
+
|
2069 |
+
var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
|
2070 |
+
c = Selector.criteria, le, p, m;
|
2071 |
+
|
2072 |
+
if (Selector._cache[e]) {
|
2073 |
+
this.matcher = Selector._cache[e]; return;
|
2074 |
+
}
|
2075 |
+
this.matcher = ["this.matcher = function(root) {",
|
2076 |
+
"var r = root, h = Selector.handlers, c = false, n;"];
|
2077 |
+
|
2078 |
+
while (e && le != e && (/\S/).test(e)) {
|
2079 |
+
le = e;
|
2080 |
+
for (var i in ps) {
|
2081 |
+
p = ps[i];
|
2082 |
+
if (m = e.match(p)) {
|
2083 |
+
this.matcher.push(typeof c[i] == 'function' ? c[i](m) :
|
2084 |
+
new Template(c[i]).evaluate(m));
|
2085 |
+
e = e.replace(m[0], '');
|
2086 |
+
break;
|
2087 |
+
}
|
2088 |
+
}
|
2089 |
+
}
|
2090 |
+
|
2091 |
+
this.matcher.push("return h.unique(n);\n}");
|
2092 |
+
eval(this.matcher.join('\n'));
|
2093 |
+
Selector._cache[this.expression] = this.matcher;
|
2094 |
+
},
|
2095 |
+
|
2096 |
+
compileXPathMatcher: function() {
|
2097 |
+
var e = this.expression, ps = Selector.patterns,
|
2098 |
+
x = Selector.xpath, le, m;
|
2099 |
+
|
2100 |
+
if (Selector._cache[e]) {
|
2101 |
+
this.xpath = Selector._cache[e]; return;
|
2102 |
+
}
|
2103 |
+
|
2104 |
+
this.matcher = ['.//*'];
|
2105 |
+
while (e && le != e && (/\S/).test(e)) {
|
2106 |
+
le = e;
|
2107 |
+
for (var i in ps) {
|
2108 |
+
if (m = e.match(ps[i])) {
|
2109 |
+
this.matcher.push(typeof x[i] == 'function' ? x[i](m) :
|
2110 |
+
new Template(x[i]).evaluate(m));
|
2111 |
+
e = e.replace(m[0], '');
|
2112 |
+
break;
|
2113 |
+
}
|
2114 |
+
}
|
2115 |
+
}
|
2116 |
+
|
2117 |
+
this.xpath = this.matcher.join('');
|
2118 |
+
Selector._cache[this.expression] = this.xpath;
|
2119 |
+
},
|
2120 |
+
|
2121 |
+
findElements: function(root) {
|
2122 |
+
root = root || document;
|
2123 |
+
if (this.xpath) return document._getElementsByXPath(this.xpath, root);
|
2124 |
+
return this.matcher(root);
|
2125 |
+
},
|
2126 |
+
|
2127 |
+
match: function(element) {
|
2128 |
+
return this.findElements(document).include(element);
|
2129 |
+
},
|
2130 |
+
|
2131 |
+
toString: function() {
|
2132 |
+
return this.expression;
|
2133 |
+
},
|
2134 |
+
|
2135 |
+
inspect: function() {
|
2136 |
+
return "#<Selector:" + this.expression.inspect() + ">";
|
2137 |
+
}
|
2138 |
+
};
|
2139 |
+
|
2140 |
+
Object.extend(Selector, {
|
2141 |
+
_cache: {},
|
2142 |
+
|
2143 |
+
xpath: {
|
2144 |
+
descendant: "//*",
|
2145 |
+
child: "/*",
|
2146 |
+
adjacent: "/following-sibling::*[1]",
|
2147 |
+
laterSibling: '/following-sibling::*',
|
2148 |
+
tagName: function(m) {
|
2149 |
+
if (m[1] == '*') return '';
|
2150 |
+
return "[local-name()='" + m[1].toLowerCase() +
|
2151 |
+
"' or local-name()='" + m[1].toUpperCase() + "']";
|
2152 |
+
},
|
2153 |
+
className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
|
2154 |
+
id: "[@id='#{1}']",
|
2155 |
+
attrPresence: "[@#{1}]",
|
2156 |
+
attr: function(m) {
|
2157 |
+
m[3] = m[5] || m[6];
|
2158 |
+
return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
|
2159 |
+
},
|
2160 |
+
pseudo: function(m) {
|
2161 |
+
var h = Selector.xpath.pseudos[m[1]];
|
2162 |
+
if (!h) return '';
|
2163 |
+
if (typeof h === 'function') return h(m);
|
2164 |
+
return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
|
2165 |
+
},
|
2166 |
+
operators: {
|
2167 |
+
'=': "[@#{1}='#{3}']",
|
2168 |
+
'!=': "[@#{1}!='#{3}']",
|
2169 |
+
'^=': "[starts-with(@#{1}, '#{3}')]",
|
2170 |
+
'$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
|
2171 |
+
'*=': "[contains(@#{1}, '#{3}')]",
|
2172 |
+
'~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
|
2173 |
+
'|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
|
2174 |
+
},
|
2175 |
+
pseudos: {
|
2176 |
+
'first-child': '[not(preceding-sibling::*)]',
|
2177 |
+
'last-child': '[not(following-sibling::*)]',
|
2178 |
+
'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
|
2179 |
+
'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
|
2180 |
+
'checked': "[@checked]",
|
2181 |
+
'disabled': "[@disabled]",
|
2182 |
+
'enabled': "[not(@disabled)]",
|
2183 |
+
'not': function(m) {
|
2184 |
+
var e = m[6], p = Selector.patterns,
|
2185 |
+
x = Selector.xpath, le, m, v;
|
2186 |
+
|
2187 |
+
var exclusion = [];
|
2188 |
+
while (e && le != e && (/\S/).test(e)) {
|
2189 |
+
le = e;
|
2190 |
+
for (var i in p) {
|
2191 |
+
if (m = e.match(p[i])) {
|
2192 |
+
v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);
|
2193 |
+
exclusion.push("(" + v.substring(1, v.length - 1) + ")");
|
2194 |
+
e = e.replace(m[0], '');
|
2195 |
+
break;
|
2196 |
+
}
|
2197 |
+
}
|
2198 |
+
}
|
2199 |
+
return "[not(" + exclusion.join(" and ") + ")]";
|
2200 |
+
},
|
2201 |
+
'nth-child': function(m) {
|
2202 |
+
return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
|
2203 |
+
},
|
2204 |
+
'nth-last-child': function(m) {
|
2205 |
+
return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
|
2206 |
+
},
|
2207 |
+
'nth-of-type': function(m) {
|
2208 |
+
return Selector.xpath.pseudos.nth("position() ", m);
|
2209 |
+
},
|
2210 |
+
'nth-last-of-type': function(m) {
|
2211 |
+
return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
|
2212 |
+
},
|
2213 |
+
'first-of-type': function(m) {
|
2214 |
+
m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
|
2215 |
+
},
|
2216 |
+
'last-of-type': function(m) {
|
2217 |
+
m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
|
2218 |
+
},
|
2219 |
+
'only-of-type': function(m) {
|
2220 |
+
var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
|
2221 |
+
},
|
2222 |
+
nth: function(fragment, m) {
|
2223 |
+
var mm, formula = m[6], predicate;
|
2224 |
+
if (formula == 'even') formula = '2n+0';
|
2225 |
+
if (formula == 'odd') formula = '2n+1';
|
2226 |
+
if (mm = formula.match(/^(\d+)$/)) // digit only
|
2227 |
+
return '[' + fragment + "= " + mm[1] + ']';
|
2228 |
+
if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
|
2229 |
+
if (mm[1] == "-") mm[1] = -1;
|
2230 |
+
var a = mm[1] ? Number(mm[1]) : 1;
|
2231 |
+
var b = mm[2] ? Number(mm[2]) : 0;
|
2232 |
+
predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
|
2233 |
+
"((#{fragment} - #{b}) div #{a} >= 0)]";
|
2234 |
+
return new Template(predicate).evaluate({
|
2235 |
+
fragment: fragment, a: a, b: b });
|
2236 |
+
}
|
2237 |
+
}
|
2238 |
+
}
|
2239 |
+
},
|
2240 |
+
|
2241 |
+
criteria: {
|
2242 |
+
tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
|
2243 |
+
className: 'n = h.className(n, r, "#{1}", c); c = false;',
|
2244 |
+
id: 'n = h.id(n, r, "#{1}", c); c = false;',
|
2245 |
+
attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
|
2246 |
+
attr: function(m) {
|
2247 |
+
m[3] = (m[5] || m[6]);
|
2248 |
+
return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
|
2249 |
+
},
|
2250 |
+
pseudo: function(m) {
|
2251 |
+
if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
|
2252 |
+
return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
|
2253 |
+
},
|
2254 |
+
descendant: 'c = "descendant";',
|
2255 |
+
child: 'c = "child";',
|
2256 |
+
adjacent: 'c = "adjacent";',
|
2257 |
+
laterSibling: 'c = "laterSibling";'
|
2258 |
+
},
|
2259 |
+
|
2260 |
+
patterns: {
|
2261 |
+
// combinators must be listed first
|
2262 |
+
// (and descendant needs to be last combinator)
|
2263 |
+
laterSibling: /^\s*~\s*/,
|
2264 |
+
child: /^\s*>\s*/,
|
2265 |
+
adjacent: /^\s*\+\s*/,
|
2266 |
+
descendant: /^\s/,
|
2267 |
+
|
2268 |
+
// selectors follow
|
2269 |
+
tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
|
2270 |
+
id: /^#([\w\-\*]+)(\b|$)/,
|
2271 |
+
className: /^\.([\w\-\*]+)(\b|$)/,
|
2272 |
+
pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/,
|
2273 |
+
attrPresence: /^\[([\w]+)\]/,
|
2274 |
+
attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/
|
2275 |
+
},
|
2276 |
+
|
2277 |
+
handlers: {
|
2278 |
+
// UTILITY FUNCTIONS
|
2279 |
+
// joins two collections
|
2280 |
+
concat: function(a, b) {
|
2281 |
+
for (var i = 0, node; node = b[i]; i++)
|
2282 |
+
a.push(node);
|
2283 |
+
return a;
|
2284 |
+
},
|
2285 |
+
|
2286 |
+
// marks an array of nodes for counting
|
2287 |
+
mark: function(nodes) {
|
2288 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2289 |
+
node._counted = true;
|
2290 |
+
return nodes;
|
2291 |
+
},
|
2292 |
+
|
2293 |
+
unmark: function(nodes) {
|
2294 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2295 |
+
node._counted = undefined;
|
2296 |
+
return nodes;
|
2297 |
+
},
|
2298 |
+
|
2299 |
+
// mark each child node with its position (for nth calls)
|
2300 |
+
// "ofType" flag indicates whether we're indexing for nth-of-type
|
2301 |
+
// rather than nth-child
|
2302 |
+
index: function(parentNode, reverse, ofType) {
|
2303 |
+
parentNode._counted = true;
|
2304 |
+
if (reverse) {
|
2305 |
+
for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
|
2306 |
+
node = nodes[i];
|
2307 |
+
if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
|
2308 |
+
}
|
2309 |
+
} else {
|
2310 |
+
for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
|
2311 |
+
if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
|
2312 |
+
}
|
2313 |
+
},
|
2314 |
+
|
2315 |
+
// filters out duplicates and extends all nodes
|
2316 |
+
unique: function(nodes) {
|
2317 |
+
if (nodes.length == 0) return nodes;
|
2318 |
+
var results = [], n;
|
2319 |
+
for (var i = 0, l = nodes.length; i < l; i++)
|
2320 |
+
if (!(n = nodes[i])._counted) {
|
2321 |
+
n._counted = true;
|
2322 |
+
results.push(Element.extend(n));
|
2323 |
+
}
|
2324 |
+
return Selector.handlers.unmark(results);
|
2325 |
+
},
|
2326 |
+
|
2327 |
+
// COMBINATOR FUNCTIONS
|
2328 |
+
descendant: function(nodes) {
|
2329 |
+
var h = Selector.handlers;
|
2330 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2331 |
+
h.concat(results, node.getElementsByTagName('*'));
|
2332 |
+
return results;
|
2333 |
+
},
|
2334 |
+
|
2335 |
+
child: function(nodes) {
|
2336 |
+
var h = Selector.handlers;
|
2337 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++) {
|
2338 |
+
for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
|
2339 |
+
if (child.nodeType == 1 && child.tagName != '!') results.push(child);
|
2340 |
+
}
|
2341 |
+
return results;
|
2342 |
+
},
|
2343 |
+
|
2344 |
+
adjacent: function(nodes) {
|
2345 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++) {
|
2346 |
+
var next = this.nextElementSibling(node);
|
2347 |
+
if (next) results.push(next);
|
2348 |
+
}
|
2349 |
+
return results;
|
2350 |
+
},
|
2351 |
+
|
2352 |
+
laterSibling: function(nodes) {
|
2353 |
+
var h = Selector.handlers;
|
2354 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2355 |
+
h.concat(results, Element.nextSiblings(node));
|
2356 |
+
return results;
|
2357 |
+
},
|
2358 |
+
|
2359 |
+
nextElementSibling: function(node) {
|
2360 |
+
while (node = node.nextSibling)
|
2361 |
+
if (node.nodeType == 1) return node;
|
2362 |
+
return null;
|
2363 |
+
},
|
2364 |
+
|
2365 |
+
previousElementSibling: function(node) {
|
2366 |
+
while (node = node.previousSibling)
|
2367 |
+
if (node.nodeType == 1) return node;
|
2368 |
+
return null;
|
2369 |
+
},
|
2370 |
+
|
2371 |
+
// TOKEN FUNCTIONS
|
2372 |
+
tagName: function(nodes, root, tagName, combinator) {
|
2373 |
+
tagName = tagName.toUpperCase();
|
2374 |
+
var results = [], h = Selector.handlers;
|
2375 |
+
if (nodes) {
|
2376 |
+
if (combinator) {
|
2377 |
+
// fastlane for ordinary descendant combinators
|
2378 |
+
if (combinator == "descendant") {
|
2379 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2380 |
+
h.concat(results, node.getElementsByTagName(tagName));
|
2381 |
+
return results;
|
2382 |
+
} else nodes = this[combinator](nodes);
|
2383 |
+
if (tagName == "*") return nodes;
|
2384 |
+
}
|
2385 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2386 |
+
if (node.tagName.toUpperCase() == tagName) results.push(node);
|
2387 |
+
return results;
|
2388 |
+
} else return root.getElementsByTagName(tagName);
|
2389 |
+
},
|
2390 |
+
|
2391 |
+
id: function(nodes, root, id, combinator) {
|
2392 |
+
var targetNode = $(id), h = Selector.handlers;
|
2393 |
+
if (!nodes && root == document) return targetNode ? [targetNode] : [];
|
2394 |
+
if (nodes) {
|
2395 |
+
if (combinator) {
|
2396 |
+
if (combinator == 'child') {
|
2397 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2398 |
+
if (targetNode.parentNode == node) return [targetNode];
|
2399 |
+
} else if (combinator == 'descendant') {
|
2400 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2401 |
+
if (Element.descendantOf(targetNode, node)) return [targetNode];
|
2402 |
+
} else if (combinator == 'adjacent') {
|
2403 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2404 |
+
if (Selector.handlers.previousElementSibling(targetNode) == node)
|
2405 |
+
return [targetNode];
|
2406 |
+
} else nodes = h[combinator](nodes);
|
2407 |
+
}
|
2408 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2409 |
+
if (node == targetNode) return [targetNode];
|
2410 |
+
return [];
|
2411 |
+
}
|
2412 |
+
return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
|
2413 |
+
},
|
2414 |
+
|
2415 |
+
className: function(nodes, root, className, combinator) {
|
2416 |
+
if (nodes && combinator) nodes = this[combinator](nodes);
|
2417 |
+
return Selector.handlers.byClassName(nodes, root, className);
|
2418 |
+
},
|
2419 |
+
|
2420 |
+
byClassName: function(nodes, root, className) {
|
2421 |
+
if (!nodes) nodes = Selector.handlers.descendant([root]);
|
2422 |
+
var needle = ' ' + className + ' ';
|
2423 |
+
for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
|
2424 |
+
nodeClassName = node.className;
|
2425 |
+
if (nodeClassName.length == 0) continue;
|
2426 |
+
if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
|
2427 |
+
results.push(node);
|
2428 |
+
}
|
2429 |
+
return results;
|
2430 |
+
},
|
2431 |
+
|
2432 |
+
attrPresence: function(nodes, root, attr) {
|
2433 |
+
var results = [];
|
2434 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2435 |
+
if (Element.hasAttribute(node, attr)) results.push(node);
|
2436 |
+
return results;
|
2437 |
+
},
|
2438 |
+
|
2439 |
+
attr: function(nodes, root, attr, value, operator) {
|
2440 |
+
if (!nodes) nodes = root.getElementsByTagName("*");
|
2441 |
+
var handler = Selector.operators[operator], results = [];
|
2442 |
+
for (var i = 0, node; node = nodes[i]; i++) {
|
2443 |
+
var nodeValue = Element.readAttribute(node, attr);
|
2444 |
+
if (nodeValue === null) continue;
|
2445 |
+
if (handler(nodeValue, value)) results.push(node);
|
2446 |
+
}
|
2447 |
+
return results;
|
2448 |
+
},
|
2449 |
+
|
2450 |
+
pseudo: function(nodes, name, value, root, combinator) {
|
2451 |
+
if (nodes && combinator) nodes = this[combinator](nodes);
|
2452 |
+
if (!nodes) nodes = root.getElementsByTagName("*");
|
2453 |
+
return Selector.pseudos[name](nodes, value, root);
|
2454 |
+
}
|
2455 |
+
},
|
2456 |
+
|
2457 |
+
pseudos: {
|
2458 |
+
'first-child': function(nodes, value, root) {
|
2459 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++) {
|
2460 |
+
if (Selector.handlers.previousElementSibling(node)) continue;
|
2461 |
+
results.push(node);
|
2462 |
+
}
|
2463 |
+
return results;
|
2464 |
+
},
|
2465 |
+
'last-child': function(nodes, value, root) {
|
2466 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++) {
|
2467 |
+
if (Selector.handlers.nextElementSibling(node)) continue;
|
2468 |
+
results.push(node);
|
2469 |
+
}
|
2470 |
+
return results;
|
2471 |
+
},
|
2472 |
+
'only-child': function(nodes, value, root) {
|
2473 |
+
var h = Selector.handlers;
|
2474 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2475 |
+
if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
|
2476 |
+
results.push(node);
|
2477 |
+
return results;
|
2478 |
+
},
|
2479 |
+
'nth-child': function(nodes, formula, root) {
|
2480 |
+
return Selector.pseudos.nth(nodes, formula, root);
|
2481 |
+
},
|
2482 |
+
'nth-last-child': function(nodes, formula, root) {
|
2483 |
+
return Selector.pseudos.nth(nodes, formula, root, true);
|
2484 |
+
},
|
2485 |
+
'nth-of-type': function(nodes, formula, root) {
|
2486 |
+
return Selector.pseudos.nth(nodes, formula, root, false, true);
|
2487 |
+
},
|
2488 |
+
'nth-last-of-type': function(nodes, formula, root) {
|
2489 |
+
return Selector.pseudos.nth(nodes, formula, root, true, true);
|
2490 |
+
},
|
2491 |
+
'first-of-type': function(nodes, formula, root) {
|
2492 |
+
return Selector.pseudos.nth(nodes, "1", root, false, true);
|
2493 |
+
},
|
2494 |
+
'last-of-type': function(nodes, formula, root) {
|
2495 |
+
return Selector.pseudos.nth(nodes, "1", root, true, true);
|
2496 |
+
},
|
2497 |
+
'only-of-type': function(nodes, formula, root) {
|
2498 |
+
var p = Selector.pseudos;
|
2499 |
+
return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
|
2500 |
+
},
|
2501 |
+
|
2502 |
+
// handles the an+b logic
|
2503 |
+
getIndices: function(a, b, total) {
|
2504 |
+
if (a == 0) return b > 0 ? [b] : [];
|
2505 |
+
return $R(1, total).inject([], function(memo, i) {
|
2506 |
+
if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
|
2507 |
+
return memo;
|
2508 |
+
});
|
2509 |
+
},
|
2510 |
+
|
2511 |
+
// handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
|
2512 |
+
nth: function(nodes, formula, root, reverse, ofType) {
|
2513 |
+
if (nodes.length == 0) return [];
|
2514 |
+
if (formula == 'even') formula = '2n+0';
|
2515 |
+
if (formula == 'odd') formula = '2n+1';
|
2516 |
+
var h = Selector.handlers, results = [], indexed = [], m;
|
2517 |
+
h.mark(nodes);
|
2518 |
+
for (var i = 0, node; node = nodes[i]; i++) {
|
2519 |
+
if (!node.parentNode._counted) {
|
2520 |
+
h.index(node.parentNode, reverse, ofType);
|
2521 |
+
indexed.push(node.parentNode);
|
2522 |
+
}
|
2523 |
+
}
|
2524 |
+
if (formula.match(/^\d+$/)) { // just a number
|
2525 |
+
formula = Number(formula);
|
2526 |
+
for (var i = 0, node; node = nodes[i]; i++)
|
2527 |
+
if (node.nodeIndex == formula) results.push(node);
|
2528 |
+
} else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
|
2529 |
+
if (m[1] == "-") m[1] = -1;
|
2530 |
+
var a = m[1] ? Number(m[1]) : 1;
|
2531 |
+
var b = m[2] ? Number(m[2]) : 0;
|
2532 |
+
var indices = Selector.pseudos.getIndices(a, b, nodes.length);
|
2533 |
+
for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
|
2534 |
+
for (var j = 0; j < l; j++)
|
2535 |
+
if (node.nodeIndex == indices[j]) results.push(node);
|
2536 |
+
}
|
2537 |
+
}
|
2538 |
+
h.unmark(nodes);
|
2539 |
+
h.unmark(indexed);
|
2540 |
+
return results;
|
2541 |
+
},
|
2542 |
+
|
2543 |
+
'empty': function(nodes, value, root) {
|
2544 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++) {
|
2545 |
+
// IE treats comments as element nodes
|
2546 |
+
if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
|
2547 |
+
results.push(node);
|
2548 |
+
}
|
2549 |
+
return results;
|
2550 |
+
},
|
2551 |
+
|
2552 |
+
'not': function(nodes, selector, root) {
|
2553 |
+
var h = Selector.handlers, selectorType, m;
|
2554 |
+
var exclusions = new Selector(selector).findElements(root);
|
2555 |
+
h.mark(exclusions);
|
2556 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2557 |
+
if (!node._counted) results.push(node);
|
2558 |
+
h.unmark(exclusions);
|
2559 |
+
return results;
|
2560 |
+
},
|
2561 |
+
|
2562 |
+
'enabled': function(nodes, value, root) {
|
2563 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2564 |
+
if (!node.disabled) results.push(node);
|
2565 |
+
return results;
|
2566 |
+
},
|
2567 |
+
|
2568 |
+
'disabled': function(nodes, value, root) {
|
2569 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2570 |
+
if (node.disabled) results.push(node);
|
2571 |
+
return results;
|
2572 |
+
},
|
2573 |
+
|
2574 |
+
'checked': function(nodes, value, root) {
|
2575 |
+
for (var i = 0, results = [], node; node = nodes[i]; i++)
|
2576 |
+
if (node.checked) results.push(node);
|
2577 |
+
return results;
|
2578 |
+
}
|
2579 |
+
},
|
2580 |
+
|
2581 |
+
operators: {
|
2582 |
+
'=': function(nv, v) { return nv == v; },
|
2583 |
+
'!=': function(nv, v) { return nv != v; },
|
2584 |
+
'^=': function(nv, v) { return nv.startsWith(v); },
|
2585 |
+
'$=': function(nv, v) { return nv.endsWith(v); },
|
2586 |
+
'*=': function(nv, v) { return nv.include(v); },
|
2587 |
+
'~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
|
2588 |
+
'|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
|
2589 |
+
},
|
2590 |
+
|
2591 |
+
matchElements: function(elements, expression) {
|
2592 |
+
var matches = new Selector(expression).findElements(), h = Selector.handlers;
|
2593 |
+
h.mark(matches);
|
2594 |
+
for (var i = 0, results = [], element; element = elements[i]; i++)
|
2595 |
+
if (element._counted) results.push(element);
|
2596 |
+
h.unmark(matches);
|
2597 |
+
return results;
|
2598 |
+
},
|
2599 |
+
|
2600 |
+
findElement: function(elements, expression, index) {
|
2601 |
+
if (typeof expression == 'number') {
|
2602 |
+
index = expression; expression = false;
|
2603 |
+
}
|
2604 |
+
return Selector.matchElements(elements, expression || '*')[index || 0];
|
2605 |
+
},
|
2606 |
+
|
2607 |
+
findChildElements: function(element, expressions) {
|
2608 |
+
var exprs = expressions.join(','), expressions = [];
|
2609 |
+
exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
|
2610 |
+
expressions.push(m[1].strip());
|
2611 |
+
});
|
2612 |
+
var results = [], h = Selector.handlers;
|
2613 |
+
for (var i = 0, l = expressions.length, selector; i < l; i++) {
|
2614 |
+
selector = new Selector(expressions[i].strip());
|
2615 |
+
h.concat(results, selector.findElements(element));
|
2616 |
+
}
|
2617 |
+
return (l > 1) ? h.unique(results) : results;
|
2618 |
+
}
|
2619 |
+
});
|
2620 |
+
|
2621 |
+
function $$() {
|
2622 |
+
return Selector.findChildElements(document, $A(arguments));
|
2623 |
+
}
|
2624 |
+
var Form = {
|
2625 |
+
reset: function(form) {
|
2626 |
+
$(form).reset();
|
2627 |
+
return form;
|
2628 |
+
},
|
2629 |
+
|
2630 |
+
serializeElements: function(elements, getHash) {
|
2631 |
+
var data = elements.inject({}, function(result, element) {
|
2632 |
+
if (!element.disabled && element.name) {
|
2633 |
+
var key = element.name, value = $(element).getValue();
|
2634 |
+
if (value != null) {
|
2635 |
+
if (key in result) {
|
2636 |
+
if (result[key].constructor != Array) result[key] = [result[key]];
|
2637 |
+
result[key].push(value);
|
2638 |
+
}
|
2639 |
+
else result[key] = value;
|
2640 |
+
}
|
2641 |
+
}
|
2642 |
+
return result;
|
2643 |
+
});
|
2644 |
+
|
2645 |
+
return getHash ? data : Hash.toQueryString(data);
|
2646 |
+
}
|
2647 |
+
};
|
2648 |
+
|
2649 |
+
Form.Methods = {
|
2650 |
+
serialize: function(form, getHash) {
|
2651 |
+
return Form.serializeElements(Form.getElements(form), getHash);
|
2652 |
+
},
|
2653 |
+
|
2654 |
+
getElements: function(form) {
|
2655 |
+
return $A($(form).getElementsByTagName('*')).inject([],
|
2656 |
+
function(elements, child) {
|
2657 |
+
if (Form.Element.Serializers[child.tagName.toLowerCase()])
|
2658 |
+
elements.push(Element.extend(child));
|
2659 |
+
return elements;
|
2660 |
+
}
|
2661 |
+
);
|
2662 |
+
},
|
2663 |
+
|
2664 |
+
getInputs: function(form, typeName, name) {
|
2665 |
+
form = $(form);
|
2666 |
+
var inputs = form.getElementsByTagName('input');
|
2667 |
+
|
2668 |
+
if (!typeName && !name) return $A(inputs).map(Element.extend);
|
2669 |
+
|
2670 |
+
for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
|
2671 |
+
var input = inputs[i];
|
2672 |
+
if ((typeName && input.type != typeName) || (name && input.name != name))
|
2673 |
+
continue;
|
2674 |
+
matchingInputs.push(Element.extend(input));
|
2675 |
+
}
|
2676 |
+
|
2677 |
+
return matchingInputs;
|
2678 |
+
},
|
2679 |
+
|
2680 |
+
disable: function(form) {
|
2681 |
+
form = $(form);
|
2682 |
+
Form.getElements(form).invoke('disable');
|
2683 |
+
return form;
|
2684 |
+
},
|
2685 |
+
|
2686 |
+
enable: function(form) {
|
2687 |
+
form = $(form);
|
2688 |
+
Form.getElements(form).invoke('enable');
|
2689 |
+
return form;
|
2690 |
+
},
|
2691 |
+
|
2692 |
+
findFirstElement: function(form) {
|
2693 |
+
return $(form).getElements().find(function(element) {
|
2694 |
+
return element.type != 'hidden' && !element.disabled &&
|
2695 |
+
['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
|
2696 |
+
});
|
2697 |
+
},
|
2698 |
+
|
2699 |
+
focusFirstElement: function(form) {
|
2700 |
+
form = $(form);
|
2701 |
+
form.findFirstElement().activate();
|
2702 |
+
return form;
|
2703 |
+
},
|
2704 |
+
|
2705 |
+
request: function(form, options) {
|
2706 |
+
form = $(form), options = Object.clone(options || {});
|
2707 |
+
|
2708 |
+
var params = options.parameters;
|
2709 |
+
options.parameters = form.serialize(true);
|
2710 |
+
|
2711 |
+
if (params) {
|
2712 |
+
if (typeof params == 'string') params = params.toQueryParams();
|
2713 |
+
Object.extend(options.parameters, params);
|
2714 |
+
}
|
2715 |
+
|
2716 |
+
if (form.hasAttribute('method') && !options.method)
|
2717 |
+
options.method = form.method;
|
2718 |
+
|
2719 |
+
return new Ajax.Request(form.readAttribute('action'), options);
|
2720 |
+
}
|
2721 |
+
}
|
2722 |
+
|
2723 |
+
/*--------------------------------------------------------------------------*/
|
2724 |
+
|
2725 |
+
Form.Element = {
|
2726 |
+
focus: function(element) {
|
2727 |
+
$(element).focus();
|
2728 |
+
return element;
|
2729 |
+
},
|
2730 |
+
|
2731 |
+
select: function(element) {
|
2732 |
+
$(element).select();
|
2733 |
+
return element;
|
2734 |
+
}
|
2735 |
+
}
|
2736 |
+
|
2737 |
+
Form.Element.Methods = {
|
2738 |
+
serialize: function(element) {
|
2739 |
+
element = $(element);
|
2740 |
+
if (!element.disabled && element.name) {
|
2741 |
+
var value = element.getValue();
|
2742 |
+
if (value != undefined) {
|
2743 |
+
var pair = {};
|
2744 |
+
pair[element.name] = value;
|
2745 |
+
return Hash.toQueryString(pair);
|
2746 |
+
}
|
2747 |
+
}
|
2748 |
+
return '';
|
2749 |
+
},
|
2750 |
+
|
2751 |
+
getValue: function(element) {
|
2752 |
+
element = $(element);
|
2753 |
+
var method = element.tagName.toLowerCase();
|
2754 |
+
return Form.Element.Serializers[method](element);
|
2755 |
+
},
|
2756 |
+
|
2757 |
+
clear: function(element) {
|
2758 |
+
$(element).value = '';
|
2759 |
+
return element;
|
2760 |
+
},
|
2761 |
+
|
2762 |
+
present: function(element) {
|
2763 |
+
return $(element).value != '';
|
2764 |
+
},
|
2765 |
+
|
2766 |
+
activate: function(element) {
|
2767 |
+
element = $(element);
|
2768 |
+
try {
|
2769 |
+
element.focus();
|
2770 |
+
if (element.select && (element.tagName.toLowerCase() != 'input' ||
|
2771 |
+
!['button', 'reset', 'submit'].include(element.type)))
|
2772 |
+
element.select();
|
2773 |
+
} catch (e) {}
|
2774 |
+
return element;
|
2775 |
+
},
|
2776 |
+
|
2777 |
+
disable: function(element) {
|
2778 |
+
element = $(element);
|
2779 |
+
element.blur();
|
2780 |
+
element.disabled = true;
|
2781 |
+
return element;
|
2782 |
+
},
|
2783 |
+
|
2784 |
+
enable: function(element) {
|
2785 |
+
element = $(element);
|
2786 |
+
element.disabled = false;
|
2787 |
+
return element;
|
2788 |
+
}
|
2789 |
+
}
|
2790 |
+
|
2791 |
+
/*--------------------------------------------------------------------------*/
|
2792 |
+
|
2793 |
+
var Field = Form.Element;
|
2794 |
+
var $F = Form.Element.Methods.getValue;
|
2795 |
+
|
2796 |
+
/*--------------------------------------------------------------------------*/
|
2797 |
+
|
2798 |
+
Form.Element.Serializers = {
|
2799 |
+
input: function(element) {
|
2800 |
+
switch (element.type.toLowerCase()) {
|
2801 |
+
case 'checkbox':
|
2802 |
+
case 'radio':
|
2803 |
+
return Form.Element.Serializers.inputSelector(element);
|
2804 |
+
default:
|
2805 |
+
return Form.Element.Serializers.textarea(element);
|
2806 |
+
}
|
2807 |
+
},
|
2808 |
+
|
2809 |
+
inputSelector: function(element) {
|
2810 |
+
return element.checked ? element.value : null;
|
2811 |
+
},
|
2812 |
+
|
2813 |
+
textarea: function(element) {
|
2814 |
+
return element.value;
|
2815 |
+
},
|
2816 |
+
|
2817 |
+
select: function(element) {
|
2818 |
+
return this[element.type == 'select-one' ?
|
2819 |
+
'selectOne' : 'selectMany'](element);
|
2820 |
+
},
|
2821 |
+
|
2822 |
+
selectOne: function(element) {
|
2823 |
+
var index = element.selectedIndex;
|
2824 |
+
return index >= 0 ? this.optionValue(element.options[index]) : null;
|
2825 |
+
},
|
2826 |
+
|
2827 |
+
selectMany: function(element) {
|
2828 |
+
var values, length = element.length;
|
2829 |
+
if (!length) return null;
|
2830 |
+
|
2831 |
+
for (var i = 0, values = []; i < length; i++) {
|
2832 |
+
var opt = element.options[i];
|
2833 |
+
if (opt.selected) values.push(this.optionValue(opt));
|
2834 |
+
}
|
2835 |
+
return values;
|
2836 |
+
},
|
2837 |
+
|
2838 |
+
optionValue: function(opt) {
|
2839 |
+
// extend element because hasAttribute may not be native
|
2840 |
+
return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
|
2841 |
+
}
|
2842 |
+
}
|
2843 |
+
|
2844 |
+
/*--------------------------------------------------------------------------*/
|
2845 |
+
|
2846 |
+
Abstract.TimedObserver = function() {}
|
2847 |
+
Abstract.TimedObserver.prototype = {
|
2848 |
+
initialize: function(element, frequency, callback) {
|
2849 |
+
this.frequency = frequency;
|
2850 |
+
this.element = $(element);
|
2851 |
+
this.callback = callback;
|
2852 |
+
|
2853 |
+
this.lastValue = this.getValue();
|
2854 |
+
this.registerCallback();
|
2855 |
+
},
|
2856 |
+
|
2857 |
+
registerCallback: function() {
|
2858 |
+
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
|
2859 |
+
},
|
2860 |
+
|
2861 |
+
onTimerEvent: function() {
|
2862 |
+
var value = this.getValue();
|
2863 |
+
var changed = ('string' == typeof this.lastValue && 'string' == typeof value
|
2864 |
+
? this.lastValue != value : String(this.lastValue) != String(value));
|
2865 |
+
if (changed) {
|
2866 |
+
this.callback(this.element, value);
|
2867 |
+
this.lastValue = value;
|
2868 |
+
}
|
2869 |
+
}
|
2870 |
+
}
|
2871 |
+
|
2872 |
+
Form.Element.Observer = Class.create();
|
2873 |
+
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
|
2874 |
+
getValue: function() {
|
2875 |
+
return Form.Element.getValue(this.element);
|
2876 |
+
}
|
2877 |
+
});
|
2878 |
+
|
2879 |
+
Form.Observer = Class.create();
|
2880 |
+
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
|
2881 |
+
getValue: function() {
|
2882 |
+
return Form.serialize(this.element);
|
2883 |
+
}
|
2884 |
+
});
|
2885 |
+
|
2886 |
+
/*--------------------------------------------------------------------------*/
|
2887 |
+
|
2888 |
+
Abstract.EventObserver = function() {}
|
2889 |
+
Abstract.EventObserver.prototype = {
|
2890 |
+
initialize: function(element, callback) {
|
2891 |
+
this.element = $(element);
|
2892 |
+
this.callback = callback;
|
2893 |
+
|
2894 |
+
this.lastValue = this.getValue();
|
2895 |
+
if (this.element.tagName.toLowerCase() == 'form')
|
2896 |
+
this.registerFormCallbacks();
|
2897 |
+
else
|
2898 |
+
this.registerCallback(this.element);
|
2899 |
+
},
|
2900 |
+
|
2901 |
+
onElementEvent: function() {
|
2902 |
+
var value = this.getValue();
|
2903 |
+
if (this.lastValue != value) {
|
2904 |
+
this.callback(this.element, value);
|
2905 |
+
this.lastValue = value;
|
2906 |
+
}
|
2907 |
+
},
|
2908 |
+
|
2909 |
+
registerFormCallbacks: function() {
|
2910 |
+
Form.getElements(this.element).each(this.registerCallback.bind(this));
|
2911 |
+
},
|
2912 |
+
|
2913 |
+
registerCallback: function(element) {
|
2914 |
+
if (element.type) {
|
2915 |
+
switch (element.type.toLowerCase()) {
|
2916 |
+
case 'checkbox':
|
2917 |
+
case 'radio':
|
2918 |
+
Event.observe(element, 'click', this.onElementEvent.bind(this));
|
2919 |
+
break;
|
2920 |
+
default:
|
2921 |
+
Event.observe(element, 'change', this.onElementEvent.bind(this));
|
2922 |
+
break;
|
2923 |
+
}
|
2924 |
+
}
|
2925 |
+
}
|
2926 |
+
}
|
2927 |
+
|
2928 |
+
Form.Element.EventObserver = Class.create();
|
2929 |
+
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
|
2930 |
+
getValue: function() {
|
2931 |
+
return Form.Element.getValue(this.element);
|
2932 |
+
}
|
2933 |
+
});
|
2934 |
+
|
2935 |
+
Form.EventObserver = Class.create();
|
2936 |
+
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
|
2937 |
+
getValue: function() {
|
2938 |
+
return Form.serialize(this.element);
|
2939 |
+
}
|
2940 |
+
});
|
2941 |
+
if (!window.Event) {
|
2942 |
+
var Event = new Object();
|
2943 |
+
}
|
2944 |
+
|
2945 |
+
Object.extend(Event, {
|
2946 |
+
KEY_BACKSPACE: 8,
|
2947 |
+
KEY_TAB: 9,
|
2948 |
+
KEY_RETURN: 13,
|
2949 |
+
KEY_ESC: 27,
|
2950 |
+
KEY_LEFT: 37,
|
2951 |
+
KEY_UP: 38,
|
2952 |
+
KEY_RIGHT: 39,
|
2953 |
+
KEY_DOWN: 40,
|
2954 |
+
KEY_DELETE: 46,
|
2955 |
+
KEY_HOME: 36,
|
2956 |
+
KEY_END: 35,
|
2957 |
+
KEY_PAGEUP: 33,
|
2958 |
+
KEY_PAGEDOWN: 34,
|
2959 |
+
|
2960 |
+
element: function(event) {
|
2961 |
+
return $(event.target || event.srcElement);
|
2962 |
+
},
|
2963 |
+
|
2964 |
+
isLeftClick: function(event) {
|
2965 |
+
return (((event.which) && (event.which == 1)) ||
|
2966 |
+
((event.button) && (event.button == 1)));
|
2967 |
+
},
|
2968 |
+
|
2969 |
+
pointerX: function(event) {
|
2970 |
+
return event.pageX || (event.clientX +
|
2971 |
+
(document.documentElement.scrollLeft || document.body.scrollLeft));
|
2972 |
+
},
|
2973 |
+
|
2974 |
+
pointerY: function(event) {
|
2975 |
+
return event.pageY || (event.clientY +
|
2976 |
+
(document.documentElement.scrollTop || document.body.scrollTop));
|
2977 |
+
},
|
2978 |
+
|
2979 |
+
stop: function(event) {
|
2980 |
+
if (event.preventDefault) {
|
2981 |
+
event.preventDefault();
|
2982 |
+
event.stopPropagation();
|
2983 |
+
} else {
|
2984 |
+
event.returnValue = false;
|
2985 |
+
event.cancelBubble = true;
|
2986 |
+
}
|
2987 |
+
},
|
2988 |
+
|
2989 |
+
// find the first node with the given tagName, starting from the
|
2990 |
+
// node the event was triggered on; traverses the DOM upwards
|
2991 |
+
findElement: function(event, tagName) {
|
2992 |
+
var element = Event.element(event);
|
2993 |
+
while (element.parentNode && (!element.tagName ||
|
2994 |
+
(element.tagName.toUpperCase() != tagName.toUpperCase())))
|
2995 |
+
element = element.parentNode;
|
2996 |
+
return element;
|
2997 |
+
},
|
2998 |
+
|
2999 |
+
observers: false,
|
3000 |
+
|
3001 |
+
_observeAndCache: function(element, name, observer, useCapture) {
|
3002 |
+
if (!this.observers) this.observers = [];
|
3003 |
+
if (element.addEventListener) {
|
3004 |
+
this.observers.push([element, name, observer, useCapture]);
|
3005 |
+
element.addEventListener(name, observer, useCapture);
|
3006 |
+
} else if (element.attachEvent) {
|
3007 |
+
this.observers.push([element, name, observer, useCapture]);
|
3008 |
+
element.attachEvent('on' + name, observer);
|
3009 |
+
}
|
3010 |
+
},
|
3011 |
+
|
3012 |
+
unloadCache: function() {
|
3013 |
+
if (!Event.observers) return;
|
3014 |
+
for (var i = 0, length = Event.observers.length; i < length; i++) {
|
3015 |
+
Event.stopObserving.apply(this, Event.observers[i]);
|
3016 |
+
Event.observers[i][0] = null;
|
3017 |
+
}
|
3018 |
+
Event.observers = false;
|
3019 |
+
},
|
3020 |
+
|
3021 |
+
observe: function(element, name, observer, useCapture) {
|
3022 |
+
element = $(element);
|
3023 |
+
useCapture = useCapture || false;
|
3024 |
+
|
3025 |
+
if (name == 'keypress' &&
|
3026 |
+
(Prototype.Browser.WebKit || element.attachEvent))
|
3027 |
+
name = 'keydown';
|
3028 |
+
|
3029 |
+
Event._observeAndCache(element, name, observer, useCapture);
|
3030 |
+
},
|
3031 |
+
|
3032 |
+
stopObserving: function(element, name, observer, useCapture) {
|
3033 |
+
element = $(element);
|
3034 |
+
useCapture = useCapture || false;
|
3035 |
+
|
3036 |
+
if (name == 'keypress' &&
|
3037 |
+
(Prototype.Browser.WebKit || element.attachEvent))
|
3038 |
+
name = 'keydown';
|
3039 |
+
|
3040 |
+
if (element.removeEventListener) {
|
3041 |
+
element.removeEventListener(name, observer, useCapture);
|
3042 |
+
} else if (element.detachEvent) {
|
3043 |
+
try {
|
3044 |
+
element.detachEvent('on' + name, observer);
|
3045 |
+
} catch (e) {}
|
3046 |
+
}
|
3047 |
+
}
|
3048 |
+
});
|
3049 |
+
|
3050 |
+
/* prevent memory leaks in IE */
|
3051 |
+
if (Prototype.Browser.IE)
|
3052 |
+
Event.observe(window, 'unload', Event.unloadCache, false);
|
3053 |
+
var Position = {
|
3054 |
+
// set to true if needed, warning: firefox performance problems
|
3055 |
+
// NOT neeeded for page scrolling, only if draggable contained in
|
3056 |
+
// scrollable elements
|
3057 |
+
includeScrollOffsets: false,
|
3058 |
+
|
3059 |
+
// must be called before calling withinIncludingScrolloffset, every time the
|
3060 |
+
// page is scrolled
|
3061 |
+
prepare: function() {
|
3062 |
+
this.deltaX = window.pageXOffset
|
3063 |
+
|| document.documentElement.scrollLeft
|
3064 |
+
|| document.body.scrollLeft
|
3065 |
+
|| 0;
|
3066 |
+
this.deltaY = window.pageYOffset
|
3067 |
+
|| document.documentElement.scrollTop
|
3068 |
+
|| document.body.scrollTop
|
3069 |
+
|| 0;
|
3070 |
+
},
|
3071 |
+
|
3072 |
+
realOffset: function(element) {
|
3073 |
+
var valueT = 0, valueL = 0;
|
3074 |
+
do {
|
3075 |
+
valueT += element.scrollTop || 0;
|
3076 |
+
valueL += element.scrollLeft || 0;
|
3077 |
+
element = element.parentNode;
|
3078 |
+
} while (element);
|
3079 |
+
return [valueL, valueT];
|
3080 |
+
},
|
3081 |
+
|
3082 |
+
cumulativeOffset: function(element) {
|
3083 |
+
var valueT = 0, valueL = 0;
|
3084 |
+
do {
|
3085 |
+
valueT += element.offsetTop || 0;
|
3086 |
+
valueL += element.offsetLeft || 0;
|
3087 |
+
element = element.offsetParent;
|
3088 |
+
} while (element);
|
3089 |
+
return [valueL, valueT];
|
3090 |
+
},
|
3091 |
+
|
3092 |
+
positionedOffset: function(element) {
|
3093 |
+
var valueT = 0, valueL = 0;
|
3094 |
+
do {
|
3095 |
+
valueT += element.offsetTop || 0;
|
3096 |
+
valueL += element.offsetLeft || 0;
|
3097 |
+
element = element.offsetParent;
|
3098 |
+
if (element) {
|
3099 |
+
if(element.tagName=='BODY') break;
|
3100 |
+
var p = Element.getStyle(element, 'position');
|
3101 |
+
if (p == 'relative' || p == 'absolute') break;
|
3102 |
+
}
|
3103 |
+
} while (element);
|
3104 |
+
return [valueL, valueT];
|
3105 |
+
},
|
3106 |
+
|
3107 |
+
offsetParent: function(element) {
|
3108 |
+
if (element.offsetParent) return element.offsetParent;
|
3109 |
+
if (element == document.body) return element;
|
3110 |
+
|
3111 |
+
while ((element = element.parentNode) && element != document.body)
|
3112 |
+
if (Element.getStyle(element, 'position') != 'static')
|
3113 |
+
return element;
|
3114 |
+
|
3115 |
+
return document.body;
|
3116 |
+
},
|
3117 |
+
|
3118 |
+
// caches x/y coordinate pair to use with overlap
|
3119 |
+
within: function(element, x, y) {
|
3120 |
+
if (this.includeScrollOffsets)
|
3121 |
+
return this.withinIncludingScrolloffsets(element, x, y);
|
3122 |
+
this.xcomp = x;
|
3123 |
+
this.ycomp = y;
|
3124 |
+
this.offset = this.cumulativeOffset(element);
|
3125 |
+
|
3126 |
+
return (y >= this.offset[1] &&
|
3127 |
+
y < this.offset[1] + element.offsetHeight &&
|
3128 |
+
x >= this.offset[0] &&
|
3129 |
+
x < this.offset[0] + element.offsetWidth);
|
3130 |
+
},
|
3131 |
+
|
3132 |
+
withinIncludingScrolloffsets: function(element, x, y) {
|
3133 |
+
var offsetcache = this.realOffset(element);
|
3134 |
+
|
3135 |
+
this.xcomp = x + offsetcache[0] - this.deltaX;
|
3136 |
+
this.ycomp = y + offsetcache[1] - this.deltaY;
|
3137 |
+
this.offset = this.cumulativeOffset(element);
|
3138 |
+
|
3139 |
+
return (this.ycomp >= this.offset[1] &&
|
3140 |
+
this.ycomp < this.offset[1] + element.offsetHeight &&
|
3141 |
+
this.xcomp >= this.offset[0] &&
|
3142 |
+
this.xcomp < this.offset[0] + element.offsetWidth);
|
3143 |
+
},
|
3144 |
+
|
3145 |
+
// within must be called directly before
|
3146 |
+
overlap: function(mode, element) {
|
3147 |
+
if (!mode) return 0;
|
3148 |
+
if (mode == 'vertical')
|
3149 |
+
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
|
3150 |
+
element.offsetHeight;
|
3151 |
+
if (mode == 'horizontal')
|
3152 |
+
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
|
3153 |
+
element.offsetWidth;
|
3154 |
+
},
|
3155 |
+
|
3156 |
+
page: function(forElement) {
|
3157 |
+
var valueT = 0, valueL = 0;
|
3158 |
+
|
3159 |
+
var element = forElement;
|
3160 |
+
do {
|
3161 |
+
valueT += element.offsetTop || 0;
|
3162 |
+
valueL += element.offsetLeft || 0;
|
3163 |
+
|
3164 |
+
// Safari fix
|
3165 |
+
if (element.offsetParent == document.body)
|
3166 |
+
if (Element.getStyle(element,'position')=='absolute') break;
|
3167 |
+
|
3168 |
+
} while (element = element.offsetParent);
|
3169 |
+
|
3170 |
+
element = forElement;
|
3171 |
+
do {
|
3172 |
+
if (!window.opera || element.tagName=='BODY') {
|
3173 |
+
valueT -= element.scrollTop || 0;
|
3174 |
+
valueL -= element.scrollLeft || 0;
|
3175 |
+
}
|
3176 |
+
} while (element = element.parentNode);
|
3177 |
+
|
3178 |
+
return [valueL, valueT];
|
3179 |
+
},
|
3180 |
+
|
3181 |
+
clone: function(source, target) {
|
3182 |
+
var options = Object.extend({
|
3183 |
+
setLeft: true,
|
3184 |
+
setTop: true,
|
3185 |
+
setWidth: true,
|
3186 |
+
setHeight: true,
|
3187 |
+
offsetTop: 0,
|
3188 |
+
offsetLeft: 0
|
3189 |
+
}, arguments[2] || {})
|
3190 |
+
|
3191 |
+
// find page position of source
|
3192 |
+
source = $(source);
|
3193 |
+
var p = Position.page(source);
|
3194 |
+
|
3195 |
+
// find coordinate system to use
|
3196 |
+
target = $(target);
|
3197 |
+
var delta = [0, 0];
|
3198 |
+
var parent = null;
|
3199 |
+
// delta [0,0] will do fine with position: fixed elements,
|
3200 |
+
// position:absolute needs offsetParent deltas
|
3201 |
+
if (Element.getStyle(target,'position') == 'absolute') {
|
3202 |
+
parent = Position.offsetParent(target);
|
3203 |
+
delta = Position.page(parent);
|
3204 |
+
}
|
3205 |
+
|
3206 |
+
// correct by body offsets (fixes Safari)
|
3207 |
+
if (parent == document.body) {
|
3208 |
+
delta[0] -= document.body.offsetLeft;
|
3209 |
+
delta[1] -= document.body.offsetTop;
|
3210 |
+
}
|
3211 |
+
|
3212 |
+
// set position
|
3213 |
+
if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
|
3214 |
+
if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
|
3215 |
+
if(options.setWidth) target.style.width = source.offsetWidth + 'px';
|
3216 |
+
if(options.setHeight) target.style.height = source.offsetHeight + 'px';
|
3217 |
+
},
|
3218 |
+
|
3219 |
+
absolutize: function(element) {
|
3220 |
+
element = $(element);
|
3221 |
+
if (element.style.position == 'absolute') return;
|
3222 |
+
Position.prepare();
|
3223 |
+
|
3224 |
+
var offsets = Position.positionedOffset(element);
|
3225 |
+
var top = offsets[1];
|
3226 |
+
var left = offsets[0];
|
3227 |
+
var width = element.clientWidth;
|
3228 |
+
var height = element.clientHeight;
|
3229 |
+
|
3230 |
+
element._originalLeft = left - parseFloat(element.style.left || 0);
|
3231 |
+
element._originalTop = top - parseFloat(element.style.top || 0);
|
3232 |
+
element._originalWidth = element.style.width;
|
3233 |
+
element._originalHeight = element.style.height;
|
3234 |
+
|
3235 |
+
element.style.position = 'absolute';
|
3236 |
+
element.style.top = top + 'px';
|
3237 |
+
element.style.left = left + 'px';
|
3238 |
+
element.style.width = width + 'px';
|
3239 |
+
element.style.height = height + 'px';
|
3240 |
+
},
|
3241 |
+
|
3242 |
+
relativize: function(element) {
|
3243 |
+
element = $(element);
|
3244 |
+
if (element.style.position == 'relative') return;
|
3245 |
+
Position.prepare();
|
3246 |
+
|
3247 |
+
element.style.position = 'relative';
|
3248 |
+
var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
|
3249 |
+
var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
|
3250 |
+
|
3251 |
+
element.style.top = top + 'px';
|
3252 |
+
element.style.left = left + 'px';
|
3253 |
+
element.style.height = element._originalHeight;
|
3254 |
+
element.style.width = element._originalWidth;
|
3255 |
+
}
|
3256 |
+
}
|
3257 |
+
|
3258 |
+
// Safari returns margins on body which is incorrect if the child is absolutely
|
3259 |
+
// positioned. For performance reasons, redefine Position.cumulativeOffset for
|
3260 |
+
// KHTML/WebKit only.
|
3261 |
+
if (Prototype.Browser.WebKit) {
|
3262 |
+
Position.cumulativeOffset = function(element) {
|
3263 |
+
var valueT = 0, valueL = 0;
|
3264 |
+
do {
|
3265 |
+
valueT += element.offsetTop || 0;
|
3266 |
+
valueL += element.offsetLeft || 0;
|
3267 |
+
if (element.offsetParent == document.body)
|
3268 |
+
if (Element.getStyle(element, 'position') == 'absolute') break;
|
3269 |
+
|
3270 |
+
element = element.offsetParent;
|
3271 |
+
} while (element);
|
3272 |
+
|
3273 |
+
return [valueL, valueT];
|
3274 |
+
}
|
3275 |
+
}
|
3276 |
+
|
3277 |
+
Element.addMethods();
|
downloader/lib/Mage/Archive.php
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Archiver is used for compress.
|
39 |
+
*/
|
40 |
+
const DEFAULT_ARCHIVER = 'gz';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Default packer for directory.
|
44 |
+
*/
|
45 |
+
const TAPE_ARCHIVER = 'tar';
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Current archiver is used for compress.
|
49 |
+
*
|
50 |
+
* @var Mage_Archiver_Tar|Mage_Archiver_Gz|Mage_Archiver_Bz
|
51 |
+
*/
|
52 |
+
protected $_archiver=null;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Accessible formats for compress.
|
56 |
+
*
|
57 |
+
* @var array
|
58 |
+
*/
|
59 |
+
protected $_formats = array(
|
60 |
+
'tar' => 'tar',
|
61 |
+
'gz' => 'gz',
|
62 |
+
'gzip' => 'gz',
|
63 |
+
'tgz' => 'tar.gz',
|
64 |
+
'tgzip' => 'tar.gz',
|
65 |
+
'bz' => 'bz',
|
66 |
+
'bzip' => 'bz',
|
67 |
+
'bzip2' => 'bz',
|
68 |
+
'bz2' => 'bz',
|
69 |
+
'tbz' => 'tar.bz',
|
70 |
+
'tbzip' => 'tar.bz',
|
71 |
+
'tbz2' => 'tar.bz',
|
72 |
+
'tbzip2' => 'tar.bz');
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Create object of current archiver by $extension.
|
76 |
+
*
|
77 |
+
* @param string $extension
|
78 |
+
* @return Mage_Archiver_Tar|Mage_Archiver_Gz|Mage_Archiver_Bz
|
79 |
+
*/
|
80 |
+
protected function _getArchiver($extension)
|
81 |
+
{
|
82 |
+
if(array_key_exists(strtolower($extension), $this->_formats)) {
|
83 |
+
$format = $this->_formats[$extension];
|
84 |
+
} else {
|
85 |
+
$format = self::DEFAULT_ARCHIVER;
|
86 |
+
}
|
87 |
+
$class = 'Mage_Archive_'.ucfirst($format);
|
88 |
+
$this->_archiver = new $class();
|
89 |
+
return $this->_archiver;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Split current format to list of archivers.
|
94 |
+
*
|
95 |
+
* @param string $source
|
96 |
+
* @return array
|
97 |
+
*/
|
98 |
+
protected function _getArchivers($source)
|
99 |
+
{
|
100 |
+
$ext = pathinfo($source, PATHINFO_EXTENSION);
|
101 |
+
if(!isset($this->_formats[$ext])) {
|
102 |
+
return array();
|
103 |
+
}
|
104 |
+
$format = $this->_formats[$ext];
|
105 |
+
if ($format) {
|
106 |
+
$archivers = explode('.', $format);
|
107 |
+
return $archivers;
|
108 |
+
}
|
109 |
+
return array();
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Pack file or directory to archivers are parsed from extension.
|
114 |
+
*
|
115 |
+
* @param string $source
|
116 |
+
* @param string $destination
|
117 |
+
* @param boolean $skipRoot skip first level parent
|
118 |
+
* @return string Path to file
|
119 |
+
*/
|
120 |
+
public function pack($source, $destination='packed.tgz', $skipRoot=false)
|
121 |
+
{
|
122 |
+
$archivers = $this->_getArchivers($destination);
|
123 |
+
$interimSource = '';
|
124 |
+
for ($i=0; $i<count($archivers); $i++ ) {
|
125 |
+
if ($i == (count($archivers) - 1)) {
|
126 |
+
$packed = $destination;
|
127 |
+
} else {
|
128 |
+
$packed = dirname($destination) . DS . '~tmp-'. microtime(true) . $archivers[$i] . '.' . $archivers[$i];
|
129 |
+
}
|
130 |
+
$source = $this->_getArchiver($archivers[$i])->pack($source, $packed, $skipRoot);
|
131 |
+
if ($interimSource && $i < count($archivers)) {
|
132 |
+
unlink($interimSource);
|
133 |
+
}
|
134 |
+
$interimSource = $source;
|
135 |
+
}
|
136 |
+
return $source;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Unpack file from archivers are parsed from extension.
|
141 |
+
* If $tillTar == true unpack file from archivers till
|
142 |
+
* meet TAR archiver.
|
143 |
+
*
|
144 |
+
* @param string $source
|
145 |
+
* @param string $destination
|
146 |
+
* @param boolean $tillTar
|
147 |
+
* @return string Path to file
|
148 |
+
*/
|
149 |
+
public function unpack($source, $destination='.', $tillTar=false, $clearInterm = true)
|
150 |
+
{
|
151 |
+
$archivers = $this->_getArchivers($source);
|
152 |
+
$interimSource = '';
|
153 |
+
for ($i=count($archivers)-1; $i>=0; $i--) {
|
154 |
+
if ($tillTar && $archivers[$i] == self::TAPE_ARCHIVER) {
|
155 |
+
break;
|
156 |
+
}
|
157 |
+
if ($i == 0) {
|
158 |
+
$packed = rtrim($destination, DS) . DS;
|
159 |
+
} else {
|
160 |
+
$packed = rtrim($destination, DS) . DS . '~tmp-'. microtime(true) . $archivers[$i-1] . '.' . $archivers[$i-1];
|
161 |
+
}
|
162 |
+
$source = $this->_getArchiver($archivers[$i])->unpack($source, $packed);
|
163 |
+
|
164 |
+
//var_dump($packed, $source);
|
165 |
+
|
166 |
+
if ($clearInterm && $interimSource && $i >= 0) {
|
167 |
+
unlink($interimSource);
|
168 |
+
}
|
169 |
+
$interimSource = $source;
|
170 |
+
}
|
171 |
+
return $source;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Extract one file from TAR (Tape Archiver).
|
176 |
+
*
|
177 |
+
* @param string $file
|
178 |
+
* @param string $source
|
179 |
+
* @param string $destination
|
180 |
+
* @return string Path to file
|
181 |
+
*/
|
182 |
+
public function extract($file, $source, $destination='.')
|
183 |
+
{
|
184 |
+
$tarFile = $this->unpack($source, $destination, true);
|
185 |
+
$resFile = $this->_getArchiver(self::TAPE_ARCHIVER)->extract($file, $tarFile, $destination);
|
186 |
+
if (!$this->isTar($source)) {
|
187 |
+
unlink($tarFile);
|
188 |
+
}
|
189 |
+
return $resFile;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Check file is archive.
|
194 |
+
*
|
195 |
+
* @param string $file
|
196 |
+
* @return boolean
|
197 |
+
*/
|
198 |
+
public function isArchive($file)
|
199 |
+
{
|
200 |
+
$archivers = $this->_getArchivers($file);
|
201 |
+
if (count($archivers)) {
|
202 |
+
return true;
|
203 |
+
}
|
204 |
+
return false;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Check file is TAR.
|
209 |
+
*
|
210 |
+
* @param mixed $file
|
211 |
+
* @return boolean
|
212 |
+
*/
|
213 |
+
public function isTar($file)
|
214 |
+
{
|
215 |
+
$archivers = $this->_getArchivers($file);
|
216 |
+
if (count($archivers)==1 && $archivers[0] == self::TAPE_ARCHIVER) {
|
217 |
+
return true;
|
218 |
+
}
|
219 |
+
return false;
|
220 |
+
}
|
221 |
+
|
222 |
+
}
|
downloader/lib/Mage/Archive/Abstract.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Abstract
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Write data to file. If file can't be opened,
|
38 |
+
*
|
39 |
+
* @param string $destination
|
40 |
+
* @param string $data
|
41 |
+
* @return boolean
|
42 |
+
*/
|
43 |
+
protected function _writeFile($destination, $data)
|
44 |
+
{
|
45 |
+
if(false === file_put_contents($destination, $data)) {
|
46 |
+
throw new Mage_Exception("Can't write to file: " . $destination);
|
47 |
+
}
|
48 |
+
return true;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Read data from file. If file can't be opened, throw to exception.
|
53 |
+
*
|
54 |
+
* @param string $source
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
protected function _readFile($source)
|
58 |
+
{
|
59 |
+
$data = '';
|
60 |
+
if (is_file($source) && is_readable($source)) {
|
61 |
+
$data = @file_get_contents($source);
|
62 |
+
if ($data === false) {
|
63 |
+
throw new Mage_Exception("Can't get contents from: " . $source);
|
64 |
+
}
|
65 |
+
}
|
66 |
+
return $data;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Get file name from source (URI) without last extension.
|
71 |
+
*
|
72 |
+
* @param string $source
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function getFilename($source, $withExtension=false)
|
76 |
+
{
|
77 |
+
$file = str_replace(dirname($source) . DS, '', $source);
|
78 |
+
if (!$withExtension) {
|
79 |
+
$file = substr($file, 0, strrpos($file, '.'));
|
80 |
+
}
|
81 |
+
return $file;
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
downloader/lib/Mage/Archive/Bz.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with bzip2 archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Bz extends Mage_Archive_Abstract implements Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Pack file by BZIP2 compressor.
|
39 |
+
*
|
40 |
+
* @param string $source
|
41 |
+
* @param string $destination
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public function pack($source, $destination)
|
45 |
+
{
|
46 |
+
$data = $this->_readFile($source);
|
47 |
+
$bzData = bzcompress($data, 9);
|
48 |
+
$this->_writeFile($destination, $bzData);
|
49 |
+
return $destination;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Unpack file by BZIP2 compressor.
|
54 |
+
*
|
55 |
+
* @param string $source
|
56 |
+
* @param string $destination
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function unpack($source, $destination)
|
60 |
+
{
|
61 |
+
$data = '';
|
62 |
+
$bzPointer = bzopen($source, 'r' );
|
63 |
+
if (empty($bzPointer)) {
|
64 |
+
throw new Exception('Can\'t open BZ archive : ' . $source);
|
65 |
+
}
|
66 |
+
while (!feof($bzPointer)) {
|
67 |
+
$data .= bzread($bzPointer, 131072);
|
68 |
+
}
|
69 |
+
bzclose($bzPointer);
|
70 |
+
if (is_dir($destination)) {
|
71 |
+
$file = $this->getFilename($source);
|
72 |
+
$destination = $destination . $file;
|
73 |
+
}
|
74 |
+
echo $destination;
|
75 |
+
$this->_writeFile($destination, $data);
|
76 |
+
return $destination;
|
77 |
+
}
|
78 |
+
|
79 |
+
}
|
downloader/lib/Mage/Archive/Gz.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with gz archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Gz extends Mage_Archive_Abstract implements Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Pack file by GZ compressor.
|
38 |
+
*
|
39 |
+
* @param string $source
|
40 |
+
* @param string $destination
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
public function pack($source, $destination)
|
44 |
+
{
|
45 |
+
$data = $this->_readFile($source);
|
46 |
+
$gzData = gzencode($data, 9);
|
47 |
+
$this->_writeFile($destination, $gzData);
|
48 |
+
return $destination;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Unpack file by GZ compressor.
|
53 |
+
*
|
54 |
+
* @param string $source
|
55 |
+
* @param string $destination
|
56 |
+
* @return string
|
57 |
+
*/
|
58 |
+
public function unpack($source, $destination)
|
59 |
+
{
|
60 |
+
$gzPointer = gzopen($source, 'r' );
|
61 |
+
if (empty($gzPointer)) {
|
62 |
+
throw new Mage_Exception('Can\'t open GZ archive : ' . $source);
|
63 |
+
}
|
64 |
+
$data = '';
|
65 |
+
while (!gzeof($gzPointer)) {
|
66 |
+
$data .= gzread($gzPointer, 131072);
|
67 |
+
}
|
68 |
+
gzclose($gzPointer);
|
69 |
+
if (is_dir($destination)) {
|
70 |
+
$file = $this->getFilename($source);
|
71 |
+
$destination = $destination . $file;
|
72 |
+
}
|
73 |
+
$this->_writeFile($destination, $data);
|
74 |
+
return $destination;
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
downloader/lib/Mage/Archive/Interface.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Interface for work with archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
interface Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Pack file or directory.
|
38 |
+
*
|
39 |
+
* @param string $source
|
40 |
+
* @param string $destination
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
public function pack($source, $destination);
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Unpack file or directory.
|
47 |
+
*
|
48 |
+
* @param string $source
|
49 |
+
* @param string $destination
|
50 |
+
* @return string
|
51 |
+
*/
|
52 |
+
public function unpack($source, $destination);
|
53 |
+
}
|
downloader/lib/Mage/Archive/Tar.php
ADDED
@@ -0,0 +1,372 @@
|
|
|
|
|