W3 Total Cache - Version 0.9.2

Version Description

  • Added support for nginx web server
  • Added support for CloudFlare
  • Added origin pull support for Amazon Cloudfront
  • Added Microsoft Azure Storage support for CDN
  • Added WinCache opcode cache support
  • Added additional minifier engines for HTML, CSS and JS including: HTMLtidy, CSStidy, Closure Compiler, YUI Compressor
  • Added Google Page Speed integration
  • Added support for @import processing
  • Added controls for page cache purging policy
  • Added auto mode for minify (not compatible with CDN)
  • Added support for set cookie domain setting
  • Added reliability improvements for Amazon Web Services
  • Added referrer group management for uniquely caching these cases
  • Added Amazon S3 bucket location selection control
  • Added support CNAMEs confguration support for Amazon Cloudfront
  • Added purge tool
  • Added support of custom wp-config.php location
  • Added cache busting support
  • Improved object caching performance when no plugins are active
  • Improved non-blocking JS embedding implementation
  • Improved reliability of CDN export operations
  • Improved implementation of headers for all cache engines
  • Improved minify help (recommendations) tool
  • Improved handling of .htaccess directive changes
  • Improved support of IIS web server
  • Improved varnish support
  • Fixed bugs with API changes with Rackspace Cloudfiles
  • Fixed bugs with origin push content delivery network methods
  • Fixed bug with HTML encoding
  • Fixed bug with emptying cache for various cache keys
  • Fixed bug with rejected CDN file support
  • Fixed bug with HTTPS mode in WP Admin
  • Fixed bug with relative document root for disk enhanced page cache
  • Fixed bug with trailing slash for disk enhanced page cache
  • Fixed bug with minify template group settings being lost upon upgrade
  • Fixed division by zero error
  • Fixed bug with object cache clones
  • Moved browser cache rules to site root instead of document root
Download this release

Release Info

Developer fredericktownes
Plugin Icon 128x128 W3 Total Cache
Version 0.9.2
Comparing to
See all releases

Code changes from version 0.9.1.3 to 0.9.2

Files changed (127) hide show
  1. inc/compat.php +41 -0
  2. inc/css/error.css +28 -28
  3. inc/css/lightbox.css +74 -16
  4. inc/css/options.css +119 -187
  5. inc/css/popup.css +207 -93
  6. inc/css/widget.css +64 -0
  7. inc/define.php +940 -668
  8. inc/error.phtml +1 -1
  9. inc/images/ps_bar.gif +0 -0
  10. inc/images/ps_grad.gif +0 -0
  11. inc/images/ps_scores.png +0 -0
  12. inc/js/lightbox.js +40 -86
  13. inc/js/options.js +433 -78
  14. inc/js/popup.js +55 -9
  15. inc/js/widget.js +11 -0
  16. inc/lightbox/cdn_s3_bucket_location.phtml +18 -0
  17. inc/lightbox/minify_recommendations.phtml +23 -20
  18. inc/lightbox/self_test.phtml +273 -332
  19. inc/lightbox/support_us.phtml +5 -3
  20. inc/lightbox/tweet.phtml +0 -26
  21. inc/mime/all.php +616 -616
  22. inc/options/browsercache.phtml +42 -28
  23. inc/options/cdn.phtml +72 -36
  24. inc/options/cdn/azure.phtml +47 -0
  25. inc/options/cdn/cf.phtml +6 -7
  26. inc/options/cdn/cf2.phtml +44 -0
  27. inc/options/cdn/cotendo.phtml +41 -0
  28. inc/options/cdn/ftp.phtml +4 -4
  29. inc/options/cdn/mirror.phtml +1 -1
  30. inc/options/cdn/netdna.phtml +5 -5
  31. inc/options/cdn/rscf.phtml +14 -5
  32. inc/options/cdn/s3.phtml +5 -6
  33. inc/options/common/header.phtml +20 -25
  34. inc/options/dbcache.phtml +10 -12
  35. inc/options/general.phtml +431 -274
  36. inc/options/install.phtml +26 -58
  37. inc/options/minify.phtml +170 -80
  38. inc/options/minify/ccjs.phtml +2 -0
  39. inc/options/minify/ccjs2.phtml +34 -0
  40. inc/options/minify/css.phtml +4 -0
  41. inc/options/minify/csstidy.phtml +34 -0
  42. inc/options/minify/csstidy2.phtml +71 -0
  43. inc/options/minify/html.phtml +2 -0
  44. inc/options/minify/htmltidy.phtml +4 -0
  45. inc/options/minify/htmltidy2.phtml +4 -0
  46. inc/options/minify/js.phtml +4 -0
  47. inc/options/minify/yuicss2.phtml +19 -0
  48. inc/options/minify/yuijs.phtml +6 -0
  49. inc/options/minify/yuijs2.phtml +19 -0
  50. inc/options/mobile.phtml +10 -9
  51. inc/options/objectcache.phtml +11 -13
  52. inc/options/pgcache.phtml +77 -47
  53. inc/options/referrer.phtml +87 -0
  54. inc/options/support.phtml +29 -21
  55. inc/options/support/bug_report.phtml +79 -83
  56. inc/options/support/email_support.phtml +79 -83
  57. inc/options/support/linux_config.phtml +67 -71
  58. inc/options/support/new_feature.phtml +44 -48
  59. inc/options/support/phone_support.phtml +79 -83
  60. inc/options/support/plugin_config.phtml +75 -79
  61. inc/options/support/theme_config.phtml +75 -79
  62. inc/options/support_payment.phtml +8 -6
  63. inc/options/support_select.phtml +6 -6
  64. inc/plugin.php +161 -0
  65. inc/popup/cdn_export_file.phtml +2 -2
  66. inc/popup/cdn_export_library.phtml +2 -2
  67. inc/popup/cdn_import_library.phtml +2 -2
  68. inc/popup/cdn_purge.phtml +47 -0
  69. inc/popup/cdn_queue.phtml +35 -4
  70. inc/popup/cdn_rename_domain.phtml +2 -2
  71. inc/popup/common/header.phtml +3 -3
  72. inc/popup/pagespeed_results.phtml +54 -0
  73. inc/widget/latest_control.phtml +4 -2
  74. inc/widget/pagespeed.phtml +24 -0
  75. inc/widget/pagespeed_control.phtml +8 -0
  76. lib/CF/cloudfiles.php +17 -7
  77. lib/CF/cloudfiles_http.php +18 -9
  78. lib/CSSTidy/class.csstidy.php +999 -0
  79. lib/CSSTidy/class.csstidy_optimise.php +809 -0
  80. lib/CSSTidy/class.csstidy_print.php +349 -0
  81. lib/CSSTidy/data.inc.php +473 -0
  82. lib/JSON.php +863 -0
  83. lib/Microsoft/Exception.php +43 -0
  84. lib/Microsoft/Http/Client.php +1444 -0
  85. lib/Microsoft/Http/Client/Adapter/Curl.php +498 -0
  86. lib/Microsoft/Http/Client/Adapter/Exception.php +38 -0
  87. lib/Microsoft/Http/Client/Adapter/Interface.php +78 -0
  88. lib/Microsoft/Http/Client/Adapter/Proxy.php +267 -0
  89. lib/Microsoft/Http/Client/Adapter/Socket.php +531 -0
  90. lib/Microsoft/Http/Client/Adapter/Stream.php +46 -0
  91. lib/Microsoft/Http/Client/Exception.php +36 -0
  92. lib/Microsoft/Http/Cookie.php +408 -0
  93. lib/Microsoft/Http/CookieJar.php +403 -0
  94. lib/Microsoft/Http/Exception.php +48 -0
  95. lib/Microsoft/Http/Response.php +664 -0
  96. lib/Microsoft/Http/Response/Stream.php +235 -0
  97. lib/Microsoft/Uri.php +188 -0
  98. lib/Microsoft/Uri/Exception.php +37 -0
  99. lib/Microsoft/Uri/Http.php +761 -0
  100. lib/Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php +257 -0
  101. lib/Microsoft/WindowsAzure/Credentials/Exception.php +48 -0
  102. lib/Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php +320 -0
  103. lib/Microsoft/WindowsAzure/Credentials/SharedKey.php +200 -0
  104. lib/Microsoft/WindowsAzure/Credentials/SharedKeyLite.php +179 -0
  105. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationDataSources.php +104 -0
  106. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationDiagnosticInfrastructureLogs.php +80 -0
  107. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationDirectories.php +103 -0
  108. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationInstance.php +234 -0
  109. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationLogs.php +80 -0
  110. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php +84 -0
  111. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationPerformanceCounters.php +102 -0
  112. lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationWindowsEventLog.php +104 -0
  113. lib/Microsoft/WindowsAzure/Diagnostics/DirectoryConfigurationSubscription.php +75 -0
  114. lib/Microsoft/WindowsAzure/Diagnostics/Exception.php +51 -0
  115. lib/Microsoft/WindowsAzure/Diagnostics/LogLevel.php +52 -0
  116. lib/Microsoft/WindowsAzure/Diagnostics/Manager.php +225 -0
  117. lib/Microsoft/WindowsAzure/Diagnostics/PerformanceCounterSubscription.php +72 -0
  118. lib/Microsoft/WindowsAzure/Exception.php +48 -0
  119. lib/Microsoft/WindowsAzure/RetryPolicy/Exception.php +49 -0
  120. lib/Microsoft/WindowsAzure/RetryPolicy/NoRetry.php +71 -0
  121. lib/Microsoft/WindowsAzure/RetryPolicy/RetryN.php +105 -0
  122. lib/Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php +90 -0
  123. lib/Microsoft/WindowsAzure/SessionHandler.php +230 -0
  124. lib/Microsoft/WindowsAzure/Storage.php +586 -0
  125. lib/Microsoft/WindowsAzure/Storage/Batch.php +261 -0
  126. lib/Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php +210 -0
  127. lib/Microsoft/WindowsAzure/Storage/Blob.php +1748 -0
inc/compat.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!function_exists('json_encode')) {
4
+ function json_encode($string) {
5
+ global $json;
6
+
7
+ if (!is_a($json, 'Services_JSON')) {
8
+ require_once W3TC_LIB_DIR . '/JSON.php';
9
+ $json = new Services_JSON();
10
+ }
11
+
12
+ return $json->encodeUnsafe($string);
13
+ }
14
+ }
15
+
16
+ if (!function_exists('json_decode')) {
17
+ function json_decode($string, $assoc_array = false) {
18
+ global $json;
19
+
20
+ if (!is_a($json, 'Services_JSON')) {
21
+ require_once W3TC_LIB_W3_DIR . '/JSON.php';
22
+ $json = new Services_JSON();
23
+ }
24
+
25
+ $res = $json->decode($string);
26
+
27
+ if ($assoc_array) {
28
+ $res = _json_decode_object_helper($res);
29
+ }
30
+
31
+ return $res;
32
+ }
33
+
34
+ function _json_decode_object_helper($data) {
35
+ if (is_object($data)) {
36
+ $data = get_object_vars($data);
37
+ }
38
+
39
+ return (is_array($data) ? array_map(__FUNCTION__, $data) : $data);
40
+ }
41
+ }
inc/css/error.css CHANGED
@@ -1,49 +1,49 @@
1
  * {
2
- margin: 0;
3
- padding: 0;
4
- color: #464646;
5
  }
6
 
7
- html,body {
8
- height: 100%;
9
  }
10
 
11
  body {
12
- line-height: 1.4em;
13
  }
14
 
15
- body,input {
16
- font-family: "Lucida Grande", Verdana, Arial;
17
- font-size: 13px;
18
  }
19
 
20
  a {
21
- color: #21759B;
22
  }
23
 
24
  a:hover {
25
- color: #D54E21;
26
  }
27
 
28
- .button,input[type="button"],input[type="submit"] {
29
- font-size: 11px;
30
- line-height: 16px;
31
- background: #f2f2f2 url(../../../../../wp-admin/images/white-grad.png) repeat-x scroll left top;
32
- border: 1px solid #bbb;
33
- color: #464646;
34
- text-shadow: 0 1px 0 #fff;
35
- cursor: pointer;
36
- padding: 2px 8px;
37
- border-radius: 11px;
38
- -webkit-border-radius: 11px;
39
- -moz-border-radius: 11px;
40
  }
41
 
42
- .button:hover,input[type="button"]:hover,input[type="submit"]:hover {
43
- border-color: #666;
44
- color: #000;
45
  }
46
 
47
- .button:active,input[type="button"]:active,input[type="submit"]:active {
48
- background: #f2f2f2 url(../../../../../images/white-grad-active.png) repeat-x scroll left top;
49
  }
1
  * {
2
+ margin: 0;
3
+ padding: 0;
4
+ color: #464646;
5
  }
6
 
7
+ html, body {
8
+ height: 100%;
9
  }
10
 
11
  body {
12
+ line-height: 1.4em;
13
  }
14
 
15
+ body, input {
16
+ font-family: "Lucida Grande", Verdana, Arial;
17
+ font-size: 13px;
18
  }
19
 
20
  a {
21
+ color: #21759B;
22
  }
23
 
24
  a:hover {
25
+ color: #D54E21;
26
  }
27
 
28
+ .button, input[type="button"], input[type="submit"] {
29
+ font-size: 11px;
30
+ line-height: 16px;
31
+ background: #f2f2f2 url(../../../../../wp-admin/images/white-grad.png) repeat-x scroll left top;
32
+ border: 1px solid #bbb;
33
+ color: #464646;
34
+ text-shadow: 0 1px 0 #fff;
35
+ cursor: pointer;
36
+ padding: 2px 8px;
37
+ border-radius: 11px;
38
+ -webkit-border-radius: 11px;
39
+ -moz-border-radius: 11px;
40
  }
41
 
42
+ .button:hover, input[type="button"]:hover, input[type="submit"]:hover {
43
+ border-color: #666;
44
+ color: #000;
45
  }
46
 
47
+ .button:active, input[type="button"]:active, input[type="submit"]:active {
48
+ background: #f2f2f2 url(../../../../../images/white-grad-active.png) repeat-x scroll left top;
49
  }
inc/css/lightbox.css CHANGED
@@ -1,27 +1,85 @@
1
  #overlay {
2
- background: #666;
3
  }
4
 
5
  .lightbox {
6
- position: absolute;
7
- background: #fdfdfd;
8
- padding: 10px 20px;
9
- border: 1px solid #bbb;
10
- border-radius: 11px;
11
- -webkit-border-radius: 11px;
12
- -moz-border-radius: 11px;
13
  }
14
 
15
  .lightbox-close {
16
- cursor: pointer;
17
- position: absolute;
18
- text-decoration: underline;
19
- top: 25px;
20
- right: 20px;
21
  }
22
 
23
  .lightbox-loader {
24
- background-image: url(../images/loader.gif);
25
- background-position: center center;
26
- background-repeat: no-repeat;
27
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #overlay {
2
+ background: #666;
3
  }
4
 
5
  .lightbox {
6
+ position: absolute;
7
+ background: #fdfdfd;
8
+ padding: 10px 20px;
9
+ border: 1px solid #bbb;
10
+ border-radius: 11px;
11
+ -webkit-border-radius: 11px;
12
+ -moz-border-radius: 11px;
13
  }
14
 
15
  .lightbox-close {
16
+ cursor: pointer;
17
+ position: absolute;
18
+ text-decoration: underline;
19
+ top: 25px;
20
+ right: 20px;
21
  }
22
 
23
  .lightbox-loader {
24
+ background-image: url(../images/loader.gif);
25
+ background-position: center center;
26
+ background-repeat: no-repeat;
27
  }
28
+
29
+ #recom_container {
30
+ overflow: auto;
31
+ height: 475px;
32
+ }
33
+
34
+ .minify-files li {
35
+ padding: 2px;
36
+ cursor: ns-resize;
37
+ list-style: none;
38
+ }
39
+
40
+ .minify-files li:hover {
41
+ background: #f9f9f9;
42
+ }
43
+
44
+ .minify-files th, .minify-files td {
45
+ line-height: normal;
46
+ border: 0;
47
+ padding: 0;
48
+ margin: 0;
49
+ }
50
+
51
+ .minify-files th {
52
+ width: auto;
53
+ color: #aaa !important;
54
+ font-size: 10px;
55
+ font-weight: normal;
56
+ text-align: left;
57
+ }
58
+
59
+ .minify-files td {
60
+ font-size: 13px;
61
+ }
62
+
63
+ th.minify-files-add, td.minify-files-add {
64
+ width: 40px;
65
+ text-align: center;
66
+ }
67
+
68
+ .minify-files-exists input, .minify-files-exists select {
69
+ color: red;
70
+ }
71
+
72
+ #w3tc-self-test {
73
+ height: 490px;
74
+ overflow: auto;
75
+ }
76
+
77
+ #w3tc-self-test ul {
78
+ list-style: none;
79
+ }
80
+
81
+ .w3tc-self-test-hint {
82
+ font-size: 0.8em;
83
+ font-style: italic;
84
+ color: #999;
85
+ }
inc/css/options.css CHANGED
@@ -1,320 +1,252 @@
1
  #icon-w3tc-logo {
2
- background: url(../images/logo.png) no-repeat;
3
- float: left;
4
- height: 36px;
5
- width: 36px
 
 
 
 
6
  }
7
 
8
  .w3tc-enabled {
9
- color: #090;
10
- font-weight: 700
11
  }
12
 
13
  .w3tc-disabled {
14
- color: #f00;
15
- font-weight: 700
16
  }
17
 
18
  .w3tc-empty {
19
- font-weight: 700;
20
- font-style: italic
21
  }
22
 
23
  .w3tc-success {
24
- background: #bfb
25
  }
26
 
27
  .w3tc-error {
28
- background: #f99
29
  }
30
 
31
  .w3tc-status {
32
- padding: 5px
33
- }
34
-
35
- .w3tc-test-ok,.w3tc-test-warn,.w3tc-test-error {
36
- font-weight: bold;
37
- }
38
-
39
- .w3tc-test-ok {
40
- color: #090;
41
- }
42
-
43
- .w3tc-test-warn {
44
- color: #f90;
45
- }
46
-
47
- .w3tc-test-error {
48
- color: #f00;
49
  }
50
 
51
  #w3tc-help ul {
52
- float: left;
53
- width: 29%;
54
- list-style-type: disc;
55
- margin: 1em 2% 1em 2%;
56
  }
57
 
58
  #w3tc-help li {
59
- margin: 0;
60
  }
61
 
62
  #w3tc-help a {
63
- text-decoration: none;
64
  }
65
 
66
  #w3tc-help a:hover {
67
- text-decoration: underline;
68
- }
69
-
70
- #w3tc-nav select {
71
- background: #f9f9f9 !important;
72
- border: 0;
73
- color: #333;
74
- font-size: 1em;
75
- font-weight: bold;
76
- }
77
-
78
- #w3tc-nav optgroup {
79
- background: #fff;
80
- font-style: normal;
81
- padding: 3px;
82
- }
83
-
84
- #w3tc-nav option {
85
- background: #fff;
86
  }
87
 
88
  #w3tc acronym {
89
- border-bottom: 1px dotted #666
90
  }
91
 
92
  #w3tc ul {
93
- list-style-type: disc;
94
- list-style-position: inside
95
  }
96
 
97
  #w3tc blockquote {
98
- font-style: italic;
99
  }
100
 
101
  #w3tc blockquote cite {
102
- font-style: 400
103
  }
104
 
105
  #w3tc optgroup {
106
- font-style: normal;
107
  }
108
 
109
  #w3tc optgroup option {
110
- text-indent: 20px;
111
  }
112
 
113
  #w3tc h2 span {
114
- font-size: 0.6em;
115
- font-style: normal;
116
- text-shadow: none;
117
  }
118
 
119
  #w3tc h5 {
120
- margin: 0
121
  }
122
 
123
  #w3tc hr {
124
- clear: both;
125
- margin-top: 10px
126
  }
127
 
128
  #w3tc ul {
129
- list-style-position: inside
130
  }
131
 
132
- #w3tc #toc a,#qa a {
133
- text-decoration: none
134
  }
135
 
136
- #w3tc #toc a:hover,#qa a:hover {
137
- text-decoration: underline
138
  }
139
 
140
  #w3tc #toc ul {
141
- margin: 0;
142
- padding: 0
143
  }
144
 
145
  #w3tc #toc li {
146
- margin: 0;
147
- padding: 0
148
  }
149
 
150
  #w3tc #toc li.col {
151
- float: left;
152
- list-style: none;
153
- margin: 0 30px 0 0;
154
- width: 30%
155
  }
156
 
157
  #w3tc #toc li.col ul {
158
- margin-left: 20px
159
  }
160
 
161
  #w3tc #toc li.col ul li {
162
- list-style: disc
163
  }
164
 
165
  #w3tc #qa {
166
- clear: both;
167
- padding: 10px;
168
  }
169
 
170
- #w3tc #qa,#w3tc #about,#w3tc #install {
171
- width: 760px;
172
  }
173
 
174
  #w3tc fieldset {
175
- margin: 1em 0;
176
- background: #fdfdfd;
177
- padding: 0 1em 1em 1em;
178
- border: 1px solid #bbb;
179
- border-radius: 11px;
180
- -webkit-border-radius: 11px;
181
- -moz-border-radius: 11px;
182
  }
183
 
184
  #w3tc fieldset .submit {
185
- margin: 1em 0 0 0;
186
- padding: 0;
187
  }
188
 
189
  #w3tc fieldset legend {
190
- color: #999;
191
- padding: 0 5px;
192
- font-weight: bold;
193
  }
194
 
195
  #w3tc fieldset legend a:hover {
196
- text-decoration: none;
197
  }
198
 
199
  #w3tc pre.code {
200
- color: #000;
201
- margin: 1em 0;
202
- overflow: auto;
203
- background: #eee;
204
- padding: 12px 15px;
205
- border: 1px solid #ccc;
206
  }
207
 
208
  #w3tc pre.console {
209
- color: #ccc;
210
- margin: 1em 0;
211
- overflow: auto;
212
- background: #000;
213
- padding: 12px 15px;
214
- border: 1px solid #ccc;
215
  }
216
 
217
  #w3tc-cdn-general th {
218
- width: 400px;
219
  }
220
 
221
  #cdn_cnames li {
222
- padding: 5px;
223
- cursor: ns-resize;
224
  }
225
 
226
  #cdn_cnames li:hover {
227
- background: #f9f9f9;
228
  }
229
 
230
  #cdn_cnames li span {
231
- color: #999;
232
  }
233
 
234
- #mobile_groups li {
235
- cursor: ns-resize;
236
- list-style: none;
237
- background: #f9f9f9;
238
- margin-bottom: 1em;
239
- border-radius: 8px;
240
- -webkit-border-radius: 8px;
241
- -moz-border-radius: 8px;
 
242
  }
243
 
244
- #mobile_groups li:hover {
245
- background: #f3f3f3;
 
246
  }
247
 
248
- #mobile_groups li table {
249
- margin: 0;
 
250
  }
251
 
252
- .mobile_group {
253
- font-weight: bold;
254
- }
255
-
256
- #recom_container,#self_test_container {
257
- overflow: auto;
258
- }
259
-
260
- #self_test_container fieldset {
261
- width: 70%;
262
- }
263
-
264
- .monospace {
265
- font-family: monospace;
266
  }
267
 
268
  .w3tc-rules {
269
- display: none;
270
- margin: 1em 0;
271
- padding: 0;
272
- background: none;
273
- }
274
-
275
- .minify-files li {
276
- padding: 2px;
277
- cursor: ns-resize;
278
- list-style: none;
279
- }
280
-
281
- .minify-files li:hover {
282
- background: #f9f9f9;
283
- }
284
-
285
- .minify-files th,.minify-files td {
286
- line-height: normal;
287
- border: 0;
288
- padding: 0;
289
- margin: 0;
290
- }
291
-
292
- .minify-files th {
293
- width: auto;
294
- color: #aaa !important;
295
- font-size: 10px;
296
- font-weight: normal;
297
- text-align: left;
298
  }
299
 
300
- .minify-files td {
301
- font-size: 13px;
 
 
 
 
 
302
  }
303
 
304
- th.minify-files-add,td.minify-files-add {
305
- width: 40px;
306
- text-align: center;
307
  }
308
 
309
- .minify-files-exists input,.minify-files-exists select {
310
- color: red;
311
  }
312
-
313
- #support_loading {
314
- height: 32px;
315
- background: url(../images/loader.gif) left center no-repeat;
316
- padding-left: 38px;
317
- line-height: 32px;
318
- margin: 1em 0;
319
- font-weight: bold;
320
- }
1
  #icon-w3tc-logo {
2
+ background: url(../images/logo.png) no-repeat;
3
+ float: left;
4
+ height: 36px;
5
+ width: 36px
6
+ }
7
+
8
+ .w3tc-options-menu-selected {
9
+ font-weight: 700
10
  }
11
 
12
  .w3tc-enabled {
13
+ color: #090;
14
+ font-weight: 700
15
  }
16
 
17
  .w3tc-disabled {
18
+ color: #f00;
19
+ font-weight: 700
20
  }
21
 
22
  .w3tc-empty {
23
+ font-weight: 700;
24
+ font-style: italic
25
  }
26
 
27
  .w3tc-success {
28
+ background: #bfb
29
  }
30
 
31
  .w3tc-error {
32
+ background: #f99
33
  }
34
 
35
  .w3tc-status {
36
+ padding: 5px
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
 
39
  #w3tc-help ul {
40
+ float: left;
41
+ width: 29%;
42
+ list-style-type: disc;
43
+ margin: 1em 2% 1em 2%;
44
  }
45
 
46
  #w3tc-help li {
47
+ margin: 0;
48
  }
49
 
50
  #w3tc-help a {
51
+ text-decoration: none;
52
  }
53
 
54
  #w3tc-help a:hover {
55
+ text-decoration: underline;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
 
58
  #w3tc acronym {
59
+ border-bottom: 1px dotted #666
60
  }
61
 
62
  #w3tc ul {
63
+ list-style-type: disc;
64
+ list-style-position: inside
65
  }
66
 
67
  #w3tc blockquote {
68
+ font-style: italic;
69
  }
70
 
71
  #w3tc blockquote cite {
72
+ font-weight: 400;
73
  }
74
 
75
  #w3tc optgroup {
76
+ font-style: normal;
77
  }
78
 
79
  #w3tc optgroup option {
80
+ text-indent: 20px;
81
  }
82
 
83
  #w3tc h2 span {
84
+ font-size: 0.6em;
85
+ font-style: normal;
86
+ text-shadow: none;
87
  }
88
 
89
  #w3tc h5 {
90
+ margin: 0
91
  }
92
 
93
  #w3tc hr {
94
+ clear: both;
95
+ margin-top: 10px
96
  }
97
 
98
  #w3tc ul {
99
+ list-style-position: inside
100
  }
101
 
102
+ #w3tc #toc a, #qa a {
103
+ text-decoration: none
104
  }
105
 
106
+ #w3tc #toc a:hover, #qa a:hover {
107
+ text-decoration: underline
108
  }
109
 
110
  #w3tc #toc ul {
111
+ margin: 0;
112
+ padding: 0
113
  }
114
 
115
  #w3tc #toc li {
116
+ margin: 0;
117
+ padding: 0
118
  }
119
 
120
  #w3tc #toc li.col {
121
+ float: left;
122
+ list-style: none;
123
+ margin: 0 30px 0 0;
124
+ width: 30%
125
  }
126
 
127
  #w3tc #toc li.col ul {
128
+ margin-left: 20px
129
  }
130
 
131
  #w3tc #toc li.col ul li {
132
+ list-style: disc
133
  }
134
 
135
  #w3tc #qa {
136
+ clear: both;
137
+ padding: 10px;
138
  }
139
 
140
+ #w3tc #qa, #w3tc #about, #w3tc #install {
141
+ width: 760px;
142
  }
143
 
144
  #w3tc fieldset {
145
+ margin: 1em 0;
146
+ background: #fdfdfd;
147
+ padding: 0 1em;
148
+ border: 1px solid #bbb;
149
+ border-radius: 11px;
150
+ -webkit-border-radius: 11px;
151
+ -moz-border-radius: 11px;
152
  }
153
 
154
  #w3tc fieldset .submit {
155
+ margin: 1em 0 0 0;
156
+ padding: 0;
157
  }
158
 
159
  #w3tc fieldset legend {
160
+ color: #999;
161
+ padding: 0 5px;
162
+ font-weight: bold;
163
  }
164
 
165
  #w3tc fieldset legend a:hover {
166
+ text-decoration: none;
167
  }
168
 
169
  #w3tc pre.code {
170
+ color: #000;
171
+ margin: 1em 0;
172
+ overflow: auto;
173
+ background: #eee;
174
+ padding: 12px 15px;
175
+ border: 1px solid #ccc;
176
  }
177
 
178
  #w3tc pre.console {
179
+ color: #ccc;
180
+ margin: 1em 0;
181
+ overflow: auto;
182
+ background: #000;
183
+ padding: 12px 15px;
184
+ border: 1px solid #ccc;
185
  }
186
 
187
  #w3tc-cdn-general th {
188
+ width: 400px;
189
  }
190
 
191
  #cdn_cnames li {
192
+ padding: 5px;
193
+ cursor: ns-resize;
194
  }
195
 
196
  #cdn_cnames li:hover {
197
+ background: #f9f9f9;
198
  }
199
 
200
  #cdn_cnames li span {
201
+ color: #999;
202
  }
203
 
204
+ #mobile_groups li,
205
+ #referrer_groups li {
206
+ cursor: ns-resize;
207
+ list-style: none;
208
+ background: #f9f9f9;
209
+ margin-bottom: 1em;
210
+ border-radius: 8px;
211
+ -webkit-border-radius: 8px;
212
+ -moz-border-radius: 8px;
213
  }
214
 
215
+ #mobile_groups li:hover,
216
+ #referrer_groups li:hover {
217
+ background: #f3f3f3;
218
  }
219
 
220
+ #mobile_groups li table,
221
+ #referrer_groups li table {
222
+ margin: 0;
223
  }
224
 
225
+ .mobile_group,
226
+ .referrer_group {
227
+ font-weight: bold;
 
 
 
 
 
 
 
 
 
 
 
228
  }
229
 
230
  .w3tc-rules {
231
+ display: none;
232
+ margin: 1em 0;
233
+ padding: 0;
234
+ background: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
 
237
+ #support_loading {
238
+ height: 32px;
239
+ background: url(../images/loader.gif) left center no-repeat;
240
+ padding-left: 38px;
241
+ line-height: 32px;
242
+ margin: 1em 0;
243
+ font-weight: bold;
244
  }
245
 
246
+ #w3tc .postbox .inside {
247
+ padding: 0 10px;
 
248
  }
249
 
250
+ #w3tc .postbox .hndle {
251
+ cursor: auto;
252
  }
 
 
 
 
 
 
 
 
 
inc/css/popup.css CHANGED
@@ -1,177 +1,291 @@
1
  * {
2
- margin: 0;
3
- padding: 0;
4
- color: #464646;
5
  }
6
 
7
- html,body {
8
- height: 100%;
9
  }
10
 
11
  body {
12
- line-height: 1em;
13
- background: #f9f9f9;
14
- padding: 0;
15
- margin: 0;
16
  }
17
 
18
- body,td,textarea,input,select {
19
- font-family: "Lucida Grande", Verdana, Arial;
20
- font-size: 13px;
21
  }
22
 
23
  p {
24
- margin: 1em 0;
25
  }
26
 
27
  h1 {
28
- font-family: Georgia, "Times New Roman", "Bitstream Charter";
29
- font-size: 24px;
30
- font-style: italic;
31
- font-weight: 400;
32
- line-height: 35px;
33
- margin: 0 0 0.8em 0;
34
- text-shadow: 0 1px 0 #fff;
 
 
 
 
 
 
 
 
35
  }
36
 
37
  a {
38
- color: #21759B;
39
  }
40
 
41
  a:hover {
42
- color: #D54E21;
43
  }
44
 
45
  #content {
46
- padding: 10px 50px;
47
  }
48
 
49
  .clear {
50
- clear: both;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
 
53
- .button,input[type="button"],input[type="submit"] {
54
- font-size: 11px;
55
- line-height: 16px;
56
- background: #f2f2f2 url(../../../../../wp-admin/images/white-grad.png) repeat-x scroll left top;
57
- border: 1px solid #bbb;
58
- color: #464646;
59
- text-shadow: 0 1px 0 #fff;
60
- cursor: pointer;
61
- padding: 2px 8px;
62
- border-radius: 11px;
63
- -webkit-border-radius: 11px;
64
- -moz-border-radius: 11px;
65
  }
66
 
67
- .button:hover,input[type="button"]:hover,input[type="submit"]:hover {
68
- border-color: #666;
69
- color: #000;
70
  }
71
 
72
- .button:active,input[type="button"]:active,input[type="submit"]:active {
73
- background: #F2F2F2 url(../../../../../wp-admin/images/white-grad-active.png) repeat-x scroll left top;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
75
 
76
  .progress {
77
- background: #fff;
78
- border: 1px solid #464646;
79
- padding: 1px;
80
- margin: 1em 0;
81
- position: relative;
82
  }
83
 
84
  .progress-value {
85
- position: absolute;
86
- line-height: 30px;
87
- font-size: 16px;
88
- font-weight: 700;
89
- color: #000;
90
- text-align: center;
91
- width: 100%;
92
  }
93
 
94
  .progress-bar {
95
- float: left;
96
- width: 0;
97
- height: 30px;
98
- background: #fc2;
99
  }
100
 
101
  .log {
102
- border: 1px solid #464646;
103
- height: 279px;
104
- overflow: auto;
105
  }
106
 
107
  .log div {
108
- padding: 3px;
109
- border-bottom: 1px solid #464646;
110
  }
111
 
112
  .log-success {
113
- background: #bfb;
114
  }
115
 
116
  .log-error {
117
- background: #f99;
118
  }
119
 
120
  .empty {
121
- font-weight: 700;
122
- font-style: italic;
123
  }
124
 
125
  .table {
126
- width: 100%;
127
- border-collapse: collapse;
128
  }
129
 
130
- .table td,th {
131
- border: 1px solid #ccc;
132
- padding: 3px 2px;
133
  }
134
 
135
  .table th {
136
- background: #eee;
137
  }
138
 
139
  .queue td {
140
- font-size: 10px;
141
  }
142
 
143
- .updated,.error {
144
- -moz-border-radius-bottomleft: 3px;
145
- -moz-border-radius-bottomright: 3px;
146
- -moz-border-radius-topleft: 3px;
147
- -moz-border-radius-topright: 3px;
148
- border-style: solid;
149
- border-width: 1px;
150
- padding: 0 0.6em;
151
- margin: 0.5em 0;
152
  }
153
 
154
  .updated {
155
- background: #ffffe0;
156
- border-color: #e6db55;
157
  }
158
 
159
  .error {
160
- background-color: #ffebe8;
161
- border-color: #cc0000;
162
  }
163
 
164
- .updated p,.error p {
165
- line-height: 1;
166
- margin: 0.5em 0;
167
- padding: 2px;
168
  }
169
 
170
  .tab-selected {
171
- font-weight: 700;
172
  }
173
 
174
  .rules {
175
- width: 100%;
176
- font-size: 9px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  }
1
  * {
2
+ margin: 0;
3
+ padding: 0;
4
+ color: #464646;
5
  }
6
 
7
+ html, body {
8
+ height: 100%;
9
  }
10
 
11
  body {
12
+ line-height: 1em;
13
+ background: #f9f9f9;
14
+ padding: 0;
15
+ margin: 0;
16
  }
17
 
18
+ body, td, textarea, input, select {
19
+ font-family: "Lucida Grande", Verdana, Arial;
20
+ font-size: 13px;
21
  }
22
 
23
  p {
24
+ margin: 1em 0;
25
  }
26
 
27
  h1 {
28
+ font-family: Georgia, "Times New Roman", "Bitstream Charter";
29
+ font-size: 24px;
30
+ font-style: italic;
31
+ font-weight: 400;
32
+ line-height: 35px;
33
+ margin: 0 0 0.8em 0;
34
+ text-shadow: 0 1px 0 #fff;
35
+ }
36
+
37
+ ul {
38
+ list-style: none;
39
+ }
40
+
41
+ li {
42
+ margin: 1em 0;
43
  }
44
 
45
  a {
46
+ color: #21759B;
47
  }
48
 
49
  a:hover {
50
+ color: #D54E21;
51
  }
52
 
53
  #content {
54
+ padding: 10px 50px;
55
  }
56
 
57
  .clear {
58
+ clear: both;
59
+ }
60
+
61
+ .button, input[type="button"], input[type="submit"] {
62
+ font-size: 11px;
63
+ line-height: 16px;
64
+ background: #f2f2f2 url(../../../../../wp-admin/images/white-grad.png) repeat-x scroll left top;
65
+ border: 1px solid #bbb;
66
+ color: #464646;
67
+ text-shadow: 0 1px 0 #fff;
68
+ cursor: pointer;
69
+ padding: 2px 8px;
70
+ border-radius: 11px;
71
+ -webkit-border-radius: 11px;
72
+ -moz-border-radius: 11px;
73
  }
74
 
75
+ .button:hover, input[type="button"]:hover, input[type="submit"]:hover {
76
+ border-color: #666;
77
+ color: #000;
 
 
 
 
 
 
 
 
 
78
  }
79
 
80
+ .button:active, input[type="button"]:active, input[type="submit"]:active {
81
+ background: #F2F2F2 url(../../../../../wp-admin/images/white-grad-active.png) repeat-x scroll left top;
 
82
  }
83
 
84
+ input.button-primary {
85
+ background: url(../../../../../wp-admin/images/button-grad.png) repeat-x scroll left top #21759B;
86
+ border-color: #298CBA;
87
+ color: #FFFFFF;
88
+ font-weight: bold;
89
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
90
+ }
91
+
92
+ input.button-primary:active, button.button-primary:active, a.button-primary:active {
93
+ background: url(../../../../../images/button-grad-active.png) repeat-x scroll left top #21759B;
94
+ color: #EAF2FA;
95
+ }
96
+
97
+ input.button-primary:hover, button.button-primary:hover, a.button-primary:hover, a.button-primary:focus, a.button-primary:active {
98
+ border-color: #13455B;
99
+ color: #EAF2FA;
100
  }
101
 
102
  .progress {
103
+ background: #fff;
104
+ border: 1px solid #464646;
105
+ padding: 1px;
106
+ margin: 1em 0;
107
+ position: relative;
108
  }
109
 
110
  .progress-value {
111
+ position: absolute;
112
+ line-height: 30px;
113
+ font-size: 16px;
114
+ font-weight: 700;
115
+ color: #000;
116
+ text-align: center;
117
+ width: 100%;
118
  }
119
 
120
  .progress-bar {
121
+ float: left;
122
+ width: 0;
123
+ height: 30px;
124
+ background: #fc2;
125
  }
126
 
127
  .log {
128
+ border: 1px solid #464646;
129
+ height: 279px;
130
+ overflow: auto;
131
  }
132
 
133
  .log div {
134
+ padding: 3px;
135
+ border-bottom: 1px solid #464646;
136
  }
137
 
138
  .log-success {
139
+ background: #bfb;
140
  }
141
 
142
  .log-error {
143
+ background: #f99;
144
  }
145
 
146
  .empty {
147
+ font-weight: 700;
148
+ font-style: italic;
149
  }
150
 
151
  .table {
152
+ width: 100%;
153
+ border-collapse: collapse;
154
  }
155
 
156
+ .table td, th {
157
+ border: 1px solid #ccc;
158
+ padding: 3px 2px;
159
  }
160
 
161
  .table th {
162
+ background: #eee;
163
  }
164
 
165
  .queue td {
166
+ font-size: 10px;
167
  }
168
 
169
+ .updated, .error {
170
+ -moz-border-radius: 3px;
171
+ -webkit-border-radius: 3px;
172
+ border-radius: 3px;
173
+ border-style: solid;
174
+ border-width: 1px;
175
+ padding: 0 0.6em;
176
+ margin: 0.5em 0;
 
177
  }
178
 
179
  .updated {
180
+ background: #ffffe0;
181
+ border-color: #e6db55;
182
  }
183
 
184
  .error {
185
+ background-color: #ffebe8;
186
+ border-color: #cc0000;
187
  }
188
 
189
+ .updated p, .error p {
190
+ line-height: 1;
191
+ margin: 0.5em 0;
192
+ padding: 2px;
193
  }
194
 
195
  .tab-selected {
196
+ font-weight: 700;
197
  }
198
 
199
  .rules {
200
+ width: 100%;
201
+ font-size: 9px;
202
+ }
203
+
204
+ .ps-rules {
205
+ margin: 1em 0;
206
+ background: #fff url(../images/ps_bar.gif) repeat-y;
207
+ }
208
+
209
+ .ps-rules a {
210
+ color: #00f;
211
+ text-decoration: none;
212
+ }
213
+
214
+ .ps-rules li,
215
+ .ps-rules p {
216
+ margin: 0;
217
+ }
218
+
219
+ .ps-rule {
220
+ clear: left;
221
+ }
222
+
223
+ .ps-rule {
224
+ line-height: 20px;
225
+ }
226
+
227
+ .ps-rule:hover {
228
+ background: #eee url(../images/ps_bar.gif) repeat-y;
229
+ }
230
+
231
+ .ps-icon {
232
+ width: 31px;
233
+ height: 20px;
234
+ position: relative;
235
+ float: left;
236
+ }
237
+
238
+ .ps-icon div {
239
+ display: block;
240
+ background: url(../images/ps_scores.png);
241
+ width: 14px;
242
+ height: 14px;
243
+ position: relative;
244
+ top: 3px;
245
+ left: 8px;
246
+ }
247
+
248
+ .ps-priority-high .ps-icon div {
249
+ background-position: 0;
250
+ }
251
+
252
+ .ps-priority-medium .ps-icon div {
253
+ background-position: -14px;
254
+ }
255
+
256
+ .ps-priority-low .ps-icon div {
257
+ background-position: -28px;
258
+ }
259
+
260
+ .ps-expand {
261
+ float: left;
262
+ width: 30px;
263
+ height: 20px;
264
+ text-align: center;
265
+ }
266
+
267
+ .ps-expand a {
268
+ color: #66d;
269
+ }
270
+
271
+ .ps-expander {
272
+ display: none;
273
+ background: #fff url(../images/ps_grad.gif) repeat-x;
274
+ margin-left: 31px;
275
+ padding: 10px 0 10px 30px;
276
+ }
277
+
278
+ .ps-blocks {
279
+ }
280
+
281
+ .ps-block p {
282
+ margin-bottom: 1em;
283
+ }
284
+
285
+ .ps-urls {
286
+ margin-bottom: 1em;
287
+ }
288
+
289
+ .ps-url {
290
+ list-style: disc inside;
291
  }
inc/css/widget.css ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .w3tc-widget-ps-rules {
2
+ margin: 1em 0;
3
+ background: #fff url(../images/ps_bar.gif) repeat-y;
4
+ }
5
+
6
+ .w3tc-widget-ps-rules a {
7
+ color: #00f;
8
+ text-decoration: none;
9
+ }
10
+
11
+ .w3tc-widget-ps-rules li,
12
+ .w3tc-widget-ps-rules p {
13
+ margin: 0;
14
+ }
15
+
16
+ .w3tc-widget-ps-rule {
17
+ line-height: 20px;
18
+ clear: left;
19
+ }
20
+
21
+ .w3tc-widget-ps-rule p {
22
+ margin-left: 40px;
23
+ line-height: 20px;
24
+ }
25
+
26
+ .w3tc-widget-ps-icon {
27
+ width: 31px;
28
+ height: 20px;
29
+ position: relative;
30
+ float: left;
31
+ }
32
+
33
+ .w3tc-widget-ps-icon div {
34
+ display: block;
35
+ background: url(../images/ps_scores.png);
36
+ width: 14px;
37
+ height: 14px;
38
+ position: relative;
39
+ top: 3px;
40
+ left: 8px;
41
+ }
42
+
43
+ .w3tc-widget-ps-priority-high .w3tc-widget-ps-icon div {
44
+ background-position: 0;
45
+ }
46
+
47
+ .w3tc-widget-ps-priority-medium .w3tc-widget-ps-icon div {
48
+ background-position: -14px;
49
+ }
50
+
51
+ .w3tc-widget-ps-priority-low .w3tc-widget-ps-icon div {
52
+ background-position: -28px;
53
+ }
54
+
55
+ .w3tc-widget-ps-expand {
56
+ float: left;
57
+ width: 30px;
58
+ height: 20px;
59
+ text-align: center;
60
+ }
61
+
62
+ .w3tc-widget-ps-expand a {
63
+ color: #66d;
64
+ }
inc/define.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- define('W3TC_VERSION', '0.9.1.3');
4
  define('W3TC_POWERED_BY', 'W3 Total Cache/' . W3TC_VERSION);
5
  define('W3TC_EMAIL', 'w3tc@w3-edge.com');
6
  define('W3TC_PAYPAL_URL', 'https://www.paypal.com/cgi-bin/webscr');
@@ -9,7 +9,6 @@ define('W3TC_LINK_URL', 'http://www.w3-edge.com/wordpress-plugins/');
9
  define('W3TC_LINK_NAME', 'WordPress Plugins');
10
  define('W3TC_FEED_URL', 'http://feeds.feedburner.com/W3TOTALCACHE');
11
  define('W3TC_README_URL', 'http://plugins.trac.wordpress.org/browser/w3-total-cache/trunk/readme.txt?format=txt');
12
- define('W3TC_TWITTER_STATUS', 'YES! I optimized my #wordpress site\'s #performance using the W3 Total Cache #plugin by @w3edge. Check it out! http://j.mp/A69xX');
13
  define('W3TC_SUPPORT_US_TIMEOUT', 2592000);
14
 
15
  define('W3TC_PHP5', PHP_VERSION >= 5);
@@ -21,6 +20,9 @@ define('W3TC_LIB_DIR', W3TC_DIR . '/lib');
21
  define('W3TC_LIB_W3_DIR', W3TC_LIB_DIR . '/W3');
22
  define('W3TC_LIB_MINIFY_DIR', W3TC_LIB_DIR . '/Minify');
23
  define('W3TC_LIB_CF_DIR', W3TC_LIB_DIR . '/CF');
 
 
 
24
  define('W3TC_PLUGINS_DIR', W3TC_DIR . '/plugins');
25
  define('W3TC_INSTALL_DIR', W3TC_DIR . '/wp-content');
26
  define('W3TC_INSTALL_MINIFY_DIR', W3TC_INSTALL_DIR . '/w3tc/min');
@@ -48,39 +50,68 @@ define('W3TC_CONFIG_MASTER_PATH', WP_CONTENT_DIR . '/w3-total-cache-config.php')
48
  define('W3TC_MINIFY_LOG_FILE', W3TC_LOG_DIR . '/minify.log');
49
  define('W3TC_CDN_COMMAND_UPLOAD', 1);
50
  define('W3TC_CDN_COMMAND_DELETE', 2);
 
51
  define('W3TC_CDN_TABLE_QUEUE', 'w3tc_cdn_queue');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  @ini_set('pcre.backtrack_limit', 4194304);
54
  @ini_set('pcre.recursion_limit', 4194304);
55
 
56
- $_w3tc_actions = array();
57
-
58
  /**
59
  * Deactivate plugin after activation error
60
- *
61
  * @return void
62
  */
63
- function w3_activation_cleanup()
64
- {
65
  $active_plugins = (array) get_option('active_plugins');
66
  $active_plugins_network = (array) get_site_option('active_sitewide_plugins');
67
-
68
  // workaround for WPMU deactivation bug
69
  remove_action('deactivate_' . W3TC_FILE, 'deactivate_sitewide_plugin');
70
-
71
  do_action('deactivate_plugin', W3TC_FILE);
72
-
73
  $key = array_search(W3TC_FILE, $active_plugins);
74
-
75
  if ($key !== false) {
76
  array_splice($active_plugins, $key, 1);
77
  }
78
-
79
  unset($active_plugins_network[W3TC_FILE]);
80
-
81
  do_action('deactivate_' . W3TC_FILE);
82
  do_action('deactivated_plugin', W3TC_FILE);
83
-
84
  update_option('active_plugins', $active_plugins);
85
  update_site_option('active_sitewide_plugins', $active_plugins_network);
86
  }
@@ -91,10 +122,9 @@ function w3_activation_cleanup()
91
  * @param string $error
92
  * @return void
93
  */
94
- function w3_activate_error($error)
95
- {
96
  w3_activation_cleanup();
97
-
98
  include W3TC_DIR . '/inc/error.phtml';
99
  exit();
100
  }
@@ -105,30 +135,28 @@ function w3_activate_error($error)
105
  * @param string $path
106
  * @return string
107
  */
108
- function w3_writable_error($path)
109
- {
110
  $activate_url = wp_nonce_url('plugins.php?action=activate&plugin=' . W3TC_FILE, 'activate-plugin_' . W3TC_FILE);
111
  $reactivate_button = sprintf('<input type="button" value="re-activate plugin" onclick="top.location.href = \'%s\'" />', addslashes($activate_url));
112
-
113
  if (w3_check_open_basedir($path)) {
114
  $error = sprintf('<strong>%s</strong> could not be created, please run following command:<br /><strong style="color: #f00;">chmod 777 %s</strong><br />then %s.', $path, (file_exists($path) ? $path : dirname($path)), $reactivate_button);
115
  } else {
116
  $error = sprintf('<strong>%s</strong> could not be created, <strong>open_basedir</strong> restriction in effect, please check your php.ini settings:<br /><strong style="color: #f00;">open_basedir = "%s"</strong><br />then %s.', $path, ini_get('open_basedir'), $reactivate_button);
117
  }
118
-
119
  w3_activate_error($error);
120
  }
121
 
122
  /**
123
  * W3 Network activation error
124
- *
125
  * @return void
126
  */
127
- function w3_network_activate_error()
128
- {
129
  w3_activation_cleanup();
130
  wp_redirect(plugins_url('inc/network_activation.php', W3TC_FILE));
131
-
132
  echo '<p><strong>W3 Total Cache Error:</strong> plugin cannot be activated network-wide.</p>';
133
  echo '<p><a href="javascript:history.back(-1);">Back</a>';
134
  exit();
@@ -137,12 +165,12 @@ function w3_network_activate_error()
137
  /**
138
  * Returns current microtime
139
  *
140
- * @return float
141
  */
142
- function w3_microtime()
143
- {
144
- list($usec, $sec) = explode(" ", microtime());
145
- return ((float) $usec + (float) $sec);
146
  }
147
 
148
  /**
@@ -153,28 +181,25 @@ function w3_microtime()
153
  * @param string
154
  * @return boolean
155
  */
156
- function w3_mkdir($path, $mask = 0755, $curr_path = '')
157
- {
158
  $path = w3_realpath($path);
159
  $path = trim($path, '/');
160
  $dirs = explode('/', $path);
161
-
162
  foreach ($dirs as $dir) {
163
  if ($dir == '') {
164
  return false;
165
  }
166
-
167
  $curr_path .= ($curr_path == '' ? '' : '/') . $dir;
168
-
169
  if (!@is_dir($curr_path)) {
170
- if (@mkdir($curr_path, $mask)) {
171
- @chmod($curr_path, $mask);
172
- } else {
173
  return false;
174
  }
175
  }
176
  }
177
-
178
  return true;
179
  }
180
 
@@ -185,14 +210,13 @@ function w3_mkdir($path, $mask = 0755, $curr_path = '')
185
  * @param array $exclude
186
  * @return void
187
  */
188
- function w3_rmdir($path, $exclude = array(), $remove = true)
189
- {
190
  $dir = @opendir($path);
191
-
192
  if ($dir) {
193
  while (($entry = @readdir($dir)) !== false) {
194
  $full_path = $path . '/' . $entry;
195
-
196
  if ($entry != '.' && $entry != '..' && !in_array($full_path, $exclude)) {
197
  if (@is_dir($full_path)) {
198
  w3_rmdir($full_path, $exclude);
@@ -201,9 +225,9 @@ function w3_rmdir($path, $exclude = array(), $remove = true)
201
  }
202
  }
203
  }
204
-
205
  @closedir($dir);
206
-
207
  if ($remove) {
208
  @rmdir($path);
209
  }
@@ -217,8 +241,7 @@ function w3_rmdir($path, $exclude = array(), $remove = true)
217
  * @param array $exclude
218
  * @return void
219
  */
220
- function w3_emptydir($path, $exclude = array())
221
- {
222
  w3_rmdir($path, $exclude, false);
223
  }
224
 
@@ -228,9 +251,18 @@ function w3_emptydir($path, $exclude = array())
228
  * @param string $content
229
  * @return boolean
230
  */
231
- function w3_is_xml(&$content)
232
- {
233
- return (stristr($content, '<?xml') !== false || stristr($content, '<html') !== false);
 
 
 
 
 
 
 
 
 
234
  }
235
 
236
  /**
@@ -238,51 +270,47 @@ function w3_is_xml(&$content)
238
  *
239
  * @return boolean
240
  */
241
- function w3_is_wpmu()
242
- {
243
  static $wpmu = null;
244
-
245
  if ($wpmu === null) {
246
- $wpmu = (w3_is_vhost() || file_exists(ABSPATH . 'wpmu-settings.php'));
247
  }
248
-
249
  return $wpmu;
250
  }
251
 
252
  /**
253
- * Returns true if it's WP with enabled Network mode
254
  *
255
  * @return boolean
256
  */
257
- function w3_is_network_mode()
258
- {
259
- static $network_mode = null;
260
-
261
- if ($network_mode === null) {
262
- $network_mode = (defined('MULTISITE') && MULTISITE);
263
- }
264
-
265
- return $network_mode;
266
  }
267
 
268
  /**
269
- * Returns if there is multisite mode
270
- *
271
  * @return boolean
272
  */
273
- function w3_is_multisite()
274
- {
275
- return (w3_is_wpmu() || w3_is_network_mode());
 
 
 
 
 
276
  }
277
 
278
  /**
279
- * Returns true if WPMU uses vhosts
280
  *
281
  * @return boolean
282
  */
283
- function w3_is_vhost()
284
- {
285
- return ((defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) || (defined('VHOST') && VHOST == 'yes'));
286
  }
287
 
288
  /**
@@ -291,8 +319,7 @@ function w3_is_vhost()
291
  * @param string $url
292
  * @return boolean
293
  */
294
- function w3_is_url($url)
295
- {
296
  return preg_match('~^https?://~', $url);
297
  }
298
 
@@ -301,182 +328,203 @@ function w3_is_url($url)
301
  *
302
  * @return boolean
303
  */
304
- function w3_is_https()
305
- {
306
  switch (true) {
307
  case (isset($_SERVER['HTTPS']) && w3_to_boolean($_SERVER['HTTPS'])):
308
  case (isset($_SERVER['SERVER_PORT']) && (int) $_SERVER['SERVER_PORT'] == 443):
309
  return true;
310
  }
311
-
312
  return false;
313
  }
314
 
315
  /**
316
  * Check if WP permalink directives exists
317
- *
318
  * @return boolean
319
  */
320
- function w3_is_permalink_rules()
321
- {
322
- $path = w3_get_home_root() . '/.htaccess';
323
-
324
- return (($data = @file_get_contents($path)) && (strstr($data, 'add a trailing slash to') !== false || strstr($data, 'BEGIN WordPress') !== false));
 
 
 
325
  }
326
 
327
  /**
328
  * Check if there was database error
329
- *
330
  * @param string $content
331
  * @return boolean
332
  */
333
- function w3_is_database_error(&$content)
334
- {
335
  return (stristr($content, '<title>Database Error</title>') !== false);
336
  }
337
 
338
  /**
339
  * Returns true if preview config exists
340
- *
341
  * @return boolean
342
  */
343
- function w3_is_preview_config()
344
- {
345
  return file_exists(W3TC_CONFIG_PREVIEW_PATH);
346
  }
347
 
348
  /**
349
  * Retuns true if preview settings active
350
- *
351
  * @return boolean
352
  */
353
- function w3_is_preview_mode()
354
- {
355
- return (w3_is_preview_config() && (defined('WP_ADMIN') || isset($_REQUEST['w3tc_preview']) || strstr($_SERVER['HTTP_REFERER'], 'w3tc_preview') !== false));
356
  }
357
 
358
  /**
359
  * Check if file is write-able
360
- *
361
  * @param string $path
362
  * @return boolean
363
  */
364
- function w3_is_writable($file)
365
- {
366
  $exists = file_exists($file);
367
-
368
  $fp = @fopen($file, 'a');
369
-
370
  if ($fp) {
371
  fclose($fp);
372
-
373
  if (!$exists) {
374
  @unlink($file);
375
  }
376
-
377
  return true;
378
  }
379
-
380
  return false;
381
  }
382
 
383
  /**
384
  * Cehck if dir is write-able
385
- *
386
  * @param string $dir
387
  * @return boolean
388
  */
389
- function w3_is_writable_dir($dir)
390
- {
391
  $file = $dir . '/' . uniqid(mt_rand()) . '.tmp';
392
-
393
  return w3_is_writable($file);
394
  }
395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  /**
397
  * Returns domain from host
398
  *
399
  * @param string $host
400
  * @return string
401
  */
402
- function w3_get_domain($host)
403
- {
404
  $host = strtolower($host);
405
-
406
  if (strpos($host, 'www.') === 0) {
407
  $host = substr($host, 4);
408
  }
409
-
410
  if (($pos = strpos($host, ':')) !== false) {
411
  $host = substr($host, 0, $pos);
412
  }
413
-
414
  $host = rtrim($host, '.');
415
-
416
  return $host;
417
  }
418
 
419
  /**
420
  * Returns array of all available blognames
421
- *
422
  * @return array
423
  */
424
- function w3_get_blognames()
425
- {
426
  global $wpdb;
427
-
428
  $blognames = array();
429
-
430
  $sql = sprintf('SELECT domain, path FROM %s', $wpdb->blogs);
431
  $blogs = $wpdb->get_results($sql);
432
-
433
  if ($blogs) {
434
  $base_path = w3_get_base_path();
435
-
436
  foreach ($blogs as $blog) {
437
  $blogname = trim(str_replace($base_path, '', $blog->path), '/');
438
-
439
  if ($blogname) {
440
  $blognames[] = $blogname;
441
  }
442
  }
443
  }
444
-
445
  return $blognames;
446
  }
447
 
448
  /**
449
  * Load blognames from file
450
- *
451
  * @return array
452
  */
453
- function w3_load_blognames()
454
- {
455
  $blognames = include W3TC_BLOGNAMES_PATH;
456
-
457
  return $blognames;
458
  }
459
 
460
  /**
461
  * Save blognames into file
462
- *
463
  * @param string $blognames
464
  * @return boolean
465
  */
466
- function w3_save_blognames($blognames = null)
467
- {
468
  if (!$blognames) {
469
  $blognames = w3_get_blognames();
470
  }
471
-
472
  $strings = array();
473
-
474
  foreach ($blognames as $blogname) {
475
  $strings[] = sprintf("'%s'", addslashes($blogname));
476
  }
477
-
478
  $data = sprintf('<?php return array(%s);', implode(', ', $strings));
479
-
480
  return @file_put_contents(W3TC_BLOGNAMES_PATH, $data);
481
  }
482
 
@@ -485,27 +533,26 @@ function w3_save_blognames($blognames = null)
485
  *
486
  * @return string
487
  */
488
- function w3_get_blogname()
489
- {
490
  static $blogname = null;
491
-
492
  if ($blogname === null) {
493
- if (w3_is_multisite()) {
494
  $host = w3_get_host();
495
  $domain = w3_get_domain($host);
496
-
497
- if (w3_is_vhost()) {
498
  $blogname = $domain;
499
  } else {
500
  $uri = $_SERVER['REQUEST_URI'];
501
  $base_path = w3_get_base_path();
502
-
503
  if ($base_path != '' && strpos($uri, $base_path) === 0) {
504
  $uri = substr_replace($uri, '/', 0, strlen($base_path));
505
  }
506
-
507
  $blogname = w3_get_blogname_from_uri($uri);
508
-
509
  if ($blogname != '') {
510
  $blogname = $blogname . '.' . $domain;
511
  } else {
@@ -516,7 +563,7 @@ function w3_get_blogname()
516
  $blogname = '';
517
  }
518
  }
519
-
520
  return $blogname;
521
  }
522
 
@@ -526,12 +573,11 @@ function w3_get_blogname()
526
  * @param string $uri
527
  * @param string
528
  */
529
- function w3_get_blogname_from_uri($uri)
530
- {
531
  $blogname = '';
532
  $matches = null;
533
  $uri = strtolower($uri);
534
-
535
  if (preg_match('~^/([a-z0-9-]+)/~', $uri, $matches)) {
536
  if (file_exists(W3TC_BLOGNAMES_PATH)) {
537
  // Get blognames from cache
@@ -542,28 +588,36 @@ function w3_get_blogname_from_uri($uri)
542
  } else {
543
  $blognames = array();
544
  }
545
-
546
  if (is_array($blognames) && in_array($matches[1], $blognames)) {
547
  $blogname = $matches[1];
548
  }
549
  }
550
-
551
  return $blogname;
552
  }
553
 
 
 
 
 
 
 
 
 
 
554
  /**
555
  * Returns URL regexp from URL
556
- *
557
  * @param string $url
558
  * @return string
559
  */
560
- function w3_get_url_regexp($url)
561
- {
562
  $url = preg_replace('~https?://~i', '', $url);
563
  $url = preg_replace('~^www\.~i', '', $url);
564
-
565
  $regexp = 'https?://(www\.)?' . w3_preg_quote($url);
566
-
567
  return $regexp;
568
  }
569
 
@@ -572,12 +626,11 @@ function w3_get_url_regexp($url)
572
  * @param string $url
573
  * @return string
574
  */
575
- function w3_get_url_ssl($url)
576
- {
577
  if (w3_is_https()) {
578
  $url = str_replace('http://', 'https://', $url);
579
  }
580
-
581
  return $url;
582
  }
583
 
@@ -587,20 +640,19 @@ function w3_get_url_ssl($url)
587
  * @return string
588
  */
589
 
590
- function w3_get_domain_url()
591
- {
592
- $site_url = w3_get_site_url();
593
- $parse_url = @parse_url($site_url);
594
-
595
  if ($parse_url && isset($parse_url['scheme']) && isset($parse_url['host'])) {
596
  $scheme = $parse_url['scheme'];
597
  $host = $parse_url['host'];
598
  $port = (isset($parse_url['port']) && $parse_url['port'] != 80 ? ':' . (int) $parse_url['port'] : '');
599
  $domain_url = sprintf('%s://%s%s', $scheme, $host, $port);
600
-
601
  return $domain_url;
602
  }
603
-
604
  return false;
605
  }
606
 
@@ -609,35 +661,28 @@ function w3_get_domain_url()
609
  *
610
  * @return string
611
  */
612
- function w3_get_domain_url_regexp()
613
- {
614
  $domain_url = w3_get_domain_url();
615
  $regexp = w3_get_url_regexp($domain_url);
616
-
617
  return $regexp;
618
  }
619
 
620
  /**
621
  * Returns home URL
622
- *
623
  * No trailing slash!
624
- *
625
  * @return string
626
  */
627
- function w3_get_home_url()
628
- {
629
  static $home_url = null;
630
-
631
  if ($home_url === null) {
632
- if (function_exists('get_option')) {
633
- $home_url = get_option('home');
634
- } else {
635
- $home_url = w3_get_site_url();
636
- }
637
-
638
  $home_url = rtrim($home_url, '/');
639
  }
640
-
641
  return $home_url;
642
  }
643
 
@@ -646,153 +691,126 @@ function w3_get_home_url()
646
  *
647
  * @return string
648
  */
649
- function w3_get_home_url_ssl()
650
- {
651
  $home_url = w3_get_home_url();
652
  $ssl = w3_get_url_ssl($home_url);
653
-
654
  return $ssl;
655
  }
656
 
657
  /**
658
- * Returns site URL
659
- *
660
- * No trailing slash!
661
  *
662
  * @return string
663
  */
664
- function w3_get_site_url()
665
- {
666
- static $site_url = null;
667
-
668
- if ($site_url === null) {
669
- if (function_exists('get_option')) {
670
- $site_url = get_option('siteurl');
671
- } else {
672
- $site_url = sprintf('http://%s%s', w3_get_host(), w3_get_base_path());
673
- }
674
-
675
- $site_url = rtrim($site_url, '/');
676
- }
677
-
678
- return $site_url;
679
- }
680
 
681
- /**
682
- * Returns SSL site url
683
- *
684
- * @return string
685
- */
686
- function w3_get_site_url_ssl()
687
- {
688
- $site_url = w3_get_site_url();
689
- $ssl = w3_get_url_ssl($site_url);
690
-
691
- return $ssl;
692
  }
693
 
694
  /**
695
- * Returns site url regexp
 
 
696
  *
697
  * @return string
698
  */
699
- function w3_get_site_url_regexp()
700
- {
701
- $site_url = w3_get_site_url();
702
- $regexp = w3_get_url_regexp($site_url);
703
-
704
- return $regexp;
 
 
 
705
  }
706
 
707
  /**
708
  * Returns absolute path to document root
709
- *
710
  * No trailing slash!
711
- *
712
  * @return string
713
  */
714
- function w3_get_document_root()
715
- {
716
  static $document_root = null;
717
-
718
  if ($document_root === null) {
719
- if (isset($_SERVER['SCRIPT_FILENAME'])) {
720
  $document_root = substr($_SERVER['SCRIPT_FILENAME'], 0, -strlen($_SERVER['PHP_SELF']));
721
- } elseif (isset($_SERVER['PATH_TRANSLATED'])) {
722
  $document_root = substr($_SERVER['PATH_TRANSLATED'], 0, -strlen($_SERVER['PHP_SELF']));
723
- } elseif (isset($_SERVER['DOCUMENT_ROOT'])) {
724
  $document_root = $_SERVER['DOCUMENT_ROOT'];
725
  } else {
726
  $document_root = w3_get_site_root();
727
  }
728
-
729
  $document_root = realpath($document_root);
730
  $document_root = w3_path($document_root);
731
  }
732
-
733
  return $document_root;
734
  }
735
 
736
  /**
737
  * Returns absolute path to home directory
738
- *
739
  * Example:
740
- *
741
  * DOCUMENT_ROOT=/var/www/vhosts/domain.com
742
  * Install dir=/var/www/vhosts/domain.com/site/blog
743
  * home=http://domain.com/site
744
  * siteurl=http://domain.com/site/blog
745
  * return /var/www/vhosts/domain.com/site
746
- *
747
  * No trailing slash!
748
- *
749
  * @return string
750
  */
751
- function w3_get_home_root()
752
- {
753
- $home_url = w3_get_home_url();
754
- $site_url = w3_get_site_url();
755
-
756
- if (w3_is_multisite()) {
757
  $path = w3_get_base_path();
758
  } else {
759
  $path = w3_get_home_path();
760
  }
761
-
762
  $home_root = w3_get_document_root() . $path;
763
  $home_root = realpath($home_root);
764
  $home_root = w3_path($home_root);
765
-
766
  return $home_root;
767
  }
768
 
769
  /**
770
  * Returns absolute path to blog install dir
771
- *
772
  * Example:
773
- *
774
  * DOCUMENT_ROOT=/var/www/vhosts/domain.com
775
  * install dir=/var/www/vhosts/domain.com/site/blog
776
  * return /var/www/vhosts/domain.com/site/blog
777
- *
778
  * No trailing slash!
779
- *
780
  * @return string
781
  */
782
- function w3_get_site_root()
783
- {
784
  $site_root = ABSPATH;
785
  $site_root = realpath($site_root);
786
  $site_root = w3_path($site_root);
787
-
788
  return $site_root;
789
  }
790
 
791
  /**
792
  * Returns blog path
793
- *
794
  * Example:
795
- *
796
  * siteurl=http://domain.com/site/blog
797
  * return /site/blog/
798
  *
@@ -800,29 +818,28 @@ function w3_get_site_root()
800
  *
801
  * @return string
802
  */
803
- function w3_get_site_path()
804
- {
805
  $site_url = w3_get_site_url();
806
  $parse_url = @parse_url($site_url);
807
-
808
  if ($parse_url && isset($parse_url['path'])) {
809
  $site_path = '/' . ltrim($parse_url['path'], '/');
810
  } else {
811
  $site_path = '/';
812
  }
813
-
814
  if (substr($site_path, -1) != '/') {
815
  $site_path .= '/';
816
  }
817
-
818
  return $site_path;
819
  }
820
 
821
  /**
822
  * Returns home path
823
- *
824
  * Example:
825
- *
826
  * home=http://domain.com/site/
827
  * siteurl=http://domain.com/site/blog
828
  * return /site/
@@ -831,163 +848,449 @@ function w3_get_site_path()
831
  *
832
  * @return string
833
  */
834
- function w3_get_home_path()
835
- {
836
  $home_url = w3_get_home_url();
837
  $parse_url = @parse_url($home_url);
838
-
839
  if ($parse_url && isset($parse_url['path'])) {
840
  $home_path = '/' . ltrim($parse_url['path'], '/');
841
  } else {
842
  $home_path = '/';
843
  }
844
-
845
  if (substr($home_path, -1) != '/') {
846
  $home_path .= '/';
847
  }
848
-
849
  return $home_path;
850
  }
851
 
852
  /**
853
  * Returns path to WP directory relative to document root
854
- *
855
  * Example:
856
- *
857
  * DOCUMENT_ROOT=/var/www/vhosts/domain.com/
858
  * Install dir=/var/www/vhosts/domain.com/site/blog/
859
  * return /site/blog/
860
- *
861
  * With trailing slash!
862
- *
863
  * @return string
864
  */
865
- function w3_get_base_path()
866
- {
867
  $document_root = w3_get_document_root();
868
  $site_root = w3_get_site_root();
869
-
870
  $base_path = str_replace($document_root, '', $site_root);
871
  $base_path = '/' . ltrim($base_path, '/');
872
-
873
  if (substr($base_path, -1) != '/') {
874
  $base_path .= '/';
875
  }
876
-
877
  return $base_path;
878
  }
879
 
880
  /**
881
  * Returns server hostname
882
- *
883
  * @return string
884
  */
885
- function w3_get_host()
886
- {
887
  static $host = null;
888
-
889
  if ($host === null) {
890
- $host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']);
891
  }
892
-
893
  return $host;
894
  }
895
 
896
  /**
897
- * Normalizes file name
898
  *
899
- * Relative to site root!
900
- *
901
- * @param string $file
902
  * @return string
903
  */
904
- function w3_normalize_file($file)
905
- {
906
- if (w3_is_url($file)) {
907
- if (strstr($file, '?') === false) {
908
- $site_url_regexp = '~' . w3_get_site_url_regexp() . '~i';
909
- $file = preg_replace($site_url_regexp, '', $file);
910
- }
911
- }
912
-
913
- if (!w3_is_url($file)) {
914
- $file = w3_path($file);
915
- $file = str_replace(w3_get_site_root(), '', $file);
916
- $file = ltrim($file, '/');
917
  }
918
-
919
- return $file;
920
  }
921
 
922
  /**
923
- * Normalizes file name for minify
924
- *
925
- * Relative to document root!
926
- *
927
- * @param string $file
928
  * @return string
929
  */
930
- function w3_normalize_file_minify($file)
931
- {
932
- if (w3_is_url($file)) {
933
- if (strstr($file, '?') === false) {
934
- $domain_url_regexp = '~' . w3_get_domain_url_regexp() . '~i';
935
- $file = preg_replace($domain_url_regexp, '', $file);
936
- }
937
- }
938
-
939
- if (!w3_is_url($file)) {
940
- $file = w3_path($file);
941
- $file = str_replace(w3_get_document_root(), '', $file);
942
- $file = ltrim($file, '/');
943
  }
944
-
945
- return $file;
946
  }
947
 
948
  /**
949
- * Translates remote file to local file
950
- *
951
- * @param string $file
952
  * @return string
953
  */
954
- function w3_translate_file($file)
955
- {
956
- if (!w3_is_url($file)) {
957
- $file = '/' . ltrim($file, '/');
958
- $regexp = '~^' . w3_preg_quote(w3_get_site_path()) . '~';
959
- $file = preg_replace($regexp, w3_get_base_path(), $file);
960
- $file = ltrim($file, '/');
961
  }
962
-
963
- return $file;
964
  }
965
 
966
  /**
967
- * Converts win path to unix
968
  *
969
- * @param string $path
970
  * @return string
971
  */
972
- function w3_path($path)
973
- {
974
- $path = preg_replace('~[/\\\]+~', '/', $path);
975
- $path = rtrim($path, '/');
976
-
977
- return $path;
 
 
 
 
978
  }
979
 
980
  /**
981
- * Returns realpath of given path
982
  *
983
- * @param string $path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
984
  */
985
- function w3_realpath($path)
986
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
987
  $path = w3_path($path);
988
  $parts = explode('/', $path);
989
  $absolutes = array();
990
-
991
  foreach ($parts as $part) {
992
  if ('.' == $part) {
993
  continue;
@@ -998,24 +1301,23 @@ function w3_realpath($path)
998
  $absolutes[] = $part;
999
  }
1000
  }
1001
-
1002
  return implode('/', $absolutes);
1003
  }
1004
 
1005
  /**
1006
  * Returns dirname of path
1007
- *
1008
  * @param string $path
1009
  * @return string
1010
  */
1011
- function w3_dirname($path)
1012
- {
1013
  $dirname = dirname($path);
1014
-
1015
  if ($dirname == '.' || $dirname == '/' || $dirname == '\\') {
1016
  $dirname = '';
1017
  }
1018
-
1019
  return $dirname;
1020
  }
1021
 
@@ -1024,19 +1326,18 @@ function w3_dirname($path)
1024
  *
1025
  * @return array
1026
  */
1027
- function w3_get_open_basedirs()
1028
- {
1029
  $open_basedir_ini = ini_get('open_basedir');
1030
  $open_basedirs = (W3TC_WIN ? preg_split('~[;,]~', $open_basedir_ini) : explode(':', $open_basedir_ini));
1031
  $result = array();
1032
-
1033
  foreach ($open_basedirs as $open_basedir) {
1034
  $open_basedir = trim($open_basedir);
1035
  if ($open_basedir != '') {
1036
  $result[] = w3_realpath($open_basedir);
1037
  }
1038
  }
1039
-
1040
  return $result;
1041
  }
1042
 
@@ -1046,21 +1347,20 @@ function w3_get_open_basedirs()
1046
  * @param string $path
1047
  * @return boolean
1048
  */
1049
- function w3_check_open_basedir($path)
1050
- {
1051
  $path = w3_realpath($path);
1052
  $open_basedirs = w3_get_open_basedirs();
1053
-
1054
  if (!count($open_basedirs)) {
1055
  return true;
1056
  }
1057
-
1058
  foreach ($open_basedirs as $open_basedir) {
1059
  if (strstr($path, $open_basedir) !== false) {
1060
  return true;
1061
  }
1062
  }
1063
-
1064
  return false;
1065
  }
1066
 
@@ -1074,14 +1374,13 @@ function w3_check_open_basedir($path)
1074
  * @param boolean $check_status
1075
  * @return string
1076
  */
1077
- function w3_http_request($method, $url, $data = '', $auth = '', $check_status = true)
1078
- {
1079
  $status = 0;
1080
  $method = strtoupper($method);
1081
-
1082
  if (function_exists('curl_init')) {
1083
  $ch = curl_init();
1084
-
1085
  curl_setopt($ch, CURLOPT_URL, $url);
1086
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1087
  curl_setopt($ch, CURLOPT_USERAGENT, W3TC_POWERED_BY);
@@ -1089,87 +1388,91 @@ function w3_http_request($method, $url, $data = '', $auth = '', $check_status =
1089
  curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
1090
  curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
1091
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
1092
- curl_setopt($ch, CURLOPT_TIMEOUT, 180);
1093
-
 
 
1094
  switch ($method) {
1095
  case 'POST':
1096
  curl_setopt($ch, CURLOPT_POST, true);
1097
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
1098
  break;
1099
-
1100
  case 'PURGE':
1101
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PURGE');
1102
  break;
1103
  }
1104
-
1105
  if ($auth) {
1106
  curl_setopt($ch, CURLOPT_USERPWD, $auth);
1107
  }
1108
-
1109
  $contents = curl_exec($ch);
1110
-
1111
  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1112
-
1113
  curl_close($ch);
1114
  } else {
1115
  $parse_url = @parse_url($url);
1116
-
1117
  if ($parse_url && isset($parse_url['host'])) {
1118
  $host = $parse_url['host'];
1119
  $port = (isset($parse_url['port']) ? (int) $parse_url['port'] : 80);
1120
  $path = (!empty($parse_url['path']) ? $parse_url['path'] : '/');
1121
  $query = (isset($parse_url['query']) ? $parse_url['query'] : '');
1122
  $request_uri = $path . ($query != '' ? '?' . $query : '');
1123
-
1124
  $request_headers_array = array(
1125
- sprintf('%s %s HTTP/1.0', $method, $request_uri),
1126
- sprintf('Host: %s', $host),
1127
- sprintf('User-Agent: %s', W3TC_POWERED_BY),
1128
  'Connection: close'
1129
  );
1130
-
1131
  if (!empty($data)) {
1132
  $request_headers_array[] = sprintf('Content-Length: %d', strlen($data));
1133
  }
1134
-
1135
  if (!empty($auth)) {
1136
  $request_headers_array[] = sprintf('Authorization: Basic %s', base64_encode($auth));
1137
  }
1138
-
1139
  $request_headers = implode("\r\n", $request_headers_array);
1140
  $request = $request_headers . "\r\n\r\n" . $data;
1141
  $errno = null;
1142
  $errstr = null;
1143
-
1144
  $fp = @fsockopen($host, $port, $errno, $errstr, 10);
1145
-
1146
  if (!$fp) {
1147
  return false;
1148
  }
1149
-
 
 
1150
  $response = '';
1151
  @fputs($fp, $request);
1152
-
1153
  while (!@feof($fp)) {
1154
  $response .= @fgets($fp, 4096);
1155
  }
1156
-
1157
  @fclose($fp);
1158
-
1159
- list($response_headers, $contents) = explode("\r\n\r\n", $response, 2);
1160
-
1161
  $matches = null;
1162
-
1163
  if (preg_match('~^HTTP/1.[01] (\d+)~', $response_headers, $matches)) {
1164
  $status = (int) $matches[1];
1165
  }
1166
  }
1167
  }
1168
-
1169
  if (!$check_status || $status == 200) {
1170
  return $contents;
1171
  }
1172
-
1173
  return false;
1174
  }
1175
 
@@ -1181,8 +1484,7 @@ function w3_http_request($method, $url, $data = '', $auth = '', $check_status =
1181
  * $param boolean $check_status
1182
  * @return string
1183
  */
1184
- function w3_http_get($url, $auth = '', $check_status = true)
1185
- {
1186
  return w3_http_request('GET', $url, null, $auth, $check_status);
1187
  }
1188
 
@@ -1195,8 +1497,7 @@ function w3_http_get($url, $auth = '', $check_status = true)
1195
  * @param boolean $check_status
1196
  * @return string
1197
  */
1198
- function w3_http_post($url, $data = '', $auth = '', $check_status = true)
1199
- {
1200
  return w3_http_request('POST', $url, $data, $auth, $check_status);
1201
  }
1202
 
@@ -1207,8 +1508,7 @@ function w3_http_post($url, $data = '', $auth = '', $check_status = true)
1207
  * $param boolean $check_status
1208
  * @return string
1209
  */
1210
- function w3_http_purge($url, $auth = '', $check_status = true)
1211
- {
1212
  return w3_http_request('PURGE', $url, null, $auth, $check_status);
1213
  }
1214
 
@@ -1217,8 +1517,7 @@ function w3_http_purge($url, $auth = '', $check_status = true)
1217
  * @param integer $time
1218
  * @return string
1219
  */
1220
- function w3_http_date($time)
1221
- {
1222
  return gmdate('D, d M Y H:i:s \G\M\T', $time);
1223
  }
1224
 
@@ -1229,14 +1528,13 @@ function w3_http_date($time)
1229
  * @param string $file
1230
  * @return boolean
1231
  */
1232
- function w3_download($url, $file)
1233
- {
1234
  $data = w3_http_get($url);
1235
-
1236
  if ($data !== false) {
1237
  return @file_put_contents($file, $data);
1238
  }
1239
-
1240
  return false;
1241
  }
1242
 
@@ -1245,98 +1543,141 @@ function w3_download($url, $file)
1245
  *
1246
  * @return array
1247
  */
1248
- function w3_upload_info()
1249
- {
1250
  static $upload_info = null;
1251
-
1252
  if ($upload_info === null) {
1253
  $upload_info = @wp_upload_dir();
1254
-
1255
  if (empty($upload_info['error'])) {
1256
- $site_url = w3_get_site_url();
1257
-
1258
  $parse_url = @parse_url($upload_info['baseurl']);
1259
-
1260
  if ($parse_url) {
1261
  $baseurlpath = (!empty($parse_url['path']) ? trim($parse_url['path'], '/') : '');
1262
  } else {
1263
  $baseurlpath = 'wp-content/uploads';
1264
  }
1265
-
1266
  $upload_info['baseurlpath'] = '/' . $baseurlpath . '/';
1267
  } else {
1268
  $upload_info = false;
1269
  }
1270
  }
1271
-
1272
  return $upload_info;
1273
  }
1274
 
1275
  /**
1276
- * Redirects to URL
1277
- *
1278
  * @param string $url
1279
- * @param string $params
 
1280
  * @return string
1281
  */
1282
- function w3_redirect($url = '', $params = array())
1283
- {
1284
- $fragment = '';
1285
-
1286
- if ($url != '' && ($parse_url = @parse_url($url))) {
1287
  $url = '';
1288
-
1289
  if (!empty($parse_url['scheme'])) {
1290
  $url .= $parse_url['scheme'] . '://';
1291
- }
1292
-
1293
- if (!empty($parse_url['user'])) {
1294
- $url .= $parse_url['user'];
1295
-
1296
- if (!empty($parse_url['pass'])) {
1297
- $url .= ':' . $parse_url['pass'];
 
 
 
 
 
 
 
 
1298
  }
1299
  }
1300
-
1301
- if (!empty($parse_url['host'])) {
1302
- $url .= $parse_url['host'];
1303
- }
1304
-
1305
- if (!empty($parse_url['port']) && $parse_url['port'] != 80) {
1306
- $url .= ':' . (int) $parse_url['port'];
1307
  }
1308
-
1309
- $url .= (!empty($parse_url['path']) ? $parse_url['path'] : '/');
1310
-
1311
  if (!empty($parse_url['query'])) {
1312
  $old_params = array();
1313
  parse_str($parse_url['query'], $old_params);
1314
-
1315
  $params = array_merge($old_params, $params);
1316
  }
1317
-
 
 
 
 
 
 
1318
  if (!empty($parse_url['fragment'])) {
1319
- $fragment = '#' . $parse_url['fragment'];
1320
  }
1321
  } else {
1322
- $parse_url = array();
1323
- }
1324
-
1325
- if (($count = count($params))) {
1326
- $query = '';
1327
-
1328
- foreach ($params as $param => $value) {
1329
- $count--;
1330
- $query .= urlencode($param) . (!empty($value) ? '=' . urlencode($value) : '') . ($count ? '&' : '');
1331
  }
1332
-
1333
- $url .= (strpos($url, '?') === false ? '?' : '&') . $query;
1334
  }
1335
-
1336
- if ($fragment != '') {
1337
- $url .= $fragment;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1338
  }
1339
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1340
  @header('Location: ' . $url);
1341
  exit();
1342
  }
@@ -1347,62 +1688,77 @@ function w3_redirect($url = '', $params = array())
1347
  * @param $engine
1348
  * @return string
1349
  */
1350
- function w3_get_engine_name($engine)
1351
- {
1352
  switch ($engine) {
1353
  case 'memcached':
1354
  $engine_name = 'memcached';
1355
  break;
1356
-
1357
  case 'apc':
1358
  $engine_name = 'apc';
1359
  break;
1360
-
1361
  case 'eaccelerator':
1362
  $engine_name = 'eaccelerator';
1363
  break;
1364
-
1365
  case 'xcache':
1366
  $engine_name = 'xcache';
1367
  break;
1368
-
 
 
 
 
1369
  case 'file':
1370
  $engine_name = 'disk';
1371
  break;
1372
-
1373
  case 'file_pgcache':
1374
  $engine_name = 'disk (enhanced)';
1375
  break;
1376
-
1377
  case 'mirror':
1378
  $engine_name = 'mirror';
1379
  break;
1380
-
1381
  case 'netdna':
1382
- $engine_name = 'mirror: netdna / maxcdn';
 
 
 
 
1383
  break;
1384
-
1385
  case 'ftp':
1386
  $engine_name = 'self-hosted / file transfer protocol upload';
1387
  break;
1388
-
1389
  case 's3':
1390
  $engine_name = 'amazon simple storage service (s3)';
1391
  break;
1392
-
1393
  case 'cf':
1394
  $engine_name = 'amazon cloudfront';
1395
  break;
1396
-
 
 
 
 
1397
  case 'rscf':
1398
  $engine_name = 'rackspace cloud files';
1399
  break;
1400
-
 
 
 
 
1401
  default:
1402
  $engine_name = 'n/a';
1403
  break;
1404
  }
1405
-
1406
  return $engine_name;
1407
  }
1408
 
@@ -1412,8 +1768,7 @@ function w3_get_engine_name($engine)
1412
  * @param mixed $value
1413
  * @return boolean
1414
  */
1415
- function w3_to_boolean($value)
1416
- {
1417
  if (is_string($value)) {
1418
  switch (strtolower($value)) {
1419
  case '+':
@@ -1424,7 +1779,7 @@ function w3_to_boolean($value)
1424
  case 'true':
1425
  case 'enabled':
1426
  return true;
1427
-
1428
  case '-':
1429
  case '0':
1430
  case 'n':
@@ -1435,27 +1790,8 @@ function w3_to_boolean($value)
1435
  return false;
1436
  }
1437
  }
1438
-
1439
- return (boolean) $value;
1440
- }
1441
 
1442
- /**
1443
- * Loads plugins
1444
- *
1445
- * @return void
1446
- */
1447
- function w3_load_plugins()
1448
- {
1449
- $dir = @opendir(W3TC_PLUGINS_DIR);
1450
-
1451
- if ($dir) {
1452
- while (($entry = @readdir($dir)) !== false) {
1453
- if (strrchr($entry, '.') === '.php') {
1454
- require_once W3TC_PLUGINS_DIR . '/' . $entry;
1455
- }
1456
- }
1457
- @closedir($dir);
1458
- }
1459
  }
1460
 
1461
  /**
@@ -1464,105 +1800,71 @@ function w3_load_plugins()
1464
  * @param string $file
1465
  * @return string
1466
  */
1467
- function w3_get_mime_type($file)
1468
- {
1469
  static $cache = array();
1470
-
1471
  if (!isset($cache[$file])) {
1472
  $mime_type = false;
1473
-
1474
  /**
1475
  * Try to detect by extension (fast)
1476
  */
1477
  $mime_types = include W3TC_DIR . '/inc/mime/all.php';
1478
-
1479
  foreach ($mime_types as $extension => $type) {
1480
  if (preg_match('~\.(' . $extension . ')$~i', $file)) {
1481
  $mime_type = $type;
1482
  break;
1483
  }
1484
  }
1485
-
1486
  /**
1487
  * Try to detect using file info function
1488
  */
1489
  if (!$mime_type && function_exists('finfo_open')) {
1490
  $finfo = @finfo_open(FILEINFO_MIME);
1491
-
1492
  if (!$finfo) {
1493
  $finfo = @finfo_open(FILEINFO_MIME);
1494
  }
1495
-
1496
  if ($finfo) {
1497
  $mime_type = @finfo_file($finfo, $file);
1498
-
1499
  if ($mime_type) {
1500
  $extra_mime_type_info = strpos($mime_type, "; ");
1501
-
1502
  if ($extra_mime_type_info) {
1503
  $mime_type = substr($mime_type, 0, $extra_mime_type_info);
1504
  }
1505
-
1506
  if ($mime_type == 'application/octet-stream') {
1507
  $mime_type = false;
1508
  }
1509
  }
1510
-
1511
  @finfo_close($finfo);
1512
  }
1513
  }
1514
-
1515
  /**
1516
  * Try to detect using mime type function
1517
  */
1518
  if (!$mime_type && function_exists('mime_content_type')) {
1519
  $mime_type = @mime_content_type($file);
1520
  }
1521
-
1522
  /**
1523
- * If detection failed use default mime type
1524
  */
1525
  if (!$mime_type) {
1526
  $mime_type = 'application/octet-stream';
1527
  }
1528
-
1529
  $cache[$file] = $mime_type;
1530
  }
1531
-
1532
- return $cache[$file];
1533
- }
1534
 
1535
- /**
1536
- * Send twitter update status request
1537
- *
1538
- * @param string $username
1539
- * @param string $password
1540
- * @param string $status
1541
- * @param string $error
1542
- * @return string
1543
- */
1544
- function w3_twitter_status_update($username, $password, $status, &$error)
1545
- {
1546
- $data = sprintf('status=%s', urlencode($status));
1547
- $auth = sprintf('%s:%s', $username, $password);
1548
-
1549
- $xml = w3_http_post('http://twitter.com/statuses/update.xml', $data, $auth);
1550
-
1551
- if ($xml) {
1552
- $matches = null;
1553
-
1554
- if (preg_match('~<id>(\d+)</id>~', $xml, $matches)) {
1555
- return $matches[1];
1556
- } elseif (preg_match('~<error>([^<]+)</error>~', $xml, $matches)) {
1557
- $error = $matches[1];
1558
- } else {
1559
- $error = 'Unknown error.';
1560
- }
1561
- } else {
1562
- $error = 'Unable to send request.';
1563
- }
1564
-
1565
- return false;
1566
  }
1567
 
1568
  /**
@@ -1571,13 +1873,12 @@ function w3_twitter_status_update($username, $password, $status, &$error)
1571
  * @param string $regexp
1572
  * @return string
1573
  */
1574
- function w3_preg_quote($string, $delimiter = null)
1575
- {
1576
  $string = preg_quote($string, $delimiter);
1577
  $string = strtr($string, array(
1578
  ' ' => '\ '
1579
  ));
1580
-
1581
  return $string;
1582
  }
1583
 
@@ -1586,8 +1887,7 @@ function w3_preg_quote($string, $delimiter = null)
1586
  *
1587
  * @return boolean
1588
  */
1589
- function w3_zlib_output_compression()
1590
- {
1591
  return w3_to_boolean(ini_get('zlib.output_compression'));
1592
  }
1593
 
@@ -1597,14 +1897,13 @@ function w3_zlib_output_compression()
1597
  * @param mixed $var
1598
  * @return mixed
1599
  */
1600
- function w3_stripslashes($var)
1601
- {
1602
  if (is_string($var)) {
1603
  return stripslashes($var);
1604
  } elseif (is_array($var)) {
1605
  $var = array_map('w3_stripslashes', $var);
1606
  }
1607
-
1608
  return $var;
1609
  }
1610
 
@@ -1612,7 +1911,7 @@ if (!function_exists('file_put_contents')) {
1612
  if (!defined('FILE_APPEND')) {
1613
  define('FILE_APPEND', 8);
1614
  }
1615
-
1616
  /**
1617
  * Puts contents to the file
1618
  *
@@ -1621,167 +1920,140 @@ if (!function_exists('file_put_contents')) {
1621
  * @param integer $flags
1622
  * @return boolean
1623
  */
1624
- function file_put_contents($filename, $data, $flags = 0)
1625
- {
1626
  $fp = fopen($filename, ($flags & FILE_APPEND ? 'a' : 'w'));
1627
-
1628
  if ($fp) {
1629
  fputs($fp, $data);
1630
  fclose($fp);
1631
-
1632
  return true;
1633
  }
1634
-
1635
  return false;
1636
  }
1637
  }
1638
 
1639
  /**
1640
- * Cleanup .htaccess rules
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1641
  *
1642
  * @param string $rules
1643
  * @return string
1644
  */
1645
- function w3_clean_rules($rules)
1646
- {
1647
  $rules = preg_replace('~[\r\n]+~', "\n", $rules);
1648
  $rules = preg_replace('~^\s+~m', '', $rules);
1649
- $rules = trim($rules);
1650
-
1651
  return $rules;
1652
  }
1653
 
1654
  /**
1655
  * Erases text from start to end
1656
  *
1657
- * @param string $text
1658
  * @param string $start
1659
  * @param string $end
1660
  * @return string
1661
  */
1662
- function w3_erase_text($text, $start, $end)
1663
- {
1664
- $text = preg_replace('~' . w3_preg_quote($start) . '.*' . w3_preg_quote($end) . '~Us', '', $text);
1665
- $text = trim($text);
1666
-
1667
- return $text;
1668
  }
1669
 
1670
  /**
1671
- * Return deafult htaccess rules for current WP version
1672
  *
1673
- * @return string
 
1674
  */
1675
- function w3_get_permalink_rules()
1676
- {
1677
- $rules = '';
1678
- $base_path = w3_get_base_path();
1679
-
1680
- if (w3_is_wpmu()) {
1681
- $rules .= "RewriteEngine On\n";
1682
- $rules .= "RewriteBase " . $base_path . "\n\n";
1683
-
1684
- $rules .= "#uploaded files\n";
1685
- $rules .= "RewriteRule ^(.*/)?files/$ index.php [L]\n";
1686
- $rules .= "RewriteCond %{REQUEST_URI} !.*wp-content/plugins.*\n";
1687
- $rules .= "RewriteRule ^(.*/)?files/(.*) wp-content/blogs.php?file=$2 [L]\n\n";
1688
-
1689
- $rules .= "# add a trailing slash to /wp-admin\n";
1690
- $rules .= "RewriteCond %{REQUEST_URI} ^.*/wp-admin$\n";
1691
- $rules .= "RewriteRule ^(.+)$ $1/ [R=301,L]\n\n";
1692
-
1693
- $rules .= "RewriteCond %{REQUEST_FILENAME} -f [OR]\n";
1694
- $rules .= "RewriteCond %{REQUEST_FILENAME} -d\n";
1695
- $rules .= "RewriteRule . - [L]\n";
1696
- $rules .= "RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-.*) $2 [L]\n";
1697
- $rules .= "RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\\.php)$ $2 [L]\n";
1698
- $rules .= "RewriteRule . index.php [L]\n\n";
1699
-
1700
- $rules .= "<IfModule mod_security.c>\n";
1701
- $rules .= "<Files async-upload.php>\n";
1702
- $rules .= "SecFilterEngine Off\n";
1703
- $rules .= "SecFilterScanPOST Off\n";
1704
- $rules .= "</Files>\n";
1705
- $rules .= "</IfModule>\n";
1706
- } elseif (w3_is_network_mode()) {
1707
- $subdomain_install = is_subdomain_install();
1708
-
1709
- $rules .= "# BEGIN WordPress\n";
1710
- $rules .= "<IfModule mod_rewrite.c>\n";
1711
- $rules .= "RewriteEngine On\n";
1712
- $rules .= "RewriteBase " . $base_path . "\n";
1713
- $rules .= "RewriteRule ^index\\.php$ - [L]\n\n";
1714
-
1715
- $rules .= "# uploaded files\n";
1716
- $rules .= "RewriteRule ^" . ($subdomain_install ? '' : '([_0-9a-zA-Z-]+/)?') . "files/(.+) wp-includes/ms-files.php?file=$" . ($subdomain_install ? 1 : 2) . " [L]\n\n";
1717
-
1718
- if (!$subdomain_install) {
1719
- $rules .= "# add a trailing slash to /wp-admin\n";
1720
- $rules .= "RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]\n";
1721
- }
1722
-
1723
- $rules .= "RewriteCond %{REQUEST_FILENAME} -f [OR]\n";
1724
- $rules .= "RewriteCond %{REQUEST_FILENAME} -d\n";
1725
- $rules .= "RewriteRule ^ - [L]\n";
1726
-
1727
- // @todo custom content dir.
1728
- if (!$subdomain_install) {
1729
- $rules .= "RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]\n";
1730
- $rules .= "RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\\.php)$ $2 [L]\n";
1731
- }
1732
-
1733
- $rules .= "RewriteRule . index.php [L]\n";
1734
- $rules .= "</IfModule>\n";
1735
- $rules .= "# END WordPress\n";
1736
- } else {
1737
- $home_path = w3_get_home_path();
1738
-
1739
- $rules .= "# BEGIN WordPress\n";
1740
- $rules .= "<IfModule mod_rewrite.c>\n";
1741
- $rules .= " RewriteEngine On\n";
1742
- $rules .= " RewriteBase " . $home_path . "\n";
1743
- $rules .= " RewriteCond %{REQUEST_FILENAME} !-f\n";
1744
- $rules .= " RewriteCond %{REQUEST_FILENAME} !-d\n";
1745
- $rules .= " RewriteRule . " . $home_path . "index.php [L]\n";
1746
- $rules .= "</IfModule>\n";
1747
- $rules .= "# END WordPress\n";
1748
- }
1749
-
1750
- return $rules;
1751
  }
1752
 
1753
  /**
1754
- * Add W3TC action callback
1755
- *
1756
- * @param string $action
1757
- * @param mixed $callback
1758
- * @return void
1759
  */
1760
- function w3tc_add_action($action, $callback)
1761
- {
1762
- global $_w3tc_actions;
1763
-
1764
- $_w3tc_actions[$action][] = $callback;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1765
  }
1766
 
1767
  /**
1768
- * Do W3TC action
1769
- *
1770
- * @param string $action
1771
- * @param mixed $value
1772
- * @return mixed
1773
  */
1774
- function w3tc_do_action($action, $value = null)
1775
- {
1776
- global $_w3tc_actions;
1777
-
1778
- if (isset($_w3tc_actions[$action])) {
1779
- foreach ((array) $_w3tc_actions[$action] as $callback) {
1780
- if (is_callable($callback)) {
1781
- $value = call_user_func($callback, $value);
1782
  }
1783
  }
 
1784
  }
1785
-
1786
- return $value;
1787
  }
1
  <?php
2
 
3
+ define('W3TC_VERSION', '0.9.1.4b');
4
  define('W3TC_POWERED_BY', 'W3 Total Cache/' . W3TC_VERSION);
5
  define('W3TC_EMAIL', 'w3tc@w3-edge.com');
6
  define('W3TC_PAYPAL_URL', 'https://www.paypal.com/cgi-bin/webscr');
9
  define('W3TC_LINK_NAME', 'WordPress Plugins');
10
  define('W3TC_FEED_URL', 'http://feeds.feedburner.com/W3TOTALCACHE');
11
  define('W3TC_README_URL', 'http://plugins.trac.wordpress.org/browser/w3-total-cache/trunk/readme.txt?format=txt');
 
12
  define('W3TC_SUPPORT_US_TIMEOUT', 2592000);
13
 
14
  define('W3TC_PHP5', PHP_VERSION >= 5);
20
  define('W3TC_LIB_W3_DIR', W3TC_LIB_DIR . '/W3');
21
  define('W3TC_LIB_MINIFY_DIR', W3TC_LIB_DIR . '/Minify');
22
  define('W3TC_LIB_CF_DIR', W3TC_LIB_DIR . '/CF');
23
+ define('W3TC_LIB_CSSTIDY_DIR', W3TC_LIB_DIR . '/CSSTidy');
24
+ define('W3TC_LIB_MICROSOFT_DIR', W3TC_LIB_DIR . '/Microsoft');
25
+ define('W3TC_LIB_NUSOAP_DIR', W3TC_LIB_DIR . '/Nusoap');
26
  define('W3TC_PLUGINS_DIR', W3TC_DIR . '/plugins');
27
  define('W3TC_INSTALL_DIR', W3TC_DIR . '/wp-content');
28
  define('W3TC_INSTALL_MINIFY_DIR', W3TC_INSTALL_DIR . '/w3tc/min');
50
  define('W3TC_MINIFY_LOG_FILE', W3TC_LOG_DIR . '/minify.log');
51
  define('W3TC_CDN_COMMAND_UPLOAD', 1);
52
  define('W3TC_CDN_COMMAND_DELETE', 2);
53
+ define('W3TC_CDN_COMMAND_PURGE', 3);
54
  define('W3TC_CDN_TABLE_QUEUE', 'w3tc_cdn_queue');
55
+ define('W3TC_CDN_LOG_FILE', W3TC_LOG_DIR . '/cdn.log');
56
+ define('W3TC_VARNISH_LOG_FILE', W3TC_LOG_DIR . '/varnish.log');
57
+
58
+ define('W3TC_MARKER_BEGIN_WORDPRESS', '# BEGIN WordPress');
59
+ define('W3TC_MARKER_BEGIN_SUPERCACHE', '# BEGIN WPSuperCache');
60
+ define('W3TC_MARKER_BEGIN_PGCACHE_CORE', '# BEGIN W3TC Page Cache core');
61
+ define('W3TC_MARKER_BEGIN_PGCACHE_CACHE', '# BEGIN W3TC Page Cache cache');
62
+ define('W3TC_MARKER_BEGIN_BROWSERCACHE_CACHE', '# BEGIN W3TC Browser Cache');
63
+ define('W3TC_MARKER_BEGIN_BROWSERCACHE_NO404WP', '# BEGIN W3TC Skip 404 error handling by WordPress for static files');
64
+ define('W3TC_MARKER_BEGIN_MINIFY_CORE', '# BEGIN W3TC Minify core');
65
+ define('W3TC_MARKER_BEGIN_MINIFY_CACHE', '# BEGIN W3TC Minify cache');
66
+
67
+ define('W3TC_MARKER_END_WORDPRESS', '# END WordPress');
68
+ define('W3TC_MARKER_END_SUPERCACHE', '# END WPSuperCache');
69
+ define('W3TC_MARKER_END_PGCACHE_CORE', '# END W3TC Page Cache core');
70
+ define('W3TC_MARKER_END_PGCACHE_CACHE', '# END W3TC Page Cache cache');
71
+ define('W3TC_MARKER_END_BROWSERCACHE_CACHE', '# END W3TC Browser Cache');
72
+ define('W3TC_MARKER_END_BROWSERCACHE_NO404WP', '# END W3TC Skip 404 error handling by WordPress for static files');
73
+ define('W3TC_MARKER_END_MINIFY_CORE', '# END W3TC Minify core');
74
+ define('W3TC_MARKER_END_MINIFY_CACHE', '# END W3TC Minify cache');
75
+
76
+ define('W3TC_INSTALL_FILE_ADVANCED_CACHE', W3TC_INSTALL_DIR . '/advanced-cache.php');
77
+ define('W3TC_INSTALL_FILE_DB', W3TC_INSTALL_DIR . '/db.php');
78
+ define('W3TC_INSTALL_FILE_OBJECT_CACHE', W3TC_INSTALL_DIR . '/object-cache.php');
79
+
80
+ define('W3TC_ADDIN_FILE_ADVANCED_CACHE', WP_CONTENT_DIR . '/advanced-cache.php');
81
+ define('W3TC_ADDIN_FILE_DB', WP_CONTENT_DIR . '/db.php');
82
+ define('W3TC_ADDIN_FILE_OBJECT_CACHE', WP_CONTENT_DIR . '/object-cache.php');
83
+
84
+ require_once W3TC_DIR . '/inc/compat.php';
85
+ require_once W3TC_DIR . '/inc/plugin.php';
86
 
87
  @ini_set('pcre.backtrack_limit', 4194304);
88
  @ini_set('pcre.recursion_limit', 4194304);
89
 
 
 
90
  /**
91
  * Deactivate plugin after activation error
92
+ *
93
  * @return void
94
  */
95
+ function w3_activation_cleanup() {
 
96
  $active_plugins = (array) get_option('active_plugins');
97
  $active_plugins_network = (array) get_site_option('active_sitewide_plugins');
98
+
99
  // workaround for WPMU deactivation bug
100
  remove_action('deactivate_' . W3TC_FILE, 'deactivate_sitewide_plugin');
101
+
102
  do_action('deactivate_plugin', W3TC_FILE);
103
+
104
  $key = array_search(W3TC_FILE, $active_plugins);
105
+
106
  if ($key !== false) {
107
  array_splice($active_plugins, $key, 1);
108
  }
109
+
110
  unset($active_plugins_network[W3TC_FILE]);
111
+
112
  do_action('deactivate_' . W3TC_FILE);
113
  do_action('deactivated_plugin', W3TC_FILE);
114
+
115
  update_option('active_plugins', $active_plugins);
116
  update_site_option('active_sitewide_plugins', $active_plugins_network);
117
  }
122
  * @param string $error
123
  * @return void
124
  */
125
+ function w3_activate_error($error) {
 
126
  w3_activation_cleanup();
127
+
128
  include W3TC_DIR . '/inc/error.phtml';
129
  exit();
130
  }
135
  * @param string $path
136
  * @return string
137
  */
138
+ function w3_writable_error($path) {
 
139
  $activate_url = wp_nonce_url('plugins.php?action=activate&plugin=' . W3TC_FILE, 'activate-plugin_' . W3TC_FILE);
140
  $reactivate_button = sprintf('<input type="button" value="re-activate plugin" onclick="top.location.href = \'%s\'" />', addslashes($activate_url));
141
+
142
  if (w3_check_open_basedir($path)) {
143
  $error = sprintf('<strong>%s</strong> could not be created, please run following command:<br /><strong style="color: #f00;">chmod 777 %s</strong><br />then %s.', $path, (file_exists($path) ? $path : dirname($path)), $reactivate_button);
144
  } else {
145
  $error = sprintf('<strong>%s</strong> could not be created, <strong>open_basedir</strong> restriction in effect, please check your php.ini settings:<br /><strong style="color: #f00;">open_basedir = "%s"</strong><br />then %s.', $path, ini_get('open_basedir'), $reactivate_button);
146
  }
147
+
148
  w3_activate_error($error);
149
  }
150
 
151
  /**
152
  * W3 Network activation error
153
+ *
154
  * @return void
155
  */
156
+ function w3_network_activate_error() {
 
157
  w3_activation_cleanup();
158
  wp_redirect(plugins_url('inc/network_activation.php', W3TC_FILE));
159
+
160
  echo '<p><strong>W3 Total Cache Error:</strong> plugin cannot be activated network-wide.</p>';
161
  echo '<p><a href="javascript:history.back(-1);">Back</a>';
162
  exit();
165
  /**
166
  * Returns current microtime
167
  *
168
+ * @return double
169
  */
170
+ function w3_microtime() {
171
+ list ($usec, $sec) = explode(' ', microtime());
172
+
173
+ return ((double) $usec + (double) $sec);
174
  }
175
 
176
  /**
181
  * @param string
182
  * @return boolean
183
  */
184
+ function w3_mkdir($path, $mask = 0777, $curr_path = '') {
 
185
  $path = w3_realpath($path);
186
  $path = trim($path, '/');
187
  $dirs = explode('/', $path);
188
+
189
  foreach ($dirs as $dir) {
190
  if ($dir == '') {
191
  return false;
192
  }
193
+
194
  $curr_path .= ($curr_path == '' ? '' : '/') . $dir;
195
+
196
  if (!@is_dir($curr_path)) {
197
+ if (!@mkdir($curr_path, $mask)) {
 
 
198
  return false;
199
  }
200
  }
201
  }
202
+
203
  return true;
204
  }
205
 
210
  * @param array $exclude
211
  * @return void
212
  */
213
+ function w3_rmdir($path, $exclude = array(), $remove = true) {
 
214
  $dir = @opendir($path);
215
+
216
  if ($dir) {
217
  while (($entry = @readdir($dir)) !== false) {
218
  $full_path = $path . '/' . $entry;
219
+
220
  if ($entry != '.' && $entry != '..' && !in_array($full_path, $exclude)) {
221
  if (@is_dir($full_path)) {
222
  w3_rmdir($full_path, $exclude);
225
  }
226
  }
227
  }
228
+
229
  @closedir($dir);
230
+
231
  if ($remove) {
232
  @rmdir($path);
233
  }
241
  * @param array $exclude
242
  * @return void
243
  */
244
+ function w3_emptydir($path, $exclude = array()) {
 
245
  w3_rmdir($path, $exclude, false);
246
  }
247
 
251
  * @param string $content
252
  * @return boolean
253
  */
254
+ function w3_is_xml($content) {
255
+ if (strlen($content) > 1000) {
256
+ $content = substr($content, 0, 1000);
257
+ }
258
+
259
+ if (strstr($content, '<!--') !== false) {
260
+ $content = preg_replace('~<!--.*?-->~s', '', $content);
261
+ }
262
+
263
+ $content = ltrim($content);
264
+
265
+ return (stripos($content, '<?xml') === 0 || stripos($content, '<html') === 0 || stripos($content, '<!DOCTYPE') === 0);
266
  }
267
 
268
  /**
270
  *
271
  * @return boolean
272
  */
273
+ function w3_is_wpmu() {
 
274
  static $wpmu = null;
275
+
276
  if ($wpmu === null) {
277
+ $wpmu = file_exists(ABSPATH . 'wpmu-settings.php');
278
  }
279
+
280
  return $wpmu;
281
  }
282
 
283
  /**
284
+ * Returns true if WPMU uses vhosts
285
  *
286
  * @return boolean
287
  */
288
+ function w3_is_subdomain_install() {
289
+ return ((defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) || (defined('VHOST') && VHOST == 'yes'));
 
 
 
 
 
 
 
290
  }
291
 
292
  /**
293
+ * Returns true if it's WP with enabled Network mode
294
+ *
295
  * @return boolean
296
  */
297
+ function w3_is_multisite() {
298
+ static $multisite = null;
299
+
300
+ if ($multisite === null) {
301
+ $multisite = ((defined('MULTISITE') && MULTISITE) || defined('SUNRISE') || w3_is_subdomain_install());
302
+ }
303
+
304
+ return $multisite;
305
  }
306
 
307
  /**
308
+ * Returns if there is multisite mode
309
  *
310
  * @return boolean
311
  */
312
+ function w3_is_network() {
313
+ return (w3_is_wpmu() || w3_is_multisite());
 
314
  }
315
 
316
  /**
319
  * @param string $url
320
  * @return boolean
321
  */
322
+ function w3_is_url($url) {
 
323
  return preg_match('~^https?://~', $url);
324
  }
325
 
328
  *
329
  * @return boolean
330
  */
331
+ function w3_is_https() {
 
332
  switch (true) {
333
  case (isset($_SERVER['HTTPS']) && w3_to_boolean($_SERVER['HTTPS'])):
334
  case (isset($_SERVER['SERVER_PORT']) && (int) $_SERVER['SERVER_PORT'] == 443):
335
  return true;
336
  }
337
+
338
  return false;
339
  }
340
 
341
  /**
342
  * Check if WP permalink directives exists
343
+ *
344
  * @return boolean
345
  */
346
+ function w3_is_permalink_rules() {
347
+ if (w3_is_apache() && !w3_is_network()) {
348
+ $path = w3_get_home_root() . '/.htaccess';
349
+
350
+ return (($data = @file_get_contents($path)) && strstr($data, W3TC_MARKER_BEGIN_WORDPRESS) !== false);
351
+ }
352
+
353
+ return true;
354
  }
355
 
356
  /**
357
  * Check if there was database error
358
+ *
359
  * @param string $content
360
  * @return boolean
361
  */
362
+ function w3_is_database_error(&$content) {
 
363
  return (stristr($content, '<title>Database Error</title>') !== false);
364
  }
365
 
366
  /**
367
  * Returns true if preview config exists
368
+ *
369
  * @return boolean
370
  */
371
+ function w3_is_preview_config() {
 
372
  return file_exists(W3TC_CONFIG_PREVIEW_PATH);
373
  }
374
 
375
  /**
376
  * Retuns true if preview settings active
377
+ *
378
  * @return boolean
379
  */
380
+ function w3_is_preview_mode() {
381
+ return (w3_is_preview_config() && (defined('WP_ADMIN') || isset($_REQUEST['w3tc_preview']) || (isset($_SERVER['HTTP_REFERER']) && strstr($_SERVER['HTTP_REFERER'], 'w3tc_preview') !== false)));
 
382
  }
383
 
384
  /**
385
  * Check if file is write-able
386
+ *
387
  * @param string $path
388
  * @return boolean
389
  */
390
+ function w3_is_writable($file) {
 
391
  $exists = file_exists($file);
392
+
393
  $fp = @fopen($file, 'a');
394
+
395
  if ($fp) {
396
  fclose($fp);
397
+
398
  if (!$exists) {
399
  @unlink($file);
400
  }
401
+
402
  return true;
403
  }
404
+
405
  return false;
406
  }
407
 
408
  /**
409
  * Cehck if dir is write-able
410
+ *
411
  * @param string $dir
412
  * @return boolean
413
  */
414
+ function w3_is_writable_dir($dir) {
 
415
  $file = $dir . '/' . uniqid(mt_rand()) . '.tmp';
416
+
417
  return w3_is_writable($file);
418
  }
419
 
420
+ /**
421
+ * Returns true if server is Apache
422
+ *
423
+ * @return boolean
424
+ */
425
+ function w3_is_apache() {
426
+ return (isset($_SERVER['SERVER_SOFTWARE']) && stristr($_SERVER['SERVER_SOFTWARE'], 'apache') !== false);
427
+ }
428
+
429
+ /**
430
+ * Returns true if server is nginx
431
+ *
432
+ * @return boolean
433
+ */
434
+ function w3_is_nginx() {
435
+ return (isset($_SERVER['SERVER_SOFTWARE']) && stristr($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false);
436
+ }
437
+
438
+ /**
439
+ * Returns true if CDN engine is mirror
440
+ *
441
+ * @param string $engine
442
+ * @return bool
443
+ */
444
+ function w3_is_cdn_mirror($engine) {
445
+ return in_array($engine, array('mirror', 'netdna', 'cotendo', 'cf2'));
446
+ }
447
+
448
  /**
449
  * Returns domain from host
450
  *
451
  * @param string $host
452
  * @return string
453
  */
454
+ function w3_get_domain($host) {
 
455
  $host = strtolower($host);
456
+
457
  if (strpos($host, 'www.') === 0) {
458
  $host = substr($host, 4);
459
  }
460
+
461
  if (($pos = strpos($host, ':')) !== false) {
462
  $host = substr($host, 0, $pos);
463
  }
464
+
465
  $host = rtrim($host, '.');
466
+
467
  return $host;
468
  }
469
 
470
  /**
471
  * Returns array of all available blognames
472
+ *
473
  * @return array
474
  */
475
+ function w3_get_blognames() {
 
476
  global $wpdb;
477
+
478
  $blognames = array();
479
+
480
  $sql = sprintf('SELECT domain, path FROM %s', $wpdb->blogs);
481
  $blogs = $wpdb->get_results($sql);
482
+
483
  if ($blogs) {
484
  $base_path = w3_get_base_path();
485
+
486
  foreach ($blogs as $blog) {
487
  $blogname = trim(str_replace($base_path, '', $blog->path), '/');
488
+
489
  if ($blogname) {
490
  $blognames[] = $blogname;
491
  }
492
  }
493
  }
494
+
495
  return $blognames;
496
  }
497
 
498
  /**
499
  * Load blognames from file
500
+ *
501
  * @return array
502
  */
503
+ function w3_load_blognames() {
 
504
  $blognames = include W3TC_BLOGNAMES_PATH;
505
+
506
  return $blognames;
507
  }
508
 
509
  /**
510
  * Save blognames into file
511
+ *
512
  * @param string $blognames
513
  * @return boolean
514
  */
515
+ function w3_save_blognames($blognames = null) {
 
516
  if (!$blognames) {
517
  $blognames = w3_get_blognames();
518
  }
519
+
520
  $strings = array();
521
+
522
  foreach ($blognames as $blogname) {
523
  $strings[] = sprintf("'%s'", addslashes($blogname));
524
  }
525
+
526
  $data = sprintf('<?php return array(%s);', implode(', ', $strings));
527
+
528
  return @file_put_contents(W3TC_BLOGNAMES_PATH, $data);
529
  }
530
 
533
  *
534
  * @return string
535
  */
536
+ function w3_get_blogname() {
 
537
  static $blogname = null;
538
+
539
  if ($blogname === null) {
540
+ if (w3_is_network()) {
541
  $host = w3_get_host();
542
  $domain = w3_get_domain($host);
543
+
544
+ if (w3_is_subdomain_install()) {
545
  $blogname = $domain;
546
  } else {
547
  $uri = $_SERVER['REQUEST_URI'];
548
  $base_path = w3_get_base_path();
549
+
550
  if ($base_path != '' && strpos($uri, $base_path) === 0) {
551
  $uri = substr_replace($uri, '/', 0, strlen($base_path));
552
  }
553
+
554
  $blogname = w3_get_blogname_from_uri($uri);
555
+
556
  if ($blogname != '') {
557
  $blogname = $blogname . '.' . $domain;
558
  } else {
563
  $blogname = '';
564
  }
565
  }
566
+
567
  return $blogname;
568
  }
569
 
573
  * @param string $uri
574
  * @param string
575
  */
576
+ function w3_get_blogname_from_uri($uri) {
 
577
  $blogname = '';
578
  $matches = null;
579
  $uri = strtolower($uri);
580
+
581
  if (preg_match('~^/([a-z0-9-]+)/~', $uri, $matches)) {
582
  if (file_exists(W3TC_BLOGNAMES_PATH)) {
583
  // Get blognames from cache
588
  } else {
589
  $blognames = array();
590
  }
591
+
592
  if (is_array($blognames) && in_array($matches[1], $blognames)) {
593
  $blogname = $matches[1];
594
  }
595
  }
596
+
597
  return $blogname;
598
  }
599
 
600
+ /**
601
+ * Returns current blog ID
602
+ *
603
+ * @return integer
604
+ */
605
+ function w3_get_blog_id() {
606
+ return (isset($GLOBALS['blog_id']) ? (int) $GLOBALS['blog_id'] : 0);
607
+ }
608
+
609
  /**
610
  * Returns URL regexp from URL
611
+ *
612
  * @param string $url
613
  * @return string
614
  */
615
+ function w3_get_url_regexp($url) {
 
616
  $url = preg_replace('~https?://~i', '', $url);
617
  $url = preg_replace('~^www\.~i', '', $url);
618
+
619
  $regexp = 'https?://(www\.)?' . w3_preg_quote($url);
620
+
621
  return $regexp;
622
  }
623
 
626
  * @param string $url
627
  * @return string
628
  */
629
+ function w3_get_url_ssl($url) {
 
630
  if (w3_is_https()) {
631
  $url = str_replace('http://', 'https://', $url);
632
  }
633
+
634
  return $url;
635
  }
636
 
640
  * @return string
641
  */
642
 
643
+ function w3_get_domain_url() {
644
+ $home_url = w3_get_home_url();
645
+ $parse_url = @parse_url($home_url);
646
+
 
647
  if ($parse_url && isset($parse_url['scheme']) && isset($parse_url['host'])) {
648
  $scheme = $parse_url['scheme'];
649
  $host = $parse_url['host'];
650
  $port = (isset($parse_url['port']) && $parse_url['port'] != 80 ? ':' . (int) $parse_url['port'] : '');
651
  $domain_url = sprintf('%s://%s%s', $scheme, $host, $port);
652
+
653
  return $domain_url;
654
  }
655
+
656
  return false;
657
  }
658
 
661
  *
662
  * @return string
663
  */
664
+ function w3_get_domain_url_regexp() {
 
665
  $domain_url = w3_get_domain_url();
666
  $regexp = w3_get_url_regexp($domain_url);
667
+
668
  return $regexp;
669
  }
670
 
671
  /**
672
  * Returns home URL
673
+ *
674
  * No trailing slash!
675
+ *
676
  * @return string
677
  */
678
+ function w3_get_home_url() {
 
679
  static $home_url = null;
680
+
681
  if ($home_url === null) {
682
+ $home_url = get_option('home');
 
 
 
 
 
683
  $home_url = rtrim($home_url, '/');
684
  }
685
+
686
  return $home_url;
687
  }
688
 
691
  *
692
  * @return string
693
  */
694
+ function w3_get_home_url_ssl() {
 
695
  $home_url = w3_get_home_url();
696
  $ssl = w3_get_url_ssl($home_url);
697
+
698
  return $ssl;
699
  }
700
 
701
  /**
702
+ * Returns home url regexp
 
 
703
  *
704
  * @return string
705
  */
706
+ function w3_get_home_url_regexp() {
707
+ $home_url = w3_get_home_url();
708
+ $regexp = w3_get_url_regexp($home_url);
 
 
 
 
 
 
 
 
 
 
 
 
 
709
 
710
+ return $regexp;
 
 
 
 
 
 
 
 
 
 
711
  }
712
 
713
  /**
714
+ * Returns site URL
715
+ *
716
+ * No trailing slash!
717
  *
718
  * @return string
719
  */
720
+ function w3_get_site_url() {
721
+ static $site_url = null;
722
+
723
+ if ($site_url === null) {
724
+ $site_url = get_option('siteurl');
725
+ $site_url = rtrim($site_url, '/');
726
+ }
727
+
728
+ return $site_url;
729
  }
730
 
731
  /**
732
  * Returns absolute path to document root
733
+ *
734
  * No trailing slash!
735
+ *
736
  * @return string
737
  */
738
+ function w3_get_document_root() {
 
739
  static $document_root = null;
740
+
741
  if ($document_root === null) {
742
+ if (!empty($_SERVER['SCRIPT_FILENAME'])) {
743
  $document_root = substr($_SERVER['SCRIPT_FILENAME'], 0, -strlen($_SERVER['PHP_SELF']));
744
+ } elseif (!empty($_SERVER['PATH_TRANSLATED'])) {
745
  $document_root = substr($_SERVER['PATH_TRANSLATED'], 0, -strlen($_SERVER['PHP_SELF']));
746
+ } elseif (!empty($_SERVER['DOCUMENT_ROOT'])) {
747
  $document_root = $_SERVER['DOCUMENT_ROOT'];
748
  } else {
749
  $document_root = w3_get_site_root();
750
  }
751
+
752
  $document_root = realpath($document_root);
753
  $document_root = w3_path($document_root);
754
  }
755
+
756
  return $document_root;
757
  }
758
 
759
  /**
760
  * Returns absolute path to home directory
761
+ *
762
  * Example:
763
+ *
764
  * DOCUMENT_ROOT=/var/www/vhosts/domain.com
765
  * Install dir=/var/www/vhosts/domain.com/site/blog
766
  * home=http://domain.com/site
767
  * siteurl=http://domain.com/site/blog
768
  * return /var/www/vhosts/domain.com/site
769
+ *
770
  * No trailing slash!
771
+ *
772
  * @return string
773
  */
774
+ function w3_get_home_root() {
775
+ if (w3_is_network()) {
 
 
 
 
776
  $path = w3_get_base_path();
777
  } else {
778
  $path = w3_get_home_path();
779
  }
780
+
781
  $home_root = w3_get_document_root() . $path;
782
  $home_root = realpath($home_root);
783
  $home_root = w3_path($home_root);
784
+
785
  return $home_root;
786
  }
787
 
788
  /**
789
  * Returns absolute path to blog install dir
790
+ *
791
  * Example:
792
+ *
793
  * DOCUMENT_ROOT=/var/www/vhosts/domain.com
794
  * install dir=/var/www/vhosts/domain.com/site/blog
795
  * return /var/www/vhosts/domain.com/site/blog
796
+ *
797
  * No trailing slash!
798
+ *
799
  * @return string
800
  */
801
+ function w3_get_site_root() {
 
802
  $site_root = ABSPATH;
803
  $site_root = realpath($site_root);
804
  $site_root = w3_path($site_root);
805
+
806
  return $site_root;
807
  }
808
 
809
  /**
810
  * Returns blog path
811
+ *
812
  * Example:
813
+ *
814
  * siteurl=http://domain.com/site/blog
815
  * return /site/blog/
816
  *
818
  *
819
  * @return string
820
  */
821
+ function w3_get_site_path() {
 
822
  $site_url = w3_get_site_url();
823
  $parse_url = @parse_url($site_url);
824
+
825
  if ($parse_url && isset($parse_url['path'])) {
826
  $site_path = '/' . ltrim($parse_url['path'], '/');
827
  } else {
828
  $site_path = '/';
829
  }
830
+
831
  if (substr($site_path, -1) != '/') {
832
  $site_path .= '/';
833
  }
834
+
835
  return $site_path;
836
  }
837
 
838
  /**
839
  * Returns home path
840
+ *
841
  * Example:
842
+ *
843
  * home=http://domain.com/site/
844
  * siteurl=http://domain.com/site/blog
845
  * return /site/
848
  *
849
  * @return string
850
  */
851
+ function w3_get_home_path() {
 
852
  $home_url = w3_get_home_url();
853
  $parse_url = @parse_url($home_url);
854
+
855
  if ($parse_url && isset($parse_url['path'])) {
856
  $home_path = '/' . ltrim($parse_url['path'], '/');
857
  } else {
858
  $home_path = '/';
859
  }
860
+
861
  if (substr($home_path, -1) != '/') {
862
  $home_path .= '/';
863
  }
864
+
865
  return $home_path;
866
  }
867
 
868
  /**
869
  * Returns path to WP directory relative to document root
870
+ *
871
  * Example:
872
+ *
873
  * DOCUMENT_ROOT=/var/www/vhosts/domain.com/
874
  * Install dir=/var/www/vhosts/domain.com/site/blog/
875
  * return /site/blog/
876
+ *
877
  * With trailing slash!
878
+ *
879
  * @return string
880
  */
881
+ function w3_get_base_path() {
 
882
  $document_root = w3_get_document_root();
883
  $site_root = w3_get_site_root();
884
+
885
  $base_path = str_replace($document_root, '', $site_root);
886
  $base_path = '/' . ltrim($base_path, '/');
887
+
888
  if (substr($base_path, -1) != '/') {
889
  $base_path .= '/';
890
  }
891
+
892
  return $base_path;
893
  }
894
 
895
  /**
896
  * Returns server hostname
897
+ *
898
  * @return string
899
  */
900
+ function w3_get_host() {
 
901
  static $host = null;
902
+
903
  if ($host === null) {
904
+ $host = (!empty($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']);
905
  }
906
+
907
  return $host;
908
  }
909
 
910
  /**
911
+ * Returns host ID
912
  *
 
 
 
913
  * @return string
914
  */
915
+ function w3_get_host_id() {
916
+ static $host_id = null;
917
+
918
+ if ($host_id === null) {
919
+ $host = w3_get_host();
920
+ $blog_id = w3_get_blog_id();
921
+
922
+ $host_id = sprintf('%s_%d', $host, $blog_id);
 
 
 
 
 
923
  }
924
+
925
+ return $host_id;
926
  }
927
 
928
  /**
929
+ * Returns nginx rules path
930
+ *
 
 
 
931
  * @return string
932
  */
933
+ function w3_get_nginx_rules_path() {
934
+ require_once W3TC_LIB_W3_DIR . '/Config.php';
935
+ $config =& W3_Config::instance();
936
+
937
+ $path = $config->get_string('config.path');
938
+
939
+ if (!$path) {
940
+ $path = w3_get_document_root() . '/nginx.conf';
 
 
 
 
 
941
  }
942
+
943
+ return $path;
944
  }
945
 
946
  /**
947
+ * Returns path of pagecache core rules file
948
+ *
 
949
  * @return string
950
  */
951
+ function w3_get_pgcache_rules_core_path() {
952
+ switch (true) {
953
+ case w3_is_apache():
954
+ return w3_get_home_root() . '/.htaccess';
955
+
956
+ case w3_is_nginx():
957
+ return w3_get_nginx_rules_path();
958
  }
959
+
960
+ return false;
961
  }
962
 
963
  /**
964
+ * Returns path of pgcache cache rules file
965
  *
 
966
  * @return string
967
  */
968
+ function w3_get_pgcache_rules_cache_path() {
969
+ switch (true) {
970
+ case w3_is_apache():
971
+ return W3TC_CACHE_FILE_PGCACHE_DIR . '/.htaccess';
972
+
973
+ case w3_is_nginx():
974
+ return w3_get_nginx_rules_path();
975
+ }
976
+
977
+ return false;
978
  }
979
 
980
  /**
981
+ * Returns path of browsercache cache rules file
982
  *
983
+ * @return string
984
+ */
985
+ function w3_get_browsercache_rules_cache_path() {
986
+ switch (true) {
987
+ case w3_is_apache():
988
+ return w3_get_home_root() . '/.htaccess';
989
+
990
+ case w3_is_nginx():
991
+ return w3_get_nginx_rules_path();
992
+ }
993
+
994
+ return false;
995
+ }
996
+
997
+ /**
998
+ * Returns path of browsercache no404wp rules file
999
+ *
1000
+ * @return string
1001
+ */
1002
+ function w3_get_browsercache_rules_no404wp_path() {
1003
+ switch (true) {
1004
+ case w3_is_apache():
1005
+ return w3_get_home_root() . '/.htaccess';
1006
+
1007
+ case w3_is_nginx():
1008
+ return w3_get_nginx_rules_path();
1009
+ }
1010
+
1011
+ return false;
1012
+ }
1013
+
1014
+ /**
1015
+ * Returns path of minify rules file
1016
+ *
1017
+ * @return string
1018
  */
1019
+ function w3_get_minify_rules_core_path() {
1020
+ switch (true) {
1021
+ case w3_is_apache():
1022
+ return W3TC_CACHE_FILE_MINIFY_DIR . '/.htaccess';
1023
+
1024
+ case w3_is_nginx():
1025
+ return w3_get_nginx_rules_path();
1026
+ }
1027
+
1028
+ return false;
1029
+ }
1030
+
1031
+ /**
1032
+ * Returns path of minify rules file
1033
+ *
1034
+ * @return string
1035
+ */
1036
+ function w3_get_minify_rules_cache_path() {
1037
+ switch (true) {
1038
+ case w3_is_apache():
1039
+ return W3TC_CACHE_FILE_MINIFY_DIR . '/.htaccess';
1040
+
1041
+ case w3_is_nginx():
1042
+ return w3_get_nginx_rules_path();
1043
+ }
1044
+
1045
+ return false;
1046
+ }
1047
+
1048
+ /**
1049
+ * Returns WP config file path
1050
+ *
1051
+ * @return string
1052
+ */
1053
+ function w3_get_wp_config_path() {
1054
+ $search = array(
1055
+ ABSPATH . 'wp-config.php',
1056
+ dirname(ABSPATH) . '/wp-config.php'
1057
+ );
1058
+
1059
+ foreach ($search as $path) {
1060
+ if (file_exists($path)) {
1061
+ return $path;
1062
+ }
1063
+ }
1064
+
1065
+ return false;
1066
+ }
1067
+
1068
+ /**
1069
+ * Returns theme key
1070
+ *
1071
+ * @param string $theme_root
1072
+ * @param string $template
1073
+ * @param string $stylesheet
1074
+ * @return string
1075
+ */
1076
+ function w3_get_theme_key($theme_root, $template, $stylesheet) {
1077
+ $site_root = w3_get_site_root();
1078
+ $theme_path = ltrim(str_replace($site_root, '', w3_path($theme_root)), '/');
1079
+
1080
+ return substr(md5($theme_path . $template . $stylesheet), 0, 5);
1081
+ }
1082
+
1083
+ /**
1084
+ * Returns theme key (legacy support)
1085
+ *
1086
+ * @param string $theme_root
1087
+ * @param string $template
1088
+ * @param string $stylesheet
1089
+ * @return string
1090
+ */
1091
+ function w3_get_theme_key_legacy($theme_root, $template, $stylesheet) {
1092
+ return substr(md5($theme_root . $template . $stylesheet), 0, 6);
1093
+ }
1094
+
1095
+ /**
1096
+ * Returns path of minify rules file
1097
+ *
1098
+ * @return string
1099
+ */
1100
+ function w3_get_cdn_rules_path() {
1101
+ switch (true) {
1102
+ case w3_is_apache():
1103
+ return '.htaccess';
1104
+
1105
+ case w3_is_nginx():
1106
+ return 'nginx.conf';
1107
+ }
1108
+
1109
+ return false;
1110
+ }
1111
+
1112
+ /**
1113
+ * Returns true if we can check rules
1114
+ *
1115
+ * @return bool
1116
+ */
1117
+ function w3_can_check_rules() {
1118
+ return (w3_is_apache() || w3_is_nginx());
1119
+ }
1120
+
1121
+ /**
1122
+ * Returns true if we can modify rules
1123
+ *
1124
+ * @param string $path
1125
+ * @return boolean
1126
+ */
1127
+ function w3_can_modify_rules($path) {
1128
+ if (w3_is_apache()) {
1129
+ switch ($path) {
1130
+ case w3_get_pgcache_rules_cache_path():
1131
+ case w3_get_minify_rules_core_path():
1132
+ case w3_get_minify_rules_cache_path():
1133
+ return true;
1134
+ }
1135
+ }
1136
+
1137
+ return false;
1138
+ }
1139
+
1140
+ /**
1141
+ * Returns true if CDN engine is supporting purge
1142
+ *
1143
+ * @param string $engine
1144
+ * @return bool
1145
+ */
1146
+ function w3_can_cdn_purge($engine) {
1147
+ return in_array($engine, array('ftp', 's3', 'cf', 'cf2', 'rscf', 'azure', 'netdna', 'cotendo'));
1148
+ }
1149
+
1150
+ /**
1151
+ * Parses path
1152
+ *
1153
+ * @param string $path
1154
+ * @return mixed
1155
+ */
1156
+ function w3_parse_path($path) {
1157
+ $path = str_replace(array(
1158
+ '%BLOG_ID%',
1159
+ '%POST_ID%',
1160
+ '%BLOGNAME%',
1161
+ '%HOST%',
1162
+ '%DOMAIN%',
1163
+ '%BASE_PATH%'
1164
+ ), array(
1165
+ (isset($GLOBALS['blog_id']) ? (int) $GLOBALS['blog_id'] : 0),
1166
+ (isset($GLOBALS['post_id']) ? (int) $GLOBALS['post_id'] : 0),
1167
+ w3_get_blogname(),
1168
+ w3_get_host(),
1169
+ w3_get_domain(w3_get_host()),
1170
+ trim(w3_get_base_path(), '/')
1171
+ ), $path);
1172
+
1173
+ return $path;
1174
+ }
1175
+
1176
+ /**
1177
+ * Normalizes file name
1178
+ *
1179
+ * Relative to site root!
1180
+ *
1181
+ * @param string $file
1182
+ * @return string
1183
+ */
1184
+ function w3_normalize_file($file) {
1185
+ if (w3_is_url($file)) {
1186
+ if (strstr($file, '?') === false) {
1187
+ $home_url_regexp = '~' . w3_get_home_url_regexp() . '~i';
1188
+ $file = preg_replace($home_url_regexp, '', $file);
1189
+ }
1190
+ }
1191
+
1192
+ if (!w3_is_url($file)) {
1193
+ $file = w3_path($file);
1194
+ $file = str_replace(w3_get_site_root(), '', $file);
1195
+ $file = ltrim($file, '/');
1196
+ }
1197
+
1198
+ return $file;
1199
+ }
1200
+
1201
+ /**
1202
+ * Normalizes file name for minify
1203
+ *
1204
+ * Relative to document root!
1205
+ *
1206
+ * @param string $file
1207
+ * @return string
1208
+ */
1209
+ function w3_normalize_file_minify($file) {
1210
+ if (w3_is_url($file)) {
1211
+ if (strstr($file, '?') === false) {
1212
+ $domain_url_regexp = '~' . w3_get_domain_url_regexp() . '~i';
1213
+ $file = preg_replace($domain_url_regexp, '', $file);
1214
+ }
1215
+ }
1216
+
1217
+ if (!w3_is_url($file)) {
1218
+ $file = w3_path($file);
1219
+ $file = str_replace(w3_get_document_root(), '', $file);
1220
+ $file = ltrim($file, '/');
1221
+ }
1222
+
1223
+ return $file;
1224
+ }
1225
+
1226
+ /**
1227
+ * Normalizes file name for minify
1228
+ *
1229
+ * Relative to document root!
1230
+ *
1231
+ * @param string $file
1232
+ * @return string
1233
+ */
1234
+ function w3_normalize_file_minify2($file) {
1235
+ $file = w3_remove_wp_query($file);
1236
+ $file = w3_normalize_file_minify($file);
1237
+ $file = w3_translate_file($file);
1238
+
1239
+ return $file;
1240
+ }
1241
+
1242
+ /**
1243
+ * Translates remote file to local file
1244
+ *
1245
+ * @param string $file
1246
+ * @return string
1247
+ */
1248
+ function w3_translate_file($file) {
1249
+ if (!w3_is_url($file)) {
1250
+ $file = '/' . ltrim($file, '/');
1251
+ $regexp = '~^' . w3_preg_quote(w3_get_site_path()) . '~';
1252
+ $file = preg_replace($regexp, w3_get_base_path(), $file);
1253
+ $file = ltrim($file, '/');
1254
+ }
1255
+
1256
+ return $file;
1257
+ }
1258
+
1259
+ /**
1260
+ * Remove WP query string from URL
1261
+ *
1262
+ * @param string $url
1263
+ * @return string
1264
+ */
1265
+ function w3_remove_wp_query($url) {
1266
+ $url = preg_replace('~[&\?]?ver=[a-z0-9-_\.]*~i', '', $url);
1267
+
1268
+ return $url;
1269
+ }
1270
+
1271
+ /**
1272
+ * Converts win path to unix
1273
+ *
1274
+ * @param string $path
1275
+ * @return string
1276
+ */
1277
+ function w3_path($path) {
1278
+ $path = preg_replace('~[/\\\]+~', '/', $path);
1279
+ $path = rtrim($path, '/');
1280
+
1281
+ return $path;
1282
+ }
1283
+
1284
+ /**
1285
+ * Returns realpath of given path
1286
+ *
1287
+ * @param string $path
1288
+ */
1289
+ function w3_realpath($path) {
1290
  $path = w3_path($path);
1291
  $parts = explode('/', $path);
1292
  $absolutes = array();
1293
+
1294
  foreach ($parts as $part) {
1295
  if ('.' == $part) {
1296
  continue;
1301
  $absolutes[] = $part;
1302
  }
1303
  }
1304
+
1305
  return implode('/', $absolutes);
1306
  }
1307
 
1308
  /**
1309
  * Returns dirname of path
1310
+ *
1311
  * @param string $path
1312
  * @return string
1313
  */
1314
+ function w3_dirname($path) {
 
1315
  $dirname = dirname($path);
1316
+
1317
  if ($dirname == '.' || $dirname == '/' || $dirname == '\\') {
1318
  $dirname = '';
1319
  }
1320
+
1321
  return $dirname;
1322
  }
1323
 
1326
  *
1327
  * @return array
1328
  */
1329
+ function w3_get_open_basedirs() {
 
1330
  $open_basedir_ini = ini_get('open_basedir');
1331
  $open_basedirs = (W3TC_WIN ? preg_split('~[;,]~', $open_basedir_ini) : explode(':', $open_basedir_ini));
1332
  $result = array();
1333
+
1334
  foreach ($open_basedirs as $open_basedir) {
1335
  $open_basedir = trim($open_basedir);
1336
  if ($open_basedir != '') {
1337
  $result[] = w3_realpath($open_basedir);
1338
  }
1339
  }
1340
+
1341
  return $result;
1342
  }
1343
 
1347
  * @param string $path
1348
  * @return boolean
1349
  */
1350
+ function w3_check_open_basedir($path) {
 
1351
  $path = w3_realpath($path);
1352
  $open_basedirs = w3_get_open_basedirs();
1353
+
1354
  if (!count($open_basedirs)) {
1355
  return true;
1356
  }
1357
+
1358
  foreach ($open_basedirs as $open_basedir) {
1359
  if (strstr($path, $open_basedir) !== false) {
1360
  return true;
1361
  }
1362
  }
1363
+
1364
  return false;
1365
  }
1366
 
1374
  * @param boolean $check_status
1375
  * @return string
1376
  */
1377
+ function w3_http_request($method, $url, $data = '', $auth = '', $check_status = true) {
 
1378
  $status = 0;
1379
  $method = strtoupper($method);
1380
+
1381
  if (function_exists('curl_init')) {
1382
  $ch = curl_init();
1383
+
1384
  curl_setopt($ch, CURLOPT_URL, $url);
1385
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1386
  curl_setopt($ch, CURLOPT_USERAGENT, W3TC_POWERED_BY);
1388
  curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
1389
  curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
1390
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
1391
+ curl_setopt($ch, CURLOPT_TIMEOUT, 60);
1392
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
1393
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
1394
+
1395
  switch ($method) {
1396
  case 'POST':
1397
  curl_setopt($ch, CURLOPT_POST, true);
1398
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
1399
  break;
1400
+
1401
  case 'PURGE':
1402
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PURGE');
1403
  break;
1404
  }
1405
+
1406
  if ($auth) {
1407
  curl_setopt($ch, CURLOPT_USERPWD, $auth);
1408
  }
1409
+
1410
  $contents = curl_exec($ch);
1411
+
1412
  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1413
+
1414
  curl_close($ch);
1415
  } else {
1416
  $parse_url = @parse_url($url);
1417
+
1418
  if ($parse_url && isset($parse_url['host'])) {
1419
  $host = $parse_url['host'];
1420
  $port = (isset($parse_url['port']) ? (int) $parse_url['port'] : 80);
1421
  $path = (!empty($parse_url['path']) ? $parse_url['path'] : '/');
1422
  $query = (isset($parse_url['query']) ? $parse_url['query'] : '');
1423
  $request_uri = $path . ($query != '' ? '?' . $query : '');
1424
+
1425
  $request_headers_array = array(
1426
+ sprintf('%s %s HTTP/1.0', $method, $request_uri),
1427
+ sprintf('Host: %s', $host),
1428
+ sprintf('User-Agent: %s', W3TC_POWERED_BY),
1429
  'Connection: close'
1430
  );
1431
+
1432
  if (!empty($data)) {
1433
  $request_headers_array[] = sprintf('Content-Length: %d', strlen($data));
1434
  }
1435
+
1436
  if (!empty($auth)) {
1437
  $request_headers_array[] = sprintf('Authorization: Basic %s', base64_encode($auth));
1438
  }
1439
+
1440
  $request_headers = implode("\r\n", $request_headers_array);
1441
  $request = $request_headers . "\r\n\r\n" . $data;
1442
  $errno = null;
1443
  $errstr = null;
1444
+
1445
  $fp = @fsockopen($host, $port, $errno, $errstr, 10);
1446
+
1447
  if (!$fp) {
1448
  return false;
1449
  }
1450
+
1451
+ @stream_set_timeout($fp, 60);
1452
+
1453
  $response = '';
1454
  @fputs($fp, $request);
1455
+
1456
  while (!@feof($fp)) {
1457
  $response .= @fgets($fp, 4096);
1458
  }
1459
+
1460
  @fclose($fp);
1461
+
1462
+ list ($response_headers, $contents) = explode("\r\n\r\n", $response, 2);
1463
+
1464
  $matches = null;
1465
+
1466
  if (preg_match('~^HTTP/1.[01] (\d+)~', $response_headers, $matches)) {
1467
  $status = (int) $matches[1];
1468
  }
1469
  }
1470
  }
1471
+
1472
  if (!$check_status || $status == 200) {
1473
  return $contents;
1474
  }
1475
+
1476
  return false;
1477
  }
1478
 
1484
  * $param boolean $check_status
1485
  * @return string
1486
  */
1487
+ function w3_http_get($url, $auth = '', $check_status = true) {
 
1488
  return w3_http_request('GET', $url, null, $auth, $check_status);
1489
  }
1490
 
1497
  * @param boolean $check_status
1498
  * @return string
1499
  */
1500
+ function w3_http_post($url, $data = '', $auth = '', $check_status = true) {
 
1501
  return w3_http_request('POST', $url, $data, $auth, $check_status);
1502
  }
1503
 
1508
  * $param boolean $check_status
1509
  * @return string
1510
  */
1511
+ function w3_http_purge($url, $auth = '', $check_status = true) {
 
1512
  return w3_http_request('PURGE', $url, null, $auth, $check_status);
1513
  }
1514
 
1517
  * @param integer $time
1518
  * @return string
1519
  */
1520
+ function w3_http_date($time) {
 
1521
  return gmdate('D, d M Y H:i:s \G\M\T', $time);
1522
  }
1523
 
1528
  * @param string $file
1529
  * @return boolean
1530
  */
1531
+ function w3_download($url, $file) {
 
1532
  $data = w3_http_get($url);
1533
+
1534
  if ($data !== false) {
1535
  return @file_put_contents($file, $data);
1536
  }
1537
+
1538
  return false;
1539
  }
1540
 
1543
  *
1544
  * @return array
1545
  */
1546
+ function w3_upload_info() {
 
1547
  static $upload_info = null;
1548
+
1549
  if ($upload_info === null) {
1550
  $upload_info = @wp_upload_dir();
1551
+
1552
  if (empty($upload_info['error'])) {
 
 
1553
  $parse_url = @parse_url($upload_info['baseurl']);
1554
+
1555
  if ($parse_url) {
1556
  $baseurlpath = (!empty($parse_url['path']) ? trim($parse_url['path'], '/') : '');
1557
  } else {
1558
  $baseurlpath = 'wp-content/uploads';
1559
  }
1560
+
1561
  $upload_info['baseurlpath'] = '/' . $baseurlpath . '/';
1562
  } else {
1563
  $upload_info = false;
1564
  }
1565
  }
1566
+
1567
  return $upload_info;
1568
  }
1569
 
1570
  /**
1571
+ * Formats URL
 
1572
  * @param string $url
1573
+ * @param array $params
1574
+ * @param boolean $skip_empty
1575
  * @return string
1576
  */
1577
+ function w3_url_format($url = '', $params = array(), $skip_empty = false, $separator = '&') {
1578
+ if ($url != '') {
1579
+ $parse_url = @parse_url($url);
 
 
1580
  $url = '';
1581
+
1582
  if (!empty($parse_url['scheme'])) {
1583
  $url .= $parse_url['scheme'] . '://';
1584
+
1585
+ if (!empty($parse_url['user'])) {
1586
+ $url .= $parse_url['user'];
1587
+
1588
+ if (!empty($parse_url['pass'])) {
1589
+ $url .= ':' . $parse_url['pass'];
1590
+ }
1591
+ }
1592
+
1593
+ if (!empty($parse_url['host'])) {
1594
+ $url .= $parse_url['host'];
1595
+ }
1596
+
1597
+ if (!empty($parse_url['port']) && $parse_url['port'] != 80) {
1598
+ $url .= ':' . (int) $parse_url['port'];
1599
  }
1600
  }
1601
+
1602
+ if (!empty($parse_url['path'])) {
1603
+ $url .= $parse_url['path'];
 
 
 
 
1604
  }
1605
+
 
 
1606
  if (!empty($parse_url['query'])) {
1607
  $old_params = array();
1608
  parse_str($parse_url['query'], $old_params);
1609
+
1610
  $params = array_merge($old_params, $params);
1611
  }
1612
+
1613
+ $query = w3_url_query($params);
1614
+
1615
+ if ($query != '') {
1616
+ $url .= '?' . $query;
1617
+ }
1618
+
1619
  if (!empty($parse_url['fragment'])) {
1620
+ $url .= '#' . $parse_url['fragment'];
1621
  }
1622
  } else {
1623
+ $query = w3_url_query($params, $skip_empty, $separator);
1624
+
1625
+ if ($query != '') {
1626
+ $url = '?' . $query;
 
 
 
 
 
1627
  }
 
 
1628
  }
1629
+
1630
+ return $url;
1631
+ }
1632
+
1633
+ /**
1634
+ * Formats query string
1635
+ *
1636
+ * @param array $params
1637
+ * @param boolean $skip_empty
1638
+ * @param string $separator
1639
+ * @return string
1640
+ */
1641
+ function w3_url_query($params = array(), $skip_empty = false, $separator = '&') {
1642
+ $str = '';
1643
+ static $stack = array();
1644
+
1645
+ foreach ((array) $params as $key => $value) {
1646
+ if ($skip_empty === true && empty($value)) {
1647
+ continue;
1648
+ }
1649
+
1650
+ array_push($stack, $key);
1651
+
1652
+ if (is_array($value)) {
1653
+ if (count($value)) {
1654
+ $str .= ($str != '' ? '&' : '') . w3_url_query($value, $skip_empty, $key);
1655
+ }
1656
+ } else {
1657
+ $name = '';
1658
+ foreach ($stack as $key) {
1659
+ $name .= ($name != '' ? '[' . $key . ']' : $key);
1660
+ }
1661
+ $str .= ($str != '' ? $separator : '') . $name . '=' . rawurlencode($value);
1662
+ }
1663
+
1664
+ array_pop($stack);
1665
  }
1666
+
1667
+ return $str;
1668
+ }
1669
+
1670
+
1671
+ /**
1672
+ * Redirects to URL
1673
+ *
1674
+ * @param string $url
1675
+ * @param string $params
1676
+ * @return string
1677
+ */
1678
+ function w3_redirect($url = '', $params = array()) {
1679
+ $url = w3_url_format($url, $params);
1680
+
1681
  @header('Location: ' . $url);
1682
  exit();
1683
  }
1688
  * @param $engine
1689
  * @return string
1690
  */
1691
+ function w3_get_engine_name($engine) {
 
1692
  switch ($engine) {
1693
  case 'memcached':
1694
  $engine_name = 'memcached';
1695
  break;
1696
+
1697
  case 'apc':
1698
  $engine_name = 'apc';
1699
  break;
1700
+
1701
  case 'eaccelerator':
1702
  $engine_name = 'eaccelerator';
1703
  break;
1704
+
1705
  case 'xcache':
1706
  $engine_name = 'xcache';
1707
  break;
1708
+
1709
+ case 'wincache':
1710
+ $engine_name = 'wincache';
1711
+ break;
1712
+
1713
  case 'file':
1714
  $engine_name = 'disk';
1715
  break;
1716
+
1717
  case 'file_pgcache':
1718
  $engine_name = 'disk (enhanced)';
1719
  break;
1720
+
1721
  case 'mirror':
1722
  $engine_name = 'mirror';
1723
  break;
1724
+
1725
  case 'netdna':
1726
+ $engine_name = 'netdna / maxcdn';
1727
+ break;
1728
+
1729
+ case 'cotendo':
1730
+ $engine_name = 'cotendo';
1731
  break;
1732
+
1733
  case 'ftp':
1734
  $engine_name = 'self-hosted / file transfer protocol upload';
1735
  break;
1736
+
1737
  case 's3':
1738
  $engine_name = 'amazon simple storage service (s3)';
1739
  break;
1740
+
1741
  case 'cf':
1742
  $engine_name = 'amazon cloudfront';
1743
  break;
1744
+
1745
+ case 'cf2':
1746
+ $engine_name = 'amazon cloudfront';
1747
+ break;
1748
+
1749
  case 'rscf':
1750
  $engine_name = 'rackspace cloud files';
1751
  break;
1752
+
1753
+ case 'azure':
1754
+ $engine_name = 'microsoft azure storage';
1755
+ break;
1756
+
1757
  default:
1758
  $engine_name = 'n/a';
1759
  break;
1760
  }
1761
+
1762
  return $engine_name;
1763
  }
1764
 
1768
  * @param mixed $value
1769
  * @return boolean
1770
  */
1771
+ function w3_to_boolean($value) {
 
1772
  if (is_string($value)) {
1773
  switch (strtolower($value)) {
1774
  case '+':
1779
  case 'true':
1780
  case 'enabled':
1781
  return true;
1782
+
1783
  case '-':
1784
  case '0':
1785
  case 'n':
1790
  return false;
1791
  }
1792
  }
 
 
 
1793
 
1794
+ return (boolean) $value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1795
  }
1796
 
1797
  /**
1800
  * @param string $file
1801
  * @return string
1802
  */
1803
+ function w3_get_mime_type($file) {
 
1804
  static $cache = array();
1805
+
1806
  if (!isset($cache[$file])) {
1807
  $mime_type = false;
1808
+
1809
  /**
1810
  * Try to detect by extension (fast)
1811
  */
1812
  $mime_types = include W3TC_DIR . '/inc/mime/all.php';
1813
+
1814
  foreach ($mime_types as $extension => $type) {
1815
  if (preg_match('~\.(' . $extension . ')$~i', $file)) {
1816
  $mime_type = $type;
1817
  break;
1818
  }
1819
  }
1820
+
1821
  /**
1822
  * Try to detect using file info function
1823
  */
1824
  if (!$mime_type && function_exists('finfo_open')) {
1825
  $finfo = @finfo_open(FILEINFO_MIME);
1826
+
1827
  if (!$finfo) {
1828
  $finfo = @finfo_open(FILEINFO_MIME);
1829
  }
1830
+
1831
  if ($finfo) {
1832
  $mime_type = @finfo_file($finfo, $file);
1833
+
1834
  if ($mime_type) {
1835
  $extra_mime_type_info = strpos($mime_type, "; ");
1836
+
1837
  if ($extra_mime_type_info) {
1838
  $mime_type = substr($mime_type, 0, $extra_mime_type_info);
1839
  }
1840
+
1841
  if ($mime_type == 'application/octet-stream') {
1842
  $mime_type = false;
1843
  }
1844
  }
1845
+
1846
  @finfo_close($finfo);
1847
  }
1848
  }
1849
+
1850
  /**
1851
  * Try to detect using mime type function
1852
  */
1853
  if (!$mime_type && function_exists('mime_content_type')) {
1854
  $mime_type = @mime_content_type($file);
1855
  }
1856
+
1857
  /**
1858
+ * If detection failed use default mime type
1859
  */
1860
  if (!$mime_type) {
1861
  $mime_type = 'application/octet-stream';
1862
  }
1863
+
1864
  $cache[$file] = $mime_type;
1865
  }
 
 
 
1866
 
1867
+ return $cache[$file];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1868
  }
1869
 
1870
  /**
1873
  * @param string $regexp
1874
  * @return string
1875
  */
1876
+ function w3_preg_quote($string, $delimiter = null) {
 
1877
  $string = preg_quote($string, $delimiter);
1878
  $string = strtr($string, array(
1879
  ' ' => '\ '
1880
  ));
1881
+
1882
  return $string;
1883
  }
1884
 
1887
  *
1888
  * @return boolean
1889
  */
1890
+ function w3_zlib_output_compression() {
 
1891
  return w3_to_boolean(ini_get('zlib.output_compression'));
1892
  }
1893
 
1897
  * @param mixed $var
1898
  * @return mixed
1899
  */
1900
+ function w3_stripslashes($var) {
 
1901
  if (is_string($var)) {
1902
  return stripslashes($var);
1903
  } elseif (is_array($var)) {
1904
  $var = array_map('w3_stripslashes', $var);
1905
  }
1906
+
1907
  return $var;
1908
  }
1909
 
1911
  if (!defined('FILE_APPEND')) {
1912
  define('FILE_APPEND', 8);
1913
  }
1914
+
1915
  /**
1916
  * Puts contents to the file
1917
  *
1920
  * @param integer $flags
1921
  * @return boolean
1922
  */
1923
+ function file_put_contents($filename, $data, $flags = 0) {
 
1924
  $fp = fopen($filename, ($flags & FILE_APPEND ? 'a' : 'w'));
1925
+
1926
  if ($fp) {
1927
  fputs($fp, $data);
1928
  fclose($fp);
1929
+
1930
  return true;
1931
  }
1932
+
1933
  return false;
1934
  }
1935
  }
1936
 
1937
  /**
1938
+ * Trim rules
1939
+ *
1940
+ * @param string $rules
1941
+ * @return string
1942
+ */
1943
+ function w3_trim_rules($rules) {
1944
+ $rules = trim($rules);
1945
+
1946
+ if ($rules != '') {
1947
+ $rules .= "\n";
1948
+ }
1949
+
1950
+ return $rules;
1951
+ }
1952
+
1953
+ /**
1954
+ * Cleanup rewrite rules
1955
  *
1956
  * @param string $rules
1957
  * @return string
1958
  */
1959
+ function w3_clean_rules($rules) {
 
1960
  $rules = preg_replace('~[\r\n]+~', "\n", $rules);
1961
  $rules = preg_replace('~^\s+~m', '', $rules);
1962
+ $rules = w3_trim_rules($rules);
1963
+
1964
  return $rules;
1965
  }
1966
 
1967
  /**
1968
  * Erases text from start to end
1969
  *
1970
+ * @param string $rules
1971
  * @param string $start
1972
  * @param string $end
1973
  * @return string
1974
  */
1975
+ function w3_erase_rules($rules, $start, $end) {
1976
+ $rules = preg_replace('~' . w3_preg_quote($start) . '.*?' . w3_preg_quote($end) . "\n*~s", '', $rules);
1977
+ $rules = w3_trim_rules($rules);
1978
+
1979
+ return $rules;
 
1980
  }
1981
 
1982
  /**
1983
+ * Extracts JS files from content
1984
  *
1985
+ * @param string $content
1986
+ * @return array
1987
  */
1988
+ function w3_extract_js($content) {
1989
+ $matches = null;
1990
+ $files = array();
1991
+
1992
+ $content = preg_replace('~<!--.*?-->~s', '', $content);
1993
+
1994
+ if (preg_match_all('~<script\s+[^<>]*src=["\']?([^"\']+)["\']?[^<>]*>\s*</script>~is', $content, $matches)) {
1995
+ $files = $matches[1];
1996
+ }
1997
+
1998
+ $files = array_filter($files, create_function('$el', 'return (strstr($el, W3TC_CONTENT_MINIFY_DIR_NAME) ? false : true);'));
1999
+ $files = array_values(array_unique($files));
2000
+
2001
+ return $files;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2002
  }
2003
 
2004
  /**
2005
+ * Extract CSS files from content
2006
+ *
2007
+ * @param string $content
2008
+ * @return array
 
2009
  */
2010
+ function w3_extract_css($content) {
2011
+ $matches = null;
2012
+ $files = array();
2013
+
2014
+ $content = preg_replace('~<!--.*?-->~s', '', $content);
2015
+
2016
+ if (preg_match_all('~<link\s+([^>]+)/?>(.*</link>)?~Uis', $content, $matches, PREG_SET_ORDER)) {
2017
+ foreach ($matches as $match) {
2018
+ $attrs = array();
2019
+ $attr_matches = null;
2020
+
2021
+ if (preg_match_all('~(\w+)=["\']([^"\']*)["\']~', $match[1], $attr_matches, PREG_SET_ORDER)) {
2022
+ foreach ($attr_matches as $attr_match) {
2023
+ $attrs[$attr_match[1]] = trim($attr_match[2]);
2024
+ }
2025
+ }
2026
+
2027
+ if (isset($attrs['href']) && isset($attrs['rel']) && stristr($attrs['rel'], 'stylesheet') !== false && (!isset($attrs['media']) || stristr($attrs['media'], 'print') === false)) {
2028
+ $files[] = $attrs['href'];
2029
+ }
2030
+ }
2031
+ }
2032
+
2033
+ if (preg_match_all('~@import\s+(url\s*)?\(?["\']?\s*([^"\'\)\s]+)\s*["\']?\)?[^;]*;?~is', $content, $matches)) {
2034
+ $files = array_merge($files, $matches[2]);
2035
+ }
2036
+
2037
+ $files = array_filter($files, create_function('$el', 'return (strstr($el, W3TC_CONTENT_MINIFY_DIR_NAME) ? false : true);'));
2038
+ $files = array_values(array_unique($files));
2039
+
2040
+ return $files;
2041
  }
2042
 
2043
  /**
2044
+ * Loads plugins
2045
+ *
2046
+ * @return void
 
 
2047
  */
2048
+ function w3_load_plugins() {
2049
+ $dir = @opendir(W3TC_PLUGINS_DIR);
2050
+
2051
+ if ($dir) {
2052
+ while (($entry = @readdir($dir)) !== false) {
2053
+ if (strrchr($entry, '.') === '.php') {
2054
+ require_once W3TC_PLUGINS_DIR . '/' . $entry;
 
2055
  }
2056
  }
2057
+ @closedir($dir);
2058
  }
 
 
2059
  }
inc/error.phtml CHANGED
@@ -1,7 +1,7 @@
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
  <html xmlns="http://www.w3.org/1999/xhtml" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>>
3
  <head>
4
- <link rel="stylesheet" type="text/css" href="<?php echo WP_PLUGIN_URL; ?>/w3-total-cache/inc/css/error.css"></link>
5
  <title>Error</title>
6
  <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
7
  </head>
1
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
  <html xmlns="http://www.w3.org/1999/xhtml" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>>
3
  <head>
4
+ <link rel="stylesheet" type="text/css" href="<?php echo plugins_url('inc/css/error.css?ver=' . W3TC_VERSION, W3TC_FILE); ?>" />
5
  <title>Error</title>
6
  <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
7
  </head>
inc/images/ps_bar.gif ADDED
Binary file
inc/images/ps_grad.gif ADDED
Binary file
inc/images/ps_scores.png ADDED
Binary file
inc/js/lightbox.js CHANGED
@@ -6,7 +6,7 @@ var W3tc_Lightbox = {
6
  create: function() {
7
  var me = this;
8
 
9
- this.container = jQuery('<div class="lightbox lightbox-loading"><div class="lightbox-close">Close window</div><div class="lightbox-content"></div></div>').css( {
10
  top: 0,
11
  left: 0,
12
  width: 0,
@@ -32,9 +32,7 @@ var W3tc_Lightbox = {
32
  },
33
 
34
  open: function(options) {
35
- var me = this;
36
-
37
- this.options = jQuery.extend( {
38
  width: 400,
39
  height: 300,
40
  offsetTop: 100,
@@ -45,7 +43,7 @@ var W3tc_Lightbox = {
45
 
46
  this.create();
47
 
48
- this.container.css( {
49
  width: this.options.width,
50
  height: this.options.height
51
  });
@@ -68,12 +66,12 @@ var W3tc_Lightbox = {
68
  },
69
 
70
  resize: function() {
71
- this.container.css( {
72
  top: this.window.scrollTop() + this.options.offsetTop,
73
  left: this.window.scrollLeft() + this.window.width() / 2 - this.container.width() / 2
74
  });
75
 
76
- jQuery('.lightbox-content', this.container).css( {
77
  width: this.width(),
78
  height: this.height()
79
  });
@@ -126,7 +124,7 @@ var W3tc_Overlay = {
126
  create: function() {
127
  var me = this;
128
 
129
- this.container = jQuery('<div id="overlay" />').css( {
130
  top: 0,
131
  left: 0,
132
  width: 0,
@@ -159,7 +157,7 @@ var W3tc_Overlay = {
159
  },
160
 
161
  resize: function() {
162
- this.container.css( {
163
  top: this.window.scrollTop(),
164
  left: this.window.scrollLeft(),
165
  width: this.window.width(),
@@ -169,71 +167,10 @@ var W3tc_Overlay = {
169
  };
170
 
171
  function w3tc_lightbox_support_us() {
172
- W3tc_Lightbox.open( {
173
- width: 590,
174
- height: 200,
175
- url: 'admin.php?page=w3tc_general&w3tc_action=support_us',
176
- callback: function(lightbox) {
177
- jQuery('.button-tweet', lightbox.container).click(function(event) {
178
- lightbox.close();
179
- w3tc_lightbox_tweet();
180
- return false;
181
- });
182
-
183
- jQuery('.button-rating', lightbox.container).click(function() {
184
- window.open('http://wordpress.org/extend/plugins/w3-total-cache/', '_blank');
185
- });
186
-
187
- jQuery('form').submit(function() {
188
- if (jQuery('select :selected', this).val() == '') {
189
- alert('Please select link location!');
190
- return false;
191
- }
192
- });
193
- }
194
- });
195
-
196
- }
197
-
198
- function w3tc_lightbox_tweet() {
199
- W3tc_Lightbox.open( {
200
- width: 550,
201
- height: 340,
202
- url: 'admin.php?page=w3tc_general&w3tc_action=tweet',
203
- callback: function(lightbox) {
204
- jQuery('form', lightbox.container).submit(function() {
205
- var me = this, username = jQuery('#tweet_username').val(), password = jQuery('#tweet_password').val();
206
-
207
- if (username == '') {
208
- alert('Please enter your twitter.com username.');
209
- return false;
210
- }
211
-
212
- if (password == '') {
213
- alert('Please enter your twitter.com password.');
214
- return false;
215
- }
216
-
217
- jQuery('input', this).attr('disabled', 'disabled');
218
-
219
- jQuery.post('admin.php?page=w3tc_general', {
220
- w3tc_action: 'twitter_status_update',
221
- username: username,
222
- password: password
223
- }, function(data) {
224
- jQuery('input', me).attr('disabled', '');
225
-
226
- if (data.result) {
227
- lightbox.close();
228
- alert('Nice! Thanks for telling your friends about us!');
229
- } else {
230
- alert('Uh oh, seems that that #failed. Please try again.');
231
- }
232
- }, 'json');
233
-
234
- return false;
235
- });
236
- }
237
  });
238
  }
239
 
@@ -251,17 +188,15 @@ function w3tc_lightbox_minify_recommendations() {
251
  height = max_height;
252
  }
253
 
254
- W3tc_Lightbox.open( {
255
  width: 1000,
256
  height: height,
257
  url: 'admin.php?page=w3tc_minify&w3tc_action=minify_recommendations',
258
  callback: function(lightbox) {
259
- jQuery('#recom_container').css('height', height - 50);
260
-
261
  var theme = jQuery('#recom_theme').val();
262
 
263
  if (jQuery.ui && jQuery.ui.sortable) {
264
- jQuery("#recom_js_files,#recom_css_files").sortable( {
265
  axis: 'y',
266
  stop: function() {
267
  jQuery(this).find('li').each(function(index) {
@@ -363,7 +298,7 @@ function w3tc_lightbox_minify_recommendations() {
363
 
364
  function w3tc_lightbox_self_test() {
365
  var min_height = 200;
366
- var max_height = 800;
367
 
368
  var height = jQuery(window).height() - 220;
369
 
@@ -373,13 +308,11 @@ function w3tc_lightbox_self_test() {
373
  height = max_height;
374
  }
375
 
376
- W3tc_Lightbox.open( {
377
  width: 800,
378
  height: height,
379
  url: 'admin.php?page=w3tc_general&w3tc_action=self_test',
380
  callback: function(lightbox) {
381
- jQuery('#self_test_container').css('height', height - 50);
382
-
383
  jQuery('.button-primary', lightbox.container).click(function() {
384
  lightbox.close();
385
  });
@@ -387,12 +320,20 @@ function w3tc_lightbox_self_test() {
387
  });
388
  }
389
 
390
- jQuery(function() {
391
- jQuery('.button-tweet').click(function() {
392
- w3tc_lightbox_tweet();
393
- return false;
 
 
 
 
 
 
394
  });
 
395
 
 
396
  jQuery('.button-minify-recommendations').click(function() {
397
  w3tc_lightbox_minify_recommendations();
398
  return false;
@@ -402,4 +343,17 @@ jQuery(function() {
402
  w3tc_lightbox_self_test();
403
  return false;
404
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  });
6
  create: function() {
7
  var me = this;
8
 
9
+ this.container = jQuery('<div class="lightbox lightbox-loading"><div class="lightbox-close">Close window</div><div class="lightbox-content"></div></div>').css({
10
  top: 0,
11
  left: 0,
12
  width: 0,
32
  },
33
 
34
  open: function(options) {
35
+ this.options = jQuery.extend({
 
 
36
  width: 400,
37
  height: 300,
38
  offsetTop: 100,
43
 
44
  this.create();
45
 
46
+ this.container.css({
47
  width: this.options.width,
48
  height: this.options.height
49
  });
66
  },
67
 
68
  resize: function() {
69
+ this.container.css({
70
  top: this.window.scrollTop() + this.options.offsetTop,
71
  left: this.window.scrollLeft() + this.window.width() / 2 - this.container.width() / 2
72
  });
73
 
74
+ jQuery('.lightbox-content', this.container).css({
75
  width: this.width(),
76
  height: this.height()
77
  });
124
  create: function() {
125
  var me = this;
126
 
127
+ this.container = jQuery('<div id="overlay" />').css({
128
  top: 0,
129
  left: 0,
130
  width: 0,
157
  },
158
 
159
  resize: function() {
160
+ this.container.css({
161
  top: this.window.scrollTop(),
162
  left: this.window.scrollLeft(),
163
  width: this.window.width(),
167
  };
168
 
169
  function w3tc_lightbox_support_us() {
170
+ W3tc_Lightbox.open({
171
+ width: 500,
172
+ height: 230,
173
+ url: 'admin.php?page=w3tc_general&w3tc_action=support_us'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  });
175
  }
176
 
188
  height = max_height;
189
  }
190
 
191
+ W3tc_Lightbox.open({
192
  width: 1000,
193
  height: height,
194
  url: 'admin.php?page=w3tc_minify&w3tc_action=minify_recommendations',
195
  callback: function(lightbox) {
 
 
196
  var theme = jQuery('#recom_theme').val();
197
 
198
  if (jQuery.ui && jQuery.ui.sortable) {
199
+ jQuery("#recom_js_files,#recom_css_files").sortable({
200
  axis: 'y',
201
  stop: function() {
202
  jQuery(this).find('li').each(function(index) {
298
 
299
  function w3tc_lightbox_self_test() {
300
  var min_height = 200;
301
+ var max_height = 1000;
302
 
303
  var height = jQuery(window).height() - 220;
304
 
308
  height = max_height;
309
  }
310
 
311
+ W3tc_Lightbox.open({
312
  width: 800,
313
  height: height,
314
  url: 'admin.php?page=w3tc_general&w3tc_action=self_test',
315
  callback: function(lightbox) {
 
 
316
  jQuery('.button-primary', lightbox.container).click(function() {
317
  lightbox.close();
318
  });
320
  });
321
  }
322
 
323
+ function w3tc_lightbox_cdn_s3_bucket_location(type) {
324
+ W3tc_Lightbox.open({
325
+ width: 500,
326
+ height: 150,
327
+ url: 'admin.php?page=w3tc_general&w3tc_action=cdn_s3_bucket_location&type=' + type,
328
+ callback: function(lightbox) {
329
+ jQuery('.button', lightbox.container).click(function() {
330
+ lightbox.close();
331
+ });
332
+ }
333
  });
334
+ }
335
 
336
+ jQuery(function() {
337
  jQuery('.button-minify-recommendations').click(function() {
338
  w3tc_lightbox_minify_recommendations();
339
  return false;
343
  w3tc_lightbox_self_test();
344
  return false;
345
  });
346
+
347
+ jQuery('.button-cdn-s3-bucket-location,.button-cdn-cf-bucket-location').click(function() {
348
+ var type = '';
349
+
350
+ if (jQuery(this).hasClass('cdn_s3')) {
351
+ type = 's3';
352
+ } else if (jQuery(this).hasClass('cdn_cf')) {
353
+ type = 'cf';
354
+ }
355
+
356
+ w3tc_lightbox_cdn_s3_bucket_location(type);
357
+ return false;
358
+ });
359
  });
inc/js/options.js CHANGED
@@ -23,7 +23,7 @@ function w3tc_input_enable(input, enabled) {
23
  } else {
24
  var t = me.attr('type');
25
  if ((t != 'radio' && t != 'checkbox') || me.is(':checked')) {
26
- me.after(jQuery('<input />').attr( {
27
  type: 'hidden',
28
  name: me.attr('name')
29
  }).val(me.val()));
@@ -56,11 +56,19 @@ function w3tc_mobile_groups_clear() {
56
  }
57
  }
58
 
 
 
 
 
 
 
 
 
59
  function w3tc_minify_js_file_add(theme, template, location, file) {
60
  var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th>Template:</th><th colspan="3">Embed Location:</th></tr><tr><td>' + (jQuery('#js_files li').size() + 1) + '.</td><td><input class="js_enabled" type="text" name="js_files[' + theme + '][' + template + '][' + location + '][]" value="" size="70" \/></td><td><select class="js_file_template js_enabled"></select></td><td><select class="js_file_location js_enabled"><optgroup label="Blocking:"><option value="include">Embed in &lt;head&gt;</option><option value="include-body">Embed after &lt;body&gt;</option><option value="include-footer">Embed before &lt;/body&gt;</option></optgroup><optgroup label="Non-Blocking:"><option value="include-nb">Embed in &lt;head&gt;</option><option value="include-body-nb">Embed after &lt;body&gt;</option><option value="include-footer-nb">Embed before &lt;/body&gt;</option></optgroup></select></td><td><input class="js_file_delete js_enabled button" type="button" value="Delete" /> <input class="js_file_verify js_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
61
  append.find('input:text').val(file);
62
  var select = append.find('.js_file_template');
63
- for ( var i in minify_templates[theme]) {
64
  select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
65
  }
66
  select.val(template);
@@ -73,7 +81,7 @@ function w3tc_minify_css_file_add(theme, template, file) {
73
  var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th colspan="2">Template:</th></tr><tr><td>' + (jQuery('#css_files li').size() + 1) + '.</td><td><input class="css_enabled" type="text" name="css_files[' + theme + '][' + template + '][include][]" value="" size="70" \/></td><td><select class="css_file_template css_enabled"></select></td><td><input class="css_file_delete css_enabled button" type="button" value="Delete" /></td><td><input class="css_file_verify css_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
74
  append.find('input:text').val(file);
75
  var select = append.find('.css_file_template');
76
- for ( var i in minify_templates[theme]) {
77
  select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
78
  }
79
  select.val(template);
@@ -118,7 +126,7 @@ function w3tc_cdn_get_cnames() {
118
 
119
  if (match) {
120
  cnames = [];
121
- for ( var i = 1; i <= 10; i++) {
122
  cnames.push('cdn' + i + '.' + match[1]);
123
  }
124
  return false;
@@ -167,23 +175,68 @@ function w3tc_cdn_cnames_assign() {
167
  });
168
  }
169
 
170
- function w3tc_toggle(name) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  var id = '#' + name, cls = '.' + name;
172
 
173
  jQuery(cls).click(function() {
174
- var checked = true;
 
175
  jQuery(cls).each(function() {
176
- if (!jQuery(this).is(':checked')) {
177
- checked = false;
178
- }
179
- });
180
- jQuery(id).each(function() {
181
- if (checked) {
182
- jQuery(this).attr('checked', 'checked');
183
- } else {
184
- jQuery(this).removeAttr('checked');
185
  }
186
  });
 
 
 
 
 
 
187
  });
188
 
189
  jQuery(id).click(function() {
@@ -198,11 +251,27 @@ function w3tc_toggle(name) {
198
  });
199
  }
200
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  jQuery(function() {
202
  // general page
203
  w3tc_toggle('enabled');
204
 
205
- jQuery('.button-rating').click(function() {
 
 
 
 
206
  window.open('http://wordpress.org/extend/plugins/w3-total-cache/', '_blank');
207
  });
208
 
@@ -212,6 +281,7 @@ jQuery(function() {
212
  w3tc_toggle('browsercache_etag');
213
  w3tc_toggle('browsercache_w3tc');
214
  w3tc_toggle('browsercache_compression');
 
215
 
216
  // minify page
217
  w3tc_input_enable('.html_enabled', jQuery('#html_enabled:checked').size());
@@ -262,9 +332,10 @@ jQuery(function() {
262
 
263
  jQuery('.js_file_delete').live('click', function() {
264
  var parent = jQuery(this).parents('li');
265
- if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to delete JS file?')) {
266
  parent.remove();
267
  w3tc_minify_js_file_clear();
 
268
  }
269
 
270
  return false;
@@ -272,9 +343,10 @@ jQuery(function() {
272
 
273
  jQuery('.css_file_delete').live('click', function() {
274
  var parent = jQuery(this).parents('li');
275
- if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to delete CSS file?')) {
276
  parent.remove();
277
  w3tc_minify_css_file_clear();
 
278
  }
279
 
280
  return false;
@@ -306,7 +378,7 @@ jQuery(function() {
306
  g = '[' + jQuery('#js_themes option[value=' + match[1] + ']').text() + '] ' + v;
307
  }
308
  if (v != '') {
309
- for ( var i = 0; i < js.length; i++) {
310
  if (js[i] == c) {
311
  duplicate = true;
312
  break;
@@ -334,7 +406,7 @@ jQuery(function() {
334
  g = '[' + jQuery('#css_themes option[value=' + match[1] + ']').text() + '] ' + v;
335
  }
336
  if (v != '') {
337
- for ( var i = 0; i < css.length; i++) {
338
  if (css[i] == c) {
339
  duplicate = true;
340
  break;
@@ -407,6 +479,10 @@ jQuery(function() {
407
  w3tc_popup('admin.php?page=w3tc_cdn&w3tc_action=cdn_rename_domain', 'cdn_rename_domain');
408
  });
409
 
 
 
 
 
410
  jQuery('.cdn_export').click(function() {
411
  w3tc_popup('admin.php?page=w3tc_cdn&w3tc_action=cdn_export&cdn_export_type=' + this.name, 'cdn_export_' + this.name);
412
  });
@@ -421,16 +497,29 @@ jQuery(function() {
421
  switch (true) {
422
  case me.hasClass('cdn_mirror'):
423
  jQuery.extend(params, {
424
- engine: 'mirror',
425
- 'config[domain][]': cnames
426
  });
 
 
 
427
  break;
428
 
429
  case me.hasClass('cdn_netdna'):
430
  jQuery.extend(params, {
431
- engine: 'netdna',
432
- 'config[domain][]': cnames
433
  });
 
 
 
 
 
 
 
 
 
 
 
 
434
  break;
435
 
436
  case me.hasClass('cdn_ftp'):
@@ -440,9 +529,11 @@ jQuery(function() {
440
  'config[user]': jQuery('#cdn_ftp_user').val(),
441
  'config[path]': jQuery('#cdn_ftp_path').val(),
442
  'config[pass]': jQuery('#cdn_ftp_pass').val(),
443
- 'config[pasv]': jQuery('#cdn_ftp_pasv:checked').size(),
444
- 'config[domain][]': cnames
445
  });
 
 
 
446
  break;
447
 
448
  case me.hasClass('cdn_s3'):
@@ -450,9 +541,11 @@ jQuery(function() {
450
  engine: 's3',
451
  'config[key]': jQuery('#cdn_s3_key').val(),
452
  'config[secret]': jQuery('#cdn_s3_secret').val(),
453
- 'config[bucket]': jQuery('#cdn_s3_bucket').val(),
454
- 'config[cname][]': cnames
455
  });
 
 
 
456
  break;
457
 
458
  case me.hasClass('cdn_cf'):
@@ -461,9 +554,24 @@ jQuery(function() {
461
  'config[key]': jQuery('#cdn_cf_key').val(),
462
  'config[secret]': jQuery('#cdn_cf_secret').val(),
463
  'config[bucket]': jQuery('#cdn_cf_bucket').val(),
464
- 'config[id]': jQuery('#cdn_cf_id').val(),
465
- 'config[cname][]': cnames
466
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
467
  break;
468
 
469
  case me.hasClass('cdn_rscf'):
@@ -471,10 +579,25 @@ jQuery(function() {
471
  engine: 'rscf',
472
  'config[user]': jQuery('#cdn_rscf_user').val(),
473
  'config[key]': jQuery('#cdn_rscf_key').val(),
 
474
  'config[container]': jQuery('#cdn_rscf_container').val(),
475
- 'config[id]': jQuery('#cdn_rscf_id').val(),
476
- 'config[cname][]': cnames
 
 
 
 
 
 
 
 
 
 
 
477
  });
 
 
 
478
  break;
479
  }
480
 
@@ -490,7 +613,7 @@ jQuery(function() {
490
  }, 'json');
491
  });
492
 
493
- jQuery('#cdn_create_container').click(function() {
494
  var me = jQuery(this);
495
  var cnames = w3tc_cdn_get_cnames();
496
  var container_id = null;
@@ -505,6 +628,7 @@ jQuery(function() {
505
  'config[key]': jQuery('#cdn_s3_key').val(),
506
  'config[secret]': jQuery('#cdn_s3_secret').val(),
507
  'config[bucket]': jQuery('#cdn_s3_bucket').val(),
 
508
  'config[cname][]': cnames
509
  });
510
  break;
@@ -517,12 +641,26 @@ jQuery(function() {
517
  'config[key]': jQuery('#cdn_cf_key').val(),
518
  'config[secret]': jQuery('#cdn_cf_secret').val(),
519
  'config[bucket]': jQuery('#cdn_cf_bucket').val(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  'config[cname][]': cnames
521
  });
522
  break;
523
 
524
  case me.hasClass('cdn_rscf'):
525
- container_id = jQuery('#cdn_rscf_id');
526
 
527
  jQuery.extend(params, {
528
  engine: 'rscf',
@@ -532,6 +670,16 @@ jQuery(function() {
532
  'config[cname][]': cnames
533
  });
534
  break;
 
 
 
 
 
 
 
 
 
 
535
  }
536
 
537
  var status = jQuery('#cdn_create_container_status');
@@ -550,6 +698,12 @@ jQuery(function() {
550
  }, 'json');
551
  });
552
 
 
 
 
 
 
 
553
  jQuery('#memcached_test').click(function() {
554
  var status = jQuery('#memcached_test_status');
555
  status.removeClass('w3tc-error');
@@ -565,6 +719,50 @@ jQuery(function() {
565
  }, 'json');
566
  });
567
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  // CDN cnames
569
  jQuery('#cdn_cname_add').click(function() {
570
  jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="" size="30" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
@@ -573,12 +771,34 @@ jQuery(function() {
573
 
574
  jQuery('.cdn_cname_delete').live('click', function() {
575
  var p = jQuery(this).parent();
576
- if (p.find('input[type=text]').val() == '' || confirm('Are you sure you want to delete JS file?')) {
577
  p.remove();
578
  w3tc_cdn_cnames_assign();
 
579
  }
580
  });
581
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
  // support tabs
583
  jQuery('#support_more_files').live('click', function() {
584
  jQuery(this).before('<input type="file" name="files[]" /><br />');
@@ -617,7 +837,7 @@ jQuery(function() {
617
  return false;
618
  }
619
 
620
- if (phone.size() && !/^[0-9\-\.\ \(\)\+]+$/.test(phone.val())) {
621
  alert('Please enter your phone in the phone field.');
622
  phone.focus();
623
  return false;
@@ -668,44 +888,50 @@ jQuery(function() {
668
  return true;
669
  });
670
 
671
- jQuery('#support_request_type').live('change', function() {
672
- var request_type = jQuery(this);
 
673
 
674
- if (request_type.val() == '') {
675
- alert('Please select request type.');
676
- request_type.focus();
677
 
678
- return false;
679
- }
680
 
681
- var action = '';
682
 
683
- switch (request_type.val()) {
684
- case 'bug_report':
685
- case 'new_feature':
686
- action = 'options_support';
687
- break;
688
 
689
- case 'email_support':
690
- case 'phone_support':
691
- case 'plugin_config':
692
- case 'theme_config':
693
- case 'linux_config':
694
- action = 'options_support_payment';
695
- break;
696
- }
697
 
698
- if (action) {
699
- jQuery('#support_container').html('<div id="support_loading">Loading...</div>').load('admin.php?page=w3tc_support&w3tc_action=' + action + '&request_type=' + request_type.val() + '&ajax=1');
700
 
701
- return false;
702
- }
703
 
704
- return true;
705
- });
 
 
 
706
 
707
  jQuery('#support_cancel').live('click', function() {
708
- jQuery('#support_container').html('<div id="support_loading">Loading...</div>').load('admin.php?page=w3tc_support&w3tc_action=options_support_select&ajax=1');
 
 
709
  });
710
 
711
  // mobile tab
@@ -771,24 +997,29 @@ jQuery(function() {
771
  group = group.replace(/_+$/, '');
772
 
773
  if (group) {
 
 
774
  jQuery('.mobile_group').each(function() {
775
  if (jQuery(this).html() == group) {
776
  alert('Group already exists!');
 
777
  return false;
778
  }
779
  });
780
 
781
- var li = jQuery('<li id="mobile_group_' + group + '"><table class="form-table"><tr><th valign="top">Group name:</th><td><span class="mobile_group_number">' + (jQuery('#mobile_groups li').size() + 1) + '.</span> <span class="mobile_group">' + group + '</span> <input type="button" class="button mobile_delete" value="Delete group" /></td></tr><tr><th><label for="mobile_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="mobile_groups[' + group + '][enabled]" value="0" /><input id="mobile_groups_' + group + '_enabled" type="checkbox" name="mobile_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th valign="top"><label for="mobile_groups_' + group + '_theme">Theme:</label></th><td><select id="mobile_groups_' + group + '_theme" name="mobile_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of user agents to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. mobile plugins) to properly handle requests for these user agents. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th valign="top"><label for="mobile_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="mobile_groups_' + group + '_redirect" type="text" name="mobile_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a mobile version of your site.</span></td></tr><tr><th valign="top"><label for="mobile_groups_' + group + '_agents">User agents:</label></th><td><textarea id="mobile_groups_' + group + '_agents" name="mobile_groups[' + group + '][agents]" rows="10" cols="50"></textarea><br /><span class="description">Specify the user agents for this group.</span></td></tr></table></li>');
782
- var select = li.find('select');
 
783
 
784
- jQuery.each(mobile_themes, function(index, value) {
785
- select.append(jQuery('<option />').val(index).html(value));
786
- });
787
 
788
- jQuery('#mobile_groups').append(li);
789
- w3tc_mobile_groups_clear();
790
 
791
- window.location.hash = '#mobile_group_' + group;
 
792
  } else {
793
  alert('Empty group name!');
794
  }
@@ -799,14 +1030,117 @@ jQuery(function() {
799
  if (confirm('Are you sure want to delete this group?')) {
800
  jQuery(this).parents('#mobile_groups li').remove();
801
  w3tc_mobile_groups_clear();
 
802
  }
803
  });
804
 
805
  w3tc_mobile_groups_clear();
806
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
807
  // add sortable
808
  if (jQuery.ui && jQuery.ui.sortable) {
809
- jQuery('#js_files,#css_files').sortable( {
810
  axis: 'y',
811
  stop: function() {
812
  jQuery(this).find('li').each(function(index) {
@@ -815,12 +1149,12 @@ jQuery(function() {
815
  }
816
  });
817
 
818
- jQuery('#cdn_cnames').sortable( {
819
  axis: 'y',
820
  stop: w3tc_cdn_cnames_assign
821
  });
822
 
823
- jQuery('#mobile_groups').sortable( {
824
  axis: 'y',
825
  stop: function() {
826
  jQuery('#mobile_groups .mobile_group_number').each(function(index) {
@@ -828,6 +1162,15 @@ jQuery(function() {
828
  });
829
  }
830
  });
 
 
 
 
 
 
 
 
 
831
  }
832
 
833
  // show hide rules
@@ -843,8 +1186,20 @@ jQuery(function() {
843
  }
844
  });
845
 
846
- // nav
847
- jQuery('#w3tc-nav select').change(function() {
848
- document.location.href = 'admin.php?page=' + jQuery(this).val();
 
 
 
 
 
 
 
 
 
 
849
  });
 
 
850
  });
23
  } else {
24
  var t = me.attr('type');
25
  if ((t != 'radio' && t != 'checkbox') || me.is(':checked')) {
26
+ me.after(jQuery('<input />').attr({
27
  type: 'hidden',
28
  name: me.attr('name')
29
  }).val(me.val()));
56
  }
57
  }
58
 
59
+ function w3tc_referrer_groups_clear() {
60
+ if (!jQuery('#referrer_groups li').size()) {
61
+ jQuery('#referrer_groups_empty').show();
62
+ } else {
63
+ jQuery('#referrer_groups_empty').hide();
64
+ }
65
+ }
66
+
67
  function w3tc_minify_js_file_add(theme, template, location, file) {
68
  var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th>Template:</th><th colspan="3">Embed Location:</th></tr><tr><td>' + (jQuery('#js_files li').size() + 1) + '.</td><td><input class="js_enabled" type="text" name="js_files[' + theme + '][' + template + '][' + location + '][]" value="" size="70" \/></td><td><select class="js_file_template js_enabled"></select></td><td><select class="js_file_location js_enabled"><optgroup label="Blocking:"><option value="include">Embed in &lt;head&gt;</option><option value="include-body">Embed after &lt;body&gt;</option><option value="include-footer">Embed before &lt;/body&gt;</option></optgroup><optgroup label="Non-Blocking:"><option value="include-nb">Embed in &lt;head&gt;</option><option value="include-body-nb">Embed after &lt;body&gt;</option><option value="include-footer-nb">Embed before &lt;/body&gt;</option></optgroup></select></td><td><input class="js_file_delete js_enabled button" type="button" value="Delete" /> <input class="js_file_verify js_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
69
  append.find('input:text').val(file);
70
  var select = append.find('.js_file_template');
71
+ for (var i in minify_templates[theme]) {
72
  select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
73
  }
74
  select.val(template);
81
  var append = jQuery('<li><table><tr><th>&nbsp;</th><th>File URI:</th><th colspan="2">Template:</th></tr><tr><td>' + (jQuery('#css_files li').size() + 1) + '.</td><td><input class="css_enabled" type="text" name="css_files[' + theme + '][' + template + '][include][]" value="" size="70" \/></td><td><select class="css_file_template css_enabled"></select></td><td><input class="css_file_delete css_enabled button" type="button" value="Delete" /></td><td><input class="css_file_verify css_enabled button" type="button" value="Verify URI" /></td></tr></table><\/li>');
82
  append.find('input:text').val(file);
83
  var select = append.find('.css_file_template');
84
+ for (var i in minify_templates[theme]) {
85
  select.append(jQuery('<option />').val(i).html(minify_templates[theme][i]));
86
  }
87
  select.val(template);
126
 
127
  if (match) {
128
  cnames = [];
129
+ for (var i = 1; i <= 10; i++) {
130
  cnames.push('cdn' + i + '.' + match[1]);
131
  }
132
  return false;
175
  });
176
  }
177
 
178
+ function w3tc_cloudflare_api_request(action, value) {
179
+ var email = jQuery('#cloudflare_email');
180
+ var key = jQuery('#cloudflare_key');
181
+ var zone = jQuery('#cloudflare_zone');
182
+
183
+ if (!email.val()) {
184
+ alert('Please enter CloudFlare E-Mail.');
185
+ email.focus();
186
+ return false;
187
+ }
188
+
189
+ if (!key.val()) {
190
+ alert('Please enter CloudFlare API key.');
191
+ key.focus();
192
+ return false;
193
+ }
194
+
195
+ if (!zone.val()) {
196
+ alert('Please enter CloudFlare zone.');
197
+ zone.focus();
198
+ return false;
199
+ }
200
+
201
+ jQuery.post('admin.php?page=w3tc_general', {
202
+ w3tc_action: 'cloudflare_api_request',
203
+ email: email.val(),
204
+ key: key.val(),
205
+ zone: zone.val(),
206
+ action: action,
207
+ value: value
208
+ }, function(data) {
209
+ alert(data.result ? 'OK' : 'Request failed. Error: ' + data.error);
210
+ }, 'json');
211
+
212
+ return true;
213
+ }
214
+
215
+ function w3tc_toggle(name, check) {
216
+ if (check === undefined) {
217
+ check = true;
218
+ }
219
+
220
  var id = '#' + name, cls = '.' + name;
221
 
222
  jQuery(cls).click(function() {
223
+ var checked = check;
224
+
225
  jQuery(cls).each(function() {
226
+ var _checked = jQuery(this).is(':checked');
227
+
228
+ if ((check && !_checked) || (!check && _checked)) {
229
+ checked = !check;
230
+
231
+ return false;
 
 
 
232
  }
233
  });
234
+
235
+ if (checked) {
236
+ jQuery(id).attr('checked', 'checked');
237
+ } else {
238
+ jQuery(id).removeAttr('checked');
239
+ }
240
  });
241
 
242
  jQuery(id).click(function() {
251
  });
252
  }
253
 
254
+ function w3tc_beforeupload_bind() {
255
+ jQuery(window).bind('beforeunload', w3tc_beforeunload);
256
+ }
257
+
258
+ function w3tc_beforeupload_unbind() {
259
+ jQuery(window).unbind('beforeunload', w3tc_beforeunload);
260
+ }
261
+
262
+ function w3tc_beforeunload() {
263
+ return 'Are you sure you wish to navigate away from this page without saving your changes?';
264
+ }
265
+
266
  jQuery(function() {
267
  // general page
268
  w3tc_toggle('enabled');
269
 
270
+ jQuery('.button-tweet').live('click', function() {
271
+ window.open('http://twitter.com/?status=' + encodeURIComponent('YES! I optimized my #wordpress site\'s #performance using the W3 Total Cache #plugin by @w3edge. Check it out! http://j.mp/A69xX'), '_blank');
272
+ });
273
+
274
+ jQuery('.button-rating').live('click', function() {
275
  window.open('http://wordpress.org/extend/plugins/w3-total-cache/', '_blank');
276
  });
277
 
281
  w3tc_toggle('browsercache_etag');
282
  w3tc_toggle('browsercache_w3tc');
283
  w3tc_toggle('browsercache_compression');
284
+ w3tc_toggle('browsercache_replace');
285
 
286
  // minify page
287
  w3tc_input_enable('.html_enabled', jQuery('#html_enabled:checked').size());
332
 
333
  jQuery('.js_file_delete').live('click', function() {
334
  var parent = jQuery(this).parents('li');
335
+ if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this JS file?')) {
336
  parent.remove();
337
  w3tc_minify_js_file_clear();
338
+ w3tc_beforeupload_bind();
339
  }
340
 
341
  return false;
343
 
344
  jQuery('.css_file_delete').live('click', function() {
345
  var parent = jQuery(this).parents('li');
346
+ if (parent.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this CSS file?')) {
347
  parent.remove();
348
  w3tc_minify_css_file_clear();
349
+ w3tc_beforeupload_bind();
350
  }
351
 
352
  return false;
378
  g = '[' + jQuery('#js_themes option[value=' + match[1] + ']').text() + '] ' + v;
379
  }
380
  if (v != '') {
381
+ for (var i = 0; i < js.length; i++) {
382
  if (js[i] == c) {
383
  duplicate = true;
384
  break;
406
  g = '[' + jQuery('#css_themes option[value=' + match[1] + ']').text() + '] ' + v;
407
  }
408
  if (v != '') {
409
+ for (var i = 0; i < css.length; i++) {
410
  if (css[i] == c) {
411
  duplicate = true;
412
  break;
479
  w3tc_popup('admin.php?page=w3tc_cdn&w3tc_action=cdn_rename_domain', 'cdn_rename_domain');
480
  });
481
 
482
+ jQuery('#cdn_purge').click(function() {
483
+ w3tc_popup('admin.php?page=w3tc_cdn&w3tc_action=cdn_purge', 'cdn_purge');
484
+ });
485
+
486
  jQuery('.cdn_export').click(function() {
487
  w3tc_popup('admin.php?page=w3tc_cdn&w3tc_action=cdn_export&cdn_export_type=' + this.name, 'cdn_export_' + this.name);
488
  });
497
  switch (true) {
498
  case me.hasClass('cdn_mirror'):
499
  jQuery.extend(params, {
500
+ engine: 'mirror'
 
501
  });
502
+ if (cnames.length) {
503
+ params['config[domain][]'] = cnames;
504
+ }
505
  break;
506
 
507
  case me.hasClass('cdn_netdna'):
508
  jQuery.extend(params, {
509
+ engine: 'netdna'
 
510
  });
511
+ if (cnames.length) {
512
+ params['config[domain][]'] = cnames;
513
+ }
514
+ break;
515
+
516
+ case me.hasClass('cdn_cotendo'):
517
+ jQuery.extend(params, {
518
+ engine: 'cotendo'
519
+ });
520
+ if (cnames.length) {
521
+ params['config[domain][]'] = cnames;
522
+ }
523
  break;
524
 
525
  case me.hasClass('cdn_ftp'):
529
  'config[user]': jQuery('#cdn_ftp_user').val(),
530
  'config[path]': jQuery('#cdn_ftp_path').val(),
531
  'config[pass]': jQuery('#cdn_ftp_pass').val(),
532
+ 'config[pasv]': jQuery('#cdn_ftp_pasv:checked').size()
 
533
  });
534
+ if (cnames.length) {
535
+ params['config[domain][]'] = cnames;
536
+ }
537
  break;
538
 
539
  case me.hasClass('cdn_s3'):
541
  engine: 's3',
542
  'config[key]': jQuery('#cdn_s3_key').val(),
543
  'config[secret]': jQuery('#cdn_s3_secret').val(),
544
+ 'config[bucket]': jQuery('#cdn_s3_bucket').val()
 
545
  });
546
+ if (cnames.length) {
547
+ params['config[cname][]'] = cnames;
548
+ }
549
  break;
550
 
551
  case me.hasClass('cdn_cf'):
554
  'config[key]': jQuery('#cdn_cf_key').val(),
555
  'config[secret]': jQuery('#cdn_cf_secret').val(),
556
  'config[bucket]': jQuery('#cdn_cf_bucket').val(),
557
+ 'config[id]': jQuery('#cdn_cf_id').val()
 
558
  });
559
+ if (cnames.length) {
560
+ params['config[cname][]'] = cnames;
561
+ }
562
+ break;
563
+
564
+ case me.hasClass('cdn_cf2'):
565
+ jQuery.extend(params, {
566
+ engine: 'cf2',
567
+ 'config[key]': jQuery('#cdn_cf2_key').val(),
568
+ 'config[secret]': jQuery('#cdn_cf2_secret').val(),
569
+ 'config[origin]': jQuery('#cdn_cf2_origin').val(),
570
+ 'config[id]': jQuery('#cdn_cf2_id').val()
571
+ });
572
+ if (cnames.length) {
573
+ params['config[cname][]'] = cnames;
574
+ }
575
  break;
576
 
577
  case me.hasClass('cdn_rscf'):
579
  engine: 'rscf',
580
  'config[user]': jQuery('#cdn_rscf_user').val(),
581
  'config[key]': jQuery('#cdn_rscf_key').val(),
582
+ 'config[location]': jQuery('#cdn_rscf_location').val(),
583
  'config[container]': jQuery('#cdn_rscf_container').val(),
584
+ 'config[id]': jQuery('#cdn_rscf_id').val()
585
+ });
586
+ if (cnames.length) {
587
+ params['config[cname][]'] = cnames;
588
+ }
589
+ break;
590
+
591
+ case me.hasClass('cdn_azure'):
592
+ jQuery.extend(params, {
593
+ engine: 'azure',
594
+ 'config[user]': jQuery('#cdn_azure_user').val(),
595
+ 'config[key]': jQuery('#cdn_azure_key').val(),
596
+ 'config[container]': jQuery('#cdn_azure_container').val()
597
  });
598
+ if (cnames.length) {
599
+ params['config[cname][]'] = cnames;
600
+ }
601
  break;
602
  }
603
 
613
  }, 'json');
614
  });
615
 
616
+ jQuery('#cdn_create_container').live('click', function() {
617
  var me = jQuery(this);
618
  var cnames = w3tc_cdn_get_cnames();
619
  var container_id = null;
628
  'config[key]': jQuery('#cdn_s3_key').val(),
629
  'config[secret]': jQuery('#cdn_s3_secret').val(),
630
  'config[bucket]': jQuery('#cdn_s3_bucket').val(),
631
+ 'config[bucket_location]': jQuery('#cdn_s3_bucket_location').val(),
632
  'config[cname][]': cnames
633
  });
634
  break;
641
  'config[key]': jQuery('#cdn_cf_key').val(),
642
  'config[secret]': jQuery('#cdn_cf_secret').val(),
643
  'config[bucket]': jQuery('#cdn_cf_bucket').val(),
644
+ 'config[bucket_location]': jQuery('#cdn_cf_bucket_location').val(),
645
+ 'config[cname][]': cnames
646
+ });
647
+ break;
648
+
649
+ case me.hasClass('cdn_cf2'):
650
+ container_id = jQuery('#cdn_cf2_id');
651
+
652
+ jQuery.extend(params, {
653
+ engine: 'cf2',
654
+ 'config[key]': jQuery('#cdn_cf2_key').val(),
655
+ 'config[secret]': jQuery('#cdn_cf2_secret').val(),
656
+ 'config[origin]': jQuery('#cdn_cf2_origin').val(),
657
+ 'config[bucket_location]': jQuery('#cdn_cf2_bucket_location').val(),
658
  'config[cname][]': cnames
659
  });
660
  break;
661
 
662
  case me.hasClass('cdn_rscf'):
663
+ container_id = jQuery('#cdn_cnames input[type=text]:first');
664
 
665
  jQuery.extend(params, {
666
  engine: 'rscf',
670
  'config[cname][]': cnames
671
  });
672
  break;
673
+
674
+ case me.hasClass('cdn_azure'):
675
+ jQuery.extend(params, {
676
+ engine: 'azure',
677
+ 'config[user]': jQuery('#cdn_azure_user').val(),
678
+ 'config[key]': jQuery('#cdn_azure_key').val(),
679
+ 'config[container]': jQuery('#cdn_azure_container').val(),
680
+ 'config[cname][]': cnames
681
+ });
682
+ break;
683
  }
684
 
685
  var status = jQuery('#cdn_create_container_status');
698
  }, 'json');
699
  });
700
 
701
+ jQuery('#cloudflare_purge_cache').click(function() {
702
+ if (confirm('Purging your site\'s cache will remove all cache files. It may take up to 48 hours for the cache to completely rebuild on CloudFlare\'s global network. Are you sure you want to purge the cache?')) {
703
+ w3tc_cloudflare_api_request('fpurge_ts', 1);
704
+ }
705
+ });
706
+
707
  jQuery('#memcached_test').click(function() {
708
  var status = jQuery('#memcached_test_status');
709
  status.removeClass('w3tc-error');
719
  }, 'json');
720
  });
721
 
722
+ jQuery('.minifier_test').click(function() {
723
+ var me = jQuery(this);
724
+ var params = {
725
+ w3tc_action: 'test_minifier'
726
+ };
727
+
728
+ switch (true) {
729
+ case me.hasClass('minifier_yuijs'):
730
+ jQuery.extend(params, {
731
+ engine: 'yuijs',
732
+ path_java: jQuery('#minify_yuijs_path_java').val(),
733
+ path_jar: jQuery('#minify_yuijs_path_jar').val()
734
+ });
735
+ break;
736
+
737
+ case me.hasClass('minifier_yuicss'):
738
+ jQuery.extend(params, {
739
+ engine: 'yuicss',
740
+ path_java: jQuery('#minify_yuicss_path_java').val(),
741
+ path_jar: jQuery('#minify_yuicss_path_jar').val()
742
+ });
743
+ break;
744
+
745
+ case me.hasClass('minifier_ccjs'):
746
+ jQuery.extend(params, {
747
+ engine: 'ccjs',
748
+ path_java: jQuery('#minify_ccjs_path_java').val(),
749
+ path_jar: jQuery('#minify_ccjs_path_jar').val()
750
+ });
751
+ break;
752
+ }
753
+
754
+ var status = me.next();
755
+ status.removeClass('w3tc-error');
756
+ status.removeClass('w3tc-success');
757
+ status.addClass('w3tc-process');
758
+ status.html('Testing...');
759
+
760
+ jQuery.post('admin.php?page=w3tc_general', params, function(data) {
761
+ status.addClass(data.result ? 'w3tc-success' : 'w3tc-error');
762
+ status.html(data.error);
763
+ }, 'json');
764
+ });
765
+
766
  // CDN cnames
767
  jQuery('#cdn_cname_add').click(function() {
768
  jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="" size="30" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
771
 
772
  jQuery('.cdn_cname_delete').live('click', function() {
773
  var p = jQuery(this).parent();
774
+ if (p.find('input[type=text]').val() == '' || confirm('Are you sure you want to remove this CNAME?')) {
775
  p.remove();
776
  w3tc_cdn_cnames_assign();
777
+ w3tc_beforeupload_bind();
778
  }
779
  });
780
 
781
+ jQuery('#cdn_form').submit(function() {
782
+ var cnames = [], ret = true;
783
+
784
+ jQuery('#cdn_cnames input[type=text]').each(function() {
785
+ var cname = jQuery(this).val();
786
+
787
+ if (cname) {
788
+ if (jQuery.inArray(cname, cnames) != -1) {
789
+ alert('CNAME "' + cname + '" already exists.');
790
+ ret = false;
791
+
792
+ return false;
793
+ } else {
794
+ cnames.push(cname);
795
+ }
796
+ }
797
+ });
798
+
799
+ return ret;
800
+ });
801
+
802
  // support tabs
803
  jQuery('#support_more_files').live('click', function() {
804
  jQuery(this).before('<input type="file" name="files[]" /><br />');
837
  return false;
838
  }
839
 
840
+ if (phone.size() && !/^[0-9\-\. \(\)\+]+$/.test(phone.val())) {
841
  alert('Please enter your phone in the phone field.');
842
  phone.focus();
843
  return false;
888
  return true;
889
  });
890
 
891
+ function w3tc_support_request_type_change() {
892
+ jQuery('#support_request_type').change(function() {
893
+ var request_type = jQuery(this);
894
 
895
+ if (request_type.val() == '') {
896
+ alert('Please select request type.');
897
+ request_type.focus();
898
 
899
+ return false;
900
+ }
901
 
902
+ var type = request_type.val(), action = '';
903
 
904
+ switch (type) {
905
+ case 'bug_report':
906
+ case 'new_feature':
907
+ action = 'options_support';
908
+ break;
909
 
910
+ case 'email_support':
911
+ case 'phone_support':
912
+ case 'plugin_config':
913
+ case 'theme_config':
914
+ case 'linux_config':
915
+ action = 'options_support_payment';
916
+ break;
917
+ }
918
 
919
+ if (action) {
920
+ jQuery('#support_container').html('<div id="support_loading">Loading...</div>').load('admin.php?page=w3tc_support&w3tc_action=' + action + '&request_type=' + type + '&ajax=1');
921
 
922
+ return false;
923
+ }
924
 
925
+ return true;
926
+ });
927
+ }
928
+
929
+ w3tc_support_request_type_change();
930
 
931
  jQuery('#support_cancel').live('click', function() {
932
+ jQuery('#support_container').html('<div id="support_loading">Loading...</div>').load('admin.php?page=w3tc_support&w3tc_action=options_support_select&ajax=1', function() {
933
+ w3tc_support_request_type_change();
934
+ });
935
  });
936
 
937
  // mobile tab
997
  group = group.replace(/_+$/, '');
998
 
999
  if (group) {
1000
+ var exists = false;
1001
+
1002
  jQuery('.mobile_group').each(function() {
1003
  if (jQuery(this).html() == group) {
1004
  alert('Group already exists!');
1005
+ exists = true;
1006
  return false;
1007
  }
1008
  });
1009
 
1010
+ if (!exists) {
1011
+ var li = jQuery('<li id="mobile_group_' + group + '"><table class="form-table"><tr><th>Group name:</th><td><span class="mobile_group_number">' + (jQuery('#mobile_groups li').size() + 1) + '.</span> <span class="mobile_group">' + group + '</span> <input type="button" class="button mobile_delete" value="Delete group" /></td></tr><tr><th><label for="mobile_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="mobile_groups[' + group + '][enabled]" value="0" /><input id="mobile_groups_' + group + '_enabled" type="checkbox" name="mobile_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th><label for="mobile_groups_' + group + '_theme">Theme:</label></th><td><select id="mobile_groups_' + group + '_theme" name="mobile_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of user agents to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. mobile plugins) to properly handle requests for these user agents. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th><label for="mobile_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="mobile_groups_' + group + '_redirect" type="text" name="mobile_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a mobile version of your site.</span></td></tr><tr><th><label for="mobile_groups_' + group + '_agents">User agents:</label></th><td><textarea id="mobile_groups_' + group + '_agents" name="mobile_groups[' + group + '][agents]" rows="10" cols="50"></textarea><br /><span class="description">Specify the user agents for this group.</span></td></tr></table></li>');
1012
+ var select = li.find('select');
1013
 
1014
+ jQuery.each(mobile_themes, function(index, value) {
1015
+ select.append(jQuery('<option />').val(index).html(value));
1016
+ });
1017
 
1018
+ jQuery('#mobile_groups').append(li);
1019
+ w3tc_mobile_groups_clear();
1020
 
1021
+ window.location.hash = '#mobile_group_' + group;
1022
+ }
1023
  } else {
1024
  alert('Empty group name!');
1025
  }
1030
  if (confirm('Are you sure want to delete this group?')) {
1031
  jQuery(this).parents('#mobile_groups li').remove();
1032
  w3tc_mobile_groups_clear();
1033
+ w3tc_beforeupload_bind();
1034
  }
1035
  });
1036
 
1037
  w3tc_mobile_groups_clear();
1038
 
1039
+ // referrer tab
1040
+ jQuery('#referrer_form').submit(function() {
1041
+ var error = false;
1042
+
1043
+ jQuery('#referrer_groups li').each(function() {
1044
+ if (jQuery(this).find(':checked').size()) {
1045
+ var group = jQuery(this).find('.referrer_group').text();
1046
+ var theme = jQuery(this).find(':selected').val();
1047
+ var redirect = jQuery(this).find('input[type=text]').val();
1048
+ var agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1049
+
1050
+ jQuery('#referrer_groups li').each(function() {
1051
+ if (jQuery(this).find(':checked').size()) {
1052
+ var compare_group = jQuery(this).find('.referrer_group').text();
1053
+ if (compare_group != group) {
1054
+ var compare_theme = jQuery(this).find(':selected').val();
1055
+ var compare_redirect = jQuery(this).find('input[type=text]').val();
1056
+ var compare_agents = jQuery.trim(jQuery(this).find('textarea').val()).split("\n");
1057
+
1058
+ if (compare_redirect == '' && redirect == '' && compare_theme != '' && compare_theme == theme) {
1059
+ alert('Duplicate theme "' + compare_theme + '" found in the group "' + group + '".');
1060
+ error = true;
1061
+ return false;
1062
+ }
1063
+
1064
+ if (compare_redirect != '' && compare_redirect == redirect) {
1065
+ alert('Duplicate redirect "' + compare_redirect + '" found in the group "' + group + '".');
1066
+ error = true;
1067
+ return false;
1068
+ }
1069
+
1070
+ jQuery.each(compare_agents, function(index, value) {
1071
+ if (jQuery.inArray(value, agents) != -1) {
1072
+ alert('Duplicate stem "' + value + '" found in the group "' + compare_group + '".');
1073
+ error = true;
1074
+ return false;
1075
+ }
1076
+ });
1077
+ }
1078
+ }
1079
+ });
1080
+
1081
+ if (error) {
1082
+ return false;
1083
+ }
1084
+ }
1085
+ });
1086
+
1087
+ if (error) {
1088
+ return false;
1089
+ }
1090
+ });
1091
+
1092
+ jQuery('#referrer_add').click(function() {
1093
+ var group = prompt('Enter group name (only "0-9", "a-z", "_" symbols are allowed).');
1094
+
1095
+ if (group !== null) {
1096
+ group = group.toLowerCase();
1097
+ group = group.replace(/[^0-9a-z_]+/g, '_');
1098
+ group = group.replace(/^_+/, '');
1099
+ group = group.replace(/_+$/, '');
1100
+
1101
+ if (group) {
1102
+ var exists = false;
1103
+
1104
+ jQuery('.referrer_group').each(function() {
1105
+ if (jQuery(this).html() == group) {
1106
+ alert('Group already exists!');
1107
+ exists = true;
1108
+ return false;
1109
+ }
1110
+ });
1111
+
1112
+ if (!exists) {
1113
+ var li = jQuery('<li id="referrer_group_' + group + '"><table class="form-table"><tr><th>Group name:</th><td><span class="referrer_group_number">' + (jQuery('#referrer_groups li').size() + 1) + '.</span> <span class="referrer_group">' + group + '</span> <input type="button" class="button referrer_delete" value="Delete group" /></td></tr><tr><th><label for="referrer_groups_' + group + '_enabled">Enabled:</label></th><td><input type="hidden" name="referrer_groups[' + group + '][enabled]" value="0" /><input id="referrer_groups_' + group + '_enabled" type="checkbox" name="referrer_groups[' + group + '][enabled]" value="1" checked="checked" /></td></tr><tr><th><label for="referrer_groups_' + group + '_theme">Theme:</label></th><td><select id="referrer_groups_' + group + '_theme" name="referrer_groups[' + group + '][theme]"><option value="">-- Pass-through --</option></select><br /><span class="description">Assign this group of referrers to a specific them. Leaving this option "Active Theme" allows any plugins you have (e.g. referrer plugins) to properly handle requests for these referrers. If the "redirect users to" field is not empty, this setting is ignored.</span></td></tr><tr><th><label for="referrer_groups_' + group + '_redirect">Redirect users to:</label></th><td><input id="referrer_groups_' + group + '_redirect" type="text" name="referrer_groups[' + group + '][redirect]" value="" size="60" /><br /><span class="description">A 302 redirect is used to send this group of users to another hostname (domain); recommended if a 3rd party service provides a referrer version of your site.</span></td></tr><tr><th><label for="referrer_groups_' + group + '_referrers">Referrers:</label></th><td><textarea id="referrer_groups_' + group + '_referrers" name="referrer_groups[' + group + '][referrers]" rows="10" cols="50"></textarea><br /><span class="description">Specify the referrers for this group.</span></td></tr></table></li>');
1114
+ var select = li.find('select');
1115
+
1116
+ jQuery.each(referrer_themes, function(index, value) {
1117
+ select.append(jQuery('<option />').val(index).html(value));
1118
+ });
1119
+
1120
+ jQuery('#referrer_groups').append(li);
1121
+ w3tc_referrer_groups_clear();
1122
+
1123
+ window.location.hash = '#referrer_group_' + group;
1124
+ }
1125
+ } else {
1126
+ alert('Empty group name!');
1127
+ }
1128
+ }
1129
+ });
1130
+
1131
+ jQuery('.referrer_delete').live('click', function() {
1132
+ if (confirm('Are you sure want to delete this group?')) {
1133
+ jQuery(this).parents('#referrer_groups li').remove();
1134
+ w3tc_referrer_groups_clear();
1135
+ w3tc_beforeupload_bind();
1136
+ }
1137
+ });
1138
+
1139
+ w3tc_referrer_groups_clear();
1140
+
1141
  // add sortable
1142
  if (jQuery.ui && jQuery.ui.sortable) {
1143
+ jQuery('#js_files,#css_files').sortable({
1144
  axis: 'y',
1145
  stop: function() {
1146
  jQuery(this).find('li').each(function(index) {
1149
  }
1150
  });
1151
 
1152
+ jQuery('#cdn_cnames').sortable({
1153
  axis: 'y',
1154
  stop: w3tc_cdn_cnames_assign
1155
  });
1156
 
1157
+ jQuery('#mobile_groups').sortable({
1158
  axis: 'y',
1159
  stop: function() {
1160
  jQuery('#mobile_groups .mobile_group_number').each(function(index) {
1162
  });
1163
  }
1164
  });
1165
+
1166
+ jQuery('#referrer_groups').sortable({
1167
+ axis: 'y',
1168
+ stop: function() {
1169
+ jQuery('#referrer_groups .referrer_group_number').each(function(index) {
1170
+ jQuery(this).html((index + 1) + '.');
1171
+ });
1172
+ }
1173
+ });
1174
  }
1175
 
1176
  // show hide rules
1186
  }
1187
  });
1188
 
1189
+ // check for unsaved changes
1190
+ jQuery('#w3tc input,#w3tc select,#w3tc textarea').live('change', function() {
1191
+ var ignore = false;
1192
+ jQuery(this).parents().andSelf().each(function() {
1193
+ if (jQuery(this).hasClass('w3tc-ignore-change') || jQuery(this).hasClass('lightbox')) {
1194
+ ignore = true;
1195
+ return false;
1196
+ }
1197
+ });
1198
+
1199
+ if (!ignore) {
1200
+ w3tc_beforeupload_bind();
1201
+ }
1202
  });
1203
+
1204
+ jQuery('.w3tc-button-save').click(w3tc_beforeupload_unbind);
1205
  });
inc/js/popup.js CHANGED
@@ -74,13 +74,13 @@ var W3tc_Popup_Cdn_Export_File = {
74
 
75
  this.upload_files = [];
76
 
77
- for ( var i = this.offset, l = this.files.length, j = 0; i < l && j < this.limit; i++, j++) {
78
  this.upload_files.push(this.files[i]);
79
  }
80
 
81
  var me = this;
82
  if (this.upload_files.length) {
83
- jQuery.ajax( {
84
  type: 'POST',
85
  url: 'admin.php?page=w3tc_cdn',
86
  data: {
@@ -118,7 +118,7 @@ var W3tc_Popup_Cdn_Export_File = {
118
 
119
  process_callback: function(data) {
120
  var failed = false;
121
- for ( var i = 0; i < data.results.length; i++) {
122
  this.add_log(data.results[i].remote_path, data.results[i].result, data.results[i].error);
123
  if (data.results[i].result == -1) {
124
  failed = true;
@@ -239,7 +239,7 @@ var W3tc_Popup_Cdn_Export_Library = {
239
  }
240
 
241
  var me = this;
242
- jQuery.ajax( {
243
  type: 'POST',
244
  url: 'admin.php?page=w3tc_cdn',
245
  data: {
@@ -283,7 +283,7 @@ var W3tc_Popup_Cdn_Export_Library = {
283
  this.set_progress((this.offset * 100 / data.total).toFixed(0));
284
 
285
  var failed = false;
286
- for ( var i = 0; i < data.results.length; i++) {
287
  this.add_log(data.results[i].remote_path, data.results[i].result, data.results[i].error);
288
  if (data.results[i].result == -1) {
289
  failed = true;
@@ -426,7 +426,7 @@ var W3tc_Popup_Cdn_Import_Library = {
426
  }
427
 
428
  var me = this;
429
- jQuery.ajax( {
430
  type: 'POST',
431
  url: 'admin.php?page=w3tc_cdn',
432
  data: {
@@ -470,7 +470,7 @@ var W3tc_Popup_Cdn_Import_Library = {
470
  this.set_progress((this.offset * 100 / data.total).toFixed(0));
471
 
472
  var failed = false;
473
- for ( var i = 0; i < data.results.length; i++) {
474
  this.add_log(data.results[i].src, data.results[i].result, data.results[i].error);
475
  if (data.results[i].result == 1) {
476
  this.add_rule(data.results[i].src, data.results[i].dst);
@@ -589,7 +589,7 @@ var W3tc_Popup_Cdn_Rename_Domain = {
589
  }
590
 
591
  var me = this;
592
- jQuery.ajax( {
593
  type: 'POST',
594
  url: 'admin.php?page=w3tc_cdn',
595
  data: {
@@ -634,7 +634,7 @@ var W3tc_Popup_Cdn_Rename_Domain = {
634
  this.set_progress((this.offset * 100 / data.total).toFixed(0));
635
 
636
  var failed = false;
637
- for ( var i = 0; i < data.results.length; i++) {
638
  this.add_log(data.results[i].old, data.results[i].result, data.results[i].error);
639
  if (data.results[i].result == -1) {
640
  failed = true;
@@ -698,6 +698,21 @@ var W3tc_Popup_Cdn_Rename_Domain = {
698
  }
699
  };
700
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701
  jQuery(function() {
702
  jQuery('.tab').click(function() {
703
  jQuery('.tab').removeClass('tab-selected');
@@ -713,4 +728,35 @@ jQuery(function() {
713
  jQuery('.cdn_queue_empty').click(function() {
714
  return confirm('Are you sure you want to empty the queue?');
715
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
716
  });
74
 
75
  this.upload_files = [];
76
 
77
+ for (var i = this.offset, l = this.files.length, j = 0; i < l && j < this.limit; i++,j++) {
78
  this.upload_files.push(this.files[i]);
79
  }
80
 
81
  var me = this;
82
  if (this.upload_files.length) {
83
+ jQuery.ajax({
84
  type: 'POST',
85
  url: 'admin.php?page=w3tc_cdn',
86
  data: {
118
 
119
  process_callback: function(data) {
120
  var failed = false;
121
+ for (var i = 0; i < data.results.length; i++) {
122
  this.add_log(data.results[i].remote_path, data.results[i].result, data.results[i].error);
123
  if (data.results[i].result == -1) {
124
  failed = true;
239
  }
240
 
241
  var me = this;
242
+ jQuery.ajax({
243
  type: 'POST',
244
  url: 'admin.php?page=w3tc_cdn',
245
  data: {
283
  this.set_progress((this.offset * 100 / data.total).toFixed(0));
284
 
285
  var failed = false;
286
+ for (var i = 0; i < data.results.length; i++) {
287
  this.add_log(data.results[i].remote_path, data.results[i].result, data.results[i].error);
288
  if (data.results[i].result == -1) {
289
  failed = true;
426
  }
427
 
428
  var me = this;
429
+ jQuery.ajax({
430
  type: 'POST',
431
  url: 'admin.php?page=w3tc_cdn',
432
  data: {
470
  this.set_progress((this.offset * 100 / data.total).toFixed(0));
471
 
472
  var failed = false;
473
+ for (var i = 0; i < data.results.length; i++) {
474
  this.add_log(data.results[i].src, data.results[i].result, data.results[i].error);
475
  if (data.results[i].result == 1) {
476
  this.add_rule(data.results[i].src, data.results[i].dst);
589
  }
590
 
591
  var me = this;
592
+ jQuery.ajax({
593
  type: 'POST',
594
  url: 'admin.php?page=w3tc_cdn',
595
  data: {
634
  this.set_progress((this.offset * 100 / data.total).toFixed(0));
635
 
636
  var failed = false;
637
+ for (var i = 0; i < data.results.length; i++) {
638
  this.add_log(data.results[i].old, data.results[i].result, data.results[i].error);
639
  if (data.results[i].result == -1) {
640
  failed = true;
698
  }
699
  };
700
 
701
+ function w3tc_ps_expand(expand) {
702
+ jQuery('.ps-rule').each(function() {
703
+ var e = jQuery(this).find('.ps-expander');
704
+ var a = jQuery(this).find('.ps-expand a');
705
+
706
+ if (!expand) {
707
+ e.hide();
708
+ a.html('+');
709
+ } else {
710
+ e.show();
711
+ a.html('-');
712
+ }
713
+ });
714
+ }
715
+
716
  jQuery(function() {
717
  jQuery('.tab').click(function() {
718
  jQuery('.tab').removeClass('tab-selected');
728
  jQuery('.cdn_queue_empty').click(function() {
729
  return confirm('Are you sure you want to empty the queue?');
730
  });
731
+
732
+ jQuery('.ps-rule').click(function() {
733
+ var e = jQuery(this).find('.ps-expander');
734
+ var a = jQuery(this).find('.ps-expand a');
735
+
736
+ if (e.is(':visible')) {
737
+ e.hide();
738
+ a.html('+');
739
+ } else {
740
+ e.show();
741
+ a.html('-');
742
+ }
743
+
744
+ return false;
745
+ });
746
+
747
+ jQuery('.ps-rule p a,.ps-expander').click(function(event) {
748
+ event.stopPropagation();
749
+ });
750
+
751
+ jQuery('.ps-expand-all').click(function() {
752
+ w3tc_ps_expand(1);
753
+ });
754
+
755
+ jQuery('.ps-collapse-all').click(function() {
756
+ w3tc_ps_expand(0);
757
+ });
758
+
759
+ jQuery('.ps-refresh').click(function() {
760
+ document.location.href = 'admin.php?page=w3tc_general&w3tc_action=pagespeed_results&force=1';
761
+ });
762
  });
inc/js/widget.js ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function() {
2
+ jQuery('.w3tc-widget-ps-view-all').click(function() {
3
+ window.open('admin.php?page=w3tc_general&w3tc_action=pagespeed_results', 'pagespeed_results', 'width=800,height=600,status=no,toolbar=no,menubar=no,scrollbars=yes');
4
+
5
+ return false;
6
+ });
7
+
8
+ jQuery('.w3tc-widget-ps-refresh').click(function() {
9
+ document.location.href = 'index.php?w3tc_widget_pagespeed_force=1';
10
+ });
11
+ });
inc/lightbox/cdn_s3_bucket_location.phtml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h3>Select bucket location</h3>
2
+
3
+ <p>
4
+ <label>Location:
5
+ <select id="cdn_<?php echo $type; ?>_bucket_location">
6
+ <?php foreach ($locations as $location => $name): ?>
7
+ <option value="<?php echo $location; ?>"><?php echo $name; ?></option>
8
+ <?php endforeach; ?>
9
+ </select>
10
+ </label>
11
+ </p>
12
+ <p>
13
+ <input id="cdn_create_container" class="button-primary cdn_<?php echo $type; ?>" type="button" value="Create bucket" />
14
+ <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
15
+ </p>
16
+ <p style="text-align: center;">
17
+ <input class="button" type="button" value="Close" />
18
+ </p>
inc/lightbox/minify_recommendations.phtml CHANGED
@@ -1,16 +1,17 @@
1
  <h3>Minify Help Wizard</h3>
2
 
 
 
 
 
 
 
 
 
 
 
3
  <div id="recom_container">
4
- <p>
5
- To get started with minify, we've identified the following external CSS and JS objects in the
6
- <select id="recom_theme">
7
- <?php foreach ($themes as $_theme_key => $_theme_name): ?>
8
- <option value="<?php echo htmlspecialchars($_theme_key); ?>"<?php selected($_theme_key, $theme_key); ?>><?php echo htmlspecialchars($_theme_name); ?><?php if ($_theme_key == $theme_key): ?> (active)<?php endif; ?></option>
9
- <?php endforeach; ?>
10
- </select>
11
- theme. Select "add" the files you wish to minify, then click "apply &amp; close" to save the settings.
12
- </p>
13
-
14
  <h4>JavaScript:</h4>
15
 
16
  <?php if (count($js_groups)) :?>
@@ -116,15 +117,17 @@
116
  <?php else:?>
117
  <p>No files found.</p>
118
  <?php endif;?>
119
-
120
- <p>
121
- <input class="recom_apply button-primary" type="button" value="Apply &amp; close" />
122
- </p>
123
-
124
- <h4>Notes:</h4>
125
-
 
 
126
  <ul>
127
- <li>Typically minification of advertiser code, analytics/statistics or any other types of tracking code is not recommended.</li>
128
- <li>Scripts that were not already detected above may require <a href="admin.php?page=w3tc_support&amp;request_type=plugin_config">professional consultation</a> to implement.</li>
129
  </ul>
130
- </div>
1
  <h3>Minify Help Wizard</h3>
2
 
3
+ <p>
4
+ To get started with minify, we've identified the following external CSS and JS objects in the
5
+ <select id="recom_theme">
6
+ <?php foreach ($themes as $_theme_key => $_theme_name): ?>
7
+ <option value="<?php echo htmlspecialchars($_theme_key); ?>"<?php selected($_theme_key, $theme_key); ?>><?php echo htmlspecialchars($_theme_name); ?><?php if ($_theme_key == $theme_key): ?> (active)<?php endif; ?></option>
8
+ <?php endforeach; ?>
9
+ </select>
10
+ theme. Select "add" the files you wish to minify, then click "apply &amp; close" to save the settings.
11
+ </p>
12
+
13
  <div id="recom_container">
14
+
 
 
 
 
 
 
 
 
 
15
  <h4>JavaScript:</h4>
16
 
17
  <?php if (count($js_groups)) :?>
117
  <?php else:?>
118
  <p>No files found.</p>
119
  <?php endif;?>
120
+ </div>
121
+
122
+ <p>
123
+ <input class="recom_apply button-primary" type="button" value="Apply &amp; close" />
124
+ </p>
125
+
126
+ <fieldset>
127
+ <legend>Notes</legend>
128
+
129
  <ul>
130
+ <li>Typically minification of advertiser code, analytics/statistics or any other types of tracking code is not recommended.</li>
131
+ <li>Scripts that were not already detected above may require <a href="admin.php?page=w3tc_support&amp;request_type=plugin_config">professional consultation</a> to implement.</li>
132
  </ul>
133
+ </fieldset>
inc/lightbox/self_test.phtml CHANGED
@@ -1,342 +1,283 @@
1
  <h3>Compatibility Test</h3>
2
 
3
- <div id="self_test_container">
 
 
 
 
 
 
 
 
 
 
 
4
  <h4>Server Modules &amp; Resources:</h4>
5
-
6
- <div class="monospace">
7
- PHP Version:
8
- <?php if (PHP_VERSION >= 5): ?>
9
- <span class="w3tc-test-ok"><?php echo PHP_VERSION; ?></span>
10
- <?php else: ?>
11
- <span class="w3tc-test-warn"><?php echo PHP_VERSION; ?> (Minify disabled)</span>;
12
- <?php endif; ?>
13
- <br />
14
-
15
- PHP Timezone:
16
- <?php if (ini_get('date.timezone')): ?>
17
- <span class="w3tc-test-ok">OK</span>
18
- <?php else: ?>
19
- <span class="w3tc-test-error">Not set</span>
20
- <?php endif; ?>
21
- <br />
22
-
23
- Web Server:
24
- <?php if (stristr($_SERVER['SERVER_SOFTWARE'], 'apache') !== false): ?>
25
- <span class="w3tc-test-ok">Apache</span>
26
- <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false): ?>
27
- <span class="w3tc-test-warn">Lite Speed</span>
28
- <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false): ?>
29
- <span class="w3tc-test-warn">nginx</span>
30
- <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false): ?>
31
- <span class="w3tc-test-warn">lighttpd</span>
32
- <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'iis') !== false): ?>
33
- <span class="w3tc-test-warn">Microsoft IIS</span>
34
- <?php else: ?>
35
- <span class="w3tc-test-error">Not detected</span>
36
- <?php endif; ?>
37
- <br />
38
 
39
- FTP functions:
40
- <?php if (function_exists('ftp_connect')): ?>
41
- <span class="w3tc-test-ok">OK</span>
42
- <?php else: ?>
43
- <span class="w3tc-test-error">Not installed</span>
44
- <?php endif; ?>
45
- (required for Self-hosted (FTP) CDN support)
46
- <br />
47
-
48
- Multibyte String support:
49
- <?php if (function_exists('mb_substr')): ?>
50
- <span class="w3tc-test-ok">OK</span>
51
- <?php else: ?>
52
- <span class="w3tc-test-error">Not installed</span>
53
- <?php endif; ?>
54
- (required for Rackspace Cloud Files support)
55
- <br />
56
-
57
- cURL extension:
58
- <?php if (function_exists('curl_init')): ?>
59
- <span class="w3tc-test-ok">OK</span>
60
- <?php else: ?>
61
- <span class="w3tc-test-error">Not installed</span>
62
- <?php endif; ?>
63
- (required for Amazon S3 support)
64
- <br />
65
-
66
- zlib extension:
67
- <?php if (function_exists('gzencode')): ?>
68
- <span class="w3tc-test-ok">OK</span>
69
- <?php else: ?>
70
- <span class="w3tc-test-error">Not installed</span>
71
- <?php endif; ?>
72
- (required for compression support)
73
- <br />
74
-
75
- Opcode cache:
76
- <?php if (function_exists('apc_store')): ?>
77
- <span class="w3tc-test-ok">APC</span>
78
- <?php elseif (function_exists('eaccelerator_put')): ?>
79
- <span class="w3tc-test-ok">eAccelerator</span>
80
- <?php elseif (function_exists('xcache_set')): ?>
81
- <span class="w3tc-test-ok">XCache</span>
82
- <?php elseif (PHP_VERSION >= 6): ?>
83
- <span class="w3tc-test-ok">PHP6</span>
84
- <?php else: ?>
85
- <span class="w3tc-test-error">Not installed</span>
86
- <?php endif; ?>
87
- <br />
88
-
89
- Memcache extension:
90
- <?php if (class_exists('Memcache')): ?>
91
- <span class="w3tc-test-ok">OK</span>
92
- <?php else: ?>
93
- <span class="w3tc-test-error">Not installed</span>
94
- <?php endif; ?>
95
- <br />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
- Mime type detection:
98
- <?php if (function_exists('finfo_open')): ?>
99
- <span class="w3tc-test-ok">Fileinfo</span>
100
- <?php elseif (function_exists('mime_content_type')): ?>
101
- <span class="w3tc-test-warn">Mimetype</span>
102
- <?php else: ?>
103
- <span class="w3tc-test-error">Not installed</span>
104
- <?php endif; ?>
105
- <br />
106
-
107
- Hash function:
108
- <?php if (function_exists('hash')): ?>
109
- <span class="w3tc-test-ok">hash</span>
110
- <?php elseif (function_exists('mhash')): ?>
111
- <span class="w3tc-test-warn">mhash</span>
112
- <?php else: ?>
113
- <span class="w3tc-test-error">Not installed</span>
114
- <?php endif; ?>
115
- (required for NetDNA purge support)
116
- <br />
117
-
118
- Safe mode:
119
- <?php if (w3_to_boolean(ini_get('safe_mode'))): ?>
120
- <span class="w3tc-test-warn">On</span>
121
- <?php else: ?>
122
- <span class="w3tc-test-ok">Off</span>
123
- <?php endif; ?>
124
- <br />
125
-
126
- Open basedir:
127
- <?php $open_basedir = ini_get('open_basedir'); if ($open_basedir): ?>
128
- <span class="w3tc-test-warn">On: <?php echo htmlspecialchars($open_basedir); ?></span>
129
- <?php else: ?>
130
- <span class="w3tc-test-ok">Off</span>
131
- <?php endif; ?>
132
- <br />
133
-
134
- zlib output compression:
135
- <?php if (w3_to_boolean(ini_get('zlib.output_compression'))): ?>
136
- <span class="w3tc-test-error">On</span>
137
- <?php else: ?>
138
- <span class="w3tc-test-ok">Off</span>
139
- <?php endif; ?>
140
- <br />
141
-
142
- <?php
143
- if (function_exists('apache_get_modules')):
144
- $apache_modules = apache_get_modules();
145
- else:
146
- $apache_modules = false;
147
- endif;
148
  ?>
149
- mod_mime:
150
- <?php if ($apache_modules): ?>
151
- <?php if (in_array('mod_mime', $apache_modules)): ?>
152
- <span class="w3tc-test-ok">OK</span>
153
- <?php else: ?>
154
- <span class="w3tc-test-error">Not installed</span>
155
- <?php endif; ?>
156
- <?php else: ?>
157
- <span class="w3tc-test-warn">Not detected</span>
158
- <?php endif; ?>
159
- <br />
160
-
161
- mod_expires:
162
- <?php if ($apache_modules): ?>
163
- <?php if (in_array('mod_expires', $apache_modules)): ?>
164
- <span class="w3tc-test-ok">OK</span>
165
- <?php else: ?>
166
- <span class="w3tc-test-error">Not installed</span>
167
- <?php endif; ?>
168
- <?php else: ?>
169
- <span class="w3tc-test-warn">Not detected</span>
170
  <?php endif; ?>
171
- <br />
172
 
173
- mod_deflate / mod_gzip:
174
- <?php if ($apache_modules): ?>
175
- <?php if (in_array('mod_deflate', $apache_modules)): ?>
176
- <span class="w3tc-test-ok">OK</span>
177
- <?php else: ?>
178
- <span class="w3tc-test-error">Not installed</span>
179
- <?php endif; ?>
180
- <?php else: ?>
181
- <span class="w3tc-test-warn">Not detected</span>
182
- <?php endif; ?>
183
- <br />
184
-
185
- mod_headers:
186
- <?php if ($apache_modules): ?>
187
- <?php if (in_array('mod_headers', $apache_modules)): ?>
188
- <span class="w3tc-test-ok">OK</span>
189
- <?php else: ?>
190
- <span class="w3tc-test-error">Not installed</span>
191
- <?php endif; ?>
192
- <?php else: ?>
193
- <span class="w3tc-test-warn">Not detected</span>
194
- <?php endif; ?>
195
- <br />
196
-
197
- mod_env:
198
- <?php if ($apache_modules): ?>
199
- <?php if (in_array('mod_env', $apache_modules)): ?>
200
- <span class="w3tc-test-ok">OK</span>
201
- <?php else: ?>
202
- <span class="w3tc-test-error">Not installed</span>
203
- <?php endif; ?>
204
- <?php else: ?>
205
- <span class="w3tc-test-warn">Not detected</span>
206
- <?php endif; ?>
207
- <br />
208
-
209
- mod_setenvif:
210
- <?php if ($apache_modules): ?>
211
- <?php if (in_array('mod_setenvif', $apache_modules)): ?>
212
- <span class="w3tc-test-ok">OK</span>
213
- <?php else: ?>
214
- <span class="w3tc-test-error">Not installed</span>
215
- <?php endif; ?>
216
- <?php else: ?>
217
- <span class="w3tc-test-warn">Not detected</span>
218
- <?php endif; ?>
219
- <br />
220
-
221
- mod_rewrite:
222
- <?php if ($apache_modules): ?>
223
- <?php if (in_array('mod_rewrite', $apache_modules)): ?>
224
- <span class="w3tc-test-ok">OK</span>
225
- <?php else: ?>
226
- <span class="w3tc-test-error">Not installed</span>
227
- <?php endif; ?>
228
- <?php else: ?>
229
- <span class="w3tc-test-warn">Not detected</span>
230
- <?php endif; ?>
231
- </div>
232
-
233
  <h4>WordPress Resources</h4>
234
-
235
- <div class="monospace">
236
- <?php echo w3_path(WP_CONTENT_DIR); ?>:
237
- <?php if (w3_is_writable_dir(WP_CONTENT_DIR)): ?>
238
- <span class="w3tc-test-ok">Write-able</span>
239
- <?php else: ?>
240
- <span class="w3tc-test-error">Not write-able</span>
241
- <?php endif; ?>
242
- <br />
243
-
244
- <?php
245
- $home_root = w3_get_home_root();
246
- $htaccess_home_path = $home_root . '/.htaccess';
247
-
248
- if (file_exists($htaccess_home_path)): ?>
249
- <?php echo htmlspecialchars($htaccess_home_path); ?>
250
- <?php if (w3_is_writable($htaccess_home_path)): ?>
251
- <span class="w3tc-test-ok">Write-able</span>
252
- <?php else: ?>
253
- <span class="w3tc-test-error">Not write-able</span>
254
- <?php endif; ?>
255
- <?php else: ?>
256
- <?php echo htmlspecialchars($home_root); ?>
257
- <?php if (w3_is_writable_dir($home_root)): ?>
258
- <span class="w3tc-test-ok">Write-able</span>
259
- <?php else: ?>
260
- <span class="w3tc-test-error">Not write-able</span>
261
- <?php endif; ?>
262
- <?php endif; ?>
263
- <br />
264
-
265
- <?php
266
- $document_root = w3_get_document_root();
267
- $htaccess_docroot_path = $document_root . '/.htaccess';
268
-
269
- if ($document_root != $home_root): if (file_exists($htaccess_docroot_path)): ?>
270
- <?php echo htmlspecialchars($htaccess_docroot_path); ?>
271
- <?php if (w3_is_writable($htaccess_docroot_path)): ?>
272
- <span class="w3tc-test-ok">Write-able</span>
273
- <?php else: ?>
274
- <span class="w3tc-test-error">Not write-able</span>
275
- <?php endif; ?>
276
- <?php else: ?>
277
- <?php echo htmlspecialchars($document_root); ?>
278
- <?php if (w3_is_writable_dir($document_root)): ?>
279
- <span class="w3tc-test-ok">Write-able</span>
280
- <?php else: ?>
281
- <span class="w3tc-test-error">Not write-able</span>
282
- <?php endif; ?>
283
- <?php endif; ?><br /><?php endif; ?>
284
-
285
- Uploads directory:
286
- <?php $uploads_dir = @wp_upload_dir(); if (!empty($uploads_dir['error'])): ?>
287
- <span class="w3tc-test-error">Error: <?php echo htmlspecialchars($uploads_dir['error']); ?></span>
288
- <?php elseif (!w3_is_writable_dir($uploads_dir['path'])): ?>
289
- <span class="w3tc-test-error">Not write-able</span>
290
- <?php else: ?>
291
- <span class="w3tc-test-ok">Write-able</span>
292
- <?php endif; ?>
293
- <br />
294
-
295
- WP_CACHE define:
296
- <?php if (defined('WP_CACHE') && WP_CACHE): ?>
297
- <span class="w3tc-test-ok">OK</span>
298
- <?php else: ?>
299
- <span class="w3tc-test-error">Not defined</span>
300
- <?php endif; ?>
301
- <br />
302
-
303
- Fancy permalinks:
304
- <?php if (get_option('permalink_structure')): ?>
305
- <span class="w3tc-test-ok">OK</span>
306
- <?php else: ?>
307
- <span class="w3tc-test-warn">Disabled</span>
308
- <?php endif; ?>
309
- <br />
310
-
311
- Network mode:
312
- <?php if (w3_is_multisite()): ?>
313
- <span class="w3tc-test-ok">On</span>
314
- <?php else: ?>
315
- <span class="w3tc-test-ok">Off</span>
316
- <?php endif; ?>
317
- <br />
318
-
319
- <?php if (w3_is_multisite()): ?>
320
- VHOST mode:
321
- <?php if (w3_is_vhost()): ?>
322
- <span class="w3tc-test-ok">On</span>
323
- <?php else: ?>
324
- <span class="w3tc-test-ok">Off</span>
325
- <?php endif; ?>
326
- <?php endif; ?>
327
- </div>
328
-
329
- <fieldset>
330
- <legend>Legend</legend>
331
-
332
- <p>
333
- <span class="w3tc-test-ok">Green</span> - Good<br />
334
- <span class="w3tc-test-warn">Orange</span> - OK<br />
335
- <span class="w3tc-test-error">Red</span> - Bad<br />
336
- </p>
337
- </fieldset>
338
-
339
- <p>
340
- <input class="button-primary" type="button" value="Close" />
341
- </p>
342
  </div>
 
 
 
 
1
  <h3>Compatibility Test</h3>
2
 
3
+ <fieldset>
4
+ <legend>Legend</legend>
5
+
6
+ <p>
7
+ <code>Installed</code>: Functionality will work properly<br />
8
+ <code>Not detected</code>: May be installed, but cannot be automatically confirmed<br />
9
+ <code>Ok</code>: Current value is acceptable.<br />
10
+ <code>Yes/No</code>: The value was successful detected.
11
+ </p>
12
+ </fieldset>
13
+
14
+ <div id="w3tc-self-test">
15
  <h4>Server Modules &amp; Resources:</h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ <ul>
18
+ <li>
19
+ PHP Version:
20
+ <?php if (PHP_VERSION >= 5): ?>
21
+ <code><?php echo PHP_VERSION; ?></code>
22
+ <?php else: ?>
23
+ <code><?php echo PHP_VERSION; ?></code>;
24
+ <?php endif; ?>
25
+ <span class="w3tc-self-test-hint">(PHP5 required for Minify, Rackspace CloudFiles, Microsoft Azure support)</span>
26
+ </li>
27
+
28
+ <li>
29
+ Web Server:
30
+ <?php if (stristr($_SERVER['SERVER_SOFTWARE'], 'apache') !== false): ?>
31
+ <code>Apache</code>
32
+ <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false): ?>
33
+ <code>Lite Speed</code>
34
+ <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false): ?>
35
+ <code>nginx</code>
36
+ <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false): ?>
37
+ <code>lighttpd</code>
38
+ <?php elseif (stristr($_SERVER['SERVER_SOFTWARE'], 'iis') !== false): ?>
39
+ <code>Microsoft IIS</code>
40
+ <?php else: ?>
41
+ <code>Not detected</code>
42
+ <?php endif; ?>
43
+ </li>
44
+
45
+ <li>
46
+ FTP functions:
47
+ <?php if (function_exists('ftp_connect')): ?>
48
+ <code>Installed</code>
49
+ <?php else: ?>
50
+ <code>Not installed</code>
51
+ <?php endif; ?>
52
+ <span class="w3tc-self-test-hint">(required for Self-hosted (FTP) CDN support)</span>
53
+ </li>
54
+
55
+ <li>
56
+ Multibyte String support:
57
+ <?php if (function_exists('mb_substr')): ?>
58
+ <code>Installed</code>
59
+ <?php else: ?>
60
+ <code>Not installed</code>
61
+ <?php endif; ?>
62
+ <span class="w3tc-self-test-hint">(required for Rackspace Cloud Files support)</span>
63
+ </li>
64
+
65
+ <li>
66
+ cURL extension:
67
+ <?php if (function_exists('curl_init')): ?>
68
+ <code>Installed</code>
69
+ <?php else: ?>
70
+ <code>Not installed</code>
71
+ <?php endif; ?>
72
+ <span class="w3tc-self-test-hint">(required for Amazon S3, Amazon CloudFront, Rackspace CloudFiles support)</span>
73
+ </li>
74
+
75
+ <li>
76
+ zlib extension:
77
+ <?php if (function_exists('gzencode')): ?>
78
+ <code>Installed</code>
79
+ <?php else: ?>
80
+ <code>Not installed</code>
81
+ <?php endif; ?>
82
+ <span class="w3tc-self-test-hint">(required for compression support)</span>
83
+ </li>
84
+
85
+ <li>
86
+ Opcode cache:
87
+ <?php if (function_exists('apc_store')): ?>
88
+ <code>Installed (APC)</code>
89
+ <?php elseif (function_exists('eaccelerator_put')): ?>
90
+ <code>Installed (eAccelerator)</code>
91
+ <?php elseif (function_exists('xcache_set')): ?>
92
+ <code>Installed (XCache)</code>
93
+ <?php elseif (PHP_VERSION >= 6): ?>
94
+ <code>PHP6</code>
95
+ <?php else: ?>
96
+ <code>Not installed</code>
97
+ <?php endif; ?>
98
+ </li>
99
+
100
+ <li>
101
+ Memcache extension:
102
+ <?php if (class_exists('Memcache')): ?>
103
+ <code>Installed</code>
104
+ <?php else: ?>
105
+ <code>Not installed</code>
106
+ <?php endif; ?>
107
+ </li>
108
+
109
+ <li>
110
+ HTML Tidy extension:
111
+ <?php if (class_exists('tidy')): ?>
112
+ <code>Installed</code>
113
+ <?php else: ?>
114
+ <code>Not installed</code>
115
+ <?php endif; ?>
116
+ <span class="w3tc-self-test-hint">(required for HTML Tidy minifier suppport)</span>
117
+ </li>
118
+
119
+ <li>
120
+ Mime type detection:
121
+ <?php if (function_exists('finfo_open')): ?>
122
+ <code>Installed (Fileinfo)</code>
123
+ <?php elseif (function_exists('mime_content_type')): ?>
124
+ <code>Installed (mime_content_type)</code>
125
+ <?php else: ?>
126
+ <code>Not installed</code>
127
+ <?php endif; ?>
128
+ <span class="w3tc-self-test-hint">(required for CDN support)</span>
129
+ </li>
130
+
131
+ <li>
132
+ Hash function:
133
+ <?php if (function_exists('hash')): ?>
134
+ <code>Installed (hash)</code>
135
+ <?php elseif (function_exists('mhash')): ?>
136
+ <code>Installed (mhash)</code>
137
+ <?php else: ?>
138
+ <code>Not installed</code>
139
+ <?php endif; ?>
140
+ <span class="w3tc-self-test-hint">(required for NetDNA purge support)</span>
141
+ </li>
142
+
143
+ <li>
144
+ Safe mode:
145
+ <?php if (w3_to_boolean(ini_get('safe_mode'))): ?>
146
+ <code>On</code>
147
+ <?php else: ?>
148
+ <code>Off</code>
149
+ <?php endif; ?>
150
+ </li>
151
+
152
+ <li>
153
+ Open basedir:
154
+ <?php $open_basedir = ini_get('open_basedir'); if ($open_basedir): ?>
155
+ <code>On: <?php echo htmlspecialchars($open_basedir); ?></code>
156
+ <?php else: ?>
157
+ <code>Off</code>
158
+ <?php endif; ?>
159
+ </li>
160
+
161
+ <li>
162
+ zlib output compression:
163
+ <?php if (w3_to_boolean(ini_get('zlib.output_compression'))): ?>
164
+ <code>On</code>
165
+ <?php else: ?>
166
+ <code>Off</code>
167
+ <?php endif; ?>
168
+ </li>
169
 
170
+ <?php
171
+ if (w3_is_apache()):
172
+ $apache_modules = (function_exists('apache_get_modules') ? apache_get_modules() : false);
173
+
174
+ $modules = array(
175
+ 'mod_deflate',
176
+ 'mod_env',
177
+ 'mod_expires',
178
+ 'mod_headers',
179
+ 'mod_mime',
180
+ 'mod_rewrite',
181
+ 'mod_setenvif'
182
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  ?>
184
+ <?php foreach ($modules as $module): ?>
185
+ <li>
186
+ <?php echo $module; ?>:
187
+ <?php if ($apache_modules): ?>
188
+ <?php if (in_array($module, $apache_modules)): ?>
189
+ <code>Installed</code>
190
+ <?php else: ?>
191
+ <code>Not installed</code>
192
+ <?php endif; ?>
193
+ <?php else: ?>
194
+ <code>Not detected</code>
195
+ <?php endif; ?>
196
+ <span class="w3tc-self-test-hint">(required for Page Cache (enhanced mode) and Browser Cache)</span>
197
+ </li>
198
+ <?php endforeach; ?>
 
 
 
 
 
 
199
  <?php endif; ?>
200
+ </ul>
201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  <h4>WordPress Resources</h4>
203
+
204
+ <ul>
205
+ <?php
206
+ $paths = array_unique(array(
207
+ w3_get_pgcache_rules_core_path(),
208
+ w3_get_browsercache_rules_cache_path(),
209
+ w3_get_browsercache_rules_no404wp_path()
210
+ ));
211
+ ?>
212
+ <?php foreach ($paths as $path): ?>
213
+ <li>
214
+ <?php echo htmlspecialchars($path); ?>:
215
+ <?php if (file_exists($path)): ?>
216
+ <?php if (w3_is_writable($path)): ?>
217
+ <code>OK</code>
218
+ <?php else: ?>
219
+ <code>Not write-able</code>
220
+ <?php endif; ?>
221
+ <?php else: ?>
222
+ <?php if (w3_is_writable_dir(dirname($path))): ?>
223
+ <code>Write-able</code>
224
+ <?php else: ?>
225
+ <code>Not write-able</code>
226
+ <?php endif; ?>
227
+ <?php endif; ?>
228
+ </li>
229
+ <?php endforeach; ?>
230
+
231
+ <li>
232
+ <?php echo w3_path(WP_CONTENT_DIR); ?>:
233
+ <?php if (w3_is_writable_dir(WP_CONTENT_DIR)): ?>
234
+ <code>OK</code>
235
+ <?php else: ?>
236
+ <code>Not write-able</code>
237
+ <?php endif; ?>
238
+ </li>
239
+
240
+ <li>
241
+ <?php $uploads_dir = @wp_upload_dir(); ?>
242
+ <?php echo htmlspecialchars($uploads_dir['path']); ?>:
243
+ <?if (!empty($uploads_dir['error'])): ?>
244
+ <code>Error: <?php echo htmlspecialchars($uploads_dir['error']); ?></code>
245
+ <?php elseif (!w3_is_writable_dir($uploads_dir['path'])): ?>
246
+ <code>Not write-able</code>
247
+ <?php else: ?>
248
+ <code>OK</code>
249
+ <?php endif; ?>
250
+ </li>
251
+
252
+ <li>
253
+ Fancy permalinks:
254
+ <?php $permalink_structure = get_option('permalink_structure'); if ($permalink_structure): ?>
255
+ <code><?php echo htmlspecialchars($permalink_structure); ?></code>
256
+ <?php else: ?>
257
+ <code>Disabled</code>
258
+ <?php endif; ?>
259
+ </li>
260
+
261
+ <li>
262
+ WP_CACHE define:
263
+ <?php if (defined('WP_CACHE')): ?>
264
+ <code>Defined (<?php echo (WP_CACHE ? 'true' : 'false'); ?>)</code>
265
+ <?php else: ?>
266
+ <code>Not defined</code>
267
+ <?php endif; ?>
268
+ </li>
269
+
270
+ <li>
271
+ Network mode:
272
+ <?php if (w3_is_network()): ?>
273
+ <code>Yes (<?php echo (w3_is_subdomain_install() ? 'subdomain' : 'subdir'); ?>)</code>
274
+ <?php else: ?>
275
+ <code>No</code>
276
+ <?php endif; ?>
277
+ </li>
278
+ </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  </div>
280
+
281
+ <p>
282
+ <input class="button-primary" type="button" value="Close" />
283
+ </p>
inc/lightbox/support_us.phtml CHANGED
@@ -9,13 +9,15 @@
9
  <select name="support" class="select-support-type">
10
  <option value="">select one</option>
11
  <?php foreach ($supports as $support_id => $support_name): ?>
12
- <option value="<?php echo $support_id; ?>"><?php echo htmlspecialchars($support_name); ?></option>
13
  <?php endforeach; ?>
14
  </select>
15
- </label>, tell your friends with a <input type="button" class="button button-tweet" value="tweet" /> and give us a great <input type="button" class="button button-rating" value="rating" />.
 
 
16
  </p>
17
 
18
- <div style="text-align:center;">
19
  <h3>THANK YOU!</h3>
20
  <p>
21
  <input type="submit" class="button-primary" value="Save and close"> or
9
  <select name="support" class="select-support-type">
10
  <option value="">select one</option>
11
  <?php foreach ($supports as $support_id => $support_name): ?>
12
+ <option value="<?php echo $support_id; ?>"<?php echo selected($this->_config->get_string('common.support'), $support_id); ?>><?php echo htmlspecialchars($support_name); ?></option>
13
  <?php endforeach; ?>
14
  </select>
15
+ </label>, tell your friends with a <input type="button" class="button button-tweet" value="tweet" />
16
+ (<input type="hidden" name="tweeted" value="0" /><label><input type="checkbox" name="tweeted" value="1"<?php checked($this->_config->get_boolean('common.tweeted', true)); ?> /> I've tweeted</label>)
17
+ and give us a great <input type="button" class="button button-rating" value="rating" />.
18
  </p>
19
 
20
+ <div style="text-align: center;">
21
  <h3>THANK YOU!</h3>
22
  <p>
23
  <input type="submit" class="button-primary" value="Save and close"> or
inc/lightbox/tweet.phtml DELETED
@@ -1,26 +0,0 @@
1
- <h3>Tweet</h3>
2
-
3
- <p>Enter your username (email), password and click "Tweet!" to support us!</p>
4
-
5
- <p>This is the message that will be tweeted:</p>
6
-
7
- <blockquote>YES! I optimized my #wordpress site's performance using the W3 Total Cache #plugin by @<a href="http://twitter.com/w3edge" target="_blank">w3edge</a>. Check it out! <a href="http://j.mp/A69xX" target="_blank">http://j.mp/A69xX</a></blockquote>
8
-
9
- <form action="">
10
- <table class="form-table">
11
- <tr>
12
- <th><label for="tweet_username">Username:</label></th>
13
- <td><input id="tweet_username" type="text" size="30" /></td>
14
- </tr>
15
- <tr>
16
- <th><label for="tweet_password">Password:</label></th>
17
- <td><input id="tweet_password" type="password" size="30" /></td>
18
- </tr>
19
- </table>
20
-
21
- <p class="submit">
22
- <input type="submit" class="button-primary" value="Tweet!" />
23
- </p>
24
- </form>
25
-
26
- <p><em>Your password is not saved. Your tweet is submitted directly to twitter.com via their <acronym title="Application Programming Interface">API</acronym>.</em></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/mime/all.php CHANGED
@@ -4,621 +4,621 @@
4
  * All possible mime types
5
  */
6
  return array(
7
- '3dml' => 'text/vnd.in3d.3dml',
8
- '3g2' => 'video/3gpp2',
9
- '3gp' => 'video/3gpp',
10
- 'aab|x32|u32|vox' => 'application/x-authorware-bin',
11
- 'aac' => 'audio/x-aac',
12
- 'aam' => 'application/x-authorware-map',
13
- 'aas' => 'application/x-authorware-seg',
14
- 'abw' => 'application/x-abiword',
15
- 'acc' => 'application/vnd.americandynamics.acc',
16
- 'ace' => 'application/x-ace-compressed',
17
- 'acu' => 'application/vnd.acucobol',
18
- 'adp' => 'audio/adpcm',
19
- 'aep' => 'application/vnd.audiograph',
20
- 'afp|listafp|list3820' => 'application/vnd.ibm.modcap',
21
- 'aif|aiff|aifc' => 'audio/x-aiff',
22
- 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
23
- 'ai|eps|ps' => 'application/postscript',
24
- 'ami' => 'application/vnd.amiga.ami',
25
- 'apk' => 'application/vnd.android.package-archive',
26
- 'application' => 'application/x-ms-application',
27
- 'apr' => 'application/vnd.lotus-approach',
28
- 'asc|sig' => 'application/pgp-signature',
29
- 'asf|asx' => 'video/x-ms-asf',
30
- 'aso' => 'application/vnd.accpac.simply.aso',
31
- 'atc|acutc' => 'application/vnd.acucorp',
32
- 'atom' => 'application/atom+xml',
33
- 'atomcat' => 'application/atomcat+xml',
34
- 'atomsvc' => 'application/atomsvc+xml',
35
- 'atx' => 'application/vnd.antix.game-component',
36
- 'au|snd' => 'audio/basic',
37
- 'avi' => 'video/x-msvideo',
38
- 'aw' => 'application/applixware',
39
- 'azf' => 'application/vnd.airzip.filesecure.azf',
40
- 'azs' => 'application/vnd.airzip.filesecure.azs',
41
- 'azw' => 'application/vnd.amazon.ebook',
42
- 'bcpio' => 'application/x-bcpio',
43
- 'bdf' => 'application/x-font-bdf',
44
- 'bdm' => 'application/vnd.syncml.dm+wbxml',
45
- 'bh2' => 'application/vnd.fujitsu.oasysprs',
46
- 'bin|dms|lha|lrf|lzh|so|iso|dmg|dist|distz|pkg|bpk|dump|elc|deploy' => 'application/octet-stream',
47
- 'bmi' => 'application/vnd.bmi',
48
- 'bmp' => 'image/bmp',
49
- 'box' => 'application/vnd.previewsystems.box',
50
- 'btif' => 'image/prs.btif',
51
- 'bz' => 'application/x-bzip',
52
- 'bz2|boz' => 'application/x-bzip2',
53
- 'c4g|c4d|c4f|c4p|c4u' => 'application/vnd.clonk.c4group',
54
- 'cab' => 'application/vnd.ms-cab-compressed',
55
- 'car' => 'application/vnd.curl.car',
56
- 'cat' => 'application/vnd.ms-pki.seccat',
57
- 'ccxml' => 'application/ccxml+xml',
58
- 'cdbcmsg' => 'application/vnd.contact.cmsg',
59
- 'cdkey' => 'application/vnd.mediastation.cdkey',
60
- 'cdx' => 'chemical/x-cdx',
61
- 'cdxml' => 'application/vnd.chemdraw+xml',
62
- 'cdy' => 'application/vnd.cinderella',
63
- 'cer' => 'application/pkix-cert',
64
- 'cgm' => 'image/cgm',
65
- 'chat' => 'application/x-chat',
66
- 'chm' => 'application/vnd.ms-htmlhelp',
67
- 'chrt' => 'application/vnd.kde.kchart',
68
- 'cif' => 'chemical/x-cif',
69
- 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
70
- 'cil' => 'application/vnd.ms-artgalry',
71
- 'cla' => 'application/vnd.claymore',
72
- 'class' => 'application/java-vm',
73
- 'clkk' => 'application/vnd.crick.clicker.keyboard',
74
- 'clkp' => 'application/vnd.crick.clicker.palette',
75
- 'clkt' => 'application/vnd.crick.clicker.template',
76
- 'clkw' => 'application/vnd.crick.clicker.wordbank',
77
- 'clkx' => 'application/vnd.crick.clicker',
78
- 'clp' => 'application/x-msclip',
79
- 'cmc' => 'application/vnd.cosmocaller',
80
- 'cmdf' => 'chemical/x-cmdf',
81
- 'cml' => 'chemical/x-cml',
82
- 'cmp' => 'application/vnd.yellowriver-custom-menu',
83
- 'cmx' => 'image/x-cmx',
84
- 'cod' => 'application/vnd.rim.cod',
85
- 'cpio' => 'application/x-cpio',
86
- 'cpt' => 'application/mac-compactpro',
87
- 'crd' => 'application/x-mscardfile',
88
- 'crl' => 'application/pkix-crl',
89
- 'csh' => 'application/x-csh',
90
- 'csml' => 'chemical/x-csml',
91
- 'csp' => 'application/vnd.commonspace',
92
- 'css' => 'text/css',
93
- 'csv' => 'text/csv',
94
- 'cu' => 'application/cu-seeme',
95
- 'curl' => 'text/vnd.curl',
96
- 'cww' => 'application/prs.cww',
97
- 'c|cc|cxx|cpp|h|hh|dic' => 'text/x-c',
98
- 'daf' => 'application/vnd.mobius.daf',
99
- 'davmount' => 'application/davmount+xml',
100
- 'dcurl' => 'text/vnd.curl.dcurl',
101
- 'dd2' => 'application/vnd.oma.dd2+xml',
102
- 'ddd' => 'application/vnd.fujixerox.ddd',
103
- 'deb|udeb' => 'application/x-debian-package',
104
- 'der|crt' => 'application/x-x509-ca-cert',
105
- 'df' => 'application/x-deflate',
106
- 'dfac' => 'application/vnd.dreamfactory',
107
- 'dir|dcr|dxr|cst|cct|cxt|w3d|fgd|swa' => 'application/x-director',
108
- 'dis' => 'application/vnd.mobius.dis',
109
- 'djvu|djv' => 'image/vnd.djvu',
110
- 'dna' => 'application/vnd.dna',
111
- 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
112
- 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
113
- 'doc|dot' => 'application/msword',
114
- 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
115
- 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
116
- 'dp' => 'application/vnd.osgi.dp',
117
- 'dpg' => 'application/vnd.dpgraph',
118
- 'dsc' => 'text/prs.lines.tag',
119
- 'dtb' => 'application/x-dtbook+xml',
120
- 'dtd' => 'application/xml-dtd',
121
- 'dts' => 'audio/vnd.dts',
122
- 'dtshd' => 'audio/vnd.dts.hd',
123
- 'dvi' => 'application/x-dvi',
124
- 'dwf' => 'model/vnd.dwf',
125
- 'dwg' => 'image/vnd.dwg',
126
- 'dxf' => 'image/vnd.dxf',
127
- 'dxp' => 'application/vnd.spotfire.dxp',
128
- 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
129
- 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
130
- 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
131
- 'ecma' => 'application/ecmascript',
132
- 'edm' => 'application/vnd.novadigm.edm',
133
- 'edx' => 'application/vnd.novadigm.edx',
134
- 'efif' => 'application/vnd.picsel',
135
- 'ei6' => 'application/vnd.pg.osasli',
136
- 'eml|all' => 'message/rfc822',
137
- 'emma' => 'application/emma+xml',
138
- 'eol' => 'audio/vnd.digital-winds',
139
- 'eot' => 'application/vnd.ms-fontobject',
140
- 'epub' => 'application/epub+zip',
141
- 'es3|et3' => 'application/vnd.eszigno3+xml',
142
- 'esf' => 'application/vnd.epson.esf',
143
- 'etx' => 'text/x-setext',
144
- 'exe|dll|com|bat|msi' => 'application/x-msdownload',
145
- 'ext' => 'application/vnd.novadigm.ext',
146
- 'ez' => 'application/andrew-inset',
147
- 'ez2' => 'application/vnd.ezpix-album',
148
- 'ez3' => 'application/vnd.ezpix-package',
149
- 'f4v' => 'video/x-f4v',
150
- 'fbs' => 'image/vnd.fastbidsheet',
151
- 'fdf' => 'application/vnd.fdf',
152
- 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
153
- 'fg5' => 'application/vnd.fujitsu.oasysgp',
154
- 'fh|fhc|fh4|fh5|fh7' => 'image/x-freehand',
155
- 'fig' => 'application/x-xfig',
156
- 'fli' => 'video/x-fli',
157
- 'flo' => 'application/vnd.micrografx.flo',
158
- 'flv' => 'video/x-flv',
159
- 'flw' => 'application/vnd.kde.kivio',
160
- 'flx' => 'text/vnd.fmi.flexstor',
161
- 'fly' => 'text/vnd.fly',
162
- 'fm|frame|maker|book' => 'application/vnd.framemaker',
163
- 'fnc' => 'application/vnd.frogans.fnc',
164
- 'fpx' => 'image/vnd.fpx',
165
- 'fsc' => 'application/vnd.fsc.weblaunch',
166
- 'fst' => 'image/vnd.fst',
167
- 'ftc' => 'application/vnd.fluxtime.clip',
168
- 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
169
- 'fvt' => 'video/vnd.fvt',
170
- 'fzs' => 'application/vnd.fuzzysheet',
171
- 'f|for|f77|f90' => 'text/x-fortran',
172
- 'g3' => 'image/g3fax',
173
- 'gac' => 'application/vnd.groove-account',
174
- 'gdl' => 'model/vnd.gdl',
175
- 'geo' => 'application/vnd.dynageo',
176
- 'gex|gre' => 'application/vnd.geometry-explorer',
177
- 'ggb' => 'application/vnd.geogebra.file',
178
- 'ggt' => 'application/vnd.geogebra.tool',
179
- 'ghf' => 'application/vnd.groove-help',
180
- 'gif' => 'image/gif',
181
- 'gim' => 'application/vnd.groove-identity-message',
182
- 'gmx' => 'application/vnd.gmx',
183
- 'gnumeric' => 'application/x-gnumeric',
184
- 'gph' => 'application/vnd.flographit',
185
- 'gqf|gqs' => 'application/vnd.grafeq',
186
- 'gram' => 'application/srgs',
187
- 'grv' => 'application/vnd.groove-injector',
188
- 'grxml' => 'application/srgs+xml',
189
- 'gsf' => 'application/x-font-ghostscript',
190
- 'gtar' => 'application/x-gtar',
191
- 'gtm' => 'application/vnd.groove-tool-message',
192
- 'gtw' => 'model/vnd.gtw',
193
- 'gv' => 'text/vnd.graphviz',
194
- 'gz' => 'application/x-gzip',
195
- 'h261' => 'video/h261',
196
- 'h263' => 'video/h263',
197
- 'h264' => 'video/h264',
198
- 'hbci' => 'application/vnd.hbci',
199
- 'hdf' => 'application/x-hdf',
200
- 'hlp' => 'application/winhlp',
201
- 'hpgl' => 'application/vnd.hp-hpgl',
202
- 'hpid' => 'application/vnd.hp-hpid',
203
- 'hps' => 'application/vnd.hp-hps',
204
- 'hqx' => 'application/mac-binhex40',
205
- 'htke' => 'application/vnd.kenameaapp',
206
- 'html|htm' => 'text/html',
207
- 'hvd' => 'application/vnd.yamaha.hv-dic',
208
- 'hvp' => 'application/vnd.yamaha.hv-voice',
209
- 'hvs' => 'application/vnd.yamaha.hv-script',
210
- 'icc|icm' => 'application/vnd.iccprofile',
211
- 'ice' => 'x-conference/x-cooltalk',
212
- 'ico' => 'image/x-icon',
213
- 'ics|ifb' => 'text/calendar',
214
- 'ief' => 'image/ief',
215
- 'ifm' => 'application/vnd.shana.informed.formdata',
216
- 'igl' => 'application/vnd.igloader',
217
- 'igs|iges' => 'model/iges',
218
- 'igx' => 'application/vnd.micrografx.igx',
219
- 'iif' => 'application/vnd.shana.informed.interchange',
220
- 'imp' => 'application/vnd.accpac.simply.imp',
221
- 'ims' => 'application/vnd.ms-ims',
222
- 'ipk' => 'application/vnd.shana.informed.package',
223
- 'irm' => 'application/vnd.ibm.rights-management',
224
- 'irp' => 'application/vnd.irepository.package+xml',
225
- 'itp' => 'application/vnd.shana.informed.formtemplate',
226
- 'ivp' => 'application/vnd.immervision-ivp',
227
- 'ivu' => 'application/vnd.immervision-ivu',
228
- 'jad' => 'text/vnd.sun.j2me.app-descriptor',
229
- 'jam' => 'application/vnd.jam',
230
- 'jar' => 'application/java-archive',
231
- 'java' => 'text/x-java-source',
232
- 'jisp' => 'application/vnd.jisp',
233
- 'jlt' => 'application/vnd.hp-jlyt',
234
- 'jnlp' => 'application/x-java-jnlp-file',
235
- 'joda' => 'application/vnd.joost.joda-archive',
236
- 'jpeg|jpg|jpe' => 'image/jpeg',
237
- 'jpgv' => 'video/jpeg',
238
- 'jpm|jpgm' => 'video/jpm',
239
- 'js' => 'application/x-javascript',
240
- 'json' => 'application/json',
241
- 'karbon' => 'application/vnd.kde.karbon',
242
- 'kfo' => 'application/vnd.kde.kformula',
243
- 'kia' => 'application/vnd.kidspiration',
244
- 'kml' => 'application/vnd.google-earth.kml+xml',
245
- 'kmz' => 'application/vnd.google-earth.kmz',
246
- 'kne|knp' => 'application/vnd.kinar',
247
- 'kon' => 'application/vnd.kde.kontour',
248
- 'kpr|kpt' => 'application/vnd.kde.kpresenter',
249
- 'ksp' => 'application/vnd.kde.kspread',
250
- 'ktz|ktr' => 'application/vnd.kahootz',
251
- 'kwd|kwt' => 'application/vnd.kde.kword',
252
- 'latex' => 'application/x-latex',
253
- 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
254
- 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
255
- 'les' => 'application/vnd.hhe.lesson-player',
256
- 'link66' => 'application/vnd.route66.link66+xml',
257
- 'lostxml' => 'application/lost+xml',
258
- 'lrm' => 'application/vnd.ms-lrm',
259
- 'ltf' => 'application/vnd.frogans.ltf',
260
- 'lvp' => 'audio/vnd.lucent.voice',
261
- 'lwp' => 'application/vnd.lotus-wordpro',
262
- 'm3u' => 'audio/x-mpegurl',
263
- 'm4v' => 'video/x-m4v',
264
- 'mag' => 'application/vnd.ecowin.chart',
265
- 'mathml' => 'application/mathml+xml',
266
- 'ma|nb|mb' => 'application/mathematica',
267
- 'mbk' => 'application/vnd.mobius.mbk',
268
- 'mbox' => 'application/mbox',
269
- 'mc1' => 'application/vnd.medcalcdata',
270
- 'mcd' => 'application/vnd.mcd',
271
- 'mcurl' => 'text/vnd.curl.mcurl',
272
- 'mdb' => 'application/x-msaccess',
273
- 'mdi' => 'image/vnd.ms-modi',
274
- 'mfm' => 'application/vnd.mfmp',
275
- 'mgz' => 'application/vnd.proteus.magazine',
276
- 'mid|midi|kar|rmi' => 'audio/midi',
277
- 'mif' => 'application/vnd.mif',
278
- 'mj2|mjp2' => 'video/mj2',
279
- 'mlp' => 'application/vnd.dolby.mlp',
280
- 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
281
- 'mmf' => 'application/vnd.smaf',
282
- 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
283
- 'mny' => 'application/x-msmoney',
284
- 'movie' => 'video/x-sgi-movie',
285
- 'mp4a' => 'audio/mp4',
286
- 'mp4s' => 'application/mp4',
287
- 'mp4|mp4v|mpg4' => 'video/mp4',
288
- 'mpc' => 'application/vnd.mophun.certificate',
289
- 'mpeg|mpg|mpe|m1v|m2v' => 'video/mpeg',
290
- 'mpga|mp2|mp2a|mp3|m2a|m3a' => 'audio/mpeg',
291
- 'mpkg' => 'application/vnd.apple.installer+xml',
292
- 'mpm' => 'application/vnd.blueice.multipass',
293
- 'mpn' => 'application/vnd.mophun.application',
294
- 'mpp|mpt' => 'application/vnd.ms-project',
295
- 'mpy' => 'application/vnd.ibm.minipay',
296
- 'mqy' => 'application/vnd.mobius.mqy',
297
- 'mrc' => 'application/marc',
298
- 'mscml' => 'application/mediaservercontrol+xml',
299
- 'mseed' => 'application/vnd.fdsn.mseed',
300
- 'mseq' => 'application/vnd.mseq',
301
- 'msf' => 'application/vnd.epson.msf',
302
- 'msh|mesh|silo' => 'model/mesh',
303
- 'msl' => 'application/vnd.mobius.msl',
304
- 'msty' => 'application/vnd.muvee.style',
305
- 'mts' => 'model/vnd.mts',
306
- 'mus' => 'application/vnd.musician',
307
- 'musicxml' => 'application/vnd.recordare.musicxml+xml',
308
- 'mvb|m13|m14' => 'application/x-msmediaview',
309
- 'mwf' => 'application/vnd.mfer',
310
- 'mxf' => 'application/mxf',
311
- 'mxl' => 'application/vnd.recordare.musicxml',
312
- 'mxml|xhvml|xvml|xvm' => 'application/xv+xml',
313
- 'mxs' => 'application/vnd.triscape.mxs',
314
- 'mxu|m4u' => 'video/vnd.mpegurl',
315
- 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
316
- 'ncx' => 'application/x-dtbncx+xml',
317
- 'nc|cdf' => 'application/x-netcdf',
318
- 'ngdat' => 'application/vnd.nokia.n-gage.data',
319
- 'nlu' => 'application/vnd.neurolanguage.nlu',
320
- 'nml' => 'application/vnd.enliven',
321
- 'nnd' => 'application/vnd.noblenet-directory',
322
- 'nns' => 'application/vnd.noblenet-sealer',
323
- 'nnw' => 'application/vnd.noblenet-web',
324
- 'npx' => 'image/vnd.net-fpx',
325
- 'nsf' => 'application/vnd.lotus-notes',
326
- 'oa2' => 'application/vnd.fujitsu.oasys2',
327
- 'oa3' => 'application/vnd.fujitsu.oasys3',
328
- 'oas' => 'application/vnd.fujitsu.oasys',
329
- 'obd' => 'application/x-msbinder',
330
- 'oda' => 'application/oda',
331
- 'odb' => 'application/vnd.oasis.opendocument.database',
332
- 'odc' => 'application/vnd.oasis.opendocument.chart',
333
- 'odf' => 'application/vnd.oasis.opendocument.formula',
334
- 'odft' => 'application/vnd.oasis.opendocument.formula-template',
335
- 'odg' => 'application/vnd.oasis.opendocument.graphics',
336
- 'odi' => 'application/vnd.oasis.opendocument.image',
337
- 'odp' => 'application/vnd.oasis.opendocument.presentation',
338
- 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
339
- 'odt' => 'application/vnd.oasis.opendocument.text',
340
- 'oga|ogg|spx' => 'audio/ogg',
341
- 'ogv' => 'video/ogg',
342
- 'ogx' => 'application/ogg',
343
- 'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
344
- 'opf' => 'application/oebps-package+xml',
345
- 'org' => 'application/vnd.lotus-organizer',
346
- 'osf' => 'application/vnd.yamaha.openscoreformat',
347
- 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
348
- 'otc' => 'application/vnd.oasis.opendocument.chart-template',
349
- 'otf' => 'application/x-font-otf',
350
- 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
351
- 'oth' => 'application/vnd.oasis.opendocument.text-web',
352
- 'oti' => 'application/vnd.oasis.opendocument.image-template',
353
- 'otm' => 'application/vnd.oasis.opendocument.text-master',
354
- 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
355
- 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
356
- 'ott' => 'application/vnd.oasis.opendocument.text-template',
357
- 'oxt' => 'application/vnd.openofficeorg.extension',
358
- 'p10' => 'application/pkcs10',
359
- 'p12|pfx' => 'application/x-pkcs12',
360
- 'p7b|spc' => 'application/x-pkcs7-certificates',
361
- 'p7m|p7c' => 'application/pkcs7-all',
362
- 'p7r' => 'application/x-pkcs7-certreqresp',
363
- 'p7s' => 'application/pkcs7-signature',
364
- 'pbd' => 'application/vnd.powerbuilder6',
365
- 'pbm' => 'image/x-portable-bitmap',
366
- 'pcf' => 'application/x-font-pcf',
367
- 'pcl' => 'application/vnd.hp-pcl',
368
- 'pclxl' => 'application/vnd.hp-pclxl',
369
- 'pcurl' => 'application/vnd.curl.pcurl',
370
- 'pcx' => 'image/x-pcx',
371
- 'pdb|pqa|oprc' => 'application/vnd.palm',
372
- 'pdf' => 'application/pdf',
373
- 'pfa|pfb|pfm|afm' => 'application/x-font-type1',
374
- 'pfr' => 'application/font-tdpfr',
375
- 'pgm' => 'image/x-portable-graymap',
376
- 'pgn' => 'application/x-chess-pgn',
377
- 'pgp' => 'application/pgp-encrypted',
378
- 'pic|pct' => 'image/x-pict',
379
- 'pki' => 'application/pkixcmp',
380
- 'pkipath' => 'application/pkix-pkipath',
381
- 'plb' => 'application/vnd.3gpp.pic-bw-large',
382
- 'plc' => 'application/vnd.mobius.plc',
383
- 'plf' => 'application/vnd.pocketlearn',
384
- 'pls' => 'application/pls+xml',
385
- 'pml' => 'application/vnd.ctc-posml',
386
- 'png' => 'image/png',
387
- 'pnm' => 'image/x-portable-anymap',
388
- 'portpkg' => 'application/vnd.macports.portpkg',
389
- 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
390
- 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
391
- 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
392
- 'ppd' => 'application/vnd.cups-ppd',
393
- 'ppm' => 'image/x-portable-pixmap',
394
- 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
395
- 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
396
- 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
397
- 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
398
- 'ppt|pps|pot' => 'application/vnd.ms-powerpoint',
399
- 'prc|mobi' => 'application/x-mobipocket-ebook',
400
- 'pre' => 'application/vnd.lotus-freelance',
401
- 'prf' => 'application/pics-rules',
402
- 'psb' => 'application/vnd.3gpp.pic-bw-small',
403
- 'psd' => 'image/vnd.adobe.photoshop',
404
- 'psf' => 'application/x-font-linux-psf',
405
- 'ptid' => 'application/vnd.pvi.ptid1',
406
- 'pub' => 'application/x-mspublisher',
407
- 'pvb' => 'application/vnd.3gpp.pic-bw-var',
408
- 'pwn' => 'application/vnd.3m.post-it-notes',
409
- 'pya' => 'audio/vnd.ms-playready.media.pya',
410
- 'pyv' => 'video/vnd.ms-playready.media.pyv',
411
- 'p|pas' => 'text/x-pascal',
412
- 'qam' => 'application/vnd.epson.quickanime',
413
- 'qbo' => 'application/vnd.intu.qbo',
414
- 'qfx' => 'application/vnd.intu.qfx',
415
- 'qps' => 'application/vnd.publishare-delta-tree',
416
- 'qt|mov' => 'video/quicktime',
417
- 'qxd|qxt|qwd|qwt|qxl|qxb' => 'application/vnd.quark.quarkxpress',
418
- 'ram|ra' => 'audio/x-pn-realaudio',
419
- 'rar' => 'application/x-rar-compressed',
420
- 'ras' => 'image/x-cmu-raster',
421
- 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
422
- 'rdf' => 'application/rdf+xml',
423
- 'rdz' => 'application/vnd.data-vision.rdz',
424
- 'rep' => 'application/vnd.businessobjects',
425
- 'res' => 'application/x-dtbresource+xml',
426
- 'rgb' => 'image/x-rgb',
427
- 'rif' => 'application/reginfo+xml',
428
- 'rl' => 'application/resource-lists+xml',
429
- 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
430
- 'rld' => 'application/resource-lists-diff+xml',
431
- 'rm' => 'application/vnd.rn-realmedia',
432
- 'rmp' => 'audio/x-pn-realaudio-plugin',
433
- 'rms' => 'application/vnd.jcp.javame.midlet-rms',
434
- 'rnc' => 'application/relax-ng-compact-syntax',
435
- 'rpss' => 'application/vnd.nokia.radio-presets',
436
- 'rpst' => 'application/vnd.nokia.radio-preset',
437
- 'rq' => 'application/sparql-query',
438
- 'rs' => 'application/rls-services+xml',
439
- 'rsd' => 'application/rsd+xml',
440
- 'rss' => 'application/rss+xml',
441
- 'rtf' => 'application/rtf',
442
- 'rtx' => 'text/richtext',
443
- 'saf' => 'application/vnd.yamaha.smaf-audio',
444
- 'sbml' => 'application/sbml+xml',
445
- 'sc' => 'application/vnd.ibm.secure-container',
446
- 'scd' => 'application/x-msschedule',
447
- 'scm' => 'application/vnd.lotus-screencam',
448
- 'scq' => 'application/scvp-cv-request',
449
- 'scs' => 'application/scvp-cv-response',
450
- 'scurl' => 'text/vnd.curl.scurl',
451
- 'sda' => 'application/vnd.stardivision.draw',
452
- 'sdc' => 'application/vnd.stardivision.calc',
453
- 'sdd' => 'application/vnd.stardivision.impress',
454
- 'sdkm|sdkd' => 'application/vnd.solent.sdkm+xml',
455
- 'sdp' => 'application/sdp',
456
- 'sdw' => 'application/vnd.stardivision.writer',
457
- 'see' => 'application/vnd.seemail',
458
- 'seed|dataless' => 'application/vnd.fdsn.seed',
459
- 'sema' => 'application/vnd.sema',
460
- 'semd' => 'application/vnd.semd',
461
- 'semf' => 'application/vnd.semf',
462
- 'ser' => 'application/java-serialized-object',
463
- 'setpay' => 'application/set-payment-initiation',
464
- 'setreg' => 'application/set-registration-initiation',
465
- 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
466
- 'sfs' => 'application/vnd.spotfire.sfs',
467
- 'sgl' => 'application/vnd.stardivision.writer-global',
468
- 'sgml|sgm' => 'text/sgml',
469
- 'sh' => 'application/x-sh',
470
- 'shar' => 'application/x-shar',
471
- 'shf' => 'application/shf+xml',
472
- 'sis|sisx' => 'application/vnd.symbian.install',
473
- 'sit' => 'application/x-stuffit',
474
- 'sitx' => 'application/x-stuffitx',
475
- 'skp|skd|skt|skm' => 'application/vnd.koan',
476
- 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
477
- 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
478
- 'slt' => 'application/vnd.epson.salt',
479
- 'smf' => 'application/vnd.stardivision.math',
480
- 'smi|smil' => 'application/smil+xml',
481
- 'snf' => 'application/x-font-snf',
482
- 'spf' => 'application/vnd.yamaha.smaf-phrase',
483
- 'spl' => 'application/x-futuresplash',
484
- 'spot' => 'text/vnd.in3d.spot',
485
- 'spp' => 'application/scvp-vp-response',
486
- 'spq' => 'application/scvp-vp-request',
487
- 'src' => 'application/x-wais-source',
488
- 'srx' => 'application/sparql-results+xml',
489
- 'sse' => 'application/vnd.kodak-descriptor',
490
- 'ssf' => 'application/vnd.epson.ssf',
491
- 'ssml' => 'application/ssml+xml',
492
- 'stc' => 'application/vnd.sun.xml.calc.template',
493
- 'std' => 'application/vnd.sun.xml.draw.template',
494
- 'stf' => 'application/vnd.wt.stf',
495
- 'sti' => 'application/vnd.sun.xml.impress.template',
496
- 'stk' => 'application/hyperstudio',
497
- 'stl' => 'application/vnd.ms-pki.stl',
498
- 'str' => 'application/vnd.pg.format',
499
- 'stw' => 'application/vnd.sun.xml.writer.template',
500
- 'sus|susp' => 'application/vnd.sus-calendar',
501
- 'sv4cpio' => 'application/x-sv4cpio',
502
- 'sv4crc' => 'application/x-sv4crc',
503
- 'svd' => 'application/vnd.svd',
504
- 'svg|svgz' => 'image/svg+xml',
505
- 'swf' => 'application/x-shockwave-flash',
506
- 'swi' => 'application/vnd.arastra.swi',
507
- 'sxc' => 'application/vnd.sun.xml.calc',
508
- 'sxd' => 'application/vnd.sun.xml.draw',
509
- 'sxg' => 'application/vnd.sun.xml.writer.global',
510
- 'sxi' => 'application/vnd.sun.xml.impress',
511
- 'sxm' => 'application/vnd.sun.xml.math',
512
- 'sxw' => 'application/vnd.sun.xml.writer',
513
- 's|asm' => 'text/x-asm',
514
- 'tao' => 'application/vnd.tao.intent-module-archive',
515
- 'tar' => 'application/x-tar',
516
- 'tcap' => 'application/vnd.3gpp2.tcap',
517
- 'tcl' => 'application/x-tcl',
518
- 'teacher' => 'application/vnd.smart.teacher',
519
- 'tex' => 'application/x-tex',
520
- 'texinfo|texi' => 'application/x-texinfo',
521
- 'tfm' => 'application/x-tex-tfm',
522
- 'tiff|tif' => 'image/tiff',
523
- 'tmo' => 'application/vnd.tmobile-livetv',
524
- 'torrent' => 'application/x-bittorrent',
525
- 'tpl' => 'application/vnd.groove-tool-template',
526
- 'tpt' => 'application/vnd.trid.tpt',
527
- 'tra' => 'application/vnd.trueapp',
528
- 'trm' => 'application/x-msterminal',
529
- 'tsv' => 'text/tab-separated-values',
530
- 'ttf|ttc' => 'application/x-font-ttf',
531
- 'twd|twds' => 'application/vnd.simtech-mindmapper',
532
- 'txd' => 'application/vnd.genomatix.tuxedo',
533
- 'txf' => 'application/vnd.mobius.txf',
534
- 'txt|text|conf|def|list|log|in' => 'text/plain',
535
- 't|tr|roff|man|me|ms' => 'text/troff',
536
- 'ufd|ufdl' => 'application/vnd.ufdl',
537
- 'umj' => 'application/vnd.umajin',
538
- 'unityweb' => 'application/vnd.unity',
539
- 'uoml' => 'application/vnd.uoml+xml',
540
- 'uri|uris|urls' => 'text/uri-list',
541
- 'ustar' => 'application/x-ustar',
542
- 'utz' => 'application/vnd.uiq.theme',
543
- 'uu' => 'text/x-uuencode',
544
- 'vcd' => 'application/x-cdlink',
545
- 'vcf' => 'text/x-vcard',
546
- 'vcg' => 'application/vnd.groove-vcard',
547
- 'vcs' => 'text/x-vcalendar',
548
- 'vcx' => 'application/vnd.vcx',
549
- 'vis' => 'application/vnd.visionary',
550
- 'viv' => 'video/vnd.vivo',
551
- 'vor' => 'application/vnd.stardivision.writer',
552
- 'vsd|vst|vss|vsw' => 'application/vnd.visio',
553
- 'vsf' => 'application/vnd.vsf',
554
- 'vtu' => 'model/vnd.vtu',
555
- 'vxml' => 'application/voicexml+xml',
556
- 'wad' => 'application/x-doom',
557
- 'wav' => 'audio/x-wav',
558
- 'wax' => 'audio/x-ms-wax',
559
- 'wbmp' => 'image/vnd.wap.wbmp',
560
- 'wbs' => 'application/vnd.criticaltools.wbs+xml',
561
- 'wbxml' => 'application/vnd.wap.wbxml',
562
- 'wm' => 'video/x-ms-wm',
563
- 'wma' => 'audio/x-ms-wma',
564
- 'wmd' => 'application/x-ms-wmd',
565
- 'wmf' => 'application/x-msmetafile',
566
- 'wml' => 'text/vnd.wap.wml',
567
- 'wmlc' => 'application/vnd.wap.wmlc',
568
- 'wmls' => 'text/vnd.wap.wmlscript',
569
- 'wmlsc' => 'application/vnd.wap.wmlscriptc',
570
- 'wmv' => 'video/x-ms-wmv',
571
- 'wmx' => 'video/x-ms-wmx',
572
- 'wmz' => 'application/x-ms-wmz',
573
- 'wpd' => 'application/vnd.wordperfect',
574
- 'wpl' => 'application/vnd.ms-wpl',
575
- 'wps|wks|wcm|wdb' => 'application/vnd.ms-works',
576
- 'wqd' => 'application/vnd.wqd',
577
- 'wri' => 'application/x-mswrite',
578
- 'wrl|vrml' => 'model/vrml',
579
- 'wsdl' => 'application/wsdl+xml',
580
- 'wspolicy' => 'application/wspolicy+xml',
581
- 'wtb' => 'application/vnd.webturbo',
582
- 'wvx' => 'video/x-ms-wvx',
583
- 'x3d' => 'application/vnd.hzn-3d-crossword',
584
- 'xap' => 'application/x-silverlight-app',
585
- 'xar' => 'application/vnd.xara',
586
- 'xbap' => 'application/x-ms-xbap',
587
- 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
588
- 'xbm' => 'image/x-xbitmap',
589
- 'xdm' => 'application/vnd.syncml.dm+xml',
590
- 'xdp' => 'application/vnd.adobe.xdp+xml',
591
- 'xdw' => 'application/vnd.fujixerox.docuworks',
592
- 'xenc' => 'application/xenc+xml',
593
- 'xer' => 'application/patch-ops-error+xml',
594
- 'xfdf' => 'application/vnd.adobe.xfdf',
595
- 'xfdl' => 'application/vnd.xfdl',
596
- 'xhtml|xht' => 'application/xhtml+xml',
597
- 'xif' => 'image/vnd.xiff',
598
- 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
599
- 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
600
- 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
601
- 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
602
- 'xls|xlm|xla|xlc|xlt|xlw' => 'application/vnd.ms-excel',
603
- 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
604
- 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
605
- 'xml|xsl' => 'application/xml',
606
- 'xo' => 'application/vnd.olpc-sugar',
607
- 'xop' => 'application/xop+xml',
608
- 'xpi' => 'application/x-xpinstall',
609
- 'xpm' => 'image/x-xpixmap',
610
- 'xpr' => 'application/vnd.is-xpr',
611
- 'xps' => 'application/vnd.ms-xpsdocument',
612
- 'xpw|xpx' => 'application/vnd.intercon.formnet',
613
- 'xslt' => 'application/xslt+xml',
614
- 'xsm' => 'application/vnd.syncml+xml',
615
- 'xspf' => 'application/xspf+xml',
616
- 'xul' => 'application/vnd.mozilla.xul+xml',
617
- 'xwd' => 'image/x-xwindowdump',
618
- 'xyz' => 'chemical/x-xyz',
619
- 'zaz' => 'application/vnd.zzazz.deck+xml',
620
- 'zip' => 'application/zip',
621
- 'zir|zirz' => 'application/vnd.zul',
622
- 'zmm' => 'application/vnd.handheld-entertainment+xml',
623
  '123' => 'application/vnd.lotus-1-2-3'
624
  );
4
  * All possible mime types
5
  */
6
  return array(
7
+ '3dml' => 'text/vnd.in3d.3dml',
8
+ '3g2' => 'video/3gpp2',
9
+ '3gp' => 'video/3gpp',
10
+ 'aab|x32|u32|vox' => 'application/x-authorware-bin',
11
+ 'aac' => 'audio/x-aac',
12
+ 'aam' => 'application/x-authorware-map',
13
+ 'aas' => 'application/x-authorware-seg',
14
+ 'abw' => 'application/x-abiword',
15
+ 'acc' => 'application/vnd.americandynamics.acc',
16
+ 'ace' => 'application/x-ace-compressed',
17
+ 'acu' => 'application/vnd.acucobol',
18
+ 'adp' => 'audio/adpcm',
19
+ 'aep' => 'application/vnd.audiograph',
20
+ 'afp|listafp|list3820' => 'application/vnd.ibm.modcap',
21
+ 'aif|aiff|aifc' => 'audio/x-aiff',
22
+ 'air' => 'application/vnd.adobe.air-application-installer-package+zip',
23
+ 'ai|eps|ps' => 'application/postscript',
24
+ 'ami' => 'application/vnd.amiga.ami',
25
+ 'apk' => 'application/vnd.android.package-archive',
26
+ 'application' => 'application/x-ms-application',
27
+ 'apr' => 'application/vnd.lotus-approach',
28
+ 'asc|sig' => 'application/pgp-signature',
29
+ 'asf|asx' => 'video/x-ms-asf',
30
+ 'aso' => 'application/vnd.accpac.simply.aso',
31
+ 'atc|acutc' => 'application/vnd.acucorp',
32
+ 'atom' => 'application/atom+xml',
33
+ 'atomcat' => 'application/atomcat+xml',
34
+ 'atomsvc' => 'application/atomsvc+xml',
35
+ 'atx' => 'application/vnd.antix.game-component',
36
+ 'au|snd' => 'audio/basic',
37
+ 'avi' => 'video/x-msvideo',
38
+ 'aw' => 'application/applixware',
39
+ 'azf' => 'application/vnd.airzip.filesecure.azf',
40
+ 'azs' => 'application/vnd.airzip.filesecure.azs',
41
+ 'azw' => 'application/vnd.amazon.ebook',
42
+ 'bcpio' => 'application/x-bcpio',
43
+ 'bdf' => 'application/x-font-bdf',
44
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
45
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
46
+ 'bin|dms|lha|lrf|lzh|so|iso|dmg|dist|distz|pkg|bpk|dump|elc|deploy' => 'application/octet-stream',
47
+ 'bmi' => 'application/vnd.bmi',
48
+ 'bmp' => 'image/bmp',
49
+ 'box' => 'application/vnd.previewsystems.box',
50
+ 'btif' => 'image/prs.btif',
51
+ 'bz' => 'application/x-bzip',
52
+ 'bz2|boz' => 'application/x-bzip2',
53
+ 'c4g|c4d|c4f|c4p|c4u' => 'application/vnd.clonk.c4group',
54
+ 'cab' => 'application/vnd.ms-cab-compressed',
55
+ 'car' => 'application/vnd.curl.car',
56
+ 'cat' => 'application/vnd.ms-pki.seccat',
57
+ 'ccxml' => 'application/ccxml+xml',
58
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
59
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
60
+ 'cdx' => 'chemical/x-cdx',
61
+ 'cdxml' => 'application/vnd.chemdraw+xml',
62
+ 'cdy' => 'application/vnd.cinderella',
63
+ 'cer' => 'application/pkix-cert',
64
+ 'cgm' => 'image/cgm',
65
+ 'chat' => 'application/x-chat',
66
+ 'chm' => 'application/vnd.ms-htmlhelp',
67
+ 'chrt' => 'application/vnd.kde.kchart',
68
+ 'cif' => 'chemical/x-cif',
69
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
70
+ 'cil' => 'application/vnd.ms-artgalry',
71
+ 'cla' => 'application/vnd.claymore',
72
+ 'class' => 'application/java-vm',
73
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
74
+ 'clkp' => 'application/vnd.crick.clicker.palette',
75
+ 'clkt' => 'application/vnd.crick.clicker.template',
76
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
77
+ 'clkx' => 'application/vnd.crick.clicker',
78
+ 'clp' => 'application/x-msclip',
79
+ 'cmc' => 'application/vnd.cosmocaller',
80
+ 'cmdf' => 'chemical/x-cmdf',
81
+ 'cml' => 'chemical/x-cml',
82
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
83
+ 'cmx' => 'image/x-cmx',
84
+ 'cod' => 'application/vnd.rim.cod',
85
+ 'cpio' => 'application/x-cpio',
86
+ 'cpt' => 'application/mac-compactpro',
87
+ 'crd' => 'application/x-mscardfile',
88
+ 'crl' => 'application/pkix-crl',
89
+ 'csh' => 'application/x-csh',
90
+ 'csml' => 'chemical/x-csml',
91
+ 'csp' => 'application/vnd.commonspace',
92
+ 'css' => 'text/css',
93
+ 'csv' => 'text/csv',
94
+ 'cu' => 'application/cu-seeme',
95
+ 'curl' => 'text/vnd.curl',
96
+ 'cww' => 'application/prs.cww',
97
+ 'c|cc|cxx|cpp|h|hh|dic' => 'text/x-c',
98
+ 'daf' => 'application/vnd.mobius.daf',
99
+ 'davmount' => 'application/davmount+xml',
100
+ 'dcurl' => 'text/vnd.curl.dcurl',
101
+ 'dd2' => 'application/vnd.oma.dd2+xml',
102
+ 'ddd' => 'application/vnd.fujixerox.ddd',
103
+ 'deb|udeb' => 'application/x-debian-package',
104
+ 'der|crt' => 'application/x-x509-ca-cert',
105
+ 'df' => 'application/x-deflate',
106
+ 'dfac' => 'application/vnd.dreamfactory',
107
+ 'dir|dcr|dxr|cst|cct|cxt|w3d|fgd|swa' => 'application/x-director',
108
+ 'dis' => 'application/vnd.mobius.dis',
109
+ 'djvu|djv' => 'image/vnd.djvu',
110
+ 'dna' => 'application/vnd.dna',
111
+ 'docm' => 'application/vnd.ms-word.document.macroenabled.12',
112
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
113
+ 'doc|dot' => 'application/msword',
114
+ 'dotm' => 'application/vnd.ms-word.template.macroenabled.12',
115
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
116
+ 'dp' => 'application/vnd.osgi.dp',
117
+ 'dpg' => 'application/vnd.dpgraph',
118
+ 'dsc' => 'text/prs.lines.tag',
119
+ 'dtb' => 'application/x-dtbook+xml',
120
+ 'dtd' => 'application/xml-dtd',
121
+ 'dts' => 'audio/vnd.dts',
122
+ 'dtshd' => 'audio/vnd.dts.hd',
123
+ 'dvi' => 'application/x-dvi',
124
+ 'dwf' => 'model/vnd.dwf',
125
+ 'dwg' => 'image/vnd.dwg',
126
+ 'dxf' => 'image/vnd.dxf',
127
+ 'dxp' => 'application/vnd.spotfire.dxp',
128
+ 'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
129
+ 'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
130
+ 'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
131
+ 'ecma' => 'application/ecmascript',
132
+ 'edm' => 'application/vnd.novadigm.edm',
133
+ 'edx' => 'application/vnd.novadigm.edx',
134
+ 'efif' => 'application/vnd.picsel',
135
+ 'ei6' => 'application/vnd.pg.osasli',
136
+ 'eml|all' => 'message/rfc822',
137
+ 'emma' => 'application/emma+xml',
138
+ 'eol' => 'audio/vnd.digital-winds',
139
+ 'eot' => 'application/vnd.ms-fontobject',
140
+ 'epub' => 'application/epub+zip',
141
+ 'es3|et3' => 'application/vnd.eszigno3+xml',
142
+ 'esf' => 'application/vnd.epson.esf',
143
+ 'etx' => 'text/x-setext',
144
+ 'exe|dll|com|bat|msi' => 'application/x-msdownload',
145
+ 'ext' => 'application/vnd.novadigm.ext',
146
+ 'ez' => 'application/andrew-inset',
147
+ 'ez2' => 'application/vnd.ezpix-album',
148
+ 'ez3' => 'application/vnd.ezpix-package',
149
+ 'f4v' => 'video/x-f4v',
150
+ 'fbs' => 'image/vnd.fastbidsheet',
151
+ 'fdf' => 'application/vnd.fdf',
152
+ 'fe_launch' => 'application/vnd.denovo.fcselayout-link',
153
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
154
+ 'fh|fhc|fh4|fh5|fh7' => 'image/x-freehand',
155
+ 'fig' => 'application/x-xfig',
156
+ 'fli' => 'video/x-fli',
157
+ 'flo' => 'application/vnd.micrografx.flo',
158
+ 'flv' => 'video/x-flv',
159
+ 'flw' => 'application/vnd.kde.kivio',
160
+ 'flx' => 'text/vnd.fmi.flexstor',
161
+ 'fly' => 'text/vnd.fly',
162
+ 'fm|frame|maker|book' => 'application/vnd.framemaker',
163
+ 'fnc' => 'application/vnd.frogans.fnc',
164
+ 'fpx' => 'image/vnd.fpx',
165
+ 'fsc' => 'application/vnd.fsc.weblaunch',
166
+ 'fst' => 'image/vnd.fst',
167
+ 'ftc' => 'application/vnd.fluxtime.clip',
168
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
169
+ 'fvt' => 'video/vnd.fvt',
170
+ 'fzs' => 'application/vnd.fuzzysheet',
171
+ 'f|for|f77|f90' => 'text/x-fortran',
172
+ 'g3' => 'image/g3fax',
173
+ 'gac' => 'application/vnd.groove-account',
174
+ 'gdl' => 'model/vnd.gdl',
175
+ 'geo' => 'application/vnd.dynageo',
176
+ 'gex|gre' => 'application/vnd.geometry-explorer',
177
+ 'ggb' => 'application/vnd.geogebra.file',
178
+ 'ggt' => 'application/vnd.geogebra.tool',
179
+ 'ghf' => 'application/vnd.groove-help',
180
+ 'gif' => 'image/gif',
181
+ 'gim' => 'application/vnd.groove-identity-message',
182
+ 'gmx' => 'application/vnd.gmx',
183
+ 'gnumeric' => 'application/x-gnumeric',
184
+ 'gph' => 'application/vnd.flographit',
185
+ 'gqf|gqs' => 'application/vnd.grafeq',
186
+ 'gram' => 'application/srgs',
187
+ 'grv' => 'application/vnd.groove-injector',
188
+ 'grxml' => 'application/srgs+xml',
189
+ 'gsf' => 'application/x-font-ghostscript',
190
+ 'gtar' => 'application/x-gtar',
191
+ 'gtm' => 'application/vnd.groove-tool-message',
192
+ 'gtw' => 'model/vnd.gtw',
193
+ 'gv' => 'text/vnd.graphviz',
194
+ 'gz' => 'application/x-gzip',
195
+ 'h261' => 'video/h261',
196
+ 'h263' => 'video/h263',
197
+ 'h264' => 'video/h264',
198
+ 'hbci' => 'application/vnd.hbci',
199
+ 'hdf' => 'application/x-hdf',
200
+ 'hlp' => 'application/winhlp',
201
+ 'hpgl' => 'application/vnd.hp-hpgl',
202
+ 'hpid' => 'application/vnd.hp-hpid',
203
+ 'hps' => 'application/vnd.hp-hps',
204
+ 'hqx' => 'application/mac-binhex40',
205
+ 'htke' => 'application/vnd.kenameaapp',
206
+ 'html|htm' => 'text/html',
207
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
208
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
209
+ 'hvs' => 'application/vnd.yamaha.hv-script',
210
+ 'icc|icm' => 'application/vnd.iccprofile',
211
+ 'ice' => 'x-conference/x-cooltalk',
212
+ 'ico' => 'image/x-icon',
213
+ 'ics|ifb' => 'text/calendar',
214
+ 'ief' => 'image/ief',
215
+ 'ifm' => 'application/vnd.shana.informed.formdata',
216
+ 'igl' => 'application/vnd.igloader',
217
+ 'igs|iges' => 'model/iges',
218
+ 'igx' => 'application/vnd.micrografx.igx',
219
+ 'iif' => 'application/vnd.shana.informed.interchange',
220
+ 'imp' => 'application/vnd.accpac.simply.imp',
221
+ 'ims' => 'application/vnd.ms-ims',
222
+ 'ipk' => 'application/vnd.shana.informed.package',
223
+ 'irm' => 'application/vnd.ibm.rights-management',
224
+ 'irp' => 'application/vnd.irepository.package+xml',
225
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
226
+ 'ivp' => 'application/vnd.immervision-ivp',
227
+ 'ivu' => 'application/vnd.immervision-ivu',
228
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
229
+ 'jam' => 'application/vnd.jam',
230
+ 'jar' => 'application/java-archive',
231
+ 'java' => 'text/x-java-source',
232
+ 'jisp' => 'application/vnd.jisp',
233
+ 'jlt' => 'application/vnd.hp-jlyt',
234
+ 'jnlp' => 'application/x-java-jnlp-file',
235
+ 'joda' => 'application/vnd.joost.joda-archive',
236
+ 'jpeg|jpg|jpe' => 'image/jpeg',
237
+ 'jpgv' => 'video/jpeg',
238
+ 'jpm|jpgm' => 'video/jpm',
239
+ 'js' => 'application/x-javascript',
240
+ 'json' => 'application/json',
241
+ 'karbon' => 'application/vnd.kde.karbon',
242
+ 'kfo' => 'application/vnd.kde.kformula',
243
+ 'kia' => 'application/vnd.kidspiration',
244
+ 'kml' => 'application/vnd.google-earth.kml+xml',
245
+ 'kmz' => 'application/vnd.google-earth.kmz',
246
+ 'kne|knp' => 'application/vnd.kinar',
247
+ 'kon' => 'application/vnd.kde.kontour',
248
+ 'kpr|kpt' => 'application/vnd.kde.kpresenter',
249
+ 'ksp' => 'application/vnd.kde.kspread',
250
+ 'ktz|ktr' => 'application/vnd.kahootz',
251
+ 'kwd|kwt' => 'application/vnd.kde.kword',
252
+ 'latex' => 'application/x-latex',
253
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
254
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
255
+ 'les' => 'application/vnd.hhe.lesson-player',
256
+ 'link66' => 'application/vnd.route66.link66+xml',
257
+ 'lostxml' => 'application/lost+xml',
258
+ 'lrm' => 'application/vnd.ms-lrm',
259
+ 'ltf' => 'application/vnd.frogans.ltf',
260
+ 'lvp' => 'audio/vnd.lucent.voice',
261
+ 'lwp' => 'application/vnd.lotus-wordpro',
262
+ 'm3u' => 'audio/x-mpegurl',
263
+ 'm4v' => 'video/x-m4v',
264
+ 'mag' => 'application/vnd.ecowin.chart',
265
+ 'mathml' => 'application/mathml+xml',
266
+ 'ma|nb|mb' => 'application/mathematica',
267
+ 'mbk' => 'application/vnd.mobius.mbk',
268
+ 'mbox' => 'application/mbox',
269
+ 'mc1' => 'application/vnd.medcalcdata',
270
+ 'mcd' => 'application/vnd.mcd',
271
+ 'mcurl' => 'text/vnd.curl.mcurl',
272
+ 'mdb' => 'application/x-msaccess',
273
+ 'mdi' => 'image/vnd.ms-modi',
274
+ 'mfm' => 'application/vnd.mfmp',
275
+ 'mgz' => 'application/vnd.proteus.magazine',
276
+ 'mid|midi|kar|rmi' => 'audio/midi',
277
+ 'mif' => 'application/vnd.mif',
278
+ 'mj2|mjp2' => 'video/mj2',
279
+ 'mlp' => 'application/vnd.dolby.mlp',
280
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
281
+ 'mmf' => 'application/vnd.smaf',
282
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
283
+ 'mny' => 'application/x-msmoney',
284
+ 'movie' => 'video/x-sgi-movie',
285
+ 'mp4a' => 'audio/mp4',
286
+ 'mp4s' => 'application/mp4',
287
+ 'mp4|mp4v|mpg4' => 'video/mp4',
288
+ 'mpc' => 'application/vnd.mophun.certificate',
289
+ 'mpeg|mpg|mpe|m1v|m2v' => 'video/mpeg',
290
+ 'mpga|mp2|mp2a|mp3|m2a|m3a' => 'audio/mpeg',
291
+ 'mpkg' => 'application/vnd.apple.installer+xml',
292
+ 'mpm' => 'application/vnd.blueice.multipass',
293
+ 'mpn' => 'application/vnd.mophun.application',
294
+ 'mpp|mpt' => 'application/vnd.ms-project',
295
+ 'mpy' => 'application/vnd.ibm.minipay',
296
+ 'mqy' => 'application/vnd.mobius.mqy',
297
+ 'mrc' => 'application/marc',
298
+ 'mscml' => 'application/mediaservercontrol+xml',
299
+ 'mseed' => 'application/vnd.fdsn.mseed',
300
+ 'mseq' => 'application/vnd.mseq',
301
+ 'msf' => 'application/vnd.epson.msf',
302
+ 'msh|mesh|silo' => 'model/mesh',
303
+ 'msl' => 'application/vnd.mobius.msl',
304
+ 'msty' => 'application/vnd.muvee.style',
305
+ 'mts' => 'model/vnd.mts',
306
+ 'mus' => 'application/vnd.musician',
307
+ 'musicxml' => 'application/vnd.recordare.musicxml+xml',
308
+ 'mvb|m13|m14' => 'application/x-msmediaview',
309
+ 'mwf' => 'application/vnd.mfer',
310
+ 'mxf' => 'application/mxf',
311
+ 'mxl' => 'application/vnd.recordare.musicxml',
312
+ 'mxml|xhvml|xvml|xvm' => 'application/xv+xml',
313
+ 'mxs' => 'application/vnd.triscape.mxs',
314
+ 'mxu|m4u' => 'video/vnd.mpegurl',
315
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
316
+ 'ncx' => 'application/x-dtbncx+xml',
317
+ 'nc|cdf' => 'application/x-netcdf',
318
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
319
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
320
+ 'nml' => 'application/vnd.enliven',
321
+ 'nnd' => 'application/vnd.noblenet-directory',
322
+ 'nns' => 'application/vnd.noblenet-sealer',
323
+ 'nnw' => 'application/vnd.noblenet-web',
324
+ 'npx' => 'image/vnd.net-fpx',
325
+ 'nsf' => 'application/vnd.lotus-notes',
326
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
327
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
328
+ 'oas' => 'application/vnd.fujitsu.oasys',
329
+ 'obd' => 'application/x-msbinder',
330
+ 'oda' => 'application/oda',
331
+ 'odb' => 'application/vnd.oasis.opendocument.database',
332
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
333
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
334
+ 'odft' => 'application/vnd.oasis.opendocument.formula-template',
335
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
336
+ 'odi' => 'application/vnd.oasis.opendocument.image',
337
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
338
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
339
+ 'odt' => 'application/vnd.oasis.opendocument.text',
340
+ 'oga|ogg|spx' => 'audio/ogg',
341
+ 'ogv' => 'video/ogg',
342
+ 'ogx' => 'application/ogg',
343
+ 'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
344
+ 'opf' => 'application/oebps-package+xml',
345
+ 'org' => 'application/vnd.lotus-organizer',
346
+ 'osf' => 'application/vnd.yamaha.openscoreformat',
347
+ 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml',
348
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
349
+ 'otf' => 'application/x-font-otf',
350
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
351
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
352
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
353
+ 'otm' => 'application/vnd.oasis.opendocument.text-master',
354
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
355
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
356
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
357
+ 'oxt' => 'application/vnd.openofficeorg.extension',
358
+ 'p10' => 'application/pkcs10',
359
+ 'p12|pfx' => 'application/x-pkcs12',
360
+ 'p7b|spc' => 'application/x-pkcs7-certificates',
361
+ 'p7m|p7c' => 'application/pkcs7-all',
362
+ 'p7r' => 'application/x-pkcs7-certreqresp',
363
+ 'p7s' => 'application/pkcs7-signature',
364
+ 'pbd' => 'application/vnd.powerbuilder6',
365
+ 'pbm' => 'image/x-portable-bitmap',
366
+ 'pcf' => 'application/x-font-pcf',
367
+ 'pcl' => 'application/vnd.hp-pcl',
368
+ 'pclxl' => 'application/vnd.hp-pclxl',
369
+ 'pcurl' => 'application/vnd.curl.pcurl',
370
+ 'pcx' => 'image/x-pcx',
371
+ 'pdb|pqa|oprc' => 'application/vnd.palm',
372
+ 'pdf' => 'application/pdf',
373
+ 'pfa|pfb|pfm|afm' => 'application/x-font-type1',
374
+ 'pfr' => 'application/font-tdpfr',
375
+ 'pgm' => 'image/x-portable-graymap',
376
+ 'pgn' => 'application/x-chess-pgn',
377
+ 'pgp' => 'application/pgp-encrypted',
378
+ 'pic|pct' => 'image/x-pict',
379
+ 'pki' => 'application/pkixcmp',
380
+ 'pkipath' => 'application/pkix-pkipath',
381
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
382
+ 'plc' => 'application/vnd.mobius.plc',
383
+ 'plf' => 'application/vnd.pocketlearn',
384
+ 'pls' => 'application/pls+xml',
385
+ 'pml' => 'application/vnd.ctc-posml',
386
+ 'png' => 'image/png',
387
+ 'pnm' => 'image/x-portable-anymap',
388
+ 'portpkg' => 'application/vnd.macports.portpkg',
389
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12',
390
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
391
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12',
392
+ 'ppd' => 'application/vnd.cups-ppd',
393
+ 'ppm' => 'image/x-portable-pixmap',
394
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
395
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
396
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12',
397
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
398
+ 'ppt|pps|pot' => 'application/vnd.ms-powerpoint',
399
+ 'prc|mobi' => 'application/x-mobipocket-ebook',
400
+ 'pre' => 'application/vnd.lotus-freelance',
401
+ 'prf' => 'application/pics-rules',
402
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
403
+ 'psd' => 'image/vnd.adobe.photoshop',
404
+ 'psf' => 'application/x-font-linux-psf',
405
+ 'ptid' => 'application/vnd.pvi.ptid1',
406
+ 'pub' => 'application/x-mspublisher',
407
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
408
+ 'pwn' => 'application/vnd.3m.post-it-notes',
409
+ 'pya' => 'audio/vnd.ms-playready.media.pya',
410
+ 'pyv' => 'video/vnd.ms-playready.media.pyv',
411
+ 'p|pas' => 'text/x-pascal',
412
+ 'qam' => 'application/vnd.epson.quickanime',
413
+ 'qbo' => 'application/vnd.intu.qbo',
414
+ 'qfx' => 'application/vnd.intu.qfx',
415
+ 'qps' => 'application/vnd.publishare-delta-tree',
416
+ 'qt|mov' => 'video/quicktime',
417
+ 'qxd|qxt|qwd|qwt|qxl|qxb' => 'application/vnd.quark.quarkxpress',
418
+ 'ram|ra' => 'audio/x-pn-realaudio',
419
+ 'rar' => 'application/x-rar-compressed',
420
+ 'ras' => 'image/x-cmu-raster',
421
+ 'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
422
+ 'rdf' => 'application/rdf+xml',
423
+ 'rdz' => 'application/vnd.data-vision.rdz',
424
+ 'rep' => 'application/vnd.businessobjects',
425
+ 'res' => 'application/x-dtbresource+xml',
426
+ 'rgb' => 'image/x-rgb',
427
+ 'rif' => 'application/reginfo+xml',
428
+ 'rl' => 'application/resource-lists+xml',
429
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
430
+ 'rld' => 'application/resource-lists-diff+xml',
431
+ 'rm' => 'application/vnd.rn-realmedia',
432
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
433
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
434
+ 'rnc' => 'application/relax-ng-compact-syntax',
435
+ 'rpss' => 'application/vnd.nokia.radio-presets',
436
+ 'rpst' => 'application/vnd.nokia.radio-preset',
437
+ 'rq' => 'application/sparql-query',
438
+ 'rs' => 'application/rls-services+xml',
439
+ 'rsd' => 'application/rsd+xml',
440
+ 'rss' => 'application/rss+xml',
441
+ 'rtf' => 'application/rtf',
442
+ 'rtx' => 'text/richtext',
443
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
444
+ 'sbml' => 'application/sbml+xml',
445
+ 'sc' => 'application/vnd.ibm.secure-container',
446
+ 'scd' => 'application/x-msschedule',
447
+ 'scm' => 'application/vnd.lotus-screencam',
448
+ 'scq' => 'application/scvp-cv-request',
449
+ 'scs' => 'application/scvp-cv-response',
450
+ 'scurl' => 'text/vnd.curl.scurl',
451
+ 'sda' => 'application/vnd.stardivision.draw',
452
+ 'sdc' => 'application/vnd.stardivision.calc',
453
+ 'sdd' => 'application/vnd.stardivision.impress',
454
+ 'sdkm|sdkd' => 'application/vnd.solent.sdkm+xml',
455
+ 'sdp' => 'application/sdp',
456
+ 'sdw' => 'application/vnd.stardivision.writer',
457
+ 'see' => 'application/vnd.seemail',
458
+ 'seed|dataless' => 'application/vnd.fdsn.seed',
459
+ 'sema' => 'application/vnd.sema',
460
+ 'semd' => 'application/vnd.semd',
461
+ 'semf' => 'application/vnd.semf',
462
+ 'ser' => 'application/java-serialized-object',
463
+ 'setpay' => 'application/set-payment-initiation',
464
+ 'setreg' => 'application/set-registration-initiation',
465
+ 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data',
466
+ 'sfs' => 'application/vnd.spotfire.sfs',
467
+ 'sgl' => 'application/vnd.stardivision.writer-global',
468
+ 'sgml|sgm' => 'text/sgml',
469
+ 'sh' => 'application/x-sh',
470
+ 'shar' => 'application/x-shar',
471
+ 'shf' => 'application/shf+xml',
472
+ 'sis|sisx' => 'application/vnd.symbian.install',
473
+ 'sit' => 'application/x-stuffit',
474
+ 'sitx' => 'application/x-stuffitx',
475
+ 'skp|skd|skt|skm' => 'application/vnd.koan',
476
+ 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12',
477
+ 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
478
+ 'slt' => 'application/vnd.epson.salt',
479
+ 'smf' => 'application/vnd.stardivision.math',
480
+ 'smi|smil' => 'application/smil+xml',
481
+ 'snf' => 'application/x-font-snf',
482
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
483
+ 'spl' => 'application/x-futuresplash',
484
+ 'spot' => 'text/vnd.in3d.spot',
485
+ 'spp' => 'application/scvp-vp-response',
486
+ 'spq' => 'application/scvp-vp-request',
487
+ 'src' => 'application/x-wais-source',
488
+ 'srx' => 'application/sparql-results+xml',
489
+ 'sse' => 'application/vnd.kodak-descriptor',
490
+ 'ssf' => 'application/vnd.epson.ssf',
491
+ 'ssml' => 'application/ssml+xml',
492
+ 'stc' => 'application/vnd.sun.xml.calc.template',
493
+ 'std' => 'application/vnd.sun.xml.draw.template',
494
+ 'stf' => 'application/vnd.wt.stf',
495
+ 'sti' => 'application/vnd.sun.xml.impress.template',
496
+ 'stk' => 'application/hyperstudio',
497
+ 'stl' => 'application/vnd.ms-pki.stl',
498
+ 'str' => 'application/vnd.pg.format',
499
+ 'stw' => 'application/vnd.sun.xml.writer.template',
500
+ 'sus|susp' => 'application/vnd.sus-calendar',
501
+ 'sv4cpio' => 'application/x-sv4cpio',
502
+ 'sv4crc' => 'application/x-sv4crc',
503
+ 'svd' => 'application/vnd.svd',
504
+ 'svg|svgz' => 'image/svg+xml',
505
+ 'swf' => 'application/x-shockwave-flash',
506
+ 'swi' => 'application/vnd.arastra.swi',
507
+ 'sxc' => 'application/vnd.sun.xml.calc',
508
+ 'sxd' => 'application/vnd.sun.xml.draw',
509
+ 'sxg' => 'application/vnd.sun.xml.writer.global',
510
+ 'sxi' => 'application/vnd.sun.xml.impress',
511
+ 'sxm' => 'application/vnd.sun.xml.math',
512
+ 'sxw' => 'application/vnd.sun.xml.writer',
513
+ 's|asm' => 'text/x-asm',
514
+ 'tao' => 'application/vnd.tao.intent-module-archive',
515
+ 'tar' => 'application/x-tar',
516
+ 'tcap' => 'application/vnd.3gpp2.tcap',
517
+ 'tcl' => 'application/x-tcl',
518
+ 'teacher' => 'application/vnd.smart.teacher',
519
+ 'tex' => 'application/x-tex',
520
+ 'texinfo|texi' => 'application/x-texinfo',
521
+ 'tfm' => 'application/x-tex-tfm',
522
+ 'tiff|tif' => 'image/tiff',
523
+ 'tmo' => 'application/vnd.tmobile-livetv',
524
+ 'torrent' => 'application/x-bittorrent',
525
+ 'tpl' => 'application/vnd.groove-tool-template',
526
+ 'tpt' => 'application/vnd.trid.tpt',
527
+ 'tra' => 'application/vnd.trueapp',
528
+ 'trm' => 'application/x-msterminal',
529
+ 'tsv' => 'text/tab-separated-values',
530
+ 'ttf|ttc' => 'application/x-font-ttf',
531
+ 'twd|twds' => 'application/vnd.simtech-mindmapper',
532
+ 'txd' => 'application/vnd.genomatix.tuxedo',
533
+ 'txf' => 'application/vnd.mobius.txf',
534
+ 'txt|text|conf|def|list|log|in' => 'text/plain',
535
+ 't|tr|roff|man|me|ms' => 'text/troff',
536
+ 'ufd|ufdl' => 'application/vnd.ufdl',
537
+ 'umj' => 'application/vnd.umajin',
538
+ 'unityweb' => 'application/vnd.unity',
539
+ 'uoml' => 'application/vnd.uoml+xml',
540
+ 'uri|uris|urls' => 'text/uri-list',
541
+ 'ustar' => 'application/x-ustar',
542
+ 'utz' => 'application/vnd.uiq.theme',
543
+ 'uu' => 'text/x-uuencode',
544
+ 'vcd' => 'application/x-cdlink',
545
+ 'vcf' => 'text/x-vcard',
546
+ 'vcg' => 'application/vnd.groove-vcard',
547
+ 'vcs' => 'text/x-vcalendar',
548
+ 'vcx' => 'application/vnd.vcx',
549
+ 'vis' => 'application/vnd.visionary',
550
+ 'viv' => 'video/vnd.vivo',
551
+ 'vor' => 'application/vnd.stardivision.writer',
552
+ 'vsd|vst|vss|vsw' => 'application/vnd.visio',
553
+ 'vsf' => 'application/vnd.vsf',
554
+ 'vtu' => 'model/vnd.vtu',
555
+ 'vxml' => 'application/voicexml+xml',
556
+ 'wad' => 'application/x-doom',
557
+ 'wav' => 'audio/x-wav',
558
+ 'wax' => 'audio/x-ms-wax',
559
+ 'wbmp' => 'image/vnd.wap.wbmp',
560
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
561
+ 'wbxml' => 'application/vnd.wap.wbxml',
562
+ 'wm' => 'video/x-ms-wm',
563
+ 'wma' => 'audio/x-ms-wma',
564
+ 'wmd' => 'application/x-ms-wmd',
565
+ 'wmf' => 'application/x-msmetafile',
566
+ 'wml' => 'text/vnd.wap.wml',
567
+ 'wmlc' => 'application/vnd.wap.wmlc',
568
+ 'wmls' => 'text/vnd.wap.wmlscript',
569
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
570
+ 'wmv' => 'video/x-ms-wmv',
571
+ 'wmx' => 'video/x-ms-wmx',
572
+ 'wmz' => 'application/x-ms-wmz',
573
+ 'wpd' => 'application/vnd.wordperfect',
574
+ 'wpl' => 'application/vnd.ms-wpl',
575
+ 'wps|wks|wcm|wdb' => 'application/vnd.ms-works',
576
+ 'wqd' => 'application/vnd.wqd',
577
+ 'wri' => 'application/x-mswrite',
578
+ 'wrl|vrml' => 'model/vrml',
579
+ 'wsdl' => 'application/wsdl+xml',
580
+ 'wspolicy' => 'application/wspolicy+xml',
581
+ 'wtb' => 'application/vnd.webturbo',
582
+ 'wvx' => 'video/x-ms-wvx',
583
+ 'x3d' => 'application/vnd.hzn-3d-crossword',
584
+ 'xap' => 'application/x-silverlight-app',
585
+ 'xar' => 'application/vnd.xara',
586
+ 'xbap' => 'application/x-ms-xbap',
587
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
588
+ 'xbm' => 'image/x-xbitmap',
589
+ 'xdm' => 'application/vnd.syncml.dm+xml',
590
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
591
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
592
+ 'xenc' => 'application/xenc+xml',
593
+ 'xer' => 'application/patch-ops-error+xml',
594
+ 'xfdf' => 'application/vnd.adobe.xfdf',
595
+ 'xfdl' => 'application/vnd.xfdl',
596
+ 'xhtml|xht' => 'application/xhtml+xml',
597
+ 'xif' => 'image/vnd.xiff',
598
+ 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12',
599
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12',
600
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12',
601
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
602
+ 'xls|xlm|xla|xlc|xlt|xlw' => 'application/vnd.ms-excel',
603
+ 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12',
604
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
605
+ 'xml|xsl' => 'application/xml',
606
+ 'xo' => 'application/vnd.olpc-sugar',
607
+ 'xop' => 'application/xop+xml',
608
+ 'xpi' => 'application/x-xpinstall',
609
+ 'xpm' => 'image/x-xpixmap',
610
+ 'xpr' => 'application/vnd.is-xpr',
611
+ 'xps' => 'application/vnd.ms-xpsdocument',
612
+ 'xpw|xpx' => 'application/vnd.intercon.formnet',
613
+ 'xslt' => 'application/xslt+xml',
614
+ 'xsm' => 'application/vnd.syncml+xml',
615
+ 'xspf' => 'application/xspf+xml',
616
+ 'xul' => 'application/vnd.mozilla.xul+xml',
617
+ 'xwd' => 'image/x-xwindowdump',
618
+ 'xyz' => 'chemical/x-xyz',
619
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
620
+ 'zip' => 'application/zip',
621
+ 'zir|zirz' => 'application/vnd.zul',
622
+ 'zmm' => 'application/vnd.handheld-entertainment+xml',
623
  '123' => 'application/vnd.lotus-1-2-3'
624
  );
inc/options/browsercache.phtml CHANGED
@@ -5,9 +5,8 @@
5
  </p>
6
 
7
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
8
- <fieldset>
9
- <legend>General</legend>
10
-
11
  <p>Specify global browser cache policy.</p>
12
 
13
  <table class="form-table">
@@ -41,15 +40,21 @@
41
  <br /><span class="description">Reduce the download time for text-based files.</span>
42
  </th>
43
  </tr>
 
 
 
 
 
 
44
  <tr>
45
  <th colspan="2">
46
  <input type="hidden" name="browsercache.no404wp" value="0" />
47
- <label><input type="checkbox" name="browsercache.no404wp" value="1"<?php checked($this->_config->get_boolean('browsercache.no404wp'), true); ?> /> Do not process 404 errors for static objects with WordPress</label>
48
  <br /><span class="description">Reduce server load by allowing the web server to handle 404 (not found) errors for static files (images etc).</span>
49
  </th>
50
  </tr>
51
  <tr>
52
- <th valign="top"><label for="browsercache_no404wp_exceptions">404 error exception list:</label></th>
53
  <td>
54
  <textarea id="browsercache_no404wp_exceptions" name="browsercache.no404wp.exceptions" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('browsercache.no404wp.exceptions'))); ?></textarea><br />
55
  <span class="description">Never process 404 (not found) events for the specified files.</span>
@@ -58,13 +63,11 @@
58
  </table>
59
 
60
  <p class="submit">
61
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
62
  </p>
63
- </fieldset>
64
 
65
- <fieldset>
66
- <legend>Cascading Style Sheets &amp; JavaScript</legend>
67
-
68
  <p>Specify browser cache policy for cascading style sheets and JavaScript files.</p>
69
 
70
  <table class="form-table">
@@ -76,7 +79,7 @@
76
  </th>
77
  </tr>
78
  <tr>
79
- <th valign="top">
80
  <label for="browsercache_cssjs_lifetime">Expires header lifetime:</label>
81
  </th>
82
  <td>
@@ -91,7 +94,7 @@
91
  </th>
92
  </tr>
93
  <tr>
94
- <th valign="top">
95
  <label for="browsercache_cssjs_cache_policy">Cache Control policy:</label>
96
  </th>
97
  <td>
@@ -126,16 +129,21 @@
126
  <br /><span class="description">Reduce the download time for text-based files.</span>
127
  </th>
128
  </tr>
 
 
 
 
 
 
 
129
  </table>
130
 
131
  <p class="submit">
132
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
133
  </p>
134
- </fieldset>
135
 
136
- <fieldset>
137
- <legend><acronym title="Hypertext Markup Language">HTML</acronym></legend>
138
-
139
  <p>Specify browser cache policy for posts, pages, feeds and text-based files.</p>
140
 
141
  <table class="form-table">
@@ -147,7 +155,7 @@
147
  </th>
148
  </tr>
149
  <tr>
150
- <th valign="top" style="width: 250px;">
151
  <label for="browsercache_html_lifetime">Expires header lifetime:</label>
152
  </th>
153
  <td>
@@ -162,7 +170,7 @@
162
  </th>
163
  </tr>
164
  <tr>
165
- <th valign="top">
166
  <label for="browsercache_html_cache_policy">Cache Control policy:</label>
167
  </th>
168
  <td>
@@ -200,13 +208,11 @@
200
  </table>
201
 
202
  <p class="submit">
203
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
204
  </p>
205
- </fieldset>
206
 
207
- <fieldset>
208
- <legend>Media &amp; Other Files</legend>
209
-
210
  <table class="form-table">
211
  <tr>
212
  <th colspan="2">
@@ -216,7 +222,7 @@
216
  </th>
217
  </tr>
218
  <tr>
219
- <th valign="top" style="width: 250px;">
220
  <label for="browsercache_other_lifetime">Expires header lifetime:</label>
221
  </th>
222
  <td>
@@ -231,7 +237,7 @@
231
  </th>
232
  </tr>
233
  <tr>
234
- <th valign="top">
235
  <label for="browsercache_other_cache_policy">Cache Control policy:</label>
236
  </th>
237
  <td>
@@ -266,12 +272,20 @@
266
  <br /><span class="description">Reduce the download time for text-based files.</span>
267
  </th>
268
  </tr>
 
 
 
 
 
 
 
269
  </table>
270
 
271
  <p class="submit">
272
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
273
  </p>
274
- </fieldset>
 
275
  </form>
276
 
277
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
5
  </p>
6
 
7
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
8
+ <div class="metabox-holder">
9
+ <?php echo $this->postbox_header('General'); ?>
 
10
  <p>Specify global browser cache policy.</p>
11
 
12
  <table class="form-table">
40
  <br /><span class="description">Reduce the download time for text-based files.</span>
41
  </th>
42
  </tr>
43
+ <tr>
44
+ <th colspan="2">
45
+ <label><input id="browsercache_replace" type="checkbox" name="replace" value="1"<?php checked($browsercache_replace, true); ?> /> Prevent caching of objects after settings change</label>
46
+ <br /><span class="description">Whenever settings are changed, a new query string will be generated and appended to objects allowing the new policy to be applied.</span>
47
+ </th>
48
+ </tr>
49
  <tr>
50
  <th colspan="2">
51
  <input type="hidden" name="browsercache.no404wp" value="0" />
52
+ <label><input type="checkbox" name="browsercache.no404wp" value="1"<?php checked($this->_config->get_boolean('browsercache.no404wp'), true); ?><?php if (!w3_can_check_rules()): ?> disabled="disabled"<?php endif; ?> /> Do not process 404 errors for static objects with WordPress</label>
53
  <br /><span class="description">Reduce server load by allowing the web server to handle 404 (not found) errors for static files (images etc).</span>
54
  </th>
55
  </tr>
56
  <tr>
57
+ <th><label for="browsercache_no404wp_exceptions">404 error exception list:</label></th>
58
  <td>
59
  <textarea id="browsercache_no404wp_exceptions" name="browsercache.no404wp.exceptions" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('browsercache.no404wp.exceptions'))); ?></textarea><br />
60
  <span class="description">Never process 404 (not found) events for the specified files.</span>
63
  </table>
64
 
65
  <p class="submit">
66
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
67
  </p>
68
+ <?php echo $this->postbox_footer(); ?>
69
 
70
+ <?php echo $this->postbox_header('Cascading Style Sheets &amp; JavaScript'); ?>
 
 
71
  <p>Specify browser cache policy for cascading style sheets and JavaScript files.</p>
72
 
73
  <table class="form-table">
79
  </th>
80
  </tr>
81
  <tr>
82
+ <th>
83
  <label for="browsercache_cssjs_lifetime">Expires header lifetime:</label>
84
  </th>
85
  <td>
94
  </th>
95
  </tr>
96
  <tr>
97
+ <th>
98
  <label for="browsercache_cssjs_cache_policy">Cache Control policy:</label>
99
  </th>
100
  <td>
129
  <br /><span class="description">Reduce the download time for text-based files.</span>
130
  </th>
131
  </tr>
132
+ <tr>
133
+ <th colspan="2">
134
+ <input type="hidden" name="browsercache.cssjs.replace" value="0" />
135
+ <label><input class="browsercache_replace" type="checkbox" name="browsercache.cssjs.replace" value="1"<?php checked($this->_config->get_boolean('browsercache.cssjs.replace'), true); ?> /> Prevent caching of objects after settings change</label>
136
+ <br /><span class="description">Whenever settings are changed, a new query string will be generated and appended to objects allowing the new policy to be applied.</span>
137
+ </th>
138
+ </tr>
139
  </table>
140
 
141
  <p class="submit">
142
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
143
  </p>
144
+ <?php echo $this->postbox_footer(); ?>
145
 
146
+ <?php echo $this->postbox_header('<acronym title="Hypertext Markup Language">HTML</acronym>'); ?>
 
 
147
  <p>Specify browser cache policy for posts, pages, feeds and text-based files.</p>
148
 
149
  <table class="form-table">
155
  </th>
156
  </tr>
157
  <tr>
158
+ <th style="width: 250px;">
159
  <label for="browsercache_html_lifetime">Expires header lifetime:</label>
160
  </th>
161
  <td>
170
  </th>
171
  </tr>
172
  <tr>
173
+ <th>
174
  <label for="browsercache_html_cache_policy">Cache Control policy:</label>
175
  </th>
176
  <td>
208
  </table>
209
 
210
  <p class="submit">
211
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
212
  </p>
213
+ <?php echo $this->postbox_footer(); ?>
214
 
215
+ <?php echo $this->postbox_header('Media &amp; Other Files'); ?>
 
 
216
  <table class="form-table">
217
  <tr>
218
  <th colspan="2">
222
  </th>
223
  </tr>
224
  <tr>
225
+ <th style="width: 250px;">
226
  <label for="browsercache_other_lifetime">Expires header lifetime:</label>
227
  </th>
228
  <td>
237
  </th>
238
  </tr>
239
  <tr>
240
+ <th>
241
  <label for="browsercache_other_cache_policy">Cache Control policy:</label>
242
  </th>
243
  <td>
272
  <br /><span class="description">Reduce the download time for text-based files.</span>
273
  </th>
274
  </tr>
275
+ <tr>
276
+ <th colspan="2">
277
+ <input type="hidden" name="browsercache.other.replace" value="0" />
278
+ <label><input class="browsercache_replace" type="checkbox" name="browsercache.other.replace" value="1"<?php checked($this->_config->get_boolean('browsercache.other.replace'), true); ?> /> Prevent caching of objects after settings change</label>
279
+ <br /><span class="description">Whenever settings are changed, a new query string will be generated and appended to objects allowing the new policy to be applied.</span>
280
+ </th>
281
+ </tr>
282
  </table>
283
 
284
  <p class="submit">
285
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
286
  </p>
287
+ <?php echo $this->postbox_footer(); ?>
288
+ </div>
289
  </form>
290
 
291
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/cdn.phtml CHANGED
@@ -10,22 +10,38 @@
10
  <p>
11
  Maximize <acronym title="Content Delivery Network">CDN</acronym> usage by <input id="cdn_rename_domain" class="button" type="button" value="modify attachment URLs" /> or
12
  <input id="cdn_import_library" class="button" type="button" value="importing attachments into the Media Library" />.
 
 
 
13
  </p>
14
  <?php else: ?>
15
  <p>
16
  Prepare the <acronym title="Content Delivery Network">CDN</acronym> by:
17
- <input id="cdn_import_library" class="button" type="button" value="importing attachments into the Media Library" /> then
18
- <input id="cdn_export_library" class="button" type="button" value="exporting media library to CDN" />.
19
  Check <input id="cdn_queue" class="button" type="button" value="unsuccessful file transfers" /> if some objects appear to be missing.
 
 
 
20
  <input id="cdn_rename_domain" class="button" type="button" value="Modify attachment URLs" /> if the domain name of your site has ever changed.
21
  </p>
22
  <?php endif; ?>
23
 
24
- <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
25
- <fieldset id="w3tc-cdn-general">
26
- <legend>General</legend>
27
-
28
  <table class="form-table">
 
 
 
 
 
 
 
 
 
 
 
 
29
  <tr>
30
  <th<?php if ($cdn_mirror): ?> colspan="2"<?php endif; ?>>
31
  <input type="hidden" name="cdn.includes.enable" value="0" />
@@ -93,22 +109,23 @@
93
  </table>
94
 
95
  <p class="submit">
96
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
97
  </p>
98
- </fieldset>
99
-
100
- <fieldset>
101
- <legend>Configuration</legend>
102
 
 
103
  <table class="form-table">
104
  <?php
105
  switch ($cdn_engine) {
106
  case 'mirror':
107
  case 'netdna':
 
108
  case 'ftp':
109
  case 's3':
110
  case 'cf':
 
111
  case 'rscf':
 
112
  include W3TC_DIR . '/inc/options/cdn/' . $cdn_engine . '.phtml';
113
  break;
114
  }
@@ -116,28 +133,41 @@
116
  </table>
117
 
118
  <p class="submit">
119
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
120
  </p>
121
- </fieldset>
122
-
123
- <fieldset>
124
- <legend>Advanced</legend>
125
 
 
126
  <table class="form-table">
 
 
 
 
 
 
 
127
  <?php if (! $cdn_mirror): ?>
 
 
 
 
 
 
 
128
  <tr>
129
- <th valign="top">
130
  <input type="hidden" name="cdn.autoupload.enabled" value="0" />
131
- <label><input type="checkbox" name="cdn.autoupload.enabled" value="1"<?php checked($this->_config->get_boolean('cdn.autoupload.enabled'), true); ?> /> Enable changed files auto-upload</label>
132
- </th>
133
- <td>
134
- <label style="font-size:13px;">
135
- Auto upload interval:
136
- <input id="cdn_autoupload_interval" type="text" name="cdn.autoupload.interval" value="<?php echo $this->_config->get_integer('cdn.autoupload.interval'); ?>" size="8" /> seconds
137
- </label><br />
138
  <span class="description">Automatically attempt to find and upload changed files.</span>
139
- </td>
140
  </tr>
 
 
 
 
 
 
 
141
  <tr>
142
  <th><label for="cdn_limit_interval">Re-transfer cycle interval:</label></th>
143
  <td>
@@ -175,47 +205,53 @@
175
  </td>
176
  </tr>
177
  <tr>
178
- <th valign="top"><label for="cdn_custom_files">Custom file list:</label></th>
179
  <td>
180
  <textarea id="cdn_custom_files" name="cdn.custom.files" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.custom.files'))); ?></textarea><br />
181
  <span class="description">Specify any files outside of theme or other common directories to host with the <acronym title="Content Delivery Network">CDN</acronym>.</span>
182
  </td>
183
  </tr>
184
  <tr>
185
- <th valign="top"><label for="cdn_reject_ua">Rejected user agents:</label></th>
186
  <td>
187
  <textarea id="cdn_reject_ua" name="cdn.reject.ua" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.reject.ua'))); ?></textarea><br />
188
  <span class="description">Specify user agents that should not access files hosted with the <acronym title="Content Delivery Network">CDN</acronym>.</span>
189
  </td>
190
  </tr>
191
  <tr>
192
- <th valign="top"><label for="cdn_reject_files">Rejected files:</label></th>
193
  <td>
194
  <textarea id="cdn_reject_files" name="cdn.reject.files" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.reject.files'))); ?></textarea><br />
195
  <span class="description">Specify the path of files that should not use the <acronym title="Content Delivery Network">CDN</acronym>.</span>
196
  </td>
197
  </tr>
 
 
 
 
 
 
 
 
198
  </table>
199
 
200
  <p class="submit">
201
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
202
  </p>
203
- </fieldset>
204
-
205
- <fieldset>
206
- <legend>Note(s):</legend>
207
 
 
208
  <table class="form-table">
209
  <tr>
210
- <th valign="top" colspan="2">
211
  <ul>
212
  <li>If using Amazon Web Services or Self-Hosted <acronym title="Content Delivery Network">CDN</acronym> types, enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression in the "Media &amp; Other Files" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
213
  </ul>
214
  </th>
215
  </tr>
216
  </table>
217
-
218
- </fieldset>
219
  </form>
220
 
221
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
10
  <p>
11
  Maximize <acronym title="Content Delivery Network">CDN</acronym> usage by <input id="cdn_rename_domain" class="button" type="button" value="modify attachment URLs" /> or
12
  <input id="cdn_import_library" class="button" type="button" value="importing attachments into the Media Library" />.
13
+ <?php if (w3_can_cdn_purge($cdn_engine)): ?>
14
+ <input id="cdn_purge" class="button" type="button" value="Purge" /> objects from the CDN using this tool.
15
+ <?php endif; ?>
16
  </p>
17
  <?php else: ?>
18
  <p>
19
  Prepare the <acronym title="Content Delivery Network">CDN</acronym> by:
20
+ <input id="cdn_import_library" class="button" type="button" value="importing attachments into the Media Library" />.
 
21
  Check <input id="cdn_queue" class="button" type="button" value="unsuccessful file transfers" /> if some objects appear to be missing.
22
+ <?php if (w3_can_cdn_purge($cdn_engine)): ?>
23
+ <input id="cdn_purge" class="button" type="button" value="Purge" /> objects from the <acronym title="Content Delivery Network">CDN</acronym> if needed.
24
+ <?php endif; ?>
25
  <input id="cdn_rename_domain" class="button" type="button" value="Modify attachment URLs" /> if the domain name of your site has ever changed.
26
  </p>
27
  <?php endif; ?>
28
 
29
+ <form id="cdn_form" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
30
+ <div class="metabox-holder">
31
+ <?php echo $this->postbox_header('General'); ?>
 
32
  <table class="form-table">
33
+ <tr>
34
+ <th<?php if ($cdn_mirror): ?> colspan="2"<?php else: ?> style="width: 300px;"<?php endif; ?>>
35
+ <input type="hidden" name="cdn.uploads.enable" value="0" />
36
+ <label><input type="checkbox" name="cdn.uploads.enable" value="1"<?php checked($this->_config->get_boolean('cdn.uploads.enable'), true); ?> /> Host attachments</label><br />
37
+ <span class="description">If checked, all attachments will be hosted with the <acronym title="Content Delivery Network">CDN</acronym>.</span>
38
+ </th>
39
+ <?php if (! $cdn_mirror): ?>
40
+ <td>
41
+ <input id="cdn_export_library" class="button" type="button" value="Upload attachments" />
42
+ </td>
43
+ <?php endif; ?>
44
+ </tr>
45
  <tr>
46
  <th<?php if ($cdn_mirror): ?> colspan="2"<?php endif; ?>>
47
  <input type="hidden" name="cdn.includes.enable" value="0" />
109
  </table>
110
 
111
  <p class="submit">
112
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
113
  </p>
114
+ <?php echo $this->postbox_footer(); ?>
 
 
 
115
 
116
+ <?php echo $this->postbox_header('Configuration'); ?>
117
  <table class="form-table">
118
  <?php
119
  switch ($cdn_engine) {
120
  case 'mirror':
121
  case 'netdna':
122
+ case 'cotendo':
123
  case 'ftp':
124
  case 's3':
125
  case 'cf':
126
+ case 'cf2':
127
  case 'rscf':
128
+ case 'azure':
129
  include W3TC_DIR . '/inc/options/cdn/' . $cdn_engine . '.phtml';
130
  break;
131
  }
133
  </table>
134
 
135
  <p class="submit">
136
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
137
  </p>
138
+ <?php echo $this->postbox_footer(); ?>
 
 
 
139
 
140
+ <?php echo $this->postbox_header('Advanced'); ?>
141
  <table class="form-table">
142
+ <tr>
143
+ <th colspan="2">
144
+ <input type="hidden" name="cdn.reject.admins" value="0" />
145
+ <label><input type="checkbox" name="cdn.reject.admins" value="1"<?php checked($this->_config->get_boolean('cdn.reject.admins'), true); ?> /> Don't replace URLs for logged in administrators</label><br />
146
+ <span class="description">Authenticated administrators will use the origin server exclusively when this option is selected.</span>
147
+ </th>
148
+ </tr>
149
  <?php if (! $cdn_mirror): ?>
150
+ <tr>
151
+ <th colspan="2">
152
+ <input type="hidden" name="minify.upload" value="0"<?php if ($this->_config->get_boolean('minify.auto')): ?> disabled="disabled"<?php endif; ?> />
153
+ <label><input type="checkbox" name="minify.upload" value="1"<?php checked($this->_config->get_boolean('minify.upload'), true); ?><?php if ($this->_config->get_boolean('minify.auto')): ?> disabled="disabled"<?php endif; ?> /> Automatically upload minify files</label><br />
154
+ <span class="description">If <acronym title="Content Delivery Network">CDN</acronym> is enabled (and not using the origin pull method), your minified files will be automatically uploaded.</span>
155
+ </th>
156
+ </tr>
157
  <tr>
158
+ <th colspan="2">
159
  <input type="hidden" name="cdn.autoupload.enabled" value="0" />
160
+ <label><input type="checkbox" name="cdn.autoupload.enabled" value="1"<?php checked($this->_config->get_boolean('cdn.autoupload.enabled'), true); ?> /> Export changed files automatically</label><br />
 
 
 
 
 
 
161
  <span class="description">Automatically attempt to find and upload changed files.</span>
162
+ </th>
163
  </tr>
164
+ <tr>
165
+ <th><label for="cdn_autoupload_interval">Auto upload interval:</label></th>
166
+ <td>
167
+ <input id="cdn_autoupload_interval" type="text" name="cdn.autoupload.interval" value="<?php echo $this->_config->get_integer('cdn.autoupload.interval'); ?>" size="8" /> seconds<br />
168
+ <span class="description">Specify the interval between upload of changed files.</span>
169
+ </td>
170
+ </tr>
171
  <tr>
172
  <th><label for="cdn_limit_interval">Re-transfer cycle interval:</label></th>
173
  <td>
205
  </td>
206
  </tr>
207
  <tr>
208
+ <th><label for="cdn_custom_files">Custom file list:</label></th>
209
  <td>
210
  <textarea id="cdn_custom_files" name="cdn.custom.files" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.custom.files'))); ?></textarea><br />
211
  <span class="description">Specify any files outside of theme or other common directories to host with the <acronym title="Content Delivery Network">CDN</acronym>.</span>
212
  </td>
213
  </tr>
214
  <tr>
215
+ <th><label for="cdn_reject_ua">Rejected user agents:</label></th>
216
  <td>
217
  <textarea id="cdn_reject_ua" name="cdn.reject.ua" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.reject.ua'))); ?></textarea><br />
218
  <span class="description">Specify user agents that should not access files hosted with the <acronym title="Content Delivery Network">CDN</acronym>.</span>
219
  </td>
220
  </tr>
221
  <tr>
222
+ <th><label for="cdn_reject_files">Rejected files:</label></th>
223
  <td>
224
  <textarea id="cdn_reject_files" name="cdn.reject.files" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.reject.files'))); ?></textarea><br />
225
  <span class="description">Specify the path of files that should not use the <acronym title="Content Delivery Network">CDN</acronym>.</span>
226
  </td>
227
  </tr>
228
+ <tr>
229
+ <th colspan="2">
230
+ <input type="hidden" name="set_cookie_domain_old" value="<?php echo (int) $set_cookie_domain; ?>" />
231
+ <input type="hidden" name="set_cookie_domain_new" value="0" />
232
+ <label><input type="checkbox" name="set_cookie_domain_new" value="1"<?php checked($set_cookie_domain, true); ?> /> Set cookie domain to &quot;<?php echo htmlspecialchars($cookie_domain); ?>&quot;</label>
233
+ <br /><span class="description">If using subdomain for CDN functionality, this setting helps prevent new users from sending cookies in requests to the CDN subdomain.</span>
234
+ </th>
235
+ </tr>
236
  </table>
237
 
238
  <p class="submit">
239
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
240
  </p>
241
+ <?php echo $this->postbox_footer(); ?>
 
 
 
242
 
243
+ <?php echo $this->postbox_header('Note(s):'); ?>
244
  <table class="form-table">
245
  <tr>
246
+ <th colspan="2">
247
  <ul>
248
  <li>If using Amazon Web Services or Self-Hosted <acronym title="Content Delivery Network">CDN</acronym> types, enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression in the "Media &amp; Other Files" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
249
  </ul>
250
  </th>
251
  </tr>
252
  </table>
253
+ <?php echo $this->postbox_footer(); ?>
254
+ </div>
255
  </form>
256
 
257
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/cdn/azure.phtml ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <th style="width: 300px;"><label for="cdn_azure_user">Account name:</label></th>
3
+ <td>
4
+ <input id="cdn_azure_user" class="w3tc-ignore-change" type="text" name="cdn.azure.user" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.azure.user')); ?>" size="30" />
5
+ </td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="cdn_azure_key">Account key:</label></th>
9
+ <td>
10
+ <input id="cdn_azure_key" class="w3tc-ignore-change" type="password" name="cdn.azure.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.azure.key')); ?>" size="60" />
11
+ </td>
12
+ </tr>
13
+ <tr>
14
+ <th><label for="cdn_azure_container">Container:</label></th>
15
+ <td>
16
+ <input id="cdn_azure_container" type="text" name="cdn.azure.container" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.azure.container')); ?>" size="30" />
17
+ <input id="cdn_create_container" class="button cdn_azure" type="button" value="Create container" />
18
+ <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
19
+ </td>
20
+ </tr>
21
+ <tr>
22
+ <th><label for="cdn_s3_ssl"><acronym title="Secure Sockets Layer">SSL</acronym> support:</label></th>
23
+ <td>
24
+ <select id="cdn_s3_ssl" name="cdn.s3.ssl">
25
+ <option value="auto"<?php selected($this->_config->get_string('cdn.azure.ssl'), 'auto'); ?>>Auto (determine connection type automatically)</option>
26
+ <option value="enabled"<?php selected($this->_config->get_string('cdn.azure.ssl'), 'enabled'); ?>>Enabled (always use SSL)</option>
27
+ <option value="disabled"<?php selected($this->_config->get_string('cdn.azure.ssl'), 'disabled'); ?>>Disabled (always use HTTP)</option>
28
+ </select>
29
+ <br /><span class="description">Some <acronym>CDN</acronym> providers may or may not support <acronym title="Secure Sockets Layer">SSL</acronym>, contact your vendor for more information.</span>
30
+ </td>
31
+ </tr>
32
+ <tr>
33
+ <th>Replace site's hostname with:</th>
34
+ <td>
35
+ <?php if (($cdn_azure_user = $this->_config->get_string('cdn.azure.user')) != ''): ?>
36
+ <?php echo htmlspecialchars($cdn_azure_user); ?>.blob.core.windows.net
37
+ <?php else: ?>
38
+ &lt;account name&gt;.blob.core.windows.net
39
+ <?php endif; ?> or CNAME:
40
+ <?php $cnames = $this->_config->get_array('cdn.azure.cname'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
41
+ </td>
42
+ </tr>
43
+ <tr>
44
+ <th colspan="2">
45
+ <input id="cdn_test" class="button cdn_azure" type="button" value="Test Microsoft Azure Storage upload" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
46
+ </th>
47
+ </tr>
inc/options/cdn/cf.phtml CHANGED
@@ -1,21 +1,20 @@
1
  <tr>
2
- <th style="width:300px;"><label for="cdn_cf_key">Access key ID:</label></th>
3
  <td>
4
- <input id="cdn_cf_key" type="text" name="cdn.cf.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.key')); ?>" size="30" />
5
  </td>
6
  </tr>
7
  <tr>
8
  <th><label for="cdn_cf_secret">Secret key:</label></th>
9
  <td>
10
- <input id="cdn_cf_secret" type="password" name="cdn.cf.secret" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.secret')); ?>" size="60" />
11
  </td>
12
  </tr>
13
  <tr>
14
  <th><label for="cdn_cf_bucket">Bucket:</label></th>
15
  <td>
16
  <input id="cdn_cf_bucket" type="text" name="cdn.cf.bucket" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.bucket')); ?>" size="30" />
17
- <input id="cdn_create_container" class="button cdn_cf" type="button" value="Create bucket" />
18
- <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
19
  </td>
20
  </tr>
21
  <tr>
@@ -32,13 +31,13 @@
32
  <tr>
33
  <th><label for="cdn_cf_id">Replace site's hostname with:</label></th>
34
  <td>
35
- <input id="cdn_cf_id" type="text" name="cdn.cf.id" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.id')); ?>" size="18" style="text-align:right;" />.cloudfront.net or CNAME:
36
  <?php $cnames = $this->_config->get_array('cdn.cf.cname'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
37
  <br /><span class="description">If you have already added a <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?CNAMEs.html" target="_blank">CNAME</a> to your <acronym title="Domain Name System">DNS</acronym> Zone, enter it here.</span>
38
  </td>
39
  </tr>
40
  <tr>
41
  <th colspan="2">
42
- <input id="cdn_test" class="button cdn_cf" type="button" value="Test CloudFront upload" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
43
  </th>
44
  </tr>
1
  <tr>
2
+ <th style="width: 300px;"><label for="cdn_cf_key">Access key ID:</label></th>
3
  <td>
4
+ <input id="cdn_cf_key" class="w3tc-ignore-change" type="text" name="cdn.cf.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.key')); ?>" size="30" />
5
  </td>
6
  </tr>
7
  <tr>
8
  <th><label for="cdn_cf_secret">Secret key:</label></th>
9
  <td>
10
+ <input id="cdn_cf_secret" class="w3tc-ignore-change" type="password" name="cdn.cf.secret" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.secret')); ?>" size="60" />
11
  </td>
12
  </tr>
13
  <tr>
14
  <th><label for="cdn_cf_bucket">Bucket:</label></th>
15
  <td>
16
  <input id="cdn_cf_bucket" type="text" name="cdn.cf.bucket" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.bucket')); ?>" size="30" />
17
+ <input class="button button-cdn-cf-bucket-location cdn_cf" type="button" value="Create bucket &amp; distribution" />
 
18
  </td>
19
  </tr>
20
  <tr>
31
  <tr>
32
  <th><label for="cdn_cf_id">Replace site's hostname with:</label></th>
33
  <td>
34
+ <input id="cdn_cf_id" type="text" name="cdn.cf.id" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf.id')); ?>" size="18" style="text-align: right;" />.cloudfront.net or CNAME:
35
  <?php $cnames = $this->_config->get_array('cdn.cf.cname'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
36
  <br /><span class="description">If you have already added a <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?CNAMEs.html" target="_blank">CNAME</a> to your <acronym title="Domain Name System">DNS</acronym> Zone, enter it here.</span>
37
  </td>
38
  </tr>
39
  <tr>
40
  <th colspan="2">
41
+ <input id="cdn_test" class="button cdn_cf" type="button" value="Test S3 upload &amp; CloudFront distribution" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
42
  </th>
43
  </tr>
inc/options/cdn/cf2.phtml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <th style="width: 300px;"><label for="cdn_cf2_key">Access key ID:</label></th>
3
+ <td>
4
+ <input id="cdn_cf2_key" class="w3tc-ignore-change" type="text" name="cdn.cf2.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf2.key')); ?>" size="30" />
5
+ </td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="cdn_cf2_secret">Secret key:</label></th>
9
+ <td>
10
+ <input id="cdn_cf2_secret" class="w3tc-ignore-change" type="password" name="cdn.cf2.secret" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf2.secret')); ?>" size="60" />
11
+ </td>
12
+ </tr>
13
+ <tr>
14
+ <th>Origin:</th>
15
+ <td>
16
+ <?php echo w3_get_host(); ?>
17
+ <input id="cdn_create_container" class="button cdn_cf2" type="button" value="Create distribution" />
18
+ <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
19
+ </td>
20
+ </tr>
21
+ <tr>
22
+ <th><label for="cdn_cf2_ssl"><acronym title="Secure Sockets Layer">SSL</acronym> support:</label></th>
23
+ <td>
24
+ <select id="cdn_cf2_ssl" name="cdn.cf2.ssl">
25
+ <option value="auto"<?php selected($this->_config->get_string('cdn.cf2.ssl'), 'auto'); ?>>Auto (determine connection type automatically)</option>
26
+ <option value="enabled"<?php selected($this->_config->get_string('cdn.cf2.ssl'), 'enabled'); ?>>Enabled (always use SSL)</option>
27
+ <option value="disabled"<?php selected($this->_config->get_string('cdn.cf2.ssl'), 'disabled'); ?>>Disabled (always use HTTP)</option>
28
+ </select>
29
+ <br /><span class="description">Some <acronym>CDN</acronym> providers may or may not support <acronym title="Secure Sockets Layer">SSL</acronym>, contact your vendor for more information.</span>
30
+ </td>
31
+ </tr>
32
+ <tr>
33
+ <th><label for="cdn_cf2_id">Replace site's hostname with:</label></th>
34
+ <td>
35
+ <input id="cdn_cf2_id" type="text" name="cdn.cf2.id" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cf2.id')); ?>" size="18" style="text-align: right;" />.cloudfront.net or CNAME:
36
+ <?php $cnames = $this->_config->get_array('cdn.cf2.cname'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
37
+ <br /><span class="description">If you have already added a <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?CNAMEs.html" target="_blank">CNAME</a> to your <acronym title="Domain Name System">DNS</acronym> Zone, enter it here.</span>
38
+ </td>
39
+ </tr>
40
+ <tr>
41
+ <th colspan="2">
42
+ <input id="cdn_test" class="button cdn_cf2" type="button" value="Test CloudFront distribution" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
43
+ </th>
44
+ </tr>
inc/options/cdn/cotendo.phtml ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <th style="width: 300px;"><label for="cdn_cotendo_username">Username:</label></th>
3
+ <td>
4
+ <input id="cdn_cotendo_username" class="w3tc-ignore-change" type="text" name="cdn.cotendo.username" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cotendo.username')); ?>" size="60" />
5
+ </td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="cdn_cotendo_password">Password:</label></th>
9
+ <td>
10
+ <input id="cdn_cotendo_password" class="w3tc-ignore-change" type="password" name="cdn.cotendo.password" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.cotendo.password')); ?>" size="60" />
11
+ </td>
12
+ </tr>
13
+ <tr>
14
+ <th><label for="cdn_cotendo_zones">Zones to purge:</label></th>
15
+ <td>
16
+ <textarea id="cdn_cotendo_zones" name="cdn.cotendo.zones" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('cdn.cotendo.zones'))); ?></textarea>
17
+ </td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="cdn_cotendo_ssl"><acronym title="Secure Sockets Layer">SSL</acronym> support:</label></th>
21
+ <td>
22
+ <select id="cdn_cotendo_ssl" name="cdn.cotendo.ssl">
23
+ <option value="auto"<?php selected($this->_config->get_string('cdn.cotendo.ssl'), 'auto'); ?>>Auto (determine connection type automatically)</option>
24
+ <option value="enabled"<?php selected($this->_config->get_string('cdn.cotendo.ssl'), 'enabled'); ?>>Enabled (always use SSL)</option>
25
+ <option value="disabled"<?php selected($this->_config->get_string('cdn.cotendo.ssl'), 'disabled'); ?>>Disabled (always use HTTP)</option>
26
+ </select>
27
+ <br /><span class="description">Some <acronym>CDN</acronym> providers may or may not support <acronym title="Secure Sockets Layer">SSL</acronym>, contact your vendor for more information.</span>
28
+ </td>
29
+ </tr>
30
+ <tr>
31
+ <th>Replace site's hostname with:</th>
32
+ <td>
33
+ <?php $cnames = $this->_config->get_array('cdn.cotendo.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
34
+ <br /><span class="description">Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
35
+ </td>
36
+ </tr>
37
+ <tr>
38
+ <th colspan="2">
39
+ <input id="cdn_test" class="button cdn_cotendo" type="button" value="Test Cotendo" /> <span id="cdn_test_status" class="w3tc-status w3tc-process"></span>
40
+ </th>
41
+ </tr>
inc/options/cdn/ftp.phtml CHANGED
@@ -6,7 +6,7 @@
6
  </th>
7
  </tr>
8
  <tr>
9
- <th style="width:300px;"><label for="cdn_ftp_host"><acronym title="File Transfer Protocol">FTP</acronym> hostname:</label></th>
10
  <td>
11
  <input id="cdn_ftp_host" type="text" name="cdn.ftp.host" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.ftp.host')); ?>" size="30" /><br />
12
  <span class="description">Specify the server's address, e.g.: "ftp.domain.com". Try "127.0.0.1" if using a sub-domain on the same server as your site.</span>
@@ -15,13 +15,13 @@
15
  <tr>
16
  <th><label for="cdn_ftp_user"><acronym title="File Transfer Protocol">FTP</acronym> username:</label></th>
17
  <td>
18
- <input id="cdn_ftp_user" type="text" name="cdn.ftp.user" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.ftp.user')); ?>" size="30" />
19
  </td>
20
  </tr>
21
  <tr>
22
  <th><label for="cdn_ftp_pass"><acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
23
  <td>
24
- <input id="cdn_ftp_pass" type="password" name="cdn.ftp.pass" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.ftp.pass')); ?>" size="30" />
25
  </td>
26
  </tr>
27
  <tr>
@@ -43,7 +43,7 @@
43
  </td>
44
  </tr>
45
  <tr>
46
- <th><label for="cdn_cnames">Replace site's hostname with:</label></th>
47
  <td>
48
  <?php $cnames = $this->_config->get_array('cdn.ftp.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
49
  <br /><span class="description">Enter the hostname or CNAME(s) of your FTP server configured above, these values will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
6
  </th>
7
  </tr>
8
  <tr>
9
+ <th style="width: 300px;"><label for="cdn_ftp_host"><acronym title="File Transfer Protocol">FTP</acronym> hostname:</label></th>
10
  <td>
11
  <input id="cdn_ftp_host" type="text" name="cdn.ftp.host" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.ftp.host')); ?>" size="30" /><br />
12
  <span class="description">Specify the server's address, e.g.: "ftp.domain.com". Try "127.0.0.1" if using a sub-domain on the same server as your site.</span>
15
  <tr>
16
  <th><label for="cdn_ftp_user"><acronym title="File Transfer Protocol">FTP</acronym> username:</label></th>
17
  <td>
18
+ <input id="cdn_ftp_user" class="w3tc-ignore-change" type="text" name="cdn.ftp.user" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.ftp.user')); ?>" size="30" />
19
  </td>
20
  </tr>
21
  <tr>
22
  <th><label for="cdn_ftp_pass"><acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
23
  <td>
24
+ <input id="cdn_ftp_pass" class="w3tc-ignore-change" type="password" name="cdn.ftp.pass" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.ftp.pass')); ?>" size="30" />
25
  </td>
26
  </tr>
27
  <tr>
43
  </td>
44
  </tr>
45
  <tr>
46
+ <th>Replace site's hostname with:</th>
47
  <td>
48
  <?php $cnames = $this->_config->get_array('cdn.ftp.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
49
  <br /><span class="description">Enter the hostname or CNAME(s) of your FTP server configured above, these values will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
inc/options/cdn/mirror.phtml CHANGED
@@ -10,7 +10,7 @@
10
  </td>
11
  </tr>
12
  <tr>
13
- <th style="width:300px;"><label for="cdn_cnames">Replace site's hostname with:</label></th>
14
  <td>
15
  <?php $cnames = $this->_config->get_array('cdn.mirror.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
16
  <br /><span class="description">Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
10
  </td>
11
  </tr>
12
  <tr>
13
+ <th>Replace site's hostname with:</th>
14
  <td>
15
  <?php $cnames = $this->_config->get_array('cdn.mirror.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
16
  <br /><span class="description">Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
inc/options/cdn/netdna.phtml CHANGED
@@ -1,13 +1,13 @@
1
  <tr>
2
- <th style="width:300px;"><label for="cdn_netdna_apiid">API ID:</label></th>
3
  <td>
4
- <input id="cdn_netdna_apiid" type="text" name="cdn.netdna.apiid" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.netdna.apiid')); ?>" size="60" />
5
  </td>
6
  </tr>
7
  <tr>
8
- <th><label for="cdn_netdna_apikey">API key:</label></th>
9
  <td>
10
- <input id="cdn_netdna_apikey" type="text" name="cdn.netdna.apikey" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.netdna.apikey')); ?>" size="60" />
11
  </td>
12
  </tr>
13
  <tr>
@@ -22,7 +22,7 @@
22
  </td>
23
  </tr>
24
  <tr>
25
- <th><label for="cdn_cnames">Replace site's hostname with:</label></th>
26
  <td>
27
  <?php $cnames = $this->_config->get_array('cdn.netdna.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
28
  <br /><span class="description">Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
1
  <tr>
2
+ <th style="width: 300px;"><label for="cdn_netdna_apiid"><acronym title="Application Programming Interface">API</acronym> ID:</label></th>
3
  <td>
4
+ <input id="cdn_netdna_apiid" class="w3tc-ignore-change" type="text" name="cdn.netdna.apiid" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.netdna.apiid')); ?>" size="60" />
5
  </td>
6
  </tr>
7
  <tr>
8
+ <th><label for="cdn_netdna_apikey"><acronym title="Application Programming Interface">API</acronym> key:</label></th>
9
  <td>
10
+ <input id="cdn_netdna_apikey" class="w3tc-ignore-change" type="password" name="cdn.netdna.apikey" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.netdna.apikey')); ?>" size="60" />
11
  </td>
12
  </tr>
13
  <tr>
22
  </td>
23
  </tr>
24
  <tr>
25
+ <th>Replace site's hostname with:</th>
26
  <td>
27
  <?php $cnames = $this->_config->get_array('cdn.netdna.domain'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
28
  <br /><span class="description">Enter the hostname provided by your <acronym>CDN</acronym> provider, this value will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
inc/options/cdn/rscf.phtml CHANGED
@@ -1,13 +1,22 @@
1
  <tr>
2
- <th style="width:300px;"><label for="cdn_rscf_user">Username:</label></th>
3
  <td>
4
- <input id="cdn_rscf_user" type="text" name="cdn.rscf.user" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.rscf.user')); ?>" size="30" />
5
  </td>
6
  </tr>
7
  <tr>
8
  <th><label for="cdn_rscf_key"><acronym title="Application Programming Interface">API</acronym> key:</label></th>
9
  <td>
10
- <input id="cdn_rscf_key" type="password" name="cdn.rscf.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.rscf.key')); ?>" size="60" />
 
 
 
 
 
 
 
 
 
11
  </td>
12
  </tr>
13
  <tr>
@@ -30,10 +39,10 @@
30
  </td>
31
  </tr>
32
  <tr>
33
- <th><label for="cdn_rscf_id">Replace site's hostname with:</label></th>
34
  <td>
35
- <input id="cdn_rscf_id" type="text" name="cdn.rscf.id" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.rscf.id')); ?>" size="18" style="text-align:right;" />.cloudfiles.rackspacecloud.com or CNAME:
36
  <?php $cnames = $this->_config->get_array('cdn.rscf.cname'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
 
37
  </td>
38
  </tr>
39
  <tr>
1
  <tr>
2
+ <th style="width: 300px;"><label for="cdn_rscf_user">Username:</label></th>
3
  <td>
4
+ <input id="cdn_rscf_user" class="w3tc-ignore-change" type="text" name="cdn.rscf.user" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.rscf.user')); ?>" size="30" />
5
  </td>
6
  </tr>
7
  <tr>
8
  <th><label for="cdn_rscf_key"><acronym title="Application Programming Interface">API</acronym> key:</label></th>
9
  <td>
10
+ <input id="cdn_rscf_key" class="w3tc-ignore-change" type="password" name="cdn.rscf.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.rscf.key')); ?>" size="60" />
11
+ </td>
12
+ </tr>
13
+ <tr>
14
+ <th><label for="cdn_rscf_location">Location:</label></th>
15
+ <td>
16
+ <select id="cdn_rscf_location" name="cdn.rscf.location">
17
+ <option value="us"<?php echo selected($this->_config->get_string('cdn.rscf.location'), 'us'); ?>>US</option>
18
+ <option value="uk"<?php echo selected($this->_config->get_string('cdn.rscf.location'), 'uk'); ?>>UK</option>
19
+ </select>
20
  </td>
21
  </tr>
22
  <tr>
39
  </td>
40
  </tr>
41
  <tr>
42
+ <th>Replace site's hostname with:</th>
43
  <td>
 
44
  <?php $cnames = $this->_config->get_array('cdn.rscf.cname'); include W3TC_DIR . '/inc/options/cdn/common/cnames.phtml'; ?>
45
+ <br /><span class="description">Enter the hostname provided by Rackspace Cloud Files, this value will replace your site's hostname in the <acronym title="Hypertext Markup Language">HTML</acronym>.</span>
46
  </td>
47
  </tr>
48
  <tr>
inc/options/cdn/s3.phtml CHANGED
@@ -1,21 +1,20 @@
1
  <tr>
2
- <th style="width:300px;"><label for="cdn_s3_key">Access key ID:</label></th>
3
  <td>
4
- <input id="cdn_s3_key" type="text" name="cdn.s3.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.s3.key')); ?>" size="30" />
5
  </td>
6
  </tr>
7
  <tr>
8
  <th><label for="cdn_s3_secret">Secret key:</label></th>
9
  <td>
10
- <input id="cdn_s3_secret" type="password" name="cdn.s3.secret" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.s3.secret')); ?>" size="60" />
11
  </td>
12
  </tr>
13
  <tr>
14
  <th><label for="cdn_s3_bucket">Bucket:</label></th>
15
  <td>
16
  <input id="cdn_s3_bucket" type="text" name="cdn.s3.bucket" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.s3.bucket')); ?>" size="30" />
17
- <input id="cdn_create_container" class="button cdn_s3" type="button" value="Create bucket" />
18
- <span id="cdn_create_container_status" class="w3tc-status w3tc-process"></span>
19
  </td>
20
  </tr>
21
  <tr>
@@ -30,7 +29,7 @@
30
  </td>
31
  </tr>
32
  <tr>
33
- <th><label for="cdn_cnames">Replace site's hostname with:</label></th>
34
  <td>
35
  <?php if (($cdn_s3_bucket = $this->_config->get_string('cdn.s3.bucket')) != ''): ?>
36
  <?php echo htmlspecialchars($cdn_s3_bucket); ?>.s3.amazonaws.com
1
  <tr>
2
+ <th style="width: 300px;"><label for="cdn_s3_key">Access key ID:</label></th>
3
  <td>
4
+ <input id="cdn_s3_key" class="w3tc-ignore-change" type="text" name="cdn.s3.key" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.s3.key')); ?>" size="30" />
5
  </td>
6
  </tr>
7
  <tr>
8
  <th><label for="cdn_s3_secret">Secret key:</label></th>
9
  <td>
10
+ <input id="cdn_s3_secret" class="w3tc-ignore-change" type="password" name="cdn.s3.secret" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.s3.secret')); ?>" size="60" />
11
  </td>
12
  </tr>
13
  <tr>
14
  <th><label for="cdn_s3_bucket">Bucket:</label></th>
15
  <td>
16
  <input id="cdn_s3_bucket" type="text" name="cdn.s3.bucket" value="<?php echo htmlspecialchars($this->_config->get_string('cdn.s3.bucket')); ?>" size="30" />
17
+ <input class="button button-cdn-s3-bucket-location cdn_s3" type="button" value="Create bucket" />
 
18
  </td>
19
  </tr>
20
  <tr>
29
  </td>
30
  </tr>
31
  <tr>
32
+ <th>Replace site's hostname with:</th>
33
  <td>
34
  <?php if (($cdn_s3_bucket = $this->_config->get_string('cdn.s3.bucket')) != ''): ?>
35
  <?php echo htmlspecialchars($cdn_s3_bucket); ?>.s3.amazonaws.com
inc/options/common/header.phtml CHANGED
@@ -1,5 +1,5 @@
1
  <?php if ($this->_support_reminder): ?>
2
- <script type="text/javascript">
3
  /*<![CDATA[*/
4
  jQuery(function($) {
5
  w3tc_lightbox_support_us();
@@ -25,27 +25,22 @@ jQuery(function($) {
25
  </div>
26
  <?php endforeach; ?>
27
 
28
- <h3 id="w3tc-nav">
29
- <label>
30
- Viewing:
31
- <select>
32
- <optgroup label="Control Panels:">
33
- <option value="w3tc_general"<?php selected($this->_page, 'w3tc_general'); ?>>General Settings</option>
34
- <option value="w3tc_pgcache"<?php selected($this->_page, 'w3tc_pgcache'); ?>>Page Cache Settings</option>
35
- <option value="w3tc_minify"<?php selected($this->_page, 'w3tc_minify'); ?>>Minify Settings</option>
36
- <option value="w3tc_dbcache"<?php selected($this->_page, 'w3tc_dbcache'); ?>>Database Cache Settings</option>
37
- <option value="w3tc_objectcache"<?php selected($this->_page, 'w3tc_objectcache'); ?>>Object Cache Settings</option>
38
- <option value="w3tc_browsercache"<?php selected($this->_page, 'w3tc_browsercache'); ?>>Browser Cache Settings</option>
39
- <option value="w3tc_mobile"<?php selected($this->_page, 'w3tc_mobile'); ?>>User Agent Groups Settings</option>
40
- <option value="w3tc_cdn"<?php selected($this->_page, 'w3tc_cdn'); ?>>Content Delivery Network (CDN) Settings&nbsp;</option>
41
- </optgroup>
42
- <optgroup label="Help:">
43
- <option value="w3tc_faq"<?php selected($this->_page, 'w3tc_faq'); ?>>Frequently Asked Questions</option>
44
- <option style="color: red;" value="w3tc_support"<?php selected($this->_page, 'w3tc_support'); ?>>Support</option>
45
- <option value="w3tc_install"<?php selected($this->_page, 'w3tc_install'); ?>>Install</option>
46
- <option value="w3tc_about"<?php selected($this->_page, 'w3tc_about'); ?>>About</option>
47
- </optgroup>
48
- </select>
49
- </label>
50
- </h3>
51
-
1
  <?php if ($this->_support_reminder): ?>
2
+ <script>
3
  /*<![CDATA[*/
4
  jQuery(function($) {
5
  w3tc_lightbox_support_us();
25
  </div>
26
  <?php endforeach; ?>
27
 
28
+ <p id="w3tc-options-menu">
29
+ <a href="?page=w3tc_general"<?php if ($this->_page == 'w3tc_general'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>General</a> |
30
+ <a href="?page=w3tc_pgcache"<?php if ($this->_page == 'w3tc_pgcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Page Cache</a> |
31
+ <?php if (W3TC_PHP5): ?>
32
+ <a href="?page=w3tc_minify"<?php if ($this->_page == 'w3tc_minify'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Minify</a> |
33
+ <?php else: ?>
34
+ Minify |
35
+ <?php endif; ?>
36
+ <a href="?page=w3tc_dbcache"<?php if ($this->_page == 'w3tc_dbcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Database Cache</a> |
37
+ <a href="?page=w3tc_objectcache"<?php if ($this->_page == 'w3tc_objectcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Object Cache</a> |
38
+ <a href="?page=w3tc_browsercache"<?php if ($this->_page == 'w3tc_browsercache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Browser Cache</a> |
39
+ <a href="?page=w3tc_mobile"<?php if ($this->_page == 'w3tc_mobile'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>User Agent Groups</a> |
40
+ <a href="?page=w3tc_referrer"<?php if ($this->_page == 'w3tc_referrer'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Referrer Groups</a> |
41
+ <a href="?page=w3tc_cdn"<?php if ($this->_page == 'w3tc_cdn'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Content Delivery Network</a> |
42
+ <a href="?page=w3tc_faq"<?php if ($this->_page == 'w3tc_faq'): ?> class="w3tc-options-menu-selected"<?php endif; ?>><acronym title="Frequently Asked Questions">FAQ</acronym></a> |
43
+ <a href="?page=w3tc_support"<?php if ($this->_page == 'w3tc_support'): ?> class="w3tc-options-menu-selected"<?php endif; ?> style="color: red;">Support</a> |
44
+ <a href="?page=w3tc_install"<?php if ($this->_page == 'w3tc_install'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Install</a> |
45
+ <a href="?page=w3tc_about"<?php if ($this->_page == 'w3tc_about'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>About</a>
46
+ </p>
 
 
 
 
 
inc/options/dbcache.phtml CHANGED
@@ -15,9 +15,8 @@
15
  </form>
16
 
17
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
18
- <fieldset>
19
- <legend>General</legend>
20
-
21
  <table class="form-table">
22
  <tr>
23
  <th>
@@ -29,13 +28,11 @@
29
  </table>
30
 
31
  <p class="submit">
32
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
33
  </p>
34
- </fieldset>
35
-
36
- <fieldset>
37
- <legend>Advanced</legend>
38
 
 
39
  <table class="form-table">
40
  <?php if ($this->_config->get_string('dbcache.engine') == 'memcached'): ?>
41
  <tr>
@@ -61,14 +58,14 @@
61
  </td>
62
  </tr>
63
  <tr>
64
- <th valign="top"><label for="dbcache_reject_uri">Never cache the following pages:</label></th>
65
  <td>
66
  <textarea id="dbcache_reject_uri" name="dbcache.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('dbcache.reject.uri'))); ?></textarea><br />
67
  <span class="description">Always ignore the specified pages / directories.</span>
68
  </td>
69
  </tr>
70
  <tr>
71
- <th valign="top"><label for="dbcache_reject_sql">Ignored query stems:</label></th>
72
  <td>
73
  <textarea id="dbcache_reject_sql" name="dbcache.reject.sql" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('dbcache.reject.sql'))); ?></textarea><br />
74
  <span class="description">Do not cache queries that contain these terms. Any entered prefix (set in wp-config.php) will be replaced with current database prefix (default: wp_). Query stems can be identified using debug mode.</span>
@@ -77,9 +74,10 @@
77
  </table>
78
 
79
  <p class="submit">
80
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
81
  </p>
82
- </fieldset>
 
83
  </form>
84
 
85
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
15
  </form>
16
 
17
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
18
+ <div class="metabox-holder">
19
+ <?php echo $this->postbox_header('General'); ?>
 
20
  <table class="form-table">
21
  <tr>
22
  <th>
28
  </table>
29
 
30
  <p class="submit">
31
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
32
  </p>
33
+ <?php echo $this->postbox_footer(); ?>
 
 
 
34
 
35
+ <?php echo $this->postbox_header('Advanced'); ?>
36
  <table class="form-table">
37
  <?php if ($this->_config->get_string('dbcache.engine') == 'memcached'): ?>
38
  <tr>
58
  </td>
59
  </tr>
60
  <tr>
61
+ <th><label for="dbcache_reject_uri">Never cache the following pages:</label></th>
62
  <td>
63
  <textarea id="dbcache_reject_uri" name="dbcache.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('dbcache.reject.uri'))); ?></textarea><br />
64
  <span class="description">Always ignore the specified pages / directories.</span>
65
  </td>
66
  </tr>
67
  <tr>
68
+ <th><label for="dbcache_reject_sql">Ignored query stems:</label></th>
69
  <td>
70
  <textarea id="dbcache_reject_sql" name="dbcache.reject.sql" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('dbcache.reject.sql'))); ?></textarea><br />
71
  <span class="description">Do not cache queries that contain these terms. Any entered prefix (set in wp-config.php) will be replaced with current database prefix (default: wp_). Query stems can be identified using debug mode.</span>
74
  </table>
75
 
76
  <p class="submit">
77
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
78
  </p>
79
+ <?php echo $this->postbox_footer(); ?>
80
+ </div>
81
  </form>
82
 
83
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/general.phtml CHANGED
@@ -17,362 +17,519 @@
17
  </form>
18
 
19
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
20
- <fieldset>
21
- <legend>General</legend>
22
-
23
  <table class="form-table">
24
- <tr>
25
- <th colspan="2">
26
- <label>
27
- <input id="enabled" type="checkbox" name="enabled" value="1"<?php checked($enabled_checked, true); ?> />
28
- Deselect this option to disable all caching functionality.
29
- </label>
30
- </th>
31
- </tr>
32
- <tr>
33
- <th valign="top">Preview Mode:</th>
34
- <td>
35
- <?php if ($preview): ?>
36
- <input type="hidden" name="preview" value="0" />
37
- <input type="submit" name="preview_save" class="button-primary" value="Disable" />
38
- <?php echo $this->button_link('Preview', w3_get_site_url() . '/?w3tc_preview=1', true); ?>
39
- <?php echo $this->button_link('Deploy', sprintf('admin.php?page=%s&preview_deploy', $this->_page)); ?>
40
- <?php else: ?>
41
- <input type="hidden" name="preview" value="1" />
42
- <input type="submit" name="preview_save" class="button-primary" value="Enable" />
43
- <?php endif; ?>
44
- <br /><span class="description">Use preview mode to test configuration scenarios prior to releasing them (deploy) on the actual site.</span>
45
- </td>
46
- </tr>
47
- </table>
48
-
49
  <p class="submit">
50
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
51
  </p>
52
- </fieldset>
53
-
54
- <fieldset>
55
- <legend><a href="admin.php?page=w3tc_pgcache">Page Cache</a></legend>
56
 
57
- <p>Enable page caching to decrease the response time of your site.</p>
 
58
 
59
  <table class="form-table">
60
  <tr>
61
- <th valign="top">Page Cache:</th>
62
- <td>
63
- <input type="hidden" name="pgcache.enabled" value="0" />
64
- <label><input class="enabled" type="checkbox" name="pgcache.enabled" value="1"<?php checked($pgcache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
65
- <br /><span class="description">Caching pages will reduce the response time of your site and increase the scale of your web server.</span>
66
- </td>
67
- </tr>
68
- <tr>
69
- <th valign="top">Page Cache Method:</th>
70
- <td>
71
- <select name="pgcache.engine">
72
- <optgroup label="Shared Server (disk enhanced is best):">
73
- <option value="file_pgcache"<?php selected($this->_config->get_string('pgcache.engine'), 'file_pgcache'); ?>>Disk (enhanced)</option>
74
- <option value="file"<?php selected($this->_config->get_string('pgcache.engine'), 'file'); ?>>Disk (basic)</option>
75
- </optgroup>
76
- <optgroup label="Dedicated / Virtual Server:">
77
- <option value="apc"<?php selected($this->_config->get_string('pgcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
78
- <option value="eaccelerator"<?php selected($this->_config->get_string('pgcache.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
79
- <option value="xcache"<?php selected($this->_config->get_string('pgcache.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
80
- </optgroup>
81
- <optgroup label="Multiple Servers:">
82
- <option value="memcached"<?php selected($this->_config->get_string('pgcache.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
83
- </optgroup>
84
- </select>
85
- </td>
 
86
  </tr>
87
  </table>
88
 
89
  <p class="submit">
90
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
 
91
  </p>
92
- </fieldset>
93
-
94
- <fieldset>
95
- <legend>
96
- <?php if (W3TC_PHP5): ?>
97
- <a href="admin.php?page=w3tc_minify">Minify</a>
98
- <?php else: ?>
99
- Minify
100
- <?php endif; ?>
101
- </legend>
102
 
103
- <p>Reduce load time by decreasing the size and number of <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files. Automatically remove unncessary data from <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym>, feed, page and post <acronym title="Hypertext Markup Language">HTML</acronym>.</p>
 
104
 
105
  <table class="form-table">
106
  <tr>
107
- <th valign="top">Minify:</th>
108
- <td>
109
- <input type="hidden" name="minify.enabled" value="0"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?> />
110
- <label><input class="enabled" type="checkbox" name="minify.enabled" value="1"<?php checked($minify_enabled, true); ?><?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?> />&nbsp;<strong>Enable</strong></label>
111
- <br /><span class="description">Minification can decrease file size of <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> and feeds respectively by ~10% on average.</span>
112
- </td>
113
- </tr>
114
- <tr>
115
- <th valign="top">Minify Cache Method:</th>
116
- <td>
117
- <select name="minify.engine"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?>>
118
- <optgroup label="Shared Server (disk is best):">
119
- <option value="file"<?php selected($this->_config->get_string('minify.engine'), 'file'); ?>>Disk</option>
120
- </optgroup>
121
- <optgroup label="Dedicated / Virtual Server:">
122
- <option value="apc"<?php selected($this->_config->get_string('minify.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
123
- <option value="eaccelerator"<?php selected($this->_config->get_string('minify.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
124
- <option value="xcache"<?php selected($this->_config->get_string('minify.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
125
- </optgroup>
126
- <optgroup label="Multiple Servers:">
127
- <option value="memcached"<?php selected($this->_config->get_string('minify.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
128
- </optgroup>
129
- </select>
130
- </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  </tr>
132
  </table>
133
 
134
  <p class="submit">
135
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
 
136
  </p>
137
- </fieldset>
138
-
139
- <fieldset>
140
- <legend><a href="admin.php?page=w3tc_dbcache">Database Cache</a></legend>
141
 
 
142
  <p>Enable database caching to reduce post, page and feed creation time.</p>
143
 
144
  <table class="form-table">
145
- <tr>
146
- <th valign="top">Database Cache:</th>
147
- <td>
148
- <input type="hidden" name="dbcache.enabled" value="0" />
149
- <label><input class="enabled" type="checkbox" name="dbcache.enabled" value="1"<?php checked($dbcache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
150
- <br /><span class="description">Caching database objects decreases the response time of your site. Best used if object caching is not possible.</span>
151
- </td>
152
- </tr>
153
- <tr>
154
- <th valign="top">Database Cache Method:</th>
155
- <td>
156
- <select name="dbcache.engine">
157
- <optgroup label="Shared Server:">
158
- <option value="file"<?php selected($this->_config->get_string('dbcache.engine'), 'file'); ?>>Disk</option>
159
- </optgroup>
160
- <optgroup label="Dedicated / Virtual Server:">
161
- <option value="apc"<?php selected($this->_config->get_string('dbcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
162
- <option value="eaccelerator"<?php selected($this->_config->get_string('dbcache.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
163
- <option value="xcache"<?php selected($this->_config->get_string('dbcache.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
164
- </optgroup>
165
- <optgroup label="Multiple Servers:">
166
- <option value="memcached"<?php selected($this->_config->get_string('dbcache.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
167
- </optgroup>
168
- </select>
169
- </td>
170
- </tr>
 
171
  </table>
172
 
173
  <p class="submit">
174
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
 
175
  </p>
176
- </fieldset>
177
-
178
-
179
- <fieldset>
180
- <legend><a href="admin.php?page=w3tc_objectcache">Object Cache</a></legend>
181
 
 
182
  <p>Enable object caching to further reduce execution time for common operations.</p>
183
 
184
- <table class="form-table">
185
- <tr>
186
- <th valign="top">Object Cache:</th>
187
- <td>
188
- <input type="hidden" name="objectcache.enabled" value="0" />
189
- <label><input class="enabled" type="checkbox" name="objectcache.enabled" value="1"<?php checked($objectcache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
190
- <br /><span class="description">Object caching greatly increases performance for highly dynamic sites (that use the Object Cache <acronym title="Application Programming Interface">API</acronym>).</span>
191
- </td>
192
- </tr>
193
- <tr>
194
- <th valign="top">Object Cache Method:</th>
195
- <td>
196
- <select name="objectcache.engine">
197
- <optgroup label="Shared Server:">
198
- <option value="file"<?php selected($this->_config->get_string('objectcache.engine'), 'file'); ?>>Disk</option>
199
- </optgroup>
200
- <optgroup label="Dedicated / Virtual Server:">
201
- <option value="apc"<?php selected($this->_config->get_string('objectcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
202
- <option value="eaccelerator"<?php selected($this->_config->get_string('objectcache.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
203
- <option value="xcache"<?php selected($this->_config->get_string('objectcache.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
204
- </optgroup>
205
- <optgroup label="Multiple Servers:">
206
- <option value="memcached"<?php selected($this->_config->get_string('objectcache.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
207
- </optgroup>
208
- </select>
209
- </td>
210
- </tr>
 
211
  </table>
212
 
213
  <p class="submit">
214
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
 
215
  </p>
216
- </fieldset>
217
 
218
- <fieldset>
219
- <legend><a href="admin.php?page=w3tc_cdn">Content Delivery Network</a></legend>
 
 
 
 
220
 
221
- <p>Host static files with your content delivery network provider to reduce page load time.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
 
 
 
 
 
 
 
223
  <table class="form-table">
224
  <tr>
225
- <th><acronym title="Content Delivery Network">CDN</acronym>:</th>
226
- <td>
227
- <input type="hidden" name="cdn.enabled" value="0" />
228
- <label><input class="enabled" type="checkbox" name="cdn.enabled" value="1"<?php checked($cdn_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
229
- <br /><span class="description">Theme files, media library attachments, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> files etc will appear to load instantly for site visitors.</span>
230
- </td>
231
- </tr>
232
- <tr>
233
- <th><acronym title="Content Delivery Network">CDN</acronym> Type:</th>
234
- <td>
235
- <select name="cdn.engine">
236
- <optgroup label="Origin Pull (mirror is best):">
237
- <option value="mirror"<?php selected($this->_config->get_string('cdn.engine'), 'mirror'); ?>>Mirror</option>
238
- <option value="netdna"<?php selected($this->_config->get_string('cdn.engine'), 'netdna'); ?>>Mirror: NetDNA / MaxCDN</option>
239
- </optgroup>
240
- <optgroup label="Origin Push:">
241
- <option value="rscf"<?php selected($this->_config->get_string('cdn.engine'), 'rscf'); ?><?php if (! W3TC_PHP5 || ! $check_curl): ?> disabled="disabled"<?php endif; ?>>Rackspace Cloud Files</option>
242
- <option value="cf"<?php selected($this->_config->get_string('cdn.engine'), 'cf'); ?><?php if (! W3TC_PHP5 || ! $check_curl): ?> disabled="disabled"<?php endif; ?>>Amazon CloudFront</option>
243
- <option value="s3"<?php selected($this->_config->get_string('cdn.engine'), 's3'); ?><?php if (! W3TC_PHP5 || ! $check_curl): ?> disabled="disabled"<?php endif; ?>>Amazon Simple Storage Service (S3)</option>
244
- <option value="ftp"<?php selected($this->_config->get_string('cdn.engine'), 'ftp'); ?><?php if (! $check_ftp): ?> disabled="disabled"<?php endif; ?>>Self-hosted / File Transfer Protocol Upload</option>
245
- </optgroup>
246
- </select><br />
247
- <span class="description">Select the <acronym title="Content Delivery Network">CDN</acronym> type you wish to use.</span>
248
- </td>
249
  </tr>
250
  </table>
251
 
252
  <p class="submit">
253
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
254
  </p>
255
- </fieldset>
256
 
257
- <fieldset>
258
- <legend><a href="admin.php?page=w3tc_browsercache">Browser Cache</a></legend>
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  <p>Reduce server load and decrease response time by using the cache available in site visitor's web browser.</p>
261
 
262
  <table class="form-table">
263
- <tr>
264
- <th valign="top">Browser Cache:</th>
265
- <td>
266
- <input type="hidden" name="browsercache.enabled" value="0" />
267
- <label><input class="enabled" type="checkbox" name="browsercache.enabled" value="1"<?php checked($browsercache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
268
- <br /><span class="description">Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression and add headers to reduce server load and decrease file load time.</span>
269
- </td>
270
- </tr>
271
  </table>
272
 
273
  <p class="submit">
274
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  </p>
276
- </fieldset>
277
-
278
- <fieldset>
279
- <legend>Support Us</legend>
280
-
281
- <p>We're working to make WordPress better. Please support us, here's how:</p>
282
-
283
- <p>
284
- <label>Link to us in your
285
- <select name="common.support">
286
- <option value="">select one</option>
287
- <?php foreach ($supports as $support_id => $support_name): ?>
288
- <option value="<?php echo $support_id; ?>"<?php selected($support, $support_id); ?>><?php echo htmlspecialchars($support_name); ?></option>
289
- <?php endforeach; ?>
290
- </select>
291
- </label>, tell your friends with a <input type="button" class="button button-tweet" value="tweet" /> and give us a perfect <input type="button" class="button button-rating" value="rating" />.
292
- </p>
293
 
294
  <p>If you want to manually place a link, here is the code:</p>
295
  <p><textarea cols="80" rows="4">Performance Optimization &lt;a href=&quot;http://www.w3-edge.com/wordpress-plugins/&quot; rel=&quot;external&quot;&gt;WordPress Plugins&lt;/a&gt; by W3 EDGE</textarea></p>
296
 
297
  <p class="submit">
298
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
299
  </p>
300
- </fieldset>
301
-
302
- <fieldset>
303
- <legend>Debug</legend>
304
 
 
305
  <p>Detailed information about each cache will be appended in (publicly available) <acronym title="Hypertext Markup Language">HTML</acronym> comments in the page's source code. Performance in this mode will not be optimal, use sparingly and disable when not in use.</p>
306
 
307
  <table class="form-table">
308
- <tr>
309
- <th valign="top">Debug Mode:</th>
310
- <td>
311
- <label><input type="checkbox" name="debug[]" value="pgcache"<?php checked($this->_config->get_boolean('pgcache.debug'), true); ?> /> Page Cache</label><br />
312
- <label><input type="checkbox" name="debug[]" value="minify"<?php checked($this->_config->get_boolean('minify.debug'), true); ?> /> Minify</label><br />
313
- <label><input type="checkbox" name="debug[]" value="dbcache"<?php checked($this->_config->get_boolean('dbcache.debug'), true); ?> /> Database Cache</label><br />
314
- <label><input type="checkbox" name="debug[]" value="objectcache"<?php checked($this->_config->get_boolean('objectcache.debug'), true); ?> /> Object Cache</label><br />
315
- <label><input type="checkbox" name="debug[]" value="cdn"<?php checked($this->_config->get_boolean('cdn.debug'), true); ?> /> Content Delivery Network</label><br />
316
- <span class="description">If selected, detailed caching information will be appear at the end of each page in a <acronym title="Hypertext Markup Language">HTML</acronym> comment. View a page's source code to review.</span>
317
- </td>
318
- </tr>
 
 
 
 
 
 
 
319
  </table>
320
 
321
  <p class="submit">
322
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
323
  </p>
324
- </fieldset>
325
-
326
- <fieldset>
327
- <legend>Miscellaneous</legend>
328
-
329
- <p>
330
- <input type="hidden" name="widget.latest.enabled" value="0" />
331
- <label><input type="checkbox" name="widget.latest.enabled" value="1"<?php checked($this->_config->get_boolean('widget.latest.enabled'), true); ?> /> Enable dashboard news widget</label>
332
- <br /><span class="description">Display latest tweets and support tips on the WordPress Dashboard.</span>
333
- </p>
334
-
335
- <p>
336
- <input type="hidden" name="file_locking" value="0"<?php if (! $can_empty_file): ?> disabled="disabled"<?php endif; ?> />
337
- <label><input type="checkbox" name="file_locking" value="1"<?php checked($file_locking, true); ?><?php if (! $can_empty_file): ?> disabled="disabled"<?php endif; ?> /> Enable file locking</label>
338
- <br /><span class="description">Not recommended for network-based file systems.</span>
339
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  <p class="submit">
342
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
343
  </p>
344
- </fieldset>
 
345
  </form>
346
 
347
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post" enctype="multipart/form-data">
348
- <fieldset>
349
- <legend>Import / Export Settings</legend>
350
-
351
  <table class="form-table">
352
  <tr>
353
- <th>Import configuration:</th>
354
- <td>
355
- <input type="file" name="config_file" />
356
- <input type="submit" name="config_import" class="button" value="Upload" />
357
- <br /><span class="description">Upload and replace the settings file on the server.</span>
358
- </td>
359
  </tr>
360
  <tr>
361
- <th>Export configuration:</th>
362
- <td>
363
- <input type="submit" name="config_export" class="button" value="Download" />
364
- <br /><span class="description">Download the settings file from the server.</span>
365
- </td>
366
  </tr>
367
  <tr>
368
- <th>Reset configuration:</th>
369
- <td>
370
- <input type="submit" name="config_reset" class="button" value="Restore Default Settings" />
371
- <br /><span class="description">Revert all settings to the defaults. Any settings staged in preview mode will not be modified.</span>
372
- </td>
373
  </tr>
374
- </table>
375
- </fieldset>
 
376
  </form>
377
 
378
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
17
  </form>
18
 
19
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
20
+ <div class="metabox-holder">
21
+ <?php echo $this->postbox_header('General'); ?>
 
22
  <table class="form-table">
23
+ <tr>
24
+ <th colspan="2">
25
+ <label>
26
+ <input id="enabled" type="checkbox" name="enabled" value="1"<?php checked($enabled_checkbox, true); ?> />
27
+ Toggle all caching types on or off at once.
28
+ </label>
29
+ </th>
30
+ </tr>
31
+ <tr>
32
+ <th>Preview Mode:</th>
33
+ <td>
34
+ <?php if ($preview): ?>
35
+ <input type="hidden" name="preview" value="0" />
36
+ <input type="submit" name="preview_save" class="button-primary" value="Disable" />
37
+ <?php echo $this->button_link('Preview', w3_get_home_url() . '/?w3tc_preview=1', true); ?>
38
+ <?php echo $this->button_link('Deploy', sprintf('admin.php?page=%s&preview_deploy', $this->_page)); ?>
39
+ <?php else: ?>
40
+ <input type="hidden" name="preview" value="1" />
41
+ <input type="submit" name="preview_save" class="button-primary" value="Enable" />
42
+ <?php endif; ?>
43
+ <br /><span class="description">Use preview mode to test configuration scenarios prior to releasing them (deploy) on the actual site.</span>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+
48
  <p class="submit">
49
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
50
  </p>
51
+ <?php echo $this->postbox_footer(); ?>
 
 
 
52
 
53
+ <?php echo $this->postbox_header('Page Cache'); ?>
54
+ <p>Enable page caching to decrease the response time of your site.</p>
55
 
56
  <table class="form-table">
57
  <tr>
58
+ <th>Page Cache:</th>
59
+ <td>
60
+ <input type="hidden" name="pgcache.enabled" value="0" />
61
+ <label><input class="enabled" type="checkbox" name="pgcache.enabled" value="1"<?php checked($pgcache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
62
+ <br /><span class="description">Caching pages will reduce the response time of your site and increase the scale of your web server.</span>
63
+ </td>
64
+ </tr>
65
+ <tr>
66
+ <th>Page Cache Method:</th>
67
+ <td>
68
+ <select name="pgcache.engine">
69
+ <optgroup label="Shared Server (disk enhanced is best):">
70
+ <option value="file_pgcache"<?php selected($this->_config->get_string('pgcache.engine'), 'file_pgcache'); ?><?php if (! $check_rules): ?> disabled="disabled"<?php endif; ?>>Disk (enhanced)</option>
71
+ <option value="file"<?php selected($this->_config->get_string('pgcache.engine'), 'file'); ?>>Disk (basic)</option>
72
+ </optgroup>
73
+ <optgroup label="Dedicated / Virtual Server:">
74
+ <option value="apc"<?php selected($this->_config->get_string('pgcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
75
+ <option value="eaccelerator"<?php selected($this->_config->get_string('pgcache.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
76
+ <option value="xcache"<?php selected($this->_config->get_string('pgcache.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
77
+ <option value="wincache"<?php selected($this->_config->get_string('pgcache.engine'), 'wincache'); ?><?php if (! $check_wincache): ?> disabled="disabled"<?php endif; ?>>Opcode: WinCache</option>
78
+ </optgroup>
79
+ <optgroup label="Multiple Servers:">
80
+ <option value="memcached"<?php selected($this->_config->get_string('pgcache.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
81
+ </optgroup>
82
+ </select>
83
+ </td>
84
  </tr>
85
  </table>
86
 
87
  <p class="submit">
88
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
89
+ <input type="submit" name="flush_pgcache" value="Empty cache"<?php if (! $pgcache_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
90
  </p>
91
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
92
 
93
+ <?php echo $this->postbox_header('Minify'); ?>
94
+ <p>Reduce load time by decreasing the size and number of <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files. Automatically remove unncessary data from <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym>, feed, page and post <acronym title="Hypertext Markup Language">HTML</acronym>.</p>
95
 
96
  <table class="form-table">
97
  <tr>
98
+ <th>Minify:</th>
99
+ <td>
100
+ <input type="hidden" name="minify.enabled" value="0"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?> />
101
+ <label><input class="enabled" type="checkbox" name="minify.enabled" value="1"<?php checked($minify_enabled, true); ?><?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?> />&nbsp;<strong>Enable</strong></label>
102
+ <br /><span class="description">Minification can decrease file size of <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> and feeds respectively by ~10% on average.</span>
103
+ </td>
104
+ </tr>
105
+ <tr>
106
+ <th>Minify mode:</th>
107
+ <td>
108
+ <label><input type="radio" name="minify.auto" value="1"<?php checked($this->_config->get_boolean('minify.auto'), true); ?><?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?> /> Auto</label>
109
+ <label><input type="radio" name="minify.auto" value="0"<?php checked($this->_config->get_boolean('minify.auto'), false); ?><?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?> /> Manual</label>
110
+ <br /><span class="description">Select manual mode to use fields on the minify settings tab to specify files to be minified, otherwise files will be minified automatically, but will not use the <acronym title="Content Delivery Network">CDN</acronym>.</span>
111
+ </td>
112
+ </tr>
113
+ <tr>
114
+ <th>Minify Cache Method:</th>
115
+ <td>
116
+ <select name="minify.engine"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?>>
117
+ <optgroup label="Shared Server (disk is best):">
118
+ <option value="file"<?php selected($this->_config->get_string('minify.engine'), 'file'); ?>>Disk</option>
119
+ </optgroup>
120
+ <optgroup label="Dedicated / Virtual Server:">
121
+ <option value="apc"<?php selected($this->_config->get_string('minify.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
122
+ <option value="eaccelerator"<?php selected($this->_config->get_string('minify.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
123
+ <option value="xcache"<?php selected($this->_config->get_string('minify.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
124
+ <option value="wincache"<?php selected($this->_config->get_string('minify.engine'), 'wincache'); ?><?php if (! $check_wincache): ?> disabled="disabled"<?php endif; ?>>Opcode: WinCache</option>
125
+ </optgroup>
126
+ <optgroup label="Multiple Servers:">
127
+ <option value="memcached"<?php selected($this->_config->get_string('minify.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
128
+ </optgroup>
129
+ </select>
130
+ </td>
131
+ </tr>
132
+ <tr>
133
+ <th><acronym title="Hypertext Markup Language">HTML</acronym> minifier:</th>
134
+ <td>
135
+ <select name="minify.html.engine"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?>>
136
+ <option value="html"<?php selected($this->_config->get_string('minify.html.engine'), 'html'); ?>>Default</option>
137
+ <option value="htmltidy"<?php selected($this->_config->get_string('minify.html.engine'), 'htmltidy'); ?><?php if (! $check_tidy): ?> disabled="disabled"<?php endif; ?>>HTML Tidy</option>
138
+ </select>
139
+ </td>
140
+ </tr>
141
+ <tr>
142
+ <th><acronym title="JavaScript">JS</acronym> minifier:</th>
143
+ <td>
144
+ <select name="minify.js.engine"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?>>
145
+ <option value="js"<?php selected($this->_config->get_string('minify.js.engine'), 'js'); ?>>JSMin (default)</option>
146
+ <option value="yuijs"<?php selected($this->_config->get_string('minify.js.engine'), 'yuijs'); ?>>YUI Compressor</option>
147
+ <option value="ccjs"<?php selected($this->_config->get_string('minify.js.engine'), 'ccjs'); ?>>Closure Compiler</option>
148
+ </select>
149
+ </td>
150
+ </tr>
151
+ <tr>
152
+ <th><acronym title="Cascading Style Sheets">CSS</acronym> minifier:</th>
153
+ <td>
154
+ <select name="minify.css.engine"<?php if (! W3TC_PHP5): ?> disabled="disabled"<?php endif; ?>>
155
+ <option value="css"<?php selected($this->_config->get_string('minify.css.engine'), 'css'); ?>>Default</option>
156
+ <option value="yuicss"<?php selected($this->_config->get_string('minify.css.engine'), 'yuicss'); ?>>YUI Compressor</option>
157
+ <option value="csstidy"<?php selected($this->_config->get_string('minify.css.engine'), 'csstidy'); ?>>CSS Tidy</option>
158
+ </select>
159
+ </td>
160
  </tr>
161
  </table>
162
 
163
  <p class="submit">
164
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
165
+ <input type="submit" name="flush_minify" value="Empty cache"<?php if (! $minify_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
166
  </p>
167
+ <?php echo $this->postbox_footer(); ?>
 
 
 
168
 
169
+ <?php echo $this->postbox_header('Database Cache'); ?>
170
  <p>Enable database caching to reduce post, page and feed creation time.</p>
171
 
172
  <table class="form-table">
173
+ <tr>
174
+ <th>Database Cache:</th>
175
+ <td>
176
+ <input type="hidden" name="dbcache.enabled" value="0" />
177
+ <label><input class="enabled" type="checkbox" name="dbcache.enabled" value="1"<?php checked($dbcache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
178
+ <br /><span class="description">Caching database objects decreases the response time of your site. Best used if object caching is not possible.</span>
179
+ </td>
180
+ </tr>
181
+ <tr>
182
+ <th>Database Cache Method:</th>
183
+ <td>
184
+ <select name="dbcache.engine">
185
+ <optgroup label="Shared Server:">
186
+ <option value="file"<?php selected($this->_config->get_string('dbcache.engine'), 'file'); ?>>Disk</option>
187
+ </optgroup>
188
+ <optgroup label="Dedicated / Virtual Server:">
189
+ <option value="apc"<?php selected($this->_config->get_string('dbcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
190
+ <option value="eaccelerator"<?php selected($this->_config->get_string('dbcache.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
191
+ <option value="xcache"<?php selected($this->_config->get_string('dbcache.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
192
+ <option value="wincache"<?php selected($this->_config->get_string('dbcache.engine'), 'wincache'); ?><?php if (! $check_wincache): ?> disabled="disabled"<?php endif; ?>>Opcode: WinCache</option>
193
+ </optgroup>
194
+ <optgroup label="Multiple Servers:">
195
+ <option value="memcached"<?php selected($this->_config->get_string('dbcache.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
196
+ </optgroup>
197
+ </select>
198
+ </td>
199
+ </tr>
200
  </table>
201
 
202
  <p class="submit">
203
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
204
+ <input type="submit" name="flush_dbcache" value="Empty cache"<?php if (! $dbcache_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
205
  </p>
206
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
207
 
208
+ <?php echo $this->postbox_header('Object Cache'); ?>
209
  <p>Enable object caching to further reduce execution time for common operations.</p>
210
 
211
+ <table class="form-table">
212
+ <tr>
213
+ <th>Object Cache:</th>
214
+ <td>
215
+ <input type="hidden" name="objectcache.enabled" value="0" />
216
+ <label><input class="enabled" type="checkbox" name="objectcache.enabled" value="1"<?php checked($objectcache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
217
+ <br /><span class="description">Object caching greatly increases performance for highly dynamic sites (that use the Object Cache <acronym title="Application Programming Interface">API</acronym>).</span>
218
+ </td>
219
+ </tr>
220
+ <tr>
221
+ <th>Object Cache Method:</th>
222
+ <td>
223
+ <select name="objectcache.engine">
224
+ <optgroup label="Shared Server:">
225
+ <option value="file"<?php selected($this->_config->get_string('objectcache.engine'), 'file'); ?>>Disk</option>
226
+ </optgroup>
227
+ <optgroup label="Dedicated / Virtual Server:">
228
+ <option value="apc"<?php selected($this->_config->get_string('objectcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?>>Opcode: Alternative PHP Cache (APC)</option>
229
+ <option value="eaccelerator"<?php selected($this->_config->get_string('objectcache.engine'), 'eaccelerator'); ?><?php if (! $check_eaccelerator): ?> disabled="disabled"<?php endif; ?>>Opcode: eAccelerator</option>
230
+ <option value="xcache"<?php selected($this->_config->get_string('objectcache.engine'), 'xcache'); ?><?php if (! $check_xcache): ?> disabled="disabled"<?php endif; ?>>Opcode: XCache</option>
231
+ <option value="wincache"<?php selected($this->_config->get_string('objectcache.engine'), 'wincache'); ?><?php if (! $check_wincache): ?> disabled="disabled"<?php endif; ?>>Opcode: WinCache</option>
232
+ </optgroup>
233
+ <optgroup label="Multiple Servers:">
234
+ <option value="memcached"<?php selected($this->_config->get_string('objectcache.engine'), 'memcached'); ?><?php if (! $check_memcached): ?> disabled="disabled"<?php endif; ?>>Memcached</option>
235
+ </optgroup>
236
+ </select>
237
+ </td>
238
+ </tr>
239
  </table>
240
 
241
  <p class="submit">
242
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
243
+ <input type="submit" name="flush_objectcache" value="Empty cache"<?php if (! $objectcache_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
244
  </p>
245
+ <?php echo $this->postbox_footer(); ?>
246
 
247
+ <?php echo $this->postbox_header('Network Performance &amp; Security powered by CloudFlare'); ?>
248
+ <p>
249
+ CloudFlare protects and accelerates websites. <a href="https://www.cloudflare.com/sign-up.html?affiliate=w3edge&amp;seed_domain=<?php echo w3_get_host(); ?>&amp;email=<?php echo htmlspecialchars($cloudflare_signup_email); ?>&amp;username=<?php echo htmlspecialchars($cloudflare_signup_user); ?>" target="_blank">Sign up now for free</a> to get started,
250
+ or if you have an account simply log in to obtain your <acronym title="Application Programming Interface">API</acronym> key from the <a href="https://www.cloudflare.com/my-account.html">Account Page</a> to enter it below.
251
+ Contact the CloudFlare <a href="http://www.cloudflare.com/help.html" target="_blank">support team</a> with any questions.
252
+ </p>
253
 
254
+ <table class="form-table">
255
+ <tr>
256
+ <th>CloudFlare:</th>
257
+ <td>
258
+ <input type="hidden" name="cloudflare.enabled" value="0" />
259
+ <label><input class="enabled" type="checkbox" name="cloudflare.enabled" value="1"<?php checked($cloudflare_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
260
+ </td>
261
+ </tr>
262
+ <tr>
263
+ <th><label for="cloudflare_email">CloudFlare account email:</label></th>
264
+ <td>
265
+ <input id="cloudflare_email" class="w3tc-ignore-change" type="text" name="cloudflare.email" value="<?php echo htmlspecialchars($this->_config->get_string('cloudflare.email')); ?>" size="60" />
266
+ </td>
267
+ </tr>
268
+ <tr>
269
+ <th><label for="cloudflare_key"><acronym title="Application Programming Interface">API</acronym> key:</label></th>
270
+ <td>
271
+ <input id="cloudflare_key" class="w3tc-ignore-change" type="password" name="cloudflare.key" value="<?php echo htmlspecialchars($this->_config->get_string('cloudflare.key')); ?>" size="60" /> (<a href="https://www.cloudflare.com/my-account.html">find it here</a>)
272
+ </td>
273
+ </tr>
274
+ <tr>
275
+ <th>Domain:</th>
276
+ <td>
277
+ <input id="cloudflare_zone" type="text" name="cloudflare.zone" value="<?php echo htmlspecialchars($this->_config->get_string('cloudflare.zone', w3_get_host())); ?>" size="40" />
278
+ </td>
279
+ </tr>
280
+ <tr>
281
+ <th>Security level:</th>
282
+ <td>
283
+ <input type="hidden" name="cloudflare_seclvl_old" value="<?php echo $cloudflare_seclvl; ?>" />
284
+ <select name="cloudflare_seclvl_new" class="w3tc-ignore-change">
285
+ <?php foreach ($cloudflare_seclvls as $cloudflare_seclvl_key => $cloudflare_seclvl_label): ?>
286
+ <option value="<?php echo $cloudflare_seclvl_key; ?>"<?php selected($cloudflare_seclvl, $cloudflare_seclvl_key); ?>><?php echo $cloudflare_seclvl_label; ?></option>
287
+ <?php endforeach; ?>
288
+ </select>
289
+ </td>
290
+ </tr>
291
+ <tr>
292
+ <th>Development mode:</th>
293
+ <td>
294
+ <input type="hidden" name="cloudflare_devmode_old" value="<?php echo $cloudflare_devmode; ?>" />
295
+ <select name="cloudflare_devmode_new" class="w3tc-ignore-change">
296
+ <?php foreach ($cloudflare_devmodes as $cloudflare_devmode_key => $cloudflare_devmode_label): ?>
297
+ <option value="<?php echo $cloudflare_devmode_key; ?>"<?php selected($cloudflare_devmode, $cloudflare_devmode_key); ?>><?php echo $cloudflare_devmode_label; ?></option>
298
+ <?php endforeach; ?>
299
+ </select>
300
+ <?php if ($cloudflare_devmode_expire): ?>
301
+ Will automatically turn off at <?php echo date('m/d/Y H:i:s', $cloudflare_devmode_expire); ?>
302
+ <?php endif; ?>
303
+ </td>
304
+ </tr>
305
+ </table>
306
 
307
+ <p class="submit">
308
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
309
+ <input id="cloudflare_purge_cache" type="button" value="Purge cache"<?php if (! $cloudflare_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
310
+ </p>
311
+ <?php echo $this->postbox_footer(); ?>
312
+
313
+ <?php echo $this->postbox_header('Varnish'); ?>
314
  <table class="form-table">
315
  <tr>
316
+ <th colspan="2">
317
+ <input type="hidden" name="varnish.enabled" value="0" />
318
+ <label><input class="enabled" type="checkbox" name="varnish.enabled" value="1"<?php checked($varnish_enabled, true); ?> /> Enable varnish cache purging</label><br />
319
+ </th>
320
+ </tr>
321
+ <tr>
322
+ <th><label for="pgcache_varnish_servers">Varnish servers:</label></th>
323
+ <td>
324
+ <textarea id="pgcache_varnish_servers" name="varnish.servers" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('varnish.servers'))); ?></textarea><br />
325
+ <span class="description">Specify the IP addresses of your varnish instances above. Your <acronym title="Varnish Configuration Language">VCL</acronym>'s <acronym title="Access Control List">ACL</acronym> must allow this request.</span>
326
+ </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  </tr>
328
  </table>
329
 
330
  <p class="submit">
331
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
332
  </p>
333
+ <?php echo $this->postbox_footer(); ?>
334
 
335
+ <?php echo $this->postbox_header('Content Delivery Network'); ?>
336
+ <p>Host static files with your content delivery network provider to reduce page load time.</p>
337
 
338
+ <table class="form-table">
339
+ <tr>
340
+ <th><acronym title="Content Delivery Network">CDN</acronym>:</th>
341
+ <td>
342
+ <input type="hidden" name="cdn.enabled" value="0" />
343
+ <label><input class="enabled" type="checkbox" name="cdn.enabled" value="1"<?php checked($cdn_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
344
+ <br /><span class="description">Theme files, media library attachments, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> files etc will appear to load instantly for site visitors.</span>
345
+ </td>
346
+ </tr>
347
+ <tr>
348
+ <th><acronym title="Content Delivery Network">CDN</acronym> Type:</th>
349
+ <td>
350
+ <select name="cdn.engine">
351
+ <optgroup label="Origin Pull (mirror is best):">
352
+ <option value="mirror"<?php selected($this->_config->get_string('cdn.engine'), 'mirror'); ?>>Mirror</option>
353
+ <option value="netdna"<?php selected($this->_config->get_string('cdn.engine'), 'netdna'); ?>>NetDNA / MaxCDN</option>
354
+ <option value="cotendo"<?php selected($this->_config->get_string('cdn.engine'), 'cotendo'); ?>>Cotendo</option>
355
+ <option value="cf2"<?php selected($this->_config->get_string('cdn.engine'), 'cf2'); ?><?php if (!W3TC_PHP5 || !$check_curl): ?> disabled="disabled"<?php endif; ?>>Amazon CloudFront</option>
356
+ </optgroup>
357
+ <optgroup label="Origin Push:">
358
+ <option value="rscf"<?php selected($this->_config->get_string('cdn.engine'), 'rscf'); ?><?php if (!W3TC_PHP5 || !$check_curl): ?> disabled="disabled"<?php endif; ?>>Rackspace Cloud Files</option>
359
+ <option value="cf"<?php selected($this->_config->get_string('cdn.engine'), 'cf'); ?><?php if (!W3TC_PHP5 || !$check_curl): ?> disabled="disabled"<?php endif; ?>>Amazon CloudFront</option>
360
+ <option value="s3"<?php selected($this->_config->get_string('cdn.engine'), 's3'); ?><?php if (!W3TC_PHP5 || !$check_curl): ?> disabled="disabled"<?php endif; ?>>Amazon Simple Storage Service (S3)</option>
361
+ <option value="azure"<?php selected($this->_config->get_string('cdn.engine'), 'azure'); ?><?php if (!W3TC_PHP5): ?> disabled="disabled"<?php endif; ?>>Microsoft Azure Storage</option>
362
+ <option value="ftp"<?php selected($this->_config->get_string('cdn.engine'), 'ftp'); ?><?php if (!$check_ftp): ?> disabled="disabled"<?php endif; ?>>Self-hosted / File Transfer Protocol Upload</option>
363
+ </optgroup>
364
+ </select><br />
365
+ <span class="description">Select the <acronym title="Content Delivery Network">CDN</acronym> type you wish to use.</span>
366
+ </td>
367
+ </tr>
368
+ </table>
369
+
370
+ <p class="submit">
371
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
372
+ <input id="cdn_purge" type="button" value="Purge cache"<?php if (!$cdn_enabled || !w3_can_cdn_purge($this->_config->get_string('cdn.engine'))): ?> disabled="disabled"<?php endif; ?> class="button" />
373
+ </p>
374
+ <?php echo $this->postbox_footer(); ?>
375
+
376
+ <?php echo $this->postbox_header('Browser Cache'); ?>
377
  <p>Reduce server load and decrease response time by using the cache available in site visitor's web browser.</p>
378
 
379
  <table class="form-table">
380
+ <tr>
381
+ <th>Browser Cache:</th>
382
+ <td>
383
+ <input type="hidden" name="browsercache.enabled" value="0" />
384
+ <label><input class="enabled" type="checkbox" name="browsercache.enabled" value="1"<?php checked($browsercache_enabled, true); ?> />&nbsp;<strong>Enable</strong></label>
385
+ <br /><span class="description">Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression and add headers to reduce server load and decrease file load time.</span>
386
+ </td>
387
+ </tr>
388
  </table>
389
 
390
  <p class="submit">
391
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
392
+ </p>
393
+ <?php echo $this->postbox_footer(); ?>
394
+
395
+ <?php echo $this->postbox_header('Support Us'); ?>
396
+ <p>We're working to make WordPress better. Please support us, here's how:</p>
397
+
398
+ <p>
399
+ <label>Link to us in your
400
+ <select name="common.support">
401
+ <option value="">select one</option>
402
+ <?php foreach ($supports as $support_id => $support_name): ?>
403
+ <option value="<?php echo $support_id; ?>"<?php selected($support, $support_id); ?>><?php echo htmlspecialchars($support_name); ?></option>
404
+ <?php endforeach; ?>
405
+ </select>
406
+ </label>, tell your friends with a <input type="button" class="button button-tweet" value="tweet" />
407
+ (<input type="hidden" name="common.tweeted" value="0" /><label><input type="checkbox" name="common.tweeted" value="1"<?php checked($this->_config->get_boolean('common.tweeted', true)); ?> /> I've tweeted</label>)
408
+ and give us a perfect <input type="button" class="button button-rating" value="rating" />.
409
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
 
411
  <p>If you want to manually place a link, here is the code:</p>
412
  <p><textarea cols="80" rows="4">Performance Optimization &lt;a href=&quot;http://www.w3-edge.com/wordpress-plugins/&quot; rel=&quot;external&quot;&gt;WordPress Plugins&lt;/a&gt; by W3 EDGE</textarea></p>
413
 
414
  <p class="submit">
415
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
416
  </p>
417
+ <?php echo $this->postbox_footer(); ?>
 
 
 
418
 
419
+ <?php echo $this->postbox_header('Debug'); ?>
420
  <p>Detailed information about each cache will be appended in (publicly available) <acronym title="Hypertext Markup Language">HTML</acronym> comments in the page's source code. Performance in this mode will not be optimal, use sparingly and disable when not in use.</p>
421
 
422
  <table class="form-table">
423
+ <tr>
424
+ <th>Debug Mode:</th>
425
+ <td>
426
+ <input type="hidden" name="pgcache.debug" value="0" />
427
+ <input type="hidden" name="minify.debug" value="0" />
428
+ <input type="hidden" name="dbcache.debug" value="0" />
429
+ <input type="hidden" name="objectcache.debug" value="0" />
430
+ <input type="hidden" name="cdn.debug" value="0" />
431
+ <input type="hidden" name="varnish.debug" value="0" />
432
+ <label><input type="checkbox" name="pgcache.debug" value="pgcache"<?php checked($this->_config->get_boolean('pgcache.debug'), true); ?> /> Page Cache</label><br />
433
+ <label><input type="checkbox" name="minify.debug" value="minify"<?php checked($this->_config->get_boolean('minify.debug'), true); ?> /> Minify</label><br />
434
+ <label><input type="checkbox" name="dbcache.debug" value="dbcache"<?php checked($this->_config->get_boolean('dbcache.debug'), true); ?> /> Database Cache</label><br />
435
+ <label><input type="checkbox" name="objectcache.debug" value="objectcache"<?php checked($this->_config->get_boolean('objectcache.debug'), true); ?> /> Object Cache</label><br />
436
+ <label><input type="checkbox" name="cdn.debug" value="cdn"<?php checked($this->_config->get_boolean('cdn.debug'), true); ?> /> Content Delivery Network</label><br />
437
+ <label><input type="checkbox" name="varnish.debug" value="varnish"<?php checked($this->_config->get_boolean('varnish.debug'), true); ?> /> Varnish</label><br />
438
+ <span class="description">If selected, detailed caching information will be appear at the end of each page in a <acronym title="Hypertext Markup Language">HTML</acronym> comment. View a page's source code to review.</span>
439
+ </td>
440
+ </tr>
441
  </table>
442
 
443
  <p class="submit">
444
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
445
  </p>
446
+ <?php echo $this->postbox_footer(); ?>
447
+
448
+ <?php echo $this->postbox_header('Miscellaneous'); ?>
449
+ <table class="form-table">
450
+ <?php if (w3_is_nginx()): ?>
451
+ <tr>
452
+ <th>Nginx server configuration file path</th>
453
+ <td>
454
+ <input type="text" name="config.path" value="<?php echo htmlspecialchars($this->_config->get_string('config.path')); ?>" size="80" />
455
+ <br /><span class="description">If empty the default path will be used..</span>
456
+ </td>
457
+ </tr>
458
+ <?php endif; ?>
459
+ <tr>
460
+ <th colspan="2">
461
+ <input type="hidden" name="config.check" value="0" />
462
+ <label><input type="checkbox" name="config.check" value="1"<?php checked($this->_config->get_boolean('config.check'), true); ?> /> Verify rewrite rules</label>
463
+ <br /><span class="description">Notify of server configuration errors, if this option is disabled, the server configuration for active settings can be found on the <a href="admin.php?page=w3tc_install">install</a> tab.</span>
464
+ </th>
465
+ </tr>
466
+ <tr>
467
+ <th colspan="2">
468
+ <input type="hidden" name="file_locking" value="0"<?php if (! $can_empty_file): ?> disabled="disabled"<?php endif; ?> />
469
+ <label><input type="checkbox" name="file_locking" value="1"<?php checked($file_locking, true); ?><?php if (! $can_empty_file): ?> disabled="disabled"<?php endif; ?> /> Enable file locking</label>
470
+ <br /><span class="description">Not recommended for "slow" network-based file systems.</span>
471
+ </th>
472
+ </tr>
473
+ <tr>
474
+ <th colspan="2">
475
+ <input type="hidden" name="widget.latest.enabled" value="0" />
476
+ <label><input type="checkbox" name="widget.latest.enabled" value="1"<?php checked($this->_config->get_boolean('widget.latest.enabled'), true); ?> /> Enable news dashboard widget</label>
477
+ <br /><span class="description">Display latest tweets and support tips on the WordPress dashboard.</span>
478
+ </th>
479
+ </tr>
480
+ <tr>
481
+ <th colspan="2">
482
+ <input type="hidden" name="widget.pagespeed.enabled" value="0" />
483
+ <label><input type="checkbox" name="widget.pagespeed.enabled" value="1"<?php checked($this->_config->get_boolean('widget.latest.enabled'), true); ?> /> Enable Google Page Speed dashboard widget</label>
484
+ <br /><span class="description">Display Google Page Speed results on the WordPress dashboard.</span>
485
+ </th>
486
+ </tr>
487
+ <tr>
488
+ <th><label for="widget_pagespeed_key">Page Speed <acronym title="Application Programming Interface">API</acronym> Key:</label></th>
489
+ <td>
490
+ <input id="widget_pagespeed_key" type="text" name="widget.pagespeed.key" value="<?php echo $this->_config->get_string('widget.pagespeed.key'); ?>" size="60" /><br />
491
+ <span class="description">To acquire an <acronym title="Application Programming Interface">API</acronym> key, visit the <a href="https://code.google.com/apis/console" target="_blank"><acronym title="Application Programming Interface">API</acronym>s Console</a>. Go to the Project Home tab, activate the Page Speed Online <acronym title="Application Programming Interface">API</acronym>, and accept the Terms of Service.
492
+ Then go to the <acronym title="Application Programming Interface">API</acronym> Access tab. The <acronym title="Application Programming Interface">API</acronym> key is in the Simple <acronym title="Application Programming Interface">API</acronym> Access section.</span>
493
+ </td>
494
+ </tr>
495
+ </table>
496
 
497
  <p class="submit">
498
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
499
  </p>
500
+ <?php echo $this->postbox_footer(); ?>
501
+ </div>
502
  </form>
503
 
504
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post" enctype="multipart/form-data">
505
+ <div class="metabox-holder">
506
+ <?php echo $this->postbox_header('Import / Export Settings'); ?>
 
507
  <table class="form-table">
508
  <tr>
509
+ <th>Import configuration:</th>
510
+ <td>
511
+ <input type="file" name="config_file" />
512
+ <input type="submit" name="config_import" class="button" value="Upload" />
513
+ <br /><span class="description">Upload and replace the active settings file.</span>
514
+ </td>
515
  </tr>
516
  <tr>
517
+ <th>Export configuration:</th>
518
+ <td>
519
+ <input type="submit" name="config_export" class="button" value="Download" />
520
+ <br /><span class="description">Download the active settings file.</span>
521
+ </td>
522
  </tr>
523
  <tr>
524
+ <th>Reset configuration:</th>
525
+ <td>
526
+ <input type="submit" name="config_reset" class="button" value="Restore Default Settings" />
527
+ <br /><span class="description">Revert all settings to the defaults. Any settings staged in preview mode will not be modified.</span>
528
+ </td>
529
  </tr>
530
+ </table>
531
+ <?php echo $this->postbox_footer(); ?>
532
+ </div>
533
  </form>
534
 
535
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/install.phtml CHANGED
@@ -21,32 +21,14 @@
21
 
22
  <hr />
23
 
24
- <?php if ($document_root_rules || $home_root_rules || $pgcache_rules || $minify_rules || $cdn_rules): ?>
25
  <h3>Rewrite rules</h3>
26
- <?php if ($document_root_rules): ?>
27
- <p><strong><?php echo htmlspecialchars($document_root_htaccess); ?>:</strong></p>
28
- <pre class="code"><?php echo htmlspecialchars($document_root_rules); ?></pre>
29
- <?php endif; ?>
30
-
31
- <?php if ($home_root_rules): ?>
32
- <p><strong><?php echo htmlspecialchars($home_root_htaccess); ?>:</strong></p>
33
- <pre class="code"><?php echo htmlspecialchars($home_root_rules); ?></pre>
34
- <?php endif; ?>
35
 
36
- <?php if ($pgcache_rules): ?>
37
- <p><strong><?php echo htmlspecialchars($pgcache_htaccess); ?>:</strong></p>
38
- <pre class="code"><?php echo htmlspecialchars($pgcache_rules); ?></pre>
39
- <?php endif; ?>
40
 
41
- <?php if ($minify_rules): ?>
42
- <p><strong><?php echo htmlspecialchars($minify_htaccess); ?>:</strong></p>
43
- <pre class="code"><?php echo htmlspecialchars($minify_rules); ?></pre>
44
- <?php endif; ?>
45
-
46
- <?php if ($cdn_rules): ?>
47
- <p><strong><?php echo htmlspecialchars($cdn_htaccess); ?>:</strong></p>
48
- <pre class="code"><?php echo htmlspecialchars($cdn_rules); ?></pre>
49
- <?php endif; ?>
50
  <hr />
51
  <?php endif; ?>
52
 
@@ -79,6 +61,10 @@
79
  Make sure ZLIB is fully installed:
80
  <pre class="console"># yum install zlib-devel</pre>
81
  </li>
 
 
 
 
82
  </ol>
83
 
84
  <hr />
@@ -160,12 +146,6 @@
160
  </li>
161
  </ol>
162
 
163
- <p>For windows users we recommend checking the following site(s) for more installation tips:</p>
164
-
165
- <ul>
166
- <li><a href="http://pureform.wordpress.com/2008/01/10/installing-memcache-on-windows-for-php/" target="_blank">Installing memcache on Windows for <acronym title="Hypertext Preprocessor">PHP</acronym></a></li>
167
- </ul>
168
-
169
  <hr />
170
 
171
  <p id="APC"><strong><acronym title="PHP Extension Community Library">PECL</acronym> Alternative PHP Cache (<acronym title="Alternative PHP Cache">APC</acronym>) Installation (Recommended):</strong><br /><em>Time required: 1 minute</em></p>
@@ -177,7 +157,7 @@
177
  </li>
178
  <li>
179
  Or via compilation. Download the <a href="http://pecl.php.net/package/APC" target="_blank">latest stable version</a> and extract:
180
- <pre class="console"># cd /usr/local/src &amp;&amp; wget <a href="http://pecl.php.net/get/APC-3.0.19.tgz" target="_blank">http://pecl.php.net/get/APC-3.0.19.tgz</a> &amp;&amp; tar -xzf APC-3.0.19.tgz &amp;&amp; cd APC-3.0.19</pre>
181
  </li>
182
  <li>
183
  Note the paths returned for the following commands:
@@ -204,12 +184,6 @@
204
  </li>
205
  </ol>
206
 
207
- <p>For windows users we recommend checking the following site(s) for more installation tips:</p>
208
-
209
- <ul>
210
- <li><a href="http://www.sitebuddy.com/PHP/Accelerators/apc_windows_binaries_builds" target="_blank"><acronym title="Alternative PHP Cache">APC</acronym> binaries for <acronym title="Hypertext Preprocessor">PHP</acronym> 5.x (windows builds)</a></li>
211
- </ul>
212
-
213
  <hr />
214
 
215
  <p id="XCache"><strong>XCache Installation:</strong><br /><em>Time required: 1 minute</em></p>
@@ -276,32 +250,26 @@
276
  </li>
277
  </ol>
278
 
279
- <p>For windows users we recommend checking the following site(s) for more installation tips:</p>
280
-
281
- <ul>
282
- <li><a href="http://www.sitebuddy.com/PHP/Accelerators/eAccelerator_windows_binaries_builds" target="_blank">eAccelerator binaries for <acronym title="Hypertext Preprocessor">PHP</acronym> 5.x (windows builds)</a></li>
283
- </ul>
284
-
285
  <hr />
286
 
287
- <fieldset>
288
- <legend>Note(s):</legend>
289
-
290
  <table class="form-table">
291
- <tr>
292
- <th valign="top" colspan="2">
293
- <ul>
294
- <li>The provided instructions are for 32-bit CentOS, however we can provide others based on <a href="mailto:wordpressexperts@w3-edge.com">your requests</a>.</li>
295
- <li>In the case where Apache is not used, the .htaccess file located in the root directory of the WordPress installation, wp-content/w3tc/pgcache/.htaccess and wp-content/w3tc/min/.htaccess contain directives that must be re-created for your web server software.</li>
296
- <li>Restarting the web server will empty the opcode cache, which means it will have to be rebuilt over time and your site's performance will suffer during this period. Still, an opcode cache should be installed in any case to maximize WordPress performance.</li>
297
- <li>Consider using memcached for objects that must persist across web server restarts or that you wish to share amongst your pool of servers (or cluster), e.g.: database objects or page cache.</li>
298
- <li>Some yum or mirrors may not have the necessary packages, in such cases you may have to do a manual installation.</li>
299
- </ul>
300
- </th>
301
- </tr>
 
302
  </table>
303
- </fieldset>
304
-
305
  </div>
306
 
307
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
21
 
22
  <hr />
23
 
24
+ <?php if (count($rewrite_rules)): ?>
25
  <h3>Rewrite rules</h3>
 
 
 
 
 
 
 
 
 
26
 
27
+ <?php foreach ($rewrite_rules as $path => $rules): ?>
28
+ <p><strong><?php echo htmlspecialchars($path); ?>:</strong></p>
29
+ <pre class="code"><?php echo htmlspecialchars($rules); ?></pre>
30
+ <?php endforeach; ?>
31
 
 
 
 
 
 
 
 
 
 
32
  <hr />
33
  <?php endif; ?>
34
 
61
  Make sure ZLIB is fully installed:
62
  <pre class="console"># yum install zlib-devel</pre>
63
  </li>
64
+ <li>
65
+ Make sure PCRE is fully installed:
66
+ <pre class="console"># yum install pcre-devel</pre>
67
+ </li>
68
  </ol>
69
 
70
  <hr />
146
  </li>
147
  </ol>
148
 
 
 
 
 
 
 
149
  <hr />
150
 
151
  <p id="APC"><strong><acronym title="PHP Extension Community Library">PECL</acronym> Alternative PHP Cache (<acronym title="Alternative PHP Cache">APC</acronym>) Installation (Recommended):</strong><br /><em>Time required: 1 minute</em></p>
157
  </li>
158
  <li>
159
  Or via compilation. Download the <a href="http://pecl.php.net/package/APC" target="_blank">latest stable version</a> and extract:
160
+ <pre class="console"># cd /usr/local/src &amp;&amp; wget <a href="http://pecl.php.net/get/APC-3.1.6.tgz" target="_blank">http://pecl.php.net/get/APC-3.1.6.tgz</a> &amp;&amp; tar -xzf APC-3.0.19.tgz &amp;&amp; cd APC-3.1.6</pre>
161
  </li>
162
  <li>
163
  Note the paths returned for the following commands:
184
  </li>
185
  </ol>
186
 
 
 
 
 
 
 
187
  <hr />
188
 
189
  <p id="XCache"><strong>XCache Installation:</strong><br /><em>Time required: 1 minute</em></p>
250
  </li>
251
  </ol>
252
 
 
 
 
 
 
 
253
  <hr />
254
 
255
+ <div class="metabox-holder">
256
+ <?php echo $this->postbox_header('Note(s):'); ?>
 
257
  <table class="form-table">
258
+ <tr>
259
+ <th colspan="2">
260
+ <ul>
261
+ <li>The provided instructions are for 32-bit CentOS, however we can provide others based on <a href="mailto:wordpressexperts@w3-edge.com">your requests</a>.</li>
262
+ <li>Best compatibility with <a href="http://www.iis.net/" target="_blank">IIS</a> is realized via <a href="http://www.microsoft.com/web/webmatrix/" target="_blank">WebMatrix</a>, which also includes the supported <a href="http://www.iis.net/download/wincacheforphp" target="_blank">WinCache</a> opcode cache.</li>
263
+ <li>In the case where Apache is not used, the .htaccess file located in the root directory of the WordPress installation, wp-content/w3tc/pgcache/.htaccess and wp-content/w3tc/min/.htaccess contain directives that must be manually created for your web server software.</li>
264
+ <li>Restarting the web server will empty the opcode cache, which means it will have to be rebuilt over time and your site's performance will suffer during this period. Still, an opcode cache should be installed in any case to maximize WordPress performance.</li>
265
+ <li>Consider using memcached for objects that must persist across web server restarts or that you wish to share amongst your pool of servers (or cluster), e.g.: database objects or page cache.</li>
266
+ <li>Some yum or mirrors may not have the necessary packages, in such cases you may have to do a manual installation.</li>
267
+ </ul>
268
+ </th>
269
+ </tr>
270
  </table>
271
+ <?php echo $this->postbox_footer(); ?>
272
+ </div>
273
  </div>
274
 
275
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/minify.phtml CHANGED
@@ -1,6 +1,6 @@
1
  <?php include W3TC_DIR . '/inc/options/common/header.phtml'; ?>
2
 
3
- <script type="text/javascript">/*<![CDATA[*/
4
  var minify_templates = {};
5
  <?php foreach ($templates as $theme_key => $theme_templates): ?>
6
  minify_templates['<?php echo addslashes($theme_key); ?>'] = {};
@@ -18,36 +18,37 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
18
  </p>
19
  <p>
20
  To rebuild the minify cache use the
 
21
  <input type="submit" name="flush_minify" value="empty cache"<?php if (! $minify_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
22
  operation.
 
23
  Get minify hints using the
24
  <input type="button" class="button button-minify-recommendations" value="help" />
25
  wizard.
26
- <input type="hidden" name="page" value="<?php echo $this->_page; ?>" />
27
  </p>
28
  </form>
29
 
30
  <form id="minify_form" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
31
- <fieldset>
32
- <legend>General</legend>
33
-
34
  <table class="form-table">
35
  <tr>
36
  <th colspan="2">
37
  <input type="hidden" name="minify.rewrite" value="0" />
38
- <label><input type="checkbox" name="minify.rewrite" value="1"<?php checked($this->_config->get_boolean('minify.rewrite'), true); ?> /> Rewrite <acronym title="Uniform Resource Locator">URL</acronym> structure</label><br />
39
  <span class="description">If disabled, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> embeddings will use GET variables instead of "fancy" links.</span>
40
  </th>
41
  </tr>
 
 
 
 
 
 
 
42
  <tr>
43
- <th colspan="2">
44
- <input type="hidden" name="minify.upload" value="0" />
45
- <label><input type="checkbox" name="minify.upload" value="1"<?php checked($this->_config->get_boolean('minify.upload'), true); ?> /> Automatically upload modified files</label><br />
46
- <span class="description">If <acronym title="Content Delivery Network">CDN</acronym> is enabled (and not using the origin pull method), your minified files will be automatically uploaded.</span>
47
- </th>
48
- </tr>
49
- <tr>
50
- <th valign="top">
51
  <label for="minify_error_notification">Minify error notification:</label>
52
  </th>
53
  <td>
@@ -64,66 +65,115 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
64
  </table>
65
 
66
  <p class="submit">
67
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
68
  </p>
69
- </fieldset>
70
-
71
- <fieldset>
72
- <legend><acronym title="Hypertext Markup Language">HTML</acronym></legend>
73
 
 
74
  <table class="form-table">
75
  <tr>
76
- <th valign="top"><acronym title="Hypertext Markup Language">HTML</acronym> minify settings:</th>
77
  <td>
78
  <input type="hidden" name="minify.html.enable" value="0" />
 
 
79
  <input type="hidden" name="minify.html.reject.feed" value="0" />
80
- <input type="hidden" name="minify.html.inline.css" value="0" />
81
- <input type="hidden" name="minify.html.inline.js" value="0" />
82
- <input type="hidden" name="minify.html.strip.crlf" value="0" />
83
  <label><input id="html_enabled" type="checkbox" name="minify.html.enable" value="1"<?php checked($this->_config->get_boolean('minify.html.enable'), true); ?> /> Enable</label><br />
 
 
84
  <label><input class="html_enabled" type="checkbox" name="minify.html.reject.feed" value="1"<?php checked($this->_config->get_boolean('minify.html.reject.feed'), true); ?> /> Don't minify feeds</label><br />
85
- <label><input class="html_enabled" type="checkbox" name="minify.html.inline.css" value="1"<?php checked($this->_config->get_boolean('minify.html.inline.css'), true); ?> /> Inline <acronym title="Cascading Style Sheet">CSS</acronym> minification</label><br />
86
- <label><input class="html_enabled" type="checkbox" name="minify.html.inline.js" value="1"<?php checked($this->_config->get_boolean('minify.html.inline.js'), true); ?> /> Inline <acronym title="JavaScript">JS</acronym> minification</label><br />
87
- <label><input class="html_enabled" type="checkbox" name="minify.html.strip.crlf" value="1"<?php checked($this->_config->get_boolean('minify.html.strip.crlf'), true); ?> /> Line break removal</label><br />
88
- </td>
89
- </tr>
90
- <tr>
91
- <th valign="top"><label for="minify_html_comments_ignore">Ignored comment stems:</label></th>
92
- <td>
93
- <textarea id="minify_html_comments_ignore" name="minify.html.comments.ignore" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('minify.html.comments.ignore'))); ?></textarea><br />
94
- <span class="description">Do not remove comments that contain these terms.</span>
 
 
 
 
95
  </td>
96
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  </table>
98
 
99
  <p class="submit">
100
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
101
  </p>
102
- </fieldset>
103
-
104
- <fieldset>
105
- <legend>JavaScript</legend>
106
 
 
107
  <table class="form-table">
108
- <tr>
109
- <th valign="top"><acronym title="JavaScript">JS</acronym> minify settings:</th>
110
- <td>
111
- <input type="hidden" name="minify.js.enable" value="0" />
112
- <input type="hidden" name="minify.js.combine.header" value="0" />
113
  <input type="hidden" name="minify.js.combine.body" value="0" />
114
- <input type="hidden" name="minify.js.combine.footer" value="0" />
115
- <input type="hidden" name="minify.js.strip.comments" value="0" />
116
- <input type="hidden" name="minify.js.strip.crlf" value="0" />
117
- <label><input id="js_enabled" type="checkbox" name="minify.js.enable" value="1"<?php checked($this->_config->get_boolean('minify.js.enable'), true); ?> /> Enable</label><br />
118
- <label><input class="js_enabled" type="checkbox" name="minify.js.combine.header" value="1"<?php checked($this->_config->get_boolean('minify.js.combine.header'), true); ?> /> Combine only after &lt;head&gt;</label><br />
119
- <label><input class="js_enabled" type="checkbox" name="minify.js.combine.body" value="1"<?php checked($this->_config->get_boolean('minify.js.combine.body'), true); ?> /> Combine only after &lt;body&gt;</label><br />
120
- <label><input class="js_enabled" type="checkbox" name="minify.js.combine.footer" value="1"<?php checked($this->_config->get_boolean('minify.js.combine.footer'), true); ?> /> Combine only before &lt;/body&gt;</label><br />
121
- <label><input class="js_enabled" type="checkbox" name="minify.js.strip.comments" value="1"<?php checked($this->_config->get_boolean('minify.js.strip.comments'), true); ?> /> Comment removal</label><br />
122
- <label><input class="js_enabled" type="checkbox" name="minify.js.strip.crlf" value="1"<?php checked($this->_config->get_boolean('minify.js.strip.crlf'), true); ?> /> Line break removal</label><br />
123
- </td>
124
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  <tr>
126
- <th valign="top"><acronym title="JavaScript">JS</acronym> file management:</th>
127
  <td>
128
  <p>
129
  <label>
@@ -191,32 +241,68 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
191
  <input id="js_file_add" class="js_enabled button" type="button" value="Add a script" />
192
  </td>
193
  </tr>
 
194
  </table>
195
 
196
  <p class="submit">
197
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
198
  </p>
199
- </fieldset>
200
-
201
- <fieldset>
202
- <legend>Cascading Style Sheets</legend>
203
 
 
204
  <table class="form-table">
205
  <tr>
206
- <th valign="top"><acronym title="Cascading Style Sheet">CSS</acronym> minify settings:</th>
207
  <td>
208
  <input type="hidden" name="minify.css.enable" value="0" />
209
  <input type="hidden" name="minify.css.combine" value="0" />
210
- <input type="hidden" name="minify.css.strip.comments" value="0" />
211
- <input type="hidden" name="minify.css.strip.crlf" value="0" />
212
  <label><input id="css_enabled" type="checkbox" name="minify.css.enable" value="1"<?php checked($this->_config->get_boolean('minify.css.enable'), true); ?> /> Enable</label><br />
213
  <label><input class="css_enabled" type="checkbox" name="minify.css.combine" value="1"<?php checked($this->_config->get_boolean('minify.css.combine'), true); ?> /> Combine only</label><br />
214
- <label><input class="css_enabled" type="checkbox" name="minify.css.strip.comments" value="1"<?php checked($this->_config->get_boolean('minify.css.strip.comments'), true); ?> /> Comment removal</label><br />
215
- <label><input class="css_enabled" type="checkbox" name="minify.css.strip.crlf" value="1"<?php checked($this->_config->get_boolean('minify.css.strip.crlf'), true); ?> /> Line break removal</label><br />
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  </td>
217
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  <tr>
219
- <th valign="top"><acronym title="Cascading Style Sheet">CSS</acronym> file management:</th>
220
  <td>
221
  <p>
222
  <label>
@@ -269,16 +355,15 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
269
  <input id="css_file_add" class="css_enabled button" type="button" value="Add a style sheet" />
270
  </td>
271
  </tr>
 
272
  </table>
273
 
274
  <p class="submit">
275
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
276
  </p>
277
- </fieldset>
278
-
279
- <fieldset>
280
- <legend>Advanced</legend>
281
 
 
282
  <table class="form-table">
283
  <?php if ($this->_config->get_string('minify.engine') == 'memcached'): ?>
284
  <tr>
@@ -302,8 +387,15 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
302
  <br /><span class="description">If caching to disk, specify how frequently expired cache data is removed. For busy sites, a lower value is best.</span>
303
  </td>
304
  </tr>
 
 
 
 
 
 
 
305
  <tr>
306
- <th valign="top"><label for="minify_reject_ua">Rejected user agents:</label></th>
307
  <td>
308
  <textarea id="minify_reject_ua" name="minify.reject.ua" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('minify.reject.ua'))); ?></textarea><br />
309
  <span class="description">Specify user agents that will never receive minified content.</span>
@@ -312,16 +404,14 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
312
  </table>
313
 
314
  <p class="submit">
315
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
316
  </p>
317
- </fieldset>
318
-
319
- <fieldset>
320
- <legend>Note(s):</legend>
321
 
 
322
  <table class="form-table">
323
  <tr>
324
- <th valign="top" colspan="2">
325
  <ul>
326
  <li>Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression in the "Cascading Style Sheets &amp; JavaScript" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
327
  <li>The <acronym title="Time to Live">TTL</acronym> of page cache files is set via the "Expires header lifetime" field in the "Cascading Style Sheets &amp; JavaScript" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
@@ -329,8 +419,8 @@ minify_templates['<?php echo addslashes($theme_key); ?>']['<?php echo addslashes
329
  </th>
330
  </tr>
331
  </table>
332
- </fieldset>
333
-
334
  </form>
335
 
336
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
1
  <?php include W3TC_DIR . '/inc/options/common/header.phtml'; ?>
2
 
3
+ <script>/*<![CDATA[*/
4
  var minify_templates = {};
5
  <?php foreach ($templates as $theme_key => $theme_templates): ?>
6
  minify_templates['<?php echo addslashes($theme_key); ?>'] = {};
18
  </p>
19
  <p>
20
  To rebuild the minify cache use the
21
+ <input type="hidden" name="page" value="<?php echo $this->_page; ?>" />
22
  <input type="submit" name="flush_minify" value="empty cache"<?php if (! $minify_enabled): ?> disabled="disabled"<?php endif; ?> class="button" />
23
  operation.
24
+ <?php if (!$auto): ?>
25
  Get minify hints using the
26
  <input type="button" class="button button-minify-recommendations" value="help" />
27
  wizard.
28
+ <?php endif; ?>
29
  </p>
30
  </form>
31
 
32
  <form id="minify_form" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
33
+ <div class="metabox-holder">
34
+ <?php echo $this->postbox_header('General'); ?>
 
35
  <table class="form-table">
36
  <tr>
37
  <th colspan="2">
38
  <input type="hidden" name="minify.rewrite" value="0" />
39
+ <label><input type="checkbox" name="minify.rewrite" value="1"<?php checked($this->_config->get_boolean('minify.rewrite'), true); ?><?php if (!w3_can_check_rules()): ?> disabled="disabled"<?php endif; ?> /> Rewrite <acronym title="Uniform Resource Locator">URL</acronym> structure</label><br />
40
  <span class="description">If disabled, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> embeddings will use GET variables instead of "fancy" links.</span>
41
  </th>
42
  </tr>
43
+ <tr>
44
+ <th colspan="2">
45
+ <input type="hidden" name="minify.reject.logged" value="0" />
46
+ <label><input type="checkbox" name="minify.reject.logged" value="1"<?php checked($this->_config->get_boolean('minify.reject.logged'), true); ?> /> Disable <acronym title="Hypertext Markup Language">HTML</acronym> minification for logged in users</label><br />
47
+ <span class="description">Authenticated users will not recieve minified pages if this option is enabled.</span>
48
+ </th>
49
+ </tr>
50
  <tr>
51
+ <th>
 
 
 
 
 
 
 
52
  <label for="minify_error_notification">Minify error notification:</label>
53
  </th>
54
  <td>
65
  </table>
66
 
67
  <p class="submit">
68
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
69
  </p>
70
+ <?php echo $this->postbox_footer(); ?>
 
 
 
71
 
72
+ <?php echo $this->postbox_header('<acronym title="Hypertext Markup Language">HTML</acronym> &amp; <acronym title="eXtensible Markup Language">XML</acronym>'); ?>
73
  <table class="form-table">
74
  <tr>
75
+ <th><acronym title="Hypertext Markup Language">HTML</acronym> minify settings:</th>
76
  <td>
77
  <input type="hidden" name="minify.html.enable" value="0" />
78
+ <input type="hidden" name="minify.html.inline.css" value="0" />
79
+ <input type="hidden" name="minify.html.inline.js" value="0" />
80
  <input type="hidden" name="minify.html.reject.feed" value="0" />
 
 
 
81
  <label><input id="html_enabled" type="checkbox" name="minify.html.enable" value="1"<?php checked($this->_config->get_boolean('minify.html.enable'), true); ?> /> Enable</label><br />
82
+ <label><input class="html_enabled" type="checkbox" name="minify.html.inline.css" value="1"<?php checked($this->_config->get_boolean('minify.html.inline.css'), true); ?> /> Inline <acronym title="Cascading Style Sheet">CSS</acronym> minification</label><br />
83
+ <label><input class="html_enabled" type="checkbox" name="minify.html.inline.js" value="1"<?php checked($this->_config->get_boolean('minify.html.inline.js'), true); ?> /> Inline <acronym title="JavaScript">JS</acronym> minification</label><br />
84
  <label><input class="html_enabled" type="checkbox" name="minify.html.reject.feed" value="1"<?php checked($this->_config->get_boolean('minify.html.reject.feed'), true); ?> /> Don't minify feeds</label><br />
85
+ <?php
86
+ $html_engine_file = '';
87
+
88
+ switch ($html_engine) {
89
+ case 'html':
90
+ case 'htmltidy':
91
+ $html_engine_file = W3TC_DIR . '/inc/options/minify/' . $html_engine . '.phtml';
92
+ break;
93
+ }
94
+
95
+ if (file_exists($html_engine_file)) {
96
+ include $html_engine_file;
97
+ }
98
+ ?>
99
  </td>
100
  </tr>
101
+ <tr>
102
+ <th><label for="minify_html_comments_ignore">Ignored comment stems:</label></th>
103
+ <td>
104
+ <textarea id="minify_html_comments_ignore" name="minify.html.comments.ignore" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('minify.html.comments.ignore'))); ?></textarea><br />
105
+ <span class="description">Do not remove comments that contain these terms.</span>
106
+ </td>
107
+ </tr>
108
+ <?php
109
+ $html_engine_file2 = '';
110
+
111
+ switch ($html_engine_file2) {
112
+ case 'html':
113
+ case 'htmltidy':
114
+ $html_engine_file = W3TC_DIR . '/inc/options/minify/' . $html_engine . '2.phtml';
115
+ break;
116
+ }
117
+
118
+ if (file_exists($html_engine_file2)) {
119
+ include $html_engine_file2;
120
+ }
121
+ ?>
122
  </table>
123
 
124
  <p class="submit">
125
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
126
  </p>
127
+ <?php echo $this->postbox_footer(); ?>
 
 
 
128
 
129
+ <?php echo $this->postbox_header('JavaScript'); ?>
130
  <table class="form-table">
131
+ <tr>
132
+ <th><acronym title="JavaScript">JS</acronym> minify settings:</th>
133
+ <td>
134
+ <input type="hidden" name="minify.js.enable" value="0" />
135
+ <input type="hidden" name="minify.js.combine.header" value="0" />
136
  <input type="hidden" name="minify.js.combine.body" value="0" />
137
+ <input type="hidden" name="minify.js.combine.footer" value="0" />
138
+ <label><input id="js_enabled" type="checkbox" name="minify.js.enable" value="1"<?php checked($this->_config->get_boolean('minify.js.enable'), true); ?> /> Enable</label><br />
139
+ <label><input class="js_enabled" type="checkbox" name="minify.js.combine.header" value="1"<?php checked($this->_config->get_boolean('minify.js.combine.header'), true); ?> /> Combine only after &lt;head&gt;</label><br />
140
+ <label><input class="js_enabled" type="checkbox" name="minify.js.combine.body" value="1"<?php checked($this->_config->get_boolean('minify.js.combine.body'), true); ?> /> Combine only after &lt;body&gt;</label><br />
141
+ <label><input class="js_enabled" type="checkbox" name="minify.js.combine.footer" value="1"<?php checked($this->_config->get_boolean('minify.js.combine.footer'), true); ?> /> Combine only before &lt;/body&gt;</label><br />
142
+ <?php
143
+ $js_engine_file = '';
144
+
145
+ switch ($js_engine) {
146
+ case 'js':
147
+ case 'yuijs':
148
+ case 'ccjs':
149
+ $js_engine_file = W3TC_DIR . '/inc/options/minify/' . $js_engine . '.phtml';
150
+ break;
151
+ }
152
+
153
+ if (file_exists($js_engine_file)) {
154
+ include $js_engine_file;
155
+ }
156
+ ?>
157
+ </td>
158
+ </tr>
159
+ <?php
160
+ $js_engine_file2 = '';
161
+
162
+ switch ($js_engine) {
163
+ case 'js':
164
+ case 'yuijs':
165
+ case 'ccjs':
166
+ $js_engine_file2 = W3TC_DIR . '/inc/options/minify/' . $js_engine . '2.phtml';
167
+ break;
168
+ }
169
+
170
+ if (file_exists($js_engine_file2)) {
171
+ include $js_engine_file2;
172
+ }
173
+ ?>
174
+ <?php if (!$auto): ?>
175
  <tr>
176
+ <th><acronym title="JavaScript">JS</acronym> file management:</th>
177
  <td>
178
  <p>
179
  <label>
241
  <input id="js_file_add" class="js_enabled button" type="button" value="Add a script" />
242
  </td>
243
  </tr>
244
+ <?php endif; ?>
245
  </table>
246
 
247
  <p class="submit">
248
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
249
  </p>
250
+ <?php echo $this->postbox_footer(); ?>
 
 
 
251
 
252
+ <?php echo $this->postbox_header('Cascading Style Sheets'); ?>
253
  <table class="form-table">
254
  <tr>
255
+ <th><acronym title="Cascading Style Sheet">CSS</acronym> minify settings:</th>
256
  <td>
257
  <input type="hidden" name="minify.css.enable" value="0" />
258
  <input type="hidden" name="minify.css.combine" value="0" />
 
 
259
  <label><input id="css_enabled" type="checkbox" name="minify.css.enable" value="1"<?php checked($this->_config->get_boolean('minify.css.enable'), true); ?> /> Enable</label><br />
260
  <label><input class="css_enabled" type="checkbox" name="minify.css.combine" value="1"<?php checked($this->_config->get_boolean('minify.css.combine'), true); ?> /> Combine only</label><br />
261
+ <?php
262
+ $css_engine_file = '';
263
+
264
+ switch ($css_engine) {
265
+ case 'css':
266
+ case 'yuicss':
267
+ case 'csstidy':
268
+ $css_engine_file = W3TC_DIR . '/inc/options/minify/' . $css_engine . '.phtml';
269
+ break;
270
+ }
271
+
272
+ if (file_exists($css_engine_file)) {
273
+ include $css_engine_file;
274
+ }
275
+ ?>
276
  </td>
277
  </tr>
278
+ <tr>
279
+ <th><label for="minify_css_import">@import handling:</label></th>
280
+ <td>
281
+ <select id="minify_css_import" class="css_enabled" name="minify.css.imports">
282
+ <?php foreach ($css_imports_values as $css_imports_key => $css_imports_value): ?>
283
+ <option value="<?php echo $css_imports_key; ?>"<?php selected($css_imports, $css_imports_key); ?>><?php echo $css_imports_value; ?></option>
284
+ <?php endforeach; ?>
285
+ </select>
286
+ </td>
287
+ </tr>
288
+ <?php
289
+ $css_engine_file2 = '';
290
+
291
+ switch ($css_engine) {
292
+ case 'css':
293
+ case 'yuicss':
294
+ case 'csstidy':
295
+ $css_engine_file2 = W3TC_DIR . '/inc/options/minify/' . $css_engine . '2.phtml';
296
+ break;
297
+ }
298
+
299
+ if (file_exists($css_engine_file2)) {
300
+ include $css_engine_file2;
301
+ }
302
+ ?>
303
+ <?php if (!$auto): ?>
304
  <tr>
305
+ <th><acronym title="Cascading Style Sheet">CSS</acronym> file management:</th>
306
  <td>
307
  <p>
308
  <label>
355
  <input id="css_file_add" class="css_enabled button" type="button" value="Add a style sheet" />
356
  </td>
357
  </tr>
358
+ <?php endif; ?>
359
  </table>
360
 
361
  <p class="submit">
362
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
363
  </p>
364
+ <?php echo $this->postbox_footer(); ?>
 
 
 
365
 
366
+ <?php echo $this->postbox_header('Advanced'); ?>
367
  <table class="form-table">
368
  <?php if ($this->_config->get_string('minify.engine') == 'memcached'): ?>
369
  <tr>
387
  <br /><span class="description">If caching to disk, specify how frequently expired cache data is removed. For busy sites, a lower value is best.</span>
388
  </td>
389
  </tr>
390
+ <tr>
391
+ <th><label for="minify_reject_uri">Never minify the following pages:</label></th>
392
+ <td>
393
+ <textarea id="minify_reject_uri" name="minify.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('minify.reject.uri'))); ?></textarea><br />
394
+ <span class="description">Always ignore the specified pages / directories.</span>
395
+ </td>
396
+ </tr>
397
  <tr>
398
+ <th><label for="minify_reject_ua">Rejected user agents:</label></th>
399
  <td>
400
  <textarea id="minify_reject_ua" name="minify.reject.ua" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('minify.reject.ua'))); ?></textarea><br />
401
  <span class="description">Specify user agents that will never receive minified content.</span>
404
  </table>
405
 
406
  <p class="submit">
407
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
408
  </p>
409
+ <?php echo $this->postbox_footer(); ?>
 
 
 
410
 
411
+ <?php echo $this->postbox_header('Note(s):'); ?>
412
  <table class="form-table">
413
  <tr>
414
+ <th colspan="2">
415
  <ul>
416
  <li>Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression in the "Cascading Style Sheets &amp; JavaScript" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
417
  <li>The <acronym title="Time to Live">TTL</acronym> of page cache files is set via the "Expires header lifetime" field in the "Cascading Style Sheets &amp; JavaScript" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
419
  </th>
420
  </tr>
421
  </table>
422
+ <?php echo $this->postbox_footer(); ?>
423
+ </div>
424
  </form>
425
 
426
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/minify/ccjs.phtml ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <input type="hidden" name="minify.ccjs.options.formatting" value="" />
2
+ <label><input class="js_enabled" type="checkbox" name="minify.ccjs.options.formatting" value="pretty_print"<?php checked($this->_config->get_string('minify.ccjs.options.formatting'), 'pretty_print'); ?> /> Pretty print</label><br />
inc/options/minify/ccjs2.phtml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $compilation_levels = array(
3
+ 'WHITESPACE_ONLY' => 'Whitespace only',
4
+ 'SIMPLE_OPTIMIZATIONS' => 'Simple optimizations',
5
+ 'ADVANCED_OPTIMIZATIONS' => 'Advanced optimizations'
6
+ );
7
+
8
+ $compilation_level = $this->_config->get_string('minify.ccjs.options.compilation_level');
9
+ ?>
10
+ <tr>
11
+ <th><label for="minify_ccjs_path_java">Path to JAVA executable:</label></th>
12
+ <td><input id="minify_ccjs_path_java" class="js_enabled" type="text" name="minify.ccjs.path.java" value="<?php echo htmlspecialchars($this->_config->get_string('minify.ccjs.path.java')); ?>" size="60" /></td>
13
+ </tr>
14
+ <tr>
15
+ <th><label for="minify_ccjs_path_jar">Path to JAR file:</label></th>
16
+ <td><input id="minify_ccjs_path_jar" class="js_enabled" type="text" name="minify.ccjs.path.jar" value="<?php echo htmlspecialchars($this->_config->get_string('minify.ccjs.path.jar')); ?>" size="60" /></td>
17
+ </tr>
18
+ <tr>
19
+ <th>&nbsp;</th>
20
+ <td>
21
+ <input class="minifier_test minifier_ccjs button" type="button" value="Test Closure Compiler" />
22
+ <span class="minifier_test_status w3tc-status w3tc-process"></span>
23
+ </td>
24
+ </tr>
25
+ <tr>
26
+ <th><label for="minify_ccjs_options_compilation_level">Compilation level:</label></th>
27
+ <td>
28
+ <select id="minify_ccjs_options_compilation_level" class="js_enabled" name="minify.ccjs.options.compilation_level">
29
+ <?php foreach ($compilation_levels as $compilation_level_key => $compilation_level_name): ?>
30
+ <option value="<?php echo $compilation_level_key; ?>"<?php selected($compilation_level, $compilation_level_key); ?>><?php echo $compilation_level_name; ?></option>
31
+ <?php endforeach; ?>
32
+ </select>
33
+ </td>
34
+ </tr>
inc/options/minify/css.phtml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <input type="hidden" name="minify.css.strip.comments" value="0" />
2
+ <input type="hidden" name="minify.css.strip.crlf" value="0" />
3
+ <label><input class="css_enabled" type="checkbox" name="minify.css.strip.comments" value="1"<?php checked($this->_config->get_boolean('minify.css.strip.comments'), true); ?> /> Preserved comment removal (not applied when combine only is active)</label><br />
4
+ <label><input class="css_enabled" type="checkbox" name="minify.css.strip.crlf" value="1"<?php checked($this->_config->get_boolean('minify.css.strip.crlf'), true); ?> /> Line break removal (not applied when combine only is active)</label><br />
inc/options/minify/csstidy.phtml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $css_levels = array(
3
+ 'CSS2.1',
4
+ 'CSS2.0',
5
+ 'CSS1.0'
6
+ );
7
+
8
+ $css_level = $this->_config->get_string('minify.csstidy.options.css_level');
9
+ ?>
10
+ <input type="hidden" name="minify.csstidy.options.remove_bslash" value="0" />
11
+ <input type="hidden" name="minify.csstidy.options.compress_colors" value="0" />
12
+ <input type="hidden" name="minify.csstidy.options.compress_font-weight" value="0" />
13
+ <input type="hidden" name="minify.csstidy.options.lowercase_s" value="0" />
14
+ <input type="hidden" name="minify.csstidy.options.remove_last_;" value="0" />
15
+ <input type="hidden" name="minify.csstidy.options.sort_properties" value="0" />
16
+ <input type="hidden" name="minify.csstidy.options.sort_selectors" value="0" />
17
+ <input type="hidden" name="minify.csstidy.options.discard_invalid_properties" value="0" />
18
+ <input type="hidden" name="minify.csstidy.options.preserve_css" value="0" />
19
+ <input type="hidden" name="minify.csstidy.options.timestamp" value="0" />
20
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.remove_bslash" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.remove_bslash'), true); ?> /> Remove unnecessary backslashes</label><br />
21
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.compress_colors" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.compress_colors'), true); ?> /> Compress colors</label><br />
22
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.compress_font-weight" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.compress_font-weight'), true); ?> /> Compress font-weight</label><br />
23
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.lowercase_s" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.lowercase_s'), true); ?> /> Lowercase selectors</label><br />
24
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.remove_last_;" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.remove_last_;'), true); ?> /> Remove last ;</label><br />
25
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.sort_properties" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.sort_properties'), true); ?> /> Sort Properties</label><br />
26
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.sort_selectors" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.sort_selectors'), true); ?> /> Sort Selectors (caution)</label><br />
27
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.discard_invalid_properties" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.discard_invalid_properties'), true); ?> /> Discard invalid properties</label>
28
+ <select class="css_enabled" name="minify.csstidy.options.css_level">
29
+ <?php foreach($css_levels as $_css_level): ?>
30
+ <option value="<?php echo $_css_level; ?>"<?php selected($css_level, $_css_level); ?>><?php echo $_css_level; ?></option>
31
+ <?php endforeach; ?>
32
+ </select><br />
33
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.preserve_css" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.preserve_css'), true); ?> /> Preserve CSS</label><br />
34
+ <label><input class="css_enabled" type="checkbox" name="minify.csstidy.options.timestamp" value="1"<?php checked($this->_config->get_boolean('minify.csstidy.options.timestamp'), true); ?> /> Add timestamp</label><br />
inc/options/minify/csstidy2.phtml ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $csstidy_templates = array(
3
+ 'highest_compression' => 'Highest (no readability, smallest size)',
4
+ 'high_compression' => 'High (moderate readability, smaller size)',
5
+ 'default' => 'Standard (balance between readability and size)',
6
+ 'low_compression' => 'Low (higher readability)',
7
+ );
8
+
9
+ $optimise_shorthands_values = array(
10
+ 0 => 'Don\'t optimise',
11
+ 1 => 'Safe optimisations',
12
+ 2 => 'All optimisations'
13
+ );
14
+
15
+ $case_properties_values = array(
16
+ 0 => 'None',
17
+ 1 => 'Lowercase',
18
+ 2 => 'Uppercase'
19
+ );
20
+
21
+ $merge_selectors_values = array(
22
+ 0 => 'Do not change anything',
23
+ 1 => 'Only seperate selectors (split at ,)',
24
+ 2 => 'Merge selectors with the same properties (fast)'
25
+ );
26
+
27
+ $csstidy_template = $this->_config->get_string('minify.csstidy.options.template');
28
+ $optimise_shorthands = $this->_config->get_integer('minify.csstidy.options.optimise_shorthands');
29
+ $case_properties = $this->_config->get_integer('minify.csstidy.options.case_properties');
30
+ $merge_selectors = $this->_config->get_integer('minify.csstidy.options.merge_selectors');
31
+ ?>
32
+ <tr>
33
+ <th><label for="minify_csstidy_options_template">Compression:</label></th>
34
+ <td>
35
+ <select id="minify_csstidy_options_template" class="css_enabled" name="minify.csstidy.options.template">
36
+ <?php foreach ($csstidy_templates as $csstidy_template_key => $csstidy_template_name): ?>
37
+ <option value="<?php echo $csstidy_template_key; ?>"<?php selected($csstidy_template, $csstidy_template_key); ?>><?php echo $csstidy_template_name; ?></option>
38
+ <?php endforeach; ?>
39
+ </select>
40
+ </td>
41
+ </tr>
42
+ <tr>
43
+ <th><label for="minify_csstidy_options_optimise_shorthands">Optimise shorthands:</label></th>
44
+ <td>
45
+ <select id="minify_csstidy_options_optimise_shorthands" class="css_enabled" name="minify.csstidy.options.optimise_shorthands">
46
+ <?php foreach ($optimise_shorthands_values as $optimise_shorthands_key => $optimise_shorthands_name): ?>
47
+ <option value="<?php echo $optimise_shorthands_key; ?>"<?php selected($optimise_shorthands, $optimise_shorthands_key); ?>><?php echo $optimise_shorthands_name; ?></option>
48
+ <?php endforeach; ?>
49
+ </select>
50
+ </td>
51
+ </tr>
52
+ <tr>
53
+ <th><label for="minify_csstidy_options_case_properties">Case for properties:</label></th>
54
+ <td>
55
+ <select id="minify_csstidy_options_case_properties" class="css_enabled" name="minify.csstidy.options.case_properties">
56
+ <?php foreach ($case_properties_values as $case_properties_key => $case_properties_name): ?>
57
+ <option value="<?php echo $case_properties_key; ?>"<?php selected($case_properties, $case_properties_key); ?>><?php echo $case_properties_name; ?></option>
58
+ <?php endforeach; ?>
59
+ </select>
60
+ </td>
61
+ </tr>
62
+ <tr>
63
+ <th><label for="minify_csstidy_options_merge_selectors">Regroup selectors:</label></th>
64
+ <td>
65
+ <select id="minify_csstidy_options_merge_selectors" class="css_enabled" name="minify.csstidy.options.merge_selectors">
66
+ <?php foreach ($merge_selectors_values as $merge_selectors_key => $merge_selectors_name): ?>
67
+ <option value="<?php echo $merge_selectors_key; ?>"<?php selected($merge_selectors, $merge_selectors_key); ?>><?php echo $merge_selectors_name; ?></option>
68
+ <?php endforeach; ?>
69
+ </select>
70
+ </td>
71
+ </tr>
inc/options/minify/html.phtml ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <input type="hidden" name="minify.html.strip.crlf" value="0" />
2
+ <label><input class="html_enabled" type="checkbox" name="minify.html.strip.crlf" value="1"<?php checked($this->_config->get_boolean('minify.html.strip.crlf'), true); ?> /> Line break removal</label><br />
inc/options/minify/htmltidy.phtml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <input type="hidden" name="minify.htmltidy.options.clean" value="0" />
2
+ <input type="hidden" name="minify.htmltidy.options.hide-comments" value="0" />
3
+ <label><input class="html_enabled" type="checkbox" name="minify.htmltidy.options.clean" value="1"<?php checked($this->_config->get_boolean('minify.htmltidy.options.clean'), true); ?> /> Clean</label><br />
4
+ <label><input class="html_enabled" type="checkbox" name="minify.htmltidy.options.hide-comments" value="1"<?php checked($this->_config->get_boolean('minify.htmltidy.options.hide-comments'), true); ?> /> Hide comments</label><br />
inc/options/minify/htmltidy2.phtml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <tr>
2
+ <th><label for="minify_htmltidy_options_wrap">Wrap after:</label></th>
3
+ <td><input id="minify_htmltidy_options_wrap" class="html_enabled" type="text" name="minify.htmltidy.options.wrap" value="<?php echo htmlspecialchars($this->_config->get_integer('minify.htmltidy.options.wrap')); ?>" size="8" style="text-align: right;" /> symbols (set to 0 to disable)</td>
4
+ </tr>
inc/options/minify/js.phtml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <input type="hidden" name="minify.js.strip.comments" value="0" />
2
+ <input type="hidden" name="minify.js.strip.crlf" value="0" />
3
+ <label><input class="js_enabled" type="checkbox" name="minify.js.strip.comments" value="1"<?php checked($this->_config->get_boolean('minify.js.strip.comments'), true); ?> /> Preserved comment removal (not applied when combine only is active)</label><br />
4
+ <label><input class="js_enabled" type="checkbox" name="minify.js.strip.crlf" value="1"<?php checked($this->_config->get_boolean('minify.js.strip.crlf'), true); ?> /> Line break removal (not safe, not applied when combine only is active)</label><br />
inc/options/minify/yuicss2.phtml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <th><label for="minify_yuicss_path_java">Path to JAVA executable:</label></th>
3
+ <td><input class="css_enabled" id="minify_yuicss_path_java" type="text" name="minify.yuicss.path.java" value="<?php echo htmlspecialchars($this->_config->get_string('minify.yuicss.path.java')); ?>" size="100" /></td>
4
+ </tr>
5
+ <tr>
6
+ <th><label for="minify_yuicss_path_jar">Path to JAR file:</label></th>
7
+ <td><input class="css_enabled" id="minify_yuicss_path_jar" type="text" name="minify.yuicss.path.jar" value="<?php echo htmlspecialchars($this->_config->get_string('minify.yuicss.path.jar')); ?>" size="100" /></td>
8
+ </tr>
9
+ <tr>
10
+ <th>&nbsp;</th>
11
+ <td>
12
+ <input class="minifier_test minifier_yuicss button" type="button" value="Test YUI Compressor" />
13
+ <span class="minifier_test_status w3tc-status w3tc-process"></span>
14
+ </td>
15
+ </tr>
16
+ <tr>
17
+ <th><label for="minify_yuicss_options_line-break">Line break after:</label></th>
18
+ <td><input class="css_enabled" id="minify_yuicss_options_line-break" type="text" name="minify.yuicss.options.line-break" value="<?php echo htmlspecialchars($this->_config->get_integer('minify.yuicss.options.line-break')); ?>" size="8" style="text-align: right;" /> symbols (set to 0 to disable)</td>
19
+ </tr>
inc/options/minify/yuijs.phtml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <input type="hidden" name="minify.yuijs.options.nomunge" value="0" />
2
+ <input type="hidden" name="minify.yuijs.options.preserve-semi" value="0" />
3
+ <input type="hidden" name="minify.yuijs.options.disable-optimizations" value="0" />
4
+ <label><input class="js_enabled" type="checkbox" name="minify.yuijs.options.nomunge" value="1"<?php checked($this->_config->get_boolean('minify.yuijs.options.nomunge'), true); ?> /> Minify only, do not obfuscate local symbols</label><br />
5
+ <label><input class="js_enabled" type="checkbox" name="minify.yuijs.options.preserve-semi" value="1"<?php checked($this->_config->get_boolean('minify.yuijs.options.preserve-semi'), true); ?> /> Preserve unnecessary semicolons</label><br />
6
+ <label><input class="js_enabled" type="checkbox" name="minify.yuijs.options.disable-optimizations" value="1"<?php checked($this->_config->get_boolean('minify.yuijs.options.disable-optimizations'), true); ?> /> Disable all the built-in micro optimizations</label><br />
inc/options/minify/yuijs2.phtml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <th><label for="minify_yuijs_path_java">Path to JAVA executable:</label></th>
3
+ <td><input id="minify_yuijs_path_java" class="js_enabled" type="text" name="minify.yuijs.path.java" value="<?php echo htmlspecialchars($this->_config->get_string('minify.yuijs.path.java')); ?>" size="100" /></td>
4
+ </tr>
5
+ <tr>
6
+ <th><label for="minify_yuijs_path_jar">Path to JAR file:</label></th>
7
+ <td><input id="minify_yuijs_path_jar" class="js_enabled" type="text" name="minify.yuijs.path.jar" value="<?php echo htmlspecialchars($this->_config->get_string('minify.yuijs.path.jar')); ?>" size="100" /></td>
8
+ </tr>
9
+ <tr>
10
+ <th>&nbsp;</th>
11
+ <td>
12
+ <input class="minifier_test minifier_yuijs button" type="button" value="Test YUI Compressor" />
13
+ <span class="minifier_test_status w3tc-status w3tc-process"></span>
14
+ </td>
15
+ </tr>
16
+ <tr>
17
+ <th><label for="minify_yuijs_options_line-break">Line break after:</label></th>
18
+ <td><input id="minify_yuijs_options_line-break" class="js_enabled" type="text" name="minify.yuijs.options.line-break" value="<?php echo htmlspecialchars($this->_config->get_integer('minify.yuijs.options.line-break')); ?>" size="8" style="text-align: right;" /> symbols (set to 0 to disable)</td>
19
+ </tr>
inc/options/mobile.phtml CHANGED
@@ -1,6 +1,6 @@
1
  <?php include W3TC_DIR . '/inc/options/common/header.phtml'; ?>
2
 
3
- <script type="text/javascript">/*<![CDATA[*/
4
  var mobile_themes = {};
5
  <?php foreach ($themes as $theme_key => $theme_name): ?>
6
  mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes($theme_name); ?>';
@@ -12,8 +12,8 @@ mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes(
12
  </p>
13
 
14
  <form id="mobile_form" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
15
- <fieldset>
16
- <legend>Manage User Agent Groups</legend>
17
  <p>
18
  <input id="mobile_add" type="button" class="button" value="Create a group" /> of user agents by specifying names in the user agents field. Assign a set of user agents to use a specific theme, redirect them to another domain or if an existing mobile plugin is active, create user agent groups to ensure that a unique cache is created for each user agent group. Drag and drop groups into order (if needed) to determine their priority (top -&gt; down).
19
  </p>
@@ -23,7 +23,7 @@ mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes(
23
  <li id="mobile_group_<?php echo htmlspecialchars($group); ?>">
24
  <table class="form-table">
25
  <tr>
26
- <th valign="top">
27
  Group name:
28
  </th>
29
  <td>
@@ -40,7 +40,7 @@ mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes(
40
  </td>
41
  </tr>
42
  <tr>
43
- <th valign="top">
44
  <label for="mobile_groups_<?php echo htmlspecialchars($group); ?>_theme">Theme:</label>
45
  </th>
46
  <td>
@@ -54,7 +54,7 @@ mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes(
54
  </td>
55
  </tr>
56
  <tr>
57
- <th valign="top">
58
  <label for="mobile_groups_<?php echo htmlspecialchars($group); ?>_redirect">Redirect users to:</label>
59
  </th>
60
  <td>
@@ -63,7 +63,7 @@ mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes(
63
  </td>
64
  </tr>
65
  <tr>
66
- <th valign="top">
67
  <label for="mobile_groups_<?php echo htmlspecialchars($group); ?>_agents">User agents:</label>
68
  </th>
69
  <td>
@@ -78,9 +78,10 @@ mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes(
78
  <div id="mobile_groups_empty" style="display: none;">No groups added. All user agents recieve the same page and minify cache results.</div>
79
 
80
  <p class="submit">
81
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
82
  </p>
83
- </fieldset>
 
84
  </form>
85
 
86
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
1
  <?php include W3TC_DIR . '/inc/options/common/header.phtml'; ?>
2
 
3
+ <script>/*<![CDATA[*/
4
  var mobile_themes = {};
5
  <?php foreach ($themes as $theme_key => $theme_name): ?>
6
  mobile_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes($theme_name); ?>';
12
  </p>
13
 
14
  <form id="mobile_form" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
15
+ <div class="metabox-holder">
16
+ <?php echo $this->postbox_header('Manage User Agent Groups'); ?>
17
  <p>
18
  <input id="mobile_add" type="button" class="button" value="Create a group" /> of user agents by specifying names in the user agents field. Assign a set of user agents to use a specific theme, redirect them to another domain or if an existing mobile plugin is active, create user agent groups to ensure that a unique cache is created for each user agent group. Drag and drop groups into order (if needed) to determine their priority (top -&gt; down).
19
  </p>
23
  <li id="mobile_group_<?php echo htmlspecialchars($group); ?>">
24
  <table class="form-table">
25
  <tr>
26
+ <th>
27
  Group name:
28
  </th>
29
  <td>
40
  </td>
41
  </tr>
42
  <tr>
43
+ <th>
44
  <label for="mobile_groups_<?php echo htmlspecialchars($group); ?>_theme">Theme:</label>
45
  </th>
46
  <td>
54
  </td>
55
  </tr>
56
  <tr>
57
+ <th>
58
  <label for="mobile_groups_<?php echo htmlspecialchars($group); ?>_redirect">Redirect users to:</label>
59
  </th>
60
  <td>
63
  </td>
64
  </tr>
65
  <tr>
66
+ <th>
67
  <label for="mobile_groups_<?php echo htmlspecialchars($group); ?>_agents">User agents:</label>
68
  </th>
69
  <td>
78
  <div id="mobile_groups_empty" style="display: none;">No groups added. All user agents recieve the same page and minify cache results.</div>
79
 
80
  <p class="submit">
81
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
82
  </p>
83
+ <?php echo $this->postbox_footer(); ?>
84
+ </div>
85
  </form>
86
 
87
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/objectcache.phtml CHANGED
@@ -15,9 +15,8 @@
15
  </form>
16
 
17
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
18
- <fieldset>
19
- <legend>General</legend>
20
-
21
  <table class="form-table">
22
  <tr>
23
  <th>
@@ -29,13 +28,11 @@
29
  </table>
30
 
31
  <p class="submit">
32
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
33
  </p>
34
- </fieldset>
35
-
36
- <fieldset>
37
- <legend>Advanced</legend>
38
 
 
39
  <table class="form-table">
40
  <?php if ($this->_config->get_string('objectcache.engine') == 'memcached'): ?>
41
  <tr>
@@ -63,21 +60,21 @@
63
  </td>
64
  </tr>
65
  <tr>
66
- <th valign="top"><label for="objectcache_reject_uri">Never cache the following pages:</label></th>
67
  <td>
68
  <textarea id="objectcache_reject_uri" name="objectcache.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('objectcache.reject.uri'))); ?></textarea>
69
  <br /><span class="description">Always ignore the specified pages / directories.</span>
70
  </td>
71
  </tr>
72
  <tr>
73
- <th valign="top"><label for="objectcache_groups_global">Global groups:</label></th>
74
  <td>
75
  <textarea id="objectcache_groups_global" name="objectcache.groups.global" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('objectcache.groups.global'))); ?></textarea>
76
  <br /><span class="description">Groups shared amongst sites in network mode.</span>
77
  </td>
78
  </tr>
79
  <tr>
80
- <th valign="top"><label for="objectcache_groups_nonpersistent">Non-persistent groups:</label></th>
81
  <td>
82
  <textarea id="objectcache_groups_nonpersistent" name="objectcache.groups.nonpersistent" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('objectcache.groups.nonpersistent'))); ?></textarea>
83
  <br /><span class="description">Groups that should not be cached.</span>
@@ -86,9 +83,10 @@
86
  </table>
87
 
88
  <p class="submit">
89
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
90
  </p>
91
- </fieldset>
 
92
  </form>
93
 
94
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
15
  </form>
16
 
17
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
18
+ <div class="metabox-holder">
19
+ <?php echo $this->postbox_header('General'); ?>
 
20
  <table class="form-table">
21
  <tr>
22
  <th>
28
  </table>
29
 
30
  <p class="submit">
31
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
32
  </p>
33
+ <?php echo $this->postbox_footer(); ?>
 
 
 
34
 
35
+ <?php echo $this->postbox_header('Advanced'); ?>
36
  <table class="form-table">
37
  <?php if ($this->_config->get_string('objectcache.engine') == 'memcached'): ?>
38
  <tr>
60
  </td>
61
  </tr>
62
  <tr>
63
+ <th><label for="objectcache_reject_uri">Never cache the following pages:</label></th>
64
  <td>
65
  <textarea id="objectcache_reject_uri" name="objectcache.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('objectcache.reject.uri'))); ?></textarea>
66
  <br /><span class="description">Always ignore the specified pages / directories.</span>
67
  </td>
68
  </tr>
69
  <tr>
70
+ <th><label for="objectcache_groups_global">Global groups:</label></th>
71
  <td>
72
  <textarea id="objectcache_groups_global" name="objectcache.groups.global" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('objectcache.groups.global'))); ?></textarea>
73
  <br /><span class="description">Groups shared amongst sites in network mode.</span>
74
  </td>
75
  </tr>
76
  <tr>
77
+ <th><label for="objectcache_groups_nonpersistent">Non-persistent groups:</label></th>
78
  <td>
79
  <textarea id="objectcache_groups_nonpersistent" name="objectcache.groups.nonpersistent" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('objectcache.groups.nonpersistent'))); ?></textarea>
80
  <br /><span class="description">Groups that should not be cached.</span>
83
  </table>
84
 
85
  <p class="submit">
86
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
87
  </p>
88
+ <?php echo $this->postbox_footer(); ?>
89
+ </div>
90
  </form>
91
 
92
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/pgcache.phtml CHANGED
@@ -15,9 +15,8 @@
15
  </form>
16
 
17
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
18
- <fieldset>
19
- <legend>General</legend>
20
-
21
  <table class="form-table">
22
  <tr>
23
  <th>
@@ -51,19 +50,17 @@
51
  <th>
52
  <input type="hidden" name="pgcache.cache.404" value="0" />
53
  <label><input type="checkbox" name="pgcache.cache.404" value="1"<?php checked($this->_config->get_boolean('pgcache.cache.404'), true); ?> /> Cache 404 (not found) pages</label><br />
54
- <span class="description">Reduce server load by caching 404 pages. The "Do not process 404 errors for static objects with WordPress" Browser Cache option is recommended.</span>
55
  </th>
56
  </tr>
57
  </table>
58
 
59
  <p class="submit">
60
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
61
  </p>
62
- </fieldset>
63
-
64
- <fieldset>
65
- <legend>Advanced</legend>
66
 
 
67
  <table class="form-table">
68
  <?php if ($this->_config->get_string('pgcache.engine') == 'memcached'): ?>
69
  <tr>
@@ -84,50 +81,48 @@
84
  </td>
85
  </tr>
86
  <tr>
87
- <th valign="top"><label for="pgcache_reject_ua">Rejected User Agents:</label></th>
88
  <td>
89
  <textarea id="pgcache_reject_ua" name="pgcache.reject.ua" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.reject.ua'))); ?></textarea><br />
90
  <span class="description">Never send cache pages for these user agents.</span>
91
  </td>
92
  </tr>
93
  <tr>
94
- <th valign="top"><label for="pgcache_reject_cookie">Rejected Cookies:</label></th>
95
  <td>
96
  <textarea id="pgcache_reject_cookie" name="pgcache.reject.cookie" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.reject.cookie'))); ?></textarea><br />
97
  <span class="description">Never cache pages that use the specified cookies.</span>
98
  </td>
99
  </tr>
100
  <tr>
101
- <th valign="top"><label for="pgcache_reject_uri">Never cache the following pages:</label></th>
102
  <td>
103
  <textarea id="pgcache_reject_uri" name="pgcache.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.reject.uri'))); ?></textarea><br />
104
  <span class="description">Always ignore the specified pages / directories.</span>
105
  </td>
106
  </tr>
107
  <tr>
108
- <th valign="top"><label for="pgcache_accept_files">Cache exception list:</label></th>
109
  <td>
110
  <textarea id="pgcache_accept_files" name="pgcache.accept.files" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.accept.files'))); ?></textarea><br />
111
  <span class="description">Cache the specified pages / directories even if listed in the "never cache the following pages" field.</span>
112
  </td>
113
  </tr>
114
  <tr>
115
- <th valign="top"><label for="pgcache_cache_headers">Specify page headers:</label></th>
116
  <td>
117
- <textarea id="pgcache_cache_headers" name="pgcache.cache.headers" cols="40" rows="5"<?php if (! W3TC_PHP5 || $this->_config->get_string('pgcache.engine') == 'file_pgcache'): ?> disabled="disabled"<?php endif; ?>><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.cache.headers'))); ?></textarea><br />
118
  <span class="description">Specify additional page headers to cache.</span>
119
  </td>
120
  </tr>
121
  </table>
122
 
123
  <p class="submit">
124
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
125
  </p>
126
- </fieldset>
127
-
128
- <fieldset>
129
- <legend>Cache Preload</legend>
130
 
 
131
  <table class="form-table">
132
  <tr>
133
  <th colspan="2">
@@ -156,44 +151,79 @@
156
  <span class="description">A <a href="http://www.xml-sitemaps.com/validate-xml-sitemap.html" target="_blank">compliant</a> sitemap can be used to specify the pages to maintain in the primed cache. Pages will be cached according to the priorities specified in the <acronym title="Extensible Markup Language">XML</acronym> file. <a href="http://wordpress.org/extend/plugins/google-sitemap-generator/" target="_blank">Google <acronym title="Extensible Markup Language">XML</acronym> Sitemaps</a> is recommended for use with this feature.</span>
157
  </td>
158
  </tr>
159
-
160
  </table>
161
 
162
  <p class="submit">
163
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
164
  </p>
165
- </fieldset>
166
 
167
- <fieldset>
168
- <legend>Varnish</legend>
169
-
170
  <table class="form-table">
171
- <tr>
172
- <th colspan="2">
173
- <input type="hidden" name="pgcache.varnish.enabled" value="0" />
174
- <label><input type="checkbox" name="pgcache.varnish.enabled" value="1"<?php checked($this->_config->get_boolean('pgcache.varnish.enabled'), true); ?> /> Enable varnish cache purging</label><br />
175
- </th>
176
- </tr>
177
- <tr>
178
- <th valign="top"><label for="pgcache_varnish_servers">Varnish servers:</label></th>
179
- <td>
180
- <textarea id="pgcache_varnish_servers" name="pgcache.varnish.servers" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.varnish.servers'))); ?></textarea><br />
181
- <span class="description">Specify the IP addresses of your varnish instances above. Your <acronym title="Varnish Configuration Language">VCL</acronym>'s <acronym title="Access Control List">ACL</acronym> must allow this request.</span>
182
- </td>
183
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  </table>
185
 
186
  <p class="submit">
187
- <input type="submit" name="options_save" class="button-primary" value="Save changes" />
188
  </p>
189
- </fieldset>
190
-
191
- <fieldset>
192
- <legend>Note(s):</legend>
193
 
 
194
  <table class="form-table">
195
  <tr>
196
- <th valign="top" colspan="2">
197
  <ul>
198
  <li>Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression in the "<acronym title="Hypertext Markup Language">HTML</acronym>" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
199
  <li>The <acronym title="Time to Live">TTL</acronym> of page cache files is set via the "Expires header lifetime" field in the "<acronym title="Hypertext Markup Language">HTML</acronym>" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
@@ -201,8 +231,8 @@
201
  </th>
202
  </tr>
203
  </table>
204
- </fieldset>
205
-
206
  </form>
207
 
208
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
15
  </form>
16
 
17
  <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
18
+ <div class="metabox-holder">
19
+ <?php echo $this->postbox_header('General'); ?>
 
20
  <table class="form-table">
21
  <tr>
22
  <th>
50
  <th>
51
  <input type="hidden" name="pgcache.cache.404" value="0" />
52
  <label><input type="checkbox" name="pgcache.cache.404" value="1"<?php checked($this->_config->get_boolean('pgcache.cache.404'), true); ?> /> Cache 404 (not found) pages</label><br />
53
+ <span class="description">Reduce server load by caching 404 pages. The "Do not process 404 errors for static objects with WordPress" <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> option is also recommended.</span>
54
  </th>
55
  </tr>
56
  </table>
57
 
58
  <p class="submit">
59
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
60
  </p>
61
+ <?php echo $this->postbox_footer(); ?>
 
 
 
62
 
63
+ <?php echo $this->postbox_header('Advanced'); ?>
64
  <table class="form-table">
65
  <?php if ($this->_config->get_string('pgcache.engine') == 'memcached'): ?>
66
  <tr>
81
  </td>
82
  </tr>
83
  <tr>
84
+ <th><label for="pgcache_reject_ua">Rejected User Agents:</label></th>
85
  <td>
86
  <textarea id="pgcache_reject_ua" name="pgcache.reject.ua" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.reject.ua'))); ?></textarea><br />
87
  <span class="description">Never send cache pages for these user agents.</span>
88
  </td>
89
  </tr>
90
  <tr>
91
+ <th><label for="pgcache_reject_cookie">Rejected Cookies:</label></th>
92
  <td>
93
  <textarea id="pgcache_reject_cookie" name="pgcache.reject.cookie" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.reject.cookie'))); ?></textarea><br />
94
  <span class="description">Never cache pages that use the specified cookies.</span>
95
  </td>
96
  </tr>
97
  <tr>
98
+ <th><label for="pgcache_reject_uri">Never cache the following pages:</label></th>
99
  <td>
100
  <textarea id="pgcache_reject_uri" name="pgcache.reject.uri" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.reject.uri'))); ?></textarea><br />
101
  <span class="description">Always ignore the specified pages / directories.</span>
102
  </td>
103
  </tr>
104
  <tr>
105
+ <th><label for="pgcache_accept_files">Cache exception list:</label></th>
106
  <td>
107
  <textarea id="pgcache_accept_files" name="pgcache.accept.files" cols="40" rows="5"><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.accept.files'))); ?></textarea><br />
108
  <span class="description">Cache the specified pages / directories even if listed in the "never cache the following pages" field.</span>
109
  </td>
110
  </tr>
111
  <tr>
112
+ <th><label for="pgcache_cache_headers">Specify page headers:</label></th>
113
  <td>
114
+ <textarea id="pgcache_cache_headers" name="pgcache.cache.headers" cols="40" rows="5"<?php if (!W3TC_PHP5 || $this->_config->get_string('pgcache.engine') == 'file_pgcache'): ?> disabled="disabled"<?php endif; ?>><?php echo htmlspecialchars(implode("\r\n", $this->_config->get_array('pgcache.cache.headers'))); ?></textarea><br />
115
  <span class="description">Specify additional page headers to cache.</span>
116
  </td>
117
  </tr>
118
  </table>
119
 
120
  <p class="submit">
121
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
122
  </p>
123
+ <?php echo $this->postbox_footer(); ?>
 
 
 
124
 
125
+ <?php echo $this->postbox_header('Cache Preload'); ?>
126
  <table class="form-table">
127
  <tr>
128
  <th colspan="2">
151
  <span class="description">A <a href="http://www.xml-sitemaps.com/validate-xml-sitemap.html" target="_blank">compliant</a> sitemap can be used to specify the pages to maintain in the primed cache. Pages will be cached according to the priorities specified in the <acronym title="Extensible Markup Language">XML</acronym> file. <a href="http://wordpress.org/extend/plugins/google-sitemap-generator/" target="_blank">Google <acronym title="Extensible Markup Language">XML</acronym> Sitemaps</a> is recommended for use with this feature.</span>
152
  </td>
153
  </tr>
 
154
  </table>
155
 
156
  <p class="submit">
157
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
158
  </p>
159
+ <?php echo $this->postbox_footer(); ?>
160
 
161
+ <?php echo $this->postbox_header('Purge Policy'); ?>
 
 
162
  <table class="form-table">
163
+ <tr>
164
+ <th colspan="2">
165
+ <p>Specify the pages and feeds to purge when posts are created, edited, or comments posted. The defaults are recommended because additional options may reduce server performance:</p>
166
+
167
+ <table border="0" cellpadding="0" cellspacing="0">
168
+ <tr>
169
+ <th style="padding-left: 0;">
170
+ <input type="hidden" name="pgcache.purge.home" value="0" />
171
+ <input type="hidden" name="pgcache.purge.post" value="0" />
172
+ <input type="hidden" name="pgcache.purge.feed.blog" value="0" />
173
+ <label><input type="checkbox" name="pgcache.purge.home" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.home'), true); ?> /> Home page</label><br />
174
+ <label><input type="checkbox" name="pgcache.purge.post" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.post'), true); ?> /> Post page</label><br />
175
+ <label><input type="checkbox" name="pgcache.purge.feed.blog" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.feed.blog'), true); ?> /> Blog feed</label><br />
176
+ </th>
177
+ <th>
178
+ <input type="hidden" name="pgcache.purge.comments" value="0" />
179
+ <input type="hidden" name="pgcache.purge.author" value="0" />
180
+ <input type="hidden" name="pgcache.purge.terms" value="0" />
181
+ <label><input type="checkbox" name="pgcache.purge.comments" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.comments'), true); ?> /> Post comments pages</label><br />
182
+ <label><input type="checkbox" name="pgcache.purge.author" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.author'), true); ?> /> Post author pages</label><br />
183
+ <label><input type="checkbox" name="pgcache.purge.terms" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.terms'), true); ?> /> Post terms pages</label><br />
184
+ </th>
185
+ <th>
186
+ <input type="hidden" name="pgcache.purge.feed.comments" value="0" />
187
+ <input type="hidden" name="pgcache.purge.feed.author" value="0" />
188
+ <input type="hidden" name="pgcache.purge.feed.terms" value="0" />
189
+ <label><input type="checkbox" name="pgcache.purge.feed.comments" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.feed.comments'), true); ?> /> Post comments feed</label><br />
190
+ <label><input type="checkbox" name="pgcache.purge.feed.author" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.feed.author'), true); ?> /> Post author feed</label><br />
191
+ <label><input type="checkbox" name="pgcache.purge.feed.terms" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.feed.terms'), true); ?> /> Post terms feeds</label>
192
+ </th>
193
+ <th>
194
+ <input type="hidden" name="pgcache.purge.archive.daily" value="0" />
195
+ <input type="hidden" name="pgcache.purge.archive.monthly" value="0" />
196
+ <input type="hidden" name="pgcache.purge.archive.yearly" value="0" />
197
+ <label><input type="checkbox" name="pgcache.purge.archive.daily" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.archive.daily'), true); ?> /> Daily archive pages</label><br />
198
+ <label><input type="checkbox" name="pgcache.purge.archive.monthly" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.archive.monthly'), true); ?> /> Monthly archive pages</label><br />
199
+ <label><input type="checkbox" name="pgcache.purge.archive.yearly" value="1"<?php checked($this->_config->get_boolean('pgcache.purge.archive.yearly'), true); ?> /> Yearly archive pages</label><br />
200
+ </th>
201
+ </tr>
202
+ </table>
203
+ </th>
204
+ </tr>
205
+ <tr>
206
+ <th colspan="2">
207
+ <p>Specify the feed types to purge:</p>
208
+ <input type="hidden" name="pgcache.purge.feed.types" value="" />
209
+ <?php foreach($feeds as $feed): ?>
210
+ <label><input type="checkbox" name="pgcache.purge.feed.types[]" value="<?php echo $feed; ?>"<?php checked(in_array($feed, $this->_config->get_array('pgcache.purge.feed.types')), true); ?> />
211
+ <?php echo $feed; ?>
212
+ <?php if ($feed == $default_feed): ?>(default)<?php endif; ?></label><br />
213
+ <?php endforeach; ?>
214
+ </th>
215
+ </tr>
216
  </table>
217
 
218
  <p class="submit">
219
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
220
  </p>
221
+ <?php echo $this->postbox_footer(); ?>
 
 
 
222
 
223
+ <?php echo $this->postbox_header('Note(s):'); ?>
224
  <table class="form-table">
225
  <tr>
226
+ <th colspan="2">
227
  <ul>
228
  <li>Enable <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression in the "<acronym title="Hypertext Markup Language">HTML</acronym>" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
229
  <li>The <acronym title="Time to Live">TTL</acronym> of page cache files is set via the "Expires header lifetime" field in the "<acronym title="Hypertext Markup Language">HTML</acronym>" section on <a href="admin.php?page=w3tc_browsercache">Browser Cache</a> Settings tab.</li>
231
  </th>
232
  </tr>
233
  </table>
234
+ <?php echo $this->postbox_footer(); ?>
235
+ </div>
236
  </form>
237
 
238
  <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/referrer.phtml ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php include W3TC_DIR . '/inc/options/common/header.phtml'; ?>
2
+
3
+ <script>/*<![CDATA[*/
4
+ var referrer_themes = {};
5
+ <?php foreach ($themes as $theme_key => $theme_name): ?>
6
+ referrer_themes['<?php echo addslashes($theme_key); ?>'] = '<?php echo addslashes($theme_name); ?>';
7
+ <?php endforeach; ?>
8
+ /*]]>*/</script>
9
+
10
+ <p>
11
+ Referrer group support is always <span class="w3tc-enabled">enabled</span>.
12
+ </p>
13
+
14
+ <form id="referrer_form" action="admin.php?page=<?php echo $this->_page; ?>" method="post">
15
+ <div class="metabox-holder">
16
+ <?php echo $this->postbox_header('Manage Referrer Groups'); ?>
17
+ <p>
18
+ <input id="referrer_add" type="button" class="button" value="Create a group" /> of referrers by specifying names in the referrers field. Assign a set of referrers to use a specific theme, redirect them to another domain, create referrer groups to ensure that a unique cache is created for each referrer group. Drag and drop groups into order (if needed) to determine their priority (top -&gt; down).
19
+ </p>
20
+
21
+ <ul id="referrer_groups">
22
+ <?php $index = 0; foreach ($groups as $group => $group_config): $index++; ?>
23
+ <li id="referrer_group_<?php echo htmlspecialchars($group); ?>">
24
+ <table class="form-table">
25
+ <tr>
26
+ <th>
27
+ Group name:
28
+ </th>
29
+ <td>
30
+ <span class="referrer_group_number"><?php echo $index; ?>.</span> <span class="referrer_group"><?php echo htmlspecialchars($group); ?></span> <input type="button" class="button referrer_delete" value="Delete group" />
31
+ </td>
32
+ </tr>
33
+ <tr>
34
+ <th>
35
+ <label for="referrer_groups_<?php echo htmlspecialchars($group); ?>_enabled">Enabled:</label>
36
+ </th>
37
+ <td>
38
+ <input type="hidden" name="referrer_groups[<?php echo htmlspecialchars($group); ?>][enabled]" value="0" />
39
+ <input id="referrer_groups_<?php echo htmlspecialchars($group); ?>_enabled" type="checkbox" name="referrer_groups[<?php echo htmlspecialchars($group); ?>][enabled]" value="1"<?php checked($group_config['enabled'], true); ?> />
40
+ </td>
41
+ </tr>
42
+ <tr>
43
+ <th>
44
+ <label for="referrer_groups_<?php echo htmlspecialchars($group); ?>_theme">Theme:</label>
45
+ </th>
46
+ <td>
47
+ <select id="referrer_groups_<?php echo htmlspecialchars($group); ?>_theme" name="referrer_groups[<?php echo htmlspecialchars($group); ?>][theme]">
48
+ <option value="">-- Pass-through --</option>
49
+ <?php foreach ($themes as $theme_key => $theme_name): ?>
50
+ <option value="<?php echo htmlspecialchars($theme_key); ?>"<?php selected($theme_key, $group_config['theme']); ?>><?php echo htmlspecialchars($theme_name); ?></option>
51
+ <?php endforeach; ?>
52
+ </select>
53
+ <br /><span class="description">Assign this group of referrers to a specific theme. Selecting "Pass-through" allows any plugin(s) (e.g. referrer plugins) to properly handle requests for these referrers. If the "redirect users to" field is not empty, this setting is ignored.</span>
54
+ </td>
55
+ </tr>
56
+ <tr>
57
+ <th>
58
+ <label for="referrer_groups_<?php echo htmlspecialchars($group); ?>_redirect">Redirect users to:</label>
59
+ </th>
60
+ <td>
61
+ <input id="referrer_groups_<?php echo htmlspecialchars($group); ?>_redirect" type="text" name="referrer_groups[<?php echo htmlspecialchars($group); ?>][redirect]" value="<?php echo htmlspecialchars($group_config['redirect']); ?>" size="60" />
62
+ <br /><span class="description">A 302 redirect is used to send this group of referrers to another hostname (domain).</span>
63
+ </td>
64
+ </tr>
65
+ <tr>
66
+ <th>
67
+ <label for="referrer_groups_<?php echo htmlspecialchars($group); ?>_referrers">Referrers:</label>
68
+ </th>
69
+ <td>
70
+ <textarea id="referrer_groups_<?php echo htmlspecialchars($group); ?>_referrers" name="referrer_groups[<?php echo htmlspecialchars($group); ?>][referrers]" rows="10" cols="50"><?php echo htmlspecialchars(implode("\r\n", (array) $group_config['referrers'])); ?></textarea>
71
+ <br /><span class="description">Specify the referrers for this group. Remember to escape special characters like spaces, dots or dashes with a backslash. Regular expressions are also supported.</span>
72
+ </td>
73
+ </tr>
74
+ </table>
75
+ </li>
76
+ <?php endforeach; ?>
77
+ </ul>
78
+ <div id="referrer_groups_empty" style="display: none;">No groups added. All referrers recieve the same page and minify cache results.</div>
79
+
80
+ <p class="submit">
81
+ <input type="submit" name="options_save" class="w3tc-button-save button-primary" value="Save all settings" />
82
+ </p>
83
+ <?php echo $this->postbox_footer(); ?>
84
+ </div>
85
+ </form>
86
+
87
+ <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
inc/options/support.phtml CHANGED
@@ -2,29 +2,37 @@
2
  <p>
3
  Request professional services, suggest a feature or submit a bug using the form below:
4
  </p>
5
- <?php endif; ?>
6
 
7
  <div id="support_container">
8
- <form action="admin.php?page=<?php echo $this->_page; ?>" method="post" enctype="multipart/form-data" id="support_form">
9
- <?php include W3TC_DIR . '/inc/options/support/' . $request_type . '.phtml'; ?>
10
-
11
- <fieldset>
12
- <legend>Notes</legend>
13
-
14
- <ul>
15
- <li>All submitted data will not be saved and is used solely for the purposes your support request. You will not be added to a mailing list, solicited without your permission, nor will your site be administered after this support case is closed.</li>
16
- <li>Instead of providing your primary administrative or <acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> accounts, create a new administrator account that can be disabled when the support case is closed.</li>
17
- <li>Please add the domain w3-edge.com to your <a href="http://en.wikipedia.org/wiki/Whitelist" target="_blank">email whitelist</a> as soon as possible.</li>
18
- </ul>
19
- </fieldset>
20
-
21
- <p>
22
- <input type="hidden" name="request_type" value="<?php echo $request_type; ?>" />
23
- <input type="hidden" name="payment" value="<?php echo $payment; ?>" />
24
- <input type="submit" name="support_request" class="button-primary" value="Submit request" />
25
- <input id="support_cancel" type="button" value="Cancel" class="button-primary" />
26
- </p>
 
 
 
 
 
 
 
 
27
  </form>
 
28
  </div>
29
 
30
- <?php if (! $ajax) include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
2
  <p>
3
  Request professional services, suggest a feature or submit a bug using the form below:
4
  </p>
 
5
 
6
  <div id="support_container">
7
+ <?php endif; ?>
8
+ <form id="support_form" class="w3tc-ignore-change" action="admin.php?page=<?php echo $this->_page; ?>" method="post" enctype="multipart/form-data">
9
+ <div class="metabox-holder">
10
+ <?php include W3TC_DIR . '/inc/options/support/' . $request_type . '.phtml'; ?>
11
+
12
+ <?php echo $this->postbox_header('Note(s):'); ?>
13
+ <table class="form-table">
14
+ <tr>
15
+ <th colspan="2">
16
+ <ul>
17
+ <li>All submitted data will not be saved and is used solely for the purposes your support request. You will not be added to a mailing list, solicited without your permission, nor will your site be administered after this support case is closed.</li>
18
+ <li>Instead of providing your primary administrative or <acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> accounts, create a new administrator account that can be disabled when the support case is closed.</li>
19
+ <li>Please add the domain w3-edge.com to your <a href="http://en.wikipedia.org/wiki/Whitelist" target="_blank">email whitelist</a> as soon as possible.</li>
20
+ </ul>
21
+ </th>
22
+ </tr>
23
+ </table>
24
+ <?php echo $this->postbox_footer(); ?>
25
+
26
+ <p>
27
+ <input type="hidden" name="request_type" value="<?php echo $request_type; ?>" />
28
+ <input type="hidden" name="request_id" value="<?php echo $request_id; ?>" />
29
+ <input type="hidden" name="payment" value="<?php echo $payment; ?>" />
30
+ <input type="submit" name="support_request" class="button-primary" value="Submit request" />
31
+ <input id="support_cancel" type="button" value="Cancel" class="button-primary" />
32
+ </p>
33
+ </div>
34
  </form>
35
+ <?php if (! $ajax): ?>
36
  </div>
37
 
38
+ <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; endif; ?>
inc/options/support/bug_report.phtml CHANGED
@@ -1,84 +1,80 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_subject">Subject:</label></th>
27
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th valign="top"><label for="support_description">Issue description:</label></th>
31
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
32
- </tr>
33
- <tr>
34
- <th><label for="support_template">Attach template:</label></th>
35
- <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
36
- <?php foreach ($template_files as $template_file): ?>
37
- <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
38
- <?php endforeach; ?>
39
- </select></td>
40
- </tr>
41
- <tr>
42
- <th><label for="support_file">Attach file:</label></th>
43
- <td>
44
- <input id="support_file" type="file" name="files[]" value="" /><br />
45
- <a href="#" id="support_more_files">Attach more files</a>
46
- </td>
47
- </tr>
48
- </table>
49
- </fieldset>
50
-
51
- <fieldset>
52
- <legend>Additional information</legend>
53
-
54
- <table class="form-table">
55
- <tr>
56
- <th><label for="support_phone">Phone:</label></th>
57
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
58
- </tr>
59
- <tr>
60
- <th><label for="support_forum_url">Forum Topic URL:</label></th>
61
- <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
62
- </tr>
63
- <tr>
64
- <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
65
- <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
66
- </tr>
67
- <tr>
68
- <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
69
- <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
70
- </tr>
71
- <tr>
72
- <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
73
- <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
74
- </tr>
75
- <tr>
76
- <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
77
- <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
78
- </tr>
79
- <tr>
80
- <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
81
- <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
82
- </tr>
83
- </table>
84
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information', 'required'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_subject">Subject:</label></th>
25
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_description">Issue description:</label></th>
29
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
30
+ </tr>
31
+ <tr>
32
+ <th><label for="support_template">Attach template:</label></th>
33
+ <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
34
+ <?php foreach ($template_files as $template_file): ?>
35
+ <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
36
+ <?php endforeach; ?>
37
+ </select></td>
38
+ </tr>
39
+ <tr>
40
+ <th><label for="support_file">Attach file:</label></th>
41
+ <td>
42
+ <input id="support_file" type="file" name="files[]" value="" /><br />
43
+ <a href="#" id="support_more_files">Attach more files</a>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+ <?php echo $this->postbox_footer(); ?>
48
 
49
+ <?php echo $this->postbox_header('Additional information'); ?>
50
+ <table class="form-table">
51
+ <tr>
52
+ <th><label for="support_phone">Phone:</label></th>
53
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
54
+ </tr>
55
+ <tr>
56
+ <th><label for="support_forum_url">Forum Topic URL:</label></th>
57
+ <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
58
+ </tr>
59
+ <tr>
60
+ <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
61
+ <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
62
+ </tr>
63
+ <tr>
64
+ <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
65
+ <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
66
+ </tr>
67
+ <tr>
68
+ <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
69
+ <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
70
+ </tr>
71
+ <tr>
72
+ <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
73
+ <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
74
+ </tr>
75
+ <tr>
76
+ <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
77
+ <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
78
+ </tr>
79
+ </table>
80
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support/email_support.phtml CHANGED
@@ -1,84 +1,80 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_subject">Subject:</label></th>
27
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th valign="top"><label for="support_description">Issue description:</label></th>
31
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
32
- </tr>
33
- <tr>
34
- <th><label for="support_template">Attach template:</label></th>
35
- <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
36
- <?php foreach ($template_files as $template_file): ?>
37
- <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
38
- <?php endforeach; ?>
39
- </select></td>
40
- </tr>
41
- <tr>
42
- <th><label for="support_file">Attach file:</label></th>
43
- <td>
44
- <input id="support_file" type="file" name="files[]" value="" /><br />
45
- <a href="#" id="support_more_files">Attach more files</a>
46
- </td>
47
- </tr>
48
- </table>
49
- </fieldset>
50
-
51
- <fieldset>
52
- <legend>Additional information</legend>
53
-
54
- <table class="form-table">
55
- <tr>
56
- <th><label for="support_phone">Phone:</label></th>
57
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
58
- </tr>
59
- <tr>
60
- <th><label for="support_forum_url">Forum Topic URL:</label></th>
61
- <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
62
- </tr>
63
- <tr>
64
- <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
65
- <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
66
- </tr>
67
- <tr>
68
- <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
69
- <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
70
- </tr>
71
- <tr>
72
- <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
73
- <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
74
- </tr>
75
- <tr>
76
- <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
77
- <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
78
- </tr>
79
- <tr>
80
- <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
81
- <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
82
- </tr>
83
- </table>
84
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information', 'required'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_subject">Subject:</label></th>
25
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_description">Issue description:</label></th>
29
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
30
+ </tr>
31
+ <tr>
32
+ <th><label for="support_template">Attach template:</label></th>
33
+ <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
34
+ <?php foreach ($template_files as $template_file): ?>
35
+ <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
36
+ <?php endforeach; ?>
37
+ </select></td>
38
+ </tr>
39
+ <tr>
40
+ <th><label for="support_file">Attach file:</label></th>
41
+ <td>
42
+ <input id="support_file" type="file" name="files[]" value="" /><br />
43
+ <a href="#" id="support_more_files">Attach more files</a>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+ <?php echo $this->postbox_footer(); ?>
48
 
49
+ <?php echo $this->postbox_header('Additional information'); ?>
50
+ <table class="form-table">
51
+ <tr>
52
+ <th><label for="support_phone">Phone:</label></th>
53
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
54
+ </tr>
55
+ <tr>
56
+ <th><label for="support_forum_url">Forum Topic URL:</label></th>
57
+ <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
58
+ </tr>
59
+ <tr>
60
+ <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
61
+ <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
62
+ </tr>
63
+ <tr>
64
+ <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
65
+ <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
66
+ </tr>
67
+ <tr>
68
+ <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
69
+ <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
70
+ </tr>
71
+ <tr>
72
+ <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
73
+ <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
74
+ </tr>
75
+ <tr>
76
+ <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
77
+ <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
78
+ </tr>
79
+ </table>
80
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support/linux_config.phtml CHANGED
@@ -1,72 +1,68 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_subject">Subject:</label></th>
27
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th valign="top"><label for="support_description">Issue description:</label></th>
31
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
32
- </tr>
33
- <tr>
34
- <th><label for="support_file">Attach file:</label></th>
35
- <td>
36
- <input id="support_file" type="file" name="files[]" value="" /><br />
37
- <a href="#" id="support_more_files">Attach more files</a>
38
- </td>
39
- </tr>
40
- <tr>
41
- <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
42
- <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
43
- </tr>
44
- <tr>
45
- <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
46
- <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
47
- </tr>
48
- <tr>
49
- <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
50
- <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
51
- </tr>
52
- <tr>
53
- <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
54
- <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
55
- </tr>
56
- <tr>
57
- <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
58
- <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
59
- </tr>
60
- </table>
61
- </fieldset>
62
-
63
- <fieldset>
64
- <legend>Additional information</legend>
65
-
66
- <table class="form-table">
67
- <tr>
68
- <th><label for="support_phone">Phone:</label></th>
69
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
70
- </tr>
71
- </table>
72
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information', 'required'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_subject">Subject:</label></th>
25
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_description">Issue description:</label></th>
29
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
30
+ </tr>
31
+ <tr>
32
+ <th><label for="support_file">Attach file:</label></th>
33
+ <td>
34
+ <input id="support_file" type="file" name="files[]" value="" /><br />
35
+ <a href="#" id="support_more_files">Attach more files</a>
36
+ </td>
37
+ </tr>
38
+ <tr>
39
+ <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
40
+ <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
41
+ </tr>
42
+ <tr>
43
+ <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
44
+ <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
45
+ </tr>
46
+ <tr>
47
+ <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
48
+ <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
49
+ </tr>
50
+ <tr>
51
+ <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
52
+ <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
53
+ </tr>
54
+ <tr>
55
+ <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
56
+ <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
57
+ </tr>
58
+ </table>
59
+ <?php echo $this->postbox_footer(); ?>
60
 
61
+ <?php echo $this->postbox_header('Additional information'); ?>
62
+ <table class="form-table">
63
+ <tr>
64
+ <th><label for="support_phone">Phone:</label></th>
65
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
66
+ </tr>
67
+ </table>
68
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support/new_feature.phtml CHANGED
@@ -1,49 +1,45 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_subject">Subject:</label></th>
27
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th valign="top"><label for="support_description">Issue description:</label></th>
31
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
32
- </tr>
33
- </table>
34
- </fieldset>
35
-
36
- <fieldset>
37
- <legend>Additional information</legend>
38
-
39
- <table class="form-table">
40
- <tr>
41
- <th><label for="support_phone">Phone:</label></th>
42
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
43
- </tr>
44
- <tr>
45
- <th><label for="support_forum_url">Forum Topic URL:</label></th>
46
- <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
47
- </tr>
48
- </table>
49
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information', 'required'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_subject">Subject:</label></th>
25
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_description">Issue description:</label></th>
29
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
30
+ </tr>
31
+ </table>
32
+ <?php echo $this->postbox_footer(); ?>
33
 
34
+ <?php echo $this->postbox_header('Additional information'); ?>
35
+ <table class="form-table">
36
+ <tr>
37
+ <th><label for="support_phone">Phone:</label></th>
38
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
39
+ </tr>
40
+ <tr>
41
+ <th><label for="support_forum_url">Forum Topic URL:</label></th>
42
+ <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
43
+ </tr>
44
+ </table>
45
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support/phone_support.phtml CHANGED
@@ -1,84 +1,80 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_phone">Phone:</label></th>
27
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th><label for="support_subject">Subject:</label></th>
31
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
32
- </tr>
33
- <tr>
34
- <th valign="top"><label for="support_description">Issue description:</label></th>
35
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
36
- </tr>
37
- <tr>
38
- <th><label for="support_template">Attach template:</label></th>
39
- <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
40
- <?php foreach ($template_files as $template_file): ?>
41
- <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
42
- <?php endforeach; ?>
43
- </select></td>
44
- </tr>
45
- <tr>
46
- <th><label for="support_file">Attach file:</label></th>
47
- <td>
48
- <input id="support_file" type="file" name="files[]" value="" /><br />
49
- <a href="#" id="support_more_files">Attach more files</a>
50
- </td>
51
- </tr>
52
- </table>
53
- </fieldset>
54
-
55
- <fieldset>
56
- <legend>Additional information</legend>
57
-
58
- <table class="form-table">
59
- <tr>
60
- <th><label for="support_forum_url">Forum Topic URL:</label></th>
61
- <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
62
- </tr>
63
- <tr>
64
- <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
65
- <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
66
- </tr>
67
- <tr>
68
- <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
69
- <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
70
- </tr>
71
- <tr>
72
- <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
73
- <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
74
- </tr>
75
- <tr>
76
- <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
77
- <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
78
- </tr>
79
- <tr>
80
- <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
81
- <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
82
- </tr>
83
- </table>
84
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information', 'required'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_phone">Phone:</label></th>
25
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_subject">Subject:</label></th>
29
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
30
+ </tr>
31
+ <tr>
32
+ <th><label for="support_description">Issue description:</label></th>
33
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
34
+ </tr>
35
+ <tr>
36
+ <th><label for="support_template">Attach template:</label></th>
37
+ <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
38
+ <?php foreach ($template_files as $template_file): ?>
39
+ <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
40
+ <?php endforeach; ?>
41
+ </select></td>
42
+ </tr>
43
+ <tr>
44
+ <th><label for="support_file">Attach file:</label></th>
45
+ <td>
46
+ <input id="support_file" type="file" name="files[]" value="" /><br />
47
+ <a href="#" id="support_more_files">Attach more files</a>
48
+ </td>
49
+ </tr>
50
+ </table>
51
+ <?php echo $this->postbox_footer(); ?>
52
 
53
+ <?php echo $this->postbox_header('Additional information'); ?>
54
+ <table class="form-table">
55
+ <tr>
56
+ <th><label for="support_forum_url">Forum Topic URL:</label></th>
57
+ <td><input id="support_forum_url" type="text" name="forum_url" value="<?php echo htmlspecialchars($forum_url); ?>" size="80" /></td>
58
+ </tr>
59
+ <tr>
60
+ <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
61
+ <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
62
+ </tr>
63
+ <tr>
64
+ <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
65
+ <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
66
+ </tr>
67
+ <tr>
68
+ <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
69
+ <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
70
+ </tr>
71
+ <tr>
72
+ <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
73
+ <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
74
+ </tr>
75
+ <tr>
76
+ <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
77
+ <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
78
+ </tr>
79
+ </table>
80
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support/plugin_config.phtml CHANGED
@@ -1,80 +1,76 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_subject">Subject:</label></th>
27
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th valign="top"><label for="support_description">Issue description:</label></th>
31
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
32
- </tr>
33
- <tr>
34
- <th><label for="support_template">Attach template:</label></th>
35
- <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
36
- <?php foreach ($template_files as $template_file): ?>
37
- <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
38
- <?php endforeach; ?>
39
- </select></td>
40
- </tr>
41
- <tr>
42
- <th><label for="support_file">Attach file:</label></th>
43
- <td>
44
- <input id="support_file" type="file" name="files[]" value="" /><br />
45
- <a href="#" id="support_more_files">Attach more files</a>
46
- </td>
47
- </tr>
48
- <tr>
49
- <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
50
- <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
51
- </tr>
52
- <tr>
53
- <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
54
- <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
55
- </tr>
56
- </table>
57
- </fieldset>
58
-
59
- <fieldset>
60
- <legend>Additional information</legend>
61
-
62
- <table class="form-table">
63
- <tr>
64
- <th><label for="support_phone">Phone:</label></th>
65
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
66
- </tr>
67
- <tr>
68
- <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
69
- <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
70
- </tr>
71
- <tr>
72
- <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
73
- <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
74
- </tr>
75
- <tr>
76
- <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
77
- <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
78
- </tr>
79
- </table>
80
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information', 'required'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_subject">Subject:</label></th>
25
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_description">Issue description:</label></th>
29
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
30
+ </tr>
31
+ <tr>
32
+ <th><label for="support_template">Attach template:</label></th>
33
+ <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
34
+ <?php foreach ($template_files as $template_file): ?>
35
+ <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
36
+ <?php endforeach; ?>
37
+ </select></td>
38
+ </tr>
39
+ <tr>
40
+ <th><label for="support_file">Attach file:</label></th>
41
+ <td>
42
+ <input id="support_file" type="file" name="files[]" value="" /><br />
43
+ <a href="#" id="support_more_files">Attach more files</a>
44
+ </td>
45
+ </tr>
46
+ <tr>
47
+ <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
48
+ <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
49
+ </tr>
50
+ <tr>
51
+ <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
52
+ <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
53
+ </tr>
54
+ </table>
55
+ <?php echo $this->postbox_footer(); ?>
56
 
57
+ <?php echo $this->postbox_header('Additional information'); ?>
58
+ <table class="form-table">
59
+ <tr>
60
+ <th><label for="support_phone">Phone:</label></th>
61
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
62
+ </tr>
63
+ <tr>
64
+ <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
65
+ <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
66
+ </tr>
67
+ <tr>
68
+ <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
69
+ <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
70
+ </tr>
71
+ <tr>
72
+ <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
73
+ <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
74
+ </tr>
75
+ </table>
76
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support/theme_config.phtml CHANGED
@@ -1,80 +1,76 @@
1
- <fieldset class="required">
2
- <legend>Required information</legend>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- <table class="form-table">
5
- <tr>
6
- <th valign="top">Request type:</th>
7
- <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
8
- </tr>
9
- <tr>
10
- <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
11
- <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
12
- </tr>
13
- <tr>
14
- <th><label for="support_name">Name:</label></th>
15
- <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
16
- </tr>
17
- <tr>
18
- <th><label for="support_email">E-Mail:</label></th>
19
- <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
20
- </tr>
21
- <tr>
22
- <th><label for="support_twitter">Twitter ID:</label></th>
23
- <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
24
- </tr>
25
- <tr>
26
- <th><label for="support_subject">Subject:</label></th>
27
- <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
28
- </tr>
29
- <tr>
30
- <th valign="top"><label for="support_description">Issue description:</label></th>
31
- <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
32
- </tr>
33
- <tr>
34
- <th><label for="support_template">Attach template:</label></th>
35
- <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
36
- <?php foreach ($template_files as $template_file): ?>
37
- <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
38
- <?php endforeach; ?>
39
- </select></td>
40
- </tr>
41
- <tr>
42
- <th><label for="support_file">Attach file:</label></th>
43
- <td>
44
- <input id="support_file" type="file" name="files[]" value="" /><br />
45
- <a href="#" id="support_more_files">Attach more files</a>
46
- </td>
47
- </tr>
48
- <tr>
49
- <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
50
- <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
51
- </tr>
52
- <tr>
53
- <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
54
- <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
55
- </tr>
56
- <tr>
57
- <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
58
- <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
59
- </tr>
60
- <tr>
61
- <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
62
- <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
63
- </tr>
64
- <tr>
65
- <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
66
- <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
67
- </tr>
68
- </table>
69
- </fieldset>
70
-
71
- <fieldset>
72
- <legend>Additional information</legend>
73
-
74
- <table class="form-table">
75
- <tr>
76
- <th><label for="support_phone">Phone:</label></th>
77
- <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
78
- </tr>
79
- </table>
80
- </fieldset>
1
+ <?php echo $this->postbox_header('Required information'); ?>
2
+ <table class="form-table">
3
+ <tr>
4
+ <th>Request type:</th>
5
+ <td><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></td>
6
+ </tr>
7
+ <tr>
8
+ <th><label for="support_url">Blog <acronym title="Uniform Resource Locator">URL</acronym>:</label></th>
9
+ <td><input id="support_url" type="text" name="url" value="<?php echo htmlspecialchars($url); ?>" size="80" /></td>
10
+ </tr>
11
+ <tr>
12
+ <th><label for="support_name">Name:</label></th>
13
+ <td><input id="support_name" type="text" name="name" value="<?php echo htmlspecialchars($name); ?>" size="80" /></td>
14
+ </tr>
15
+ <tr>
16
+ <th><label for="support_email">E-Mail:</label></th>
17
+ <td><input id="support_email" type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" size="80" /></td>
18
+ </tr>
19
+ <tr>
20
+ <th><label for="support_twitter">Twitter ID:</label></th>
21
+ <td><input id="support_twitter" type="text" name="twitter" value="<?php echo htmlspecialchars($twitter); ?>" size="80" /></td>
22
+ </tr>
23
+ <tr>
24
+ <th><label for="support_subject">Subject:</label></th>
25
+ <td><input id="support_subject" type="text" name="subject" value="<?php echo htmlspecialchars($subject); ?>" size="80" /></td>
26
+ </tr>
27
+ <tr>
28
+ <th><label for="support_description">Issue description:</label></th>
29
+ <td><textarea id="support_description" name="description" cols="70" rows="8"><?php echo htmlspecialchars($description); ?></textarea></td>
30
+ </tr>
31
+ <tr>
32
+ <th><label for="support_template">Attach template:</label></th>
33
+ <td><select id="support_template" name="templates[]" multiple="multiple" size="10" style="height: auto;">
34
+ <?php foreach ($template_files as $template_file): ?>
35
+ <option value="<?php echo htmlspecialchars($template_file); ?>"<?php if (in_array($template_file, $templates)): ?> selected="selected"<?php endif; ?>><?php echo htmlspecialchars($template_file); ?></option>
36
+ <?php endforeach; ?>
37
+ </select></td>
38
+ </tr>
39
+ <tr>
40
+ <th><label for="support_file">Attach file:</label></th>
41
+ <td>
42
+ <input id="support_file" type="file" name="files[]" value="" /><br />
43
+ <a href="#" id="support_more_files">Attach more files</a>
44
+ </td>
45
+ </tr>
46
+ <tr>
47
+ <th><label for="support_wp_login"><acronym title="WordPress">WP</acronym> Admin login:</label></th>
48
+ <td><input id="support_wp_login" type="text" name="wp_login" value="<?php echo htmlspecialchars($wp_login); ?>" size="80" /></td>
49
+ </tr>
50
+ <tr>
51
+ <th><label for="support_wp_password"><acronym title="WordPress">WP</acronym> Admin password:</label></th>
52
+ <td><input id="support_wp_password" type="text" name="wp_password" value="<?php echo htmlspecialchars($wp_password); ?>" size="80" /></td>
53
+ </tr>
54
+ <tr>
55
+ <th><label for="support_ftp_host"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> host:</label></th>
56
+ <td><input id="support_ftp_host" type="text" name="ftp_host" value="<?php echo htmlspecialchars($ftp_host); ?>" size="80" /></td>
57
+ </tr>
58
+ <tr>
59
+ <th><label for="support_ftp_login"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> login:</label></th>
60
+ <td><input id="support_ftp_login" type="text" name="ftp_login" value="<?php echo htmlspecialchars($ftp_login); ?>" size="80" /></td>
61
+ </tr>
62
+ <tr>
63
+ <th><label for="support_ftp_password"><acronym title="Secure Shell">SSH</acronym> / <acronym title="File Transfer Protocol">FTP</acronym> password:</label></th>
64
+ <td><input id="support_ftp_password" type="text" name="ftp_password" value="<?php echo htmlspecialchars($ftp_password); ?>" size="80" /></td>
65
+ </tr>
66
+ </table>
67
+ <?php echo $this->postbox_footer(); ?>
68
 
69
+ <?php echo $this->postbox_header('Additional information'); ?>
70
+ <table class="form-table">
71
+ <tr>
72
+ <th><label for="support_phone">Phone:</label></th>
73
+ <td><input id="support_phone" type="text" name="phone" value="<?php echo htmlspecialchars($phone); ?>" size="80" /></td>
74
+ </tr>
75
+ </table>
76
+ <?php echo $this->postbox_footer(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/options/support_payment.phtml CHANGED
@@ -2,12 +2,12 @@
2
  <p>
3
  Request professional services, suggest a feature or submit a bug using the form below:
4
  </p>
5
- <?php endif; ?>
6
 
7
  <div id="support_container">
 
8
  <form action="<?php echo W3TC_PAYPAL_URL; ?>" method="get">
9
- <fieldset>
10
- <legend>Request payment</legend>
11
 
12
  <p><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></p>
13
 
@@ -16,7 +16,7 @@
16
  <p>
17
  <input type="hidden" name="cmd" value="_xclick" />
18
  <input type="hidden" name="business" value="<?php echo W3TC_PAYPAL_BUSINESS; ?>" />
19
- <input type="hidden" name="item_name" value="<?php echo htmlspecialchars($this->_request_types[$request_type]); ?>" />
20
  <input type="hidden" name="amount" value="<?php echo sprintf('%.2f', $this->_request_prices[$request_type]); ?>" />
21
  <input type="hidden" name="currency_code" value="USD" />
22
  <input type="hidden" name="no_shipping" value="1" />
@@ -26,8 +26,10 @@
26
  <input type="submit" class="button-primary" value="Buy now" />
27
  <input id="support_cancel" type="button" value="Cancel" class="button-primary" />
28
  </p>
29
- </fieldset>
 
30
  </form>
 
31
  </div>
32
 
33
- <?php if (! $ajax) include W3TC_DIR . '/inc/options/common/footer.phtml'; ?>
2
  <p>
3
  Request professional services, suggest a feature or submit a bug using the form below:
4
  </p>
 
5
 
6
  <div id="support_container">
7
+ <?php endif; ?>
8
  <form action="<?php echo W3TC_PAYPAL_URL; ?>" method="get">
9
+ <div class="metabox-holder">
10
+ <?php echo $this->postbox_header('Request payment'); ?>
11
 
12
  <p><?php echo htmlspecialchars($this->_request_types[$request_type]); ?></p>
13
 
16
  <p>
17
  <input type="hidden" name="cmd" value="_xclick" />
18
  <input type="hidden" name="business" value="<?php echo W3TC_PAYPAL_BUSINESS; ?>" />
19
+ <input type="hidden" name="item_name" value="<?php echo htmlspecialchars(sprintf('%s: %s (#%s)', ucfirst(w3_get_host()), $this->_request_types[$request_type], $request_id)); ?>" />
20
  <input type="hidden" name="amount" value="<?php echo sprintf('%.2f', $this->_request_prices[$request_type]); ?>" />
21
  <input type="hidden" name="currency_code" value="USD" />
22
  <input type="hidden" name="no_shipping" value="1" />
26
  <input type="submit" class="button-primary" value="Buy now" />
27
  <input id="support_cancel" type="button" value="Cancel" class="button-primary" />
28
  </p>
29
+ <?php echo $this->postbox_footer(); ?>
30
+ </div>
31
  </form>
32
+ <?php if (! $ajax): ?>
33
  </div>
34
 
35
+ <?php include W3TC_DIR . '/inc/options/common/footer.phtml'; endif; ?>
inc/options/support_select.phtml CHANGED
@@ -5,13 +5,12 @@
5
  <?php endif; ?>
6
 
7
  <div id="support_container">
8
- <form id="support_select_form" action="admin.php" method="get">
9
- <fieldset>
10
- <legend>Choose request type</legend>
11
-
12
  <table class="form-table">
13
  <tr>
14
- <th valign="top"><label for="support_request_type">Request type:</label></th>
15
  <td>
16
  <input type="hidden" name="page" value="<?php echo $this->_page; ?>" />
17
  <select id="support_request_type" name="request_type">
@@ -27,7 +26,8 @@
27
  </td>
28
  </tr>
29
  </table>
30
- </fieldset>
 
31
  </form>
32
  </div>
33
 
5
  <?php endif; ?>
6
 
7
  <div id="support_container">
8
+ <form id="support_select_form" class="w3tc-ignore-change" action="admin.php" method="get">
9
+ <div class="metabox-holder">
10
+ <?php echo $this->postbox_header('Choose request type'); ?>
 
11
  <table class="form-table">
12
  <tr>
13
+ <th><label for="support_request_type">Request type:</label></th>
14
  <td>
15
  <input type="hidden" name="page" value="<?php echo $this->_page; ?>" />
16
  <select id="support_request_type" name="request_type">
26
  </td>
27
  </tr>
28
  </table>
29
+ <?php echo $this->postbox_footer(); ?>
30
+ </div>
31
  </form>
32
  </div>
33
 
inc/plugin.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * W3 Total Cache plugins API
5
+ */
6
+
7
+ /**
8
+ * Add W3TC action callback
9
+ *
10
+ * @param string $action
11
+ * @param mixed $callback
12
+ * @return void
13
+ */
14
+ function w3tc_add_action($action, $callback) {
15
+ $GLOBALS['_w3tc_actions'][$action][] = $callback;
16
+ }
17
+
18
+ /**
19
+ * Do W3TC action
20
+ *
21
+ * @param string $action
22
+ * @param mixed $value
23
+ * @return mixed
24
+ */
25
+ function w3tc_do_action($action, $value = null) {
26
+ if (isset($GLOBALS['_w3tc_actions'][$action])) {
27
+ foreach ((array) $GLOBALS['_w3tc_actions'][$action] as $callback) {
28
+ if (is_callable($callback)) {
29
+ $value = call_user_func($callback, $value);
30
+ }
31
+ }
32
+ }
33
+
34
+ return $value;
35
+ }
36
+
37
+ /**
38
+ * Shortcut for page cache flush
39
+ *
40
+ * @return boolean
41
+ */
42
+ function w3tc_pgcache_flush() {
43
+ require_once W3TC_LIB_W3_DIR . '/PgCache.php';
44
+
45
+ $w3_pgcache = & W3_PgCache::instance();
46
+
47
+ return $w3_pgcache->flush();
48
+ }
49
+
50
+ /**
51
+ * Shortcut for page post cache flush
52
+ *
53
+ * @param integer $post_id
54
+ * @return boolean
55
+ */
56
+ function w3tc_pgcache_flush_post($post_id) {
57
+ require_once W3TC_LIB_W3_DIR . '/PgCache.php';
58
+
59
+ $w3_pgcache = & W3_PgCache::instance();
60
+
61
+ return $w3_pgcache->flush_post($post_id);
62
+ }
63
+
64
+ /**
65
+ * Shortcut for database cache flush
66
+ *
67
+ * @return boolean
68
+ */
69
+ function w3tc_dbcache_flush() {
70
+ require_once W3TC_LIB_W3_DIR . '/Db.php';
71
+
72
+ $w3_db = & W3_Db::instance();
73
+
74
+ return $w3_db->flush_cache();
75
+ }
76
+
77
+ /**
78
+ * Shortcut for minify cache flush
79
+ *
80
+ * @return boolean
81
+ */
82
+ function w3tc_minify_flush() {
83
+ require_once W3TC_LIB_W3_DIR . '/Minify.php';
84
+
85
+ $w3_minify = & W3_Minify::instance();
86
+
87
+ return $w3_minify->flush();
88
+ }
89
+
90
+ /**
91
+ * Shortcut for objectcache cache flush
92
+ *
93
+ * @return boolean
94
+ */
95
+ function w3tc_objectcache_flush() {
96
+ require_once W3TC_LIB_W3_DIR . '/ObjectCache.php';
97
+
98
+ $w3_objectcache = & W3_ObjectCache::instance();
99
+
100
+ return $w3_objectcache->flush();
101
+ }
102
+
103
+ /**
104
+ * Prints script tag for scripts group
105
+ *
106
+ * @param string $location
107
+ * @retun void
108
+ */
109
+ function w3tc_minify_script_group($location) {
110
+ require_once W3TC_LIB_W3_DIR . '/Plugin/Minify.php';
111
+
112
+ $w3_plugin_minify = & W3_Plugin_Minify::instance();
113
+ $w3_plugin_minify->printed_scripts[] = $location;
114
+
115
+ echo $w3_plugin_minify->get_script_group($location);
116
+ }
117
+
118
+ /**
119
+ * Prints style tag for styles group
120
+ *
121
+ * @param string $location
122
+ * @retun void
123
+ */
124
+ function w3tc_minify_style_group($location) {
125
+ require_once W3TC_LIB_W3_DIR . '/Plugin/Minify.php';
126
+
127
+ $w3_plugin_minify = & W3_Plugin_Minify::instance();
128
+ $w3_plugin_minify->printed_styles[] = $location;
129
+
130
+ echo $w3_plugin_minify->get_style_group($location);
131
+ }
132
+
133
+ /**
134
+ * Prints script tag for custom scripts
135
+ *
136
+ * @param string|array $files
137
+ * @param boolean $blocking
138
+ * @return void
139
+ */
140
+ function w3tc_minify_script_custom($files, $blocking = true) {
141
+ require_once W3TC_LIB_W3_DIR . '/Plugin/Minify.php';
142
+
143
+ $w3_plugin_minify = & W3_Plugin_Minify::instance();
144
+
145
+ echo $w3_plugin_minify->get_script_custom($files, $blocking);
146
+ }
147
+
148
+ /**
149
+ * Prints style tag for custom styles
150
+ *
151
+ * @param string|array $files
152
+ * @param boolean $import
153
+ * @return void
154
+ */
155
+ function w3tc_minify_style_custom($files, $import = false) {
156
+ require_once W3TC_LIB_W3_DIR . '/Plugin/Minify.php';
157
+
158
+ $w3_plugin_minify = & W3_Plugin_Minify::instance();
159
+
160
+ echo $w3_plugin_minify->get_style_custom($files, $import);
161
+ }
inc/popup/cdn_export_file.phtml CHANGED
@@ -1,6 +1,6 @@
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
- <script type="text/javascript">
4
  var files = [
5
  <?php $files_count = count($files); foreach ($files as $index => $file): ?>
6
  '<?php echo addslashes($file); ?>'<?php if ($index < $files_count - 1): ?>,<?php endif; ?>
@@ -38,7 +38,7 @@ jQuery(function() {
38
  </table>
39
 
40
  <p>
41
- <input id="cdn_export_file_start" class="button" type="button" value="Start"<?php if (! $files_count): ?> disabled="disabled"<?php endif; ?> />
42
  </p>
43
 
44
  <div id="cdn_export_file_progress" class="progress">
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
+ <script>
4
  var files = [
5
  <?php $files_count = count($files); foreach ($files as $index => $file): ?>
6
  '<?php echo addslashes($file); ?>'<?php if ($index < $files_count - 1): ?>,<?php endif; ?>
38
  </table>
39
 
40
  <p>
41
+ <input id="cdn_export_file_start" class="button-primary" type="button" value="Start"<?php if (! $files_count): ?> disabled="disabled"<?php endif; ?> />
42
  </p>
43
 
44
  <div id="cdn_export_file_progress" class="progress">
inc/popup/cdn_export_library.phtml CHANGED
@@ -1,6 +1,6 @@
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
- <script type="text/javascript">
4
  /*<![CDATA[*/
5
  jQuery(function() {
6
  W3tc_Popup_Cdn_Export_Library.init();
@@ -33,7 +33,7 @@ jQuery(function() {
33
  </table>
34
 
35
  <p>
36
- <input id="cdn_export_library_start" class="button" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
37
  </p>
38
 
39
  <div id="cdn_export_library_progress" class="progress">
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
+ <script>
4
  /*<![CDATA[*/
5
  jQuery(function() {
6
  W3tc_Popup_Cdn_Export_Library.init();
33
  </table>
34
 
35
  <p>
36
+ <input id="cdn_export_library_start" class="button-primary" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
37
  </p>
38
 
39
  <div id="cdn_export_library_progress" class="progress">
inc/popup/cdn_import_library.phtml CHANGED
@@ -1,6 +1,6 @@
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
- <script type="text/javascript">
4
  /*<![CDATA[*/
5
  var cdn_host = '<?php echo $cdn_host; ?>';
6
 
@@ -45,7 +45,7 @@ jQuery(function() {
45
  </table>
46
 
47
  <p>
48
- <input id="cdn_import_library_start" class="button" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
49
  </p>
50
 
51
  <div id="cdn_import_library_progress" class="progress">
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
+ <script>
4
  /*<![CDATA[*/
5
  var cdn_host = '<?php echo $cdn_host; ?>';
6
 
45
  </table>
46
 
47
  <p>
48
+ <input id="cdn_import_library_start" class="button-primary" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
49
  </p>
50
 
51
  <div id="cdn_import_library_progress" class="progress">
inc/popup/cdn_purge.phtml ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
+
3
+ <p>
4
+ Remove objects from the CDN by specifying the relative path on individual lines below and clicking the "Purge" button when done. For example:
5
+ </p>
6
+ <p>
7
+ <?php switch ($this->_config->get_string('cdn.engine')):
8
+ case 'cotendo': ?>
9
+ <ul>
10
+ <li><em>wp-content/themes/twentyten/images/headers/</em> &mdash; the folder itself (only when accessed directly without any file).</li>
11
+ <li><em>wp-content/themes/twentyten/images/headers/*.</em> &mdash; all files in the folder with no extension, with all parameter variations.</li>
12
+ <li><em>wp-content/themes/twentyten/images/headers/*.jpg</em> &mdash; all files in the folder whose extension is "jpg".</li>
13
+ <li><em>wp-content/themes/twentyten/images/headers/path</em> &mdash; the specific file (when the file does not have an extension), and without parameters.</li>
14
+ <li><em>wp-content/themes/twentyten/images/headers/path.jpg</em> &mdash; the specific file with its extension, and without parameters.</li>
15
+ <li><em>wp-content/themes/twentyten/images/headers/path.jpg?*</em> &mdash; the specific file with its extension, with all variation of parameters.</li>
16
+ <li><em>wp-content/themes/twentyten/images/headers/path.jpg?key=value</em> &mdash; the specific file with its extension, with the specific parameters.</li>
17
+ </ul>
18
+ <?php break;
19
+
20
+ default: ?>
21
+ <em>wp-content/themes/twentyten/images/headers/path.jpg</em>
22
+ <?php break;
23
+ endswitch; ?>
24
+ </p>
25
+
26
+
27
+ <form action="admin.php?page=<?php echo $this->_page; ?>" method="post">
28
+ <p>Files to purge:</p>
29
+ <p>
30
+ <textarea name="files" rows="10" cols="90"></textarea>
31
+ </p>
32
+ <p>
33
+ <input type="hidden" name="w3tc_action" value="cdn_purge_post" />
34
+ <input class="button-primary" type="submit" value="Purge" />
35
+ </p>
36
+ </form>
37
+
38
+ <div class="log">
39
+ <?php foreach ($results as $result): ?>
40
+ <div class="log-<?php echo ($result['result'] == W3TC_CDN_RESULT_OK ? 'success' : 'error') ?>">
41
+ <?php echo htmlspecialchars($result['remote_path']); ?>
42
+ <strong><?php echo htmlspecialchars($result['error']); ?></strong>
43
+ </div>
44
+ <?php endforeach; ?>
45
+ </div>
46
+
47
+ <?php include W3TC_DIR . '/inc/popup/common/footer.phtml'; ?>
inc/popup/cdn_queue.phtml CHANGED
@@ -3,10 +3,11 @@
3
  <p>This tool lists the pending file uploads and deletions.</p>
4
  <p id="w3tc-options-menu">
5
  <a href="#cdn_queue_upload" rel="#cdn_queue_upload" class="tab<?php if ($cdn_queue_tab == 'upload'): ?> tab-selected<?php endif; ?>">Upload queue</a> |
6
- <a href="#cdn_queue_delete" rel="#cdn_queue_delete" class="tab<?php if ($cdn_queue_tab == 'delete'): ?> tab-selected<?php endif; ?>">Delete queue</a>
 
7
  </p>
8
 
9
- <div id="cdn_queue_upload" class="tab-content"<?php if ($cdn_queue_tab != 'upload'): ?> style="display:none;"<?php endif; ?>>
10
  <?php if (! empty($queue[W3TC_CDN_COMMAND_UPLOAD])): ?>
11
  <table class="table queue">
12
  <tr>
@@ -36,7 +37,7 @@
36
  <?php endif; ?>
37
  </div>
38
 
39
- <div id="cdn_queue_delete" class="tab-content"<?php if ($cdn_queue_tab != 'delete'): ?> style="display:none;"<?php endif; ?>>
40
  <?php if (! empty($queue[W3TC_CDN_COMMAND_DELETE])): ?>
41
  <table class="table queue">
42
  <tr>
@@ -59,11 +60,41 @@
59
  <?php endforeach; ?>
60
  </table>
61
  <p>
62
- <a href="admin.php?page=w3tc_cdn&amp;w3tc_action=cdn_queue&amp;cdn_queue_tab=delete&amp;cdn_queue_action=empty&amp;cdn_queue_type=<?php echo W3TC_CDN_COMMAND_DELETE; ?>" class="cdn_queue_empty">Empty upload queue</a>
63
  </p>
64
  <?php else: ?>
65
  <p class="empty">Delete queue is empty</p>
66
  <?php endif; ?>
67
  </div>
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  <?php include W3TC_DIR . '/inc/popup/common/footer.phtml'; ?>
3
  <p>This tool lists the pending file uploads and deletions.</p>
4
  <p id="w3tc-options-menu">
5
  <a href="#cdn_queue_upload" rel="#cdn_queue_upload" class="tab<?php if ($cdn_queue_tab == 'upload'): ?> tab-selected<?php endif; ?>">Upload queue</a> |
6
+ <a href="#cdn_queue_delete" rel="#cdn_queue_delete" class="tab<?php if ($cdn_queue_tab == 'delete'): ?> tab-selected<?php endif; ?>">Delete queue</a> |
7
+ <a href="#cdn_queue_purge" rel="#cdn_queue_purge" class="tab<?php if ($cdn_queue_tab == 'purge'): ?> tab-selected<?php endif; ?>">Purge queue</a>
8
  </p>
9
 
10
+ <div id="cdn_queue_upload" class="tab-content"<?php if ($cdn_queue_tab != 'upload'): ?> style="display: none;"<?php endif; ?>>
11
  <?php if (! empty($queue[W3TC_CDN_COMMAND_UPLOAD])): ?>
12
  <table class="table queue">
13
  <tr>
37
  <?php endif; ?>
38
  </div>
39
 
40
+ <div id="cdn_queue_delete" class="tab-content"<?php if ($cdn_queue_tab != 'delete'): ?> style="display: none;"<?php endif; ?>>
41
  <?php if (! empty($queue[W3TC_CDN_COMMAND_DELETE])): ?>
42
  <table class="table queue">
43
  <tr>
60
  <?php endforeach; ?>
61
  </table>
62
  <p>
63
+ <a href="admin.php?page=w3tc_cdn&amp;w3tc_action=cdn_queue&amp;cdn_queue_tab=delete&amp;cdn_queue_action=empty&amp;cdn_queue_type=<?php echo W3TC_CDN_COMMAND_DELETE; ?>" class="cdn_queue_empty">Empty delete queue</a>
64
  </p>
65
  <?php else: ?>
66
  <p class="empty">Delete queue is empty</p>
67
  <?php endif; ?>
68
  </div>
69
 
70
+ <div id="cdn_queue_purge" class="tab-content"<?php if ($cdn_queue_tab != 'purge'): ?> style="display: none;"<?php endif; ?>>
71
+ <?php if (! empty($queue[W3TC_CDN_COMMAND_PURGE])): ?>
72
+ <table class="table queue">
73
+ <tr>
74
+ <th>Local Path</th>
75
+ <th>Remote Path</th>
76
+ <th>Last Error</th>
77
+ <th width="25%">Date</th>
78
+ <th width="10%">Delete</th>
79
+ </tr>
80
+ <?php foreach ((array) $queue[W3TC_CDN_COMMAND_PURGE] as $result): ?>
81
+ <tr>
82
+ <td><?php echo htmlspecialchars($result->local_path); ?></td>
83
+ <td><?php echo htmlspecialchars($result->remote_path); ?></td>
84
+ <td><?php echo htmlspecialchars($result->last_error); ?></td>
85
+ <td align="center"><?php echo htmlspecialchars($result->date); ?></td>
86
+ <td align="center">
87
+ <a href="admin.php?page=w3tc_cdn&amp;w3tc_action=cdn_queue&amp;cdn_queue_tab=purge&amp;cdn_queue_action=delete&amp;cdn_queue_id=<?php echo $result->id; ?>" class="cdn_queue_delete">Delete</a>
88
+ </td>
89
+ </tr>
90
+ <?php endforeach; ?>
91
+ </table>
92
+ <p>
93
+ <a href="admin.php?page=w3tc_cdn&amp;w3tc_action=cdn_queue&amp;cdn_queue_tab=purge&amp;cdn_queue_action=empty&amp;cdn_queue_type=<?php echo W3TC_CDN_COMMAND_PURGE; ?>" class="cdn_queue_empty">Empty purge queue</a>
94
+ </p>
95
+ <?php else: ?>
96
+ <p class="empty">Purge queue is empty</p>
97
+ <?php endif; ?>
98
+ </div>
99
+
100
  <?php include W3TC_DIR . '/inc/popup/common/footer.phtml'; ?>
inc/popup/cdn_rename_domain.phtml CHANGED
@@ -1,6 +1,6 @@
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
- <script type="text/javascript">
4
  /*<![CDATA[*/
5
  jQuery(function() {
6
  W3tc_Popup_Cdn_Rename_Domain.init();
@@ -40,7 +40,7 @@ jQuery(function() {
40
  </table>
41
 
42
  <p>
43
- <input id="cdn_rename_domain_start" class="button" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
44
  </p>
45
 
46
  <div id="cdn_rename_domain_progress" class="progress">
1
  <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
 
3
+ <script>
4
  /*<![CDATA[*/
5
  jQuery(function() {
6
  W3tc_Popup_Cdn_Rename_Domain.init();
40
  </table>
41
 
42
  <p>
43
+ <input id="cdn_rename_domain_start" class="button-primary" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
44
  </p>
45
 
46
  <div id="cdn_rename_domain_progress" class="progress">
inc/popup/common/header.phtml CHANGED
@@ -14,9 +14,9 @@
14
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
15
  <html xmlns="http://www.w3.org/1999/xhtml" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>>
16
  <head>
17
- <link rel="stylesheet" type="text/css" href="<?php echo WP_PLUGIN_URL; ?>/w3-total-cache/inc/css/popup.css?ver=<?php echo W3TC_VERSION; ?>"></link>
18
- <script type="text/javascript" src="<?php echo w3_get_site_url(); ?>/<?php echo WPINC; ?>/js/jquery/jquery.js?ver=<?php echo W3TC_VERSION; ?>"></script>
19
- <script type="text/javascript" src="<?php echo WP_PLUGIN_URL; ?>/w3-total-cache/inc/js/popup.js?ver=<?php echo W3TC_VERSION; ?>"></script>
20
  <title><?php echo htmlspecialchars($title); ?> - W3 Total Cache</title>
21
  <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
22
  </head>
14
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
15
  <html xmlns="http://www.w3.org/1999/xhtml" <?php do_action('admin_xml_ns'); ?> <?php language_attributes(); ?>>
16
  <head>
17
+ <link rel="stylesheet" type="text/css" href="<?php echo plugins_url('inc/css/popup.css?ver=' . W3TC_VERSION, W3TC_FILE); ?>" />
18
+ <script src="<?php echo site_url('wp-includes/js/jquery/jquery.js?ver=' . W3TC_VERSION); ?>"></script>
19
+ <script src="<?php echo plugins_url('inc/js/popup.js?ver=' . W3TC_VERSION, W3TC_FILE); ?>"></script>
20
  <title><?php echo htmlspecialchars($title); ?> - W3 Total Cache</title>
21
  <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
22
  </head>
inc/popup/pagespeed_results.phtml ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php include W3TC_DIR . '/inc/popup/common/header.phtml'; ?>
2
+
3
+ <?php if ($results): ?>
4
+ <h4>Page Speed Score: <?php echo $results['score']; ?>/100</h4>
5
+
6
+ <p>
7
+ <input class="button ps-expand-all" type="button" value="Expand all" />
8
+ <input class="button ps-collapse-all" type="button" value="Collapse all" />
9
+ <input class="button ps-refresh" type="button" value="Refresh analysis" />
10
+ </p>
11
+
12
+ <ul class="ps-rules">
13
+ <?php foreach ($results['rules'] as $index => $rule): ?>
14
+ <li class="ps-rule ps-priority-<?php echo $rule['priority']; ?>">
15
+ <div class="ps-icon"><div></div></div>
16
+ <div class="ps-expand"><?php if (count($rule['blocks'])): ?><a href="#">+</a><?php endif; ?></div>
17
+ <p><?php echo $rule['name']; ?></p>
18
+
19
+ <?php if (count($rule['blocks']) || count($rule['resolution'])): ?>
20
+ <div class="ps-expander">
21
+ <?php if (count($rule['blocks'])): ?>
22
+ <ul class="ps-blocks">
23
+ <?php foreach ($rule['blocks'] as $block): ?>
24
+ <li class="ps-block">
25
+ <p><?php echo $block['header']; ?></p>
26
+
27
+ <?php if (count($block['urls'])): ?>
28
+ <ul class="ps-urls">
29
+ <?php foreach ($block['urls'] as $url): ?>
30
+ <li class="ps-url"><?php echo $url['result']; ?></li>
31
+ <?php endforeach; ?>
32
+ </ul>
33
+ <?php endif; ?>
34
+ </li>
35
+ <?php endforeach; ?>
36
+ </ul>
37
+ <?php endif; ?>
38
+
39
+ <?php if (count($rule['resolution'])): ?>
40
+ <p><strong>Resolution:</strong> <?php echo $rule['resolution']['header']; ?></p>
41
+ <?php endif; ?>
42
+ </div>
43
+ <?php endif; ?>
44
+ </li>
45
+ <?php endforeach; ?>
46
+ </ul>
47
+ <?php else: ?>
48
+ <p>Unable to fetch Page Speed results.</p>
49
+ <p>
50
+ <input class="button ps-refresh" type="button" value="Refresh Analysis" />
51
+ </p>
52
+ <?php endif; ?>
53
+
54
+ <?php include W3TC_DIR . '/inc/popup/common/footer.phtml'; ?>
inc/widget/latest_control.phtml CHANGED
@@ -1,4 +1,6 @@
1
  <p>
2
- <label for="w3tc_latest">How many items would you like to display?</label>
3
- <input id="w3tc_latest" type="text" name="w3tc_latest_items" value="<?php echo $this->_config->get_integer('widget.latest.items'); ?>" size="5" />
 
 
4
  </p>
1
  <p>
2
+ <label>
3
+ How many items would you like to display?
4
+ <input type="text" name="w3tc_widget_latest_items" value="<?php echo $this->_config->get_integer('widget.latest.items'); ?>" size="5" />
5
+ </label>
6
  </p>
inc/widget/pagespeed.phtml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ($results): ?>
2
+ <h4>Page Speed Score: <?php echo $results['score']; ?>/100</h4>
3
+
4
+ <ul class="w3tc-widget-ps-rules">
5
+ <?php foreach ($results['rules'] as $index => $rule): if ($index > 5) break; ?>
6
+ <li class="w3tc-widget-ps-rule w3tc-widget-ps-priority-<?php echo $rule['priority']; ?>">
7
+ <div class="w3tc-widget-ps-icon"><div></div></div>
8
+ <p><?php echo $rule['name']; ?></p>
9
+ </li>
10
+ <?php endforeach; ?>
11
+ </ul>
12
+
13
+ <p>
14
+ <input class="button w3tc-widget-ps-refresh" type="button" value="Refresh analysis" />
15
+ <input class="button w3tc-widget-ps-view-all" type="button" value="View all results" />
16
+ </p>
17
+ <?php else: ?>
18
+ <?php if ($key): ?>
19
+ <p>Unable to fetch Page Speed results.</p>
20
+ <p><input class="button w3tc-widget-ps-refresh" type="button" value="Refresh Analysis" /></p>
21
+ <?php else: ?>
22
+ <p>Google Page Speed score is not available. Please follow the directions found in the Miscellanous settings box on the <a href="admin.php?page=w3tc_general">General Settings</a> tab.</p>
23
+ <?php endif; ?>
24
+ <?php endif; ?>
inc/widget/pagespeed_control.phtml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <p>
2
+ <label>
3
+ Page Speed API Key:
4
+ <input type="text" name="w3tc_widget_pagespeed_key" value="<?php echo $this->_config->get_string('widget.pagespeed.key'); ?>" size="60" />
5
+ </label>
6
+ </p>
7
+ <p>To acquire an API key, visit the <a href="https://code.google.com/apis/console" target="_blank">APIs Console</a>. Go to the Project Home tab, activate the Page Speed Online API, and accept the Terms of Service.</p>
8
+ <p>Then go to the API Access tab. The API key is in the Simple API Access section.</p>
lib/CF/cloudfiles.php CHANGED
@@ -76,8 +76,9 @@ require("cloudfiles_http.php");
76
  define("DEFAULT_CF_API_VERSION", 1);
77
  define("MAX_CONTAINER_NAME_LEN", 256);
78
  define("MAX_OBJECT_NAME_LEN", 1024);
79
- define("MAX_OBJECT_SIZE", 5*1024*1024*1024+1); # bigger than S3! ;-)
80
-
 
81
  /**
82
  * Class for handling Cloud Files Authentication, call it's {@link authenticate()}
83
  * method to obtain authorized service urls and an authentication token.
@@ -88,6 +89,14 @@ define("MAX_OBJECT_SIZE", 5*1024*1024*1024+1); # bigger than S3! ;-)
88
  * #
89
  * $auth = new CF_Authentication("username", "api_key");
90
  *
 
 
 
 
 
 
 
 
91
  * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
92
  * # file. This API ships with a newer version obtained directly from
93
  * # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
@@ -122,10 +131,10 @@ class CF_Authentication
122
  *
123
  * @param string $username Mosso username
124
  * @param string $api_key Mosso API Access Key
125
- * @param string $account <b>Deprecated</b> <i>Account name</i>
126
- * @param string $auth_host <b>Deprecated</b> <i>Authentication service URI</i>
127
  */
128
- function __construct($username=NULL, $api_key=NULL, $account=NULL, $auth_host=NULL)
129
  {
130
 
131
  $this->dbug = False;
@@ -757,13 +766,14 @@ class CF_Connection
757
  * )
758
  * </code>
759
  *
 
760
  * @return array list of published Container names
761
  * @throws InvalidResponseException unexpected response
762
  */
763
- function list_public_containers()
764
  {
765
  list($status, $reason, $containers) =
766
- $this->cfs_http->list_cdn_containers();
767
  #if ($status == 401 && $this->_re_auth()) {
768
  # return $this->list_public_containers();
769
  #}
76
  define("DEFAULT_CF_API_VERSION", 1);
77
  define("MAX_CONTAINER_NAME_LEN", 256);
78
  define("MAX_OBJECT_NAME_LEN", 1024);
79
+ define("MAX_OBJECT_SIZE", 5*1024*1024*1024+1);
80
+ define("US_AUTHURL", "https://auth.api.rackspacecloud.com");
81
+ define("UK_AUTHURL", "https://lon.auth.api.rackspacecloud.com");
82
  /**
83
  * Class for handling Cloud Files Authentication, call it's {@link authenticate()}
84
  * method to obtain authorized service urls and an authentication token.
89
  * #
90
  * $auth = new CF_Authentication("username", "api_key");
91
  *
92
+ * # NOTE: For UK Customers please specify your AuthURL Manually
93
+ * # There is a Predfined constant to use EX:
94
+ * #
95
+ * # $auth = new CF_Authentication("username, "api_key", NULL, UK_AUTHURL);
96
+ * # Using the UK_AUTHURL keyword will force the api to use the UK AuthUrl.
97
+ * # rather then the US one. The NULL Is passed for legacy purposes and must
98
+ * # be passed to function correctly.
99
+ *
100
  * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
101
  * # file. This API ships with a newer version obtained directly from
102
  * # cURL's web site (http://curl.haxx.se). To use the newer CA bundle,
131
  *
132
  * @param string $username Mosso username
133
  * @param string $api_key Mosso API Access Key
134
+ * @param string $account <i>Account name</i>
135
+ * @param string $auth_host <i>Authentication service URI</i>
136
  */
137
+ function __construct($username=NULL, $api_key=NULL, $account=NULL, $auth_host=US_AUTHURL)
138
  {
139
 
140
  $this->dbug = False;
766
  * )
767
  * </code>
768
  *
769
+ * @param bool $enabled_only Will list all containers ever CDN enabled if * set to false or only currently enabled CDN containers if set to true. * Defaults to false.
770
  * @return array list of published Container names
771
  * @throws InvalidResponseException unexpected response
772
  */
773
+ function list_public_containers($enabled_only=False)
774
  {
775
  list($status, $reason, $containers) =
776
+ $this->cfs_http->list_cdn_containers($enabled_only);
777
  #if ($status == 401 && $this->_re_auth()) {
778
  # return $this->list_public_containers();
779
  #}
lib/CF/cloudfiles_http.php CHANGED
@@ -29,7 +29,7 @@
29
  */
30
  require_once("cloudfiles_exceptions.php");
31
 
32
- define("PHP_CF_VERSION", "1.7.4");
33
  define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
34
  define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
35
  define("ACCOUNT_BYTES_USED", "X-Account-Bytes-Used");
@@ -183,7 +183,7 @@ class CF_Http
183
  function authenticate($user, $pass, $acct=NULL, $host=NULL)
184
  {
185
  $path = array();
186
- if (isset($acct) || isset($host)) {
187
  $headers = array(
188
  sprintf("%s: %s", AUTH_USER_HEADER_LEGACY, $user),
189
  sprintf("%s: %s", AUTH_KEY_HEADER_LEGACY, $pass),
@@ -196,7 +196,7 @@ class CF_Http
196
  sprintf("%s: %s", AUTH_USER_HEADER, $user),
197
  sprintf("%s: %s", AUTH_KEY_HEADER, $pass),
198
  );
199
- $path[] = "https://auth.api.rackspacecloud.com";
200
  }
201
  $path[] = "v1.0";
202
  $url = implode("/", $path);
@@ -207,13 +207,14 @@ class CF_Http
207
  curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
208
  }
209
  curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
210
- curl_setopt($curl_ch, CURLOPT_FOLLOWLOCATION, 1);
211
  curl_setopt($curl_ch, CURLOPT_MAXREDIRS, 4);
212
  curl_setopt($curl_ch, CURLOPT_HEADER, 0);
213
  curl_setopt($curl_ch, CURLOPT_HTTPHEADER, $headers);
214
  curl_setopt($curl_ch, CURLOPT_USERAGENT, USER_AGENT);
215
  curl_setopt($curl_ch, CURLOPT_RETURNTRANSFER, TRUE);
216
  curl_setopt($curl_ch, CURLOPT_HEADERFUNCTION,array(&$this,'_auth_hdr_cb'));
 
217
  curl_setopt($curl_ch, CURLOPT_URL, $url);
218
  curl_exec($curl_ch);
219
  curl_close($curl_ch);
@@ -224,14 +225,21 @@ class CF_Http
224
 
225
  # (CDN) GET /v1/Account
226
  #
227
- function list_cdn_containers()
228
  {
229
  $conn_type = "GET_CALL";
230
- $url_path = $this->_make_path("CDN", $container_name);
231
 
232
  $this->_write_callback_type = "TEXT_LIST";
233
- $return_code = $this->_send_request($conn_type, $url_path);
234
-
 
 
 
 
 
 
 
235
  if (!$return_code) {
236
  $this->error_str .= ": Failed to obtain valid HTTP response.";
237
  array(0,$this->error_str,array());
@@ -1175,7 +1183,8 @@ class CF_Http
1175
  curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
1176
  }
1177
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
1178
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
 
1179
  curl_setopt($ch, CURLOPT_MAXREDIRS, 4);
1180
  curl_setopt($ch, CURLOPT_HEADER, 0);
1181
  curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$this, '_header_cb'));
29
  */
30
  require_once("cloudfiles_exceptions.php");
31
 
32
+ define("PHP_CF_VERSION", "1.7.6");
33
  define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
34
  define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
35
  define("ACCOUNT_BYTES_USED", "X-Account-Bytes-Used");
183
  function authenticate($user, $pass, $acct=NULL, $host=NULL)
184
  {
185
  $path = array();
186
+ if (isset($acct)){
187
  $headers = array(
188
  sprintf("%s: %s", AUTH_USER_HEADER_LEGACY, $user),
189
  sprintf("%s: %s", AUTH_KEY_HEADER_LEGACY, $pass),
196
  sprintf("%s: %s", AUTH_USER_HEADER, $user),
197
  sprintf("%s: %s", AUTH_KEY_HEADER, $pass),
198
  );
199
+ $path[] = $host;
200
  }
201
  $path[] = "v1.0";
202
  $url = implode("/", $path);
207
  curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
208
  }
209
  curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
210
+ @curl_setopt($curl_ch, CURLOPT_FOLLOWLOCATION, 1);
211
  curl_setopt($curl_ch, CURLOPT_MAXREDIRS, 4);
212
  curl_setopt($curl_ch, CURLOPT_HEADER, 0);
213
  curl_setopt($curl_ch, CURLOPT_HTTPHEADER, $headers);
214
  curl_setopt($curl_ch, CURLOPT_USERAGENT, USER_AGENT);
215
  curl_setopt($curl_ch, CURLOPT_RETURNTRANSFER, TRUE);
216
  curl_setopt($curl_ch, CURLOPT_HEADERFUNCTION,array(&$this,'_auth_hdr_cb'));
217
+ curl_setopt($curl_ch, CURLOPT_CONNECTTIMEOUT, 10);
218
  curl_setopt($curl_ch, CURLOPT_URL, $url);
219
  curl_exec($curl_ch);
220
  curl_close($curl_ch);
225
 
226
  # (CDN) GET /v1/Account
227
  #
228
+ function list_cdn_containers($enabled_only)
229
  {
230
  $conn_type = "GET_CALL";
231
+ $url_path = $this->_make_path("CDN");
232
 
233
  $this->_write_callback_type = "TEXT_LIST";
234
+ if ($enabled_only)
235
+ {
236
+ $return_code = $this->_send_request($conn_type, $url_path .
237
+ '/?enabled_only=true');
238
+ }
239
+ else
240
+ {
241
+ $return_code = $this->_send_request($conn_type, $url_path);
242
+ }
243
  if (!$return_code) {
244
  $this->error_str .= ": Failed to obtain valid HTTP response.";
245
  array(0,$this->error_str,array());
1183
  curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
1184
  }
1185
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
1186
+ @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
1187
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
1188
  curl_setopt($ch, CURLOPT_MAXREDIRS, 4);
1189
  curl_setopt($ch, CURLOPT_HEADER, 0);
1190
  curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$this, '_header_cb'));
lib/CSSTidy/class.csstidy.php ADDED
@@ -0,0 +1,999 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * CSSTidy - CSS Parser and Optimiser
4
+ *
5
+ * CSS Parser class
6
+ *
7
+ * This file is part of CSSTidy.
8
+ *
9
+ * CSSTidy is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * CSSTidy is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with CSSTidy; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
+ *
23
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
24
+ * @package csstidy
25
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
26
+ */
27
+
28
+ /**
29
+ * Various CSS data needed for correct optimisations etc.
30
+ *
31
+ * @version 1.3
32
+ */
33
+ require('data.inc.php');
34
+
35
+ /**
36
+ * Contains a class for printing CSS code
37
+ *
38
+ * @version 1.0
39
+ */
40
+ require('class.csstidy_print.php');
41
+
42
+ /**
43
+ * Contains a class for optimising CSS code
44
+ *
45
+ * @version 1.0
46
+ */
47
+ require('class.csstidy_optimise.php');
48
+
49
+ /**
50
+ * CSS Parser class
51
+ *
52
+ * This class represents a CSS parser which reads CSS code and saves it in an array.
53
+ * In opposite to most other CSS parsers, it does not use regular expressions and
54
+ * thus has full CSS2 support and a higher reliability.
55
+ * Additional to that it applies some optimisations and fixes to the CSS code.
56
+ * An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
57
+ * @package csstidy
58
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
59
+ * @version 1.3
60
+ */
61
+ class csstidy {
62
+
63
+ /**
64
+ * Saves the parsed CSS
65
+ * @var array
66
+ * @access public
67
+ */
68
+ var $css = array();
69
+
70
+ /**
71
+ * Saves the parsed CSS (raw)
72
+ * @var array
73
+ * @access private
74
+ */
75
+ var $tokens = array();
76
+
77
+ /**
78
+ * Printer class
79
+ * @see csstidy_print
80
+ * @var object
81
+ * @access public
82
+ */
83
+ var $print;
84
+
85
+ /**
86
+ * Optimiser class
87
+ * @see csstidy_optimise
88
+ * @var object
89
+ * @access private
90
+ */
91
+ var $optimise;
92
+
93
+ /**
94
+ * Saves the CSS charset (@charset)
95
+ * @var string
96
+ * @access private
97
+ */
98
+ var $charset = '';
99
+
100
+ /**
101
+ * Saves all @import URLs
102
+ * @var array
103
+ * @access private
104
+ */
105
+ var $import = array();
106
+
107
+ /**
108
+ * Saves the namespace
109
+ * @var string
110
+ * @access private
111
+ */
112
+ var $namespace = '';
113
+
114
+ /**
115
+ * Contains the version of csstidy
116
+ * @var string
117
+ * @access private
118
+ */
119
+ var $version = '1.3';
120
+
121
+ /**
122
+ * Stores the settings
123
+ * @var array
124
+ * @access private
125
+ */
126
+ var $settings = array();
127
+
128
+ /**
129
+ * Saves the parser-status.
130
+ *
131
+ * Possible values:
132
+ * - is = in selector
133
+ * - ip = in property
134
+ * - iv = in value
135
+ * - instr = in string (started at " or ' or ( )
136
+ * - ic = in comment (ignore everything)
137
+ * - at = in @-block
138
+ *
139
+ * @var string
140
+ * @access private
141
+ */
142
+ var $status = 'is';
143
+
144
+
145
+ /**
146
+ * Saves the current at rule (@media)
147
+ * @var string
148
+ * @access private
149
+ */
150
+ var $at = '';
151
+
152
+ /**
153
+ * Saves the current selector
154
+ * @var string
155
+ * @access private
156
+ */
157
+ var $selector = '';
158
+
159
+ /**
160
+ * Saves the current property
161
+ * @var string
162
+ * @access private
163
+ */
164
+ var $property = '';
165
+
166
+ /**
167
+ * Saves the position of , in selectors
168
+ * @var array
169
+ * @access private
170
+ */
171
+ var $sel_separate = array();
172
+
173
+ /**
174
+ * Saves the current value
175
+ * @var string
176
+ * @access private
177
+ */
178
+ var $value = '';
179
+
180
+ /**
181
+ * Saves the current sub-value
182
+ *
183
+ * Example for a subvalue:
184
+ * background:url(foo.png) red no-repeat;
185
+ * "url(foo.png)", "red", and "no-repeat" are subvalues,
186
+ * seperated by whitespace
187
+ * @var string
188
+ * @access private
189
+ */
190
+ var $sub_value = '';
191
+
192
+ /**
193
+ * Array which saves all subvalues for a property.
194
+ * @var array
195
+ * @see sub_value
196
+ * @access private
197
+ */
198
+ var $sub_value_arr = array();
199
+
200
+ /**
201
+ * Saves the char which opened the last string
202
+ * @var string
203
+ * @access private
204
+ */
205
+ var $str_char = '';
206
+ var $cur_string = '';
207
+
208
+ /**
209
+ * Status from which the parser switched to ic or instr
210
+ * @var string
211
+ * @access private
212
+ */
213
+ var $from = '';
214
+
215
+ /**
216
+ * Variable needed to manage string-in-strings, for example url("foo.png")
217
+ * @var string
218
+ * @access private
219
+ */
220
+ var $str_in_str = false;
221
+
222
+ /**
223
+ * =true if in invalid at-rule
224
+ * @var bool
225
+ * @access private
226
+ */
227
+ var $invalid_at = false;
228
+
229
+ /**
230
+ * =true if something has been added to the current selector
231
+ * @var bool
232
+ * @access private
233
+ */
234
+ var $added = false;
235
+
236
+ /**
237
+ * Array which saves the message log
238
+ * @var array
239
+ * @access private
240
+ */
241
+ var $log = array();
242
+
243
+ /**
244
+ * Saves the line number
245
+ * @var integer
246
+ * @access private
247
+ */
248
+ var $line = 1;
249
+
250
+ /**
251
+ * Loads standard template and sets default settings
252
+ * @access private
253
+ * @version 1.3
254
+ */
255
+ function csstidy()
256
+ {
257
+ $this->settings['remove_bslash'] = true;
258
+ $this->settings['compress_colors'] = true;
259
+ $this->settings['compress_font-weight'] = true;
260
+ $this->settings['lowercase_s'] = false;
261
+ $this->settings['optimise_shorthands'] = 1;
262
+ $this->settings['remove_last_;'] = false;
263
+ $this->settings['case_properties'] = 1;
264
+ $this->settings['sort_properties'] = false;
265
+ $this->settings['sort_selectors'] = false;
266
+ $this->settings['merge_selectors'] = 2;
267
+ $this->settings['discard_invalid_properties'] = false;
268
+ $this->settings['css_level'] = 'CSS2.1';
269
+ $this->settings['preserve_css'] = false;
270
+ $this->settings['timestamp'] = false;
271
+
272
+ $this->load_template('default');
273
+ $this->print = new csstidy_print($this);
274
+ $this->optimise = new csstidy_optimise($this);
275
+ }
276
+
277
+ /**
278
+ * Get the value of a setting.
279
+ * @param string $setting
280
+ * @access public
281
+ * @return mixed
282
+ * @version 1.0
283
+ */
284
+ function get_cfg($setting)
285
+ {
286
+ if(isset($this->settings[$setting]))
287
+ {
288
+ return $this->settings[$setting];
289
+ }
290
+ return false;
291
+ }
292
+
293
+ /**
294
+ * Set the value of a setting.
295
+ * @param string $setting
296
+ * @param mixed $value
297
+ * @access public
298
+ * @return bool
299
+ * @version 1.0
300
+ */
301
+ function set_cfg($setting,$value)
302
+ {
303
+ if(isset($this->settings[$setting]) && $value !== '')
304
+ {
305
+ $this->settings[$setting] = $value;
306
+ return true;
307
+ }
308
+ return false;
309
+ }
310
+
311
+ /**
312
+ * Adds a token to $this->tokens
313
+ * @param mixed $type
314
+ * @param string $data
315
+ * @param bool $do add a token even if preserve_css is off
316
+ * @access private
317
+ * @version 1.0
318
+ */
319
+ function _add_token($type, $data, $do = false) {
320
+ if($this->get_cfg('preserve_css') || $do) {
321
+ $this->tokens[] = array($type, ($type == COMMENT) ? $data : trim($data));
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Add a message to the message log
327
+ * @param string $message
328
+ * @param string $type
329
+ * @param integer $line
330
+ * @access private
331
+ * @version 1.0
332
+ */
333
+ function log($message,$type,$line = -1)
334
+ {
335
+ if($line === -1)
336
+ {
337
+ $line = $this->line;
338
+ }
339
+ $line = intval($line);
340
+ $add = array('m' => $message, 't' => $type);
341
+ if(!isset($this->log[$line]) || !in_array($add,$this->log[$line]))
342
+ {
343
+ $this->log[$line][] = $add;
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Parse unicode notations and find a replacement character
349
+ * @param string $string
350
+ * @param integer $i
351
+ * @access private
352
+ * @return string
353
+ * @version 1.2
354
+ */
355
+ function _unicode(&$string, &$i)
356
+ {
357
+ ++$i;
358
+ $add = '';
359
+ $tokens =& $GLOBALS['csstidy']['tokens'];
360
+ $replaced = false;
361
+
362
+ while($i < strlen($string) && (ctype_xdigit($string{$i}) || ctype_space($string{$i})) && strlen($add) < 6)
363
+ {
364
+ $add .= $string{$i};
365
+
366
+ if(ctype_space($string{$i})) {
367
+ break;
368
+ }
369
+ $i++;
370
+ }
371
+
372
+ if(hexdec($add) > 47 && hexdec($add) < 58 || hexdec($add) > 64 && hexdec($add) < 91 || hexdec($add) > 96 && hexdec($add) < 123)
373
+ {
374
+ $this->log('Replaced unicode notation: Changed \\'. $add .' to ' . chr(hexdec($add)),'Information');
375
+ $add = chr(hexdec($add));
376
+ $replaced = true;
377
+ }
378
+ else {
379
+ $add = trim('\\'.$add);
380
+ }
381
+
382
+ if(@ctype_xdigit($string{$i+1}) && ctype_space($string{$i})
383
+ && !$replaced || !ctype_space($string{$i})) {
384
+ $i--;
385
+ }
386
+
387
+ if($add != '\\' || !$this->get_cfg('remove_bslash') || strpos($tokens, $string{$i+1}) !== false) {
388
+ return $add;
389
+ }
390
+
391
+ if($add == '\\') {
392
+ $this->log('Removed unnecessary backslash','Information');
393
+ }
394
+ return '';
395
+ }
396
+
397
+ /**
398
+ * Loads a new template
399
+ * @param string $content either filename (if $from_file == true), content of a template file, "high_compression", "highest_compression", "low_compression", or "default"
400
+ * @param bool $from_file uses $content as filename if true
401
+ * @access public
402
+ * @version 1.1
403
+ * @see http://csstidy.sourceforge.net/templates.php
404
+ */
405
+ function load_template($content, $from_file=true)
406
+ {
407
+ $predefined_templates =& $GLOBALS['csstidy']['predefined_templates'];
408
+ if($content == 'high_compression' || $content == 'default' || $content == 'highest_compression' || $content == 'low_compression')
409
+ {
410
+ $this->template = $predefined_templates[$content];
411
+ return;
412
+ }
413
+
414
+ if($from_file)
415
+ {
416
+ $content = strip_tags(file_get_contents($content),'<span>');
417
+ }
418
+ $content = str_replace("\r\n","\n",$content); // Unify newlines (because the output also only uses \n)
419
+ $template = explode('|',$content);
420
+
421
+ for ($i = 0; $i < count($template); $i++ )
422
+ {
423
+ $this->template[$i] = $template[$i];
424
+ }
425
+ }
426
+
427
+ /**
428
+ * Starts parsing from URL
429
+ * @param string $url
430
+ * @access public
431
+ * @version 1.0
432
+ */
433
+ function parse_from_url($url)
434
+ {
435
+ return $this->parse(@file_get_contents($url));
436
+ }
437
+
438
+ /**
439
+ * Checks if there is a token at the current position
440
+ * @param string $string
441
+ * @param integer $i
442
+ * @access public
443
+ * @version 1.11
444
+ */
445
+ function is_token(&$string, $i)
446
+ {
447
+ $tokens =& $GLOBALS['csstidy']['tokens'];
448
+ return (strpos($tokens, $string{$i}) !== false && !csstidy::escaped($string,$i));
449
+ }
450
+
451
+
452
+ /**
453
+ * Parses CSS in $string. The code is saved as array in $this->css
454
+ * @param string $string the CSS code
455
+ * @access public
456
+ * @return bool
457
+ * @version 1.1
458
+ */
459
+ function parse($string) {
460
+ // PHP bug? Settings need to be refreshed in PHP4
461
+ $this->print = new csstidy_print($this);
462
+ $this->optimise = new csstidy_optimise($this);
463
+
464
+ $all_properties =& $GLOBALS['csstidy']['all_properties'];
465
+ $at_rules =& $GLOBALS['csstidy']['at_rules'];
466
+
467
+ $this->css = array();
468
+ $this->print->input_css = $string;
469
+ $string = str_replace("\r\n","\n",$string) . ' ';
470
+ $cur_comment = '';
471
+
472
+ for ($i = 0, $size = strlen($string); $i < $size; $i++ )
473
+ {
474
+ if($string{$i} == "\n" || $string{$i} == "\r")
475
+ {
476
+ ++$this->line;
477
+ }
478
+
479
+ switch($this->status)
480
+ {
481
+ /* Case in at-block */
482
+ case 'at':
483
+ if(csstidy::is_token($string,$i))
484
+ {
485
+ if($string{$i} == '/' && @$string{$i+1} == '*')
486
+ {
487
+ $this->status = 'ic'; ++$i;
488
+ $this->from = 'at';
489
+ }
490
+ elseif($string{$i} == '{')
491
+ {
492
+ $this->status = 'is';
493
+ $this->_add_token(AT_START, $this->at);
494
+ }
495
+ elseif($string{$i} == ',')
496
+ {
497
+ $this->at = trim($this->at).',';
498
+ }
499
+ elseif($string{$i} == '\\')
500
+ {
501
+ $this->at .= $this->_unicode($string,$i);
502
+ }
503
+ }
504
+ else
505
+ {
506
+ $lastpos = strlen($this->at)-1;
507
+ if(!( (ctype_space($this->at{$lastpos}) || csstidy::is_token($this->at,$lastpos) && $this->at{$lastpos} == ',') && ctype_space($string{$i})))
508
+ {
509
+ $this->at .= $string{$i};
510
+ }
511
+ }
512
+ break;
513
+
514
+ /* Case in-selector */
515
+ case 'is':
516
+ if(csstidy::is_token($string,$i))
517
+ {
518
+ if($string{$i} == '/' && @$string{$i+1} == '*' && trim($this->selector) == '')
519
+ {
520
+ $this->status = 'ic'; ++$i;
521
+ $this->from = 'is';
522
+ }
523
+ elseif($string{$i} == '@' && trim($this->selector) == '')
524
+ {
525
+ // Check for at-rule
526
+ $this->invalid_at = true;
527
+ foreach($at_rules as $name => $type)
528
+ {
529
+ if(!strcasecmp(substr($string,$i+1,strlen($name)),$name))
530
+ {
531
+ ($type == 'at') ? $this->at = '@'.$name : $this->selector = '@'.$name;
532
+ $this->status = $type;
533
+ $i += strlen($name);
534
+ $this->invalid_at = false;
535
+ }
536
+ }
537
+
538
+ if($this->invalid_at)
539
+ {
540
+ $this->selector = '@';
541
+ $invalid_at_name = '';
542
+ for($j = $i+1; $j < $size; ++$j)
543
+ {
544
+ if(!ctype_alpha($string{$j}))
545
+ {
546
+ break;
547
+ }
548
+ $invalid_at_name .= $string{$j};
549
+ }
550
+ $this->log('Invalid @-rule: '.$invalid_at_name.' (removed)','Warning');
551
+ }
552
+ }
553
+ elseif(($string{$i} == '"' || $string{$i} == "'"))
554
+ {
555
+ $this->cur_string = $string{$i};
556
+ $this->status = 'instr';
557
+ $this->str_char = $string{$i};
558
+ $this->from = 'is';
559
+ }
560
+ elseif($this->invalid_at && $string{$i} == ';')
561
+ {
562
+ $this->invalid_at = false;
563
+ $this->status = 'is';
564
+ }
565
+ elseif($string{$i} == '{')
566
+ {
567
+ $this->status = 'ip';
568
+ $this->_add_token(SEL_START, $this->selector);
569
+ $this->added = false;
570
+ }
571
+ elseif($string{$i} == '}')
572
+ {
573
+ $this->_add_token(AT_END, $this->at);
574
+ $this->at = '';
575
+ $this->selector = '';
576
+ $this->sel_separate = array();
577
+ }
578
+ elseif($string{$i} == ',')
579
+ {
580
+ $this->selector = trim($this->selector).',';
581
+ $this->sel_separate[] = strlen($this->selector);
582
+ }
583
+ elseif($string{$i} == '\\')
584
+ {
585
+ $this->selector .= $this->_unicode($string,$i);
586
+ }
587
+ // remove unnecessary universal selector, FS#147
588
+ else if(!($string{$i} == '*' && @in_array($string{$i+1}, array('.', '#', '[', ':')))) {
589
+ $this->selector .= $string{$i};
590
+ }
591
+ }
592
+ else
593
+ {
594
+ $lastpos = strlen($this->selector)-1;
595
+ if($lastpos == -1 || !( (ctype_space($this->selector{$lastpos}) || csstidy::is_token($this->selector,$lastpos) && $this->selector{$lastpos} == ',') && ctype_space($string{$i})))
596
+ {
597
+ $this->selector .= $string{$i};
598
+ }
599
+ }
600
+ break;
601
+
602
+ /* Case in-property */
603
+ case 'ip':
604
+ if(csstidy::is_token($string,$i))
605
+ {
606
+ if(($string{$i} == ':' || $string{$i} == '=') && $this->property != '')
607
+ {
608
+ $this->status = 'iv';
609
+ if(!$this->get_cfg('discard_invalid_properties') || csstidy::property_is_valid($this->property)) {
610
+ $this->_add_token(PROPERTY, $this->property);
611
+ }
612
+ }
613
+ elseif($string{$i} == '/' && @$string{$i+1} == '*' && $this->property == '')
614
+ {
615
+ $this->status = 'ic'; ++$i;
616
+ $this->from = 'ip';
617
+ }
618
+ elseif($string{$i} == '}')
619
+ {
620
+ $this->explode_selectors();
621
+ $this->status = 'is';
622
+ $this->invalid_at = false;
623
+ $this->_add_token(SEL_END, $this->selector);
624
+ $this->selector = '';
625
+ $this->property = '';
626
+ }
627
+ elseif($string{$i} == ';')
628
+ {
629
+ $this->property = '';
630
+ }
631
+ elseif($string{$i} == '\\')
632
+ {
633
+ $this->property .= $this->_unicode($string,$i);
634
+ }
635
+ }
636
+ elseif(!ctype_space($string{$i}))
637
+ {
638
+ $this->property .= $string{$i};
639
+ }
640
+ break;
641
+
642
+ /* Case in-value */
643
+ case 'iv':
644
+ $pn = (($string{$i} == "\n" || $string{$i} == "\r") && $this->property_is_next($string,$i+1) || $i == strlen($string)-1);
645
+ if(csstidy::is_token($string,$i) || $pn)
646
+ {
647
+ if($string{$i} == '/' && @$string{$i+1} == '*')
648
+ {
649
+ $this->status = 'ic'; ++$i;
650
+ $this->from = 'iv';
651
+ }
652
+ elseif(($string{$i} == '"' || $string{$i} == "'" || $string{$i} == '('))
653
+ {
654
+ $this->cur_string = $string{$i};
655
+ $this->str_char = ($string{$i} == '(') ? ')' : $string{$i};
656
+ $this->status = 'instr';
657
+ $this->from = 'iv';
658
+ }
659
+ elseif($string{$i} == ',')
660
+ {
661
+ $this->sub_value = trim($this->sub_value).',';
662
+ }
663
+ elseif($string{$i} == '\\')
664
+ {
665
+ $this->sub_value .= $this->_unicode($string,$i);
666
+ }
667
+ elseif($string{$i} == ';' || $pn)
668
+ {
669
+ if($this->selector{0} == '@' && isset($at_rules[substr($this->selector,1)]) && $at_rules[substr($this->selector,1)] == 'iv')
670
+ {
671
+ $this->sub_value_arr[] = trim($this->sub_value);
672
+
673
+ $this->status = 'is';
674
+
675
+ switch($this->selector)
676
+ {
677
+ case '@charset': $this->charset = $this->sub_value_arr[0]; break;
678
+ case '@namespace': $this->namespace = implode(' ',$this->sub_value_arr); break;
679
+ case '@import': $this->import[] = implode(' ',$this->sub_value_arr); break;
680
+ }
681
+
682
+ $this->sub_value_arr = array();
683
+ $this->sub_value = '';
684
+ $this->selector = '';
685
+ $this->sel_separate = array();
686
+ }
687
+ else
688
+ {
689
+ $this->status = 'ip';
690
+ }
691
+ }
692
+ elseif($string{$i} != '}')
693
+ {
694
+ $this->sub_value .= $string{$i};
695
+ }
696
+ if(($string{$i} == '}' || $string{$i} == ';' || $pn) && !empty($this->selector))
697
+ {
698
+ if($this->at == '')
699
+ {
700
+ $this->at = DEFAULT_AT;
701
+ }
702
+
703
+ // case settings
704
+ if($this->get_cfg('lowercase_s'))
705
+ {
706
+ $this->selector = strtolower($this->selector);
707
+ }
708
+ $this->property = strtolower($this->property);
709
+
710
+ $this->optimise->subvalue();
711
+ if($this->sub_value != '') {
712
+ $this->sub_value_arr[] = $this->sub_value;
713
+ $this->sub_value = '';
714
+ }
715
+
716
+ $this->value = implode(' ',$this->sub_value_arr);
717
+
718
+ $this->selector = trim($this->selector);
719
+
720
+ $this->optimise->value();
721
+
722
+ $valid = csstidy::property_is_valid($this->property);
723
+ if((!$this->invalid_at || $this->get_cfg('preserve_css')) && (!$this->get_cfg('discard_invalid_properties') || $valid))
724
+ {
725
+ $this->css_add_property($this->at,$this->selector,$this->property,$this->value);
726
+ $this->_add_token(VALUE, $this->value);
727
+ $this->optimise->shorthands();
728
+ }
729
+ if(!$valid)
730
+ {
731
+ if($this->get_cfg('discard_invalid_properties'))
732
+ {
733
+ $this->log('Removed invalid property: '.$this->property,'Warning');
734
+ }
735
+ else
736
+ {
737
+ $this->log('Invalid property in '.strtoupper($this->get_cfg('css_level')).': '.$this->property,'Warning');
738
+ }
739
+ }
740
+
741
+ $this->property = '';
742
+ $this->sub_value_arr = array();
743
+ $this->value = '';
744
+ }
745
+ if($string{$i} == '}')
746
+ {
747
+ $this->explode_selectors();
748
+ $this->_add_token(SEL_END, $this->selector);
749
+ $this->status = 'is';
750
+ $this->invalid_at = false;
751
+ $this->selector = '';
752
+ }
753
+ }
754
+ elseif(!$pn)
755
+ {
756
+ $this->sub_value .= $string{$i};
757
+
758
+ if(ctype_space($string{$i}))
759
+ {
760
+ $this->optimise->subvalue();
761
+ if($this->sub_value != '') {
762
+ $this->sub_value_arr[] = $this->sub_value;
763
+ $this->sub_value = '';
764
+ }
765
+ }
766
+ }
767
+ break;
768
+
769
+ /* Case in string */
770
+ case 'instr':
771
+ if($this->str_char == ')' && ($string{$i} == '"' || $string{$i} == '\'') && !$this->str_in_str && !csstidy::escaped($string,$i))
772
+ {
773
+ $this->str_in_str = true;
774
+ }
775
+ elseif($this->str_char == ')' && ($string{$i} == '"' || $string{$i} == '\'') && $this->str_in_str && !csstidy::escaped($string,$i))
776
+ {
777
+ $this->str_in_str = false;
778
+ }
779
+ $temp_add = $string{$i}; // ...and no not-escaped backslash at the previous position
780
+ if( ($string{$i} == "\n" || $string{$i} == "\r") && !($string{$i-1} == '\\' && !csstidy::escaped($string,$i-1)) )
781
+ {
782
+ $temp_add = "\\A ";
783
+ $this->log('Fixed incorrect newline in string','Warning');
784
+ }
785
+ if (!($this->str_char == ')' && in_array($string{$i}, $GLOBALS['csstidy']['whitespace']) && !$this->str_in_str)) {
786
+ $this->cur_string .= $temp_add;
787
+ }
788
+ if($string{$i} == $this->str_char && !csstidy::escaped($string,$i) && !$this->str_in_str)
789
+ {
790
+ $this->status = $this->from;
791
+ if (!preg_match('|[' . implode('', $GLOBALS['csstidy']['whitespace']) . ']|uis', $this->cur_string) && $this->property != 'content') {
792
+ if ($this->str_char == '"' || $this->str_char == '\'') {
793
+ $this->cur_string = substr($this->cur_string, 1, -1);
794
+ } else if (strlen($this->cur_string) > 3 && ($this->cur_string[1] == '"' || $this->cur_string[1] == '\'')) /* () */ {
795
+ $this->cur_string = $this->cur_string[0] . substr($this->cur_string, 2, -2) . substr($this->cur_string, -1);
796
+ }
797
+ }
798
+ if($this->from == 'iv')
799
+ {
800
+ $this->sub_value .= $this->cur_string;
801
+ }
802
+ elseif($this->from == 'is')
803
+ {
804
+ $this->selector .= $this->cur_string;
805
+ }
806
+ }
807
+ break;
808
+
809
+ /* Case in-comment */
810
+ case 'ic':
811
+ if($string{$i} == '*' && $string{$i+1} == '/')
812
+ {
813
+ $this->status = $this->from;
814
+ $i++;
815
+ $this->_add_token(COMMENT, $cur_comment);
816
+ $cur_comment = '';
817
+ }
818
+ else
819
+ {
820
+ $cur_comment .= $string{$i};
821
+ }
822
+ break;
823
+ }
824
+ }
825
+
826
+ $this->optimise->postparse();
827
+
828
+ $this->print->_reset();
829
+
830
+ return !(empty($this->css) && empty($this->import) && empty($this->charset) && empty($this->tokens) && empty($this->namespace));
831
+ }
832
+
833
+ /**
834
+ * Explodes selectors
835
+ * @access private
836
+ * @version 1.0
837
+ */
838
+ function explode_selectors()
839
+ {
840
+ // Explode multiple selectors
841
+ if($this->get_cfg('merge_selectors') == 1)
842
+ {
843
+ $new_sels = array();
844
+ $lastpos = 0;
845
+ $this->sel_separate[] = strlen($this->selector);
846
+ foreach($this->sel_separate as $num => $pos)
847
+ {
848
+ if($num == count($this->sel_separate)-1) {
849
+ $pos += 1;
850
+ }
851
+
852
+ $new_sels[] = substr($this->selector,$lastpos,$pos-$lastpos-1);
853
+ $lastpos = $pos;
854
+ }
855
+
856
+ if(count($new_sels) > 1)
857
+ {
858
+ foreach($new_sels as $selector)
859
+ {
860
+ $this->merge_css_blocks($this->at,$selector,$this->css[$this->at][$this->selector]);
861
+ }
862
+ unset($this->css[$this->at][$this->selector]);
863
+ }
864
+ }
865
+ $this->sel_separate = array();
866
+ }
867
+
868
+ /**
869
+ * Checks if a character is escaped (and returns true if it is)
870
+ * @param string $string
871
+ * @param integer $pos
872
+ * @access public
873
+ * @return bool
874
+ * @version 1.02
875
+ */
876
+ function escaped(&$string,$pos)
877
+ {
878
+ return !(@($string{$pos-1} != '\\') || csstidy::escaped($string,$pos-1));
879
+ }
880
+
881
+ /**
882
+ * Adds a property with value to the existing CSS code
883
+ * @param string $media
884
+ * @param string $selector
885
+ * @param string $property
886
+ * @param string $new_val
887
+ * @access private
888
+ * @version 1.2
889
+ */
890
+ function css_add_property($media,$selector,$property,$new_val)
891
+ {
892
+ if($this->get_cfg('preserve_css') || trim($new_val) == '') {
893
+ return;
894
+ }
895
+
896
+ $this->added = true;
897
+ if(isset($this->css[$media][$selector][$property]))
898
+ {
899
+ if((csstidy::is_important($this->css[$media][$selector][$property]) && csstidy::is_important($new_val)) || !csstidy::is_important($this->css[$media][$selector][$property]))
900
+ {
901
+ unset($this->css[$media][$selector][$property]);
902
+ $this->css[$media][$selector][$property] = trim($new_val);
903
+ }
904
+ }
905
+ else
906
+ {
907
+ $this->css[$media][$selector][$property] = trim($new_val);
908
+ }
909
+ }
910
+
911
+ /**
912
+ * Adds CSS to an existing media/selector
913
+ * @param string $media
914
+ * @param string $selector
915
+ * @param array $css_add
916
+ * @access private
917
+ * @version 1.1
918
+ */
919
+ function merge_css_blocks($media,$selector,$css_add)
920
+ {
921
+ foreach($css_add as $property => $value)
922
+ {
923
+ $this->css_add_property($media,$selector,$property,$value,false);
924
+ }
925
+ }
926
+
927
+ /**
928
+ * Checks if $value is !important.
929
+ * @param string $value
930
+ * @return bool
931
+ * @access public
932
+ * @version 1.0
933
+ */
934
+ function is_important(&$value)
935
+ {
936
+ return (!strcasecmp(substr(str_replace($GLOBALS['csstidy']['whitespace'],'',$value),-10,10),'!important'));
937
+ }
938
+
939
+ /**
940
+ * Returns a value without !important
941
+ * @param string $value
942
+ * @return string
943
+ * @access public
944
+ * @version 1.0
945
+ */
946
+ function gvw_important($value)
947
+ {
948
+ if(csstidy::is_important($value))
949
+ {
950
+ $value = trim($value);
951
+ $value = substr($value,0,-9);
952
+ $value = trim($value);
953
+ $value = substr($value,0,-1);
954
+ $value = trim($value);
955
+ return $value;
956
+ }
957
+ return $value;
958
+ }
959
+
960
+ /**
961
+ * Checks if the next word in a string from pos is a CSS property
962
+ * @param string $istring
963
+ * @param integer $pos
964
+ * @return bool
965
+ * @access private
966
+ * @version 1.2
967
+ */
968
+ function property_is_next($istring, $pos)
969
+ {
970
+ $all_properties =& $GLOBALS['csstidy']['all_properties'];
971
+ $istring = substr($istring,$pos,strlen($istring)-$pos);
972
+ $pos = strpos($istring,':');
973
+ if($pos === false)
974
+ {
975
+ return false;
976
+ }
977
+ $istring = strtolower(trim(substr($istring,0,$pos)));
978
+ if(isset($all_properties[$istring]))
979
+ {
980
+ $this->log('Added semicolon to the end of declaration','Warning');
981
+ return true;
982
+ }
983
+ return false;
984
+ }
985
+
986
+ /**
987
+ * Checks if a property is valid
988
+ * @param string $property
989
+ * @return bool;
990
+ * @access public
991
+ * @version 1.0
992
+ */
993
+ function property_is_valid($property) {
994
+ $all_properties =& $GLOBALS['csstidy']['all_properties'];
995
+ return (isset($all_properties[$property]) && strpos($all_properties[$property],strtoupper($this->get_cfg('css_level'))) !== false );
996
+ }
997
+
998
+ }
999
+ ?>
lib/CSSTidy/class.csstidy_optimise.php ADDED
@@ -0,0 +1,809 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * CSSTidy - CSS Parser and Optimiser
4
+ *
5
+ * CSS Optimising Class
6
+ * This class optimises CSS data generated by csstidy.
7
+ *
8
+ * This file is part of CSSTidy.
9
+ *
10
+ * CSSTidy is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * CSSTidy is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with CSSTidy; if not, write to the Free Software
22
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
+ *
24
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
25
+ * @package csstidy
26
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
27
+ */
28
+
29
+ /**
30
+ * CSS Optimising Class
31
+ *
32
+ * This class optimises CSS data generated by csstidy.
33
+ *
34
+ * @package csstidy
35
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
36
+ * @version 1.0
37
+ */
38
+
39
+ class csstidy_optimise
40
+ {
41
+ /**
42
+ * Constructor
43
+ * @param array $css contains the class csstidy
44
+ * @access private
45
+ * @version 1.0
46
+ */
47
+ function csstidy_optimise(&$css)
48
+ {
49
+ $this->parser =& $css;
50
+ $this->css =& $css->css;
51
+ $this->sub_value =& $css->sub_value;
52
+ $this->at =& $css->at;
53
+ $this->selector =& $css->selector;
54
+ $this->property =& $css->property;
55
+ $this->value =& $css->value;
56
+ }
57
+
58
+ /**
59
+ * Optimises $css after parsing
60
+ * @access public
61
+ * @version 1.0
62
+ */
63
+ function postparse()
64
+ {
65
+ if ($this->parser->get_cfg('preserve_css')) {
66
+ return;
67
+ }
68
+
69
+ if ($this->parser->get_cfg('merge_selectors') == 2)
70
+ {
71
+ foreach ($this->css as $medium => $value)
72
+ {
73
+ $this->merge_selectors($this->css[$medium]);
74
+ }
75
+ }
76
+
77
+ if ($this->parser->get_cfg('optimise_shorthands') > 0)
78
+ {
79
+ foreach ($this->css as $medium => $value)
80
+ {
81
+ foreach ($value as $selector => $value1)
82
+ {
83
+ $this->css[$medium][$selector] = csstidy_optimise::merge_4value_shorthands($this->css[$medium][$selector]);
84
+
85
+ if ($this->parser->get_cfg('optimise_shorthands') < 2) {
86
+ continue;
87
+ }
88
+
89
+ $this->css[$medium][$selector] = csstidy_optimise::merge_bg($this->css[$medium][$selector]);
90
+ if (empty($this->css[$medium][$selector])) {
91
+ unset($this->css[$medium][$selector]);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Optimises values
100
+ * @access public
101
+ * @version 1.0
102
+ */
103
+ function value()
104
+ {
105
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
106
+
107
+ // optimise shorthand properties
108
+ if(isset($shorthands[$this->property]))
109
+ {
110
+ $temp = csstidy_optimise::shorthand($this->value); // FIXME - move
111
+ if($temp != $this->value)
112
+ {
113
+ $this->parser->log('Optimised shorthand notation ('.$this->property.'): Changed "'.$this->value.'" to "'.$temp.'"','Information');
114
+ }
115
+ $this->value = $temp;
116
+ }
117
+
118
+ // Remove whitespace at ! important
119
+ if($this->value != $this->compress_important($this->value))
120
+ {
121
+ $this->parser->log('Optimised !important','Information');
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Optimises shorthands
127
+ * @access public
128
+ * @version 1.0
129
+ */
130
+ function shorthands()
131
+ {
132
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
133
+
134
+ if(!$this->parser->get_cfg('optimise_shorthands') || $this->parser->get_cfg('preserve_css')) {
135
+ return;
136
+ }
137
+
138
+ if($this->property == 'background' && $this->parser->get_cfg('optimise_shorthands') > 1)
139
+ {
140
+ unset($this->css[$this->at][$this->selector]['background']);
141
+ $this->parser->merge_css_blocks($this->at,$this->selector,csstidy_optimise::dissolve_short_bg($this->value));
142
+ }
143
+ if(isset($shorthands[$this->property]))
144
+ {
145
+ $this->parser->merge_css_blocks($this->at,$this->selector,csstidy_optimise::dissolve_4value_shorthands($this->property,$this->value));
146
+ if(is_array($shorthands[$this->property]))
147
+ {
148
+ unset($this->css[$this->at][$this->selector][$this->property]);
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Optimises a sub-value
155
+ * @access public
156
+ * @version 1.0
157
+ */
158
+ function subvalue()
159
+ {
160
+ $replace_colors =& $GLOBALS['csstidy']['replace_colors'];
161
+
162
+ $this->sub_value = trim($this->sub_value);
163
+ if($this->sub_value == '') // caution : '0'
164
+ {
165
+ return;
166
+ }
167
+
168
+ $important = '';
169
+ if(csstidy::is_important($this->sub_value))
170
+ {
171
+ $important = '!important';
172
+ }
173
+ $this->sub_value = csstidy::gvw_important($this->sub_value);
174
+
175
+ // Compress font-weight
176
+ if($this->property == 'font-weight' && $this->parser->get_cfg('compress_font-weight'))
177
+ {
178
+ if($this->sub_value == 'bold')
179
+ {
180
+ $this->sub_value = '700';
181
+ $this->parser->log('Optimised font-weight: Changed "bold" to "700"','Information');
182
+ }
183
+ else if($this->sub_value == 'normal')
184
+ {
185
+ $this->sub_value = '400';
186
+ $this->parser->log('Optimised font-weight: Changed "normal" to "400"','Information');
187
+ }
188
+ }
189
+
190
+ $temp = $this->compress_numbers($this->sub_value);
191
+ if($temp != $this->sub_value)
192
+ {
193
+ if(strlen($temp) > strlen($this->sub_value)) {
194
+ $this->parser->log('Fixed invalid number: Changed "'.$this->sub_value.'" to "'.$temp.'"','Warning');
195
+ } else {
196
+ $this->parser->log('Optimised number: Changed "'.$this->sub_value.'" to "'.$temp.'"','Information');
197
+ }
198
+ $this->sub_value = $temp;
199
+ }
200
+ if($this->parser->get_cfg('compress_colors'))
201
+ {
202
+ $temp = $this->cut_color($this->sub_value);
203
+ if($temp !== $this->sub_value)
204
+ {
205
+ if(isset($replace_colors[$this->sub_value])) {
206
+ $this->parser->log('Fixed invalid color name: Changed "'.$this->sub_value.'" to "'.$temp.'"','Warning');
207
+ } else {
208
+ $this->parser->log('Optimised color: Changed "'.$this->sub_value.'" to "'.$temp.'"','Information');
209
+ }
210
+ $this->sub_value = $temp;
211
+ }
212
+ }
213
+ $this->sub_value .= $important;
214
+ }
215
+
216
+ /**
217
+ * Compresses shorthand values. Example: margin:1px 1px 1px 1px -> margin:1px
218
+ * @param string $value
219
+ * @access public
220
+ * @return string
221
+ * @version 1.0
222
+ */
223
+ function shorthand($value)
224
+ {
225
+ $important = '';
226
+ if(csstidy::is_important($value))
227
+ {
228
+ $values = csstidy::gvw_important($value);
229
+ $important = '!important';
230
+ }
231
+ else $values = $value;
232
+
233
+ $values = explode(' ',$values);
234
+ switch(count($values))
235
+ {
236
+ case 4:
237
+ if($values[0] == $values[1] && $values[0] == $values[2] && $values[0] == $values[3])
238
+ {
239
+ return $values[0].$important;
240
+ }
241
+ elseif($values[1] == $values[3] && $values[0] == $values[2])
242
+ {
243
+ return $values[0].' '.$values[1].$important;
244
+ }
245
+ elseif($values[1] == $values[3])
246
+ {
247
+ return $values[0].' '.$values[1].' '.$values[2].$important;
248
+ }
249
+ break;
250
+
251
+ case 3:
252
+ if($values[0] == $values[1] && $values[0] == $values[2])
253
+ {
254
+ return $values[0].$important;
255
+ }
256
+ elseif($values[0] == $values[2])
257
+ {
258
+ return $values[0].' '.$values[1].$important;
259
+ }
260
+ break;
261
+
262
+ case 2:
263
+ if($values[0] == $values[1])
264
+ {
265
+ return $values[0].$important;
266
+ }
267
+ break;
268
+ }
269
+
270
+ return $value;
271
+ }
272
+
273
+ /**
274
+ * Removes unnecessary whitespace in ! important
275
+ * @param string $string
276
+ * @return string
277
+ * @access public
278
+ * @version 1.1
279
+ */
280
+ function compress_important(&$string)
281
+ {
282
+ if(csstidy::is_important($string))
283
+ {
284
+ $string = csstidy::gvw_important($string) . '!important';
285
+ }
286
+ return $string;
287
+ }
288
+
289
+ /**
290
+ * Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
291
+ * @param string $color
292
+ * @return string
293
+ * @version 1.1
294
+ */
295
+ function cut_color($color)
296
+ {
297
+ $replace_colors =& $GLOBALS['csstidy']['replace_colors'];
298
+
299
+ // rgb(0,0,0) -> #000000 (or #000 in this case later)
300
+ if(strtolower(substr($color,0,4)) == 'rgb(')
301
+ {
302
+ $color_tmp = substr($color,4,strlen($color)-5);
303
+ $color_tmp = explode(',',$color_tmp);
304
+ for ( $i = 0; $i < count($color_tmp); $i++ )
305
+ {
306
+ $color_tmp[$i] = trim ($color_tmp[$i]);
307
+ if(substr($color_tmp[$i],-1) == '%')
308
+ {
309
+ $color_tmp[$i] = round((255*$color_tmp[$i])/100);
310
+ }
311
+ if($color_tmp[$i]>255) $color_tmp[$i] = 255;
312
+ }
313
+ $color = '#';
314
+ for ($i = 0; $i < 3; $i++ )
315
+ {
316
+ if($color_tmp[$i]<16) {
317
+ $color .= '0' . dechex($color_tmp[$i]);
318
+ } else {
319
+ $color .= dechex($color_tmp[$i]);
320
+ }
321
+ }
322
+ }
323
+
324
+ // Fix bad color names
325
+ if(isset($replace_colors[strtolower($color)]))
326
+ {
327
+ $color = $replace_colors[strtolower($color)];
328
+ }
329
+
330
+ // #aabbcc -> #abc
331
+ if(strlen($color) == 7)
332
+ {
333
+ $color_temp = strtolower($color);
334
+ if($color_temp{0} == '#' && $color_temp{1} == $color_temp{2} && $color_temp{3} == $color_temp{4} && $color_temp{5} == $color_temp{6})
335
+ {
336
+ $color = '#'.$color{1}.$color{3}.$color{5};
337
+ }
338
+ }
339
+
340
+ switch(strtolower($color))
341
+ {
342
+ /* color name -> hex code */
343
+ case 'black': return '#000';
344
+ case 'fuchsia': return '#F0F';
345
+ case 'white': return '#FFF';
346
+ case 'yellow': return '#FF0';
347
+
348
+ /* hex code -> color name */
349
+ case '#800000': return 'maroon';
350
+ case '#ffa500': return 'orange';
351
+ case '#808000': return 'olive';
352
+ case '#800080': return 'purple';
353
+ case '#008000': return 'green';
354
+ case '#000080': return 'navy';
355
+ case '#008080': return 'teal';
356
+ case '#c0c0c0': return 'silver';
357
+ case '#808080': return 'gray';
358
+ case '#f00': return 'red';
359
+ }
360
+
361
+ return $color;
362
+ }
363
+
364
+ /**
365
+ * Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 )
366
+ * @param string $subvalue
367
+ * @return string
368
+ * @version 1.2
369
+ */
370
+ function compress_numbers($subvalue)
371
+ {
372
+ $units =& $GLOBALS['csstidy']['units'];
373
+ $unit_values =& $GLOBALS['csstidy']['unit_values'];
374
+ $color_values =& $GLOBALS['csstidy']['color_values'];
375
+
376
+ // for font:1em/1em sans-serif...;
377
+ if($this->property == 'font')
378
+ {
379
+ $temp = explode('/',$subvalue);
380
+ }
381
+ else
382
+ {
383
+ $temp = array($subvalue);
384
+ }
385
+ for ($l = 0; $l < count($temp); $l++)
386
+ {
387
+ // continue if no numeric value
388
+ if (!(strlen($temp[$l]) > 0 && ( is_numeric($temp[$l]{0}) || $temp[$l]{0} == '+' || $temp[$l]{0} == '-' ) ))
389
+ {
390
+ continue;
391
+ }
392
+
393
+ // Fix bad colors
394
+ if (in_array($this->property, $color_values))
395
+ {
396
+ $temp[$l] = '#'.$temp[$l];
397
+ }
398
+
399
+ if (floatval($temp[$l]) == 0)
400
+ {
401
+ $temp[$l] = '0';
402
+ }
403
+ else
404
+ {
405
+ $unit_found = FALSE;
406
+ for ($m = 0, $size_4 = count($units); $m < $size_4; $m++)
407
+ {
408
+ if (strpos(strtolower($temp[$l]),$units[$m]) !== FALSE)
409
+ {
410
+ $temp[$l] = floatval($temp[$l]).$units[$m];
411
+ $unit_found = TRUE;
412
+ break;
413
+ }
414
+ }
415
+ if (!$unit_found && in_array($this->property,$unit_values,TRUE))
416
+ {
417
+ $temp[$l] = floatval($temp[$l]).'px';
418
+ }
419
+ else if (!$unit_found)
420
+ {
421
+ $temp[$l] = floatval($temp[$l]);
422
+ }
423
+ // Remove leading zero
424
+ if (abs(floatval($temp[$l])) < 1) {
425
+ if (floatval($temp[$l]) < 0) {
426
+ $temp[$l] = '-' . substr($temp[$l], 2);
427
+ } else {
428
+ $temp[$l] = substr($temp[$l], 1);
429
+ }
430
+ }
431
+ }
432
+ }
433
+
434
+ return ((count($temp) > 1) ? $temp[0].'/'.$temp[1] : $temp[0]);
435
+ }
436
+
437
+ /**
438
+ * Merges selectors with same properties. Example: a{color:red} b{color:red} -> a,b{color:red}
439
+ * Very basic and has at least one bug. Hopefully there is a replacement soon.
440
+ * @param array $array
441
+ * @return array
442
+ * @access public
443
+ * @version 1.2
444
+ */
445
+ function merge_selectors(&$array)
446
+ {
447
+ $css = $array;
448
+ foreach($css as $key => $value)
449
+ {
450
+ if(!isset($css[$key]))
451
+ {
452
+ continue;
453
+ }
454
+ $newsel = '';
455
+
456
+ // Check if properties also exist in another selector
457
+ $keys = array();
458
+ // PHP bug (?) without $css = $array; here
459
+ foreach($css as $selector => $vali)
460
+ {
461
+ if($selector == $key)
462
+ {
463
+ continue;
464
+ }
465
+
466
+ if($css[$key] === $vali)
467
+ {
468
+ $keys[] = $selector;
469
+ }
470
+ }
471
+
472
+ if(!empty($keys))
473
+ {
474
+ $newsel = $key;
475
+ unset($css[$key]);
476
+ foreach($keys as $selector)
477
+ {
478
+ unset($css[$selector]);
479
+ $newsel .= ','.$selector;
480
+ }
481
+ $css[$newsel] = $value;
482
+ }
483
+ }
484
+ $array = $css;
485
+ }
486
+
487
+ /**
488
+ * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
489
+ * @param string $property
490
+ * @param string $value
491
+ * @return array
492
+ * @version 1.0
493
+ * @see merge_4value_shorthands()
494
+ */
495
+ function dissolve_4value_shorthands($property,$value)
496
+ {
497
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
498
+ if(!is_array($shorthands[$property]))
499
+ {
500
+ $return[$property] = $value;
501
+ return $return;
502
+ }
503
+
504
+ $important = '';
505
+ if(csstidy::is_important($value))
506
+ {
507
+ $value = csstidy::gvw_important($value);
508
+ $important = '!important';
509
+ }
510
+ $values = explode(' ',$value);
511
+
512
+
513
+ $return = array();
514
+ if(count($values) == 4)
515
+ {
516
+ for($i=0;$i<4;$i++)
517
+ {
518
+ $return[$shorthands[$property][$i]] = $values[$i].$important;
519
+ }
520
+ }
521
+ elseif(count($values) == 3)
522
+ {
523
+ $return[$shorthands[$property][0]] = $values[0].$important;
524
+ $return[$shorthands[$property][1]] = $values[1].$important;
525
+ $return[$shorthands[$property][3]] = $values[1].$important;
526
+ $return[$shorthands[$property][2]] = $values[2].$important;
527
+ }
528
+ elseif(count($values) == 2)
529
+ {
530
+ for($i=0;$i<4;$i++)
531
+ {
532
+ $return[$shorthands[$property][$i]] = (($i % 2 != 0)) ? $values[1].$important : $values[0].$important;
533
+ }
534
+ }
535
+ else
536
+ {
537
+ for($i=0;$i<4;$i++)
538
+ {
539
+ $return[$shorthands[$property][$i]] = $values[0].$important;
540
+ }
541
+ }
542
+
543
+ return $return;
544
+ }
545
+
546
+ /**
547
+ * Explodes a string as explode() does, however, not if $sep is escaped or within a string.
548
+ * @param string $sep seperator
549
+ * @param string $string
550
+ * @return array
551
+ * @version 1.0
552
+ */
553
+ function explode_ws($sep,$string)
554
+ {
555
+ $status = 'st';
556
+ $to = '';
557
+
558
+ $output = array();
559
+ $num = 0;
560
+ for($i = 0, $len = strlen($string);$i < $len; $i++)
561
+ {
562
+ switch($status)
563
+ {
564
+ case 'st':
565
+ if($string{$i} == $sep && !csstidy::escaped($string,$i))
566
+ {
567
+ ++$num;
568
+ }
569
+ elseif($string{$i} == '"' || $string{$i} == '\'' || $string{$i} == '(' && !csstidy::escaped($string,$i))
570
+ {
571
+ $status = 'str';
572
+ $to = ($string{$i} == '(') ? ')' : $string{$i};
573
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
574
+ }
575
+ else
576
+ {
577
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
578
+ }
579
+ break;
580
+
581
+ case 'str':
582
+ if($string{$i} == $to && !csstidy::escaped($string,$i))
583
+ {
584
+ $status = 'st';
585
+ }
586
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
587
+ break;
588
+ }
589
+ }
590
+
591
+ if(isset($output[0]))
592
+ {
593
+ return $output;
594
+ }
595
+ else
596
+ {
597
+ return array($output);
598
+ }
599
+ }
600
+
601
+ /**
602
+ * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
603
+ * @param array $array
604
+ * @return array
605
+ * @version 1.2
606
+ * @see dissolve_4value_shorthands()
607
+ */
608
+ function merge_4value_shorthands($array)
609
+ {
610
+ $return = $array;
611
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
612
+
613
+ foreach($shorthands as $key => $value)
614
+ {
615
+ if(isset($array[$value[0]]) && isset($array[$value[1]])
616
+ && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0)
617
+ {
618
+ $return[$key] = '';
619
+
620
+ $important = '';
621
+ for($i = 0; $i < 4; $i++)
622
+ {
623
+ $val = $array[$value[$i]];
624
+ if(csstidy::is_important($val))
625
+ {
626
+ $important = '!important';
627
+ $return[$key] .= csstidy::gvw_important($val).' ';
628
+ }
629
+ else
630
+ {
631
+ $return[$key] .= $val.' ';
632
+ }
633
+ unset($return[$value[$i]]);
634
+ }
635
+ $return[$key] = csstidy_optimise::shorthand(trim($return[$key].$important));
636
+ }
637
+ }
638
+ return $return;
639
+ }
640
+
641
+ /**
642
+ * Dissolve background property
643
+ * @param string $str_value
644
+ * @return array
645
+ * @version 1.0
646
+ * @see merge_bg()
647
+ * @todo full CSS 3 compliance
648
+ */
649
+ function dissolve_short_bg($str_value)
650
+ {
651
+ $background_prop_default =& $GLOBALS['csstidy']['background_prop_default'];
652
+ $repeat = array('repeat','repeat-x','repeat-y','no-repeat','space');
653
+ $attachment = array('scroll','fixed','local');
654
+ $clip = array('border','padding');
655
+ $origin = array('border','padding','content');
656
+ $pos = array('top','center','bottom','left','right');
657
+ $important = '';
658
+ $return = array('background-image' => NULL,'background-size' => NULL,'background-repeat' => NULL,'background-position' => NULL,'background-attachment'=>NULL,'background-clip' => NULL,'background-origin' => NULL,'background-color' => NULL);
659
+
660
+ if(csstidy::is_important($str_value))
661
+ {
662
+ $important = ' !important';
663
+ $str_value = csstidy::gvw_important($str_value);
664
+ }
665
+
666
+ $str_value = csstidy_optimise::explode_ws(',',$str_value);
667
+ for($i = 0; $i < count($str_value); $i++)
668
+ {
669
+ $have['clip'] = FALSE; $have['pos'] = FALSE;
670
+ $have['color'] = FALSE; $have['bg'] = FALSE;
671
+
672
+ $str_value[$i] = csstidy_optimise::explode_ws(' ',trim($str_value[$i]));
673
+
674
+ for($j = 0; $j < count($str_value[$i]); $j++)
675
+ {
676
+ if($have['bg'] === FALSE && (substr($str_value[$i][$j],0,4) == 'url(' || $str_value[$i][$j] === 'none'))
677
+ {
678
+ $return['background-image'] .= $str_value[$i][$j].',';
679
+ $have['bg'] = TRUE;
680
+ }
681
+ elseif(in_array($str_value[$i][$j],$repeat,TRUE))
682
+ {
683
+ $return['background-repeat'] .= $str_value[$i][$j].',';
684
+ }
685
+ elseif(in_array($str_value[$i][$j],$attachment,TRUE))
686
+ {
687
+ $return['background-attachment'] .= $str_value[$i][$j].',';
688
+ }
689
+ elseif(in_array($str_value[$i][$j],$clip,TRUE) && !$have['clip'])
690
+ {
691
+ $return['background-clip'] .= $str_value[$i][$j].',';
692
+ $have['clip'] = TRUE;
693
+ }
694
+ elseif(in_array($str_value[$i][$j],$origin,TRUE))
695
+ {
696
+ $return['background-origin'] .= $str_value[$i][$j].',';
697
+ }
698
+ elseif($str_value[$i][$j]{0} == '(')
699
+ {
700
+ $return['background-size'] .= substr($str_value[$i][$j],1,-1).',';
701
+ }
702
+ elseif(in_array($str_value[$i][$j],$pos,TRUE) || is_numeric($str_value[$i][$j]{0}) || $str_value[$i][$j]{0} === NULL)
703
+ {
704
+ $return['background-position'] .= $str_value[$i][$j];
705
+ if(!$have['pos']) $return['background-position'] .= ' '; else $return['background-position'].= ',';
706
+ $have['pos'] = TRUE;
707
+ }
708
+ elseif(!$have['color'])
709
+ {
710
+ $return['background-color'] .= $str_value[$i][$j].',';
711
+ $have['color'] = TRUE;
712
+ }
713
+ }
714
+ }
715
+
716
+ foreach($background_prop_default as $bg_prop => $default_value)
717
+ {
718
+ if($return[$bg_prop] !== NULL)
719
+ {
720
+ $return[$bg_prop] = substr($return[$bg_prop],0,-1).$important;
721
+ }
722
+ else $return[$bg_prop] = $default_value.$important;
723
+ }
724
+ return $return;
725
+ }
726
+
727
+ /**
728
+ * Merges all background properties
729
+ * @param array $input_css
730
+ * @return array
731
+ * @version 1.0
732
+ * @see dissolve_short_bg()
733
+ * @todo full CSS 3 compliance
734
+ */
735
+ function merge_bg($input_css)
736
+ {
737
+ $background_prop_default =& $GLOBALS['csstidy']['background_prop_default'];
738
+ // Max number of background images. CSS3 not yet fully implemented
739
+ $number_of_values = @max(count(csstidy_optimise::explode_ws(',',$input_css['background-image'])),count(csstidy_optimise::explode_ws(',',$input_css['background-color'])),1);
740
+ // Array with background images to check if BG image exists
741
+ $bg_img_array = @csstidy_optimise::explode_ws(',',csstidy::gvw_important($input_css['background-image']));
742
+ $new_bg_value = '';
743
+ $important = '';
744
+
745
+ for($i = 0; $i < $number_of_values; $i++)
746
+ {
747
+ foreach($background_prop_default as $bg_property => $default_value)
748
+ {
749
+ // Skip if property does not exist
750
+ if(!isset($input_css[$bg_property]))
751
+ {
752
+ continue;
753
+ }
754
+
755
+ $cur_value = $input_css[$bg_property];
756
+
757
+ // Skip some properties if there is no background image
758
+ if((!isset($bg_img_array[$i]) || $bg_img_array[$i] === 'none')
759
+ && ($bg_property === 'background-size' || $bg_property === 'background-position'
760
+ || $bg_property === 'background-attachment' || $bg_property === 'background-repeat'))
761
+ {
762
+ continue;
763
+ }
764
+
765
+ // Remove !important
766
+ if(csstidy::is_important($cur_value))
767
+ {
768
+ $important = ' !important';
769
+ $cur_value = csstidy::gvw_important($cur_value);
770
+ }
771
+
772
+ // Do not add default values
773
+ if($cur_value === $default_value)
774
+ {
775
+ continue;
776
+ }
777
+
778
+ $temp = csstidy_optimise::explode_ws(',',$cur_value);
779
+
780
+ if(isset($temp[$i]))
781
+ {
782
+ if($bg_property == 'background-size')
783
+ {
784
+ $new_bg_value .= '('.$temp[$i].') ';
785
+ }
786
+ else
787
+ {
788
+ $new_bg_value .= $temp[$i].' ';
789
+ }
790
+ }
791
+ }
792
+
793
+ $new_bg_value = trim($new_bg_value);
794
+ if($i != $number_of_values-1) $new_bg_value .= ',';
795
+ }
796
+
797
+ // Delete all background-properties
798
+ foreach($background_prop_default as $bg_property => $default_value)
799
+ {
800
+ unset($input_css[$bg_property]);
801
+ }
802
+
803
+ // Add new background property
804
+ if($new_bg_value !== '') $input_css['background'] = $new_bg_value.$important;
805
+
806
+ return $input_css;
807
+ }
808
+ }
809
+ ?>
lib/CSSTidy/class.csstidy_print.php ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * CSSTidy - CSS Parser and Optimiser
4
+ *
5
+ * CSS Printing class
6
+ * This class prints CSS data generated by csstidy.
7
+ *
8
+ * This file is part of CSSTidy.
9
+ *
10
+ * CSSTidy is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * CSSTidy is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with CSSTidy; if not, write to the Free Software
22
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
+ *
24
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
25
+ * @package csstidy
26
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
27
+ */
28
+
29
+ /**
30
+ * CSS Printing class
31
+ *
32
+ * This class prints CSS data generated by csstidy.
33
+ *
34
+ * @package csstidy
35
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
36
+ * @version 1.0
37
+ */
38
+
39
+ class csstidy_print
40
+ {
41
+ /**
42
+ * Saves the input CSS string
43
+ * @var string
44
+ * @access private
45
+ */
46
+ var $input_css = '';
47
+
48
+ /**
49
+ * Saves the formatted CSS string
50
+ * @var string
51
+ * @access public
52
+ */
53
+ var $output_css = '';
54
+
55
+ /**
56
+ * Saves the formatted CSS string (plain text)
57
+ * @var string
58
+ * @access public
59
+ */
60
+ var $output_css_plain = '';
61
+
62
+ /**
63
+ * Constructor
64
+ * @param array $css contains the class csstidy
65
+ * @access private
66
+ * @version 1.0
67
+ */
68
+ function csstidy_print(&$css)
69
+ {
70
+ $this->parser =& $css;
71
+ $this->css =& $css->css;
72
+ $this->template =& $css->template;
73
+ $this->tokens =& $css->tokens;
74
+ $this->charset =& $css->charset;
75
+ $this->import =& $css->import;
76
+ $this->namespace =& $css->namespace;
77
+ }
78
+
79
+ /**
80
+ * Resets output_css and output_css_plain (new css code)
81
+ * @access private
82
+ * @version 1.0
83
+ */
84
+ function _reset()
85
+ {
86
+ $this->output_css = '';
87
+ $this->output_css_plain = '';
88
+ }
89
+
90
+ /**
91
+ * Returns the CSS code as plain text
92
+ * @return string
93
+ * @access public
94
+ * @version 1.0
95
+ */
96
+ function plain()
97
+ {
98
+ $this->_print(true);
99
+ return $this->output_css_plain;
100
+ }
101
+
102
+ /**
103
+ * Returns the formatted CSS code
104
+ * @return string
105
+ * @access public
106
+ * @version 1.0
107
+ */
108
+ function formatted()
109
+ {
110
+ $this->_print(false);
111
+ return $this->output_css;
112
+ }
113
+
114
+ /**
115
+ * Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain
116
+ * @param bool $plain plain text or not
117
+ * @access private
118
+ * @version 2.0
119
+ */
120
+ function _print($plain = false)
121
+ {
122
+ if ($this->output_css && $this->output_css_plain) {
123
+ return;
124
+ }
125
+
126
+ $output = '';
127
+ if (!$this->parser->get_cfg('preserve_css')) {
128
+ $this->_convert_raw_css();
129
+ }
130
+
131
+ $template =& $this->template;
132
+
133
+ if ($plain) {
134
+ $template = array_map('strip_tags', $template);
135
+ }
136
+
137
+ if ($this->parser->get_cfg('timestamp')) {
138
+ array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' '));
139
+ }
140
+
141
+ if (!empty($this->charset)) {
142
+ $output .= $template[0].'@charset '.$template[5].$this->charset.$template[6];
143
+ }
144
+
145
+ if (!empty($this->import)) {
146
+ for ($i = 0, $size = count($this->import); $i < $size; $i ++) {
147
+ $output .= $template[0].'@import '.$template[5].$this->import[$i].$template[6];
148
+ }
149
+ }
150
+
151
+ if (!empty($this->namespace)) {
152
+ $output .= $template[0].'@namespace '.$template[5].$this->namespace.$template[6];
153
+ }
154
+
155
+ $output .= $template[13];
156
+ $in_at_out = '';
157
+ $out =& $output;
158
+
159
+ foreach ($this->tokens as $key => $token)
160
+ {
161
+ switch ($token[0])
162
+ {
163
+ case AT_START:
164
+ $out .= $template[0].$this->_htmlsp($token[1], $plain).$template[1];
165
+ $out =& $in_at_out;
166
+ break;
167
+
168
+ case SEL_START:
169
+ if($this->parser->get_cfg('lowercase_s')) $token[1] = strtolower($token[1]);
170
+ $out .= ($token[1]{0} !== '@') ? $template[2].$this->_htmlsp($token[1], $plain) : $template[0].$this->_htmlsp($token[1], $plain);
171
+ $out .= $template[3];
172
+ break;
173
+
174
+ case PROPERTY:
175
+ if($this->parser->get_cfg('case_properties') == 2) $token[1] = strtoupper($token[1]);
176
+ if($this->parser->get_cfg('case_properties') == 1) $token[1] = strtolower($token[1]);
177
+ $out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
178
+ break;
179
+
180
+ case VALUE:
181
+ $out .= $this->_htmlsp($token[1], $plain);
182
+ if($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) {
183
+ $out .= str_replace(';', '', $template[6]);
184
+ } else {
185
+ $out .= $template[6];
186
+ }
187
+ break;
188
+
189
+ case SEL_END:
190
+ $out .= $template[7];
191
+ if($this->_seeknocomment($key, 1) != AT_END) $out .= $template[8];
192
+ break;
193
+
194
+ case AT_END:
195
+ $out =& $output;
196
+ $out .= $template[10] . str_replace("\n", "\n" . $template[10], $in_at_out);
197
+ $in_at_out = '';
198
+ $out .= $template[9];
199
+ break;
200
+
201
+ case COMMENT:
202
+ $out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12];
203
+ break;
204
+ }
205
+ }
206
+
207
+ $output = trim($output);
208
+
209
+ if (!$plain) {
210
+ $this->output_css = $output;
211
+ $this->_print(true);
212
+ } else {
213
+ $this->output_css_plain = $output;
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Gets the next token type which is $move away from $key, excluding comments
219
+ * @param integer $key current position
220
+ * @param integer $move move this far
221
+ * @return mixed a token type
222
+ * @access private
223
+ * @version 1.0
224
+ */
225
+ function _seeknocomment($key, $move) {
226
+ $go = ($move > 0) ? 1 : -1;
227
+ for ($i = $key + 1; abs($key-$i)-1 < abs($move); $i += $go) {
228
+ if (!isset($this->tokens[$i])) {
229
+ return;
230
+ }
231
+ if ($this->tokens[$i][0] == COMMENT) {
232
+ $move += 1;
233
+ continue;
234
+ }
235
+ return $this->tokens[$i][0];
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Converts $this->css array to a raw array ($this->tokens)
241
+ * @access private
242
+ * @version 1.0
243
+ */
244
+ function _convert_raw_css()
245
+ {
246
+ $this->tokens = array();
247
+
248
+ foreach ($this->css as $medium => $val)
249
+ {
250
+ if ($this->parser->get_cfg('sort_selectors')) ksort($val);
251
+ if ($medium != DEFAULT_AT) {
252
+ $this->parser->_add_token(AT_START, $medium, true);
253
+ }
254
+
255
+ foreach ($val as $selector => $vali)
256
+ {
257
+ if ($this->parser->get_cfg('sort_properties')) ksort($vali);
258
+ $this->parser->_add_token(SEL_START, $selector, true);
259
+
260
+ foreach ($vali as $property => $valj)
261
+ {
262
+ $this->parser->_add_token(PROPERTY, $property, true);
263
+ $this->parser->_add_token(VALUE, $valj, true);
264
+ }
265
+
266
+ $this->parser->_add_token(SEL_END, $selector, true);
267
+ }
268
+
269
+ if ($medium != DEFAULT_AT) {
270
+ $this->parser->_add_token(AT_END, $medium, true);
271
+ }
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes print_code() cleaner.
277
+ * @param string $string
278
+ * @param bool $plain
279
+ * @return string
280
+ * @see csstidy_print::_print()
281
+ * @access private
282
+ * @version 1.0
283
+ */
284
+ function _htmlsp($string, $plain)
285
+ {
286
+ if (!$plain) {
287
+ return htmlspecialchars($string);
288
+ }
289
+ return $string;
290
+ }
291
+
292
+ /**
293
+ * Get compression ratio
294
+ * @access public
295
+ * @return float
296
+ * @version 1.2
297
+ */
298
+ function get_ratio()
299
+ {
300
+ if (!$this->output_css_plain) {
301
+ $this->formatted();
302
+ }
303
+ return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100;
304
+ }
305
+
306
+ /**
307
+ * Get difference between the old and new code in bytes and prints the code if necessary.
308
+ * @access public
309
+ * @return string
310
+ * @version 1.1
311
+ */
312
+ function get_diff()
313
+ {
314
+ if (!$this->output_css_plain) {
315
+ $this->formatted();
316
+ }
317
+
318
+ $diff = strlen($this->output_css_plain) - strlen($this->input_css);
319
+
320
+ if ($diff > 0) {
321
+ return '+' . $diff;
322
+ } elseif ($diff == 0) {
323
+ return '+-' . $diff;
324
+ }
325
+
326
+ return $diff;
327
+ }
328
+
329
+ /**
330
+ * Get the size of either input or output CSS in KB
331
+ * @param string $loc default is "output"
332
+ * @access public
333
+ * @return integer
334
+ * @version 1.0
335
+ */
336
+ function size($loc = 'output')
337
+ {
338
+ if ($loc == 'output' && !$this->output_css) {
339
+ $this->formatted();
340
+ }
341
+
342
+ if ($loc == 'input') {
343
+ return (strlen($this->input_css) / 1000);
344
+ } else {
345
+ return (strlen($this->output_css_plain) / 1000);
346
+ }
347
+ }
348
+ }
349
+ ?>
lib/CSSTidy/data.inc.php ADDED
@@ -0,0 +1,473 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Various CSS Data for CSSTidy
4
+ *
5
+ * This file is part of CSSTidy.
6
+ *
7
+ * CSSTidy is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * CSSTidy is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with CSSTidy; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+ *
21
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
22
+ * @package csstidy
23
+ * @author Florian Schmitz (floele at gmail dot com) 2005
24
+ */
25
+
26
+ define('AT_START', 1);
27
+ define('AT_END', 2);
28
+ define('SEL_START', 3);
29
+ define('SEL_END', 4);
30
+ define('PROPERTY', 5);
31
+ define('VALUE', 6);
32
+ define('COMMENT', 7);
33
+ define('DEFAULT_AT', 41);
34
+
35
+ /**
36
+ * All whitespace allowed in CSS
37
+ *
38
+ * @global array $GLOBALS['csstidy']['whitespace']
39
+ * @version 1.0
40
+ */
41
+ $GLOBALS['csstidy']['whitespace'] = array(' ',"\n","\t","\r","\x0B");
42
+
43
+ /**
44
+ * All CSS tokens used by csstidy
45
+ *
46
+ * @global string $GLOBALS['csstidy']['tokens']
47
+ * @version 1.0
48
+ */
49
+ $GLOBALS['csstidy']['tokens'] = '/@}{;:=\'"(,\\!$%&)*+.<>?[]^`|~';
50
+
51
+ /**
52
+ * All CSS units (CSS 3 units included)
53
+ *
54
+ * @see compress_numbers()
55
+ * @global array $GLOBALS['csstidy']['units']
56
+ * @version 1.0
57
+ */
58
+ $GLOBALS['csstidy']['units'] = array('in','cm','mm','pt','pc','px','rem','em','%','ex','gd','vw','vh','vm','deg','grad','rad','ms','s','khz','hz');
59
+
60
+ /**
61
+ * Available at-rules
62
+ *
63
+ * @global array $GLOBALS['csstidy']['at_rules']
64
+ * @version 1.0
65
+ */
66
+ $GLOBALS['csstidy']['at_rules'] = array('page' => 'is','font-face' => 'is','charset' => 'iv', 'import' => 'iv','namespace' => 'iv','media' => 'at');
67
+
68
+ /**
69
+ * Properties that need a value with unit
70
+ *
71
+ * @todo CSS3 properties
72
+ * @see compress_numbers();
73
+ * @global array $GLOBALS['csstidy']['unit_values']
74
+ * @version 1.2
75
+ */
76
+ $GLOBALS['csstidy']['unit_values'] = array ('background', 'background-position', 'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-width',
77
+ 'border-top-width', 'border-right-width', 'border-left-width', 'border-bottom-width', 'bottom', 'border-spacing', 'font-size',
78
+ 'height', 'left', 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'max-height', 'max-width',
79
+ 'min-height', 'min-width', 'outline-width', 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
80
+ 'position', 'right', 'top', 'text-indent', 'letter-spacing', 'word-spacing', 'width');
81
+
82
+ /**
83
+ * Properties that allow <color> as value
84
+ *
85
+ * @todo CSS3 properties
86
+ * @see compress_numbers();
87
+ * @global array $GLOBALS['csstidy']['color_values']
88
+ * @version 1.0
89
+ */
90
+ $GLOBALS['csstidy']['color_values'] = array();
91
+ $GLOBALS['csstidy']['color_values'][] = 'background-color';
92
+ $GLOBALS['csstidy']['color_values'][] = 'border-color';
93
+ $GLOBALS['csstidy']['color_values'][] = 'border-top-color';
94
+ $GLOBALS['csstidy']['color_values'][] = 'border-right-color';
95
+ $GLOBALS['csstidy']['color_values'][] = 'border-bottom-color';
96
+ $GLOBALS['csstidy']['color_values'][] = 'border-left-color';
97
+ $GLOBALS['csstidy']['color_values'][] = 'color';
98
+ $GLOBALS['csstidy']['color_values'][] = 'outline-color';
99
+
100
+
101
+ /**
102
+ * Default values for the background properties
103
+ *
104
+ * @todo Possibly property names will change during CSS3 development
105
+ * @global array $GLOBALS['csstidy']['background_prop_default']
106
+ * @see dissolve_short_bg()
107
+ * @see merge_bg()
108
+ * @version 1.0
109
+ */
110
+ $GLOBALS['csstidy']['background_prop_default'] = array();
111
+ $GLOBALS['csstidy']['background_prop_default']['background-image'] = 'none';
112
+ $GLOBALS['csstidy']['background_prop_default']['background-size'] = 'auto';
113
+ $GLOBALS['csstidy']['background_prop_default']['background-repeat'] = 'repeat';
114
+ $GLOBALS['csstidy']['background_prop_default']['background-position'] = '0 0';
115
+ $GLOBALS['csstidy']['background_prop_default']['background-attachment'] = 'scroll';
116
+ $GLOBALS['csstidy']['background_prop_default']['background-clip'] = 'border';
117
+ $GLOBALS['csstidy']['background_prop_default']['background-origin'] = 'padding';
118
+ $GLOBALS['csstidy']['background_prop_default']['background-color'] = 'transparent';
119
+
120
+ /**
121
+ * A list of non-W3C color names which get replaced by their hex-codes
122
+ *
123
+ * @global array $GLOBALS['csstidy']['replace_colors']
124
+ * @see cut_color()
125
+ * @version 1.0
126
+ */
127
+ $GLOBALS['csstidy']['replace_colors'] = array();
128
+ $GLOBALS['csstidy']['replace_colors']['aliceblue'] = '#F0F8FF';
129
+ $GLOBALS['csstidy']['replace_colors']['antiquewhite'] = '#FAEBD7';
130
+ $GLOBALS['csstidy']['replace_colors']['aquamarine'] = '#7FFFD4';
131
+ $GLOBALS['csstidy']['replace_colors']['azure'] = '#F0FFFF';
132
+ $GLOBALS['csstidy']['replace_colors']['beige'] = '#F5F5DC';
133
+ $GLOBALS['csstidy']['replace_colors']['bisque'] = '#FFE4C4';
134
+ $GLOBALS['csstidy']['replace_colors']['blanchedalmond'] = '#FFEBCD';
135
+ $GLOBALS['csstidy']['replace_colors']['blueviolet'] = '#8A2BE2';
136
+ $GLOBALS['csstidy']['replace_colors']['brown'] = '#A52A2A';
137
+ $GLOBALS['csstidy']['replace_colors']['burlywood'] = '#DEB887';
138
+ $GLOBALS['csstidy']['replace_colors']['cadetblue'] = '#5F9EA0';
139
+ $GLOBALS['csstidy']['replace_colors']['chartreuse'] = '#7FFF00';
140
+ $GLOBALS['csstidy']['replace_colors']['chocolate'] = '#D2691E';
141
+ $GLOBALS['csstidy']['replace_colors']['coral'] = '#FF7F50';
142
+ $GLOBALS['csstidy']['replace_colors']['cornflowerblue'] = '#6495ED';
143
+ $GLOBALS['csstidy']['replace_colors']['cornsilk'] = '#FFF8DC';
144
+ $GLOBALS['csstidy']['replace_colors']['crimson'] = '#DC143C';
145
+ $GLOBALS['csstidy']['replace_colors']['cyan'] = '#00FFFF';
146
+ $GLOBALS['csstidy']['replace_colors']['darkblue'] = '#00008B';
147
+ $GLOBALS['csstidy']['replace_colors']['darkcyan'] = '#008B8B';
148
+ $GLOBALS['csstidy']['replace_colors']['darkgoldenrod'] = '#B8860B';
149
+ $GLOBALS['csstidy']['replace_colors']['darkgray'] = '#A9A9A9';
150
+ $GLOBALS['csstidy']['replace_colors']['darkgreen'] = '#006400';
151
+ $GLOBALS['csstidy']['replace_colors']['darkkhaki'] = '#BDB76B';
152
+ $GLOBALS['csstidy']['replace_colors']['darkmagenta'] = '#8B008B';
153
+ $GLOBALS['csstidy']['replace_colors']['darkolivegreen'] = '#556B2F';
154
+ $GLOBALS['csstidy']['replace_colors']['darkorange'] = '#FF8C00';
155
+ $GLOBALS['csstidy']['replace_colors']['darkorchid'] = '#9932CC';
156
+ $GLOBALS['csstidy']['replace_colors']['darkred'] = '#8B0000';
157
+ $GLOBALS['csstidy']['replace_colors']['darksalmon'] = '#E9967A';
158
+ $GLOBALS['csstidy']['replace_colors']['darkseagreen'] = '#8FBC8F';
159
+ $GLOBALS['csstidy']['replace_colors']['darkslateblue'] = '#483D8B';
160
+ $GLOBALS['csstidy']['replace_colors']['darkslategray'] = '#2F4F4F';
161
+ $GLOBALS['csstidy']['replace_colors']['darkturquoise'] = '#00CED1';
162
+ $GLOBALS['csstidy']['replace_colors']['darkviolet'] = '#9400D3';
163
+ $GLOBALS['csstidy']['replace_colors']['deeppink'] = '#FF1493';
164
+ $GLOBALS['csstidy']['replace_colors']['deepskyblue'] = '#00BFFF';
165
+ $GLOBALS['csstidy']['replace_colors']['dimgray'] = '#696969';
166
+ $GLOBALS['csstidy']['replace_colors']['dodgerblue'] = '#1E90FF';
167
+ $GLOBALS['csstidy']['replace_colors']['feldspar'] = '#D19275';
168
+ $GLOBALS['csstidy']['replace_colors']['firebrick'] = '#B22222';
169
+ $GLOBALS['csstidy']['replace_colors']['floralwhite'] = '#FFFAF0';
170
+ $GLOBALS['csstidy']['replace_colors']['forestgreen'] = '#228B22';
171
+ $GLOBALS['csstidy']['replace_colors']['gainsboro'] = '#DCDCDC';
172
+ $GLOBALS['csstidy']['replace_colors']['ghostwhite'] = '#F8F8FF';
173
+ $GLOBALS['csstidy']['replace_colors']['gold'] = '#FFD700';
174
+ $GLOBALS['csstidy']['replace_colors']['goldenrod'] = '#DAA520';
175
+ $GLOBALS['csstidy']['replace_colors']['greenyellow'] = '#ADFF2F';
176
+ $GLOBALS['csstidy']['replace_colors']['honeydew'] = '#F0FFF0';
177
+ $GLOBALS['csstidy']['replace_colors']['hotpink'] = '#FF69B4';
178
+ $GLOBALS['csstidy']['replace_colors']['indianred'] = '#CD5C5C';
179
+ $GLOBALS['csstidy']['replace_colors']['indigo'] = '#4B0082';
180
+ $GLOBALS['csstidy']['replace_colors']['ivory'] = '#FFFFF0';
181
+ $GLOBALS['csstidy']['replace_colors']['khaki'] = '#F0E68C';
182
+ $GLOBALS['csstidy']['replace_colors']['lavender'] = '#E6E6FA';
183
+ $GLOBALS['csstidy']['replace_colors']['lavenderblush'] = '#FFF0F5';
184
+ $GLOBALS['csstidy']['replace_colors']['lawngreen'] = '#7CFC00';
185
+ $GLOBALS['csstidy']['replace_colors']['lemonchiffon'] = '#FFFACD';
186
+ $GLOBALS['csstidy']['replace_colors']['lightblue'] = '#ADD8E6';
187
+ $GLOBALS['csstidy']['replace_colors']['lightcoral'] = '#F08080';
188
+ $GLOBALS['csstidy']['replace_colors']['lightcyan'] = '#E0FFFF';
189
+ $GLOBALS['csstidy']['replace_colors']['lightgoldenrodyellow'] = '#FAFAD2';
190
+ $GLOBALS['csstidy']['replace_colors']['lightgrey'] = '#D3D3D3';
191
+ $GLOBALS['csstidy']['replace_colors']['lightgreen'] = '#90EE90';
192
+ $GLOBALS['csstidy']['replace_colors']['lightpink'] = '#FFB6C1';
193
+ $GLOBALS['csstidy']['replace_colors']['lightsalmon'] = '#FFA07A';
194
+ $GLOBALS['csstidy']['replace_colors']['lightseagreen'] = '#20B2AA';
195
+ $GLOBALS['csstidy']['replace_colors']['lightskyblue'] = '#87CEFA';
196
+ $GLOBALS['csstidy']['replace_colors']['lightslateblue'] = '#8470FF';
197
+ $GLOBALS['csstidy']['replace_colors']['lightslategray'] = '#778899';
198
+ $GLOBALS['csstidy']['replace_colors']['lightsteelblue'] = '#B0C4DE';
199
+ $GLOBALS['csstidy']['replace_colors']['lightyellow'] = '#FFFFE0';
200
+ $GLOBALS['csstidy']['replace_colors']['limegreen'] = '#32CD32';
201
+ $GLOBALS['csstidy']['replace_colors']['linen'] = '#FAF0E6';
202
+ $GLOBALS['csstidy']['replace_colors']['magenta'] = '#FF00FF';
203
+ $GLOBALS['csstidy']['replace_colors']['mediumaquamarine'] = '#66CDAA';
204
+ $GLOBALS['csstidy']['replace_colors']['mediumblue'] = '#0000CD';
205
+ $GLOBALS['csstidy']['replace_colors']['mediumorchid'] = '#BA55D3';
206
+ $GLOBALS['csstidy']['replace_colors']['mediumpurple'] = '#9370D8';
207
+ $GLOBALS['csstidy']['replace_colors']['mediumseagreen'] = '#3CB371';
208
+ $GLOBALS['csstidy']['replace_colors']['mediumslateblue'] = '#7B68EE';
209
+ $GLOBALS['csstidy']['replace_colors']['mediumspringgreen'] = '#00FA9A';
210
+ $GLOBALS['csstidy']['replace_colors']['mediumturquoise'] = '#48D1CC';
211
+ $GLOBALS['csstidy']['replace_colors']['mediumvioletred'] = '#C71585';
212
+ $GLOBALS['csstidy']['replace_colors']['midnightblue'] = '#191970';
213
+ $GLOBALS['csstidy']['replace_colors']['mintcream'] = '#F5FFFA';
214
+ $GLOBALS['csstidy']['replace_colors']['mistyrose'] = '#FFE4E1';
215
+ $GLOBALS['csstidy']['replace_colors']['moccasin'] = '#FFE4B5';
216
+ $GLOBALS['csstidy']['replace_colors']['navajowhite'] = '#FFDEAD';
217
+ $GLOBALS['csstidy']['replace_colors']['oldlace'] = '#FDF5E6';
218
+ $GLOBALS['csstidy']['replace_colors']['olivedrab'] = '#6B8E23';
219
+ $GLOBALS['csstidy']['replace_colors']['orangered'] = '#FF4500';
220
+ $GLOBALS['csstidy']['replace_colors']['orchid'] = '#DA70D6';
221
+ $GLOBALS['csstidy']['replace_colors']['palegoldenrod'] = '#EEE8AA';
222
+ $GLOBALS['csstidy']['replace_colors']['palegreen'] = '#98FB98';
223
+ $GLOBALS['csstidy']['replace_colors']['paleturquoise'] = '#AFEEEE';
224
+ $GLOBALS['csstidy']['replace_colors']['palevioletred'] = '#D87093';
225
+ $GLOBALS['csstidy']['replace_colors']['papayawhip'] = '#FFEFD5';
226
+ $GLOBALS['csstidy']['replace_colors']['peachpuff'] = '#FFDAB9';
227
+ $GLOBALS['csstidy']['replace_colors']['peru'] = '#CD853F';
228
+ $GLOBALS['csstidy']['replace_colors']['pink'] = '#FFC0CB';
229
+ $GLOBALS['csstidy']['replace_colors']['plum'] = '#DDA0DD';
230
+ $GLOBALS['csstidy']['replace_colors']['powderblue'] = '#B0E0E6';
231
+ $GLOBALS['csstidy']['replace_colors']['rosybrown'] = '#BC8F8F';
232
+ $GLOBALS['csstidy']['replace_colors']['royalblue'] = '#4169E1';
233
+ $GLOBALS['csstidy']['replace_colors']['saddlebrown'] = '#8B4513';
234
+ $GLOBALS['csstidy']['replace_colors']['salmon'] = '#FA8072';
235
+ $GLOBALS['csstidy']['replace_colors']['sandybrown'] = '#F4A460';
236
+ $GLOBALS['csstidy']['replace_colors']['seagreen'] = '#2E8B57';
237
+ $GLOBALS['csstidy']['replace_colors']['seashell'] = '#FFF5EE';
238
+ $GLOBALS['csstidy']['replace_colors']['sienna'] = '#A0522D';
239
+ $GLOBALS['csstidy']['replace_colors']['skyblue'] = '#87CEEB';
240
+ $GLOBALS['csstidy']['replace_colors']['slateblue'] = '#6A5ACD';
241
+ $GLOBALS['csstidy']['replace_colors']['slategray'] = '#708090';
242
+ $GLOBALS['csstidy']['replace_colors']['snow'] = '#FFFAFA';
243
+ $GLOBALS['csstidy']['replace_colors']['springgreen'] = '#00FF7F';
244
+ $GLOBALS['csstidy']['replace_colors']['steelblue'] = '#4682B4';
245
+ $GLOBALS['csstidy']['replace_colors']['tan'] = '#D2B48C';
246
+ $GLOBALS['csstidy']['replace_colors']['thistle'] = '#D8BFD8';
247
+ $GLOBALS['csstidy']['replace_colors']['tomato'] = '#FF6347';
248
+ $GLOBALS['csstidy']['replace_colors']['turquoise'] = '#40E0D0';
249
+ $GLOBALS['csstidy']['replace_colors']['violet'] = '#EE82EE';
250
+ $GLOBALS['csstidy']['replace_colors']['violetred'] = '#D02090';
251
+ $GLOBALS['csstidy']['replace_colors']['wheat'] = '#F5DEB3';
252
+ $GLOBALS['csstidy']['replace_colors']['whitesmoke'] = '#F5F5F5';
253
+ $GLOBALS['csstidy']['replace_colors']['yellowgreen'] = '#9ACD32';
254
+
255
+
256
+ /**
257
+ * A list of all shorthand properties that are devided into four properties and/or have four subvalues
258
+ *
259
+ * @global array $GLOBALS['csstidy']['shorthands']
260
+ * @todo Are there new ones in CSS3?
261
+ * @see dissolve_4value_shorthands()
262
+ * @see merge_4value_shorthands()
263
+ * @version 1.0
264
+ */
265
+ $GLOBALS['csstidy']['shorthands'] = array();
266
+ $GLOBALS['csstidy']['shorthands']['border-color'] = array('border-top-color','border-right-color','border-bottom-color','border-left-color');
267
+ $GLOBALS['csstidy']['shorthands']['border-style'] = array('border-top-style','border-right-style','border-bottom-style','border-left-style');
268
+ $GLOBALS['csstidy']['shorthands']['border-width'] = array('border-top-width','border-right-width','border-bottom-width','border-left-width');
269
+ $GLOBALS['csstidy']['shorthands']['margin'] = array('margin-top','margin-right','margin-bottom','margin-left');
270
+ $GLOBALS['csstidy']['shorthands']['padding'] = array('padding-top','padding-right','padding-bottom','padding-left');
271
+ $GLOBALS['csstidy']['shorthands']['-moz-border-radius'] = 0;
272
+
273
+ /**
274
+ * All CSS Properties. Needed for csstidy::property_is_next()
275
+ *
276
+ * @global array $GLOBALS['csstidy']['all_properties']
277
+ * @todo Add CSS3 properties
278
+ * @version 1.0
279
+ * @see csstidy::property_is_next()
280
+ */
281
+ $GLOBALS['csstidy']['all_properties'] = array();
282
+ $GLOBALS['csstidy']['all_properties']['background'] = 'CSS1.0,CSS2.0,CSS2.1';
283
+ $GLOBALS['csstidy']['all_properties']['background-color'] = 'CSS1.0,CSS2.0,CSS2.1';
284
+ $GLOBALS['csstidy']['all_properties']['background-image'] = 'CSS1.0,CSS2.0,CSS2.1';
285
+ $GLOBALS['csstidy']['all_properties']['background-repeat'] = 'CSS1.0,CSS2.0,CSS2.1';
286
+ $GLOBALS['csstidy']['all_properties']['background-attachment'] = 'CSS1.0,CSS2.0,CSS2.1';
287
+ $GLOBALS['csstidy']['all_properties']['background-position'] = 'CSS1.0,CSS2.0,CSS2.1';
288
+ $GLOBALS['csstidy']['all_properties']['border'] = 'CSS1.0,CSS2.0,CSS2.1';
289
+ $GLOBALS['csstidy']['all_properties']['border-top'] = 'CSS1.0,CSS2.0,CSS2.1';
290
+ $GLOBALS['csstidy']['all_properties']['border-right'] = 'CSS1.0,CSS2.0,CSS2.1';
291
+ $GLOBALS['csstidy']['all_properties']['border-bottom'] = 'CSS1.0,CSS2.0,CSS2.1';
292
+ $GLOBALS['csstidy']['all_properties']['border-left'] = 'CSS1.0,CSS2.0,CSS2.1';
293
+ $GLOBALS['csstidy']['all_properties']['border-color'] = 'CSS1.0,CSS2.0,CSS2.1';
294
+ $GLOBALS['csstidy']['all_properties']['border-top-color'] = 'CSS2.0,CSS2.1';
295
+ $GLOBALS['csstidy']['all_properties']['border-bottom-color'] = 'CSS2.0,CSS2.1';
296
+ $GLOBALS['csstidy']['all_properties']['border-left-color'] = 'CSS2.0,CSS2.1';
297
+ $GLOBALS['csstidy']['all_properties']['border-right-color'] = 'CSS2.0,CSS2.1';
298
+ $GLOBALS['csstidy']['all_properties']['border-style'] = 'CSS1.0,CSS2.0,CSS2.1';
299
+ $GLOBALS['csstidy']['all_properties']['border-top-style'] = 'CSS2.0,CSS2.1';
300
+ $GLOBALS['csstidy']['all_properties']['border-right-style'] = 'CSS2.0,CSS2.1';
301
+ $GLOBALS['csstidy']['all_properties']['border-left-style'] = 'CSS2.0,CSS2.1';
302
+ $GLOBALS['csstidy']['all_properties']['border-bottom-style'] = 'CSS2.0,CSS2.1';
303
+ $GLOBALS['csstidy']['all_properties']['border-width'] = 'CSS1.0,CSS2.0,CSS2.1';
304
+ $GLOBALS['csstidy']['all_properties']['border-top-width'] = 'CSS1.0,CSS2.0,CSS2.1';
305
+ $GLOBALS['csstidy']['all_properties']['border-right-width'] = 'CSS1.0,CSS2.0,CSS2.1';
306
+ $GLOBALS['csstidy']['all_properties']['border-left-width'] = 'CSS1.0,CSS2.0,CSS2.1';
307
+ $GLOBALS['csstidy']['all_properties']['border-bottom-width'] = 'CSS1.0,CSS2.0,CSS2.1';
308
+ $GLOBALS['csstidy']['all_properties']['border-collapse'] = 'CSS2.0,CSS2.1';
309
+ $GLOBALS['csstidy']['all_properties']['border-spacing'] = 'CSS2.0,CSS2.1';
310
+ $GLOBALS['csstidy']['all_properties']['bottom'] = 'CSS2.0,CSS2.1';
311
+ $GLOBALS['csstidy']['all_properties']['caption-side'] = 'CSS2.0,CSS2.1';
312
+ $GLOBALS['csstidy']['all_properties']['content'] = 'CSS2.0,CSS2.1';
313
+ $GLOBALS['csstidy']['all_properties']['clear'] = 'CSS1.0,CSS2.0,CSS2.1';
314
+ $GLOBALS['csstidy']['all_properties']['clip'] = 'CSS1.0,CSS2.0,CSS2.1';
315
+ $GLOBALS['csstidy']['all_properties']['color'] = 'CSS1.0,CSS2.0,CSS2.1';
316
+ $GLOBALS['csstidy']['all_properties']['counter-reset'] = 'CSS2.0,CSS2.1';
317
+ $GLOBALS['csstidy']['all_properties']['counter-increment'] = 'CSS2.0,CSS2.1';
318
+ $GLOBALS['csstidy']['all_properties']['cursor'] = 'CSS2.0,CSS2.1';
319
+ $GLOBALS['csstidy']['all_properties']['empty-cells'] = 'CSS2.0,CSS2.1';
320
+ $GLOBALS['csstidy']['all_properties']['display'] = 'CSS1.0,CSS2.0,CSS2.1';
321
+ $GLOBALS['csstidy']['all_properties']['direction'] = 'CSS2.0,CSS2.1';
322
+ $GLOBALS['csstidy']['all_properties']['float'] = 'CSS1.0,CSS2.0,CSS2.1';
323
+ $GLOBALS['csstidy']['all_properties']['font'] = 'CSS1.0,CSS2.0,CSS2.1';
324
+ $GLOBALS['csstidy']['all_properties']['font-family'] = 'CSS1.0,CSS2.0,CSS2.1';
325
+ $GLOBALS['csstidy']['all_properties']['font-style'] = 'CSS1.0,CSS2.0,CSS2.1';
326
+ $GLOBALS['csstidy']['all_properties']['font-variant'] = 'CSS1.0,CSS2.0,CSS2.1';
327
+ $GLOBALS['csstidy']['all_properties']['font-weight'] = 'CSS1.0,CSS2.0,CSS2.1';
328
+ $GLOBALS['csstidy']['all_properties']['font-stretch'] = 'CSS2.0';
329
+ $GLOBALS['csstidy']['all_properties']['font-size-adjust'] = 'CSS2.0';
330
+ $GLOBALS['csstidy']['all_properties']['font-size'] = 'CSS1.0,CSS2.0,CSS2.1';
331
+ $GLOBALS['csstidy']['all_properties']['height'] = 'CSS1.0,CSS2.0,CSS2.1';
332
+ $GLOBALS['csstidy']['all_properties']['left'] = 'CSS1.0,CSS2.0,CSS2.1';
333
+ $GLOBALS['csstidy']['all_properties']['line-height'] = 'CSS1.0,CSS2.0,CSS2.1';
334
+ $GLOBALS['csstidy']['all_properties']['list-style'] = 'CSS1.0,CSS2.0,CSS2.1';
335
+ $GLOBALS['csstidy']['all_properties']['list-style-type'] = 'CSS1.0,CSS2.0,CSS2.1';
336
+ $GLOBALS['csstidy']['all_properties']['list-style-image'] = 'CSS1.0,CSS2.0,CSS2.1';
337
+ $GLOBALS['csstidy']['all_properties']['list-style-position'] = 'CSS1.0,CSS2.0,CSS2.1';
338
+ $GLOBALS['csstidy']['all_properties']['margin'] = 'CSS1.0,CSS2.0,CSS2.1';
339
+ $GLOBALS['csstidy']['all_properties']['margin-top'] = 'CSS1.0,CSS2.0,CSS2.1';
340
+ $GLOBALS['csstidy']['all_properties']['margin-right'] = 'CSS1.0,CSS2.0,CSS2.1';
341
+ $GLOBALS['csstidy']['all_properties']['margin-bottom'] = 'CSS1.0,CSS2.0,CSS2.1';
342
+ $GLOBALS['csstidy']['all_properties']['margin-left'] = 'CSS1.0,CSS2.0,CSS2.1';
343
+ $GLOBALS['csstidy']['all_properties']['marks'] = 'CSS1.0,CSS2.0';
344
+ $GLOBALS['csstidy']['all_properties']['marker-offset'] = 'CSS2.0';
345
+ $GLOBALS['csstidy']['all_properties']['max-height'] = 'CSS2.0,CSS2.1';
346
+ $GLOBALS['csstidy']['all_properties']['max-width'] = 'CSS2.0,CSS2.1';
347
+ $GLOBALS['csstidy']['all_properties']['min-height'] = 'CSS2.0,CSS2.1';
348
+ $GLOBALS['csstidy']['all_properties']['min-width'] = 'CSS2.0,CSS2.1';
349
+ $GLOBALS['csstidy']['all_properties']['overflow'] = 'CSS1.0,CSS2.0,CSS2.1';
350
+ $GLOBALS['csstidy']['all_properties']['orphans'] = 'CSS2.0,CSS2.1';
351
+ $GLOBALS['csstidy']['all_properties']['outline'] = 'CSS2.0,CSS2.1';
352
+ $GLOBALS['csstidy']['all_properties']['outline-width'] = 'CSS2.0,CSS2.1';
353
+ $GLOBALS['csstidy']['all_properties']['outline-style'] = 'CSS2.0,CSS2.1';
354
+ $GLOBALS['csstidy']['all_properties']['outline-color'] = 'CSS2.0,CSS2.1';
355
+ $GLOBALS['csstidy']['all_properties']['padding'] = 'CSS1.0,CSS2.0,CSS2.1';
356
+ $GLOBALS['csstidy']['all_properties']['padding-top'] = 'CSS1.0,CSS2.0,CSS2.1';
357
+ $GLOBALS['csstidy']['all_properties']['padding-right'] = 'CSS1.0,CSS2.0,CSS2.1';
358
+ $GLOBALS['csstidy']['all_properties']['padding-bottom'] = 'CSS1.0,CSS2.0,CSS2.1';
359
+ $GLOBALS['csstidy']['all_properties']['padding-left'] = 'CSS1.0,CSS2.0,CSS2.1';
360
+ $GLOBALS['csstidy']['all_properties']['page-break-before'] = 'CSS1.0,CSS2.0,CSS2.1';
361
+ $GLOBALS['csstidy']['all_properties']['page-break-after'] = 'CSS1.0,CSS2.0,CSS2.1';
362
+ $GLOBALS['csstidy']['all_properties']['page-break-inside'] = 'CSS2.0,CSS2.1';
363
+ $GLOBALS['csstidy']['all_properties']['page'] = 'CSS2.0';
364
+ $GLOBALS['csstidy']['all_properties']['position'] = 'CSS1.0,CSS2.0,CSS2.1';
365
+ $GLOBALS['csstidy']['all_properties']['quotes'] = 'CSS2.0,CSS2.1';
366
+ $GLOBALS['csstidy']['all_properties']['right'] = 'CSS2.0,CSS2.1';
367
+ $GLOBALS['csstidy']['all_properties']['size'] = 'CSS1.0,CSS2.0';
368
+ $GLOBALS['csstidy']['all_properties']['speak-header'] = 'CSS2.0,CSS2.1';
369
+ $GLOBALS['csstidy']['all_properties']['table-layout'] = 'CSS2.0,CSS2.1';
370
+ $GLOBALS['csstidy']['all_properties']['top'] = 'CSS1.0,CSS2.0,CSS2.1';
371
+ $GLOBALS['csstidy']['all_properties']['text-indent'] = 'CSS1.0,CSS2.0,CSS2.1';
372
+ $GLOBALS['csstidy']['all_properties']['text-align'] = 'CSS1.0,CSS2.0,CSS2.1';
373
+ $GLOBALS['csstidy']['all_properties']['text-decoration'] = 'CSS1.0,CSS2.0,CSS2.1';
374
+ $GLOBALS['csstidy']['all_properties']['text-shadow'] = 'CSS2.0';
375
+ $GLOBALS['csstidy']['all_properties']['letter-spacing'] = 'CSS1.0,CSS2.0,CSS2.1';
376
+ $GLOBALS['csstidy']['all_properties']['word-spacing'] = 'CSS1.0,CSS2.0,CSS2.1';
377
+ $GLOBALS['csstidy']['all_properties']['text-transform'] = 'CSS1.0,CSS2.0,CSS2.1';
378
+ $GLOBALS['csstidy']['all_properties']['white-space'] = 'CSS1.0,CSS2.0,CSS2.1';
379
+ $GLOBALS['csstidy']['all_properties']['unicode-bidi'] = 'CSS2.0,CSS2.1';
380
+ $GLOBALS['csstidy']['all_properties']['vertical-align'] = 'CSS1.0,CSS2.0,CSS2.1';
381
+ $GLOBALS['csstidy']['all_properties']['visibility'] = 'CSS1.0,CSS2.0,CSS2.1';
382
+ $GLOBALS['csstidy']['all_properties']['width'] = 'CSS1.0,CSS2.0,CSS2.1';
383
+ $GLOBALS['csstidy']['all_properties']['widows'] = 'CSS2.0,CSS2.1';
384
+ $GLOBALS['csstidy']['all_properties']['z-index'] = 'CSS1.0,CSS2.0,CSS2.1';
385
+ /* Speech */
386
+ $GLOBALS['csstidy']['all_properties']['volume'] = 'CSS2.0,CSS2.1';
387
+ $GLOBALS['csstidy']['all_properties']['speak'] = 'CSS2.0,CSS2.1';
388
+ $GLOBALS['csstidy']['all_properties']['pause'] = 'CSS2.0,CSS2.1';
389
+ $GLOBALS['csstidy']['all_properties']['pause-before'] = 'CSS2.0,CSS2.1';
390
+ $GLOBALS['csstidy']['all_properties']['pause-after'] = 'CSS2.0,CSS2.1';
391
+ $GLOBALS['csstidy']['all_properties']['cue'] = 'CSS2.0,CSS2.1';
392
+ $GLOBALS['csstidy']['all_properties']['cue-before'] = 'CSS2.0,CSS2.1';
393
+ $GLOBALS['csstidy']['all_properties']['cue-after'] = 'CSS2.0,CSS2.1';
394
+ $GLOBALS['csstidy']['all_properties']['play-during'] = 'CSS2.0,CSS2.1';
395
+ $GLOBALS['csstidy']['all_properties']['azimuth'] = 'CSS2.0,CSS2.1';
396
+ $GLOBALS['csstidy']['all_properties']['elevation'] = 'CSS2.0,CSS2.1';
397
+ $GLOBALS['csstidy']['all_properties']['speech-rate'] = 'CSS2.0,CSS2.1';
398
+ $GLOBALS['csstidy']['all_properties']['voice-family'] = 'CSS2.0,CSS2.1';
399
+ $GLOBALS['csstidy']['all_properties']['pitch'] = 'CSS2.0,CSS2.1';
400
+ $GLOBALS['csstidy']['all_properties']['pitch-range'] = 'CSS2.0,CSS2.1';
401
+ $GLOBALS['csstidy']['all_properties']['stress'] = 'CSS2.0,CSS2.1';
402
+ $GLOBALS['csstidy']['all_properties']['richness'] = 'CSS2.0,CSS2.1';
403
+ $GLOBALS['csstidy']['all_properties']['speak-punctuation'] = 'CSS2.0,CSS2.1';
404
+ $GLOBALS['csstidy']['all_properties']['speak-numeral'] = 'CSS2.0,CSS2.1';
405
+
406
+ /**
407
+ * An array containing all predefined templates.
408
+ *
409
+ * @global array $GLOBALS['csstidy']['predefined_templates']
410
+ * @version 1.0
411
+ * @see csstidy::load_template()
412
+ */
413
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="at">'; //string before @rule
414
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after @-rule
415
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="selector">'; //string before selector
416
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after selector
417
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="property">'; //string before property
418
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '</span><span class="value">'; //string after property+before value
419
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '</span><span class="format">;</span>'."\n"; //string after value
420
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="format">}</span>'; //closing bracket - selector
421
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = "\n\n"; //space between blocks {...}
422
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = "\n".'<span class="format">}</span>'. "\n\n"; //closing bracket @-rule
423
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = ''; //indent in @-rule
424
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="comment">'; // before comment
425
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = '</span>'."\n"; // after comment
426
+ $GLOBALS['csstidy']['predefined_templates']['default'][] = "\n"; // after last line @-rule
427
+
428
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="at">';
429
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span> <span class="format">{</span>'."\n";
430
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="selector">';
431
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="format">{</span>';
432
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="property">';
433
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="value">';
434
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="format">;</span>';
435
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="format">}</span>';
436
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = "\n";
437
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = "\n". '<span class="format">}'."\n".'</span>';
438
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '';
439
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="comment">'; // before comment
440
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span>'; // after comment
441
+ $GLOBALS['csstidy']['predefined_templates']['high_compression'][] = "\n";
442
+
443
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="at">';
444
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">{</span>';
445
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="selector">';
446
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">{</span>';
447
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="property">';
448
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="value">';
449
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">;</span>';
450
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="format">}</span>';
451
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '';
452
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="format">}</span>';
453
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '';
454
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="comment">'; // before comment
455
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span>'; // after comment
456
+ $GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '';
457
+
458
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="at">';
459
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span> <span class="format">{</span>'."\n";
460
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="selector">';
461
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span>'."\n".'<span class="format">{</span>'."\n";
462
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = ' <span class="property">';
463
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span><span class="value">';
464
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span><span class="format">;</span>'."\n";
465
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="format">}</span>';
466
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = "\n\n";
467
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = "\n".'<span class="format">}</span>'."\n\n";
468
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = ' ';
469
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="comment">'; // before comment
470
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span>'."\n"; // after comment
471
+ $GLOBALS['csstidy']['predefined_templates']['low_compression'][] = "\n";
472
+
473
+ ?>
lib/JSON.php ADDED
@@ -0,0 +1,863 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( !class_exists( 'Services_JSON' ) ) :
3
+ /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
+ /**
5
+ * Converts to and from JSON format.
6
+ *
7
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
+ * format. It is easy for humans to read and write. It is easy for machines
9
+ * to parse and generate. It is based on a subset of the JavaScript
10
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
+ * This feature can also be found in Python. JSON is a text format that is
12
+ * completely language independent but uses conventions that are familiar
13
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
14
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
+ * ideal data-interchange language.
16
+ *
17
+ * This package provides a simple encoder and decoder for JSON notation. It
18
+ * is intended for use with client-side Javascript applications that make
19
+ * use of HTTPRequest to perform server communication functions - data can
20
+ * be encoded into JSON notation for use in a client-side javascript, or
21
+ * decoded from incoming Javascript requests. JSON format is native to
22
+ * Javascript, and can be directly eval()'ed with no further parsing
23
+ * overhead
24
+ *
25
+ * All strings should be in ASCII or UTF-8 format!
26
+ *
27
+ * LICENSE: Redistribution and use in source and binary forms, with or
28
+ * without modification, are permitted provided that the following
29
+ * conditions are met: Redistributions of source code must retain the
30
+ * above copyright notice, this list of conditions and the following
31
+ * disclaimer. Redistributions in binary form must reproduce the above
32
+ * copyright notice, this list of conditions and the following disclaimer
33
+ * in the documentation and/or other materials provided with the
34
+ * distribution.
35
+ *
36
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
+ * DAMAGE.
47
+ *
48
+ * @category
49
+ * @package Services_JSON
50
+ * @author Michal Migurski <mike-json@teczno.com>
51
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
+ * @copyright 2005 Michal Migurski
54
+ * @version CVS: $Id: JSON.php 288200 2009-09-09 15:41:29Z alan_k $
55
+ * @license http://www.opensource.org/licenses/bsd-license.php
56
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
+ */
58
+
59
+ /**
60
+ * Marker constant for Services_JSON::decode(), used to flag stack state
61
+ */
62
+ define('SERVICES_JSON_SLICE', 1);
63
+
64
+ /**
65
+ * Marker constant for Services_JSON::decode(), used to flag stack state
66
+ */
67
+ define('SERVICES_JSON_IN_STR', 2);
68
+
69
+ /**
70
+ * Marker constant for Services_JSON::decode(), used to flag stack state
71
+ */
72
+ define('SERVICES_JSON_IN_ARR', 3);
73
+
74
+ /**
75
+ * Marker constant for Services_JSON::decode(), used to flag stack state
76
+ */
77
+ define('SERVICES_JSON_IN_OBJ', 4);
78
+
79
+ /**
80
+ * Marker constant for Services_JSON::decode(), used to flag stack state
81
+ */
82
+ define('SERVICES_JSON_IN_CMT', 5);
83
+
84
+ /**
85
+ * Behavior switch for Services_JSON::decode()
86
+ */
87
+ define('SERVICES_JSON_LOOSE_TYPE', 16);
88
+
89
+ /**
90
+ * Behavior switch for Services_JSON::decode()
91
+ */
92
+ define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
+
94
+ /**
95
+ * Converts to and from JSON format.
96
+ *
97
+ * Brief example of use:
98
+ *
99
+ * <code>
100
+ * // create a new instance of Services_JSON
101
+ * $json = new Services_JSON();
102
+ *
103
+ * // convert a complexe value to JSON notation, and send it to the browser
104
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
+ * $output = $json->encode($value);
106
+ *
107
+ * print($output);
108
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
+ *
110
+ * // accept incoming POST data, assumed to be in JSON notation
111
+ * $input = file_get_contents('php://input', 1000000);
112
+ * $value = $json->decode($input);
113
+ * </code>
114
+ */
115
+ class Services_JSON
116
+ {
117
+ /**
118
+ * constructs a new JSON instance
119
+ *
120
+ * @param int $use object behavior flags; combine with boolean-OR
121
+ *
122
+ * possible values:
123
+ * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
+ * "{...}" syntax creates associative arrays
125
+ * instead of objects in decode().
126
+ * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
+ * Values which can't be encoded (e.g. resources)
128
+ * appear as NULL instead of throwing errors.
129
+ * By default, a deeply-nested resource will
130
+ * bubble up with an error, so all return values
131
+ * from encode() should be checked with isError()
132
+ */
133
+ function Services_JSON($use = 0)
134
+ {
135
+ $this->use = $use;
136
+ }
137
+
138
+ /**
139
+ * convert a string from one UTF-16 char to one UTF-8 char
140
+ *
141
+ * Normally should be handled by mb_convert_encoding, but
142
+ * provides a slower PHP-only method for installations
143
+ * that lack the multibye string extension.
144
+ *
145
+ * @param string $utf16 UTF-16 character
146
+ * @return string UTF-8 character
147
+ * @access private
148
+ */
149
+ function utf162utf8($utf16)
150
+ {
151
+ // oh please oh please oh please oh please oh please
152
+ if(function_exists('mb_convert_encoding')) {
153
+ return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
154
+ }
155
+
156
+ $bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
157
+
158
+ switch(true) {
159
+ case ((0x7F & $bytes) == $bytes):
160
+ // this case should never be reached, because we are in ASCII range
161
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
162
+ return chr(0x7F & $bytes);
163
+
164
+ case (0x07FF & $bytes) == $bytes:
165
+ // return a 2-byte UTF-8 character
166
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
167
+ return chr(0xC0 | (($bytes >> 6) & 0x1F))
168
+ . chr(0x80 | ($bytes & 0x3F));
169
+
170
+ case (0xFFFF & $bytes) == $bytes:
171
+ // return a 3-byte UTF-8 character
172
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
+ return chr(0xE0 | (($bytes >> 12) & 0x0F))
174
+ . chr(0x80 | (($bytes >> 6) & 0x3F))
175
+ . chr(0x80 | ($bytes & 0x3F));
176
+ }
177
+
178
+ // ignoring UTF-32 for now, sorry
179
+ return '';
180
+ }
181
+
182
+ /**
183
+ * convert a string from one UTF-8 char to one UTF-16 char
184
+ *
185
+ * Normally should be handled by mb_convert_encoding, but
186
+ * provides a slower PHP-only method for installations
187
+ * that lack the multibye string extension.
188
+ *
189
+ * @param string $utf8 UTF-8 character
190
+ * @return string UTF-16 character
191
+ * @access private
192
+ */
193
+ function utf82utf16($utf8)
194
+ {
195
+ // oh please oh please oh please oh please oh please
196
+ if(function_exists('mb_convert_encoding')) {
197
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
198
+ }
199
+
200
+ switch(strlen($utf8)) {
201
+ case 1:
202
+ // this case should never be reached, because we are in ASCII range
203
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
204
+ return $utf8;
205
+
206
+ case 2:
207
+ // return a UTF-16 character from a 2-byte UTF-8 char
208
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
209
+ return chr(0x07 & (ord($utf8[0]) >> 2))
210
+ . chr((0xC0 & (ord($utf8[0]) << 6))
211
+ | (0x3F & ord($utf8[1])));
212
+
213
+ case 3:
214
+ // return a UTF-16 character from a 3-byte UTF-8 char
215
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
216
+ return chr((0xF0 & (ord($utf8[0]) << 4))
217
+ | (0x0F & (ord($utf8[1]) >> 2)))
218
+ . chr((0xC0 & (ord($utf8[1]) << 6))
219
+ | (0x7F & ord($utf8[2])));
220
+ }
221
+
222
+ // ignoring UTF-32 for now, sorry
223
+ return '';
224
+ }
225
+
226
+ /**
227
+ * encodes an arbitrary variable into JSON format (and sends JSON Header)
228
+ *
229
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
230
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
231
+ * if var is a strng, note that encode() always expects it
232
+ * to be in ASCII or UTF-8 format!
233
+ *
234
+ * @return mixed JSON string representation of input var or an error if a problem occurs
235
+ * @access public
236
+ */
237
+ function encode($var)
238
+ {
239
+ header('Content-type: application/json');
240
+ return $this->_encode($var);
241
+ }
242
+ /**
243
+ * encodes an arbitrary variable into JSON format without JSON Header - warning - may allow CSS!!!!)
244
+ *
245
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
246
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
247
+ * if var is a strng, note that encode() always expects it
248
+ * to be in ASCII or UTF-8 format!
249
+ *
250
+ * @return mixed JSON string representation of input var or an error if a problem occurs
251
+ * @access public
252
+ */
253
+ function encodeUnsafe($var)
254
+ {
255
+ return $this->_encode($var);
256
+ }
257
+ /**
258
+ * PRIVATE CODE that does the work of encodes an arbitrary variable into JSON format
259
+ *
260
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
261
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
262
+ * if var is a strng, note that encode() always expects it
263
+ * to be in ASCII or UTF-8 format!
264
+ *
265
+ * @return mixed JSON string representation of input var or an error if a problem occurs
266
+ * @access public
267
+ */
268
+ function _encode($var)
269
+ {
270
+
271
+ switch (gettype($var)) {
272
+ case 'boolean':
273
+ return $var ? 'true' : 'false';
274
+
275
+ case 'NULL':
276
+ return 'null';
277
+
278
+ case 'integer':
279
+ return (int) $var;
280
+
281
+ case 'double':
282
+ case 'float':
283
+ return (float) $var;
284
+
285
+ case 'string':
286
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
287
+ $ascii = '';
288
+ $strlen_var = strlen($var);
289
+
290
+ /*
291
+ * Iterate over every character in the string,
292
+ * escaping with a slash or encoding to UTF-8 where necessary
293
+ */
294
+ for ($c = 0; $c < $strlen_var; ++$c) {
295
+
296
+ $ord_var_c = ord($var[$c]);
297
+
298
+ switch (true) {
299
+ case $ord_var_c == 0x08:
300
+ $ascii .= '\b';
301
+ break;
302
+ case $ord_var_c == 0x09:
303
+ $ascii .= '\t';
304
+ break;
305
+ case $ord_var_c == 0x0A:
306
+ $ascii .= '\n';
307
+ break;
308
+ case $ord_var_c == 0x0C:
309
+ $ascii .= '\f';
310
+ break;
311
+ case $ord_var_c == 0x0D:
312
+ $ascii .= '\r';
313
+ break;
314
+
315
+ case $ord_var_c == 0x22:
316
+ case $ord_var_c == 0x2F:
317
+ case $ord_var_c == 0x5C:
318
+ // double quote, slash, slosh
319
+ $ascii .= '\\'.$var[$c];
320
+ break;
321
+
322
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
323
+ // characters U-00000000 - U-0000007F (same as ASCII)
324
+ $ascii .= $var[$c];
325
+ break;
326
+
327
+ case (($ord_var_c & 0xE0) == 0xC0):
328
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
329
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
330
+ if ($c+1 >= $strlen_var) {
331
+ $c += 1;
332
+ $ascii .= '?';
333
+ break;
334
+ }
335
+
336
+ $char = pack('C*', $ord_var_c, ord($var[$c + 1]));
337
+ $c += 1;
338
+ $utf16 = $this->utf82utf16($char);
339
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
340
+ break;
341
+
342
+ case (($ord_var_c & 0xF0) == 0xE0):
343
+ if ($c+2 >= $strlen_var) {
344
+ $c += 2;
345
+ $ascii .= '?';
346
+ break;
347
+ }
348
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
349
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
350
+ $char = pack('C*', $ord_var_c,
351
+ @ord($var[$c + 1]),
352
+ @ord($var[$c + 2]));
353
+ $c += 2;
354
+ $utf16 = $this->utf82utf16($char);
355
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
356
+ break;
357
+
358
+ case (($ord_var_c & 0xF8) == 0xF0):
359
+ if ($c+3 >= $strlen_var) {
360
+ $c += 3;
361
+ $ascii .= '?';
362
+ break;
363
+ }
364
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
365
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
366
+ $char = pack('C*', $ord_var_c,
367
+ ord($var[$c + 1]),
368
+ ord($var[$c + 2]),
369
+ ord($var[$c + 3]));
370
+ $c += 3;
371
+ $utf16 = $this->utf82utf16($char);
372
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
373
+ break;
374
+
375
+ case (($ord_var_c & 0xFC) == 0xF8):
376
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
377
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
378
+ if ($c+4 >= $strlen_var) {
379
+ $c += 4;
380
+ $ascii .= '?';
381
+ break;
382
+ }
383
+ $char = pack('C*', $ord_var_c,
384
+ ord($var[$c + 1]),
385
+ ord($var[$c + 2]),
386
+ ord($var[$c + 3]),
387
+ ord($var[$c + 4]));
388
+ $c += 4;
389
+ $utf16 = $this->utf82utf16($char);
390
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
391
+ break;
392
+
393
+ case (($ord_var_c & 0xFE) == 0xFC):
394
+ if ($c+5 >= $strlen_var) {
395
+ $c += 5;
396
+ $ascii .= '?';
397
+ break;
398
+ }
399
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
400
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
401
+ $char = pack('C*', $ord_var_c,
402
+ ord($var[$c + 1]),
403
+ ord($var[$c + 2]),
404
+ ord($var[$c + 3]),
405
+ ord($var[$c + 4]),
406
+ ord($var[$c + 5]));
407
+ $c += 5;
408
+ $utf16 = $this->utf82utf16($char);
409
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
410
+ break;
411
+ }
412
+ }
413
+ return '"'.$ascii.'"';
414
+
415
+ case 'array':
416
+ /*
417
+ * As per JSON spec if any array key is not an integer
418
+ * we must treat the the whole array as an object. We
419
+ * also try to catch a sparsely populated associative
420
+ * array with numeric keys here because some JS engines
421
+ * will create an array with empty indexes up to
422
+ * max_index which can cause memory issues and because
423
+ * the keys, which may be relevant, will be remapped
424
+ * otherwise.
425
+ *
426
+ * As per the ECMA and JSON specification an object may
427
+ * have any string as a property. Unfortunately due to
428
+ * a hole in the ECMA specification if the key is a
429
+ * ECMA reserved word or starts with a digit the
430
+ * parameter is only accessible using ECMAScript's
431
+ * bracket notation.
432
+ */
433
+
434
+ // treat as a JSON object
435
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
436
+ $properties = array_map(array($this, 'name_value'),
437
+ array_keys($var),
438
+ array_values($var));
439
+
440
+ foreach($properties as $property) {
441
+ if(Services_JSON::isError($property)) {
442
+ return $property;
443
+ }
444
+ }
445
+
446
+ return '{' . join(',', $properties) . '}';
447
+ }
448
+
449
+ // treat it like a regular array
450
+ $elements = array_map(array($this, '_encode'), $var);
451
+
452
+ foreach($elements as $element) {
453
+ if(Services_JSON::isError($element)) {
454
+ return $element;
455
+ }
456
+ }
457
+
458
+ return '[' . join(',', $elements) . ']';
459
+
460
+ case 'object':
461
+ $vars = get_object_vars($var);
462
+
463
+ $properties = array_map(array($this, 'name_value'),
464
+ array_keys($vars),
465
+ array_values($vars));
466
+
467
+ foreach($properties as $property) {
468
+ if(Services_JSON::isError($property)) {
469
+ return $property;
470
+ }
471
+ }
472
+
473
+ return '{' . join(',', $properties) . '}';
474
+
475
+ default:
476
+ return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
477
+ ? 'null'
478
+ : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
479
+ }
480
+ }
481
+
482
+ /**
483
+ * array-walking function for use in generating JSON-formatted name-value pairs
484
+ *
485
+ * @param string $name name of key to use
486
+ * @param mixed $value reference to an array element to be encoded
487
+ *
488
+ * @return string JSON-formatted name-value pair, like '"name":value'
489
+ * @access private
490
+ */
491
+ function name_value($name, $value)
492
+ {
493
+ $encoded_value = $this->_encode($value);
494
+
495
+ if(Services_JSON::isError($encoded_value)) {
496
+ return $encoded_value;
497
+ }
498
+
499
+ return $this->_encode(strval($name)) . ':' . $encoded_value;
500
+ }
501
+
502
+ /**
503
+ * reduce a string by removing leading and trailing comments and whitespace
504
+ *
505
+ * @param $str string string value to strip of comments and whitespace
506
+ *
507
+ * @return string string value stripped of comments and whitespace
508
+ * @access private
509
+ */
510
+ function reduce_string($str)
511
+ {
512
+ $str = preg_replace(array(
513
+
514
+ // eliminate single line comments in '// ...' form
515
+ '#^\s*//(.+)$#m',
516
+
517
+ // eliminate multi-line comments in '/* ... */' form, at start of string
518
+ '#^\s*/\*(.+)\*/#Us',
519
+
520
+ // eliminate multi-line comments in '/* ... */' form, at end of string
521
+ '#/\*(.+)\*/\s*$#Us'
522
+
523
+ ), '', $str);
524
+
525
+ // eliminate extraneous space
526
+ return trim($str);
527
+ }
528
+
529
+ /**
530
+ * decodes a JSON string into appropriate variable
531
+ *
532
+ * @param string $str JSON-formatted string
533
+ *
534
+ * @return mixed number, boolean, string, array, or object
535
+ * corresponding to given JSON input string.
536
+ * See argument 1 to Services_JSON() above for object-output behavior.
537
+ * Note that decode() always returns strings
538
+ * in ASCII or UTF-8 format!
539
+ * @access public
540
+ */
541
+ function decode($str)
542
+ {
543
+ $str = $this->reduce_string($str);
544
+
545
+ switch (strtolower($str)) {
546
+ case 'true':
547
+ return true;
548
+
549
+ case 'false':
550
+ return false;
551
+
552
+ case 'null':
553
+ return null;
554
+
555
+ default:
556
+ $m = array();
557
+
558
+ if (is_numeric($str)) {
559
+ // Lookie-loo, it's a number
560
+
561
+ // This would work on its own, but I'm trying to be
562
+ // good about returning integers where appropriate:
563
+ // return (float)$str;
564
+
565
+ // Return float or int, as appropriate
566
+ return ((float)$str == (integer)$str)
567
+ ? (integer)$str
568
+ : (float)$str;
569
+
570
+ } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
571
+ // STRINGS RETURNED IN UTF-8 FORMAT
572
+ $delim = substr($str, 0, 1);
573
+ $chrs = substr($str, 1, -1);
574
+ $utf8 = '';
575
+ $strlen_chrs = strlen($chrs);
576
+
577
+ for ($c = 0; $c < $strlen_chrs; ++$c) {
578
+
579
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
580
+ $ord_chrs_c = ord($chrs[$c]);
581
+
582
+ switch (true) {
583
+ case $substr_chrs_c_2 == '\b':
584
+ $utf8 .= chr(0x08);
585
+ ++$c;
586
+ break;
587
+ case $substr_chrs_c_2 == '\t':
588
+ $utf8 .= chr(0x09);
589
+ ++$c;
590
+ break;
591
+ case $substr_chrs_c_2 == '\n':
592
+ $utf8 .= chr(0x0A);
593
+ ++$c;
594
+ break;
595
+ case $substr_chrs_c_2 == '\f':
596
+ $utf8 .= chr(0x0C);
597
+ ++$c;
598
+ break;
599
+ case $substr_chrs_c_2 == '\r':
600
+ $utf8 .= chr(0x0D);
601
+ ++$c;
602
+ break;
603
+
604
+ case $substr_chrs_c_2 == '\\"':
605
+ case $substr_chrs_c_2 == '\\\'':
606
+ case $substr_chrs_c_2 == '\\\\':
607
+ case $substr_chrs_c_2 == '\\/':
608
+ if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
609
+ ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
610
+ $utf8 .= $chrs[++$c];
611
+ }
612
+ break;
613
+
614
+ case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
615
+ // single, escaped unicode character
616
+ $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
617
+ . chr(hexdec(substr($chrs, ($c + 4), 2)));
618
+ $utf8 .= $this->utf162utf8($utf16);
619
+ $c += 5;
620
+ break;
621
+
622
+ case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
623
+ $utf8 .= $chrs[$c];
624
+ break;
625
+
626
+ case ($ord_chrs_c & 0xE0) == 0xC0:
627
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
628
+ //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
629
+ $utf8 .= substr($chrs, $c, 2);
630
+ ++$c;
631
+ break;
632
+
633
+ case ($ord_chrs_c & 0xF0) == 0xE0:
634
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
635
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
636
+ $utf8 .= substr($chrs, $c, 3);
637
+ $c += 2;
638
+ break;
639
+
640
+ case ($ord_chrs_c & 0xF8) == 0xF0:
641
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
642
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
643
+ $utf8 .= substr($chrs, $c, 4);
644
+ $c += 3;
645
+ break;
646
+
647
+ case ($ord_chrs_c & 0xFC) == 0xF8:
648
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
649
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
650
+ $utf8 .= substr($chrs, $c, 5);
651
+ $c += 4;
652
+ break;
653
+
654
+ case ($ord_chrs_c & 0xFE) == 0xFC:
655
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
656
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
657
+ $utf8 .= substr($chrs, $c, 6);
658
+ $c += 5;
659
+ break;
660
+
661
+ }
662
+
663
+ }
664
+
665
+ return $utf8;
666
+
667
+ } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
668
+ // array, or object notation
669
+
670
+ if ($str[0] == '[') {
671
+ $stk = array(SERVICES_JSON_IN_ARR);
672
+ $arr = array();
673
+ } else {
674
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
675
+ $stk = array(SERVICES_JSON_IN_OBJ);
676
+ $obj = array();
677
+ } else {
678
+ $stk = array(SERVICES_JSON_IN_OBJ);
679
+ $obj = new stdClass();
680
+ }
681
+ }
682
+
683
+ array_push($stk, array('what' => SERVICES_JSON_SLICE,
684
+ 'where' => 0,
685
+ 'delim' => false));
686
+
687
+ $chrs = substr($str, 1, -1);
688
+ $chrs = $this->reduce_string($chrs);
689
+
690
+ if ($chrs == '') {
691
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
692
+ return $arr;
693
+
694
+ } else {
695
+ return $obj;
696
+
697
+ }
698
+ }
699
+
700
+ //print("\nparsing {$chrs}\n");
701
+
702
+ $strlen_chrs = strlen($chrs);
703
+
704
+ for ($c = 0; $c <= $strlen_chrs; ++$c) {
705
+
706
+ $top = end($stk);
707
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
708
+
709
+ if (($c == $strlen_chrs) || (($chrs[$c] == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
710
+ // found a comma that is not inside a string, array, etc.,
711
+ // OR we've reached the end of the character list
712
+ $slice = substr($chrs, $top['where'], ($c - $top['where']));
713
+ array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
714
+ //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
715
+
716
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
717
+ // we are in an array, so just push an element onto the stack
718
+ array_push($arr, $this->decode($slice));
719
+
720
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
721
+ // we are in an object, so figure
722
+ // out the property name and set an
723
+ // element in an associative array,
724
+ // for now
725
+ $parts = array();
726
+
727
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
728
+ // "name":value pair
729
+ $key = $this->decode($parts[1]);
730
+ $val = $this->decode($parts[2]);
731
+
732
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
733
+ $obj[$key] = $val;
734
+ } else {
735
+ $obj->$key = $val;
736
+ }
737
+ } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
738
+ // name:value pair, where name is unquoted
739
+ $key = $parts[1];
740
+ $val = $this->decode($parts[2]);
741
+
742
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
743
+ $obj[$key] = $val;
744
+ } else {
745
+ $obj->$key = $val;
746
+ }
747
+ }
748
+
749
+ }
750
+
751
+ } elseif ((($chrs[$c] == '"') || ($chrs[$c] == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
752
+ // found a quote, and we are not inside a string
753
+ array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs[$c]));
754
+ //print("Found start of string at {$c}\n");
755
+
756
+ } elseif (($chrs[$c] == $top['delim']) &&
757
+ ($top['what'] == SERVICES_JSON_IN_STR) &&
758
+ ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
759
+ // found a quote, we're in a string, and it's not escaped
760
+ // we know that it's not escaped becase there is _not_ an
761
+ // odd number of backslashes at the end of the string so far
762
+ array_pop($stk);
763
+ //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
764
+
765
+ } elseif (($chrs[$c] == '[') &&
766
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
767
+ // found a left-bracket, and we are in an array, object, or slice
768
+ array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
769
+ //print("Found start of array at {$c}\n");
770
+
771
+ } elseif (($chrs[$c] == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
772
+ // found a right-bracket, and we're in an array
773
+ array_pop($stk);
774
+ //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
775
+
776
+ } elseif (($chrs[$c] == '{') &&
777
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
778
+ // found a left-brace, and we are in an array, object, or slice
779
+ array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
780
+ //print("Found start of object at {$c}\n");
781
+
782
+ } elseif (($chrs[$c] == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
783
+ // found a right-brace, and we're in an object
784
+ array_pop($stk);
785
+ //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
786
+
787
+ } elseif (($substr_chrs_c_2 == '/*') &&
788
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
789
+ // found a comment start, and we are in an array, object, or slice
790
+ array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
791
+ $c++;
792
+ //print("Found start of comment at {$c}\n");
793
+
794
+ } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
795
+ // found a comment end, and we're in one now
796
+ array_pop($stk);
797
+ $c++;
798
+
799
+ for ($i = $top['where']; $i <= $c; ++$i)
800
+ $chrs = substr_replace($chrs, ' ', $i, 1);
801
+
802
+ //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
803
+
804
+ }
805
+
806
+ }
807
+
808
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
809
+ return $arr;
810
+
811
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
812
+ return $obj;
813
+
814
+ }
815
+
816
+ }
817
+ }
818
+ }
819
+
820
+ /**
821
+ * @todo Ultimately, this should just call PEAR::isError()
822
+ */
823
+ function isError($data, $code = null)
824
+ {
825
+ if (class_exists('pear')) {
826
+ return PEAR::isError($data, $code);
827
+ } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
828
+ is_subclass_of($data, 'services_json_error'))) {
829
+ return true;
830
+ }
831
+
832
+ return false;
833
+ }
834
+ }
835
+
836
+ if (class_exists('PEAR_Error')) {
837
+
838
+ class Services_JSON_Error extends PEAR_Error
839
+ {
840
+ function Services_JSON_Error($message = 'unknown error', $code = null,
841
+ $mode = null, $options = null, $userinfo = null)
842
+ {
843
+ parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
844
+ }
845
+ }
846
+
847
+ } else {
848
+
849
+ /**
850
+ * @todo Ultimately, this class shall be descended from PEAR_Error
851
+ */
852
+ class Services_JSON_Error
853
+ {
854
+ function Services_JSON_Error($message = 'unknown error', $code = null,
855
+ $mode = null, $options = null, $userinfo = null)
856
+ {
857
+
858
+ }
859
+ }
860
+
861
+ }
862
+ endif;
863
+ ?>
lib/Microsoft/Exception.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ */
33
+
34
+
35
+ /**
36
+ * @category Microsoft
37
+ * @package Microsoft
38
+ * @subpackage Exception
39
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
40
+ * @license http://phpazure.codeplex.com/license
41
+ */
42
+ class Microsoft_Exception extends Exception
43
+ {}
lib/Microsoft/Http/Client.php ADDED
@@ -0,0 +1,1444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client
19
+ * @version $Id: Client.php 19661 2009-12-15 18:03:07Z matthew $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+
25
+ /**
26
+ * @see Microsoft_Uri
27
+ */
28
+ require_once 'Microsoft/Uri.php';
29
+
30
+
31
+ /**
32
+ * @see Microsoft_Http_Client_Adapter_Interface
33
+ */
34
+ require_once 'Microsoft/Http/Client/Adapter/Interface.php';
35
+
36
+
37
+ /**
38
+ * @see Microsoft_Http_Response
39
+ */
40
+ require_once 'Microsoft/Http/Response.php';
41
+
42
+ /**
43
+ * @see Microsoft_Http_Response_Stream
44
+ */
45
+ require_once 'Microsoft/Http/Response/Stream.php';
46
+
47
+ /**
48
+ * Microsoft_Http_Client is an implemetation of an HTTP client in PHP. The client
49
+ * supports basic features like sending different HTTP requests and handling
50
+ * redirections, as well as more advanced features like proxy settings, HTTP
51
+ * authentication and cookie persistance (using a Microsoft_Http_CookieJar object)
52
+ *
53
+ * @todo Implement proxy settings
54
+ * @category Microsoft
55
+ * @package Microsoft_Http
56
+ * @subpackage Client
57
+ * @throws Microsoft_Http_Client_Exception
58
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
59
+ * @license http://framework.zend.com/license/new-bsd New BSD License
60
+ */
61
+ class Microsoft_Http_Client
62
+ {
63
+ /**
64
+ * HTTP request methods
65
+ */
66
+ const GET = 'GET';
67
+ const POST = 'POST';
68
+ const PUT = 'PUT';
69
+ const HEAD = 'HEAD';
70
+ const DELETE = 'DELETE';
71
+ const TRACE = 'TRACE';
72
+ const OPTIONS = 'OPTIONS';
73
+ const CONNECT = 'CONNECT';
74
+ const MERGE = 'MERGE';
75
+
76
+ /**
77
+ * Supported HTTP Authentication methods
78
+ */
79
+ const AUTH_BASIC = 'basic';
80
+ //const AUTH_DIGEST = 'digest'; <-- not implemented yet
81
+
82
+ /**
83
+ * HTTP protocol versions
84
+ */
85
+ const HTTP_1 = '1.1';
86
+ const HTTP_0 = '1.0';
87
+
88
+ /**
89
+ * Content attributes
90
+ */
91
+ const CONTENT_TYPE = 'Content-Type';
92
+ const CONTENT_LENGTH = 'Content-Length';
93
+
94
+ /**
95
+ * POST data encoding methods
96
+ */
97
+ const ENC_URLENCODED = 'application/x-www-form-urlencoded';
98
+ const ENC_FORMDATA = 'multipart/form-data';
99
+
100
+ /**
101
+ * Configuration array, set using the constructor or using ::setConfig()
102
+ *
103
+ * @var array
104
+ */
105
+ protected $config = array(
106
+ 'maxredirects' => 5,
107
+ 'strictredirects' => false,
108
+ 'useragent' => 'Microsoft_Http_Client',
109
+ 'timeout' => 10,
110
+ 'adapter' => 'Microsoft_Http_Client_Adapter_Socket',
111
+ 'httpversion' => self::HTTP_1,
112
+ 'keepalive' => false,
113
+ 'storeresponse' => true,
114
+ 'strict' => true,
115
+ 'output_stream' => false,
116
+ );
117
+
118
+ /**
119
+ * The adapter used to preform the actual connection to the server
120
+ *
121
+ * @var Microsoft_Http_Client_Adapter_Interface
122
+ */
123
+ protected $adapter = null;
124
+
125
+ /**
126
+ * Request URI
127
+ *
128
+ * @var Microsoft_Uri_Http
129
+ */
130
+ protected $uri = null;
131
+
132
+ /**
133
+ * Associative array of request headers
134
+ *
135
+ * @var array
136
+ */
137
+ protected $headers = array();
138
+
139
+ /**
140
+ * HTTP request method
141
+ *
142
+ * @var string
143
+ */
144
+ protected $method = self::GET;
145
+
146
+ /**
147
+ * Associative array of GET parameters
148
+ *
149
+ * @var array
150
+ */
151
+ protected $paramsGet = array();
152
+
153
+ /**
154
+ * Assiciative array of POST parameters
155
+ *
156
+ * @var array
157
+ */
158
+ protected $paramsPost = array();
159
+
160
+ /**
161
+ * Request body content type (for POST requests)
162
+ *
163
+ * @var string
164
+ */
165
+ protected $enctype = null;
166
+
167
+ /**
168
+ * The raw post data to send. Could be set by setRawData($data, $enctype).
169
+ *
170
+ * @var string
171
+ */
172
+ protected $raw_post_data = null;
173
+
174
+ /**
175
+ * HTTP Authentication settings
176
+ *
177
+ * Expected to be an associative array with this structure:
178
+ * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic')
179
+ * Where 'type' should be one of the supported authentication types (see the AUTH_*
180
+ * constants), for example 'basic' or 'digest'.
181
+ *
182
+ * If null, no authentication will be used.
183
+ *
184
+ * @var array|null
185
+ */
186
+ protected $auth;
187
+
188
+ /**
189
+ * File upload arrays (used in POST requests)
190
+ *
191
+ * An associative array, where each element is of the format:
192
+ * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents')
193
+ *
194
+ * @var array
195
+ */
196
+ protected $files = array();
197
+
198
+ /**
199
+ * The client's cookie jar
200
+ *
201
+ * @var Microsoft_Http_CookieJar
202
+ */
203
+ protected $cookiejar = null;
204
+
205
+ /**
206
+ * The last HTTP request sent by the client, as string
207
+ *
208
+ * @var string
209
+ */
210
+ protected $last_request = null;
211
+
212
+ /**
213
+ * The last HTTP response received by the client
214
+ *
215
+ * @var Microsoft_Http_Response
216
+ */
217
+ protected $last_response = null;
218
+
219
+ /**
220
+ * Redirection counter
221
+ *
222
+ * @var int
223
+ */
224
+ protected $redirectCounter = 0;
225
+
226
+ /**
227
+ * Fileinfo magic database resource
228
+ *
229
+ * This varaiable is populated the first time _detectFileMimeType is called
230
+ * and is then reused on every call to this method
231
+ *
232
+ * @var resource
233
+ */
234
+ static protected $_fileInfoDb = null;
235
+
236
+ /**
237
+ * Contructor method. Will create a new HTTP client. Accepts the target
238
+ * URL and optionally configuration array.
239
+ *
240
+ * @param Microsoft_Uri_Http|string $uri
241
+ * @param array $config Configuration key-value pairs.
242
+ */
243
+ public function __construct($uri = null, $config = null)
244
+ {
245
+ if ($uri !== null) {
246
+ $this->setUri($uri);
247
+ }
248
+ if ($config !== null) {
249
+ $this->setConfig($config);
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Set the URI for the next request
255
+ *
256
+ * @param Microsoft_Uri_Http|string $uri
257
+ * @return Microsoft_Http_Client
258
+ * @throws Microsoft_Http_Client_Exception
259
+ */
260
+ public function setUri($uri)
261
+ {
262
+ if (is_string($uri)) {
263
+ $uri = Microsoft_Uri::factory($uri);
264
+ }
265
+
266
+ if (!$uri instanceof Microsoft_Uri_Http) {
267
+ /** @see Microsoft_Http_Client_Exception */
268
+ require_once 'Microsoft/Http/Client/Exception.php';
269
+ throw new Microsoft_Http_Client_Exception('Passed parameter is not a valid HTTP URI.');
270
+ }
271
+
272
+ // Set auth if username and password has been specified in the uri
273
+ if ($uri->getUsername() && $uri->getPassword()) {
274
+ $this->setAuth($uri->getUsername(), $uri->getPassword());
275
+ }
276
+
277
+ // We have no ports, set the defaults
278
+ if (! $uri->getPort()) {
279
+ $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80));
280
+ }
281
+
282
+ $this->uri = $uri;
283
+
284
+ return $this;
285
+ }
286
+
287
+ /**
288
+ * Get the URI for the next request
289
+ *
290
+ * @param boolean $as_string If true, will return the URI as a string
291
+ * @return Microsoft_Uri_Http|string
292
+ */
293
+ public function getUri($as_string = false)
294
+ {
295
+ if ($as_string && $this->uri instanceof Microsoft_Uri_Http) {
296
+ return $this->uri->__toString();
297
+ } else {
298
+ return $this->uri;
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Set configuration parameters for this HTTP client
304
+ *
305
+ * @param Microsoft_Config | array $config
306
+ * @return Microsoft_Http_Client
307
+ * @throws Microsoft_Http_Client_Exception
308
+ */
309
+ public function setConfig($config = array())
310
+ {
311
+ if ($config instanceof Microsoft_Config) {
312
+ $config = $config->toArray();
313
+
314
+ } elseif (! is_array($config)) {
315
+ /** @see Microsoft_Http_Client_Exception */
316
+ require_once 'Microsoft/Http/Client/Exception.php';
317
+ throw new Microsoft_Http_Client_Exception('Array expected, got ' . gettype($config));
318
+ }
319
+
320
+ foreach ($config as $k => $v) {
321
+ $this->config[strtolower($k)] = $v;
322
+ }
323
+
324
+ // Pass configuration options to the adapter if it exists
325
+ if ($this->adapter instanceof Microsoft_Http_Client_Adapter_Interface) {
326
+ $this->adapter->setConfig($config);
327
+ }
328
+
329
+ return $this;
330
+ }
331
+
332
+ /**
333
+ * Set the next request's method
334
+ *
335
+ * Validated the passed method and sets it. If we have files set for
336
+ * POST requests, and the new method is not POST, the files are silently
337
+ * dropped.
338
+ *
339
+ * @param string $method
340
+ * @return Microsoft_Http_Client
341
+ * @throws Microsoft_Http_Client_Exception
342
+ */
343
+ public function setMethod($method = self::GET)
344
+ {
345
+ if (! preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/', $method)) {
346
+ /** @see Microsoft_Http_Client_Exception */
347
+ require_once 'Microsoft/Http/Client/Exception.php';
348
+ throw new Microsoft_Http_Client_Exception("'{$method}' is not a valid HTTP request method.");
349
+ }
350
+
351
+ if ($method == self::POST && $this->enctype === null) {
352
+ $this->setEncType(self::ENC_URLENCODED);
353
+ }
354
+
355
+ $this->method = $method;
356
+
357
+ return $this;
358
+ }
359
+
360
+ /**
361
+ * Set one or more request headers
362
+ *
363
+ * This function can be used in several ways to set the client's request
364
+ * headers:
365
+ * 1. By providing two parameters: $name as the header to set (eg. 'Host')
366
+ * and $value as it's value (eg. 'www.example.com').
367
+ * 2. By providing a single header string as the only parameter
368
+ * eg. 'Host: www.example.com'
369
+ * 3. By providing an array of headers as the first parameter
370
+ * eg. array('host' => 'www.example.com', 'x-foo: bar'). In This case
371
+ * the function will call itself recursively for each array item.
372
+ *
373
+ * @param string|array $name Header name, full header string ('Header: value')
374
+ * or an array of headers
375
+ * @param mixed $value Header value or null
376
+ * @return Microsoft_Http_Client
377
+ * @throws Microsoft_Http_Client_Exception
378
+ */
379
+ public function setHeaders($name, $value = null)
380
+ {
381
+ // If we got an array, go recusive!
382
+ if (is_array($name)) {
383
+ foreach ($name as $k => $v) {
384
+ if (is_string($k)) {
385
+ $this->setHeaders($k, $v);
386
+ } else {
387
+ $this->setHeaders($v, null);
388
+ }
389
+ }
390
+ } else {
391
+ // Check if $name needs to be split
392
+ if ($value === null && (strpos($name, ':') > 0)) {
393
+ list($name, $value) = explode(':', $name, 2);
394
+ }
395
+
396
+ // Make sure the name is valid if we are in strict mode
397
+ if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) {
398
+ /** @see Microsoft_Http_Client_Exception */
399
+ require_once 'Microsoft/Http/Client/Exception.php';
400
+ throw new Microsoft_Http_Client_Exception("{$name} is not a valid HTTP header name");
401
+ }
402
+
403
+ $normalized_name = strtolower($name);
404
+
405
+ // If $value is null or false, unset the header
406
+ if ($value === null || $value === false) {
407
+ unset($this->headers[$normalized_name]);
408
+
409
+ // Else, set the header
410
+ } else {
411
+ // Header names are stored lowercase internally.
412
+ if (is_string($value)) {
413
+ $value = trim($value);
414
+ }
415
+ $this->headers[$normalized_name] = array($name, $value);
416
+ }
417
+ }
418
+
419
+ return $this;
420
+ }
421
+
422
+ /**
423
+ * Get the value of a specific header
424
+ *
425
+ * Note that if the header has more than one value, an array
426
+ * will be returned.
427
+ *
428
+ * @param string $key
429
+ * @return string|array|null The header value or null if it is not set
430
+ */
431
+ public function getHeader($key)
432
+ {
433
+ $key = strtolower($key);
434
+ if (isset($this->headers[$key])) {
435
+ return $this->headers[$key][1];
436
+ } else {
437
+ return null;
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Set a GET parameter for the request. Wrapper around _setParameter
443
+ *
444
+ * @param string|array $name
445
+ * @param string $value
446
+ * @return Microsoft_Http_Client
447
+ */
448
+ public function setParameterGet($name, $value = null)
449
+ {
450
+ if (is_array($name)) {
451
+ foreach ($name as $k => $v)
452
+ $this->_setParameter('GET', $k, $v);
453
+ } else {
454
+ $this->_setParameter('GET', $name, $value);
455
+ }
456
+
457
+ return $this;
458
+ }
459
+
460
+ /**
461
+ * Set a POST parameter for the request. Wrapper around _setParameter
462
+ *
463
+ * @param string|array $name
464
+ * @param string $value
465
+ * @return Microsoft_Http_Client
466
+ */
467
+ public function setParameterPost($name, $value = null)
468
+ {
469
+ if (is_array($name)) {
470
+ foreach ($name as $k => $v)
471
+ $this->_setParameter('POST', $k, $v);
472
+ } else {
473
+ $this->_setParameter('POST', $name, $value);
474
+ }
475
+
476
+ return $this;
477
+ }
478
+
479
+ /**
480
+ * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost
481
+ *
482
+ * @param string $type GET or POST
483
+ * @param string $name
484
+ * @param string $value
485
+ * @return null
486
+ */
487
+ protected function _setParameter($type, $name, $value)
488
+ {
489
+ $parray = array();
490
+ $type = strtolower($type);
491
+ switch ($type) {
492
+ case 'get':
493
+ $parray = &$this->paramsGet;
494
+ break;
495
+ case 'post':
496
+ $parray = &$this->paramsPost;
497
+ break;
498
+ }
499
+
500
+ if ($value === null) {
501
+ if (isset($parray[$name])) unset($parray[$name]);
502
+ } else {
503
+ $parray[$name] = $value;
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Get the number of redirections done on the last request
509
+ *
510
+ * @return int
511
+ */
512
+ public function getRedirectionsCount()
513
+ {
514
+ return $this->redirectCounter;
515
+ }
516
+
517
+ /**
518
+ * Set HTTP authentication parameters
519
+ *
520
+ * $type should be one of the supported types - see the self::AUTH_*
521
+ * constants.
522
+ *
523
+ * To enable authentication:
524
+ * <code>
525
+ * $this->setAuth('shahar', 'secret', Microsoft_Http_Client::AUTH_BASIC);
526
+ * </code>
527
+ *
528
+ * To disable authentication:
529
+ * <code>
530
+ * $this->setAuth(false);
531
+ * </code>
532
+ *
533
+ * @see http://www.faqs.org/rfcs/rfc2617.html
534
+ * @param string|false $user User name or false disable authentication
535
+ * @param string $password Password
536
+ * @param string $type Authentication type
537
+ * @return Microsoft_Http_Client
538
+ * @throws Microsoft_Http_Client_Exception
539
+ */
540
+ public function setAuth($user, $password = '', $type = self::AUTH_BASIC)
541
+ {
542
+ // If we got false or null, disable authentication
543
+ if ($user === false || $user === null) {
544
+ $this->auth = null;
545
+
546
+ // Clear the auth information in the uri instance as well
547
+ if ($this->uri instanceof Microsoft_Uri_Http) {
548
+ $this->getUri()->setUsername('');
549
+ $this->getUri()->setPassword('');
550
+ }
551
+ // Else, set up authentication
552
+ } else {
553
+ // Check we got a proper authentication type
554
+ if (! defined('self::AUTH_' . strtoupper($type))) {
555
+ /** @see Microsoft_Http_Client_Exception */
556
+ require_once 'Microsoft/Http/Client/Exception.php';
557
+ throw new Microsoft_Http_Client_Exception("Invalid or not supported authentication type: '$type'");
558
+ }
559
+
560
+ $this->auth = array(
561
+ 'user' => (string) $user,
562
+ 'password' => (string) $password,
563
+ 'type' => $type
564
+ );
565
+ }
566
+
567
+ return $this;
568
+ }
569
+
570
+ /**
571
+ * Set the HTTP client's cookie jar.
572
+ *
573
+ * A cookie jar is an object that holds and maintains cookies across HTTP requests
574
+ * and responses.
575
+ *
576
+ * @param Microsoft_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable
577
+ * @return Microsoft_Http_Client
578
+ * @throws Microsoft_Http_Client_Exception
579
+ */
580
+ public function setCookieJar($cookiejar = true)
581
+ {
582
+ if (! class_exists('Microsoft_Http_CookieJar')) {
583
+ require_once 'Microsoft/Http/CookieJar.php';
584
+ }
585
+
586
+ if ($cookiejar instanceof Microsoft_Http_CookieJar) {
587
+ $this->cookiejar = $cookiejar;
588
+ } elseif ($cookiejar === true) {
589
+ $this->cookiejar = new Microsoft_Http_CookieJar();
590
+ } elseif (! $cookiejar) {
591
+ $this->cookiejar = null;
592
+ } else {
593
+ /** @see Microsoft_Http_Client_Exception */
594
+ require_once 'Microsoft/Http/Client/Exception.php';
595
+ throw new Microsoft_Http_Client_Exception('Invalid parameter type passed as CookieJar');
596
+ }
597
+
598
+ return $this;
599
+ }
600
+
601
+ /**
602
+ * Return the current cookie jar or null if none.
603
+ *
604
+ * @return Microsoft_Http_CookieJar|null
605
+ */
606
+ public function getCookieJar()
607
+ {
608
+ return $this->cookiejar;
609
+ }
610
+
611
+ /**
612
+ * Add a cookie to the request. If the client has no Cookie Jar, the cookies
613
+ * will be added directly to the headers array as "Cookie" headers.
614
+ *
615
+ * @param Microsoft_Http_Cookie|string $cookie
616
+ * @param string|null $value If "cookie" is a string, this is the cookie value.
617
+ * @return Microsoft_Http_Client
618
+ * @throws Microsoft_Http_Client_Exception
619
+ */
620
+ public function setCookie($cookie, $value = null)
621
+ {
622
+ if (! class_exists('Microsoft_Http_Cookie')) {
623
+ require_once 'Microsoft/Http/Cookie.php';
624
+ }
625
+
626
+ if (is_array($cookie)) {
627
+ foreach ($cookie as $c => $v) {
628
+ if (is_string($c)) {
629
+ $this->setCookie($c, $v);
630
+ } else {
631
+ $this->setCookie($v);
632
+ }
633
+ }
634
+
635
+ return $this;
636
+ }
637
+
638
+ if ($value !== null) {
639
+ $value = urlencode($value);
640
+ }
641
+
642
+ if (isset($this->cookiejar)) {
643
+ if ($cookie instanceof Microsoft_Http_Cookie) {
644
+ $this->cookiejar->addCookie($cookie);
645
+ } elseif (is_string($cookie) && $value !== null) {
646
+ $cookie = Microsoft_Http_Cookie::fromString("{$cookie}={$value}", $this->uri);
647
+ $this->cookiejar->addCookie($cookie);
648
+ }
649
+ } else {
650
+ if ($cookie instanceof Microsoft_Http_Cookie) {
651
+ $name = $cookie->getName();
652
+ $value = $cookie->getValue();
653
+ $cookie = $name;
654
+ }
655
+
656
+ if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) {
657
+ /** @see Microsoft_Http_Client_Exception */
658
+ require_once 'Microsoft/Http/Client/Exception.php';
659
+ throw new Microsoft_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})");
660
+ }
661
+
662
+ $value = addslashes($value);
663
+
664
+ if (! isset($this->headers['cookie'])) {
665
+ $this->headers['cookie'] = array('Cookie', '');
666
+ }
667
+ $this->headers['cookie'][1] .= $cookie . '=' . $value . '; ';
668
+ }
669
+
670
+ return $this;
671
+ }
672
+
673
+ /**
674
+ * Set a file to upload (using a POST request)
675
+ *
676
+ * Can be used in two ways:
677
+ *
678
+ * 1. $data is null (default): $filename is treated as the name if a local file which
679
+ * will be read and sent. Will try to guess the content type using mime_content_type().
680
+ * 2. $data is set - $filename is sent as the file name, but $data is sent as the file
681
+ * contents and no file is read from the file system. In this case, you need to
682
+ * manually set the Content-Type ($ctype) or it will default to
683
+ * application/octet-stream.
684
+ *
685
+ * @param string $filename Name of file to upload, or name to save as
686
+ * @param string $formname Name of form element to send as
687
+ * @param string $data Data to send (if null, $filename is read and sent)
688
+ * @param string $ctype Content type to use (if $data is set and $ctype is
689
+ * null, will be application/octet-stream)
690
+ * @return Microsoft_Http_Client
691
+ * @throws Microsoft_Http_Client_Exception
692
+ */
693
+ public function setFileUpload($filename, $formname, $data = null, $ctype = null)
694
+ {
695
+ if ($data === null) {
696
+ if (($data = @file_get_contents($filename)) === false) {
697
+ /** @see Microsoft_Http_Client_Exception */
698
+ require_once 'Microsoft/Http/Client/Exception.php';
699
+ throw new Microsoft_Http_Client_Exception("Unable to read file '{$filename}' for upload");
700
+ }
701
+
702
+ if (! $ctype) {
703
+ $ctype = $this->_detectFileMimeType($filename);
704
+ }
705
+ }
706
+
707
+ // Force enctype to multipart/form-data
708
+ $this->setEncType(self::ENC_FORMDATA);
709
+
710
+ $this->files[] = array(
711
+ 'formname' => $formname,
712
+ 'filename' => basename($filename),
713
+ 'ctype' => $ctype,
714
+ 'data' => $data
715
+ );
716
+
717
+ return $this;
718
+ }
719
+
720
+ /**
721
+ * Set the encoding type for POST data
722
+ *
723
+ * @param string $enctype
724
+ * @return Microsoft_Http_Client
725
+ */
726
+ public function setEncType($enctype = self::ENC_URLENCODED)
727
+ {
728
+ $this->enctype = $enctype;
729
+
730
+ return $this;
731
+ }
732
+
733
+ /**
734
+ * Set the raw (already encoded) POST data.
735
+ *
736
+ * This function is here for two reasons:
737
+ * 1. For advanced user who would like to set their own data, already encoded
738
+ * 2. For backwards compatibilty: If someone uses the old post($data) method.
739
+ * this method will be used to set the encoded data.
740
+ *
741
+ * $data can also be stream (such as file) from which the data will be read.
742
+ *
743
+ * @param string|resource $data
744
+ * @param string $enctype
745
+ * @return Microsoft_Http_Client
746
+ */
747
+ public function setRawData($data, $enctype = null)
748
+ {
749
+ $this->raw_post_data = $data;
750
+ $this->setEncType($enctype);
751
+ if (is_resource($data)) {
752
+ // We've got stream data
753
+ $stat = @fstat($data);
754
+ if($stat) {
755
+ $this->setHeaders(self::CONTENT_LENGTH, $stat['size']);
756
+ }
757
+ }
758
+ return $this;
759
+ }
760
+
761
+ /**
762
+ * Clear all GET and POST parameters
763
+ *
764
+ * Should be used to reset the request parameters if the client is
765
+ * used for several concurrent requests.
766
+ *
767
+ * clearAll parameter controls if we clean just parameters or also
768
+ * headers and last_*
769
+ *
770
+ * @param bool $clearAll Should all data be cleared?
771
+ * @return Microsoft_Http_Client
772
+ */
773
+ public function resetParameters($clearAll = false)
774
+ {
775
+ // Reset parameter data
776
+ $this->paramsGet = array();
777
+ $this->paramsPost = array();
778
+ $this->files = array();
779
+ $this->raw_post_data = null;
780
+
781
+ if($clearAll) {
782
+ $this->headers = array();
783
+ $this->last_request = null;
784
+ $this->last_response = null;
785
+ } else {
786
+ // Clear outdated headers
787
+ if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) {
788
+ unset($this->headers[strtolower(self::CONTENT_TYPE)]);
789
+ }
790
+ if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) {
791
+ unset($this->headers[strtolower(self::CONTENT_LENGTH)]);
792
+ }
793
+ }
794
+
795
+ return $this;
796
+ }
797
+
798
+ /**
799
+ * Get the last HTTP request as string
800
+ *
801
+ * @return string
802
+ */
803
+ public function getLastRequest()
804
+ {
805
+ return $this->last_request;
806
+ }
807
+
808
+ /**
809
+ * Get the last HTTP response received by this client
810
+ *
811
+ * If $config['storeresponse'] is set to false, or no response was
812
+ * stored yet, will return null
813
+ *
814
+ * @return Microsoft_Http_Response or null if none
815
+ */
816
+ public function getLastResponse()
817
+ {
818
+ return $this->last_response;
819
+ }
820
+
821
+ /**
822
+ * Load the connection adapter
823
+ *
824
+ * While this method is not called more than one for a client, it is
825
+ * seperated from ->request() to preserve logic and readability
826
+ *
827
+ * @param Microsoft_Http_Client_Adapter_Interface|string $adapter
828
+ * @return null
829
+ * @throws Microsoft_Http_Client_Exception
830
+ */
831
+ public function setAdapter($adapter)
832
+ {
833
+ if (is_string($adapter)) {
834
+ if (!class_exists($adapter)) {
835
+ @require_once( str_replace('_', '/', $adapter) . '.php' );
836
+ }
837
+
838
+ $adapter = new $adapter;
839
+ }
840
+
841
+ if (! $adapter instanceof Microsoft_Http_Client_Adapter_Interface) {
842
+ /** @see Microsoft_Http_Client_Exception */
843
+ require_once 'Microsoft/Http/Client/Exception.php';
844
+ throw new Microsoft_Http_Client_Exception('Passed adapter is not a HTTP connection adapter');
845
+ }
846
+
847
+ $this->adapter = $adapter;
848
+ $config = $this->config;
849
+ unset($config['adapter']);
850
+ $this->adapter->setConfig($config);
851
+ }
852
+
853
+ /**
854
+ * Load the connection adapter
855
+ *
856
+ * @return Microsoft_Http_Client_Adapter_Interface $adapter
857
+ */
858
+ public function getAdapter()
859
+ {
860
+ return $this->adapter;
861
+ }
862
+
863
+ /**
864
+ * Set streaming for received data
865
+ *
866
+ * @param string|boolean $streamfile Stream file, true for temp file, false/null for no streaming
867
+ * @return Microsoft_Http_Client
868
+ */
869
+ public function setStream($streamfile = true)
870
+ {
871
+ $this->setConfig(array("output_stream" => $streamfile));
872
+ return $this;
873
+ }
874
+
875
+ /**
876
+ * Get status of streaming for received data
877
+ * @return boolean|string
878
+ */
879
+ public function getStream()
880
+ {
881
+ return $this->config["output_stream"];
882
+ }
883
+
884
+ /**
885
+ * Create temporary stream
886
+ *
887
+ * @return resource
888
+ */
889
+ protected function _openTempStream()
890
+ {
891
+ $this->_stream_name = $this->config['output_stream'];
892
+ if(!is_string($this->_stream_name)) {
893
+ // If name is not given, create temp name
894
+ $this->_stream_name = tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(),
895
+ 'Microsoft_Http_Client');
896
+ }
897
+
898
+ $fp = fopen($this->_stream_name, "w+b");
899
+ if(!$fp) {
900
+ $this->close();
901
+ require_once 'Microsoft/Http/Client/Exception.php';
902
+ throw new Microsoft_Http_Client_Exception("Could not open temp file $name");
903
+
904
+ }
905
+ return $fp;
906
+ }
907
+
908
+ /**
909
+ * Send the HTTP request and return an HTTP response object
910
+ *
911
+ * @param string $method
912
+ * @return Microsoft_Http_Response
913
+ * @throws Microsoft_Http_Client_Exception
914
+ */
915
+ public function request($method = null)
916
+ {
917
+ if (! $this->uri instanceof Microsoft_Uri_Http) {
918
+ /** @see Microsoft_Http_Client_Exception */
919
+ require_once 'Microsoft/Http/Client/Exception.php';
920
+ throw new Microsoft_Http_Client_Exception('No valid URI has been passed to the client');
921
+ }
922
+
923
+ if ($method) {
924
+ $this->setMethod($method);
925
+ }
926
+ $this->redirectCounter = 0;
927
+ $response = null;
928
+
929
+ // Make sure the adapter is loaded
930
+ if ($this->adapter == null) {
931
+ $this->setAdapter($this->config['adapter']);
932
+ }
933
+
934
+ // Send the first request. If redirected, continue.
935
+ do {
936
+ // Clone the URI and add the additional GET parameters to it
937
+ $uri = clone $this->uri;
938
+ if (! empty($this->paramsGet)) {
939
+ $query = $uri->getQuery();
940
+ if (! empty($query)) {
941
+ $query .= '&';
942
+ }
943
+ $query .= http_build_query($this->paramsGet, null, '&');
944
+
945
+ $uri->setQuery($query);
946
+ }
947
+
948
+ $body = $this->_prepareBody();
949
+ $headers = $this->_prepareHeaders();
950
+
951
+ // check that adapter supports streaming before using it
952
+ if(is_resource($body) && !($this->adapter instanceof Microsoft_Http_Client_Adapter_Stream)) {
953
+ /** @see Microsoft_Http_Client_Exception */
954
+ require_once 'Microsoft/Http/Client/Exception.php';
955
+ throw new Microsoft_Http_Client_Exception('Adapter does not support streaming');
956
+ }
957
+
958
+ // Open the connection, send the request and read the response
959
+ $this->adapter->connect($uri->getHost(), $uri->getPort(),
960
+ ($uri->getScheme() == 'https' ? true : false));
961
+
962
+ if($this->config['output_stream']) {
963
+ if($this->adapter instanceof Microsoft_Http_Client_Adapter_Stream) {
964
+ $stream = $this->_openTempStream();
965
+ $this->adapter->setOutputStream($stream);
966
+ } else {
967
+ /** @see Microsoft_Http_Client_Exception */
968
+ require_once 'Microsoft/Http/Client/Exception.php';
969
+ throw new Microsoft_Http_Client_Exception('Adapter does not support streaming');
970
+ }
971
+ }
972
+
973
+ $this->last_request = $this->adapter->write($this->method,
974
+ $uri, $this->config['httpversion'], $headers, $body);
975
+
976
+ $response = $this->adapter->read();
977
+ if (! $response) {
978
+ /** @see Microsoft_Http_Client_Exception */
979
+ require_once 'Microsoft/Http/Client/Exception.php';
980
+ throw new Microsoft_Http_Client_Exception('Unable to read response, or response is empty');
981
+ }
982
+
983
+ if($this->config['output_stream']) {
984
+ rewind($stream);
985
+ // cleanup the adapter
986
+ $this->adapter->setOutputStream(null);
987
+ $response = Microsoft_Http_Response_Stream::fromStream($response, $stream);
988
+ $response->setStreamName($this->_stream_name);
989
+ if(!is_string($this->config['output_stream'])) {
990
+ // we used temp name, will need to clean up
991
+ $response->setCleanup(true);
992
+ }
993
+ } else {
994
+ $response = Microsoft_Http_Response::fromString($response);
995
+ }
996
+
997
+ if ($this->config['storeresponse']) {
998
+ $this->last_response = $response;
999
+ }
1000
+
1001
+ // Load cookies into cookie jar
1002
+ if (isset($this->cookiejar)) {
1003
+ $this->cookiejar->addCookiesFromResponse($response, $uri);
1004
+ }
1005
+
1006
+ // If we got redirected, look for the Location header
1007
+ if ($response->isRedirect() && ($location = $response->getHeader('location'))) {
1008
+
1009
+ // Check whether we send the exact same request again, or drop the parameters
1010
+ // and send a GET request
1011
+ if ($response->getStatus() == 303 ||
1012
+ ((! $this->config['strictredirects']) && ($response->getStatus() == 302 ||
1013
+ $response->getStatus() == 301))) {
1014
+
1015
+ $this->resetParameters();
1016
+ $this->setMethod(self::GET);
1017
+ }
1018
+
1019
+ // If we got a well formed absolute URI
1020
+ if (Microsoft_Uri_Http::check($location)) {
1021
+ $this->setHeaders('host', null);
1022
+ $this->setUri($location);
1023
+
1024
+ } else {
1025
+
1026
+ // Split into path and query and set the query
1027
+ if (strpos($location, '?') !== false) {
1028
+ list($location, $query) = explode('?', $location, 2);
1029
+ } else {
1030
+ $query = '';
1031
+ }
1032
+ $this->uri->setQuery($query);
1033
+
1034
+ // Else, if we got just an absolute path, set it
1035
+ if(strpos($location, '/') === 0) {
1036
+ $this->uri->setPath($location);
1037
+
1038
+ // Else, assume we have a relative path
1039
+ } else {
1040
+ // Get the current path directory, removing any trailing slashes
1041
+ $path = $this->uri->getPath();
1042
+ $path = rtrim(substr($path, 0, strrpos($path, '/')), "/");
1043
+ $this->uri->setPath($path . '/' . $location);
1044
+ }
1045
+ }
1046
+ ++$this->redirectCounter;
1047
+
1048
+ } else {
1049
+ // If we didn't get any location, stop redirecting
1050
+ break;
1051
+ }
1052
+
1053
+ } while ($this->redirectCounter < $this->config['maxredirects']);
1054
+
1055
+ return $response;
1056
+ }
1057
+
1058
+ /**
1059
+ * Prepare the request headers
1060
+ *
1061
+ * @return array
1062
+ */
1063
+ protected function _prepareHeaders()
1064
+ {
1065
+ $headers = array();
1066
+
1067
+ // Set the host header
1068
+ if (! isset($this->headers['host'])) {
1069
+ $host = $this->uri->getHost();
1070
+
1071
+ // If the port is not default, add it
1072
+ if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) ||
1073
+ ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) {
1074
+ $host .= ':' . $this->uri->getPort();
1075
+ }
1076
+
1077
+ $headers[] = "Host: {$host}";
1078
+ }
1079
+
1080
+ // Set the connection header
1081
+ if (! isset($this->headers['connection'])) {
1082
+ if (! $this->config['keepalive']) {
1083
+ $headers[] = "Connection: close";
1084
+ }
1085
+ }
1086
+
1087
+ // Set the Accept-encoding header if not set - depending on whether
1088
+ // zlib is available or not.
1089
+ if (! isset($this->headers['accept-encoding'])) {
1090
+ if (function_exists('gzinflate')) {
1091
+ $headers[] = 'Accept-encoding: gzip, deflate';
1092
+ } else {
1093
+ $headers[] = 'Accept-encoding: identity';
1094
+ }
1095
+ }
1096
+
1097
+ // Set the Content-Type header
1098
+ if ($this->method == self::POST &&
1099
+ (! isset($this->headers[strtolower(self::CONTENT_TYPE)]) && isset($this->enctype))) {
1100
+
1101
+ $headers[] = self::CONTENT_TYPE . ': ' . $this->enctype;
1102
+ }
1103
+
1104
+ // Set the user agent header
1105
+ if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) {
1106
+ $headers[] = "User-Agent: {$this->config['useragent']}";
1107
+ }
1108
+
1109
+ // Set HTTP authentication if needed
1110
+ if (is_array($this->auth)) {
1111
+ $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']);
1112
+ $headers[] = "Authorization: {$auth}";
1113
+ }
1114
+
1115
+ // Load cookies from cookie jar
1116
+ if (isset($this->cookiejar)) {
1117
+ $cookstr = $this->cookiejar->getMatchingCookies($this->uri,
1118
+ true, Microsoft_Http_CookieJar::COOKIE_STRING_CONCAT);
1119
+
1120
+ if ($cookstr) {
1121
+ $headers[] = "Cookie: {$cookstr}";
1122
+ }
1123
+ }
1124
+
1125
+ // Add all other user defined headers
1126
+ foreach ($this->headers as $header) {
1127
+ list($name, $value) = $header;
1128
+ if (is_array($value)) {
1129
+ $value = implode(', ', $value);
1130
+ }
1131
+
1132
+ $headers[] = "$name: $value";
1133
+ }
1134
+
1135
+ return $headers;
1136
+ }
1137
+
1138
+ /**
1139
+ * Prepare the request body (for POST and PUT requests)
1140
+ *
1141
+ * @return string
1142
+ * @throws Microsoft_Http_Client_Exception
1143
+ */
1144
+ protected function _prepareBody()
1145
+ {
1146
+ // According to RFC2616, a TRACE request should not have a body.
1147
+ if ($this->method == self::TRACE) {
1148
+ return '';
1149
+ }
1150
+
1151
+ if (isset($this->raw_post_data) && is_resource($this->raw_post_data)) {
1152
+ return $this->raw_post_data;
1153
+ }
1154
+ // If mbstring overloads substr and strlen functions, we have to
1155
+ // override it's internal encoding
1156
+ if (function_exists('mb_internal_encoding') &&
1157
+ ((int) ini_get('mbstring.func_overload')) & 2) {
1158
+
1159
+ $mbIntEnc = mb_internal_encoding();
1160
+ mb_internal_encoding('ASCII');
1161
+ }
1162
+
1163
+ // If we have raw_post_data set, just use it as the body.
1164
+ if (isset($this->raw_post_data)) {
1165
+ $this->setHeaders(self::CONTENT_LENGTH, strlen($this->raw_post_data));
1166
+ if (isset($mbIntEnc)) {
1167
+ mb_internal_encoding($mbIntEnc);
1168
+ }
1169
+
1170
+ return $this->raw_post_data;
1171
+ }
1172
+
1173
+ $body = '';
1174
+
1175
+ // If we have files to upload, force enctype to multipart/form-data
1176
+ if (count ($this->files) > 0) {
1177
+ $this->setEncType(self::ENC_FORMDATA);
1178
+ }
1179
+
1180
+ // If we have POST parameters or files, encode and add them to the body
1181
+ if (count($this->paramsPost) > 0 || count($this->files) > 0) {
1182
+ switch($this->enctype) {
1183
+ case self::ENC_FORMDATA:
1184
+ // Encode body as multipart/form-data
1185
+ $boundary = '---ZENDHTTPCLIENT-' . md5(microtime());
1186
+ $this->setHeaders(self::CONTENT_TYPE, self::ENC_FORMDATA . "; boundary={$boundary}");
1187
+
1188
+ // Get POST parameters and encode them
1189
+ $params = self::_flattenParametersArray($this->paramsPost);
1190
+ foreach ($params as $pp) {
1191
+ $body .= self::encodeFormData($boundary, $pp[0], $pp[1]);
1192
+ }
1193
+
1194
+ // Encode files
1195
+ foreach ($this->files as $file) {
1196
+ $fhead = array(self::CONTENT_TYPE => $file['ctype']);
1197
+ $body .= self::encodeFormData($boundary, $file['formname'], $file['data'], $file['filename'], $fhead);
1198
+ }
1199
+
1200
+ $body .= "--{$boundary}--\r\n";
1201
+ break;
1202
+
1203
+ case self::ENC_URLENCODED:
1204
+ // Encode body as application/x-www-form-urlencoded
1205
+ $this->setHeaders(self::CONTENT_TYPE, self::ENC_URLENCODED);
1206
+ $body = http_build_query($this->paramsPost, '', '&');
1207
+ break;
1208
+
1209
+ default:
1210
+ if (isset($mbIntEnc)) {
1211
+ mb_internal_encoding($mbIntEnc);
1212
+ }
1213
+
1214
+ /** @see Microsoft_Http_Client_Exception */
1215
+ require_once 'Microsoft/Http/Client/Exception.php';
1216
+ throw new Microsoft_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." .
1217
+ " Please use Microsoft_Http_Client::setRawData to send this kind of content.");
1218
+ break;
1219
+ }
1220
+ }
1221
+
1222
+ // Set the Content-Length if we have a body or if request is POST/PUT
1223
+ if ($body || $this->method == self::POST || $this->method == self::PUT) {
1224
+ $this->setHeaders(self::CONTENT_LENGTH, strlen($body));
1225
+ }
1226
+
1227
+ if (isset($mbIntEnc)) {
1228
+ mb_internal_encoding($mbIntEnc);
1229
+ }
1230
+
1231
+ return $body;
1232
+ }
1233
+
1234
+ /**
1235
+ * Helper method that gets a possibly multi-level parameters array (get or
1236
+ * post) and flattens it.
1237
+ *
1238
+ * The method returns an array of (key, value) pairs (because keys are not
1239
+ * necessarily unique. If one of the parameters in as array, it will also
1240
+ * add a [] suffix to the key.
1241
+ *
1242
+ * This method is deprecated since Zend Framework 1.9 in favour of
1243
+ * self::_flattenParametersArray() and will be dropped in 2.0
1244
+ *
1245
+ * @deprecated since 1.9
1246
+ *
1247
+ * @param array $parray The parameters array
1248
+ * @param bool $urlencode Whether to urlencode the name and value
1249
+ * @return array
1250
+ */
1251
+ protected function _getParametersRecursive($parray, $urlencode = false)
1252
+ {
1253
+ // Issue a deprecated notice
1254
+ trigger_error("The " . __METHOD__ . " method is deprecated and will be dropped in 2.0.",
1255
+ E_USER_NOTICE);
1256
+
1257
+ if (! is_array($parray)) {
1258
+ return $parray;
1259
+ }
1260
+ $parameters = array();
1261
+
1262
+ foreach ($parray as $name => $value) {
1263
+ if ($urlencode) {
1264
+ $name = urlencode($name);
1265
+ }
1266
+
1267
+ // If $value is an array, iterate over it
1268
+ if (is_array($value)) {
1269
+ $name .= ($urlencode ? '%5B%5D' : '[]');
1270
+ foreach ($value as $subval) {
1271
+ if ($urlencode) {
1272
+ $subval = urlencode($subval);
1273
+ }
1274
+ $parameters[] = array($name, $subval);
1275
+ }
1276
+ } else {
1277
+ if ($urlencode) {
1278
+ $value = urlencode($value);
1279
+ }
1280
+ $parameters[] = array($name, $value);
1281
+ }
1282
+ }
1283
+
1284
+ return $parameters;
1285
+ }
1286
+
1287
+ /**
1288
+ * Attempt to detect the MIME type of a file using available extensions
1289
+ *
1290
+ * This method will try to detect the MIME type of a file. If the fileinfo
1291
+ * extension is available, it will be used. If not, the mime_magic
1292
+ * extension which is deprected but is still available in many PHP setups
1293
+ * will be tried.
1294
+ *
1295
+ * If neither extension is available, the default application/octet-stream
1296
+ * MIME type will be returned
1297
+ *
1298
+ * @param string $file File path
1299
+ * @return string MIME type
1300
+ */
1301
+ protected function _detectFileMimeType($file)
1302
+ {
1303
+ $type = null;
1304
+
1305
+ // First try with fileinfo functions
1306
+ if (function_exists('finfo_open')) {
1307
+ if (self::$_fileInfoDb === null) {
1308
+ self::$_fileInfoDb = @finfo_open(FILEINFO_MIME);
1309
+ }
1310
+
1311
+ if (self::$_fileInfoDb) {
1312
+ $type = finfo_file(self::$_fileInfoDb, $file);
1313
+ }
1314
+
1315
+ } elseif (function_exists('mime_content_type')) {
1316
+ $type = mime_content_type($file);
1317
+ }
1318
+
1319
+ // Fallback to the default application/octet-stream
1320
+ if (! $type) {
1321
+ $type = 'application/octet-stream';
1322
+ }
1323
+
1324
+ return $type;
1325
+ }
1326
+
1327
+ /**
1328
+ * Encode data to a multipart/form-data part suitable for a POST request.
1329
+ *
1330
+ * @param string $boundary
1331
+ * @param string $name
1332
+ * @param mixed $value
1333
+ * @param string $filename
1334
+ * @param array $headers Associative array of optional headers @example ("Content-Transfer-Encoding" => "binary")
1335
+ * @return string
1336
+ */
1337
+ public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) {
1338
+ $ret = "--{$boundary}\r\n" .
1339
+ 'Content-Disposition: form-data; name="' . $name .'"';
1340
+
1341
+ if ($filename) {
1342
+ $ret .= '; filename="' . $filename . '"';
1343
+ }
1344
+ $ret .= "\r\n";
1345
+
1346
+ foreach ($headers as $hname => $hvalue) {
1347
+ $ret .= "{$hname}: {$hvalue}\r\n";
1348
+ }
1349
+ $ret .= "\r\n";
1350
+
1351
+ $ret .= "{$value}\r\n";
1352
+
1353
+ return $ret;
1354
+ }
1355
+
1356
+ /**
1357
+ * Create a HTTP authentication "Authorization:" header according to the
1358
+ * specified user, password and authentication method.
1359
+ *
1360
+ * @see http://www.faqs.org/rfcs/rfc2617.html
1361
+ * @param string $user
1362
+ * @param string $password
1363
+ * @param string $type
1364
+ * @return string
1365
+ * @throws Microsoft_Http_Client_Exception
1366
+ */
1367
+ public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC)
1368
+ {
1369
+ $authHeader = null;
1370
+
1371
+ switch ($type) {
1372
+ case self::AUTH_BASIC:
1373
+ // In basic authentication, the user name cannot contain ":"
1374
+ if (strpos($user, ':') !== false) {
1375
+ /** @see Microsoft_Http_Client_Exception */
1376
+ require_once 'Microsoft/Http/Client/Exception.php';
1377
+ throw new Microsoft_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication");
1378
+ }
1379
+
1380
+ $authHeader = 'Basic ' . base64_encode($user . ':' . $password);
1381
+ break;
1382
+
1383
+ //case self::AUTH_DIGEST:
1384
+ /**
1385
+ * @todo Implement digest authentication
1386
+ */
1387
+ // break;
1388
+
1389
+ default:
1390
+ /** @see Microsoft_Http_Client_Exception */
1391
+ require_once 'Microsoft/Http/Client/Exception.php';
1392
+ throw new Microsoft_Http_Client_Exception("Not a supported HTTP authentication type: '$type'");
1393
+ }
1394
+
1395
+ return $authHeader;
1396
+ }
1397
+
1398
+ /**
1399
+ * Convert an array of parameters into a flat array of (key, value) pairs
1400
+ *
1401
+ * Will flatten a potentially multi-dimentional array of parameters (such
1402
+ * as POST parameters) into a flat array of (key, value) paris. In case
1403
+ * of multi-dimentional arrays, square brackets ([]) will be added to the
1404
+ * key to indicate an array.
1405
+ *
1406
+ * @since 1.9
1407
+ *
1408
+ * @param array $parray
1409
+ * @param string $prefix
1410
+ * @return array
1411
+ */
1412
+ static protected function _flattenParametersArray($parray, $prefix = null)
1413
+ {
1414
+ if (! is_array($parray)) {
1415
+ return $parray;
1416
+ }
1417
+
1418
+ $parameters = array();
1419
+
1420
+ foreach($parray as $name => $value) {
1421
+
1422
+ // Calculate array key
1423
+ if ($prefix) {
1424
+ if (is_int($name)) {
1425
+ $key = $prefix . '[]';
1426
+ } else {
1427
+ $key = $prefix . "[$name]";
1428
+ }
1429
+ } else {
1430
+ $key = $name;
1431
+ }
1432
+
1433
+ if (is_array($value)) {
1434
+ $parameters = array_merge($parameters, self::_flattenParametersArray($value, $key));
1435
+
1436
+ } else {
1437
+ $parameters[] = array($key, $value);
1438
+ }
1439
+ }
1440
+
1441
+ return $parameters;
1442
+ }
1443
+
1444
+ }
lib/Microsoft/Http/Client/Adapter/Curl.php ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Curl.php 19238 2009-11-25 17:13:38Z bate $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+
29
+ /**
30
+ * @see Microsoft_Http_Client_Adapter_Interface
31
+ */
32
+ require_once 'Microsoft/Http/Client/Adapter/Interface.php';
33
+ /**
34
+ * @see Microsoft_Http_Client_Adapter_Stream
35
+ */
36
+ require_once 'Microsoft/Http/Client/Adapter/Stream.php';
37
+
38
+ /**
39
+ * An adapter class for Microsoft_Http_Client based on the curl extension.
40
+ * Curl requires libcurl. See for full requirements the PHP manual: http://php.net/curl
41
+ *
42
+ * @category Microsoft
43
+ * @package Microsoft_Http
44
+ * @subpackage Client_Adapter
45
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
46
+ * @license http://framework.zend.com/license/new-bsd New BSD License
47
+ */
48
+ class Microsoft_Http_Client_Adapter_Curl implements Microsoft_Http_Client_Adapter_Interface, Microsoft_Http_Client_Adapter_Stream
49
+ {
50
+ /**
51
+ * Parameters array
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_config = array();
56
+
57
+ /**
58
+ * What host/port are we connected to?
59
+ *
60
+ * @var array
61
+ */
62
+ protected $_connected_to = array(null, null);
63
+
64
+ /**
65
+ * The curl session handle
66
+ *
67
+ * @var resource|null
68
+ */
69
+ protected $_curl = null;
70
+
71
+ /**
72
+ * List of cURL options that should never be overwritten
73
+ *
74
+ * @var array
75
+ */
76
+ protected $_invalidOverwritableCurlOptions = array(
77
+ CURLOPT_HTTPGET,
78
+ CURLOPT_POST,
79
+ CURLOPT_PUT,
80
+ CURLOPT_CUSTOMREQUEST,
81
+ CURLOPT_HEADER,
82
+ CURLOPT_RETURNTRANSFER,
83
+ CURLOPT_HTTPHEADER,
84
+ CURLOPT_POSTFIELDS,
85
+ CURLOPT_INFILE,
86
+ CURLOPT_INFILESIZE,
87
+ CURLOPT_PORT,
88
+ CURLOPT_MAXREDIRS,
89
+ CURLOPT_CONNECTTIMEOUT,
90
+ CURL_HTTP_VERSION_1_1,
91
+ CURL_HTTP_VERSION_1_0,
92
+ );
93
+
94
+ /**
95
+ * Response gotten from server
96
+ *
97
+ * @var string
98
+ */
99
+ protected $_response = null;
100
+
101
+ /**
102
+ * Stream for storing output
103
+ *
104
+ * @var resource
105
+ */
106
+ protected $out_stream;
107
+
108
+ /**
109
+ * Adapter constructor
110
+ *
111
+ * Config is set using setConfig()
112
+ *
113
+ * @return void
114
+ * @throws Microsoft_Http_Client_Adapter_Exception
115
+ */
116
+ public function __construct()
117
+ {
118
+ if (!extension_loaded('curl')) {
119
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
120
+ throw new Microsoft_Http_Client_Adapter_Exception('cURL extension has to be loaded to use this Microsoft_Http_Client adapter.');
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Set the configuration array for the adapter
126
+ *
127
+ * @throws Microsoft_Http_Client_Adapter_Exception
128
+ * @param array $config
129
+ * @return Microsoft_Http_Client_Adapter_Curl
130
+ */
131
+ public function setConfig($config = array())
132
+ {
133
+ if (! is_array($config)) {
134
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
135
+ throw new Microsoft_Http_Client_Adapter_Exception(
136
+ 'Array expected, got ' . gettype($config)
137
+ );
138
+ }
139
+
140
+ if(isset($config['proxy_user']) && isset($config['proxy_pass'])) {
141
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $config['proxy_user'].":".$config['proxy_pass']);
142
+ unset($config['proxy_user'], $config['proxy_pass']);
143
+ }
144
+
145
+ foreach ($config as $k => $v) {
146
+ $option = strtolower($k);
147
+ switch($option) {
148
+ case 'proxy_host':
149
+ $this->setCurlOption(CURLOPT_PROXY, $v);
150
+ break;
151
+ case 'proxy_port':
152
+ $this->setCurlOption(CURLOPT_PROXYPORT, $v);
153
+ break;
154
+ default:
155
+ $this->_config[$option] = $v;
156
+ break;
157
+ }
158
+ }
159
+
160
+ return $this;
161
+ }
162
+
163
+ /**
164
+ * Retrieve the array of all configuration options
165
+ *
166
+ * @return array
167
+ */
168
+ public function getConfig()
169
+ {
170
+ return $this->_config;
171
+ }
172
+
173
+ /**
174
+ * Direct setter for cURL adapter related options.
175
+ *
176
+ * @param string|int $option
177
+ * @param mixed $value
178
+ * @return Microsoft_Http_Adapter_Curl
179
+ */
180
+ public function setCurlOption($option, $value)
181
+ {
182
+ if (!isset($this->_config['curloptions'])) {
183
+ $this->_config['curloptions'] = array();
184
+ }
185
+ $this->_config['curloptions'][$option] = $value;
186
+ return $this;
187
+ }
188
+
189
+ /**
190
+ * Initialize curl
191
+ *
192
+ * @param string $host
193
+ * @param int $port
194
+ * @param boolean $secure
195
+ * @return void
196
+ * @throws Microsoft_Http_Client_Adapter_Exception if unable to connect
197
+ */
198
+ public function connect($host, $port = 80, $secure = false)
199
+ {
200
+ // If we're already connected, disconnect first
201
+ if ($this->_curl) {
202
+ $this->close();
203
+ }
204
+
205
+ // If we are connected to a different server or port, disconnect first
206
+ if ($this->_curl
207
+ && is_array($this->_connected_to)
208
+ && ($this->_connected_to[0] != $host
209
+ || $this->_connected_to[1] != $port)
210
+ ) {
211
+ $this->close();
212
+ }
213
+
214
+ // Do the actual connection
215
+ $this->_curl = curl_init();
216
+ if ($port != 80) {
217
+ curl_setopt($this->_curl, CURLOPT_PORT, intval($port));
218
+ }
219
+
220
+ // Set timeout
221
+ curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']);
222
+
223
+ // Set Max redirects
224
+ curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']);
225
+
226
+ if (!$this->_curl) {
227
+ $this->close();
228
+
229
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
230
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port);
231
+ }
232
+
233
+ if ($secure !== false) {
234
+ // Behave the same like Microsoft_Http_Adapter_Socket on SSL options.
235
+ if (isset($this->_config['sslcert'])) {
236
+ curl_setopt($this->_curl, CURLOPT_SSLCERT, $this->_config['sslcert']);
237
+ }
238
+ if (isset($this->_config['sslpassphrase'])) {
239
+ curl_setopt($this->_curl, CURLOPT_SSLCERTPASSWD, $this->_config['sslpassphrase']);
240
+ }
241
+ }
242
+
243
+ // Update connected_to
244
+ $this->_connected_to = array($host, $port);
245
+ }
246
+
247
+ /**
248
+ * Send request to the remote server
249
+ *
250
+ * @param string $method
251
+ * @param Microsoft_Uri_Http $uri
252
+ * @param float $http_ver
253
+ * @param array $headers
254
+ * @param string $body
255
+ * @return string $request
256
+ * @throws Microsoft_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option
257
+ */
258
+ public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '')
259
+ {
260
+ // Make sure we're properly connected
261
+ if (!$this->_curl) {
262
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
263
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are not connected");
264
+ }
265
+
266
+ if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) {
267
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
268
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host");
269
+ }
270
+
271
+ // set URL
272
+ curl_setopt($this->_curl, CURLOPT_URL, $uri->__toString());
273
+
274
+ // ensure correct curl call
275
+ $curlValue = true;
276
+ switch ($method) {
277
+ case Microsoft_Http_Client::GET:
278
+ $curlMethod = CURLOPT_HTTPGET;
279
+ break;
280
+
281
+ case Microsoft_Http_Client::POST:
282
+ $curlMethod = CURLOPT_POST;
283
+ break;
284
+
285
+ case Microsoft_Http_Client::PUT:
286
+ // There are two different types of PUT request, either a Raw Data string has been set
287
+ // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used.
288
+ if(is_resource($body)) {
289
+ $this->_config['curloptions'][CURLOPT_INFILE] = $body;
290
+ }
291
+ if (isset($this->_config['curloptions'][CURLOPT_INFILE])) {
292
+ // Now we will probably already have Content-Length set, so that we have to delete it
293
+ // from $headers at this point:
294
+ foreach ($headers AS $k => $header) {
295
+ if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) {
296
+ if(is_resource($body)) {
297
+ $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1];
298
+ }
299
+ unset($headers[$k]);
300
+ }
301
+ }
302
+
303
+ if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) {
304
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
305
+ throw new Microsoft_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE.");
306
+ }
307
+
308
+ if(is_resource($body)) {
309
+ $body = '';
310
+ }
311
+
312
+ $curlMethod = CURLOPT_PUT;
313
+ } else {
314
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
315
+ $curlValue = "PUT";
316
+ }
317
+ break;
318
+
319
+ case Microsoft_Http_Client::DELETE:
320
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
321
+ $curlValue = "DELETE";
322
+ break;
323
+
324
+ case Microsoft_Http_Client::OPTIONS:
325
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
326
+ $curlValue = "OPTIONS";
327
+ break;
328
+
329
+ case Microsoft_Http_Client::TRACE:
330
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
331
+ $curlValue = "TRACE";
332
+ break;
333
+
334
+ default:
335
+ // For now, through an exception for unsupported request methods
336
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
337
+ throw new Microsoft_Http_Client_Adapter_Exception("Method currently not supported");
338
+ }
339
+
340
+ if(is_resource($body) && $curlMethod != CURLOPT_PUT) {
341
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
342
+ throw new Microsoft_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT");
343
+ }
344
+
345
+ // get http version to use
346
+ $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
347
+
348
+ // mark as HTTP request and set HTTP method
349
+ curl_setopt($this->_curl, $curlHttp, true);
350
+ curl_setopt($this->_curl, $curlMethod, $curlValue);
351
+
352
+ if($this->out_stream) {
353
+ // headers will be read into the response
354
+ curl_setopt($this->_curl, CURLOPT_HEADER, false);
355
+ curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader"));
356
+ // and data will be written into the file
357
+ curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream);
358
+ } else {
359
+ // ensure headers are also returned
360
+ curl_setopt($this->_curl, CURLOPT_HEADER, true);
361
+
362
+ // ensure actual response is returned
363
+ curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true);
364
+ }
365
+
366
+ // set additional headers
367
+ $headers['Accept'] = '';
368
+ curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $headers);
369
+
370
+ /**
371
+ * Make sure POSTFIELDS is set after $curlMethod is set:
372
+ * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161
373
+ */
374
+ if ($method == Microsoft_Http_Client::POST) {
375
+ curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body);
376
+ } elseif ($curlMethod == CURLOPT_PUT) {
377
+ // this covers a PUT by file-handle:
378
+ // Make the setting of this options explicit (rather than setting it through the loop following a bit lower)
379
+ // to group common functionality together.
380
+ curl_setopt($this->_curl, CURLOPT_INFILE, $this->_config['curloptions'][CURLOPT_INFILE]);
381
+ curl_setopt($this->_curl, CURLOPT_INFILESIZE, $this->_config['curloptions'][CURLOPT_INFILESIZE]);
382
+ unset($this->_config['curloptions'][CURLOPT_INFILE]);
383
+ unset($this->_config['curloptions'][CURLOPT_INFILESIZE]);
384
+ } elseif ($method == Microsoft_Http_Client::PUT) {
385
+ // This is a PUT by a setRawData string, not by file-handle
386
+ curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body);
387
+ }
388
+
389
+ // set additional curl options
390
+ if (isset($this->_config['curloptions'])) {
391
+ foreach ((array)$this->_config['curloptions'] as $k => $v) {
392
+ if (!in_array($k, $this->_invalidOverwritableCurlOptions)) {
393
+ if (@curl_setopt($this->_curl, $k, $v) == false) {
394
+ require_once 'Microsoft/Http/Client/Exception.php';
395
+ throw new Microsoft_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k));
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ // send the request
402
+ $response = curl_exec($this->_curl);
403
+
404
+ // if we used streaming, headers are already there
405
+ if(!is_resource($this->out_stream)) {
406
+ $this->_response = $response;
407
+ }
408
+
409
+ $request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT);
410
+ $request .= $body;
411
+
412
+ if (empty($this->_response)) {
413
+ require_once 'Microsoft/Http/Client/Exception.php';
414
+ throw new Microsoft_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl));
415
+ }
416
+
417
+ // cURL automatically decodes chunked-messages, this means we have to disallow the Microsoft_Http_Response to do it again
418
+ if (stripos($this->_response, "Transfer-Encoding: chunked\r\n")) {
419
+ $this->_response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->_response);
420
+ }
421
+
422
+ // Eliminate multiple HTTP responses.
423
+ do {
424
+ $parts = preg_split('|(?:\r?\n){2}|m', $this->_response, 2);
425
+ $again = false;
426
+
427
+ if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) {
428
+ $this->_response = $parts[1];
429
+ $again = true;
430
+ }
431
+ } while ($again);
432
+
433
+ // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string:
434
+ if (stripos($this->_response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) {
435
+ $this->_response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->_response);
436
+ }
437
+
438
+ return $request;
439
+ }
440
+
441
+ /**
442
+ * Return read response from server
443
+ *
444
+ * @return string
445
+ */
446
+ public function read()
447
+ {
448
+ return $this->_response;
449
+ }
450
+
451
+ /**
452
+ * Close the connection to the server
453
+ *
454
+ */
455
+ public function close()
456
+ {
457
+ if(is_resource($this->_curl)) {
458
+ curl_close($this->_curl);
459
+ }
460
+ $this->_curl = null;
461
+ $this->_connected_to = array(null, null);
462
+ }
463
+
464
+ /**
465
+ * Get cUrl Handle
466
+ *
467
+ * @return resource
468
+ */
469
+ public function getHandle()
470
+ {
471
+ return $this->_curl;
472
+ }
473
+
474
+ /**
475
+ * Set output stream for the response
476
+ *
477
+ * @param resource $stream
478
+ * @return Microsoft_Http_Client_Adapter_Socket
479
+ */
480
+ public function setOutputStream($stream)
481
+ {
482
+ $this->out_stream = $stream;
483
+ return $this;
484
+ }
485
+
486
+ /**
487
+ * Header reader function for CURL
488
+ *
489
+ * @param resource $curl
490
+ * @param string $header
491
+ * @return int
492
+ */
493
+ public function readHeader($curl, $header)
494
+ {
495
+ $this->_response .= $header;
496
+ return strlen($header);
497
+ }
498
+ }
lib/Microsoft/Http/Client/Adapter/Exception.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Http
17
+ * @subpackage Client_Adapter_Exception
18
+ * @version $Id: Exception.php 17026 2009-07-24 09:09:19Z shahar $
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see Microsoft_Http_Client_Exception
25
+ */
26
+ require_once 'Microsoft/Http/Client/Exception.php';
27
+
28
+ /**
29
+ * @category Microsoft
30
+ * @package Microsoft_Http
31
+ * @subpackage Client_Adapter
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Microsoft_Http_Client_Adapter_Exception extends Microsoft_Http_Client_Exception
36
+ {
37
+ const READ_TIMEOUT = 1000;
38
+ }
lib/Microsoft/Http/Client/Adapter/Interface.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Interface.php 16214 2009-06-21 19:34:03Z thomas $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * An interface description for Microsoft_Http_Client_Adapter classes.
26
+ *
27
+ * These classes are used as connectors for Microsoft_Http_Client, performing the
28
+ * tasks of connecting, writing, reading and closing connection to the server.
29
+ *
30
+ * @category Microsoft
31
+ * @package Microsoft_Http
32
+ * @subpackage Client_Adapter
33
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ interface Microsoft_Http_Client_Adapter_Interface
37
+ {
38
+ /**
39
+ * Set the configuration array for the adapter
40
+ *
41
+ * @param array $config
42
+ */
43
+ public function setConfig($config = array());
44
+
45
+ /**
46
+ * Connect to the remote server
47
+ *
48
+ * @param string $host
49
+ * @param int $port
50
+ * @param boolean $secure
51
+ */
52
+ public function connect($host, $port = 80, $secure = false);
53
+
54
+ /**
55
+ * Send request to the remote server
56
+ *
57
+ * @param string $method
58
+ * @param Microsoft_Uri_Http $url
59
+ * @param string $http_ver
60
+ * @param array $headers
61
+ * @param string $body
62
+ * @return string Request as text
63
+ */
64
+ public function write($method, $url, $http_ver = '1.1', $headers = array(), $body = '');
65
+
66
+ /**
67
+ * Read response from server
68
+ *
69
+ * @return string
70
+ */
71
+ public function read();
72
+
73
+ /**
74
+ * Close the connection to the server
75
+ *
76
+ */
77
+ public function close();
78
+ }
lib/Microsoft/Http/Client/Adapter/Proxy.php ADDED
@@ -0,0 +1,267 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Proxy.php 17059 2009-07-25 11:24:49Z shahar $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+ /**
29
+ * @see Microsoft_Http_Client
30
+ */
31
+ require_once 'Microsoft/Http/Client.php';
32
+ /**
33
+ * @see Microsoft_Http_Client_Adapter_Socket
34
+ */
35
+ require_once 'Microsoft/Http/Client/Adapter/Socket.php';
36
+
37
+ /**
38
+ * HTTP Proxy-supporting Microsoft_Http_Client adapter class, based on the default
39
+ * socket based adapter.
40
+ *
41
+ * Should be used if proxy HTTP access is required. If no proxy is set, will
42
+ * fall back to Microsoft_Http_Client_Adapter_Socket behavior. Just like the
43
+ * default Socket adapter, this adapter does not require any special extensions
44
+ * installed.
45
+ *
46
+ * @category Microsoft
47
+ * @package Microsoft_Http
48
+ * @subpackage Client_Adapter
49
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
50
+ * @license http://framework.zend.com/license/new-bsd New BSD License
51
+ */
52
+ class Microsoft_Http_Client_Adapter_Proxy extends Microsoft_Http_Client_Adapter_Socket
53
+ {
54
+ /**
55
+ * Parameters array
56
+ *
57
+ * @var array
58
+ */
59
+ protected $config = array(
60
+ 'ssltransport' => 'ssl',
61
+ 'sslcert' => null,
62
+ 'sslpassphrase' => null,
63
+ 'proxy_host' => '',
64
+ 'proxy_port' => 8080,
65
+ 'proxy_user' => '',
66
+ 'proxy_pass' => '',
67
+ 'proxy_auth' => Microsoft_Http_Client::AUTH_BASIC,
68
+ 'persistent' => false
69
+ );
70
+
71
+ /**
72
+ * Whether HTTPS CONNECT was already negotiated with the proxy or not
73
+ *
74
+ * @var boolean
75
+ */
76
+ protected $negotiated = false;
77
+
78
+ /**
79
+ * Connect to the remote server
80
+ *
81
+ * Will try to connect to the proxy server. If no proxy was set, will
82
+ * fall back to the target server (behave like regular Socket adapter)
83
+ *
84
+ * @param string $host
85
+ * @param int $port
86
+ * @param boolean $secure
87
+ */
88
+ public function connect($host, $port = 80, $secure = false)
89
+ {
90
+ // If no proxy is set, fall back to Socket adapter
91
+ if (! $this->config['proxy_host']) {
92
+ return parent::connect($host, $port, $secure);
93
+ }
94
+
95
+ // Connect (a non-secure connection) to the proxy server
96
+ return parent::connect(
97
+ $this->config['proxy_host'],
98
+ $this->config['proxy_port'],
99
+ false
100
+ );
101
+ }
102
+
103
+ /**
104
+ * Send request to the proxy server
105
+ *
106
+ * @param string $method
107
+ * @param Microsoft_Uri_Http $uri
108
+ * @param string $http_ver
109
+ * @param array $headers
110
+ * @param string $body
111
+ * @return string Request as string
112
+ */
113
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
114
+ {
115
+ // If no proxy is set, fall back to default Socket adapter
116
+ if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body);
117
+
118
+ // Make sure we're properly connected
119
+ if (! $this->socket) {
120
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
121
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are not connected");
122
+ }
123
+
124
+ $host = $this->config['proxy_host'];
125
+ $port = $this->config['proxy_port'];
126
+
127
+ if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) {
128
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
129
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
130
+ }
131
+
132
+ // Add Proxy-Authorization header
133
+ if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization'])) {
134
+ $headers['proxy-authorization'] = Microsoft_Http_Client::encodeAuthHeader(
135
+ $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth']
136
+ );
137
+ }
138
+
139
+ // if we are proxying HTTPS, preform CONNECT handshake with the proxy
140
+ if ($uri->getScheme() == 'https' && (! $this->negotiated)) {
141
+ $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers);
142
+ $this->negotiated = true;
143
+ }
144
+
145
+ // Save request method for later
146
+ $this->method = $method;
147
+
148
+ // Build request headers
149
+ if ($this->negotiated) {
150
+ $path = $uri->getPath();
151
+ if ($uri->getQuery()) {
152
+ $path .= '?' . $uri->getQuery();
153
+ }
154
+ $request = "$method $path HTTP/$http_ver\r\n";
155
+ } else {
156
+ $request = "$method $uri HTTP/$http_ver\r\n";
157
+ }
158
+
159
+ // Add all headers to the request string
160
+ foreach ($headers as $k => $v) {
161
+ if (is_string($k)) $v = "$k: $v";
162
+ $request .= "$v\r\n";
163
+ }
164
+
165
+ // Add the request body
166
+ $request .= "\r\n" . $body;
167
+
168
+ // Send the request
169
+ if (! @fwrite($this->socket, $request)) {
170
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
171
+ throw new Microsoft_Http_Client_Adapter_Exception("Error writing request to proxy server");
172
+ }
173
+
174
+ return $request;
175
+ }
176
+
177
+ /**
178
+ * Preform handshaking with HTTPS proxy using CONNECT method
179
+ *
180
+ * @param string $host
181
+ * @param integer $port
182
+ * @param string $http_ver
183
+ * @param array $headers
184
+ */
185
+ protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
186
+ {
187
+ $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
188
+ "Host: " . $this->config['proxy_host'] . "\r\n";
189
+
190
+ // Add the user-agent header
191
+ if (isset($this->config['useragent'])) {
192
+ $request .= "User-agent: " . $this->config['useragent'] . "\r\n";
193
+ }
194
+
195
+ // If the proxy-authorization header is set, send it to proxy but remove
196
+ // it from headers sent to target host
197
+ if (isset($headers['proxy-authorization'])) {
198
+ $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n";
199
+ unset($headers['proxy-authorization']);
200
+ }
201
+
202
+ $request .= "\r\n";
203
+
204
+ // Send the request
205
+ if (! @fwrite($this->socket, $request)) {
206
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
207
+ throw new Microsoft_Http_Client_Adapter_Exception("Error writing request to proxy server");
208
+ }
209
+
210
+ // Read response headers only
211
+ $response = '';
212
+ $gotStatus = false;
213
+ while ($line = @fgets($this->socket)) {
214
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
215
+ if ($gotStatus) {
216
+ $response .= $line;
217
+ if (!chop($line)) break;
218
+ }
219
+ }
220
+
221
+ // Check that the response from the proxy is 200
222
+ if (Microsoft_Http_Response::extractCode($response) != 200) {
223
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
224
+ throw new Microsoft_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
225
+ }
226
+
227
+ // If all is good, switch socket to secure mode. We have to fall back
228
+ // through the different modes
229
+ $modes = array(
230
+ STREAM_CRYPTO_METHOD_TLS_CLIENT,
231
+ STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
232
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
233
+ STREAM_CRYPTO_METHOD_SSLv2_CLIENT
234
+ );
235
+
236
+ $success = false;
237
+ foreach($modes as $mode) {
238
+ $success = stream_socket_enable_crypto($this->socket, true, $mode);
239
+ if ($success) break;
240
+ }
241
+
242
+ if (! $success) {
243
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
244
+ throw new Microsoft_Http_Client_Adapter_Exception("Unable to connect to" .
245
+ " HTTPS server through proxy: could not negotiate secure connection.");
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Close the connection to the server
251
+ *
252
+ */
253
+ public function close()
254
+ {
255
+ parent::close();
256
+ $this->negotiated = false;
257
+ }
258
+
259
+ /**
260
+ * Destructor: make sure the socket is disconnected
261
+ *
262
+ */
263
+ public function __destruct()
264
+ {
265
+ if ($this->socket) $this->close();
266
+ }
267
+ }
lib/Microsoft/Http/Client/Adapter/Socket.php ADDED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Socket.php 19219 2009-11-24 22:25:36Z stas $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+ /**
29
+ * @see Microsoft_Http_Client_Adapter_Interface
30
+ */
31
+ require_once 'Microsoft/Http/Client/Adapter/Interface.php';
32
+ /**
33
+ * @see Microsoft_Http_Client_Adapter_Stream
34
+ */
35
+ require_once 'Microsoft/Http/Client/Adapter/Stream.php';
36
+
37
+ /**
38
+ * A sockets based (stream_socket_client) adapter class for Microsoft_Http_Client. Can be used
39
+ * on almost every PHP environment, and does not require any special extensions.
40
+ *
41
+ * @category Microsoft
42
+ * @package Microsoft_Http
43
+ * @subpackage Client_Adapter
44
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
45
+ * @license http://framework.zend.com/license/new-bsd New BSD License
46
+ */
47
+ class Microsoft_Http_Client_Adapter_Socket implements Microsoft_Http_Client_Adapter_Interface, Microsoft_Http_Client_Adapter_Stream
48
+ {
49
+ /**
50
+ * The socket for server connection
51
+ *
52
+ * @var resource|null
53
+ */
54
+ protected $socket = null;
55
+
56
+ /**
57
+ * What host/port are we connected to?
58
+ *
59
+ * @var array
60
+ */
61
+ protected $connected_to = array(null, null);
62
+
63
+ /**
64
+ * Stream for storing output
65
+ *
66
+ * @var resource
67
+ */
68
+ protected $out_stream = null;
69
+
70
+ /**
71
+ * Parameters array
72
+ *
73
+ * @var array
74
+ */
75
+ protected $config = array(
76
+ 'persistent' => false,
77
+ 'ssltransport' => 'ssl',
78
+ 'sslcert' => null,
79
+ 'sslpassphrase' => null
80
+ );
81
+
82
+ /**
83
+ * Request method - will be set by write() and might be used by read()
84
+ *
85
+ * @var string
86
+ */
87
+ protected $method = null;
88
+
89
+ /**
90
+ * Stream context
91
+ *
92
+ * @var resource
93
+ */
94
+ protected $_context = null;
95
+
96
+ /**
97
+ * Adapter constructor, currently empty. Config is set using setConfig()
98
+ *
99
+ */
100
+ public function __construct()
101
+ {
102
+ }
103
+
104
+ /**
105
+ * Set the configuration array for the adapter
106
+ *
107
+ * @param array $config
108
+ */
109
+ public function setConfig($config = array())
110
+ {
111
+ if (! is_array($config)) {
112
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
113
+ throw new Microsoft_Http_Client_Adapter_Exception(
114
+ 'Array expected, got ' . gettype($config)
115
+ );
116
+ }
117
+
118
+ foreach ($config as $k => $v) {
119
+ $this->config[strtolower($k)] = $v;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Retrieve the array of all configuration options
125
+ *
126
+ * @return array
127
+ */
128
+ public function getConfig()
129
+ {
130
+ return $this->config;
131
+ }
132
+
133
+ /**
134
+ * Set the stream context for the TCP connection to the server
135
+ *
136
+ * Can accept either a pre-existing stream context resource, or an array
137
+ * of stream options, similar to the options array passed to the
138
+ * stream_context_create() PHP function. In such case a new stream context
139
+ * will be created using the passed options.
140
+ *
141
+ * @since Zend Framework 1.9
142
+ *
143
+ * @param mixed $context Stream context or array of context options
144
+ * @return Microsoft_Http_Client_Adapter_Socket
145
+ */
146
+ public function setStreamContext($context)
147
+ {
148
+ if (is_resource($context) && get_resource_type($context) == 'stream-context') {
149
+ $this->_context = $context;
150
+
151
+ } elseif (is_array($context)) {
152
+ $this->_context = stream_context_create($context);
153
+
154
+ } else {
155
+ // Invalid parameter
156
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
157
+ throw new Microsoft_Http_Client_Adapter_Exception(
158
+ "Expecting either a stream context resource or array, got " . gettype($context)
159
+ );
160
+ }
161
+
162
+ return $this;
163
+ }
164
+
165
+ /**
166
+ * Get the stream context for the TCP connection to the server.
167
+ *
168
+ * If no stream context is set, will create a default one.
169
+ *
170
+ * @return resource
171
+ */
172
+ public function getStreamContext()
173
+ {
174
+ if (! $this->_context) {
175
+ $this->_context = stream_context_create();
176
+ }
177
+
178
+ return $this->_context;
179
+ }
180
+
181
+ /**
182
+ * Connect to the remote server
183
+ *
184
+ * @param string $host
185
+ * @param int $port
186
+ * @param boolean $secure
187
+ */
188
+ public function connect($host, $port = 80, $secure = false)
189
+ {
190
+ // If the URI should be accessed via SSL, prepend the Hostname with ssl://
191
+ $host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
192
+
193
+ // If we are connected to the wrong host, disconnect first
194
+ if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
195
+ if (is_resource($this->socket)) $this->close();
196
+ }
197
+
198
+ // Now, if we are not connected, connect
199
+ if (! is_resource($this->socket) || ! $this->config['keepalive']) {
200
+ $context = $this->getStreamContext();
201
+ if ($secure) {
202
+ if ($this->config['sslcert'] !== null) {
203
+ if (! stream_context_set_option($context, 'ssl', 'local_cert',
204
+ $this->config['sslcert'])) {
205
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
206
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to set sslcert option');
207
+ }
208
+ }
209
+ if ($this->config['sslpassphrase'] !== null) {
210
+ if (! stream_context_set_option($context, 'ssl', 'passphrase',
211
+ $this->config['sslpassphrase'])) {
212
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
213
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to set sslpassphrase option');
214
+ }
215
+ }
216
+ }
217
+
218
+ $flags = STREAM_CLIENT_CONNECT;
219
+ if ($this->config['persistent']) $flags |= STREAM_CLIENT_PERSISTENT;
220
+
221
+ $this->socket = @stream_socket_client($host . ':' . $port,
222
+ $errno,
223
+ $errstr,
224
+ (int) $this->config['timeout'],
225
+ $flags,
226
+ $context);
227
+
228
+ if (! $this->socket) {
229
+ $this->close();
230
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
231
+ throw new Microsoft_Http_Client_Adapter_Exception(
232
+ 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
233
+ }
234
+
235
+ // Set the stream timeout
236
+ if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
237
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
238
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to set the connection timeout');
239
+ }
240
+
241
+ // Update connected_to
242
+ $this->connected_to = array($host, $port);
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Send request to the remote server
248
+ *
249
+ * @param string $method
250
+ * @param Microsoft_Uri_Http $uri
251
+ * @param string $http_ver
252
+ * @param array $headers
253
+ * @param string $body
254
+ * @return string Request as string
255
+ */
256
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
257
+ {
258
+ // Make sure we're properly connected
259
+ if (! $this->socket) {
260
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
261
+ throw new Microsoft_Http_Client_Adapter_Exception('Trying to write but we are not connected');
262
+ }
263
+
264
+ $host = $uri->getHost();
265
+ $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
266
+ if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) {
267
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
268
+ throw new Microsoft_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host');
269
+ }
270
+
271
+ // Save request method for later
272
+ $this->method = $method;
273
+
274
+ // Build request headers
275
+ $path = $uri->getPath();
276
+ if ($uri->getQuery()) $path .= '?' . $uri->getQuery();
277
+ $request = "{$method} {$path} HTTP/{$http_ver}\r\n";
278
+ foreach ($headers as $k => $v) {
279
+ if (is_string($k)) $v = ucfirst($k) . ": $v";
280
+ $request .= "$v\r\n";
281
+ }
282
+
283
+ if(is_resource($body)) {
284
+ $request .= "\r\n";
285
+ } else {
286
+ // Add the request body
287
+ $request .= "\r\n" . $body;
288
+ }
289
+
290
+ // Send the request
291
+ if (! @fwrite($this->socket, $request)) {
292
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
293
+ throw new Microsoft_Http_Client_Adapter_Exception('Error writing request to server');
294
+ }
295
+
296
+ if(is_resource($body)) {
297
+ if(stream_copy_to_stream($body, $this->socket) == 0) {
298
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
299
+ throw new Microsoft_Http_Client_Adapter_Exception('Error writing request to server');
300
+ }
301
+ }
302
+
303
+ return $request;
304
+ }
305
+
306
+ /**
307
+ * Read response from server
308
+ *
309
+ * @return string
310
+ */
311
+ public function read()
312
+ {
313
+ // First, read headers only
314
+ $response = '';
315
+ $gotStatus = false;
316
+ $stream = !empty($this->config['stream']);
317
+
318
+ while (($line = @fgets($this->socket)) !== false) {
319
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
320
+ if ($gotStatus) {
321
+ $response .= $line;
322
+ if (rtrim($line) === '') break;
323
+ }
324
+ }
325
+
326
+ $this->_checkSocketReadTimeout();
327
+
328
+ $statusCode = Microsoft_Http_Response::extractCode($response);
329
+
330
+ // Handle 100 and 101 responses internally by restarting the read again
331
+ if ($statusCode == 100 || $statusCode == 101) return $this->read();
332
+
333
+ // Check headers to see what kind of connection / transfer encoding we have
334
+ $headers = Microsoft_Http_Response::extractHeaders($response);
335
+
336
+ /**
337
+ * Responses to HEAD requests and 204 or 304 responses are not expected
338
+ * to have a body - stop reading here
339
+ */
340
+ if ($statusCode == 304 || $statusCode == 204 ||
341
+ $this->method == Microsoft_Http_Client::HEAD) {
342
+
343
+ // Close the connection if requested to do so by the server
344
+ if (isset($headers['connection']) && $headers['connection'] == 'close') {
345
+ $this->close();
346
+ }
347
+ return $response;
348
+ }
349
+
350
+ // If we got a 'transfer-encoding: chunked' header
351
+ if (isset($headers['transfer-encoding'])) {
352
+
353
+ if (strtolower($headers['transfer-encoding']) == 'chunked') {
354
+
355
+ do {
356
+ $line = @fgets($this->socket);
357
+ $this->_checkSocketReadTimeout();
358
+
359
+ $chunk = $line;
360
+
361
+ // Figure out the next chunk size
362
+ $chunksize = trim($line);
363
+ if (! ctype_xdigit($chunksize)) {
364
+ $this->close();
365
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
366
+ throw new Microsoft_Http_Client_Adapter_Exception('Invalid chunk size "' .
367
+ $chunksize . '" unable to read chunked body');
368
+ }
369
+
370
+ // Convert the hexadecimal value to plain integer
371
+ $chunksize = hexdec($chunksize);
372
+
373
+ // Read next chunk
374
+ $read_to = ftell($this->socket) + $chunksize;
375
+
376
+ do {
377
+ $current_pos = ftell($this->socket);
378
+ if ($current_pos >= $read_to) break;
379
+
380
+ if($this->out_stream) {
381
+ if(stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) {
382
+ $this->_checkSocketReadTimeout();
383
+ break;
384
+ }
385
+ } else {
386
+ $line = @fread($this->socket, $read_to - $current_pos);
387
+ if ($line === false || strlen($line) === 0) {
388
+ $this->_checkSocketReadTimeout();
389
+ break;
390
+ }
391
+ $chunk .= $line;
392
+ }
393
+ } while (! feof($this->socket));
394
+
395
+ $chunk .= @fgets($this->socket);
396
+ $this->_checkSocketReadTimeout();
397
+
398
+ if(!$this->out_stream) {
399
+ $response .= $chunk;
400
+ }
401
+ } while ($chunksize > 0);
402
+ } else {
403
+ $this->close();
404
+ throw new Microsoft_Http_Client_Adapter_Exception('Cannot handle "' .
405
+ $headers['transfer-encoding'] . '" transfer encoding');
406
+ }
407
+
408
+ // We automatically decode chunked-messages when writing to a stream
409
+ // this means we have to disallow the Microsoft_Http_Response to do it again
410
+ if ($this->out_stream) {
411
+ $response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response);
412
+ }
413
+ // Else, if we got the content-length header, read this number of bytes
414
+ } elseif (isset($headers['content-length'])) {
415
+
416
+ $current_pos = ftell($this->socket);
417
+ $chunk = '';
418
+
419
+ for ($read_to = $current_pos + $headers['content-length'];
420
+ $read_to > $current_pos;
421
+ $current_pos = ftell($this->socket)) {
422
+
423
+ if($this->out_stream) {
424
+ if(@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) {
425
+ $this->_checkSocketReadTimeout();
426
+ break;
427
+ }
428
+ } else {
429
+ $chunk = @fread($this->socket, $read_to - $current_pos);
430
+ if ($chunk === false || strlen($chunk) === 0) {
431
+ $this->_checkSocketReadTimeout();
432
+ break;
433
+ }
434
+
435
+ $response .= $chunk;
436
+ }
437
+
438
+ // Break if the connection ended prematurely
439
+ if (feof($this->socket)) break;
440
+ }
441
+
442
+ // Fallback: just read the response until EOF
443
+ } else {
444
+
445
+ do {
446
+ if($this->out_stream) {
447
+ if(@stream_copy_to_stream($this->socket, $this->out_stream) == 0) {
448
+ $this->_checkSocketReadTimeout();
449
+ break;
450
+ }
451
+ } else {
452
+ $buff = @fread($this->socket, 8192);
453
+ if ($buff === false || strlen($buff) === 0) {
454
+ $this->_checkSocketReadTimeout();
455
+ break;
456
+ } else {
457
+ $response .= $buff;
458
+ }
459
+ }
460
+
461
+ } while (feof($this->socket) === false);
462
+
463
+ $this->close();
464
+ }
465
+
466
+ // Close the connection if requested to do so by the server
467
+ if (isset($headers['connection']) && $headers['connection'] == 'close') {
468
+ $this->close();
469
+ }
470
+
471
+ return $response;
472
+ }
473
+
474
+ /**
475
+ * Close the connection to the server
476
+ *
477
+ */
478
+ public function close()
479
+ {
480
+ if (is_resource($this->socket)) @fclose($this->socket);
481
+ $this->socket = null;
482
+ $this->connected_to = array(null, null);
483
+ }
484
+
485
+ /**
486
+ * Check if the socket has timed out - if so close connection and throw
487
+ * an exception
488
+ *
489
+ * @throws Microsoft_Http_Client_Adapter_Exception with READ_TIMEOUT code
490
+ */
491
+ protected function _checkSocketReadTimeout()
492
+ {
493
+ if ($this->socket) {
494
+ $info = stream_get_meta_data($this->socket);
495
+ $timedout = $info['timed_out'];
496
+ if ($timedout) {
497
+ $this->close();
498
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
499
+ throw new Microsoft_Http_Client_Adapter_Exception(
500
+ "Read timed out after {$this->config['timeout']} seconds",
501
+ Microsoft_Http_Client_Adapter_Exception::READ_TIMEOUT
502
+ );
503
+ }
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Set output stream for the response
509
+ *
510
+ * @param resource $stream
511
+ * @return Microsoft_Http_Client_Adapter_Socket
512
+ */
513
+ public function setOutputStream($stream)
514
+ {
515
+ $this->out_stream = $stream;
516
+ return $this;
517
+ }
518
+
519
+ /**
520
+ * Destructor: make sure the socket is disconnected
521
+ *
522
+ * If we are in persistent TCP mode, will not close the connection
523
+ *
524
+ */
525
+ public function __destruct()
526
+ {
527
+ if (! $this->config['persistent']) {
528
+ if ($this->socket) $this->close();
529
+ }
530
+ }
531
+ }
lib/Microsoft/Http/Client/Adapter/Stream.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Interface.php 16214 2009-06-21 19:34:03Z thomas $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * An interface description for Microsoft_Http_Client_Adapter_Stream classes.
26
+ *
27
+ * This interface decribes Microsoft_Http_Client_Adapter which supports streaming.
28
+ *
29
+ * @category Microsoft
30
+ * @package Microsoft_Http
31
+ * @subpackage Client_Adapter
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ interface Microsoft_Http_Client_Adapter_Stream
36
+ {
37
+ /**
38
+ * Set output stream
39
+ *
40
+ * This function sets output stream where the result will be stored.
41
+ *
42
+ * @param resource $stream Stream to write the output to
43
+ *
44
+ */
45
+ function setOutputStream($stream);
46
+ }
lib/Microsoft/Http/Client/Exception.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Http
17
+ * @subpackage Client_Exception
18
+ * @version $Id: Exception.php 16872 2009-07-20 11:47:08Z mikaelkael $
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see Microsoft_Http_Exception
25
+ */
26
+ require_once 'Microsoft/Http/Exception.php';
27
+
28
+ /**
29
+ * @category Microsoft
30
+ * @package Microsoft_Http
31
+ * @subpackage Client
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Microsoft_Http_Client_Exception extends Microsoft_Http_Exception
36
+ {}
lib/Microsoft/Http/Cookie.php ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Cookie
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @version $Id: Cookie.php 17131 2009-07-26 10:03:39Z shahar $
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+
29
+
30
+ /**
31
+ * Microsoft_Http_Cookie is a class describing an HTTP cookie and all it's parameters.
32
+ *
33
+ * Microsoft_Http_Cookie is a class describing an HTTP cookie and all it's parameters. The
34
+ * class also enables validating whether the cookie should be sent to the server in
35
+ * a specified scenario according to the request URI, the expiry time and whether
36
+ * session cookies should be used or not. Generally speaking cookies should be
37
+ * contained in a Cookiejar object, or instantiated manually and added to an HTTP
38
+ * request.
39
+ *
40
+ * See http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
41
+ *
42
+ * @category Microsoft
43
+ * @package Microsoft_Http
44
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
45
+ * @license http://framework.zend.com/license/new-bsd New BSD License
46
+ */
47
+ class Microsoft_Http_Cookie
48
+ {
49
+ /**
50
+ * Cookie name
51
+ *
52
+ * @var string
53
+ */
54
+ protected $name;
55
+
56
+ /**
57
+ * Cookie value
58
+ *
59
+ * @var string
60
+ */
61
+ protected $value;
62
+
63
+ /**
64
+ * Cookie expiry date
65
+ *
66
+ * @var int
67
+ */
68
+ protected $expires;
69
+
70
+ /**
71
+ * Cookie domain
72
+ *
73
+ * @var string
74
+ */
75
+ protected $domain;
76
+
77
+ /**
78
+ * Cookie path
79
+ *
80
+ * @var string
81
+ */
82
+ protected $path;
83
+
84
+ /**
85
+ * Whether the cookie is secure or not
86
+ *
87
+ * @var boolean
88
+ */
89
+ protected $secure;
90
+
91
+ /**
92
+ * Cookie object constructor
93
+ *
94
+ * @todo Add validation of each one of the parameters (legal domain, etc.)
95
+ *
96
+ * @param string $name
97
+ * @param string $value
98
+ * @param string $domain
99
+ * @param int $expires
100
+ * @param string $path
101
+ * @param bool $secure
102
+ */
103
+ public function __construct($name, $value, $domain, $expires = null, $path = null, $secure = false)
104
+ {
105
+ if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
106
+ require_once 'Microsoft/Http/Exception.php';
107
+ throw new Microsoft_Http_Exception("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
108
+ }
109
+
110
+ if (! $this->name = (string) $name) {
111
+ require_once 'Microsoft/Http/Exception.php';
112
+ throw new Microsoft_Http_Exception('Cookies must have a name');
113
+ }
114
+
115
+ if (! $this->domain = (string) $domain) {
116
+ require_once 'Microsoft/Http/Exception.php';
117
+ throw new Microsoft_Http_Exception('Cookies must have a domain');
118
+ }
119
+
120
+ $this->value = (string) $value;
121
+ $this->expires = ($expires === null ? null : (int) $expires);
122
+ $this->path = ($path ? $path : '/');
123
+ $this->secure = $secure;
124
+ }
125
+
126
+ /**
127
+ * Get Cookie name
128
+ *
129
+ * @return string
130
+ */
131
+ public function getName()
132
+ {
133
+ return $this->name;
134
+ }
135
+
136
+ /**
137
+ * Get cookie value
138
+ *
139
+ * @return string
140
+ */
141
+ public function getValue()
142
+ {
143
+ return $this->value;
144
+ }
145
+
146
+ /**
147
+ * Get cookie domain
148
+ *
149
+ * @return string
150
+ */
151
+ public function getDomain()
152
+ {
153
+ return $this->domain;
154
+ }
155
+
156
+ /**
157
+ * Get the cookie path
158
+ *
159
+ * @return string
160
+ */
161
+ public function getPath()
162
+ {
163
+ return $this->path;
164
+ }
165
+
166
+ /**
167
+ * Get the expiry time of the cookie, or null if no expiry time is set
168
+ *
169
+ * @return int|null
170
+ */
171
+ public function getExpiryTime()
172
+ {
173
+ return $this->expires;
174
+ }
175
+
176
+ /**
177
+ * Check whether the cookie should only be sent over secure connections
178
+ *
179
+ * @return boolean
180
+ */
181
+ public function isSecure()
182
+ {
183
+ return $this->secure;
184
+ }
185
+
186
+ /**
187
+ * Check whether the cookie has expired
188
+ *
189
+ * Always returns false if the cookie is a session cookie (has no expiry time)
190
+ *
191
+ * @param int $now Timestamp to consider as "now"
192
+ * @return boolean
193
+ */
194
+ public function isExpired($now = null)
195
+ {
196
+ if ($now === null) $now = time();
197
+ if (is_int($this->expires) && $this->expires < $now) {
198
+ return true;
199
+ } else {
200
+ return false;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Check whether the cookie is a session cookie (has no expiry time set)
206
+ *
207
+ * @return boolean
208
+ */
209
+ public function isSessionCookie()
210
+ {
211
+ return ($this->expires === null);
212
+ }
213
+
214
+ /**
215
+ * Checks whether the cookie should be sent or not in a specific scenario
216
+ *
217
+ * @param string|Microsoft_Uri_Http $uri URI to check against (secure, domain, path)
218
+ * @param boolean $matchSessionCookies Whether to send session cookies
219
+ * @param int $now Override the current time when checking for expiry time
220
+ * @return boolean
221
+ */
222
+ public function match($uri, $matchSessionCookies = true, $now = null)
223
+ {
224
+ if (is_string ($uri)) {
225
+ $uri = Microsoft_Uri_Http::factory($uri);
226
+ }
227
+
228
+ // Make sure we have a valid Microsoft_Uri_Http object
229
+ if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) {
230
+ require_once 'Microsoft/Http/Exception.php';
231
+ throw new Microsoft_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI');
232
+ }
233
+
234
+ // Check that the cookie is secure (if required) and not expired
235
+ if ($this->secure && $uri->getScheme() != 'https') return false;
236
+ if ($this->isExpired($now)) return false;
237
+ if ($this->isSessionCookie() && ! $matchSessionCookies) return false;
238
+
239
+ // Check if the domain matches
240
+ if (! self::matchCookieDomain($this->getDomain(), $uri->getHost())) {
241
+ return false;
242
+ }
243
+
244
+ // Check that path matches using prefix match
245
+ if (! self::matchCookiePath($this->getPath(), $uri->getPath())) {
246
+ return false;
247
+ }
248
+
249
+ // If we didn't die until now, return true.
250
+ return true;
251
+ }
252
+
253
+ /**
254
+ * Get the cookie as a string, suitable for sending as a "Cookie" header in an
255
+ * HTTP request
256
+ *
257
+ * @return string
258
+ */
259
+ public function __toString()
260
+ {
261
+ return $this->name . '=' . urlencode($this->value) . ';';
262
+ }
263
+
264
+ /**
265
+ * Generate a new Cookie object from a cookie string
266
+ * (for example the value of the Set-Cookie HTTP header)
267
+ *
268
+ * @param string $cookieStr
269
+ * @param Microsoft_Uri_Http|string $ref_uri Reference URI for default values (domain, path)
270
+ * @return Microsoft_Http_Cookie A new Microsoft_Http_Cookie object or false on failure.
271
+ */
272
+ public static function fromString($cookieStr, $ref_uri = null)
273
+ {
274
+ // Set default values
275
+ if (is_string($ref_uri)) {
276
+ $ref_uri = Microsoft_Uri_Http::factory($ref_uri);
277
+ }
278
+
279
+ $name = '';
280
+ $value = '';
281
+ $domain = '';
282
+ $path = '';
283
+ $expires = null;
284
+ $secure = false;
285
+ $parts = explode(';', $cookieStr);
286
+
287
+ // If first part does not include '=', fail
288
+ if (strpos($parts[0], '=') === false) return false;
289
+
290
+ // Get the name and value of the cookie
291
+ list($name, $value) = explode('=', trim(array_shift($parts)), 2);
292
+ $name = trim($name);
293
+ $value = urldecode(trim($value));
294
+
295
+ // Set default domain and path
296
+ if ($ref_uri instanceof Microsoft_Uri_Http) {
297
+ $domain = $ref_uri->getHost();
298
+ $path = $ref_uri->getPath();
299
+ $path = substr($path, 0, strrpos($path, '/'));
300
+ }
301
+
302
+ // Set other cookie parameters
303
+ foreach ($parts as $part) {
304
+ $part = trim($part);
305
+ if (strtolower($part) == 'secure') {
306
+ $secure = true;
307
+ continue;
308
+ }
309
+
310
+ $keyValue = explode('=', $part, 2);
311
+ if (count($keyValue) == 2) {
312
+ list($k, $v) = $keyValue;
313
+ switch (strtolower($k)) {
314
+ case 'expires':
315
+ if(($expires = strtotime($v)) === false) {
316
+ /**
317
+ * The expiration is past Tue, 19 Jan 2038 03:14:07 UTC
318
+ * the maximum for 32-bit signed integer. Microsoft_Date
319
+ * can get around that limit.
320
+ *
321
+ * @see Microsoft_Date
322
+ */
323
+ require_once 'Microsoft/Date.php';
324
+
325
+ $expireDate = new Microsoft_Date($v);
326
+ $expires = $expireDate->getTimestamp();
327
+ }
328
+ break;
329
+
330
+ case 'path':
331
+ $path = $v;
332
+ break;
333
+
334
+ case 'domain':
335
+ $domain = $v;
336
+ break;
337
+
338
+ default:
339
+ break;
340
+ }
341
+ }
342
+ }
343
+
344
+ if ($name !== '') {
345
+ return new self($name, $value, $domain, $expires, $path, $secure);
346
+ } else {
347
+ return false;
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Check if a cookie's domain matches a host name.
353
+ *
354
+ * Used by Microsoft_Http_Cookie and Microsoft_Http_CookieJar for cookie matching
355
+ *
356
+ * @param string $cookieDomain
357
+ * @param string $host
358
+ *
359
+ * @return boolean
360
+ */
361
+ public static function matchCookieDomain($cookieDomain, $host)
362
+ {
363
+ if (! $cookieDomain) {
364
+ require_once 'Microsoft/Http/Exception.php';
365
+ throw new Microsoft_Http_Exception("\$cookieDomain is expected to be a cookie domain");
366
+ }
367
+
368
+ if (! $host) {
369
+ require_once 'Microsoft/Http/Exception.php';
370
+ throw new Microsoft_Http_Exception("\$host is expected to be a host name");
371
+ }
372
+
373
+ $cookieDomain = strtolower($cookieDomain);
374
+ $host = strtolower($host);
375
+
376
+ if ($cookieDomain[0] == '.') {
377
+ $cookieDomain = substr($cookieDomain, 1);
378
+ }
379
+
380
+ // Check for either exact match or suffix match
381
+ return ($cookieDomain == $host ||
382
+ preg_match("/\.$cookieDomain$/", $host));
383
+ }
384
+
385
+ /**
386
+ * Check if a cookie's path matches a URL path
387
+ *
388
+ * Used by Microsoft_Http_Cookie and Microsoft_Http_CookieJar for cookie matching
389
+ *
390
+ * @param string $cookiePath
391
+ * @param string $path
392
+ * @return boolean
393
+ */
394
+ public static function matchCookiePath($cookiePath, $path)
395
+ {
396
+ if (! $cookiePath) {
397
+ require_once 'Microsoft/Http/Exception.php';
398
+ throw new Microsoft_Http_Exception("\$cookiePath is expected to be a cookie path");
399
+ }
400
+
401
+ if (! $path) {
402
+ require_once 'Microsoft/Http/Exception.php';
403
+ throw new Microsoft_Http_Exception("\$path is expected to be a host name");
404
+ }
405
+
406
+ return (strpos($path, $cookiePath) === 0);
407
+ }
408
+ }
lib/Microsoft/Http/CookieJar.php ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Http
17
+ * @subpackage CookieJar
18
+ * @version $Id: CookieJar.php 17131 2009-07-26 10:03:39Z shahar $
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see Microsoft_Uri
25
+ */
26
+ require_once "Microsoft/Uri.php";
27
+ /**
28
+ * @see Microsoft_Http_Cookie
29
+ */
30
+ require_once "Microsoft/Http/Cookie.php";
31
+ /**
32
+ * @see Microsoft_Http_Response
33
+ */
34
+ require_once "Microsoft/Http/Response.php";
35
+
36
+ /**
37
+ * A Microsoft_Http_CookieJar object is designed to contain and maintain HTTP cookies, and should
38
+ * be used along with Microsoft_Http_Client in order to manage cookies across HTTP requests and
39
+ * responses.
40
+ *
41
+ * The class contains an array of Microsoft_Http_Cookie objects. Cookies can be added to the jar
42
+ * automatically from a request or manually. Then, the jar can find and return the cookies
43
+ * needed for a specific HTTP request.
44
+ *
45
+ * A special parameter can be passed to all methods of this class that return cookies: Cookies
46
+ * can be returned either in their native form (as Microsoft_Http_Cookie objects) or as strings -
47
+ * the later is suitable for sending as the value of the "Cookie" header in an HTTP request.
48
+ * You can also choose, when returning more than one cookie, whether to get an array of strings
49
+ * (by passing Microsoft_Http_CookieJar::COOKIE_STRING_ARRAY) or one unified string for all cookies
50
+ * (by passing Microsoft_Http_CookieJar::COOKIE_STRING_CONCAT).
51
+ *
52
+ * @link http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
53
+ *
54
+ * @category Microsoft
55
+ * @package Microsoft_Http
56
+ * @subpackage CookieJar
57
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
58
+ * @license http://framework.zend.com/license/new-bsd New BSD License
59
+ */
60
+ class Microsoft_Http_CookieJar implements Countable, IteratorAggregate
61
+ {
62
+ /**
63
+ * Return cookie(s) as a Microsoft_Http_Cookie object
64
+ *
65
+ */
66
+ const COOKIE_OBJECT = 0;
67
+
68
+ /**
69
+ * Return cookie(s) as a string (suitable for sending in an HTTP request)
70
+ *
71
+ */
72
+ const COOKIE_STRING_ARRAY = 1;
73
+
74
+ /**
75
+ * Return all cookies as one long string (suitable for sending in an HTTP request)
76
+ *
77
+ */
78
+ const COOKIE_STRING_CONCAT = 2;
79
+
80
+ /**
81
+ * Array storing cookies
82
+ *
83
+ * Cookies are stored according to domain and path:
84
+ * $cookies
85
+ * + www.mydomain.com
86
+ * + /
87
+ * - cookie1
88
+ * - cookie2
89
+ * + /somepath
90
+ * - othercookie
91
+ * + www.otherdomain.net
92
+ * + /
93
+ * - alsocookie
94
+ *
95
+ * @var array
96
+ */
97
+ protected $cookies = array();
98
+
99
+ /**
100
+ * The Microsoft_Http_Cookie array
101
+ *
102
+ * @var array
103
+ */
104
+ protected $_rawCookies = array();
105
+
106
+ /**
107
+ * Construct a new CookieJar object
108
+ *
109
+ */
110
+ public function __construct()
111
+ { }
112
+
113
+ /**
114
+ * Add a cookie to the jar. Cookie should be passed either as a Microsoft_Http_Cookie object
115
+ * or as a string - in which case an object is created from the string.
116
+ *
117
+ * @param Microsoft_Http_Cookie|string $cookie
118
+ * @param Microsoft_Uri_Http|string $ref_uri Optional reference URI (for domain, path, secure)
119
+ */
120
+ public function addCookie($cookie, $ref_uri = null)
121
+ {
122
+ if (is_string($cookie)) {
123
+ $cookie = Microsoft_Http_Cookie::fromString($cookie, $ref_uri);
124
+ }
125
+
126
+ if ($cookie instanceof Microsoft_Http_Cookie) {
127
+ $domain = $cookie->getDomain();
128
+ $path = $cookie->getPath();
129
+ if (! isset($this->cookies[$domain])) $this->cookies[$domain] = array();
130
+ if (! isset($this->cookies[$domain][$path])) $this->cookies[$domain][$path] = array();
131
+ $this->cookies[$domain][$path][$cookie->getName()] = $cookie;
132
+ $this->_rawCookies[] = $cookie;
133
+ } else {
134
+ require_once 'Microsoft/Http/Exception.php';
135
+ throw new Microsoft_Http_Exception('Supplient argument is not a valid cookie string or object');
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Parse an HTTP response, adding all the cookies set in that response
141
+ * to the cookie jar.
142
+ *
143
+ * @param Microsoft_Http_Response $response
144
+ * @param Microsoft_Uri_Http|string $ref_uri Requested URI
145
+ */
146
+ public function addCookiesFromResponse($response, $ref_uri)
147
+ {
148
+ if (! $response instanceof Microsoft_Http_Response) {
149
+ require_once 'Microsoft/Http/Exception.php';
150
+ throw new Microsoft_Http_Exception('$response is expected to be a Response object, ' .
151
+ gettype($response) . ' was passed');
152
+ }
153
+
154
+ $cookie_hdrs = $response->getHeader('Set-Cookie');
155
+
156
+ if (is_array($cookie_hdrs)) {
157
+ foreach ($cookie_hdrs as $cookie) {
158
+ $this->addCookie($cookie, $ref_uri);
159
+ }
160
+ } elseif (is_string($cookie_hdrs)) {
161
+ $this->addCookie($cookie_hdrs, $ref_uri);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Get all cookies in the cookie jar as an array
167
+ *
168
+ * @param int $ret_as Whether to return cookies as objects of Microsoft_Http_Cookie or as strings
169
+ * @return array|string
170
+ */
171
+ public function getAllCookies($ret_as = self::COOKIE_OBJECT)
172
+ {
173
+ $cookies = $this->_flattenCookiesArray($this->cookies, $ret_as);
174
+ return $cookies;
175
+ }
176
+
177
+ /**
178
+ * Return an array of all cookies matching a specific request according to the request URI,
179
+ * whether session cookies should be sent or not, and the time to consider as "now" when
180
+ * checking cookie expiry time.
181
+ *
182
+ * @param string|Microsoft_Uri_Http $uri URI to check against (secure, domain, path)
183
+ * @param boolean $matchSessionCookies Whether to send session cookies
184
+ * @param int $ret_as Whether to return cookies as objects of Microsoft_Http_Cookie or as strings
185
+ * @param int $now Override the current time when checking for expiry time
186
+ * @return array|string
187
+ */
188
+ public function getMatchingCookies($uri, $matchSessionCookies = true,
189
+ $ret_as = self::COOKIE_OBJECT, $now = null)
190
+ {
191
+ if (is_string($uri)) $uri = Microsoft_Uri::factory($uri);
192
+ if (! $uri instanceof Microsoft_Uri_Http) {
193
+ require_once 'Microsoft/Http/Exception.php';
194
+ throw new Microsoft_Http_Exception("Invalid URI string or object passed");
195
+ }
196
+
197
+ // First, reduce the array of cookies to only those matching domain and path
198
+ $cookies = $this->_matchDomain($uri->getHost());
199
+ $cookies = $this->_matchPath($cookies, $uri->getPath());
200
+ $cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT);
201
+
202
+ // Next, run Cookie->match on all cookies to check secure, time and session mathcing
203
+ $ret = array();
204
+ foreach ($cookies as $cookie)
205
+ if ($cookie->match($uri, $matchSessionCookies, $now))
206
+ $ret[] = $cookie;
207
+
208
+ // Now, use self::_flattenCookiesArray again - only to convert to the return format ;)
209
+ $ret = $this->_flattenCookiesArray($ret, $ret_as);
210
+
211
+ return $ret;
212
+ }
213
+
214
+ /**
215
+ * Get a specific cookie according to a URI and name
216
+ *
217
+ * @param Microsoft_Uri_Http|string $uri The uri (domain and path) to match
218
+ * @param string $cookie_name The cookie's name
219
+ * @param int $ret_as Whether to return cookies as objects of Microsoft_Http_Cookie or as strings
220
+ * @return Microsoft_Http_Cookie|string
221
+ */
222
+ public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT)
223
+ {
224
+ if (is_string($uri)) {
225
+ $uri = Microsoft_Uri::factory($uri);
226
+ }
227
+
228
+ if (! $uri instanceof Microsoft_Uri_Http) {
229
+ require_once 'Microsoft/Http/Exception.php';
230
+ throw new Microsoft_Http_Exception('Invalid URI specified');
231
+ }
232
+
233
+ // Get correct cookie path
234
+ $path = $uri->getPath();
235
+ $path = substr($path, 0, strrpos($path, '/'));
236
+ if (! $path) $path = '/';
237
+
238
+ if (isset($this->cookies[$uri->getHost()][$path][$cookie_name])) {
239
+ $cookie = $this->cookies[$uri->getHost()][$path][$cookie_name];
240
+
241
+ switch ($ret_as) {
242
+ case self::COOKIE_OBJECT:
243
+ return $cookie;
244
+ break;
245
+
246
+ case self::COOKIE_STRING_ARRAY:
247
+ case self::COOKIE_STRING_CONCAT:
248
+ return $cookie->__toString();
249
+ break;
250
+
251
+ default:
252
+ require_once 'Microsoft/Http/Exception.php';
253
+ throw new Microsoft_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}");
254
+ break;
255
+ }
256
+ } else {
257
+ return false;
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Helper function to recursivly flatten an array. Shoud be used when exporting the
263
+ * cookies array (or parts of it)
264
+ *
265
+ * @param Microsoft_Http_Cookie|array $ptr
266
+ * @param int $ret_as What value to return
267
+ * @return array|string
268
+ */
269
+ protected function _flattenCookiesArray($ptr, $ret_as = self::COOKIE_OBJECT) {
270
+ if (is_array($ptr)) {
271
+ $ret = ($ret_as == self::COOKIE_STRING_CONCAT ? '' : array());
272
+ foreach ($ptr as $item) {
273
+ if ($ret_as == self::COOKIE_STRING_CONCAT) {
274
+ $ret .= $this->_flattenCookiesArray($item, $ret_as);
275
+ } else {
276
+ $ret = array_merge($ret, $this->_flattenCookiesArray($item, $ret_as));
277
+ }
278
+ }
279
+ return $ret;
280
+ } elseif ($ptr instanceof Microsoft_Http_Cookie) {
281
+ switch ($ret_as) {
282
+ case self::COOKIE_STRING_ARRAY:
283
+ return array($ptr->__toString());
284
+ break;
285
+
286
+ case self::COOKIE_STRING_CONCAT:
287
+ return $ptr->__toString();
288
+ break;
289
+
290
+ case self::COOKIE_OBJECT:
291
+ default:
292
+ return array($ptr);
293
+ break;
294
+ }
295
+ }
296
+
297
+ return null;
298
+ }
299
+
300
+ /**
301
+ * Return a subset of the cookies array matching a specific domain
302
+ *
303
+ * @param string $domain
304
+ * @return array
305
+ */
306
+ protected function _matchDomain($domain)
307
+ {
308
+ $ret = array();
309
+
310
+ foreach (array_keys($this->cookies) as $cdom) {
311
+ if (Microsoft_Http_Cookie::matchCookieDomain($cdom, $domain)) {
312
+ $ret[$cdom] = $this->cookies[$cdom];
313
+ }
314
+ }
315
+
316
+ return $ret;
317
+ }
318
+
319
+ /**
320
+ * Return a subset of a domain-matching cookies that also match a specified path
321
+ *
322
+ * @param array $dom_array
323
+ * @param string $path
324
+ * @return array
325
+ */
326
+ protected function _matchPath($domains, $path)
327
+ {
328
+ $ret = array();
329
+
330
+ foreach ($domains as $dom => $paths_array) {
331
+ foreach (array_keys($paths_array) as $cpath) {
332
+ if (Microsoft_Http_Cookie::matchCookiePath($cpath, $path)) {
333
+ if (! isset($ret[$dom])) {
334
+ $ret[$dom] = array();
335
+ }
336
+
337
+ $ret[$dom][$cpath] = $paths_array[$cpath];
338
+ }
339
+ }
340
+ }
341
+
342
+ return $ret;
343
+ }
344
+
345
+ /**
346
+ * Create a new CookieJar object and automatically load into it all the
347
+ * cookies set in an Http_Response object. If $uri is set, it will be
348
+ * considered as the requested URI for setting default domain and path
349
+ * of the cookie.
350
+ *
351
+ * @param Microsoft_Http_Response $response HTTP Response object
352
+ * @param Microsoft_Uri_Http|string $uri The requested URI
353
+ * @return Microsoft_Http_CookieJar
354
+ * @todo Add the $uri functionality.
355
+ */
356
+ public static function fromResponse(Microsoft_Http_Response $response, $ref_uri)
357
+ {
358
+ $jar = new self();
359
+ $jar->addCookiesFromResponse($response, $ref_uri);
360
+ return $jar;
361
+ }
362
+
363
+ /**
364
+ * Required by Countable interface
365
+ *
366
+ * @return int
367
+ */
368
+ public function count()
369
+ {
370
+ return count($this->_rawCookies);
371
+ }
372
+
373
+ /**
374
+ * Required by IteratorAggregate interface
375
+ *
376
+ * @return ArrayIterator
377
+ */
378
+ public function getIterator()
379
+ {
380
+ return new ArrayIterator($this->_rawCookies);
381
+ }
382
+
383
+ /**
384
+ * Tells if the jar is empty of any cookie
385
+ *
386
+ * @return bool
387
+ */
388
+ public function isEmpty()
389
+ {
390
+ return count($this) == 0;
391
+ }
392
+
393
+ /**
394
+ * Empties the cookieJar of any cookie
395
+ *
396
+ * @return Microsoft_Http_CookieJar
397
+ */
398
+ public function reset()
399
+ {
400
+ $this->cookies = $this->_rawCookies = array();
401
+ return $this;
402
+ }
403
+ }
lib/Microsoft/Http/Exception.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_Http
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_Exception
38
+ */
39
+ require_once 'Microsoft/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_Http
44
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
45
+ * @license http://phpazure.codeplex.com/license
46
+ */
47
+ class Microsoft_Http_Exception extends Microsoft_Exception
48
+ {}
lib/Microsoft/Http/Response.php ADDED
@@ -0,0 +1,664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Response
19
+ * @version $Id: Response.php 35835 2009-12-17 09:40:36Z unknown $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * Microsoft_Http_Response represents an HTTP 1.0 / 1.1 response message. It
26
+ * includes easy access to all the response's different elemts, as well as some
27
+ * convenience methods for parsing and validating HTTP responses.
28
+ *
29
+ * @package Microsoft_Http
30
+ * @subpackage Response
31
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Microsoft_Http_Response
35
+ {
36
+ /**
37
+ * List of all known HTTP response codes - used by responseCodeAsText() to
38
+ * translate numeric codes to messages.
39
+ *
40
+ * @var array
41
+ */
42
+ protected static $messages = array(
43
+ // Informational 1xx
44
+ 100 => 'Continue',
45
+ 101 => 'Switching Protocols',
46
+
47
+ // Success 2xx
48
+ 200 => 'OK',
49
+ 201 => 'Created',
50
+ 202 => 'Accepted',
51
+ 203 => 'Non-Authoritative Information',
52
+ 204 => 'No Content',
53
+ 205 => 'Reset Content',
54
+ 206 => 'Partial Content',
55
+
56
+ // Redirection 3xx
57
+ 300 => 'Multiple Choices',
58
+ 301 => 'Moved Permanently',
59
+ 302 => 'Found', // 1.1
60
+ 303 => 'See Other',
61
+ 304 => 'Not Modified',
62
+ 305 => 'Use Proxy',
63
+ // 306 is deprecated but reserved
64
+ 307 => 'Temporary Redirect',
65
+
66
+ // Client Error 4xx
67
+ 400 => 'Bad Request',
68
+ 401 => 'Unauthorized',
69
+ 402 => 'Payment Required',
70
+ 403 => 'Forbidden',
71
+ 404 => 'Not Found',
72
+ 405 => 'Method Not Allowed',
73
+ 406 => 'Not Acceptable',
74
+ 407 => 'Proxy Authentication Required',
75
+ 408 => 'Request Timeout',
76
+ 409 => 'Conflict',
77
+ 410 => 'Gone',
78
+ 411 => 'Length Required',
79
+ 412 => 'Precondition Failed',
80
+ 413 => 'Request Entity Too Large',
81
+ 414 => 'Request-URI Too Long',
82
+ 415 => 'Unsupported Media Type',
83
+ 416 => 'Requested Range Not Satisfiable',
84
+ 417 => 'Expectation Failed',
85
+
86
+ // Server Error 5xx
87
+ 500 => 'Internal Server Error',
88
+ 501 => 'Not Implemented',
89
+ 502 => 'Bad Gateway',
90
+ 503 => 'Service Unavailable',
91
+ 504 => 'Gateway Timeout',
92
+ 505 => 'HTTP Version Not Supported',
93
+ 509 => 'Bandwidth Limit Exceeded'
94
+ );
95
+
96
+ /**
97
+ * The HTTP version (1.0, 1.1)
98
+ *
99
+ * @var string
100
+ */
101
+ protected $version;
102
+
103
+ /**
104
+ * The HTTP response code
105
+ *
106
+ * @var int
107
+ */
108
+ protected $code;
109
+
110
+ /**
111
+ * The HTTP response code as string
112
+ * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500)
113
+ *
114
+ * @var string
115
+ */
116
+ protected $message;
117
+
118
+ /**
119
+ * The HTTP response headers array
120
+ *
121
+ * @var array
122
+ */
123
+ protected $headers = array();
124
+
125
+ /**
126
+ * The HTTP response body
127
+ *
128
+ * @var string
129
+ */
130
+ protected $body;
131
+
132
+ /**
133
+ * HTTP response constructor
134
+ *
135
+ * In most cases, you would use Microsoft_Http_Response::fromString to parse an HTTP
136
+ * response string and create a new Microsoft_Http_Response object.
137
+ *
138
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
139
+ * headers and will throw an exception if the passed values do not form a valid HTTP
140
+ * responses.
141
+ *
142
+ * If no message is passed, the message will be guessed according to the response code.
143
+ *
144
+ * @param int $code Response code (200, 404, ...)
145
+ * @param array $headers Headers array
146
+ * @param string $body Response body
147
+ * @param string $version HTTP version
148
+ * @param string $message Response code as text
149
+ * @throws Microsoft_Http_Exception
150
+ */
151
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
152
+ {
153
+ // Make sure the response code is valid and set it
154
+ if (self::responseCodeAsText($code) === null) {
155
+ require_once 'Microsoft/Http/Exception.php';
156
+ throw new Microsoft_Http_Exception("{$code} is not a valid HTTP response code");
157
+ }
158
+
159
+ $this->code = $code;
160
+
161
+ // Make sure we got valid headers and set them
162
+ if (! is_array($headers)) {
163
+ require_once 'Microsoft/Http/Exception.php';
164
+ throw new Microsoft_Http_Exception('No valid headers were passed');
165
+ }
166
+
167
+ foreach ($headers as $name => $value) {
168
+ if (is_int($name))
169
+ list($name, $value) = explode(": ", $value, 1);
170
+
171
+ $this->headers[ucwords(strtolower($name))] = $value;
172
+ }
173
+
174
+ // Set the body
175
+ $this->body = $body;
176
+
177
+ // Set the HTTP version
178
+ if (! preg_match('|^\d\.\d$|', $version)) {
179
+ require_once 'Microsoft/Http/Exception.php';
180
+ throw new Microsoft_Http_Exception("Invalid HTTP response version: $version");
181
+ }
182
+
183
+ $this->version = $version;
184
+
185
+ // If we got the response message, set it. Else, set it according to
186
+ // the response code
187
+ if (is_string($message)) {
188
+ $this->message = $message;
189
+ } else {
190
+ $this->message = self::responseCodeAsText($code);
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Check whether the response is an error
196
+ *
197
+ * @return boolean
198
+ */
199
+ public function isError()
200
+ {
201
+ $restype = floor($this->code / 100);
202
+ if ($restype == 4 || $restype == 5) {
203
+ return true;
204
+ }
205
+
206
+ return false;
207
+ }
208
+
209
+ /**
210
+ * Check whether the response in successful
211
+ *
212
+ * @return boolean
213
+ */
214
+ public function isSuccessful()
215
+ {
216
+ $restype = floor($this->code / 100);
217
+ if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ???
218
+ return true;
219
+ }
220
+
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * Check whether the response is a redirection
226
+ *
227
+ * @return boolean
228
+ */
229
+ public function isRedirect()
230
+ {
231
+ $restype = floor($this->code / 100);
232
+ if ($restype == 3) {
233
+ return true;
234
+ }
235
+
236
+ return false;
237
+ }
238
+
239
+ /**
240
+ * Get the response body as string
241
+ *
242
+ * This method returns the body of the HTTP response (the content), as it
243
+ * should be in it's readable version - that is, after decoding it (if it
244
+ * was decoded), deflating it (if it was gzip compressed), etc.
245
+ *
246
+ * If you want to get the raw body (as transfered on wire) use
247
+ * $this->getRawBody() instead.
248
+ *
249
+ * @return string
250
+ */
251
+ public function getBody()
252
+ {
253
+ $body = '';
254
+
255
+ // Decode the body if it was transfer-encoded
256
+ switch (strtolower($this->getHeader('transfer-encoding'))) {
257
+
258
+ // Handle chunked body
259
+ case 'chunked':
260
+ $body = self::decodeChunkedBody($this->body);
261
+ break;
262
+
263
+ // No transfer encoding, or unknown encoding extension:
264
+ // return body as is
265
+ default:
266
+ $body = $this->body;
267
+ break;
268
+ }
269
+
270
+ // Decode any content-encoding (gzip or deflate) if needed
271
+ switch (strtolower($this->getHeader('content-encoding'))) {
272
+
273
+ // Handle gzip encoding
274
+ case 'gzip':
275
+ $body = self::decodeGzip($body);
276
+ break;
277
+
278
+ // Handle deflate encoding
279
+ case 'deflate':
280
+ $body = self::decodeDeflate($body);
281
+ break;
282
+
283
+ default:
284
+ break;
285
+ }
286
+
287
+ return $body;
288
+ }
289
+
290
+ /**
291
+ * Get the raw response body (as transfered "on wire") as string
292
+ *
293
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
294
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
295
+ *
296
+ * @return string
297
+ */
298
+ public function getRawBody()
299
+ {
300
+ return $this->body;
301
+ }
302
+
303
+ /**
304
+ * Get the HTTP version of the response
305
+ *
306
+ * @return string
307
+ */
308
+ public function getVersion()
309
+ {
310
+ return $this->version;
311
+ }
312
+
313
+ /**
314
+ * Get the HTTP response status code
315
+ *
316
+ * @return int
317
+ */
318
+ public function getStatus()
319
+ {
320
+ return $this->code;
321
+ }
322
+
323
+ /**
324
+ * Return a message describing the HTTP response code
325
+ * (Eg. "OK", "Not Found", "Moved Permanently")
326
+ *
327
+ * @return string
328
+ */
329
+ public function getMessage()
330
+ {
331
+ return $this->message;
332
+ }
333
+
334
+ /**
335
+ * Get the response headers
336
+ *
337
+ * @return array
338
+ */
339
+ public function getHeaders()
340
+ {
341
+ return $this->headers;
342
+ }
343
+
344
+ /**
345
+ * Get a specific header as string, or null if it is not set
346
+ *
347
+ * @param string$header
348
+ * @return string|array|null
349
+ */
350
+ public function getHeader($header)
351
+ {
352
+ $header = ucwords(strtolower($header));
353
+ if (! is_string($header) || ! isset($this->headers[$header])) return null;
354
+
355
+ return $this->headers[$header];
356
+ }
357
+
358
+ /**
359
+ * Get all headers as string
360
+ *
361
+ * @param boolean $status_line Whether to return the first status line (IE "HTTP 200 OK")
362
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
363
+ * @return string
364
+ */
365
+ public function getHeadersAsString($status_line = true, $br = "\n")
366
+ {
367
+ $str = '';
368
+
369
+ if ($status_line) {
370
+ $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}";
371
+ }
372
+
373
+ // Iterate over the headers and stringify them
374
+ foreach ($this->headers as $name => $value)
375
+ {
376
+ if (is_string($value))
377
+ $str .= "{$name}: {$value}{$br}";
378
+
379
+ elseif (is_array($value)) {
380
+ foreach ($value as $subval) {
381
+ $str .= "{$name}: {$subval}{$br}";
382
+ }
383
+ }
384
+ }
385
+
386
+ return $str;
387
+ }
388
+
389
+ /**
390
+ * Get the entire response as string
391
+ *
392
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
393
+ * @return string
394
+ */
395
+ public function asString($br = "\n")
396
+ {
397
+ return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody();
398
+ }
399
+
400
+ /**
401
+ * Implements magic __toString()
402
+ *
403
+ * @return string
404
+ */
405
+ public function __toString()
406
+ {
407
+ return $this->asString();
408
+ }
409
+
410
+ /**
411
+ * A convenience function that returns a text representation of
412
+ * HTTP response codes. Returns 'Unknown' for unknown codes.
413
+ * Returns array of all codes, if $code is not specified.
414
+ *
415
+ * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown')
416
+ * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference
417
+ *
418
+ * @param int $code HTTP response code
419
+ * @param boolean $http11 Use HTTP version 1.1
420
+ * @return string
421
+ */
422
+ public static function responseCodeAsText($code = null, $http11 = true)
423
+ {
424
+ $messages = self::$messages;
425
+ if (! $http11) $messages[302] = 'Moved Temporarily';
426
+
427
+ if ($code === null) {
428
+ return $messages;
429
+ } elseif (isset($messages[$code])) {
430
+ return $messages[$code];
431
+ } else {
432
+ return 'Unknown';
433
+ }
434
+ }
435
+
436
+ /**
437
+ * Extract the response code from a response string
438
+ *
439
+ * @param string $response_str
440
+ * @return int
441
+ */
442
+ public static function extractCode($response_str)
443
+ {
444
+ preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
445
+
446
+ if (isset($m[1])) {
447
+ return (int) $m[1];
448
+ } else {
449
+ return false;
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Extract the HTTP message from a response
455
+ *
456
+ * @param string $response_str
457
+ * @return string
458
+ */
459
+ public static function extractMessage($response_str)
460
+ {
461
+ preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m);
462
+
463
+ if (isset($m[1])) {
464
+ return $m[1];
465
+ } else {
466
+ return false;
467
+ }
468
+ }
469
+
470
+ /**
471
+ * Extract the HTTP version from a response
472
+ *
473
+ * @param string $response_str
474
+ * @return string
475
+ */
476
+ public static function extractVersion($response_str)
477
+ {
478
+ preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m);
479
+
480
+ if (isset($m[1])) {
481
+ return $m[1];
482
+ } else {
483
+ return false;
484
+ }
485
+ }
486
+
487
+ /**
488
+ * Extract the headers from a response string
489
+ *
490
+ * @param string $response_str
491
+ * @return array
492
+ */
493
+ public static function extractHeaders($response_str)
494
+ {
495
+ $headers = array();
496
+
497
+ // First, split body and headers
498
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
499
+ if (! $parts[0]) return $headers;
500
+
501
+ // Split headers part to lines
502
+ $lines = explode("\n", $parts[0]);
503
+ unset($parts);
504
+ $last_header = null;
505
+
506
+ foreach($lines as $line) {
507
+ $line = trim($line, "\r\n");
508
+ if ($line == "") break;
509
+
510
+ if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) {
511
+ unset($last_header);
512
+ $h_name = strtolower($m[1]);
513
+ $h_value = $m[2];
514
+
515
+ if (isset($headers[$h_name])) {
516
+ if (! is_array($headers[$h_name])) {
517
+ $headers[$h_name] = array($headers[$h_name]);
518
+ }
519
+
520
+ $headers[$h_name][] = $h_value;
521
+ } else {
522
+ $headers[$h_name] = $h_value;
523
+ }
524
+ $last_header = $h_name;
525
+ } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) {
526
+ if (is_array($headers[$last_header])) {
527
+ end($headers[$last_header]);
528
+ $last_header_key = key($headers[$last_header]);
529
+ $headers[$last_header][$last_header_key] .= $m[1];
530
+ } else {
531
+ $headers[$last_header] .= $m[1];
532
+ }
533
+ }
534
+ }
535
+
536
+ return $headers;
537
+ }
538
+
539
+ /**
540
+ * Extract the body from a response string
541
+ *
542
+ * @param string $response_str
543
+ * @return string
544
+ */
545
+ public static function extractBody($response_str)
546
+ {
547
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
548
+ if (isset($parts[1])) {
549
+ return $parts[1];
550
+ }
551
+ return '';
552
+ }
553
+
554
+ /**
555
+ * Decode a "chunked" transfer-encoded body and return the decoded text
556
+ *
557
+ * @param string $body
558
+ * @return string
559
+ */
560
+ public static function decodeChunkedBody($body)
561
+ {
562
+ $decBody = '';
563
+
564
+ // If mbstring overloads substr and strlen functions, we have to
565
+ // override it's internal encoding
566
+ if (function_exists('mb_internal_encoding') &&
567
+ ((int) ini_get('mbstring.func_overload')) & 2) {
568
+
569
+ $mbIntEnc = mb_internal_encoding();
570
+ mb_internal_encoding('ASCII');
571
+ }
572
+
573
+ while (trim($body)) {
574
+ if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
575
+ require_once 'Microsoft/Http/Exception.php';
576
+ throw new Microsoft_Http_Exception("Error parsing body - doesn't seem to be a chunked message");
577
+ }
578
+
579
+ $length = hexdec(trim($m[1]));
580
+ $cut = strlen($m[0]);
581
+ $decBody .= substr($body, $cut, $length);
582
+ $body = substr($body, $cut + $length + 2);
583
+ }
584
+
585
+ if (isset($mbIntEnc)) {
586
+ mb_internal_encoding($mbIntEnc);
587
+ }
588
+
589
+ return $decBody;
590
+ }
591
+
592
+ /**
593
+ * Decode a gzip encoded message (when Content-encoding = gzip)
594
+ *
595
+ * Currently requires PHP with zlib support
596
+ *
597
+ * @param string $body
598
+ * @return string
599
+ */
600
+ public static function decodeGzip($body)
601
+ {
602
+ if (! function_exists('gzinflate')) {
603
+ require_once 'Microsoft/Http/Exception.php';
604
+ throw new Microsoft_Http_Exception(
605
+ 'zlib extension is required in order to decode "gzip" encoding'
606
+ );
607
+ }
608
+
609
+ return gzinflate(substr($body, 10));
610
+ }
611
+
612
+ /**
613
+ * Decode a zlib deflated message (when Content-encoding = deflate)
614
+ *
615
+ * Currently requires PHP with zlib support
616
+ *
617
+ * @param string $body
618
+ * @return string
619
+ */
620
+ public static function decodeDeflate($body)
621
+ {
622
+ if (! function_exists('gzuncompress')) {
623
+ require_once 'Microsoft/Http/Exception.php';
624
+ throw new Microsoft_Http_Exception(
625
+ 'zlib extension is required in order to decode "deflate" encoding'
626
+ );
627
+ }
628
+
629
+ /**
630
+ * Some servers (IIS ?) send a broken deflate response, without the
631
+ * RFC-required zlib header.
632
+ *
633
+ * We try to detect the zlib header, and if it does not exsit we
634
+ * teat the body is plain DEFLATE content.
635
+ *
636
+ * This method was adapted from PEAR HTTP_Request2 by (c) Alexey Borzov
637
+ *
638
+ * @link http://framework.zend.com/issues/browse/ZF-6040
639
+ */
640
+ $zlibHeader = unpack('n', substr($body, 0, 2));
641
+ if ($zlibHeader[1] % 31 == 0) {
642
+ return gzuncompress($body);
643
+ } else {
644
+ return gzinflate($body);
645
+ }
646
+ }
647
+
648
+ /**
649
+ * Create a new Microsoft_Http_Response object from a string
650
+ *
651
+ * @param string $response_str
652
+ * @return Microsoft_Http_Response
653
+ */
654
+ public static function fromString($response_str)
655
+ {
656
+ $code = self::extractCode($response_str);
657
+ $headers = self::extractHeaders($response_str);
658
+ $body = self::extractBody($response_str);
659
+ $version = self::extractVersion($response_str);
660
+ $message = self::extractMessage($response_str);
661
+
662
+ return new Microsoft_Http_Response($code, $headers, $body, $version, $message);
663
+ }
664
+ }
lib/Microsoft/Http/Response/Stream.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Response
19
+ * @version $Id: Response.php 17131 2009-07-26 10:03:39Z shahar $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * Microsoft_Http_Response represents an HTTP 1.0 / 1.1 response message. It
26
+ * includes easy access to all the response's different elemts, as well as some
27
+ * convenience methods for parsing and validating HTTP responses.
28
+ *
29
+ * @package Microsoft_Http
30
+ * @subpackage Response
31
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Microsoft_Http_Response_Stream extends Microsoft_Http_Response
35
+ {
36
+ /**
37
+ * Response as stream
38
+ *
39
+ * @var resource
40
+ */
41
+ protected $stream;
42
+
43
+ /**
44
+ * The name of the file containing the stream
45
+ *
46
+ * Will be empty if stream is not file-based.
47
+ *
48
+ * @var string
49
+ */
50
+ protected $stream_name;
51
+
52
+ /**
53
+ * Should we clean up the stream file when this response is closed?
54
+ *
55
+ * @var boolean
56
+ */
57
+ protected $_cleanup;
58
+
59
+ /**
60
+ * Get the response as stream
61
+ *
62
+ * @return resourse
63
+ */
64
+ public function getStream()
65
+ {
66
+ return $this->stream;
67
+ }
68
+
69
+ /**
70
+ * Set the response stream
71
+ *
72
+ * @param resourse $stream
73
+ * @return Microsoft_Http_Response_Stream
74
+ */
75
+ public function setStream($stream)
76
+ {
77
+ $this->stream = $stream;
78
+ return $this;
79
+ }
80
+
81
+ /**
82
+ * Get the cleanup trigger
83
+ *
84
+ * @return boolean
85
+ */
86
+ public function getCleanup() {
87
+ return $this->_cleanup;
88
+ }
89
+
90
+ /**
91
+ * Set the cleanup trigger
92
+ *
93
+ * @param $cleanup Set cleanup trigger
94
+ */
95
+ public function setCleanup($cleanup = true) {
96
+ $this->_cleanup = $cleanup;
97
+ }
98
+
99
+ /**
100
+ * Get file name associated with the stream
101
+ *
102
+ * @return string
103
+ */
104
+ public function getStreamName() {
105
+ return $this->stream_name;
106
+ }
107
+
108
+ /**
109
+ * Set file name associated with the stream
110
+ *
111
+ * @param string $stream_name Name to set
112
+ * @return Microsoft_Http_Response_Stream
113
+ */
114
+ public function setStreamName($stream_name) {
115
+ $this->stream_name = $stream_name;
116
+ return $this;
117
+ }
118
+
119
+
120
+ /**
121
+ * HTTP response constructor
122
+ *
123
+ * In most cases, you would use Microsoft_Http_Response::fromString to parse an HTTP
124
+ * response string and create a new Microsoft_Http_Response object.
125
+ *
126
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
127
+ * headers and will throw an exception if the passed values do not form a valid HTTP
128
+ * responses.
129
+ *
130
+ * If no message is passed, the message will be guessed according to the response code.
131
+ *
132
+ * @param int $code Response code (200, 404, ...)
133
+ * @param array $headers Headers array
134
+ * @param string $body Response body
135
+ * @param string $version HTTP version
136
+ * @param string $message Response code as text
137
+ * @throws Microsoft_Http_Exception
138
+ */
139
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
140
+ {
141
+
142
+ if(is_resource($body)) {
143
+ $this->setStream($body);
144
+ $body = '';
145
+ }
146
+ parent::__construct($code, $headers, $body, $version, $message);
147
+ }
148
+
149
+ /**
150
+ * Create a new Microsoft_Http_Response_Stream object from a string
151
+ *
152
+ * @param string $response_str
153
+ * @param resource $stream
154
+ * @return Microsoft_Http_Response_Stream
155
+ */
156
+ public static function fromStream($response_str, $stream)
157
+ {
158
+ $code = self::extractCode($response_str);
159
+ $headers = self::extractHeaders($response_str);
160
+ $version = self::extractVersion($response_str);
161
+ $message = self::extractMessage($response_str);
162
+
163
+ return new self($code, $headers, $stream, $version, $message);
164
+ }
165
+
166
+ /**
167
+ * Get the response body as string
168
+ *
169
+ * This method returns the body of the HTTP response (the content), as it
170
+ * should be in it's readable version - that is, after decoding it (if it
171
+ * was decoded), deflating it (if it was gzip compressed), etc.
172
+ *
173
+ * If you want to get the raw body (as transfered on wire) use
174
+ * $this->getRawBody() instead.
175
+ *
176
+ * @return string
177
+ */
178
+ public function getBody()
179
+ {
180
+ if($this->stream != null) {
181
+ $this->readStream();
182
+ }
183
+ return parent::getBody();
184
+ }
185
+
186
+ /**
187
+ * Get the raw response body (as transfered "on wire") as string
188
+ *
189
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
190
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
191
+ *
192
+ * @return string
193
+ */
194
+ public function getRawBody()
195
+ {
196
+ if($this->stream) {
197
+ $this->readStream();
198
+ }
199
+ return $this->body;
200
+ }
201
+
202
+ /**
203
+ * Read stream content and return it as string
204
+ *
205
+ * Function reads the remainder of the body from the stream and closes the stream.
206
+ *
207
+ * @return string
208
+ */
209
+ protected function readStream()
210
+ {
211
+ if(!is_resource($this->stream)) {
212
+ return '';
213
+ }
214
+
215
+ if(isset($headers['content-length'])) {
216
+ $this->body = stream_get_contents($this->stream, $headers['content-length']);
217
+ } else {
218
+ $this->body = stream_get_contents($this->stream);
219
+ }
220
+ fclose($this->stream);
221
+ $this->stream = null;
222
+ }
223
+
224
+ public function __destruct()
225
+ {
226
+ if(is_resource($this->stream)) {
227
+ fclose($this->stream);
228
+ $this->stream = null;
229
+ }
230
+ if($this->_cleanup) {
231
+ @unlink($this->stream_name);
232
+ }
233
+ }
234
+
235
+ }
lib/Microsoft/Uri.php ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Uri
17
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Uri.php 18950 2009-11-12 15:37:56Z alexander $
20
+ */
21
+
22
+ /**
23
+ * Abstract class for all Microsoft_Uri handlers
24
+ *
25
+ * @category Microsoft
26
+ * @package Microsoft_Uri
27
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ abstract class Microsoft_Uri
31
+ {
32
+ /**
33
+ * Scheme of this URI (http, ftp, etc.)
34
+ *
35
+ * @var string
36
+ */
37
+ protected $_scheme = '';
38
+
39
+ /**
40
+ * Global configuration array
41
+ *
42
+ * @var array
43
+ */
44
+ static protected $_config = array(
45
+ 'allow_unwise' => false
46
+ );
47
+
48
+ /**
49
+ * Return a string representation of this URI.
50
+ *
51
+ * @see getUri()
52
+ * @return string
53
+ */
54
+ public function __toString()
55
+ {
56
+ return $this->getUri();
57
+ }
58
+
59
+ /**
60
+ * Convenience function, checks that a $uri string is well-formed
61
+ * by validating it but not returning an object. Returns TRUE if
62
+ * $uri is a well-formed URI, or FALSE otherwise.
63
+ *
64
+ * @param string $uri The URI to check
65
+ * @return boolean
66
+ */
67
+ public static function check($uri)
68
+ {
69
+ try {
70
+ $uri = self::factory($uri);
71
+ } catch (Exception $e) {
72
+ return false;
73
+ }
74
+
75
+ return $uri->valid();
76
+ }
77
+
78
+ /**
79
+ * Create a new Microsoft_Uri object for a URI. If building a new URI, then $uri should contain
80
+ * only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI.
81
+ *
82
+ * @param string $uri The URI form which a Microsoft_Uri instance is created
83
+ * @throws Microsoft_Uri_Exception When an empty string was supplied for the scheme
84
+ * @throws Microsoft_Uri_Exception When an illegal scheme is supplied
85
+ * @throws Microsoft_Uri_Exception When the scheme is not supported
86
+ * @return Microsoft_Uri
87
+ * @link http://www.faqs.org/rfcs/rfc2396.html
88
+ */
89
+ public static function factory($uri = 'http')
90
+ {
91
+ // Separate the scheme from the scheme-specific parts
92
+ $uri = explode(':', $uri, 2);
93
+ $scheme = strtolower($uri[0]);
94
+ $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
95
+
96
+ if (strlen($scheme) === 0) {
97
+ require_once 'Microsoft/Uri/Exception.php';
98
+ throw new Microsoft_Uri_Exception('An empty string was supplied for the scheme');
99
+ }
100
+
101
+ // Security check: $scheme is used to load a class file, so only alphanumerics are allowed.
102
+ if (ctype_alnum($scheme) === false) {
103
+ require_once 'Microsoft/Uri/Exception.php';
104
+ throw new Microsoft_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted');
105
+ }
106
+
107
+ /**
108
+ * Create a new Microsoft_Uri object for the $uri. If a subclass of Microsoft_Uri exists for the
109
+ * scheme, return an instance of that class. Otherwise, a Microsoft_Uri_Exception is thrown.
110
+ */
111
+ switch ($scheme) {
112
+ case 'http':
113
+ // Break intentionally omitted
114
+ case 'https':
115
+ $className = 'Microsoft_Uri_Http';
116
+ break;
117
+
118
+ case 'mailto':
119
+ // TODO
120
+ default:
121
+ require_once 'Microsoft/Uri/Exception.php';
122
+ throw new Microsoft_Uri_Exception("Scheme \"$scheme\" is not supported");
123
+ break;
124
+ }
125
+
126
+ if (!class_exists($className)) {
127
+ require_once str_replace('_', '/', $className) . '.php';
128
+ }
129
+ $schemeHandler = new $className($scheme, $schemeSpecific);
130
+
131
+ return $schemeHandler;
132
+ }
133
+
134
+ /**
135
+ * Get the URI's scheme
136
+ *
137
+ * @return string|false Scheme or false if no scheme is set.
138
+ */
139
+ public function getScheme()
140
+ {
141
+ if (empty($this->_scheme) === false) {
142
+ return $this->_scheme;
143
+ } else {
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Set global configuration options
150
+ *
151
+ * @param Microsoft_Config|array $config
152
+ */
153
+ static public function setConfig($config)
154
+ {
155
+ if ($config instanceof Microsoft_Config) {
156
+ $config = $config->toArray();
157
+ } elseif (!is_array($config)) {
158
+ throw new Microsoft_Uri_Exception("Config must be an array or an instance of Microsoft_Config.");
159
+ }
160
+
161
+ foreach ($config as $k => $v) {
162
+ self::$_config[$k] = $v;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Microsoft_Uri and its subclasses cannot be instantiated directly.
168
+ * Use Microsoft_Uri::factory() to return a new Microsoft_Uri object.
169
+ *
170
+ * @param string $scheme The scheme of the URI
171
+ * @param string $schemeSpecific The scheme-specific part of the URI
172
+ */
173
+ abstract protected function __construct($scheme, $schemeSpecific = '');
174
+
175
+ /**
176
+ * Return a string representation of this URI.
177
+ *
178
+ * @return string
179
+ */
180
+ abstract public function getUri();
181
+
182
+ /**
183
+ * Returns TRUE if this URI is valid, or FALSE otherwise.
184
+ *
185
+ * @return boolean
186
+ */
187
+ abstract public function valid();
188
+ }
lib/Microsoft/Uri/Exception.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Uri
17
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Exception.php 16208 2009-06-21 19:19:26Z thomas $
20
+ */
21
+
22
+ /**
23
+ * @see Microsoft_Exception
24
+ */
25
+ require_once 'Microsoft/Exception.php';
26
+
27
+ /**
28
+ * Exceptions for Microsoft_Uri
29
+ *
30
+ * @category Microsoft
31
+ * @package Microsoft_Uri
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Microsoft_Uri_Exception extends Microsoft_Exception
36
+ {
37
+ }
lib/Microsoft/Uri/Http.php ADDED
@@ -0,0 +1,761 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Uri
17
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Http.php 19041 2009-11-19 15:19:07Z sgehrig $
20
+ */
21
+
22
+ /**
23
+ * @see Microsoft_Uri
24
+ */
25
+ require_once 'Microsoft/Uri.php';
26
+
27
+ /**
28
+ * HTTP(S) URI handler
29
+ *
30
+ * @category Microsoft
31
+ * @package Microsoft_Uri
32
+ * @uses Microsoft_Uri
33
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Microsoft_Uri_Http extends Microsoft_Uri
37
+ {
38
+ /**
39
+ * Character classes for validation regular expressions
40
+ */
41
+ const CHAR_ALNUM = 'A-Za-z0-9';
42
+ const CHAR_MARK = '-_.!~*\'()\[\]';
43
+ const CHAR_RESERVED = ';\/?:@&=+$,';
44
+ const CHAR_SEGMENT = ':@&=+$,;';
45
+ const CHAR_UNWISE = '{}|\\\\^`';
46
+
47
+ /**
48
+ * HTTP username
49
+ *
50
+ * @var string
51
+ */
52
+ protected $_username = '';
53
+
54
+ /**
55
+ * HTTP password
56
+ *
57
+ * @var string
58
+ */
59
+ protected $_password = '';
60
+
61
+ /**
62
+ * HTTP host
63
+ *
64
+ * @var string
65
+ */
66
+ protected $_host = '';
67
+
68
+ /**
69
+ * HTTP post
70
+ *
71
+ * @var string
72
+ */
73
+ protected $_port = '';
74
+
75
+ /**
76
+ * HTTP part
77
+ *
78
+ * @var string
79
+ */
80
+ protected $_path = '';
81
+
82
+ /**
83
+ * HTTP query
84
+ *
85
+ * @var string
86
+ */
87
+ protected $_query = '';
88
+
89
+ /**
90
+ * HTTP fragment
91
+ *
92
+ * @var string
93
+ */
94
+ protected $_fragment = '';
95
+
96
+ /**
97
+ * Regular expression grammar rules for validation; values added by constructor
98
+ *
99
+ * @var array
100
+ */
101
+ protected $_regex = array();
102
+
103
+ /**
104
+ * Constructor accepts a string $scheme (e.g., http, https) and a scheme-specific part of the URI
105
+ * (e.g., example.com/path/to/resource?query=param#fragment)
106
+ *
107
+ * @param string $scheme The scheme of the URI
108
+ * @param string $schemeSpecific The scheme-specific part of the URI
109
+ * @throws Microsoft_Uri_Exception When the URI is not valid
110
+ */
111
+ protected function __construct($scheme, $schemeSpecific = '')
112
+ {
113
+ // Set the scheme
114
+ $this->_scheme = $scheme;
115
+
116
+ // Set up grammar rules for validation via regular expressions. These
117
+ // are to be used with slash-delimited regular expression strings.
118
+
119
+ // Escaped special characters (eg. '%25' for '%')
120
+ $this->_regex['escaped'] = '%[[:xdigit:]]{2}';
121
+
122
+ // Unreserved characters
123
+ $this->_regex['unreserved'] = '[' . self::CHAR_ALNUM . self::CHAR_MARK . ']';
124
+
125
+ // Segment can use escaped, unreserved or a set of additional chars
126
+ $this->_regex['segment'] = '(?:' . $this->_regex['escaped'] . '|[' .
127
+ self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_SEGMENT . '])*';
128
+
129
+ // Path can be a series of segmets char strings seperated by '/'
130
+ $this->_regex['path'] = '(?:\/(?:' . $this->_regex['segment'] . ')?)+';
131
+
132
+ // URI characters can be escaped, alphanumeric, mark or reserved chars
133
+ $this->_regex['uric'] = '(?:' . $this->_regex['escaped'] . '|[' .
134
+ self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_RESERVED .
135
+
136
+ // If unwise chars are allowed, add them to the URI chars class
137
+ (self::$_config['allow_unwise'] ? self::CHAR_UNWISE : '') . '])';
138
+
139
+ // If no scheme-specific part was supplied, the user intends to create
140
+ // a new URI with this object. No further parsing is required.
141
+ if (strlen($schemeSpecific) === 0) {
142
+ return;
143
+ }
144
+
145
+ // Parse the scheme-specific URI parts into the instance variables.
146
+ $this->_parseUri($schemeSpecific);
147
+
148
+ // Validate the URI
149
+ if ($this->valid() === false) {
150
+ require_once 'Microsoft/Uri/Exception.php';
151
+ throw new Microsoft_Uri_Exception('Invalid URI supplied');
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Creates a Microsoft_Uri_Http from the given string
157
+ *
158
+ * @param string $uri String to create URI from, must start with
159
+ * 'http://' or 'https://'
160
+ * @throws InvalidArgumentException When the given $uri is not a string or
161
+ * does not start with http:// or https://
162
+ * @throws Microsoft_Uri_Exception When the given $uri is invalid
163
+ * @return Microsoft_Uri_Http
164
+ */
165
+ public static function fromString($uri)
166
+ {
167
+ if (is_string($uri) === false) {
168
+ require_once 'Microsoft/Uri/Exception.php';
169
+ throw new Microsoft_Uri_Exception('$uri is not a string');
170
+ }
171
+
172
+ $uri = explode(':', $uri, 2);
173
+ $scheme = strtolower($uri[0]);
174
+ $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
175
+
176
+ if (in_array($scheme, array('http', 'https')) === false) {
177
+ require_once 'Microsoft/Uri/Exception.php';
178
+ throw new Microsoft_Uri_Exception("Invalid scheme: '$scheme'");
179
+ }
180
+
181
+ $schemeHandler = new Microsoft_Uri_Http($scheme, $schemeSpecific);
182
+ return $schemeHandler;
183
+ }
184
+
185
+ /**
186
+ * Parse the scheme-specific portion of the URI and place its parts into instance variables.
187
+ *
188
+ * @param string $schemeSpecific The scheme-specific portion to parse
189
+ * @throws Microsoft_Uri_Exception When scheme-specific decoposition fails
190
+ * @throws Microsoft_Uri_Exception When authority decomposition fails
191
+ * @return void
192
+ */
193
+ protected function _parseUri($schemeSpecific)
194
+ {
195
+ // High-level decomposition parser
196
+ $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
197
+ $status = @preg_match($pattern, $schemeSpecific, $matches);
198
+ if ($status === false) {
199
+ require_once 'Microsoft/Uri/Exception.php';
200
+ throw new Microsoft_Uri_Exception('Internal error: scheme-specific decomposition failed');
201
+ }
202
+
203
+ // Failed decomposition; no further processing needed
204
+ if ($status === false) {
205
+ return;
206
+ }
207
+
208
+ // Save URI components that need no further decomposition
209
+ $this->_path = isset($matches[4]) === true ? $matches[4] : '';
210
+ $this->_query = isset($matches[6]) === true ? $matches[6] : '';
211
+ $this->_fragment = isset($matches[8]) === true ? $matches[8] : '';
212
+
213
+ // Additional decomposition to get username, password, host, and port
214
+ $combo = isset($matches[3]) === true ? $matches[3] : '';
215
+ $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
216
+ $status = @preg_match($pattern, $combo, $matches);
217
+ if ($status === false) {
218
+ require_once 'Microsoft/Uri/Exception.php';
219
+ throw new Microsoft_Uri_Exception('Internal error: authority decomposition failed');
220
+ }
221
+
222
+ // Failed decomposition; no further processing needed
223
+ if ($status === false) {
224
+ return;
225
+ }
226
+
227
+ // Save remaining URI components
228
+ $this->_username = isset($matches[2]) === true ? $matches[2] : '';
229
+ $this->_password = isset($matches[4]) === true ? $matches[4] : '';
230
+ $this->_host = isset($matches[5]) === true ? $matches[5] : '';
231
+ $this->_port = isset($matches[7]) === true ? $matches[7] : '';
232
+
233
+ }
234
+
235
+ /**
236
+ * Returns a URI based on current values of the instance variables. If any
237
+ * part of the URI does not pass validation, then an exception is thrown.
238
+ *
239
+ * @throws Microsoft_Uri_Exception When one or more parts of the URI are invalid
240
+ * @return string
241
+ */
242
+ public function getUri()
243
+ {
244
+ if ($this->valid() === false) {
245
+ require_once 'Microsoft/Uri/Exception.php';
246
+ throw new Microsoft_Uri_Exception('One or more parts of the URI are invalid');
247
+ }
248
+
249
+ $password = strlen($this->_password) > 0 ? ":$this->_password" : '';
250
+ $auth = strlen($this->_username) > 0 ? "$this->_username$password@" : '';
251
+ $port = strlen($this->_port) > 0 ? ":$this->_port" : '';
252
+ $query = strlen($this->_query) > 0 ? "?$this->_query" : '';
253
+ $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : '';
254
+
255
+ return $this->_scheme
256
+ . '://'
257
+ . $auth
258
+ . $this->_host
259
+ . $port
260
+ . $this->_path
261
+ . $query
262
+ . $fragment;
263
+ }
264
+
265
+ /**
266
+ * Validate the current URI from the instance variables. Returns true if and only if all
267
+ * parts pass validation.
268
+ *
269
+ * @return boolean
270
+ */
271
+ public function valid()
272
+ {
273
+ // Return true if and only if all parts of the URI have passed validation
274
+ return $this->validateUsername()
275
+ and $this->validatePassword()
276
+ and $this->validateHost()
277
+ and $this->validatePort()
278
+ and $this->validatePath()
279
+ and $this->validateQuery()
280
+ and $this->validateFragment();
281
+ }
282
+
283
+ /**
284
+ * Returns the username portion of the URL, or FALSE if none.
285
+ *
286
+ * @return string
287
+ */
288
+ public function getUsername()
289
+ {
290
+ return strlen($this->_username) > 0 ? $this->_username : false;
291
+ }
292
+
293
+ /**
294
+ * Returns true if and only if the username passes validation. If no username is passed,
295
+ * then the username contained in the instance variable is used.
296
+ *
297
+ * @param string $username The HTTP username
298
+ * @throws Microsoft_Uri_Exception When username validation fails
299
+ * @return boolean
300
+ * @link http://www.faqs.org/rfcs/rfc2396.html
301
+ */
302
+ public function validateUsername($username = null)
303
+ {
304
+ if ($username === null) {
305
+ $username = $this->_username;
306
+ }
307
+
308
+ // If the username is empty, then it is considered valid
309
+ if (strlen($username) === 0) {
310
+ return true;
311
+ }
312
+
313
+ // Check the username against the allowed values
314
+ $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
315
+ self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username);
316
+
317
+ if ($status === false) {
318
+ require_once 'Microsoft/Uri/Exception.php';
319
+ throw new Microsoft_Uri_Exception('Internal error: username validation failed');
320
+ }
321
+
322
+ return $status === 1;
323
+ }
324
+
325
+ /**
326
+ * Sets the username for the current URI, and returns the old username
327
+ *
328
+ * @param string $username The HTTP username
329
+ * @throws Microsoft_Uri_Exception When $username is not a valid HTTP username
330
+ * @return string
331
+ */
332
+ public function setUsername($username)
333
+ {
334
+ if ($this->validateUsername($username) === false) {
335
+ require_once 'Microsoft/Uri/Exception.php';
336
+ throw new Microsoft_Uri_Exception("Username \"$username\" is not a valid HTTP username");
337
+ }
338
+
339
+ $oldUsername = $this->_username;
340
+ $this->_username = $username;
341
+
342
+ return $oldUsername;
343
+ }
344
+
345
+ /**
346
+ * Returns the password portion of the URL, or FALSE if none.
347
+ *
348
+ * @return string
349
+ */
350
+ public function getPassword()
351
+ {
352
+ return strlen($this->_password) > 0 ? $this->_password : false;
353
+ }
354
+
355
+ /**
356
+ * Returns true if and only if the password passes validation. If no password is passed,
357
+ * then the password contained in the instance variable is used.
358
+ *
359
+ * @param string $password The HTTP password
360
+ * @throws Microsoft_Uri_Exception When password validation fails
361
+ * @return boolean
362
+ * @link http://www.faqs.org/rfcs/rfc2396.html
363
+ */
364
+ public function validatePassword($password = null)
365
+ {
366
+ if ($password === null) {
367
+ $password = $this->_password;
368
+ }
369
+
370
+ // If the password is empty, then it is considered valid
371
+ if (strlen($password) === 0) {
372
+ return true;
373
+ }
374
+
375
+ // If the password is nonempty, but there is no username, then it is considered invalid
376
+ if (strlen($password) > 0 and strlen($this->_username) === 0) {
377
+ return false;
378
+ }
379
+
380
+ // Check the password against the allowed values
381
+ $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
382
+ self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password);
383
+
384
+ if ($status === false) {
385
+ require_once 'Microsoft/Uri/Exception.php';
386
+ throw new Microsoft_Uri_Exception('Internal error: password validation failed.');
387
+ }
388
+
389
+ return $status == 1;
390
+ }
391
+
392
+ /**
393
+ * Sets the password for the current URI, and returns the old password
394
+ *
395
+ * @param string $password The HTTP password
396
+ * @throws Microsoft_Uri_Exception When $password is not a valid HTTP password
397
+ * @return string
398
+ */
399
+ public function setPassword($password)
400
+ {
401
+ if ($this->validatePassword($password) === false) {
402
+ require_once 'Microsoft/Uri/Exception.php';
403
+ throw new Microsoft_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
404
+ }
405
+
406
+ $oldPassword = $this->_password;
407
+ $this->_password = $password;
408
+
409
+ return $oldPassword;
410
+ }
411
+
412
+ /**
413
+ * Returns the domain or host IP portion of the URL, or FALSE if none.
414
+ *
415
+ * @return string
416
+ */
417
+ public function getHost()
418
+ {
419
+ return strlen($this->_host) > 0 ? $this->_host : false;
420
+ }
421
+
422
+ /**
423
+ * Returns true if and only if the host string passes validation. If no host is passed,
424
+ * then the host contained in the instance variable is used.
425
+ *
426
+ * @param string $host The HTTP host
427
+ * @return boolean
428
+ * @uses Microsoft_Filter
429
+ */
430
+ public function validateHost($host = null)
431
+ {
432
+ if ($host === null) {
433
+ $host = $this->_host;
434
+ }
435
+
436
+ // If the host is empty, then it is considered invalid
437
+ if (strlen($host) === 0) {
438
+ return false;
439
+ }
440
+
441
+ return true;
442
+ }
443
+
444
+ /**
445
+ * Sets the host for the current URI, and returns the old host
446
+ *
447
+ * @param string $host The HTTP host
448
+ * @throws Microsoft_Uri_Exception When $host is nota valid HTTP host
449
+ * @return string
450
+ */
451
+ public function setHost($host)
452
+ {
453
+ if ($this->validateHost($host) === false) {
454
+ require_once 'Microsoft/Uri/Exception.php';
455
+ throw new Microsoft_Uri_Exception("Host \"$host\" is not a valid HTTP host");
456
+ }
457
+
458
+ $oldHost = $this->_host;
459
+ $this->_host = $host;
460
+
461
+ return $oldHost;
462
+ }
463
+
464
+ /**
465
+ * Returns the TCP port, or FALSE if none.
466
+ *
467
+ * @return string
468
+ */
469
+ public function getPort()
470
+ {
471
+ return strlen($this->_port) > 0 ? $this->_port : false;
472
+ }
473
+
474
+ /**
475
+ * Returns true if and only if the TCP port string passes validation. If no port is passed,
476
+ * then the port contained in the instance variable is used.
477
+ *
478
+ * @param string $port The HTTP port
479
+ * @return boolean
480
+ */
481
+ public function validatePort($port = null)
482
+ {
483
+ if ($port === null) {
484
+ $port = $this->_port;
485
+ }
486
+
487
+ // If the port is empty, then it is considered valid
488
+ if (strlen($port) === 0) {
489
+ return true;
490
+ }
491
+
492
+ // Check the port against the allowed values
493
+ return ctype_digit((string) $port) and 1 <= $port and $port <= 65535;
494
+ }
495
+
496
+ /**
497
+ * Sets the port for the current URI, and returns the old port
498
+ *
499
+ * @param string $port The HTTP port
500
+ * @throws Microsoft_Uri_Exception When $port is not a valid HTTP port
501
+ * @return string
502
+ */
503
+ public function setPort($port)
504
+ {
505
+ if ($this->validatePort($port) === false) {
506
+ require_once 'Microsoft/Uri/Exception.php';
507
+ throw new Microsoft_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
508
+ }
509
+
510
+ $oldPort = $this->_port;
511
+ $this->_port = $port;
512
+
513
+ return $oldPort;
514
+ }
515
+
516
+ /**
517
+ * Returns the path and filename portion of the URL, or FALSE if none.
518
+ *
519
+ * @return string
520
+ */
521
+ public function getPath()
522
+ {
523
+ return strlen($this->_path) > 0 ? $this->_path : '/';
524
+ }
525
+
526
+ /**
527
+ * Returns true if and only if the path string passes validation. If no path is passed,
528
+ * then the path contained in the instance variable is used.
529
+ *
530
+ * @param string $path The HTTP path
531
+ * @throws Microsoft_Uri_Exception When path validation fails
532
+ * @return boolean
533
+ */
534
+ public function validatePath($path = null)
535
+ {
536
+ if ($path === null) {
537
+ $path = $this->_path;
538
+ }
539
+
540
+ // If the path is empty, then it is considered valid
541
+ if (strlen($path) === 0) {
542
+ return true;
543
+ }
544
+
545
+ // Determine whether the path is well-formed
546
+ $pattern = '/^' . $this->_regex['path'] . '$/';
547
+ $status = @preg_match($pattern, $path);
548
+ if ($status === false) {
549
+ require_once 'Microsoft/Uri/Exception.php';
550
+ throw new Microsoft_Uri_Exception('Internal error: path validation failed');
551
+ }
552
+
553
+ return (boolean) $status;
554
+ }
555
+
556
+ /**
557
+ * Sets the path for the current URI, and returns the old path
558
+ *
559
+ * @param string $path The HTTP path
560
+ * @throws Microsoft_Uri_Exception When $path is not a valid HTTP path
561
+ * @return string
562
+ */
563
+ public function setPath($path)
564
+ {
565
+ if ($this->validatePath($path) === false) {
566
+ require_once 'Microsoft/Uri/Exception.php';
567
+ throw new Microsoft_Uri_Exception("Path \"$path\" is not a valid HTTP path");
568
+ }
569
+
570
+ $oldPath = $this->_path;
571
+ $this->_path = $path;
572
+
573
+ return $oldPath;
574
+ }
575
+
576
+ /**
577
+ * Returns the query portion of the URL (after ?), or FALSE if none.
578
+ *
579
+ * @return string
580
+ */
581
+ public function getQuery()
582
+ {
583
+ return strlen($this->_query) > 0 ? $this->_query : false;
584
+ }
585
+
586
+ /**
587
+ * Returns the query portion of the URL (after ?) as a
588
+ * key-value-array. If the query is empty an empty array
589
+ * is returned
590
+ *
591
+ * @return array
592
+ */
593
+ public function getQueryAsArray()
594
+ {
595
+ $query = $this->getQuery();
596
+ $querryArray = array();
597
+ if ($query !== false) {
598
+ parse_str($query, $querryArray);
599
+ }
600
+ return $querryArray;
601
+ }
602
+
603
+ /**
604
+ * Returns true if and only if the query string passes validation. If no query is passed,
605
+ * then the query string contained in the instance variable is used.
606
+ *
607
+ * @param string $query The query to validate
608
+ * @throws Microsoft_Uri_Exception When query validation fails
609
+ * @return boolean
610
+ * @link http://www.faqs.org/rfcs/rfc2396.html
611
+ */
612
+ public function validateQuery($query = null)
613
+ {
614
+ if ($query === null) {
615
+ $query = $this->_query;
616
+ }
617
+
618
+ // If query is empty, it is considered to be valid
619
+ if (strlen($query) === 0) {
620
+ return true;
621
+ }
622
+
623
+ // Determine whether the query is well-formed
624
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
625
+ $status = @preg_match($pattern, $query);
626
+ if ($status === false) {
627
+ require_once 'Microsoft/Uri/Exception.php';
628
+ throw new Microsoft_Uri_Exception('Internal error: query validation failed');
629
+ }
630
+
631
+ return $status == 1;
632
+ }
633
+
634
+ /**
635
+ * Add or replace params in the query string for the current URI, and
636
+ * return the old query.
637
+ *
638
+ * @param array $queryParams
639
+ * @return string Old query string
640
+ */
641
+ public function addReplaceQueryParameters(array $queryParams)
642
+ {
643
+ $queryParams = array_merge($this->getQueryAsArray(), $queryParams);
644
+ return $this->setQuery($queryParams);
645
+ }
646
+
647
+ /**
648
+ * Remove params in the query string for the current URI, and
649
+ * return the old query.
650
+ *
651
+ * @param array $queryParamKeys
652
+ * @return string Old query string
653
+ */
654
+ public function removeQueryParameters(array $queryParamKeys)
655
+ {
656
+ $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0));
657
+ return $this->setQuery($queryParams);
658
+ }
659
+
660
+ /**
661
+ * Set the query string for the current URI, and return the old query
662
+ * string This method accepts both strings and arrays.
663
+ *
664
+ * @param string|array $query The query string or array
665
+ * @throws Microsoft_Uri_Exception When $query is not a valid query string
666
+ * @return string Old query string
667
+ */
668
+ public function setQuery($query)
669
+ {
670
+ $oldQuery = $this->_query;
671
+
672
+ // If query is empty, set an empty string
673
+ if (empty($query) === true) {
674
+ $this->_query = '';
675
+ return $oldQuery;
676
+ }
677
+
678
+ // If query is an array, make a string out of it
679
+ if (is_array($query) === true) {
680
+ $query = http_build_query($query, '', '&');
681
+ } else {
682
+ // If it is a string, make sure it is valid. If not parse and encode it
683
+ $query = (string) $query;
684
+ if ($this->validateQuery($query) === false) {
685
+ parse_str($query, $queryArray);
686
+ $query = http_build_query($queryArray, '', '&');
687
+ }
688
+ }
689
+
690
+ // Make sure the query is valid, and set it
691
+ if ($this->validateQuery($query) === false) {
692
+ require_once 'Microsoft/Uri/Exception.php';
693
+ throw new Microsoft_Uri_Exception("'$query' is not a valid query string");
694
+ }
695
+
696
+ $this->_query = $query;
697
+
698
+ return $oldQuery;
699
+ }
700
+
701
+ /**
702
+ * Returns the fragment portion of the URL (after #), or FALSE if none.
703
+ *
704
+ * @return string|false
705
+ */
706
+ public function getFragment()
707
+ {
708
+ return strlen($this->_fragment) > 0 ? $this->_fragment : false;
709
+ }
710
+
711
+ /**
712
+ * Returns true if and only if the fragment passes validation. If no fragment is passed,
713
+ * then the fragment contained in the instance variable is used.
714
+ *
715
+ * @param string $fragment Fragment of an URI
716
+ * @throws Microsoft_Uri_Exception When fragment validation fails
717
+ * @return boolean
718
+ * @link http://www.faqs.org/rfcs/rfc2396.html
719
+ */
720
+ public function validateFragment($fragment = null)
721
+ {
722
+ if ($fragment === null) {
723
+ $fragment = $this->_fragment;
724
+ }
725
+
726
+ // If fragment is empty, it is considered to be valid
727
+ if (strlen($fragment) === 0) {
728
+ return true;
729
+ }
730
+
731
+ // Determine whether the fragment is well-formed
732
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
733
+ $status = @preg_match($pattern, $fragment);
734
+ if ($status === false) {
735
+ require_once 'Microsoft/Uri/Exception.php';
736
+ throw new Microsoft_Uri_Exception('Internal error: fragment validation failed');
737
+ }
738
+
739
+ return (boolean) $status;
740
+ }
741
+
742
+ /**
743
+ * Sets the fragment for the current URI, and returns the old fragment
744
+ *
745
+ * @param string $fragment Fragment of the current URI
746
+ * @throws Microsoft_Uri_Exception When $fragment is not a valid HTTP fragment
747
+ * @return string
748
+ */
749
+ public function setFragment($fragment)
750
+ {
751
+ if ($this->validateFragment($fragment) === false) {
752
+ require_once 'Microsoft/Uri/Exception.php';
753
+ throw new Microsoft_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
754
+ }
755
+
756
+ $oldFragment = $this->_fragment;
757
+ $this->_fragment = $fragment;
758
+
759
+ return $oldFragment;
760
+ }
761
+ }
lib/Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id: SharedKeyCredentials.php 14561 2009-05-07 08:05:12Z unknown $
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_Http_Client
37
+ */
38
+ require_once 'Microsoft/Http/Client.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Credentials_Exception
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Credentials/Exception.php';
44
+
45
+ /**
46
+ * @category Microsoft
47
+ * @package Microsoft_WindowsAzure
48
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
49
+ * @license http://phpazure.codeplex.com/license
50
+ */
51
+ abstract class Microsoft_WindowsAzure_Credentials_CredentialsAbstract
52
+ {
53
+ /**
54
+ * Development storage account and key
55
+ */
56
+ const DEVSTORE_ACCOUNT = "devstoreaccount1";
57
+ const DEVSTORE_KEY = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
58
+
59
+ /**
60
+ * HTTP header prefixes
61
+ */
62
+ const PREFIX_PROPERTIES = "x-ms-prop-";
63
+ const PREFIX_METADATA = "x-ms-meta-";
64
+ const PREFIX_STORAGE_HEADER = "x-ms-";
65
+
66
+ /**
67
+ * Permissions
68
+ */
69
+ const PERMISSION_READ = "r";
70
+ const PERMISSION_WRITE = "w";
71
+ const PERMISSION_DELETE = "d";
72
+ const PERMISSION_LIST = "l";
73
+
74
+ /**
75
+ * Account name for Windows Azure
76
+ *
77
+ * @var string
78
+ */
79
+ protected $_accountName = '';
80
+
81
+ /**
82
+ * Account key for Windows Azure
83
+ *
84
+ * @var string
85
+ */
86
+ protected $_accountKey = '';
87
+
88
+ /**
89
+ * Use path-style URI's
90
+ *
91
+ * @var boolean
92
+ */
93
+ protected $_usePathStyleUri = false;
94
+
95
+ /**
96
+ * Creates a new Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
97
+ *
98
+ * @param string $accountName Account name for Windows Azure
99
+ * @param string $accountKey Account key for Windows Azure
100
+ * @param boolean $usePathStyleUri Use path-style URI's
101
+ */
102
+ public function __construct(
103
+ $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
104
+ $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
105
+ $usePathStyleUri = false
106
+ ) {
107
+ $this->_accountName = $accountName;
108
+ $this->_accountKey = base64_decode($accountKey);
109
+ $this->_usePathStyleUri = $usePathStyleUri;
110
+ }
111
+
112
+ /**
113
+ * Set account name for Windows Azure
114
+ *
115
+ * @param string $value
116
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
117
+ */
118
+ public function setAccountName($value = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT)
119
+ {
120
+ $this->_accountName = $value;
121
+ return $this;
122
+ }
123
+
124
+ /**
125
+ * Set account key for Windows Azure
126
+ *
127
+ * @param string $value
128
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
129
+ */
130
+ public function setAccountkey($value = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY)
131
+ {
132
+ $this->_accountKey = base64_decode($value);
133
+ return $this;
134
+ }
135
+
136
+ /**
137
+ * Set use path-style URI's
138
+ *
139
+ * @param boolean $value
140
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
141
+ */
142
+ public function setUsePathStyleUri($value = false)
143
+ {
144
+ $this->_usePathStyleUri = $value;
145
+ return $this;
146
+ }
147
+
148
+ /**
149
+ * Sign request URL with credentials
150
+ *
151
+ * @param string $requestUrl Request URL
152
+ * @param string $resourceType Resource type
153
+ * @param string $requiredPermission Required permission
154
+ * @return string Signed request URL
155
+ */
156
+ abstract public function signRequestUrl(
157
+ $requestUrl = '',
158
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
159
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
160
+ );
161
+
162
+ /**
163
+ * Sign request headers with credentials
164
+ *
165
+ * @param string $httpVerb HTTP verb the request will use
166
+ * @param string $path Path for the request
167
+ * @param string $queryString Query string for the request
168
+ * @param array $headers x-ms headers to add
169
+ * @param boolean $forTableStorage Is the request for table storage?
170
+ * @param string $resourceType Resource type
171
+ * @param string $requiredPermission Required permission
172
+ * @param mixed $rawData Raw post data
173
+ * @return array Array of headers
174
+ */
175
+ abstract public function signRequestHeaders(
176
+ $httpVerb = Microsoft_Http_Client::GET,
177
+ $path = '/',
178
+ $queryString = '',
179
+ $headers = null,
180
+ $forTableStorage = false,
181
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
182
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
183
+ $rawData = null
184
+ );
185
+
186
+
187
+ /**
188
+ * Prepare query string for signing
189
+ *
190
+ * @param string $value Original query string
191
+ * @return string Query string for signing
192
+ */
193
+ protected function _prepareQueryStringForSigning($value)
194
+ {
195
+ // Return value
196
+ $returnValue = array();
197
+
198
+ // Prepare query string
199
+ $queryParts = $this->_makeArrayOfQueryString($value);
200
+ foreach ($queryParts as $key => $value) {
201
+ $returnValue[] = $key . '=' . $value;
202
+ }
203
+
204
+ // Return
205
+ if (count($returnValue) > 0) {
206
+ return '?' . implode('&', $returnValue);
207
+ } else {
208
+ return '';
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Make array of query string
214
+ *
215
+ * @param string $value Query string
216
+ * @return array Array of key/value pairs
217
+ */
218
+ protected function _makeArrayOfQueryString($value)
219
+ {
220
+ // Returnvalue
221
+ $returnValue = array();
222
+
223
+ // Remove front ?
224
+ if (strlen($value) > 0 && strpos($value, '?') === 0) {
225
+ $value = substr($value, 1);
226
+ }
227
+
228
+ // Split parts
229
+ $queryParts = explode('&', $value);
230
+ foreach ($queryParts as $queryPart) {
231
+ $queryPart = explode('=', $queryPart, 2);
232
+
233
+ if ($queryPart[0] != '') {
234
+ $returnValue[ $queryPart[0] ] = isset($queryPart[1]) ? $queryPart[1] : '';
235
+ }
236
+ }
237
+
238
+ // Sort
239
+ ksort($returnValue);
240
+
241
+ // Return
242
+ return $returnValue;
243
+ }
244
+
245
+ /**
246
+ * Returns an array value if the key is set, otherwide returns $valueIfNotSet
247
+ *
248
+ * @param array $array
249
+ * @param mixed $key
250
+ * @param mixed $valueIfNotSet
251
+ * @return mixed
252
+ */
253
+ protected function _issetOr($array, $key, $valueIfNotSet)
254
+ {
255
+ return isset($array[$key]) ? $array[$key] : $valueIfNotSet;
256
+ }
257
+ }
lib/Microsoft/WindowsAzure/Credentials/Exception.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 28585 2009-09-07 12:12:56Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
45
+ * @license http://phpazure.codeplex.com/license
46
+ */
47
+ class Microsoft_WindowsAzure_Credentials_Exception extends Microsoft_WindowsAzure_Exception
48
+ {}
lib/Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id: SharedKeyCredentials.php 24305 2009-07-23 06:30:04Z unknown $
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
37
+ */
38
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Storage
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Storage.php';
44
+
45
+ /**
46
+ * @see Microsoft_Http_Client
47
+ */
48
+ require_once 'Microsoft/Http/Client.php';
49
+
50
+ /**
51
+ * @category Microsoft
52
+ * @package Microsoft_WindowsAzure
53
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
54
+ * @license http://phpazure.codeplex.com/license
55
+ */
56
+ class Microsoft_WindowsAzure_Credentials_SharedAccessSignature
57
+ extends Microsoft_WindowsAzure_Credentials_CredentialsAbstract
58
+ {
59
+ /**
60
+ * Permission set
61
+ *
62
+ * @var array
63
+ */
64
+ protected $_permissionSet = array();
65
+
66
+ /**
67
+ * Creates a new Microsoft_WindowsAzure_Credentials_SharedAccessSignature instance
68
+ *
69
+ * @param string $accountName Account name for Windows Azure
70
+ * @param string $accountKey Account key for Windows Azure
71
+ * @param boolean $usePathStyleUri Use path-style URI's
72
+ * @param array $permissionSet Permission set
73
+ */
74
+ public function __construct(
75
+ $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
76
+ $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
77
+ $usePathStyleUri = false, $permissionSet = array()
78
+ ) {
79
+ parent::__construct($accountName, $accountKey, $usePathStyleUri);
80
+ $this->_permissionSet = $permissionSet;
81
+ }
82
+
83
+ /**
84
+ * Get permission set
85
+ *
86
+ * @return array
87
+ */
88
+ public function getPermissionSet()
89
+ {
90
+ return $this->_permissionSet;
91
+ }
92
+
93
+ /**
94
+ * Set permisison set
95
+ *
96
+ * Warning: fine-grained permissions should be added prior to coarse-grained permissions.
97
+ * For example: first add blob permissions, end with container-wide permissions.
98
+ *
99
+ * Warning: the signed access signature URL must match the account name of the
100
+ * Microsoft_WindowsAzure_Credentials_Microsoft_WindowsAzure_Credentials_SharedAccessSignature instance
101
+ *
102
+ * @param array $value Permission set
103
+ * @return void
104
+ */
105
+ public function setPermissionSet($value = array())
106
+ {
107
+ foreach ($value as $url) {
108
+ if (strpos($url, $this->_accountName) === false) {
109
+ throw new Microsoft_WindowsAzure_Exception('The permission set can only contain URLs for the account name specified in the Microsoft_WindowsAzure_Credentials_SharedAccessSignature instance.');
110
+ }
111
+ }
112
+ $this->_permissionSet = $value;
113
+ }
114
+
115
+ /**
116
+ * Create signature
117
+ *
118
+ * @param string $path Path for the request
119
+ * @param string $resource Signed resource - container (c) - blob (b)
120
+ * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
121
+ * @param string $start The time at which the Shared Access Signature becomes valid.
122
+ * @param string $expiry The time at which the Shared Access Signature becomes invalid.
123
+ * @param string $identifier Signed identifier
124
+ * @return string
125
+ */
126
+ public function createSignature(
127
+ $path = '/',
128
+ $resource = 'b',
129
+ $permissions = 'r',
130
+ $start = '',
131
+ $expiry = '',
132
+ $identifier = ''
133
+ ) {
134
+ // Determine path
135
+ if ($this->_usePathStyleUri) {
136
+ $path = substr($path, strpos($path, '/'));
137
+ }
138
+
139
+ // Add trailing slash to $path
140
+ if (substr($path, 0, 1) !== '/') {
141
+ $path = '/' . $path;
142
+ }
143
+
144
+ // Build canonicalized resource string
145
+ $canonicalizedResource = '/' . $this->_accountName;
146
+ /*if ($this->_usePathStyleUri) {
147
+ $canonicalizedResource .= '/' . $this->_accountName;
148
+ }*/
149
+ $canonicalizedResource .= $path;
150
+
151
+ // Create string to sign
152
+ $stringToSign = array();
153
+ $stringToSign[] = $permissions;
154
+ $stringToSign[] = $start;
155
+ $stringToSign[] = $expiry;
156
+ $stringToSign[] = $canonicalizedResource;
157
+ $stringToSign[] = $identifier;
158
+
159
+ $stringToSign = implode("\n", $stringToSign);
160
+ $signature = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
161
+
162
+ return $signature;
163
+ }
164
+
165
+ /**
166
+ * Create signed query string
167
+ *
168
+ * @param string $path Path for the request
169
+ * @param string $queryString Query string for the request
170
+ * @param string $resource Signed resource - container (c) - blob (b)
171
+ * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
172
+ * @param string $start The time at which the Shared Access Signature becomes valid.
173
+ * @param string $expiry The time at which the Shared Access Signature becomes invalid.
174
+ * @param string $identifier Signed identifier
175
+ * @return string
176
+ */
177
+ public function createSignedQueryString(
178
+ $path = '/',
179
+ $queryString = '',
180
+ $resource = 'b',
181
+ $permissions = 'r',
182
+ $start = '',
183
+ $expiry = '',
184
+ $identifier = ''
185
+ ) {
186
+ // Parts
187
+ $parts = array();
188
+ if ($start !== '') {
189
+ $parts[] = 'st=' . urlencode($start);
190
+ }
191
+ $parts[] = 'se=' . urlencode($expiry);
192
+ $parts[] = 'sr=' . $resource;
193
+ $parts[] = 'sp=' . $permissions;
194
+ if ($identifier !== '') {
195
+ $parts[] = 'si=' . urlencode($identifier);
196
+ }
197
+ $parts[] = 'sig=' . urlencode($this->createSignature($path, $resource, $permissions, $start, $expiry, $identifier));
198
+
199
+ // Assemble parts and query string
200
+ if ($queryString != '') {
201
+ $queryString .= '&';
202
+ }
203
+ $queryString .= implode('&', $parts);
204
+
205
+ return $queryString;
206
+ }
207
+
208
+ /**
209
+ * Permission matches request?
210
+ *
211
+ * @param string $permissionUrl Permission URL
212
+ * @param string $requestUrl Request URL
213
+ * @param string $resourceType Resource type
214
+ * @param string $requiredPermission Required permission
215
+ * @return string Signed request URL
216
+ */
217
+ public function permissionMatchesRequest(
218
+ $permissionUrl = '',
219
+ $requestUrl = '',
220
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
221
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
222
+ ) {
223
+ // Build requirements
224
+ $requiredResourceType = $resourceType;
225
+ if ($requiredResourceType == Microsoft_WindowsAzure_Storage::RESOURCE_BLOB) {
226
+ $requiredResourceType .= Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER;
227
+ }
228
+
229
+ // Parse permission url
230
+ $parsedPermissionUrl = parse_url($permissionUrl);
231
+
232
+ // Parse permission properties
233
+ $permissionParts = explode('&', $parsedPermissionUrl['query']);
234
+
235
+ // Parse request url
236
+ $parsedRequestUrl = parse_url($requestUrl);
237
+
238
+ // Check if permission matches request
239
+ $matches = true;
240
+ foreach ($permissionParts as $part) {
241
+ list($property, $value) = explode('=', $part, 2);
242
+
243
+ if ($property == 'sr') {
244
+ $matches = $matches && (strpbrk($value, $requiredResourceType) !== false);
245
+ }
246
+
247
+ if ($property == 'sp') {
248
+ $matches = $matches && (strpbrk($value, $requiredPermission) !== false);
249
+ }
250
+ }
251
+
252
+ // Ok, but... does the resource match?
253
+ $matches = $matches && (strpos($parsedRequestUrl['path'], $parsedPermissionUrl['path']) !== false);
254
+
255
+ // Return
256
+ return $matches;
257
+ }
258
+
259
+ /**
260
+ * Sign request URL with credentials
261
+ *
262
+ * @param string $requestUrl Request URL
263
+ * @param string $resourceType Resource type
264
+ * @param string $requiredPermission Required permission
265
+ * @return string Signed request URL
266
+ */
267
+ public function signRequestUrl(
268
+ $requestUrl = '',
269
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
270
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
271
+ ) {
272
+ // Look for a matching permission
273
+ foreach ($this->getPermissionSet() as $permittedUrl) {
274
+ if ($this->permissionMatchesRequest($permittedUrl, $requestUrl, $resourceType, $requiredPermission)) {
275
+ // This matches, append signature data
276
+ $parsedPermittedUrl = parse_url($permittedUrl);
277
+
278
+ if (strpos($requestUrl, '?') === false) {
279
+ $requestUrl .= '?';
280
+ } else {
281
+ $requestUrl .= '&';
282
+ }
283
+
284
+ $requestUrl .= $parsedPermittedUrl['query'];
285
+
286
+ // Return url
287
+ return $requestUrl;
288
+ }
289
+ }
290
+
291
+ // Return url, will be unsigned...
292
+ return $requestUrl;
293
+ }
294
+
295
+ /**
296
+ * Sign request with credentials
297
+ *
298
+ * @param string $httpVerb HTTP verb the request will use
299
+ * @param string $path Path for the request
300
+ * @param string $queryString Query string for the request
301
+ * @param array $headers x-ms headers to add
302
+ * @param boolean $forTableStorage Is the request for table storage?
303
+ * @param string $resourceType Resource type
304
+ * @param string $requiredPermission Required permission
305
+ * @param mixed $rawData Raw post data
306
+ * @return array Array of headers
307
+ */
308
+ public function signRequestHeaders(
309
+ $httpVerb = Microsoft_Http_Client::GET,
310
+ $path = '/',
311
+ $queryString = '',
312
+ $headers = null,
313
+ $forTableStorage = false,
314
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
315
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
316
+ $rawData = null
317
+ ) {
318
+ return $headers;
319
+ }
320
+ }
lib/Microsoft/WindowsAzure/Credentials/SharedKey.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id$
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
37
+ */
38
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Storage
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Storage.php';
44
+
45
+ /**
46
+ * @see Microsoft_Http_Client
47
+ */
48
+ require_once 'Microsoft/Http/Client.php';
49
+
50
+ /**
51
+ * @see Microsoft_WindowsAzure_Credentials_Exception
52
+ */
53
+ require_once 'Microsoft/WindowsAzure/Credentials/Exception.php';
54
+
55
+ /**
56
+ * @category Microsoft
57
+ * @package Microsoft_WindowsAzure
58
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
59
+ * @license http://phpazure.codeplex.com/license
60
+ */
61
+ class Microsoft_WindowsAzure_Credentials_SharedKey
62
+ extends Microsoft_WindowsAzure_Credentials_CredentialsAbstract
63
+ {
64
+ /**
65
+ * Sign request URL with credentials
66
+ *
67
+ * @param string $requestUrl Request URL
68
+ * @param string $resourceType Resource type
69
+ * @param string $requiredPermission Required permission
70
+ * @return string Signed request URL
71
+ */
72
+ public function signRequestUrl(
73
+ $requestUrl = '',
74
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
75
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
76
+ ) {
77
+ return $requestUrl;
78
+ }
79
+
80
+ /**
81
+ * Sign request headers with credentials
82
+ *
83
+ * @param string $httpVerb HTTP verb the request will use
84
+ * @param string $path Path for the request
85
+ * @param string $queryString Query string for the request
86
+ * @param array $headers x-ms headers to add
87
+ * @param boolean $forTableStorage Is the request for table storage?
88
+ * @param string $resourceType Resource type
89
+ * @param string $requiredPermission Required permission
90
+ * @param mixed $rawData Raw post data
91
+ * @return array Array of headers
92
+ */
93
+ public function signRequestHeaders(
94
+ $httpVerb = Microsoft_Http_Client::GET,
95
+ $path = '/',
96
+ $queryString = '',
97
+ $headers = null,
98
+ $forTableStorage = false,
99
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
100
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
101
+ $rawData = null
102
+ ) {
103
+ // http://github.com/sriramk/winazurestorage/blob/214010a2f8931bac9c96dfeb337d56fe084ca63b/winazurestorage.py
104
+
105
+ // Table storage?
106
+ if ($forTableStorage) {
107
+ throw new Microsoft_WindowsAzure_Credentials_Exception('The Windows Azure SDK for PHP does not support SharedKey authentication on table storage. Use SharedKeyLite authentication instead.');
108
+ }
109
+
110
+ // Determine path
111
+ if ($this->_usePathStyleUri) {
112
+ $path = substr($path, strpos($path, '/'));
113
+ }
114
+
115
+ // Determine query
116
+ $queryString = $this->_prepareQueryStringForSigning($queryString);
117
+
118
+ // Canonicalized headers
119
+ $canonicalizedHeaders = array();
120
+
121
+ // Request date
122
+ $requestDate = '';
123
+ if (isset($headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) {
124
+ $requestDate = $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'];
125
+ } else {
126
+ $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
127
+ $canonicalizedHeaders[] = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date:' . $requestDate;
128
+ }
129
+
130
+ // Build canonicalized headers
131
+ if (!is_null($headers)) {
132
+ foreach ($headers as $header => $value) {
133
+ if (is_bool($value)) {
134
+ $value = $value === true ? 'True' : 'False';
135
+ }
136
+
137
+ $headers[$header] = $value;
138
+ if (substr($header, 0, strlen(Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER)) == Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER) {
139
+ $canonicalizedHeaders[] = strtolower($header) . ':' . $value;
140
+ }
141
+ }
142
+ }
143
+ sort($canonicalizedHeaders);
144
+
145
+ // Build canonicalized resource string
146
+ $canonicalizedResource = '/' . $this->_accountName;
147
+ if ($this->_usePathStyleUri) {
148
+ $canonicalizedResource .= '/' . $this->_accountName;
149
+ }
150
+ $canonicalizedResource .= $path;
151
+ if ($queryString !== '') {
152
+ $queryStringItems = $this->_makeArrayOfQueryString($queryString);
153
+ foreach ($queryStringItems as $key => $value) {
154
+ $canonicalizedResource .= "\n" . strtolower($key) . ':' . $value;
155
+ }
156
+ }
157
+
158
+ // Content-Length header
159
+ $contentLength = '';
160
+ if (strtoupper($httpVerb) != Microsoft_Http_Client::GET
161
+ && strtoupper($httpVerb) != Microsoft_Http_Client::DELETE
162
+ && strtoupper($httpVerb) != Microsoft_Http_Client::HEAD) {
163
+ $contentLength = 0;
164
+
165
+ if (!is_null($rawData)) {
166
+ $contentLength = strlen($rawData);
167
+ }
168
+ }
169
+
170
+ // Create string to sign
171
+ $stringToSign = array();
172
+ $stringToSign[] = strtoupper($httpVerb); // VERB
173
+ $stringToSign[] = $this->_issetOr($headers, 'Content-Encoding', ''); // Content-Encoding
174
+ $stringToSign[] = $this->_issetOr($headers, 'Content-Language', ''); // Content-Language
175
+ $stringToSign[] = $contentLength; // Content-Length
176
+ $stringToSign[] = $this->_issetOr($headers, 'Content-MD5', ''); // Content-MD5
177
+ $stringToSign[] = $this->_issetOr($headers, 'Content-Type', ''); // Content-Type
178
+ $stringToSign[] = ""; // Date
179
+ $stringToSign[] = $this->_issetOr($headers, 'If-Modified-Since', ''); // If-Modified-Since
180
+ $stringToSign[] = $this->_issetOr($headers, 'If-Match', ''); // If-Match
181
+ $stringToSign[] = $this->_issetOr($headers, 'If-None-Match', ''); // If-None-Match
182
+ $stringToSign[] = $this->_issetOr($headers, 'If-Unmodified-Since', ''); // If-Unmodified-Since
183
+ $stringToSign[] = $this->_issetOr($headers, 'Range', ''); // Range
184
+
185
+ if (!$forTableStorage && count($canonicalizedHeaders) > 0) {
186
+ $stringToSign[] = implode("\n", $canonicalizedHeaders); // Canonicalized headers
187
+ }
188
+
189
+ $stringToSign[] = $canonicalizedResource; // Canonicalized resource
190
+ $stringToSign = implode("\n", $stringToSign);
191
+ $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
192
+
193
+ // Sign request
194
+ $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate;
195
+ $headers['Authorization'] = 'SharedKey ' . $this->_accountName . ':' . $signString;
196
+
197
+ // Return headers
198
+ return $headers;
199
+ }
200
+ }
lib/Microsoft/WindowsAzure/Credentials/SharedKeyLite.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id: SharedKeyCredentials.php 14561 2009-05-07 08:05:12Z unknown $
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
37
+ */
38
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Storage
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Storage.php';
44
+
45
+ /**
46
+ * @see Microsoft_WindowsAzure_Credentials_SharedKey
47
+ */
48
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
49
+
50
+ /**
51
+ * @see Microsoft_WindowsAzure_Credentials_Exception
52
+ */
53
+ require_once 'Microsoft/WindowsAzure/Credentials/Exception.php';
54
+
55
+ /**
56
+ * @category Microsoft
57
+ * @package Microsoft_WindowsAzure
58
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
59
+ * @license http://phpazure.codeplex.com/license
60
+ */
61
+ class Microsoft_WindowsAzure_Credentials_SharedKeyLite
62
+ extends Microsoft_WindowsAzure_Credentials_CredentialsAbstract
63
+ {
64
+ /**
65
+ * Sign request URL with credentials
66
+ *
67
+ * @param string $requestUrl Request URL
68
+ * @param string $resourceType Resource type
69
+ * @param string $requiredPermission Required permission
70
+ * @return string Signed request URL
71
+ */
72
+ public function signRequestUrl(
73
+ $requestUrl = '',
74
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
75
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
76
+ ) {
77
+ return $requestUrl;
78
+ }
79
+
80
+ /**
81
+ * Sign request headers with credentials
82
+ *
83
+ * @param string $httpVerb HTTP verb the request will use
84
+ * @param string $path Path for the request
85
+ * @param string $queryString Query string for the request
86
+ * @param array $headers x-ms headers to add
87
+ * @param boolean $forTableStorage Is the request for table storage?
88
+ * @param string $resourceType Resource type
89
+ * @param string $requiredPermission Required permission
90
+ * @param mixed $rawData Raw post data
91
+ * @return array Array of headers
92
+ */
93
+ public function signRequestHeaders(
94
+ $httpVerb = Microsoft_Http_Client::GET,
95
+ $path = '/',
96
+ $queryString = '',
97
+ $headers = null,
98
+ $forTableStorage = false,
99
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
100
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
101
+ $rawData = null
102
+ ) {
103
+ // Table storage?
104
+ if (!$forTableStorage) {
105
+ throw new Microsoft_WindowsAzure_Credentials_Exception('The Windows Azure SDK for PHP does not support SharedKeyLite authentication on blob or queue storage. Use SharedKey authentication instead.');
106
+ }
107
+
108
+ // Determine path
109
+ if ($this->_usePathStyleUri) {
110
+ $path = substr($path, strpos($path, '/'));
111
+ }
112
+
113
+ // Determine query
114
+ $queryString = $this->_prepareQueryStringForSigning($queryString);
115
+
116
+ // Build canonicalized resource string
117
+ $canonicalizedResource = '/' . $this->_accountName;
118
+ if ($this->_usePathStyleUri) {
119
+ $canonicalizedResource .= '/' . $this->_accountName;
120
+ }
121
+ $canonicalizedResource .= $path;
122
+ if ($queryString !== '') {
123
+ $canonicalizedResource .= $queryString;
124
+ }
125
+
126
+ // Request date
127
+ $requestDate = '';
128
+ if (isset($headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) {
129
+ $requestDate = $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'];
130
+ } else {
131
+ $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
132
+ }
133
+
134
+ // Create string to sign
135
+ $stringToSign = array();
136
+ $stringToSign[] = $requestDate; // Date
137
+ $stringToSign[] = $canonicalizedResource; // Canonicalized resource
138
+ $stringToSign = implode("\n", $stringToSign);
139
+ $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
140
+
141
+ // Sign request
142
+ $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate;
143
+ $headers['Authorization'] = 'SharedKeyLite ' . $this->_accountName . ':' . $signString;
144
+
145
+ // Return headers
146
+ return $headers;
147
+ }
148
+
149
+ /**
150
+ * Prepare query string for signing
151
+ *
152
+ * @param string $value Original query string
153
+ * @return string Query string for signing
154
+ */
155
+ protected function _prepareQueryStringForSigning($value)
156
+ {
157
+ // Check for 'comp='
158
+ if (strpos($value, 'comp=') === false) {
159
+ // If not found, no query string needed
160
+ return '';
161
+ } else {
162
+ // If found, make sure it is the only parameter being used
163
+ if (strlen($value) > 0 && strpos($value, '?') === 0) {
164
+ $value = substr($value, 1);
165
+ }
166
+
167
+ // Split parts
168
+ $queryParts = explode('&', $value);
169
+ foreach ($queryParts as $queryPart) {
170
+ if (strpos($queryPart, 'comp=') !== false) {
171
+ return '?' . $queryPart;
172
+ }
173
+ }
174
+
175
+ // Should never happen...
176
+ return '';
177
+ }
178
+ }
179
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationDataSources.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationLogs.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationDiagnosticInfrastructureLogs.php';
55
+
56
+ /**
57
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters
58
+ */
59
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationPerformanceCounters.php';
60
+
61
+ /**
62
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog
63
+ */
64
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationWindowsEventLog.php';
65
+
66
+ /**
67
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories
68
+ */
69
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationDirectories.php';
70
+
71
+ /**
72
+ * @category Microsoft
73
+ * @package Microsoft_WindowsAzure
74
+ * @subpackage Diagnostics
75
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
76
+ * @license http://phpazure.codeplex.com/license
77
+ *
78
+ * @property int OverallQuotaInMB Overall quota in MB
79
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs Logs Logs
80
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs DiagnosticInfrastructureLogs Diagnostic infrastructure logs
81
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters PerformanceCounters Performance counters
82
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog WindowsEventLog Windows Event Log
83
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories Directories Directories
84
+ */
85
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources
86
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
87
+ {
88
+ /**
89
+ * Constructor
90
+ *
91
+ * @param int $overallQuotaInMB Overall quota in MB
92
+ */
93
+ public function __construct($overallQuotaInMB = 0)
94
+ {
95
+ $this->_data = array(
96
+ 'overallquotainmb' => $overallQuotaInMB,
97
+ 'logs' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs(),
98
+ 'diagnosticinfrastructurelogs' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs(),
99
+ 'performancecounters' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters(),
100
+ 'windowseventlog' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog(),
101
+ 'directories' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories()
102
+ );
103
+ }
104
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationDiagnosticInfrastructureLogs.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_LogLevel
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/LogLevel.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property string ScheduledTransferLogLevelFilter Scheduled transfer log level filter
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ * @param string $scheduledTransferLogLevelFilter Scheduled transfer log level filter
71
+ */
72
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0, $scheduledTransferLogLevelFilter = Microsoft_WindowsAzure_Diagnostics_LogLevel::UNDEFINED)
73
+ {
74
+ $this->_data = array(
75
+ 'bufferquotainmb' => $bufferQuotaInMB,
76
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
77
+ 'scheduledtransferloglevelfilter' => $scheduledTransferLogLevelFilter
78
+ );
79
+ }
80
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationDirectories.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_DirectoryConfigurationSubscription
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/DirectoryConfigurationSubscription.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property array Subscriptions Subscriptions
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ */
71
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0)
72
+ {
73
+ $this->_data = array(
74
+ 'bufferquotainmb' => $bufferQuotaInMB,
75
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
76
+ 'subscriptions' => array()
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Add subscription
82
+ *
83
+ * @param string $path Path
84
+ * @param string $container Container
85
+ * @param int $directoryQuotaInMB Directory quota in MB
86
+ */
87
+ public function addSubscription($path, $container, $directoryQuotaInMB = 1024)
88
+ {
89
+ $this->_data['subscriptions'][$path] = new Microsoft_WindowsAzure_Diagnostics_DirectoryConfigurationSubscription($path, $container, $directoryQuotaInMB);
90
+ }
91
+
92
+ /**
93
+ * Remove subscription
94
+ *
95
+ * @param string $path Path
96
+ */
97
+ public function removeSubscription($path)
98
+ {
99
+ if (isset($this->_data['subscriptions'][$path])) {
100
+ unset($this->_data['subscriptions'][$path]);
101
+ }
102
+ }
103
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationInstance.php ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationDataSources.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources DataSources Data sources
59
+ */
60
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
61
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
62
+ {
63
+ /**
64
+ * Constructor
65
+ */
66
+ public function __construct()
67
+ {
68
+ $this->_data = array(
69
+ 'datasources' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources()
70
+ );
71
+ }
72
+
73
+ /**
74
+ * Load configuration XML
75
+ *
76
+ * @param string $configurationXml Configuration XML
77
+ */
78
+ public function loadXml($configurationXml)
79
+ {
80
+ // Convert to SimpleXMLElement
81
+ $configurationXml = simplexml_load_string($configurationXml);
82
+
83
+ // Assign general settings
84
+ $this->DataSources->OverallQuotaInMB = (int)$configurationXml->DataSources->OverallQuotaInMB;
85
+
86
+ // Assign Logs settings
87
+ $this->DataSources->Logs->BufferQuotaInMB = (int)$configurationXml->DataSources->Logs->BufferQuotaInMB;
88
+ $this->DataSources->Logs->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->Logs->ScheduledTransferPeriodInMinutes;
89
+ $this->DataSources->Logs->ScheduledTransferLogLevelFilter = (string)$configurationXml->DataSources->Logs->ScheduledTransferLogLevelFilter;
90
+
91
+ // Assign DiagnosticInfrastructureLogs settings
92
+ $this->DataSources->DiagnosticInfrastructureLogs->BufferQuotaInMB = (int)$configurationXml->DataSources->DiagnosticInfrastructureLogs->BufferQuotaInMB;
93
+ $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferPeriodInMinutes;
94
+ $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferLogLevelFilter = (string)$configurationXml->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferLogLevelFilter;
95
+
96
+ // Assign PerformanceCounters settings
97
+ $this->DataSources->PerformanceCounters->BufferQuotaInMB = (int)$configurationXml->DataSources->PerformanceCounters->BufferQuotaInMB;
98
+ $this->DataSources->PerformanceCounters->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->PerformanceCounters->ScheduledTransferPeriodInMinutes;
99
+ if ($configurationXml->DataSources->PerformanceCounters->Subscriptions
100
+ && $configurationXml->DataSources->PerformanceCounters->Subscriptions->PerformanceCounterConfiguration) {
101
+ $subscriptions = $configurationXml->DataSources->PerformanceCounters->Subscriptions;
102
+ if (count($subscriptions->PerformanceCounterConfiguration) > 1) {
103
+ $subscriptions = $subscriptions->PerformanceCounterConfiguration;
104
+ } else {
105
+ $subscriptions = array($subscriptions->PerformanceCounterConfiguration);
106
+ }
107
+ foreach ($subscriptions as $subscription) {
108
+ $this->DataSources->PerformanceCounters->addSubscription((string)$subscription->CounterSpecifier, (int)$subscription->SampleRateInSeconds);
109
+ }
110
+ }
111
+
112
+ // Assign WindowsEventLog settings
113
+ $this->DataSources->WindowsEventLog->BufferQuotaInMB = (int)$configurationXml->DataSources->WindowsEventLog->BufferQuotaInMB;
114
+ $this->DataSources->WindowsEventLog->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->WindowsEventLog->ScheduledTransferPeriodInMinutes;
115
+ $this->DataSources->WindowsEventLog->ScheduledTransferLogLevelFilter = (string)$configurationXml->DataSources->WindowsEventLog->ScheduledTransferLogLevelFilter;
116
+ if ($configurationXml->DataSources->WindowsEventLog->Subscriptions
117
+ && $configurationXml->DataSources->WindowsEventLog->Subscriptions->string) {
118
+ $subscriptions = $configurationXml->DataSources->WindowsEventLog->Subscriptions;
119
+ if (count($subscriptions->string) > 1) {
120
+ $subscriptions = $subscriptions->string;
121
+ } else {
122
+ $subscriptions = array($subscriptions->string);
123
+ }
124
+ foreach ($subscriptions as $subscription) {
125
+ $this->DataSources->WindowsEventLog->addSubscription((string)$subscription);
126
+ }
127
+ }
128
+
129
+ // Assign Directories settings
130
+ $this->DataSources->Directories->BufferQuotaInMB = (int)$configurationXml->DataSources->Directories->BufferQuotaInMB;
131
+ $this->DataSources->Directories->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->Directories->ScheduledTransferPeriodInMinutes;
132
+
133
+ if ($configurationXml->DataSources->Directories->Subscriptions
134
+ && $configurationXml->DataSources->Directories->Subscriptions->DirectoryConfiguration) {
135
+ $subscriptions = $configurationXml->DataSources->Directories->Subscriptions;
136
+ if (count($subscriptions->DirectoryConfiguration) > 1) {
137
+ $subscriptions = $subscriptions->DirectoryConfiguration;
138
+ } else {
139
+ $subscriptions = array($subscriptions->DirectoryConfiguration);
140
+ }
141
+ foreach ($subscriptions as $subscription) {
142
+ $this->DataSources->Directories->addSubscription((string)$subscription->Path, (string)$subscription->Container, (int)$subscription->DirectoryQuotaInMB);
143
+ }
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Create configuration XML
149
+ *
150
+ * @return string
151
+ */
152
+ public function toXml()
153
+ {
154
+ // Return value
155
+ $returnValue = array();
156
+
157
+ // Build XML
158
+ $returnValue[] = '<?xml version="1.0"?>';
159
+ $returnValue[] = '<ConfigRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
160
+
161
+ // Add data sources
162
+ $returnValue[] = ' <DataSources>';
163
+
164
+ $returnValue[] = ' <OverallQuotaInMB>' . $this->DataSources->OverallQuotaInMB . '</OverallQuotaInMB>';
165
+
166
+ $returnValue[] = ' <Logs>';
167
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->Logs->BufferQuotaInMB . '</BufferQuotaInMB>';
168
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->Logs->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
169
+ $returnValue[] = ' <ScheduledTransferLogLevelFilter>' . $this->DataSources->Logs->ScheduledTransferLogLevelFilter . '</ScheduledTransferLogLevelFilter>';
170
+ $returnValue[] = ' </Logs>';
171
+
172
+ $returnValue[] = ' <DiagnosticInfrastructureLogs>';
173
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->DiagnosticInfrastructureLogs->BufferQuotaInMB . '</BufferQuotaInMB>';
174
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
175
+ $returnValue[] = ' <ScheduledTransferLogLevelFilter>' . $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferLogLevelFilter . '</ScheduledTransferLogLevelFilter>';
176
+ $returnValue[] = ' </DiagnosticInfrastructureLogs>';
177
+
178
+ $returnValue[] = ' <PerformanceCounters>';
179
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->PerformanceCounters->BufferQuotaInMB . '</BufferQuotaInMB>';
180
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->PerformanceCounters->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
181
+ if (count($this->DataSources->PerformanceCounters->Subscriptions) == 0) {
182
+ $returnValue[] = ' <Subscriptions />';
183
+ } else {
184
+ $returnValue[] = ' <Subscriptions>';
185
+ foreach ($this->DataSources->PerformanceCounters->Subscriptions as $subscription) {
186
+ $returnValue[] = ' <PerformanceCounterConfiguration>';
187
+ $returnValue[] = ' <CounterSpecifier>' . $subscription->CounterSpecifier . '</CounterSpecifier>';
188
+ $returnValue[] = ' <SampleRateInSeconds>' . $subscription->SampleRateInSeconds . '</SampleRateInSeconds>';
189
+ $returnValue[] = ' </PerformanceCounterConfiguration>';
190
+ }
191
+ $returnValue[] = ' </Subscriptions>';
192
+ }
193
+ $returnValue[] = ' </PerformanceCounters>';
194
+
195
+ $returnValue[] = ' <WindowsEventLog>';
196
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->WindowsEventLog->BufferQuotaInMB . '</BufferQuotaInMB>';
197
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->WindowsEventLog->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
198
+ if (count($this->DataSources->WindowsEventLog->Subscriptions) == 0) {
199
+ $returnValue[] = ' <Subscriptions />';
200
+ } else {
201
+ $returnValue[] = ' <Subscriptions>';
202
+ foreach ($this->DataSources->WindowsEventLog->Subscriptions as $subscription) {
203
+ $returnValue[] = ' <string>' . $subscription . '</string>';
204
+ }
205
+ $returnValue[] = ' </Subscriptions>';
206
+ }
207
+ $returnValue[] = ' <ScheduledTransferLogLevelFilter>' . $this->DataSources->WindowsEventLog->ScheduledTransferLogLevelFilter . '</ScheduledTransferLogLevelFilter>';
208
+ $returnValue[] = ' </WindowsEventLog>';
209
+
210
+ $returnValue[] = ' <Directories>';
211
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->Directories->BufferQuotaInMB . '</BufferQuotaInMB>';
212
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->Directories->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
213
+ if (count($this->DataSources->Directories->Subscriptions) == 0) {
214
+ $returnValue[] = ' <Subscriptions />';
215
+ } else {
216
+ $returnValue[] = ' <Subscriptions>';
217
+ foreach ($this->DataSources->Directories->Subscriptions as $subscription) {
218
+ $returnValue[] = ' <DirectoryConfiguration>';
219
+ $returnValue[] = ' <Path>' . $subscription->Path . '</Path>';
220
+ $returnValue[] = ' <Container>' . $subscription->Container . '</Container>';
221
+ $returnValue[] = ' <DirectoryQuotaInMB>' . $subscription->DirectoryQuotaInMB . '</DirectoryQuotaInMB>';
222
+ $returnValue[] = ' </DirectoryConfiguration>';
223
+ }
224
+ $returnValue[] = ' </Subscriptions>';
225
+ }
226
+ $returnValue[] = ' </Directories>';
227
+
228
+ $returnValue[] = ' </DataSources>';
229
+ $returnValue[] = '</ConfigRequest>';
230
+
231
+ // Return
232
+ return implode("\r\n", $returnValue);
233
+ }
234
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationLogs.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_LogLevel
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/LogLevel.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property string ScheduledTransferLogLevelFilter Scheduled transfer log level filter
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ * @param string $scheduledTransferLogLevelFilter Scheduled transfer log level filter
71
+ */
72
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0, $scheduledTransferLogLevelFilter = Microsoft_WindowsAzure_Diagnostics_LogLevel::UNDEFINED)
73
+ {
74
+ $this->_data = array(
75
+ 'bufferquotainmb' => $bufferQuotaInMB,
76
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
77
+ 'scheduledtransferloglevelfilter' => $scheduledTransferLogLevelFilter
78
+ );
79
+ }
80
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage Diagnostics
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ abstract class Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
49
+ {
50
+ /**
51
+ * Data
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_data = null;
56
+
57
+ /**
58
+ * Magic overload for setting properties
59
+ *
60
+ * @param string $name Name of the property
61
+ * @param string $value Value to set
62
+ */
63
+ public function __set($name, $value) {
64
+ if (array_key_exists(strtolower($name), $this->_data)) {
65
+ $this->_data[strtolower($name)] = $value;
66
+ return;
67
+ }
68
+
69
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception("Unknown property: " . $name);
70
+ }
71
+
72
+ /**
73
+ * Magic overload for getting properties
74
+ *
75
+ * @param string $name Name of the property
76
+ */
77
+ public function __get($name) {
78
+ if (array_key_exists(strtolower($name), $this->_data)) {
79
+ return $this->_data[strtolower($name)];
80
+ }
81
+
82
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception("Unknown property: " . $name);
83
+ }
84
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationPerformanceCounters.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_PerformanceCounterSubscription
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/PerformanceCounterSubscription.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property array Subscriptions Subscriptions
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ */
71
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0)
72
+ {
73
+ $this->_data = array(
74
+ 'bufferquotainmb' => $bufferQuotaInMB,
75
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
76
+ 'subscriptions' => array()
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Add subscription
82
+ *
83
+ * @param string $counterSpecifier Counter specifier
84
+ * @param int $sampleRateInSeconds Sample rate in seconds
85
+ */
86
+ public function addSubscription($counterSpecifier, $sampleRateInSeconds = 1)
87
+ {
88
+ $this->_data['subscriptions'][$counterSpecifier] = new Microsoft_WindowsAzure_Diagnostics_PerformanceCounterSubscription($counterSpecifier, $sampleRateInSeconds);
89
+ }
90
+
91
+ /**
92
+ * Remove subscription
93
+ *
94
+ * @param string $counterSpecifier Counter specifier
95
+ */
96
+ public function removeSubscription($counterSpecifier)
97
+ {
98
+ if (isset($this->_data['subscriptions'][$counterSpecifier])) {
99
+ unset($this->_data['subscriptions'][$counterSpecifier]);
100
+ }
101
+ }
102
+ }
lib/Microsoft/WindowsAzure/Diagnostics/ConfigurationWindowsEventLog.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_LogLevel
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/LogLevel.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property string ScheduledTransferLogLevelFilter Scheduled transfer log level filter
61
+ * @property array Subscriptions Subscriptions
62
+ */
63
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog
64
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
65
+ {
66
+ /**
67
+ * Constructor
68
+ *
69
+ * @param int $bufferQuotaInMB Buffer quota in MB
70
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
71
+ * @param string $scheduledTransferLogLevelFilter Scheduled transfer log level filter
72
+ */
73
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0, $scheduledTransferLogLevelFilter = Microsoft_WindowsAzure_Diagnostics_LogLevel::UNDEFINED)
74
+ {
75
+ $this->_data = array(
76
+ 'bufferquotainmb' => $bufferQuotaInMB,
77
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
78
+ 'scheduledtransferloglevelfilter' => $scheduledTransferLogLevelFilter,
79
+ 'subscriptions' => array()
80
+ );
81
+ }
82
+
83
+ /**
84
+ * Add subscription
85
+ *
86
+ * @param string $filter Event log filter
87
+ */
88
+ public function addSubscription($filter)
89
+ {
90
+ $this->_data['subscriptions'][$filter] = $filter;
91
+ }
92
+
93
+ /**
94
+ * Remove subscription
95
+ *
96
+ * @param string $filter Event log filter
97
+ */
98
+ public function removeSubscription($filter)
99
+ {
100
+ if (isset($this->_data['subscriptions'][$filter])) {
101
+ unset($this->_data['subscriptions'][$filter]);
102
+ }
103
+ }
104
+ }
lib/Microsoft/WindowsAzure/Diagnostics/DirectoryConfigurationSubscription.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Diagnostics
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string Path Path
54
+ * @property string Container Container
55
+ * @property int DirectoryQuotaInMB Directory quota in MB
56
+ */
57
+ class Microsoft_WindowsAzure_Diagnostics_DirectoryConfigurationSubscription
58
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
59
+ {
60
+ /**
61
+ * Constructor
62
+ *
63
+ * @param string $path Path
64
+ * @param string $container Container
65
+ * @param int $directoryQuotaInMB Directory quota in MB
66
+ */
67
+ public function __construct($path, $container, $directoryQuotaInMB = 1024)
68
+ {
69
+ $this->_data = array(
70
+ 'path' => $path,
71
+ 'container' => $container,
72
+ 'directoryquotainmb' => $directoryQuotaInMB
73
+ );
74
+ }
75
+ }
lib/Microsoft/WindowsAzure/Diagnostics/Exception.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage Diagnostics
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ class Microsoft_WindowsAzure_Diagnostics_Exception
49
+ extends Microsoft_WindowsAzure_Exception
50
+ {
51
+ }
lib/Microsoft/WindowsAzure/Diagnostics/LogLevel.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+
37
+ /**
38
+ * @category Microsoft
39
+ * @package Microsoft_WindowsAzure
40
+ * @subpackage Diagnostics
41
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
42
+ * @license http://phpazure.codeplex.com/license
43
+ */
44
+ class Microsoft_WindowsAzure_Diagnostics_LogLevel
45
+ {
46
+ const UNDEFINED = 'Undefined';
47
+ const CRITICAL = 'Critical';
48
+ const ERROR = 'Error';
49
+ const WARNING = 'Warning';
50
+ const INFORMATION = 'Information';
51
+ const VERBOSE = 'Verbose';
52
+ }
lib/Microsoft/WindowsAzure/Diagnostics/Manager.php ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Storage_Blob
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationInstance.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ */
58
+ class Microsoft_WindowsAzure_Diagnostics_Manager
59
+ {
60
+ /**
61
+ * Blob storage client
62
+ *
63
+ * @var Microsoft_WindowsAzure_Storage_Blob
64
+ */
65
+ protected $_blobStorageClient = null;
66
+
67
+ /**
68
+ * Control container name
69
+ *
70
+ * @var string
71
+ */
72
+ protected $_controlContainer = '';
73
+
74
+ /**
75
+ * Create a new instance of Microsoft_WindowsAzure_Diagnostics_Manager
76
+ *
77
+ * @param Microsoft_WindowsAzure_Storage_Blob $blobStorageClient Blob storage client
78
+ * @param string $controlContainer Control container name
79
+ */
80
+ public function __construct(Microsoft_WindowsAzure_Storage_Blob $blobStorageClient = null, $controlContainer = 'wad-control-container')
81
+ {
82
+ $this->_blobStorageClient = $blobStorageClient;
83
+ $this->_controlContainer = $controlContainer;
84
+
85
+ $this->_ensureStorageInitialized();
86
+ }
87
+
88
+ /**
89
+ * Ensure storage has been initialized
90
+ */
91
+ protected function _ensureStorageInitialized()
92
+ {
93
+ if (!$this->_blobStorageClient->containerExists($this->_controlContainer)) {
94
+ $this->_blobStorageClient->createContainer($this->_controlContainer);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Get default configuration values
100
+ *
101
+ * @return Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
102
+ */
103
+ public function getDefaultConfiguration()
104
+ {
105
+ return new Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance();
106
+ }
107
+
108
+ /**
109
+ * Checks if a configuration for a specific role instance exists.
110
+ *
111
+ * @param string $roleInstance Role instance name, can be found in $_SERVER['RdRoleId'] when hosted on Windows Azure.
112
+ * @return boolean
113
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
114
+ */
115
+ public function configurationForRoleInstanceExists($roleInstance = null)
116
+ {
117
+ if (is_null($roleInstance)) {
118
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Role instance should be specified. Try reading $_SERVER[\'RdRoleId\'] for this information if the application is hosted on Windows Azure Fabric or Development Fabric.');
119
+ }
120
+
121
+ return $this->_blobStorageClient->blobExists($this->_controlContainer, $roleInstance);
122
+ }
123
+
124
+ /**
125
+ * Checks if a configuration for current role instance exists. Only works on Development Fabric or Windows Azure Fabric.
126
+ *
127
+ * @return boolean
128
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
129
+ */
130
+ public function configurationForCurrentRoleInstanceExists()
131
+ {
132
+ if (!isset($_SERVER['RdRoleId'])) {
133
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
134
+ }
135
+
136
+ return $this->_blobStorageClient->blobExists($this->_controlContainer, $this->_getCurrentRoleInstanceId());
137
+ }
138
+
139
+ /**
140
+ * Get configuration for current role instance. Only works on Development Fabric or Windows Azure Fabric.
141
+ *
142
+ * @return Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
143
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
144
+ */
145
+ public function getConfigurationForCurrentRoleInstance()
146
+ {
147
+ if (!isset($_SERVER['RdRoleId'])) {
148
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
149
+ }
150
+ return $this->getConfigurationForRoleInstance($this->_getCurrentRoleInstanceId());
151
+ }
152
+
153
+ /**
154
+ * Get the current role instance ID. Only works on Development Fabric or Windows Azure Fabric.
155
+ *
156
+ * @return string
157
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
158
+ */
159
+ protected function _getCurrentRoleInstanceId()
160
+ {
161
+ if (!isset($_SERVER['RdRoleId'])) {
162
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
163
+ }
164
+
165
+ if (strpos($_SERVER['RdRoleId'], 'deployment(') === false) {
166
+ return $_SERVER['RdRoleId'];
167
+ } else {
168
+ $roleIdParts = explode('.', $_SERVER['RdRoleId']);
169
+ return $roleIdParts[0] . '/' . $roleIdParts[2] . '/' . $_SERVER['RdRoleId'];
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Set configuration for current role instance. Only works on Development Fabric or Windows Azure Fabric.
175
+ *
176
+ * @param Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration Configuration to apply
177
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
178
+ */
179
+ public function setConfigurationForCurrentRoleInstance(Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration)
180
+ {
181
+ if (!isset($_SERVER['RdRoleId'])) {
182
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
183
+ }
184
+
185
+ $this->setConfigurationForRoleInstance($this->_getCurrentRoleInstanceId(), $configuration);
186
+ }
187
+
188
+ /**
189
+ * Get configuration for a specific role instance
190
+ *
191
+ * @param string $roleInstance Role instance name, can be found in $_SERVER['RdRoleId'] when hosted on Windows Azure.
192
+ * @return Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
193
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
194
+ */
195
+ public function getConfigurationForRoleInstance($roleInstance = null)
196
+ {
197
+ if (is_null($roleInstance)) {
198
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Role instance should be specified. Try reading $_SERVER[\'RdRoleId\'] for this information if the application is hosted on Windows Azure Fabric or Development Fabric.');
199
+ }
200
+
201
+ if ($this->_blobStorageClient->blobExists($this->_controlContainer, $roleInstance)) {
202
+ $configurationInstance = new Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance();
203
+ $configurationInstance->loadXml( $this->_blobStorageClient->getBlobData($this->_controlContainer, $roleInstance) );
204
+ return $configurationInstance;
205
+ }
206
+
207
+ return new Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance();
208
+ }
209
+
210
+ /**
211
+ * Set configuration for a specific role instance
212
+ *
213
+ * @param string $roleInstance Role instance name, can be found in $_SERVER['RdRoleId'] when hosted on Windows Azure.
214
+ * @param Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration Configuration to apply
215
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
216
+ */
217
+ public function setConfigurationForRoleInstance($roleInstance = null, Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration)
218
+ {
219
+ if (is_null($roleInstance)) {
220
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Role instance should be specified. Try reading $_SERVER[\'RdRoleId\'] for this information if the application is hosted on Windows Azure Fabric or Development Fabric.');
221
+ }
222
+
223
+ $this->_blobStorageClient->putBlobData($this->_controlContainer, $roleInstance, $configuration->toXml(), array(), null, array('Content-Type' => 'text/xml'));
224
+ }
225
+ }
lib/Microsoft/WindowsAzure/Diagnostics/PerformanceCounterSubscription.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Diagnostics
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string CounterSpecifier Counter specifier
54
+ * @property int SampleRateInSeconds Sample rate in seconds
55
+ */
56
+ class Microsoft_WindowsAzure_Diagnostics_PerformanceCounterSubscription
57
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
58
+ {
59
+ /**
60
+ * Constructor
61
+ *
62
+ * @param string $counterSpecifier Counter specifier
63
+ * @param int $sampleRateInSeconds Sample rate in seconds
64
+ */
65
+ public function __construct($counterSpecifier, $sampleRateInSeconds = 1)
66
+ {
67
+ $this->_data = array(
68
+ 'counterspecifier' => $counterSpecifier,
69
+ 'samplerateinseconds' => $sampleRateInSeconds
70
+ );
71
+ }
72
+ }
lib/Microsoft/WindowsAzure/Exception.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_Exception
38
+ */
39
+ require_once 'Microsoft/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
45
+ * @license http://phpazure.codeplex.com/license
46
+ */
47
+ class Microsoft_WindowsAzure_Exception extends Microsoft_Exception
48
+ {}
lib/Microsoft/WindowsAzure/RetryPolicy/Exception.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage RetryPolicy
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ class Microsoft_WindowsAzure_RetryPolicy_Exception extends Microsoft_WindowsAzure_Exception
49
+ {}
lib/Microsoft/WindowsAzure/RetryPolicy/NoRetry.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage RetryPolicy
31
+ * @version $Id: NoRetry.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage RetryPolicy
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ class Microsoft_WindowsAzure_RetryPolicy_NoRetry extends Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
49
+ {
50
+ /**
51
+ * Execute function under retry policy
52
+ *
53
+ * @param string|array $function Function to execute
54
+ * @param array $parameters Parameters for function call
55
+ * @return mixed
56
+ */
57
+ public function execute($function, $parameters = array())
58
+ {
59
+ $returnValue = null;
60
+
61
+ try
62
+ {
63
+ $returnValue = call_user_func_array($function, $parameters);
64
+ return $returnValue;
65
+ }
66
+ catch (Exception $ex)
67
+ {
68
+ throw $ex;
69
+ }
70
+ }
71
+ }
lib/Microsoft/WindowsAzure/RetryPolicy/RetryN.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage RetryPolicy
31
+ * @version $Id: RetryN.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_RetryPolicy_Exception
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/Exception.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage RetryPolicy
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ */
53
+ class Microsoft_WindowsAzure_RetryPolicy_RetryN extends Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
54
+ {
55
+ /**
56
+ * Number of retries
57
+ *
58
+ * @var int
59
+ */
60
+ protected $_retryCount = 1;
61
+
62
+ /**
63
+ * Interval between retries (in milliseconds)
64
+ *
65
+ * @var int
66
+ */
67
+ protected $_retryInterval = 0;
68
+
69
+ /**
70
+ * Constructor
71
+ *
72
+ * @param int $count Number of retries
73
+ * @param int $intervalBetweenRetries Interval between retries (in milliseconds)
74
+ */
75
+ public function __construct($count = 1, $intervalBetweenRetries = 0)
76
+ {
77
+ $this->_retryCount = $count;
78
+ $this->_retryInterval = $intervalBetweenRetries;
79
+ }
80
+
81
+ /**
82
+ * Execute function under retry policy
83
+ *
84
+ * @param string|array $function Function to execute
85
+ * @param array $parameters Parameters for function call
86
+ * @return mixed
87
+ */
88
+ public function execute($function, $parameters = array())
89
+ {
90
+ $returnValue = null;
91
+
92
+ for ($retriesLeft = $this->_retryCount; $retriesLeft >= 0; --$retriesLeft) {
93
+ try {
94
+ $returnValue = call_user_func_array($function, $parameters);
95
+ return $returnValue;
96
+ } catch (Exception $ex) {
97
+ if ($retriesLeft == 1) {
98
+ throw new Microsoft_WindowsAzure_RetryPolicy_Exception("Exceeded retry count of " . $this->_retryCount . ". " . $ex->getMessage());
99
+ }
100
+
101
+ usleep($this->_retryInterval * 1000);
102
+ }
103
+ }
104
+ }
105
+ }
lib/Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage RetryPolicy
31
+ * @version $Id: RetryPolicy.php 28585 2009-09-07 12:12:56Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_RetryPolicy_NoRetry
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/NoRetry.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryN
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryN.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage RetryPolicy
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ */
58
+ abstract class Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
59
+ {
60
+ /**
61
+ * Execute function under retry policy
62
+ *
63
+ * @param string|array $function Function to execute
64
+ * @param array $parameters Parameters for function call
65
+ * @return mixed
66
+ */
67
+ public abstract function execute($function, $parameters = array());
68
+
69
+ /**
70
+ * Create a Microsoft_WindowsAzure_RetryPolicy_NoRetry instance
71
+ *
72
+ * @return Microsoft_WindowsAzure_RetryPolicy_NoRetry
73
+ */
74
+ public static function noRetry()
75
+ {
76
+ return new Microsoft_WindowsAzure_RetryPolicy_NoRetry();
77
+ }
78
+
79
+ /**
80
+ * Create a Microsoft_WindowsAzure_RetryPolicy_RetryN instance
81
+ *
82
+ * @param int $count Number of retries
83
+ * @param int $intervalBetweenRetries Interval between retries (in milliseconds)
84
+ * @return Microsoft_WindowsAzure_RetryPolicy_RetryN
85
+ */
86
+ public static function retryN($count = 1, $intervalBetweenRetries = 0)
87
+ {
88
+ return new Microsoft_WindowsAzure_RetryPolicy_RetryN($count, $intervalBetweenRetries);
89
+ }
90
+ }
lib/Microsoft/WindowsAzure/SessionHandler.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Session
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 21617 2009-06-12 10:46:31Z unknown $
34
+ */
35
+
36
+ /** Microsoft_WindowsAzure_Storage_Table */
37
+ require_once 'Microsoft/WindowsAzure/Storage/Table.php';
38
+
39
+ /**
40
+ * @see Microsoft_WindowsAzure_Exception
41
+ */
42
+ require_once 'Microsoft/WindowsAzure/Exception.php';
43
+
44
+ /**
45
+ * @category Microsoft
46
+ * @package Microsoft_WindowsAzure
47
+ * @subpackage Session
48
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
49
+ * @license http://phpazure.codeplex.com/license
50
+ */
51
+ class Microsoft_WindowsAzure_SessionHandler
52
+ {
53
+ /**
54
+ * Table storage
55
+ *
56
+ * @var Microsoft_WindowsAzure_Storage_Table
57
+ */
58
+ protected $_tableStorage;
59
+
60
+ /**
61
+ * Session table name
62
+ *
63
+ * @var string
64
+ */
65
+ protected $_sessionTable;
66
+
67
+ /**
68
+ * Session table partition
69
+ *
70
+ * @var string
71
+ */
72
+ protected $_sessionTablePartition;
73
+
74
+ /**
75
+ * Creates a new Microsoft_WindowsAzure_SessionHandler instance
76
+ *
77
+ * @param Microsoft_WindowsAzure_Storage_Table $tableStorage Table storage
78
+ * @param string $sessionTable Session table name
79
+ * @param string $sessionTablePartition Session table partition
80
+ */
81
+ public function __construct(Microsoft_WindowsAzure_Storage_Table $tableStorage, $sessionTable = 'phpsessions', $sessionTablePartition = 'sessions')
82
+ {
83
+ // Set properties
84
+ $this->_tableStorage = $tableStorage;
85
+ $this->_sessionTable = $sessionTable;
86
+ $this->_sessionTablePartition = $sessionTablePartition;
87
+ }
88
+
89
+ /**
90
+ * Registers the current session handler as PHP's session handler
91
+ *
92
+ * @return boolean
93
+ */
94
+ public function register()
95
+ {
96
+ return session_set_save_handler(array($this, 'open'),
97
+ array($this, 'close'),
98
+ array($this, 'read'),
99
+ array($this, 'write'),
100
+ array($this, 'destroy'),
101
+ array($this, 'gc')
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Open the session store
107
+ *
108
+ * @return bool
109
+ */
110
+ public function open()
111
+ {
112
+ // Make sure table exists
113
+ $tableExists = $this->_tableStorage->tableExists($this->_sessionTable);
114
+ if (!$tableExists) {
115
+ $this->_tableStorage->createTable($this->_sessionTable);
116
+ }
117
+
118
+ // Ok!
119
+ return true;
120
+ }
121
+
122
+ /**
123
+ * Close the session store
124
+ *
125
+ * @return bool
126
+ */
127
+ public function close()
128
+ {
129
+ return true;
130
+ }
131
+
132
+ /**
133
+ * Read a specific session
134
+ *
135
+ * @param int $id Session Id
136
+ * @return string
137
+ */
138
+ public function read($id)
139
+ {
140
+ try
141
+ {
142
+ $sessionRecord = $this->_tableStorage->retrieveEntityById(
143
+ $this->_sessionTable,
144
+ $this->_sessionTablePartition,
145
+ $id
146
+ );
147
+ return base64_decode($sessionRecord->serializedData);
148
+ }
149
+ catch (Microsoft_WindowsAzure_Exception $ex)
150
+ {
151
+ return '';
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Write a specific session
157
+ *
158
+ * @param int $id Session Id
159
+ * @param string $serializedData Serialized PHP object
160
+ */
161
+ public function write($id, $serializedData)
162
+ {
163
+ $sessionRecord = new Microsoft_WindowsAzure_Storage_DynamicTableEntity($this->_sessionTablePartition, $id);
164
+ $sessionRecord->sessionExpires = time();
165
+ $sessionRecord->serializedData = base64_encode($serializedData);
166
+
167
+ $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32');
168
+
169
+ try
170
+ {
171
+ $this->_tableStorage->updateEntity($this->_sessionTable, $sessionRecord);
172
+ }
173
+ catch (Microsoft_WindowsAzure_Exception $unknownRecord)
174
+ {
175
+ $this->_tableStorage->insertEntity($this->_sessionTable, $sessionRecord);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Destroy a specific session
181
+ *
182
+ * @param int $id Session Id
183
+ * @return boolean
184
+ */
185
+ public function destroy($id)
186
+ {
187
+ try
188
+ {
189
+ $sessionRecord = $this->_tableStorage->retrieveEntityById(
190
+ $this->_sessionTable,
191
+ $this->_sessionTablePartition,
192
+ $id
193
+ );
194
+ $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord);
195
+
196
+ return true;
197
+ }
198
+ catch (Microsoft_WindowsAzure_Exception $ex)
199
+ {
200
+ return false;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Garbage collector
206
+ *
207
+ * @param int $lifeTime Session maximal lifetime
208
+ * @see session.gc_divisor 100
209
+ * @see session.gc_maxlifetime 1440
210
+ * @see session.gc_probability 1
211
+ * @usage Execution rate 1/100 (session.gc_probability/session.gc_divisor)
212
+ * @return boolean
213
+ */
214
+ public function gc($lifeTime)
215
+ {
216
+ try
217
+ {
218
+ $result = $this->_tableStorage->retrieveEntities($this->_sessionTable, 'PartitionKey eq \'' . $this->_sessionTablePartition . '\' and sessionExpires lt ' . (time() - $lifeTime));
219
+ foreach ($result as $sessionRecord)
220
+ {
221
+ $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord);
222
+ }
223
+ return true;
224
+ }
225
+ catch (Microsoft_WindowsAzure_exception $ex)
226
+ {
227
+ return false;
228
+ }
229
+ }
230
+ }
lib/Microsoft/WindowsAzure/Storage.php ADDED
@@ -0,0 +1,586 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 51671 2010-09-30 08:33:45Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_SharedKey
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_Exception
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/Exception.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Client
58
+ */
59
+ require_once 'Microsoft/Http/Client.php';
60
+
61
+ /**
62
+ * @see Microsoft_Http_Response
63
+ */
64
+ require_once 'Microsoft/Http/Response.php';
65
+
66
+ /**
67
+ * @category Microsoft
68
+ * @package Microsoft_WindowsAzure
69
+ * @subpackage Storage
70
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
71
+ * @license http://phpazure.codeplex.com/license
72
+ */
73
+ class Microsoft_WindowsAzure_Storage
74
+ {
75
+ /**
76
+ * Development storage URLS
77
+ */
78
+ const URL_DEV_BLOB = "127.0.0.1:10000";
79
+ const URL_DEV_QUEUE = "127.0.0.1:10001";
80
+ const URL_DEV_TABLE = "127.0.0.1:10002";
81
+
82
+ /**
83
+ * Live storage URLS
84
+ */
85
+ const URL_CLOUD_BLOB = "blob.core.windows.net";
86
+ const URL_CLOUD_QUEUE = "queue.core.windows.net";
87
+ const URL_CLOUD_TABLE = "table.core.windows.net";
88
+
89
+ /**
90
+ * Resource types
91
+ */
92
+ const RESOURCE_UNKNOWN = "unknown";
93
+ const RESOURCE_CONTAINER = "c";
94
+ const RESOURCE_BLOB = "b";
95
+ const RESOURCE_TABLE = "t";
96
+ const RESOURCE_ENTITY = "e";
97
+ const RESOURCE_QUEUE = "q";
98
+
99
+ /**
100
+ * HTTP header prefixes
101
+ */
102
+ const PREFIX_PROPERTIES = "x-ms-prop-";
103
+ const PREFIX_METADATA = "x-ms-meta-";
104
+ const PREFIX_STORAGE_HEADER = "x-ms-";
105
+
106
+ /**
107
+ * Current API version
108
+ *
109
+ * @var string
110
+ */
111
+ protected $_apiVersion = '2009-09-19';
112
+
113
+ /**
114
+ * Storage host name
115
+ *
116
+ * @var string
117
+ */
118
+ protected $_host = '';
119
+
120
+ /**
121
+ * Account name for Windows Azure
122
+ *
123
+ * @var string
124
+ */
125
+ protected $_accountName = '';
126
+
127
+ /**
128
+ * Account key for Windows Azure
129
+ *
130
+ * @var string
131
+ */
132
+ protected $_accountKey = '';
133
+
134
+ /**
135
+ * Use path-style URI's
136
+ *
137
+ * @var boolean
138
+ */
139
+ protected $_usePathStyleUri = false;
140
+
141
+ /**
142
+ * Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
143
+ *
144
+ * @var Microsoft_WindowsAzure_Credentials_CredentialsAbstract
145
+ */
146
+ protected $_credentials = null;
147
+
148
+ /**
149
+ * Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance
150
+ *
151
+ * @var Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
152
+ */
153
+ protected $_retryPolicy = null;
154
+
155
+ /**
156
+ * Microsoft_Http_Client channel used for communication with REST services
157
+ *
158
+ * @var Microsoft_Http_Client
159
+ */
160
+ protected $_httpClientChannel = null;
161
+
162
+ /**
163
+ * Use proxy?
164
+ *
165
+ * @var boolean
166
+ */
167
+ protected $_useProxy = false;
168
+
169
+ /**
170
+ * Proxy url
171
+ *
172
+ * @var string
173
+ */
174
+ protected $_proxyUrl = '';
175
+
176
+ /**
177
+ * Proxy port
178
+ *
179
+ * @var int
180
+ */
181
+ protected $_proxyPort = 80;
182
+
183
+ /**
184
+ * Proxy credentials
185
+ *
186
+ * @var string
187
+ */
188
+ protected $_proxyCredentials = '';
189
+
190
+ /**
191
+ * Creates a new Microsoft_WindowsAzure_Storage instance
192
+ *
193
+ * @param string $host Storage host name
194
+ * @param string $accountName Account name for Windows Azure
195
+ * @param string $accountKey Account key for Windows Azure
196
+ * @param boolean $usePathStyleUri Use path-style URI's
197
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
198
+ */
199
+ public function __construct(
200
+ $host = self::URL_DEV_BLOB,
201
+ $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
202
+ $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
203
+ $usePathStyleUri = false,
204
+ Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null
205
+ ) {
206
+ $this->_host = $host;
207
+ $this->_accountName = $accountName;
208
+ $this->_accountKey = $accountKey;
209
+ $this->_usePathStyleUri = $usePathStyleUri;
210
+
211
+ // Using local storage?
212
+ if (!$this->_usePathStyleUri
213
+ && ($this->_host == self::URL_DEV_BLOB
214
+ || $this->_host == self::URL_DEV_QUEUE
215
+ || $this->_host == self::URL_DEV_TABLE)
216
+ ) {
217
+ // Local storage
218
+ $this->_usePathStyleUri = true;
219
+ }
220
+
221
+ if (is_null($this->_credentials)) {
222
+ $this->_credentials = new Microsoft_WindowsAzure_Credentials_SharedKey(
223
+ $this->_accountName, $this->_accountKey, $this->_usePathStyleUri);
224
+ }
225
+
226
+ $this->_retryPolicy = $retryPolicy;
227
+ if (is_null($this->_retryPolicy)) {
228
+ $this->_retryPolicy = Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
229
+ }
230
+
231
+ // Setup default Microsoft_Http_Client channel
232
+ $options = array(
233
+ 'adapter' => 'Microsoft_Http_Client_Adapter_Proxy'
234
+ );
235
+ if (function_exists('curl_init')) {
236
+ // Set cURL options if cURL is used afterwards
237
+ $options['curloptions'] = array(
238
+ CURLOPT_FOLLOWLOCATION => true,
239
+ CURLOPT_TIMEOUT => 120,
240
+ );
241
+ }
242
+ $this->_httpClientChannel = new Microsoft_Http_Client(null, $options);
243
+ }
244
+
245
+ /**
246
+ * Set the HTTP client channel to use
247
+ *
248
+ * @param Microsoft_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name.
249
+ */
250
+ public function setHttpClientChannel($adapterInstance = 'Microsoft_Http_Client_Adapter_Proxy')
251
+ {
252
+ $this->_httpClientChannel->setAdapter($adapterInstance);
253
+ }
254
+
255
+ /**
256
+ * Retrieve HTTP client channel
257
+ *
258
+ * @return Microsoft_Http_Client_Adapter_Interface
259
+ */
260
+ public function getHttpClientChannel()
261
+ {
262
+ return $this->_httpClientChannel;
263
+ }
264
+
265
+ /**
266
+ * Set retry policy to use when making requests
267
+ *
268
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
269
+ */
270
+ public function setRetryPolicy(Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
271
+ {
272
+ $this->_retryPolicy = $retryPolicy;
273
+ if (is_null($this->_retryPolicy)) {
274
+ $this->_retryPolicy = Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Set proxy
280
+ *
281
+ * @param boolean $useProxy Use proxy?
282
+ * @param string $proxyUrl Proxy URL
283
+ * @param int $proxyPort Proxy port
284
+ * @param string $proxyCredentials Proxy credentials
285
+ */
286
+ public function setProxy($useProxy = false, $proxyUrl = '', $proxyPort = 80, $proxyCredentials = '')
287
+ {
288
+ $this->_useProxy = $useProxy;
289
+ $this->_proxyUrl = $proxyUrl;
290
+ $this->_proxyPort = $proxyPort;
291
+ $this->_proxyCredentials = $proxyCredentials;
292
+
293
+ if ($this->_useProxy) {
294
+ $credentials = explode(':', $this->_proxyCredentials);
295
+
296
+ $this->_httpClientChannel->setConfig(array(
297
+ 'proxy_host' => $this->_proxyUrl,
298
+ 'proxy_port' => $this->_proxyPort,
299
+ 'proxy_user' => $credentials[0],
300
+ 'proxy_pass' => $credentials[1],
301
+ ));
302
+ } else {
303
+ $this->_httpClientChannel->setConfig(array(
304
+ 'proxy_host' => '',
305
+ 'proxy_port' => 8080,
306
+ 'proxy_user' => '',
307
+ 'proxy_pass' => '',
308
+ ));
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Returns the Windows Azure account name
314
+ *
315
+ * @return string
316
+ */
317
+ public function getAccountName()
318
+ {
319
+ return $this->_accountName;
320
+ }
321
+
322
+ /**
323
+ * Get base URL for creating requests
324
+ *
325
+ * @return string
326
+ */
327
+ public function getBaseUrl()
328
+ {
329
+ if ($this->_usePathStyleUri) {
330
+ return 'http://' . $this->_host . '/' . $this->_accountName;
331
+ } else {
332
+ return 'http://' . $this->_accountName . '.' . $this->_host;
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Set Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
338
+ *
339
+ * @param Microsoft_WindowsAzure_Credentials_CredentialsAbstract $credentials Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance to use for request signing.
340
+ */
341
+ public function setCredentials(Microsoft_WindowsAzure_Credentials_CredentialsAbstract $credentials)
342
+ {
343
+ $this->_credentials = $credentials;
344
+ $this->_credentials->setAccountName($this->_accountName);
345
+ $this->_credentials->setAccountkey($this->_accountKey);
346
+ $this->_credentials->setUsePathStyleUri($this->_usePathStyleUri);
347
+ }
348
+
349
+ /**
350
+ * Get Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
351
+ *
352
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
353
+ */
354
+ public function getCredentials()
355
+ {
356
+ return $this->_credentials;
357
+ }
358
+
359
+ /**
360
+ * Perform request using Microsoft_Http_Client channel
361
+ *
362
+ * @param string $path Path
363
+ * @param string $queryString Query string
364
+ * @param string $httpVerb HTTP verb the request will use
365
+ * @param array $headers x-ms headers to add
366
+ * @param boolean $forTableStorage Is the request for table storage?
367
+ * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
368
+ * @param string $resourceType Resource type
369
+ * @param string $requiredPermission Required permission
370
+ * @return Microsoft_Http_Response
371
+ */
372
+ protected function _performRequest(
373
+ $path = '/',
374
+ $queryString = '',
375
+ $httpVerb = Microsoft_Http_Client::GET,
376
+ $headers = array(),
377
+ $forTableStorage = false,
378
+ $rawData = null,
379
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
380
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
381
+ ) {
382
+ // Clean path
383
+ if (strpos($path, '/') !== 0) {
384
+ $path = '/' . $path;
385
+ }
386
+
387
+ // Clean headers
388
+ if (is_null($headers)) {
389
+ $headers = array();
390
+ }
391
+
392
+ // Ensure cUrl will also work correctly:
393
+ // - disable Content-Type if required
394
+ // - disable Expect: 100 Continue
395
+ if (!isset($headers["Content-Type"])) {
396
+ $headers["Content-Type"] = '';
397
+ }
398
+ $headers["Expect"]= '';
399
+
400
+ // Add version header
401
+ $headers['x-ms-version'] = $this->_apiVersion;
402
+
403
+ // URL encoding
404
+ $path = self::urlencode($path);
405
+ $queryString = self::urlencode($queryString);
406
+
407
+ // Generate URL and sign request
408
+ $requestUrl = $this->_credentials
409
+ ->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission);
410
+ $requestHeaders = $this->_credentials
411
+ ->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission, $rawData);
412
+
413
+ // Prepare request
414
+ $this->_httpClientChannel->resetParameters(true);
415
+ $this->_httpClientChannel->setUri($requestUrl);
416
+ $this->_httpClientChannel->setHeaders($requestHeaders);
417
+ $this->_httpClientChannel->setRawData($rawData);
418
+
419
+ // Execute request
420
+ $response = $this->_retryPolicy->execute(
421
+ array($this->_httpClientChannel, 'request'),
422
+ array($httpVerb)
423
+ );
424
+
425
+ return $response;
426
+ }
427
+
428
+ /**
429
+ * Parse result from Microsoft_Http_Response
430
+ *
431
+ * @param Microsoft_Http_Response $response Response from HTTP call
432
+ * @return object
433
+ * @throws Microsoft_WindowsAzure_Exception
434
+ */
435
+ protected function _parseResponse(Microsoft_Http_Response $response = null)
436
+ {
437
+ if (is_null($response)) {
438
+ throw new Microsoft_WindowsAzure_Exception('Response should not be null.');
439
+ }
440
+
441
+ $xml = @simplexml_load_string($response->getBody());
442
+
443
+ if ($xml !== false) {
444
+ // Fetch all namespaces
445
+ $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true));
446
+
447
+ // Register all namespace prefixes
448
+ foreach ($namespaces as $prefix => $ns) {
449
+ if ($prefix != '') {
450
+ $xml->registerXPathNamespace($prefix, $ns);
451
+ }
452
+ }
453
+ }
454
+
455
+ return $xml;
456
+ }
457
+
458
+ /**
459
+ * Generate metadata headers
460
+ *
461
+ * @param array $metadata
462
+ * @return HTTP headers containing metadata
463
+ */
464
+ protected function _generateMetadataHeaders($metadata = array())
465
+ {
466
+ // Validate
467
+ if (!is_array($metadata)) {
468
+ return array();
469
+ }
470
+
471
+ // Return headers
472
+ $headers = array();
473
+ foreach ($metadata as $key => $value) {
474
+ if (strpos($value, "\r") !== false || strpos($value, "\n") !== false) {
475
+ throw new Microsoft_WindowsAzure_Exception('Metadata cannot contain newline characters.');
476
+ }
477
+
478
+ if (!self::isValidMetadataName($key)) {
479
+ throw new Microsoft_WindowsAzure_Exception('Metadata name does not adhere to metadata naming conventions. See http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx for more information.');
480
+ }
481
+
482
+ $headers["x-ms-meta-" . strtolower($key)] = $value;
483
+ }
484
+ return $headers;
485
+ }
486
+
487
+ /**
488
+ * Parse metadata headers
489
+ *
490
+ * @param array $headers HTTP headers containing metadata
491
+ * @return array
492
+ */
493
+ protected function _parseMetadataHeaders($headers = array())
494
+ {
495
+ // Validate
496
+ if (!is_array($headers)) {
497
+ return array();
498
+ }
499
+
500
+ // Return metadata
501
+ $metadata = array();
502
+ foreach ($headers as $key => $value) {
503
+ if (substr(strtolower($key), 0, 10) == "x-ms-meta-") {
504
+ $metadata[str_replace("x-ms-meta-", '', strtolower($key))] = $value;
505
+ }
506
+ }
507
+ return $metadata;
508
+ }
509
+
510
+ /**
511
+ * Parse metadata XML
512
+ *
513
+ * @param SimpleXMLElement $parentElement Element containing the Metadata element.
514
+ * @return array
515
+ */
516
+ protected function _parseMetadataElement($element = null)
517
+ {
518
+ // Metadata present?
519
+ if (!is_null($element) && isset($element->Metadata) && !is_null($element->Metadata)) {
520
+ return get_object_vars($element->Metadata);
521
+ }
522
+
523
+ return array();
524
+ }
525
+
526
+ /**
527
+ * Generate ISO 8601 compliant date string in UTC time zone
528
+ *
529
+ * @param int $timestamp
530
+ * @return string
531
+ */
532
+ public function isoDate($timestamp = null)
533
+ {
534
+ $tz = @date_default_timezone_get();
535
+ @date_default_timezone_set('UTC');
536
+
537
+ if (is_null($timestamp)) {
538
+ $timestamp = time();
539
+ }
540
+
541
+ $returnValue = str_replace('+00:00', '.0000000Z', @date('c', $timestamp));
542
+ @date_default_timezone_set($tz);
543
+ return $returnValue;
544
+ }
545
+
546
+ /**
547
+ * URL encode function
548
+ *
549
+ * @param string $value Value to encode
550
+ * @return string Encoded value
551
+ */
552
+ public static function urlencode($value)
553
+ {
554
+ return str_replace(' ', '%20', $value);
555
+ }
556
+
557
+ /**
558
+ * Is valid metadata name?
559
+ *
560
+ * @param string $metadataName Metadata name
561
+ * @return boolean
562
+ */
563
+ public static function isValidMetadataName($metadataName = '')
564
+ {
565
+ if (preg_match("/^[a-zA-Z0-9_@][a-zA-Z0-9_]*$/", $metadataName) === 0) {
566
+ return false;
567
+ }
568
+
569
+ if ($metadataName == '') {
570
+ return false;
571
+ }
572
+
573
+ return true;
574
+ }
575
+
576
+ /**
577
+ * Builds a query string from an array of elements
578
+ *
579
+ * @param array Array of elements
580
+ * @return string Assembled query string
581
+ */
582
+ public static function createQueryStringFromArray($queryString)
583
+ {
584
+ return count($queryString) > 0 ? '?' . implode('&', $queryString) : '';
585
+ }
586
+ }
lib/Microsoft/WindowsAzure/Storage/Batch.php ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 21617 2009-06-12 10:46:31Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_BatchStorageAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ */
53
+ class Microsoft_WindowsAzure_Storage_Batch
54
+ {
55
+ /**
56
+ * Storage client the batch is defined on
57
+ *
58
+ * @var Microsoft_WindowsAzure_Storage_BatchStorageAbstract
59
+ */
60
+ protected $_storageClient = null;
61
+
62
+ /**
63
+ * For table storage?
64
+ *
65
+ * @var boolean
66
+ */
67
+ protected $_forTableStorage = false;
68
+
69
+ /**
70
+ * Base URL
71
+ *
72
+ * @var string
73
+ */
74
+ protected $_baseUrl;
75
+
76
+ /**
77
+ * Pending operations
78
+ *
79
+ * @var unknown_type
80
+ */
81
+ protected $_operations = array();
82
+
83
+ /**
84
+ * Does the batch contain a single select?
85
+ *
86
+ * @var boolean
87
+ */
88
+ protected $_isSingleSelect = false;
89
+
90
+ /**
91
+ * Creates a new Microsoft_WindowsAzure_Storage_Batch
92
+ *
93
+ * @param Microsoft_WindowsAzure_Storage_BatchStorageAbstract $storageClient Storage client the batch is defined on
94
+ */
95
+ public function __construct(Microsoft_WindowsAzure_Storage_BatchStorageAbstract $storageClient = null, $baseUrl = '')
96
+ {
97
+ $this->_storageClient = $storageClient;
98
+ $this->_baseUrl = $baseUrl;
99
+ $this->_beginBatch();
100
+ }
101
+
102
+ /**
103
+ * Get base URL for creating requests
104
+ *
105
+ * @return string
106
+ */
107
+ public function getBaseUrl()
108
+ {
109
+ return $this->_baseUrl;
110
+ }
111
+
112
+ /**
113
+ * Starts a new batch operation set
114
+ *
115
+ * @throws Microsoft_WindowsAzure_Exception
116
+ */
117
+ protected function _beginBatch()
118
+ {
119
+ $this->_storageClient->setCurrentBatch($this);
120
+ }
121
+
122
+ /**
123
+ * Cleanup current batch
124
+ */
125
+ protected function _clean()
126
+ {
127
+ unset($this->_operations);
128
+ $this->_storageClient->setCurrentBatch(null);
129
+ $this->_storageClient = null;
130
+ unset($this);
131
+ }
132
+
133
+ /**
134
+ * Enlist operation in current batch
135
+ *
136
+ * @param string $path Path
137
+ * @param string $queryString Query string
138
+ * @param string $httpVerb HTTP verb the request will use
139
+ * @param array $headers x-ms headers to add
140
+ * @param boolean $forTableStorage Is the request for table storage?
141
+ * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
142
+ * @throws Microsoft_WindowsAzure_Exception
143
+ */
144
+ public function enlistOperation($path = '/', $queryString = '', $httpVerb = Microsoft_Http_Client::GET, $headers = array(), $forTableStorage = false, $rawData = null)
145
+ {
146
+ // Set _forTableStorage
147
+ if ($forTableStorage) {
148
+ $this->_forTableStorage = true;
149
+ }
150
+
151
+ // Set _isSingleSelect
152
+ if ($httpVerb == Microsoft_Http_Client::GET) {
153
+ if (count($this->_operations) > 0) {
154
+ throw new Microsoft_WindowsAzure_Exception("Select operations can only be performed in an empty batch transaction.");
155
+ }
156
+ $this->_isSingleSelect = true;
157
+ }
158
+
159
+ // Clean path
160
+ if (strpos($path, '/') !== 0) {
161
+ $path = '/' . $path;
162
+ }
163
+
164
+ // Clean headers
165
+ if (is_null($headers)) {
166
+ $headers = array();
167
+ }
168
+
169
+ // URL encoding
170
+ $path = Microsoft_WindowsAzure_Storage::urlencode($path);
171
+ $queryString = Microsoft_WindowsAzure_Storage::urlencode($queryString);
172
+
173
+ // Generate URL
174
+ $requestUrl = $this->getBaseUrl() . $path . $queryString;
175
+
176
+ // Generate $rawData
177
+ if (is_null($rawData)) {
178
+ $rawData = '';
179
+ }
180
+
181
+ // Add headers
182
+ if ($httpVerb != Microsoft_Http_Client::GET) {
183
+ $headers['Content-ID'] = count($this->_operations) + 1;
184
+ if ($httpVerb != Microsoft_Http_Client::DELETE) {
185
+ $headers['Content-Type'] = 'application/atom+xml;type=entry';
186
+ }
187
+ $headers['Content-Length'] = strlen($rawData);
188
+ }
189
+
190
+ // Generate $operation
191
+ $operation = '';
192
+ $operation .= $httpVerb . ' ' . $requestUrl . ' HTTP/1.1' . "\n";
193
+ foreach ($headers as $key => $value)
194
+ {
195
+ $operation .= $key . ': ' . $value . "\n";
196
+ }
197
+ $operation .= "\n";
198
+
199
+ // Add data
200
+ $operation .= $rawData;
201
+
202
+ // Store operation
203
+ $this->_operations[] = $operation;
204
+ }
205
+
206
+ /**
207
+ * Commit current batch
208
+ *
209
+ * @return Microsoft_Http_Response
210
+ * @throws Microsoft_WindowsAzure_Exception
211
+ */
212
+ public function commit()
213
+ {
214
+ // Perform batch
215
+ $response = $this->_storageClient->performBatch($this->_operations, $this->_forTableStorage, $this->_isSingleSelect);
216
+
217
+ // Dispose
218
+ $this->_clean();
219
+
220
+ // Parse response
221
+ $errors = null;
222
+ preg_match_all('/<message (.*)>(.*)<\/message>/', $response->getBody(), $errors);
223
+
224
+ // Error?
225
+ if (count($errors[2]) > 0) {
226
+ throw new Microsoft_WindowsAzure_Exception('An error has occured while committing a batch: ' . $errors[2][0]);
227
+ }
228
+
229
+ // Return
230
+ return $response;
231
+ }
232
+
233
+ /**
234
+ * Rollback current batch
235
+ */
236
+ public function rollback()
237
+ {
238
+ // Dispose
239
+ $this->_clean();
240
+ }
241
+
242
+ /**
243
+ * Get operation count
244
+ *
245
+ * @return integer
246
+ */
247
+ public function getOperationCount()
248
+ {
249
+ return count($this->_operations);
250
+ }
251
+
252
+ /**
253
+ * Is single select?
254
+ *
255
+ * @return boolean
256
+ */
257
+ public function isSingleSelect()
258
+ {
259
+ return $this->_isSingleSelect;
260
+ }
261
+ }
lib/Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 21617 2009-06-12 10:46:31Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Storage
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Storage.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Exception
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Exception.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_Storage_Batch
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/Storage/Batch.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Client
58
+ */
59
+ require_once 'Microsoft/Http/Client.php';
60
+
61
+ /**
62
+ * @see Microsoft_Http_Response
63
+ */
64
+ require_once 'Microsoft/Http/Response.php';
65
+
66
+ /**
67
+ * @category Microsoft
68
+ * @package Microsoft_WindowsAzure
69
+ * @subpackage Storage
70
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
71
+ * @license http://phpazure.codeplex.com/license
72
+ */
73
+ abstract class Microsoft_WindowsAzure_Storage_BatchStorageAbstract
74
+ extends Microsoft_WindowsAzure_Storage
75
+ {
76
+ /**
77
+ * Current batch
78
+ *
79
+ * @var Microsoft_WindowsAzure_Storage_Batch
80
+ */
81
+ protected $_currentBatch = null;
82
+
83
+ /**
84
+ * Set current batch
85
+ *
86
+ * @param Microsoft_WindowsAzure_Storage_Batch $batch Current batch
87
+ * @throws Microsoft_WindowsAzure_Exception
88
+ */
89
+ public function setCurrentBatch(Microsoft_WindowsAzure_Storage_Batch $batch = null)
90
+ {
91
+ if (!is_null($batch) && $this->isInBatch()) {
92
+ throw new Microsoft_WindowsAzure_Exception('Only one batch can be active at a time.');
93
+ }
94
+ $this->_currentBatch = $batch;
95
+ }
96
+
97
+ /**
98
+ * Get current batch
99
+ *
100
+ * @return Microsoft_WindowsAzure_Storage_Batch
101
+ */
102
+ public function getCurrentBatch()
103
+ {
104
+ return $this->_currentBatch;
105
+ }
106
+
107
+ /**
108
+ * Is there a current batch?
109
+ *
110
+ * @return boolean
111
+ */
112
+ public function isInBatch()
113
+ {
114
+ return !is_null($this->_currentBatch);
115
+ }
116
+
117
+ /**
118
+ * Starts a new batch operation set
119
+ *
120
+ * @return Microsoft_WindowsAzure_Storage_Batch
121
+ * @throws Microsoft_WindowsAzure_Exception
122
+ */
123
+ public function startBatch()
124
+ {
125
+ return new Microsoft_WindowsAzure_Storage_Batch($this, $this->getBaseUrl());
126
+ }
127
+
128
+ /**
129
+ * Perform batch using Microsoft_Http_Client channel, combining all batch operations into one request
130
+ *
131
+ * @param array $operations Operations in batch
132
+ * @param boolean $forTableStorage Is the request for table storage?
133
+ * @param boolean $isSingleSelect Is the request a single select statement?
134
+ * @param string $resourceType Resource type
135
+ * @param string $requiredPermission Required permission
136
+ * @return Microsoft_Http_Response
137
+ */
138
+ public function performBatch($operations = array(), $forTableStorage = false, $isSingleSelect = false, $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN, $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ)
139
+ {
140
+ // Generate boundaries
141
+ $batchBoundary = 'batch_' . md5(time() . microtime());
142
+ $changesetBoundary = 'changeset_' . md5(time() . microtime());
143
+
144
+ // Set headers
145
+ $headers = array();
146
+
147
+ // Add version header
148
+ $headers['x-ms-version'] = $this->_apiVersion;
149
+
150
+ // Add dataservice headers
151
+ $headers['DataServiceVersion'] = '1.0;NetFx';
152
+ $headers['MaxDataServiceVersion'] = '1.0;NetFx';
153
+
154
+ // Add content-type header
155
+ $headers['Content-Type'] = 'multipart/mixed; boundary=' . $batchBoundary;
156
+
157
+ // Set path and query string
158
+ $path = '/$batch';
159
+ $queryString = '';
160
+
161
+ // Set verb
162
+ $httpVerb = Microsoft_Http_Client::POST;
163
+
164
+ // Generate raw data
165
+ $rawData = '';
166
+
167
+ // Single select?
168
+ if ($isSingleSelect) {
169
+ $operation = $operations[0];
170
+ $rawData .= '--' . $batchBoundary . "\n";
171
+ $rawData .= 'Content-Type: application/http' . "\n";
172
+ $rawData .= 'Content-Transfer-Encoding: binary' . "\n\n";
173
+ $rawData .= $operation;
174
+ $rawData .= '--' . $batchBoundary . '--';
175
+ } else {
176
+ $rawData .= '--' . $batchBoundary . "\n";
177
+ $rawData .= 'Content-Type: multipart/mixed; boundary=' . $changesetBoundary . "\n\n";
178
+
179
+ // Add operations
180
+ foreach ($operations as $operation)
181
+ {
182
+ $rawData .= '--' . $changesetBoundary . "\n";
183
+ $rawData .= 'Content-Type: application/http' . "\n";
184
+ $rawData .= 'Content-Transfer-Encoding: binary' . "\n\n";
185
+ $rawData .= $operation;
186
+ }
187
+ $rawData .= '--' . $changesetBoundary . '--' . "\n";
188
+
189
+ $rawData .= '--' . $batchBoundary . '--';
190
+ }
191
+
192
+ // Generate URL and sign request
193
+ $requestUrl = $this->_credentials->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission);
194
+ $requestHeaders = $this->_credentials->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission);
195
+
196
+ // Prepare request
197
+ $this->_httpClientChannel->resetParameters(true);
198
+ $this->_httpClientChannel->setUri($requestUrl);
199
+ $this->_httpClientChannel->setHeaders($requestHeaders);
200
+ $this->_httpClientChannel->setRawData($rawData);
201
+
202
+ // Execute request
203
+ $response = $this->_retryPolicy->execute(
204
+ array($this->_httpClientChannel, 'request'),
205
+ array($httpVerb)
206
+ );
207
+
208
+ return $response;
209
+ }
210
+ }
lib/Microsoft/WindowsAzure/Storage/Blob.php ADDED
@@ -0,0 +1,2035 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://todo name_todo
33
+ * @version $Id: Blob.php 53747 2010-11-18 19:34:25Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract_SharedKey
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_SharedAccessSignature
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
50
+
51
+ /**
52
+ * @see Microsoft_Http_Client
53
+ */
54
+ require_once 'Microsoft/Http/Client.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Response
58
+ */
59
+ require_once 'Microsoft/Http/Response.php';
60
+
61
+ /**
62
+ * @see Microsoft_WindowsAzure_Storage
63
+ */
64
+ require_once 'Microsoft/WindowsAzure/Storage.php';
65
+
66
+ /**
67
+ * @see Microsoft_WindowsAzure_Storage_BlobContainer
68
+ */
69
+ require_once 'Microsoft/WindowsAzure/Storage/BlobContainer.php';
70
+
71
+ /**
72
+ * @see Microsoft_WindowsAzure_Storage_BlobInstance
73
+ */
74
+ require_once 'Microsoft/WindowsAzure/Storage/BlobInstance.php';
75
+
76
+ /**
77
+ * @see Microsoft_WindowsAzure_Storage_PageRegionInstance
78
+ */
79
+ require_once 'Microsoft/WindowsAzure/Storage/PageRegionInstance.php';
80
+
81
+ /**
82
+ * @see Microsoft_WindowsAzure_Storage_LeaseInstance
83
+ */
84
+ require_once 'Microsoft/WindowsAzure/Storage/LeaseInstance.php';
85
+
86
+ /**
87
+ * @see Microsoft_WindowsAzure_Storage_SignedIdentifier
88
+ */
89
+ require_once 'Microsoft/WindowsAzure/Storage/SignedIdentifier.php';
90
+
91
+ /**
92
+ * @see Microsoft_WindowsAzure_Exception
93
+ */
94
+ require_once 'Microsoft/WindowsAzure/Exception.php';
95
+
96
+
97
+ /**
98
+ * @category Microsoft
99
+ * @package Microsoft_WindowsAzure
100
+ * @subpackage Storage
101
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
102
+ * @license http://phpazure.codeplex.com/license
103
+ */
104
+ class Microsoft_WindowsAzure_Storage_Blob extends Microsoft_WindowsAzure_Storage
105
+ {
106
+ /**
107
+ * ACL - Private access
108
+ */
109
+ const ACL_PRIVATE = null;
110
+
111
+ /**
112
+ * ACL - Public access (read all blobs)
113
+ *
114
+ * @deprecated Use ACL_PUBLIC_CONTAINER or ACL_PUBLIC_BLOB instead.
115
+ */
116
+ const ACL_PUBLIC = 'container';
117
+
118
+ /**
119
+ * ACL - Blob Public access (read all blobs)
120
+ */
121
+ const ACL_PUBLIC_BLOB = 'blob';
122
+
123
+ /**
124
+ * ACL - Container Public access (enumerate and read all blobs)
125
+ */
126
+ const ACL_PUBLIC_CONTAINER = 'container';
127
+
128
+ /**
129
+ * Blob lease constants
130
+ */
131
+ const LEASE_ACQUIRE = 'acquire';
132
+ const LEASE_RENEW = 'renew';
133
+ const LEASE_RELEASE = 'release';
134
+ const LEASE_BREAK = 'break';
135
+
136
+ /**
137
+ * Maximal blob size (in bytes)
138
+ */
139
+ const MAX_BLOB_SIZE = 67108864;
140
+
141
+ /**
142
+ * Maximal blob transfer size (in bytes)
143
+ */
144
+ const MAX_BLOB_TRANSFER_SIZE = 4194304;
145
+
146
+ /**
147
+ * Blob types
148
+ */
149
+ const BLOBTYPE_BLOCK = 'BlockBlob';
150
+ const BLOBTYPE_PAGE = 'PageBlob';
151
+
152
+ /**
153
+ * Put page write options
154
+ */
155
+ const PAGE_WRITE_UPDATE = 'update';
156
+ const PAGE_WRITE_CLEAR = 'clear';
157
+
158
+ /**
159
+ * Stream wrapper clients
160
+ *
161
+ * @var array
162
+ */
163
+ protected static $_wrapperClients = array();
164
+
165
+ /**
166
+ * SharedAccessSignature credentials
167
+ *
168
+ * @var Microsoft_WindowsAzure_Credentials_SharedAccessSignature
169
+ */
170
+ private $_sharedAccessSignatureCredentials = null;
171
+
172
+ /**
173
+ * Creates a new Microsoft_WindowsAzure_Storage_Blob instance
174
+ *
175
+ * @param string $host Storage host name
176
+ * @param string $accountName Account name for Windows Azure
177
+ * @param string $accountKey Account key for Windows Azure
178
+ * @param boolean $usePathStyleUri Use path-style URI's
179
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
180
+ */
181
+ public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
182
+ {
183
+ parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
184
+
185
+ // API version
186
+ $this->_apiVersion = '2009-09-19';
187
+
188
+ // SharedAccessSignature credentials
189
+ $this->_sharedAccessSignatureCredentials = new Microsoft_WindowsAzure_Credentials_SharedAccessSignature($accountName, $accountKey, $usePathStyleUri);
190
+ }
191
+
192
+ /**
193
+ * Check if a blob exists
194
+ *
195
+ * @param string $containerName Container name
196
+ * @param string $blobName Blob name
197
+ * @param string $snapshotId Snapshot identifier
198
+ * @return boolean
199
+ */
200
+ public function blobExists($containerName = '', $blobName = '', $snapshotId = null)
201
+ {
202
+ if ($containerName === '') {
203
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
204
+ }
205
+ if (!self::isValidContainerName($containerName)) {
206
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
207
+ }
208
+ if ($blobName === '') {
209
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
210
+ }
211
+
212
+ // Get blob instance
213
+ try {
214
+ $this->getBlobInstance($containerName, $blobName, $snapshotId);
215
+ } catch (Microsoft_WindowsAzure_Exception $e) {
216
+ return false;
217
+ }
218
+
219
+ return true;
220
+ }
221
+
222
+ /**
223
+ * Check if a container exists
224
+ *
225
+ * @param string $containerName Container name
226
+ * @return boolean
227
+ */
228
+ public function containerExists($containerName = '')
229
+ {
230
+ if ($containerName === '') {
231
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
232
+ }
233
+ if (!self::isValidContainerName($containerName)) {
234
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
235
+ }
236
+
237
+ // List containers
238
+ $containers = $this->listContainers($containerName, 1);
239
+ foreach ($containers as $container) {
240
+ if ($container->Name == $containerName) {
241
+ return true;
242
+ }
243
+ }
244
+
245
+ return false;
246
+ }
247
+
248
+ /**
249
+ * Create container
250
+ *
251
+ * @param string $containerName Container name
252
+ * @param array $metadata Key/value pairs of meta data
253
+ * @return object Container properties
254
+ * @throws Microsoft_WindowsAzure_Exception
255
+ */
256
+ public function createContainer($containerName = '', $metadata = array())
257
+ {
258
+ if ($containerName === '') {
259
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
260
+ }
261
+ if (!self::isValidContainerName($containerName)) {
262
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
263
+ }
264
+ if (!is_array($metadata)) {
265
+ throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
266
+ }
267
+
268
+ // Create metadata headers
269
+ $headers = array();
270
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
271
+
272
+ // Perform request
273
+ $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
274
+ if ($response->isSuccessful()) {
275
+ return new Microsoft_WindowsAzure_Storage_BlobContainer(
276
+ $containerName,
277
+ $response->getHeader('Etag'),
278
+ $response->getHeader('Last-modified'),
279
+ $metadata
280
+ );
281
+ } else {
282
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Create container if it does not exist
288
+ *
289
+ * @param string $containerName Container name
290
+ * @param array $metadata Key/value pairs of meta data
291
+ * @throws Microsoft_WindowsAzure_Exception
292
+ */
293
+ public function createContainerIfNotExists($containerName = '', $metadata = array())
294
+ {
295
+ if (!$this->containerExists($containerName)) {
296
+ $this->createContainer($containerName, $metadata);
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Get container ACL
302
+ *
303
+ * @param string $containerName Container name
304
+ * @param bool $signedIdentifiers Display only private/blob/container or display signed identifiers?
305
+ * @return string Acl, to be compared with Microsoft_WindowsAzure_Storage_Blob::ACL_*
306
+ * @throws Microsoft_WindowsAzure_Exception
307
+ */
308
+ public function getContainerAcl($containerName = '', $signedIdentifiers = false)
309
+ {
310
+ if ($containerName === '') {
311
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
312
+ }
313
+ if (!self::isValidContainerName($containerName)) {
314
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
315
+ }
316
+
317
+ // Perform request
318
+ $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
319
+ if ($response->isSuccessful()) {
320
+ if ($signedIdentifiers == false) {
321
+ // Only private/blob/container
322
+ $accessType = $response->getHeader(Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access');
323
+ if (strtolower($accessType) == 'true') {
324
+ $accessType = self::ACL_PUBLIC_CONTAINER;
325
+ }
326
+ return $accessType;
327
+ } else {
328
+ // Parse result
329
+ $result = $this->_parseResponse($response);
330
+ if (!$result) {
331
+ return array();
332
+ }
333
+
334
+ $entries = null;
335
+ if ($result->SignedIdentifier) {
336
+ if (count($result->SignedIdentifier) > 1) {
337
+ $entries = $result->SignedIdentifier;
338
+ } else {
339
+ $entries = array($result->SignedIdentifier);
340
+ }
341
+ }
342
+
343
+ // Return value
344
+ $returnValue = array();
345
+ foreach ($entries as $entry) {
346
+ $returnValue[] = new Microsoft_WindowsAzure_Storage_SignedIdentifier(
347
+ $entry->Id,
348
+ $entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '',
349
+ $entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '',
350
+ $entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : ''
351
+ );
352
+ }
353
+
354
+ // Return
355
+ return $returnValue;
356
+ }
357
+ } else {
358
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Set container ACL
364
+ *
365
+ * @param string $containerName Container name
366
+ * @param bool $acl Microsoft_WindowsAzure_Storage_Blob::ACL_*
367
+ * @param array $signedIdentifiers Signed identifiers
368
+ * @throws Microsoft_WindowsAzure_Exception
369
+ */
370
+ public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array())
371
+ {
372
+ if ($containerName === '') {
373
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
374
+ }
375
+ if (!self::isValidContainerName($containerName)) {
376
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
377
+ }
378
+
379
+ // Headers
380
+ $headers = array();
381
+
382
+ // Acl specified?
383
+ if ($acl != self::ACL_PRIVATE && !is_null($acl) && $acl != '') {
384
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access'] = $acl;
385
+ }
386
+
387
+ // Policies
388
+ $policies = null;
389
+ if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) {
390
+ $policies = '';
391
+ $policies .= '<?xml version="1.0" encoding="utf-8"?>' . "\r\n";
392
+ $policies .= '<SignedIdentifiers>' . "\r\n";
393
+ foreach ($signedIdentifiers as $signedIdentifier) {
394
+ $policies .= ' <SignedIdentifier>' . "\r\n";
395
+ $policies .= ' <Id>' . $signedIdentifier->Id . '</Id>' . "\r\n";
396
+ $policies .= ' <AccessPolicy>' . "\r\n";
397
+ if ($signedIdentifier->Start != '')
398
+ $policies .= ' <Start>' . $signedIdentifier->Start . '</Start>' . "\r\n";
399
+ if ($signedIdentifier->Expiry != '')
400
+ $policies .= ' <Expiry>' . $signedIdentifier->Expiry . '</Expiry>' . "\r\n";
401
+ if ($signedIdentifier->Permissions != '')
402
+ $policies .= ' <Permission>' . $signedIdentifier->Permissions . '</Permission>' . "\r\n";
403
+ $policies .= ' </AccessPolicy>' . "\r\n";
404
+ $policies .= ' </SignedIdentifier>' . "\r\n";
405
+ }
406
+ $policies .= '</SignedIdentifiers>' . "\r\n";
407
+ }
408
+
409
+ // Perform request
410
+ $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Microsoft_Http_Client::PUT, $headers, false, $policies, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
411
+ if (!$response->isSuccessful()) {
412
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Get container
418
+ *
419
+ * @param string $containerName Container name
420
+ * @return Microsoft_WindowsAzure_Storage_BlobContainer
421
+ * @throws Microsoft_WindowsAzure_Exception
422
+ */
423
+ public function getContainer($containerName = '')
424
+ {
425
+ if ($containerName === '') {
426
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
427
+ }
428
+ if (!self::isValidContainerName($containerName)) {
429
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
430
+ }
431
+
432
+ // Perform request
433
+ $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
434
+ if ($response->isSuccessful()) {
435
+ // Parse metadata
436
+ $metadata = $this->_parseMetadataHeaders($response->getHeaders());
437
+
438
+ // Return container
439
+ return new Microsoft_WindowsAzure_Storage_BlobContainer(
440
+ $containerName,
441
+ $response->getHeader('Etag'),
442
+ $response->getHeader('Last-modified'),
443
+ $metadata
444
+ );
445
+ } else {
446
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Get container metadata
452
+ *
453
+ * @param string $containerName Container name
454
+ * @return array Key/value pairs of meta data
455
+ * @throws Microsoft_WindowsAzure_Exception
456
+ */
457
+ public function getContainerMetadata($containerName = '')
458
+ {
459
+ if ($containerName === '') {
460
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
461
+ }
462
+ if (!self::isValidContainerName($containerName)) {
463
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
464
+ }
465
+
466
+ return $this->getContainer($containerName)->Metadata;
467
+ }
468
+
469
+ /**
470
+ * Set container metadata
471
+ *
472
+ * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container. It's not possible to modify an individual name/value pair.
473
+ *
474
+ * @param string $containerName Container name
475
+ * @param array $metadata Key/value pairs of meta data
476
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
477
+ * @throws Microsoft_WindowsAzure_Exception
478
+ */
479
+ public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array())
480
+ {
481
+ if ($containerName === '') {
482
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
483
+ }
484
+ if (!self::isValidContainerName($containerName)) {
485
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
486
+ }
487
+ if (!is_array($metadata)) {
488
+ throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
489
+ }
490
+ if (count($metadata) == 0) {
491
+ return;
492
+ }
493
+
494
+ // Create metadata headers
495
+ $headers = array();
496
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
497
+
498
+ // Additional headers?
499
+ foreach ($additionalHeaders as $key => $value) {
500
+ $headers[$key] = $value;
501
+ }
502
+
503
+ // Perform request
504
+ $response = $this->_performRequest($containerName, '?restype=container&comp=metadata', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
505
+ if (!$response->isSuccessful()) {
506
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Delete container
512
+ *
513
+ * @param string $containerName Container name
514
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
515
+ * @throws Microsoft_WindowsAzure_Exception
516
+ */
517
+ public function deleteContainer($containerName = '', $additionalHeaders = array())
518
+ {
519
+ if ($containerName === '') {
520
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
521
+ }
522
+ if (!self::isValidContainerName($containerName)) {
523
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
524
+ }
525
+
526
+ // Additional headers?
527
+ $headers = array();
528
+ foreach ($additionalHeaders as $key => $value) {
529
+ $headers[$key] = $value;
530
+ }
531
+
532
+ // Perform request
533
+ $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::DELETE, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
534
+ if (!$response->isSuccessful()) {
535
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
536
+ }
537
+ }
538
+
539
+ /**
540
+ * List containers
541
+ *
542
+ * @param string $prefix Optional. Filters the results to return only containers whose name begins with the specified prefix.
543
+ * @param int $maxResults Optional. Specifies the maximum number of containers to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
544
+ * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
545
+ * @param string $include Optional. Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
546
+ * @param int $currentResultCount Current result count (internal use)
547
+ * @return array
548
+ * @throws Microsoft_WindowsAzure_Exception
549
+ */
550
+ public function listContainers($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
551
+ {
552
+ // Build query string
553
+ $queryString = array('comp=list');
554
+ if (!is_null($prefix)) {
555
+ $queryString[] = 'prefix=' . $prefix;
556
+ }
557
+ if (!is_null($maxResults)) {
558
+ $queryString[] = 'maxresults=' . $maxResults;
559
+ }
560
+ if (!is_null($marker)) {
561
+ $queryString[] = 'marker=' . $marker;
562
+ }
563
+ if (!is_null($include)) {
564
+ $queryString[] = 'include=' . $include;
565
+ }
566
+ $queryString = self::createQueryStringFromArray($queryString);
567
+
568
+ // Perform request
569
+ $response = $this->_performRequest('', $queryString, Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
570
+ if ($response->isSuccessful()) {
571
+ $xmlContainers = $this->_parseResponse($response)->Containers->Container;
572
+ $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
573
+
574
+ $containers = array();
575
+ if (!is_null($xmlContainers)) {
576
+ for ($i = 0; $i < count($xmlContainers); $i++) {
577
+ $containers[] = new Microsoft_WindowsAzure_Storage_BlobContainer(
578
+ (string)$xmlContainers[$i]->Name,
579
+ (string)$xmlContainers[$i]->Etag,
580
+ (string)$xmlContainers[$i]->LastModified,
581
+ $this->_parseMetadataElement($xmlContainers[$i])
582
+ );
583
+ }
584
+ }
585
+ $currentResultCount = $currentResultCount + count($containers);
586
+ if (!is_null($maxResults) && $currentResultCount < $maxResults) {
587
+ if (!is_null($xmlMarker) && $xmlMarker != '') {
588
+ $containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
589
+ }
590
+ }
591
+ if (!is_null($maxResults) && count($containers) > $maxResults) {
592
+ $containers = array_slice($containers, 0, $maxResults);
593
+ }
594
+
595
+ return $containers;
596
+ } else {
597
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
598
+ }
599
+ }
600
+
601
+ /**
602
+ * Put blob
603
+ *
604
+ * @param string $containerName Container name
605
+ * @param string $blobName Blob name
606
+ * @param string $localFileName Local file name to be uploaded
607
+ * @param array $metadata Key/value pairs of meta data
608
+ * @param string $leaseId Lease identifier
609
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
610
+ * @return object Partial blob properties
611
+ * @throws Microsoft_WindowsAzure_Exception
612
+ */
613
+ public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
614
+ {
615
+ if ($containerName === '') {
616
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
617
+ }
618
+ if (!self::isValidContainerName($containerName)) {
619
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
620
+ }
621
+ if ($blobName === '') {
622
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
623
+ }
624
+ if ($localFileName === '') {
625
+ throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
626
+ }
627
+ if (!file_exists($localFileName)) {
628
+ throw new Microsoft_WindowsAzure_Exception('Local file not found.');
629
+ }
630
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
631
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
632
+ }
633
+
634
+ // Check file size
635
+ if (filesize($localFileName) >= self::MAX_BLOB_SIZE) {
636
+ return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
637
+ }
638
+
639
+ // Put the data to Windows Azure Storage
640
+ return $this->putBlobData($containerName, $blobName, file_get_contents($localFileName), $metadata, $leaseId, $additionalHeaders);
641
+ }
642
+
643
+ /**
644
+ * Put blob data
645
+ *
646
+ * @param string $containerName Container name
647
+ * @param string $blobName Blob name
648
+ * @param mixed $data Data to store
649
+ * @param array $metadata Key/value pairs of meta data
650
+ * @param string $leaseId Lease identifier
651
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
652
+ * @return object Partial blob properties
653
+ * @throws Microsoft_WindowsAzure_Exception
654
+ */
655
+ public function putBlobData($containerName = '', $blobName = '', $data = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
656
+ {
657
+ if ($containerName === '') {
658
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
659
+ }
660
+ if (!self::isValidContainerName($containerName)) {
661
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
662
+ }
663
+ if ($blobName === '') {
664
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
665
+ }
666
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
667
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
668
+ }
669
+
670
+ // Create metadata headers
671
+ $headers = array();
672
+ if (!is_null($leaseId)) {
673
+ $headers['x-ms-lease-id'] = $leaseId;
674
+ }
675
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
676
+
677
+ // Additional headers?
678
+ foreach ($additionalHeaders as $key => $value) {
679
+ $headers[$key] = $value;
680
+ }
681
+
682
+ // Specify blob type
683
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_BLOCK;
684
+
685
+ // Resource name
686
+ $resourceName = self::createResourceName($containerName , $blobName);
687
+
688
+ // Perform request
689
+ $response = $this->_performRequest($resourceName, '', Microsoft_Http_Client::PUT, $headers, false, $data, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
690
+ if ($response->isSuccessful()) {
691
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
692
+ $containerName,
693
+ $blobName,
694
+ null,
695
+ $response->getHeader('Etag'),
696
+ $response->getHeader('Last-modified'),
697
+ $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
698
+ strlen($data),
699
+ '',
700
+ '',
701
+ '',
702
+ '',
703
+ false,
704
+ $metadata
705
+ );
706
+ } else {
707
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
708
+ }
709
+ }
710
+
711
+ /**
712
+ * Put large blob (> 64 MB)
713
+ *
714
+ * @param string $containerName Container name
715
+ * @param string $blobName Blob name
716
+ * @param string $localFileName Local file name to be uploaded
717
+ * @param array $metadata Key/value pairs of meta data
718
+ * @param string $leaseId Lease identifier
719
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
720
+ * @return object Partial blob properties
721
+ * @throws Microsoft_WindowsAzure_Exception
722
+ */
723
+ public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
724
+ {
725
+ if ($containerName === '') {
726
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
727
+ }
728
+ if (!self::isValidContainerName($containerName)) {
729
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
730
+ }
731
+ if ($blobName === '') {
732
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
733
+ }
734
+ if ($localFileName === '') {
735
+ throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
736
+ }
737
+ if (!file_exists($localFileName)) {
738
+ throw new Microsoft_WindowsAzure_Exception('Local file not found.');
739
+ }
740
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
741
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
742
+ }
743
+
744
+ // Check file size
745
+ if (filesize($localFileName) < self::MAX_BLOB_SIZE) {
746
+ return $this->putBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
747
+ }
748
+
749
+ // Determine number of parts
750
+ $numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE );
751
+
752
+ // Generate block id's
753
+ $blockIdentifiers = array();
754
+ for ($i = 0; $i < $numberOfParts; $i++) {
755
+ $blockIdentifiers[] = $this->_generateBlockId($i);
756
+ }
757
+
758
+ // Open file
759
+ $fp = fopen($localFileName, 'r');
760
+ if ($fp === false) {
761
+ throw new Microsoft_WindowsAzure_Exception('Could not open local file.');
762
+ }
763
+
764
+ // Upload parts
765
+ for ($i = 0; $i < $numberOfParts; $i++) {
766
+ // Seek position in file
767
+ fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE);
768
+
769
+ // Read contents
770
+ $fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE);
771
+
772
+ // Put block
773
+ $this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents, $leaseId);
774
+
775
+ // Dispose file contents
776
+ $fileContents = null;
777
+ unset($fileContents);
778
+ }
779
+
780
+ // Close file
781
+ fclose($fp);
782
+
783
+ // Put block list
784
+ $this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata, $leaseId, $additionalHeaders);
785
+
786
+ // Return information of the blob
787
+ return $this->getBlobInstance($containerName, $blobName, null, $leaseId);
788
+ }
789
+
790
+ /**
791
+ * Put large blob block
792
+ *
793
+ * @param string $containerName Container name
794
+ * @param string $blobName Blob name
795
+ * @param string $identifier Block ID
796
+ * @param array $contents Contents of the block
797
+ * @param string $leaseId Lease identifier
798
+ * @throws Microsoft_WindowsAzure_Exception
799
+ */
800
+ public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '', $leaseId = null)
801
+ {
802
+ if ($containerName === '') {
803
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
804
+ }
805
+ if (!self::isValidContainerName($containerName)) {
806
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
807
+ }
808
+ if ($identifier === '') {
809
+ throw new Microsoft_WindowsAzure_Exception('Block identifier is not specified.');
810
+ }
811
+ if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) {
812
+ throw new Microsoft_WindowsAzure_Exception('Block size is too big.');
813
+ }
814
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
815
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
816
+ }
817
+
818
+ // Headers
819
+ $headers = array();
820
+ if (!is_null($leaseId)) {
821
+ $headers['x-ms-lease-id'] = $leaseId;
822
+ }
823
+
824
+ // Resource name
825
+ $resourceName = self::createResourceName($containerName , $blobName);
826
+
827
+ // Upload
828
+ $response = $this->_performRequest($resourceName, '?comp=block&blockid=' . base64_encode($identifier), Microsoft_Http_Client::PUT, $headers, false, $contents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
829
+ if (!$response->isSuccessful()) {
830
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
831
+ }
832
+ }
833
+
834
+ /**
835
+ * Put block list
836
+ *
837
+ * @param string $containerName Container name
838
+ * @param string $blobName Blob name
839
+ * @param array $blockList Array of block identifiers
840
+ * @param array $metadata Key/value pairs of meta data
841
+ * @param string $leaseId Lease identifier
842
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
843
+ * @throws Microsoft_WindowsAzure_Exception
844
+ */
845
+ public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $leaseId = null, $additionalHeaders = array())
846
+ {
847
+ if ($containerName === '') {
848
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
849
+ }
850
+ if (!self::isValidContainerName($containerName)) {
851
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
852
+ }
853
+ if ($blobName === '') {
854
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
855
+ }
856
+ if (count($blockList) == 0) {
857
+ throw new Microsoft_WindowsAzure_Exception('Block list does not contain any elements.');
858
+ }
859
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
860
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
861
+ }
862
+
863
+ // Generate block list
864
+ $blocks = '';
865
+ foreach ($blockList as $block) {
866
+ $blocks .= ' <Latest>' . base64_encode($block) . '</Latest>' . "\n";
867
+ }
868
+
869
+ // Generate block list request
870
+ $fileContents = utf8_encode(implode("\n", array(
871
+ '<?xml version="1.0" encoding="utf-8"?>',
872
+ '<BlockList>',
873
+ $blocks,
874
+ '</BlockList>'
875
+ )));
876
+
877
+ // Create metadata headers
878
+ $headers = array();
879
+ if (!is_null($leaseId)) {
880
+ $headers['x-ms-lease-id'] = $leaseId;
881
+ }
882
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
883
+
884
+ // Additional headers?
885
+ foreach ($additionalHeaders as $key => $value) {
886
+ $headers[$key] = $value;
887
+ }
888
+
889
+ // Resource name
890
+ $resourceName = self::createResourceName($containerName , $blobName);
891
+
892
+ // Perform request
893
+ $response = $this->_performRequest($resourceName, '?comp=blocklist', Microsoft_Http_Client::PUT, $headers, false, $fileContents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
894
+ if (!$response->isSuccessful()) {
895
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
896
+ }
897
+ }
898
+
899
+ /**
900
+ * Get block list
901
+ *
902
+ * @param string $containerName Container name
903
+ * @param string $blobName Blob name
904
+ * @param string $snapshotId Snapshot identifier
905
+ * @param string $leaseId Lease identifier
906
+ * @param integer $type Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
907
+ * @return array
908
+ * @throws Microsoft_WindowsAzure_Exception
909
+ */
910
+ public function getBlockList($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $type = 0)
911
+ {
912
+ if ($containerName === '') {
913
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
914
+ }
915
+ if (!self::isValidContainerName($containerName)) {
916
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
917
+ }
918
+ if ($blobName === '') {
919
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
920
+ }
921
+ if ($type < 0 || $type > 2) {
922
+ throw new Microsoft_WindowsAzure_Exception('Invalid type of block list to retrieve.');
923
+ }
924
+
925
+ // Set $blockListType
926
+ $blockListType = 'all';
927
+ if ($type == 1) {
928
+ $blockListType = 'committed';
929
+ }
930
+ if ($type == 2) {
931
+ $blockListType = 'uncommitted';
932
+ }
933
+
934
+ // Headers
935
+ $headers = array();
936
+ if (!is_null($leaseId)) {
937
+ $headers['x-ms-lease-id'] = $leaseId;
938
+ }
939
+
940
+ // Build query string
941
+ $queryString = array('comp=blocklist', 'blocklisttype=' . $blockListType);
942
+ if (!is_null($snapshotId)) {
943
+ $queryString[] = 'snapshot=' . $snapshotId;
944
+ }
945
+ $queryString = self::createQueryStringFromArray($queryString);
946
+
947
+ // Resource name
948
+ $resourceName = self::createResourceName($containerName , $blobName);
949
+
950
+ // Perform request
951
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
952
+ if ($response->isSuccessful()) {
953
+ // Parse response
954
+ $blockList = $this->_parseResponse($response);
955
+
956
+ // Create return value
957
+ $returnValue = array();
958
+ if ($blockList->CommittedBlocks) {
959
+ foreach ($blockList->CommittedBlocks->Block as $block) {
960
+ $returnValue['CommittedBlocks'][] = (object)array(
961
+ 'Name' => (string)$block->Name,
962
+ 'Size' => (string)$block->Size
963
+ );
964
+ }
965
+ }
966
+ if ($blockList->UncommittedBlocks) {
967
+ foreach ($blockList->UncommittedBlocks->Block as $block) {
968
+ $returnValue['UncommittedBlocks'][] = (object)array(
969
+ 'Name' => (string)$block->Name,
970
+ 'Size' => (string)$block->Size
971
+ );
972
+ }
973
+ }
974
+
975
+ return $returnValue;
976
+ } else {
977
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
978
+ }
979
+ }
980
+
981
+ /**
982
+ * Create page blob
983
+ *
984
+ * @param string $containerName Container name
985
+ * @param string $blobName Blob name
986
+ * @param int $size Size of the page blob in bytes
987
+ * @param array $metadata Key/value pairs of meta data
988
+ * @param string $leaseId Lease identifier
989
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
990
+ * @return object Partial blob properties
991
+ * @throws Microsoft_WindowsAzure_Exception
992
+ */
993
+ public function createPageBlob($containerName = '', $blobName = '', $size = 0, $metadata = array(), $leaseId = null, $additionalHeaders = array())
994
+ {
995
+ if ($containerName === '') {
996
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
997
+ }
998
+ if (!self::isValidContainerName($containerName)) {
999
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1000
+ }
1001
+ if ($blobName === '') {
1002
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1003
+ }
1004
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1005
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1006
+ }
1007
+ if ($size <= 0) {
1008
+ throw new Microsoft_WindowsAzure_Exception('Page blob size must be specified.');
1009
+ }
1010
+
1011
+ // Create metadata headers
1012
+ $headers = array();
1013
+ if (!is_null($leaseId)) {
1014
+ $headers['x-ms-lease-id'] = $leaseId;
1015
+ }
1016
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
1017
+
1018
+ // Additional headers?
1019
+ foreach ($additionalHeaders as $key => $value) {
1020
+ $headers[$key] = $value;
1021
+ }
1022
+
1023
+ // Specify blob type & blob length
1024
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_PAGE;
1025
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-content-length'] = $size;
1026
+ $headers['Content-Length'] = 0;
1027
+
1028
+ // Resource name
1029
+ $resourceName = self::createResourceName($containerName , $blobName);
1030
+
1031
+ // Perform request
1032
+ $response = $this->_performRequest($resourceName, '', Microsoft_Http_Client::PUT, $headers, false, '', Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1033
+ if ($response->isSuccessful()) {
1034
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
1035
+ $containerName,
1036
+ $blobName,
1037
+ null,
1038
+ $response->getHeader('Etag'),
1039
+ $response->getHeader('Last-modified'),
1040
+ $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
1041
+ $size,
1042
+ '',
1043
+ '',
1044
+ '',
1045
+ '',
1046
+ false,
1047
+ $metadata
1048
+ );
1049
+ } else {
1050
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1051
+ }
1052
+ }
1053
+
1054
+ /**
1055
+ * Put page in page blob
1056
+ *
1057
+ * @param string $containerName Container name
1058
+ * @param string $blobName Blob name
1059
+ * @param int $startByteOffset Start byte offset
1060
+ * @param int $endByteOffset End byte offset
1061
+ * @param mixed $contents Page contents
1062
+ * @param string $writeMethod Write method (Microsoft_WindowsAzure_Storage_Blob::PAGE_WRITE_*)
1063
+ * @param string $leaseId Lease identifier
1064
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1065
+ * @throws Microsoft_WindowsAzure_Exception
1066
+ */
1067
+ public function putPage($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $contents = '', $writeMethod = self::PAGE_WRITE_UPDATE, $leaseId = null, $additionalHeaders = array())
1068
+ {
1069
+ if ($containerName === '') {
1070
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1071
+ }
1072
+ if (!self::isValidContainerName($containerName)) {
1073
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1074
+ }
1075
+ if ($blobName === '') {
1076
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1077
+ }
1078
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1079
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1080
+ }
1081
+ if ($startByteOffset % 512 != 0) {
1082
+ throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
1083
+ }
1084
+ if (($endByteOffset + 1) % 512 != 0) {
1085
+ throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
1086
+ }
1087
+
1088
+ // Determine size
1089
+ $size = strlen($contents);
1090
+ if ($size >= self::MAX_BLOB_TRANSFER_SIZE) {
1091
+ throw new Microsoft_WindowsAzure_Exception('Page blob size must not be larger than ' + self::MAX_BLOB_TRANSFER_SIZE . ' bytes.');
1092
+ }
1093
+
1094
+ // Create metadata headers
1095
+ $headers = array();
1096
+ if (!is_null($leaseId)) {
1097
+ $headers['x-ms-lease-id'] = $leaseId;
1098
+ }
1099
+
1100
+ // Additional headers?
1101
+ foreach ($additionalHeaders as $key => $value) {
1102
+ $headers[$key] = $value;
1103
+ }
1104
+
1105
+ // Specify range
1106
+ $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
1107
+
1108
+ // Write method
1109
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'page-write'] = $writeMethod;
1110
+
1111
+ // Resource name
1112
+ $resourceName = self::createResourceName($containerName , $blobName);
1113
+
1114
+ // Perform request
1115
+ $response = $this->_performRequest($resourceName, '?comp=page', Microsoft_Http_Client::PUT, $headers, false, $contents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1116
+ if (!$response->isSuccessful()) {
1117
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1118
+ }
1119
+ }
1120
+
1121
+ /**
1122
+ * Put page in page blob
1123
+ *
1124
+ * @param string $containerName Container name
1125
+ * @param string $blobName Blob name
1126
+ * @param int $startByteOffset Start byte offset
1127
+ * @param int $endByteOffset End byte offset
1128
+ * @param string $leaseId Lease identifier
1129
+ * @return array Array of page ranges
1130
+ * @throws Microsoft_WindowsAzure_Exception
1131
+ */
1132
+ public function getPageRegions($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $leaseId = null)
1133
+ {
1134
+ if ($containerName === '') {
1135
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1136
+ }
1137
+ if (!self::isValidContainerName($containerName)) {
1138
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1139
+ }
1140
+ if ($blobName === '') {
1141
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1142
+ }
1143
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1144
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1145
+ }
1146
+ if ($startByteOffset % 512 != 0) {
1147
+ throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
1148
+ }
1149
+ if ($endByteOffset > 0 && ($endByteOffset + 1) % 512 != 0) {
1150
+ throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
1151
+ }
1152
+
1153
+ // Create metadata headers
1154
+ $headers = array();
1155
+ if (!is_null($leaseId)) {
1156
+ $headers['x-ms-lease-id'] = $leaseId;
1157
+ }
1158
+
1159
+ // Specify range?
1160
+ if ($endByteOffset > 0) {
1161
+ $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
1162
+ }
1163
+
1164
+ // Resource name
1165
+ $resourceName = self::createResourceName($containerName , $blobName);
1166
+
1167
+ // Perform request
1168
+ $response = $this->_performRequest($resourceName, '?comp=pagelist', Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1169
+ if ($response->isSuccessful()) {
1170
+ $result = $this->_parseResponse($response);
1171
+ $xmlRanges = null;
1172
+ if (count($result->PageRange) > 1) {
1173
+ $xmlRanges = $result->PageRange;
1174
+ } else {
1175
+ $xmlRanges = array($result->PageRange);
1176
+ }
1177
+
1178
+ $ranges = array();
1179
+ for ($i = 0; $i < count($xmlRanges); $i++) {
1180
+ $ranges[] = new Microsoft_WindowsAzure_Storage_PageRegionInstance(
1181
+ (int)$xmlRanges[$i]->Start,
1182
+ (int)$xmlRanges[$i]->End
1183
+ );
1184
+ }
1185
+
1186
+ return $ranges;
1187
+ } else {
1188
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1189
+ }
1190
+ }
1191
+
1192
+ /**
1193
+ * Copy blob
1194
+ *
1195
+ * @param string $sourceContainerName Source container name
1196
+ * @param string $sourceBlobName Source blob name
1197
+ * @param string $destinationContainerName Destination container name
1198
+ * @param string $destinationBlobName Destination blob name
1199
+ * @param array $metadata Key/value pairs of meta data
1200
+ * @param string $sourceSnapshotId Source snapshot identifier
1201
+ * @param string $destinationLeaseId Destination lease identifier
1202
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information.
1203
+ * @return object Partial blob properties
1204
+ * @throws Microsoft_WindowsAzure_Exception
1205
+ */
1206
+ public function copyBlob($sourceContainerName = '', $sourceBlobName = '', $destinationContainerName = '', $destinationBlobName = '', $metadata = array(), $sourceSnapshotId = null, $destinationLeaseId = null, $additionalHeaders = array())
1207
+ {
1208
+ if ($sourceContainerName === '') {
1209
+ throw new Microsoft_WindowsAzure_Exception('Source container name is not specified.');
1210
+ }
1211
+ if (!self::isValidContainerName($sourceContainerName)) {
1212
+ throw new Microsoft_WindowsAzure_Exception('Source container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1213
+ }
1214
+ if ($sourceBlobName === '') {
1215
+ throw new Microsoft_WindowsAzure_Exception('Source blob name is not specified.');
1216
+ }
1217
+ if ($destinationContainerName === '') {
1218
+ throw new Microsoft_WindowsAzure_Exception('Destination container name is not specified.');
1219
+ }
1220
+ if (!self::isValidContainerName($destinationContainerName)) {
1221
+ throw new Microsoft_WindowsAzure_Exception('Destination container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1222
+ }
1223
+ if ($destinationBlobName === '') {
1224
+ throw new Microsoft_WindowsAzure_Exception('Destination blob name is not specified.');
1225
+ }
1226
+ if ($sourceContainerName === '$root' && strpos($sourceBlobName, '/') !== false) {
1227
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1228
+ }
1229
+ if ($destinationContainerName === '$root' && strpos($destinationBlobName, '/') !== false) {
1230
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1231
+ }
1232
+
1233
+ // Create metadata headers
1234
+ $headers = array();
1235
+ if (!is_null($destinationLeaseId)) {
1236
+ $headers['x-ms-lease-id'] = $destinationLeaseId;
1237
+ }
1238
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
1239
+
1240
+ // Additional headers?
1241
+ foreach ($additionalHeaders as $key => $value) {
1242
+ $headers[$key] = $value;
1243
+ }
1244
+
1245
+ // Resource names
1246
+ $sourceResourceName = self::createResourceName($sourceContainerName, $sourceBlobName);
1247
+ if (!is_null($sourceSnapshotId)) {
1248
+ $sourceResourceName .= '?snapshot=' . $sourceSnapshotId;
1249
+ }
1250
+ $destinationResourceName = self::createResourceName($destinationContainerName, $destinationBlobName);
1251
+
1252
+ // Set source blob
1253
+ $headers["x-ms-copy-source"] = '/' . $this->_accountName . '/' . $sourceResourceName;
1254
+
1255
+ // Perform request
1256
+ $response = $this->_performRequest($destinationResourceName, '', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1257
+ if ($response->isSuccessful()) {
1258
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
1259
+ $destinationContainerName,
1260
+ $destinationBlobName,
1261
+ null,
1262
+ $response->getHeader('Etag'),
1263
+ $response->getHeader('Last-modified'),
1264
+ $this->getBaseUrl() . '/' . $destinationContainerName . '/' . $destinationBlobName,
1265
+ 0,
1266
+ '',
1267
+ '',
1268
+ '',
1269
+ '',
1270
+ false,
1271
+ $metadata
1272
+ );
1273
+ } else {
1274
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1275
+ }
1276
+ }
1277
+
1278
+ /**
1279
+ * Get blob
1280
+ *
1281
+ * @param string $containerName Container name
1282
+ * @param string $blobName Blob name
1283
+ * @param string $localFileName Local file name to store downloaded blob
1284
+ * @param string $snapshotId Snapshot identifier
1285
+ * @param string $leaseId Lease identifier
1286
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1287
+ * @throws Microsoft_WindowsAzure_Exception
1288
+ */
1289
+ public function getBlob($containerName = '', $blobName = '', $localFileName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1290
+ {
1291
+ if ($containerName === '') {
1292
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1293
+ }
1294
+ if (!self::isValidContainerName($containerName)) {
1295
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1296
+ }
1297
+ if ($blobName === '') {
1298
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1299
+ }
1300
+ if ($localFileName === '') {
1301
+ throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
1302
+ }
1303
+
1304
+ // Fetch data
1305
+ file_put_contents($localFileName, $this->getBlobData($containerName, $blobName, $snapshotId, $leaseId, $additionalHeaders));
1306
+ }
1307
+
1308
+ /**
1309
+ * Get blob data
1310
+ *
1311
+ * @param string $containerName Container name
1312
+ * @param string $blobName Blob name
1313
+ * @param string $snapshotId Snapshot identifier
1314
+ * @param string $leaseId Lease identifier
1315
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1316
+ * @return mixed Blob contents
1317
+ * @throws Microsoft_WindowsAzure_Exception
1318
+ */
1319
+ public function getBlobData($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1320
+ {
1321
+ if ($containerName === '') {
1322
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1323
+ }
1324
+ if (!self::isValidContainerName($containerName)) {
1325
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1326
+ }
1327
+ if ($blobName === '') {
1328
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1329
+ }
1330
+
1331
+ // Build query string
1332
+ $queryString = array();
1333
+ if (!is_null($snapshotId)) {
1334
+ $queryString[] = 'snapshot=' . $snapshotId;
1335
+ }
1336
+ $queryString = self::createQueryStringFromArray($queryString);
1337
+
1338
+ // Additional headers?
1339
+ $headers = array();
1340
+ if (!is_null($leaseId)) {
1341
+ $headers['x-ms-lease-id'] = $leaseId;
1342
+ }
1343
+ foreach ($additionalHeaders as $key => $value) {
1344
+ $headers[$key] = $value;
1345
+ }
1346
+
1347
+ // Resource name
1348
+ $resourceName = self::createResourceName($containerName , $blobName);
1349
+
1350
+ // Perform request
1351
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
1352
+ if ($response->isSuccessful()) {
1353
+ return $response->getBody();
1354
+ } else {
1355
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1356
+ }
1357
+ }
1358
+
1359
+ /**
1360
+ * Get blob instance
1361
+ *
1362
+ * @param string $containerName Container name
1363
+ * @param string $blobName Blob name
1364
+ * @param string $snapshotId Snapshot identifier
1365
+ * @param string $leaseId Lease identifier
1366
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1367
+ * @return Microsoft_WindowsAzure_Storage_BlobInstance
1368
+ * @throws Microsoft_WindowsAzure_Exception
1369
+ */
1370
+ public function getBlobInstance($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1371
+ {
1372
+ if ($containerName === '') {
1373
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1374
+ }
1375
+ if (!self::isValidContainerName($containerName)) {
1376
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1377
+ }
1378
+ if ($blobName === '') {
1379
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1380
+ }
1381
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1382
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1383
+ }
1384
+
1385
+ // Build query string
1386
+ $queryString = array();
1387
+ if (!is_null($snapshotId)) {
1388
+ $queryString[] = 'snapshot=' . $snapshotId;
1389
+ }
1390
+ $queryString = self::createQueryStringFromArray($queryString);
1391
+
1392
+ // Additional headers?
1393
+ $headers = array();
1394
+ if (!is_null($leaseId)) {
1395
+ $headers['x-ms-lease-id'] = $leaseId;
1396
+ }
1397
+ foreach ($additionalHeaders as $key => $value) {
1398
+ $headers[$key] = $value;
1399
+ }
1400
+
1401
+ // Resource name
1402
+ $resourceName = self::createResourceName($containerName , $blobName);
1403
+
1404
+ // Perform request
1405
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::HEAD, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
1406
+ if ($response->isSuccessful()) {
1407
+ // Parse metadata
1408
+ $metadata = $this->_parseMetadataHeaders($response->getHeaders());
1409
+
1410
+ // Return blob
1411
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
1412
+ $containerName,
1413
+ $blobName,
1414
+ $snapshotId,
1415
+ $response->getHeader('Etag'),
1416
+ $response->getHeader('Last-modified'),
1417
+ $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
1418
+ $response->getHeader('Content-Length'),
1419
+ $response->getHeader('Content-Type'),
1420
+ $response->getHeader('Content-MD5'),
1421
+ $response->getHeader('Content-Encoding'),
1422
+ $response->getHeader('Content-Language'),
1423
+ $response->getHeader('Cache-Control'),
1424
+ $response->getHeader('x-ms-blob-type'),
1425
+ $response->getHeader('x-ms-lease-status'),
1426
+ false,
1427
+ $metadata
1428
+ );
1429
+ } else {
1430
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1431
+ }
1432
+ }
1433
+
1434
+ /**
1435
+ * Get blob metadata
1436
+ *
1437
+ * @param string $containerName Container name
1438
+ * @param string $blobName Blob name
1439
+ * @param string $snapshotId Snapshot identifier
1440
+ * @param string $leaseId Lease identifier
1441
+ * @return array Key/value pairs of meta data
1442
+ * @throws Microsoft_WindowsAzure_Exception
1443
+ */
1444
+ public function getBlobMetadata($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null)
1445
+ {
1446
+ if ($containerName === '') {
1447
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1448
+ }
1449
+ if (!self::isValidContainerName($containerName)) {
1450
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1451
+ }
1452
+ if ($blobName === '') {
1453
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1454
+ }
1455
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1456
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1457
+ }
1458
+
1459
+ return $this->getBlobInstance($containerName, $blobName, $snapshotId, $leaseId)->Metadata;
1460
+ }
1461
+
1462
+ /**
1463
+ * Set blob metadata
1464
+ *
1465
+ * Calling the Set Blob Metadata operation overwrites all existing metadata that is associated with the blob. It's not possible to modify an individual name/value pair.
1466
+ *
1467
+ * @param string $containerName Container name
1468
+ * @param string $blobName Blob name
1469
+ * @param array $metadata Key/value pairs of meta data
1470
+ * @param string $leaseId Lease identifier
1471
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1472
+ * @throws Microsoft_WindowsAzure_Exception
1473
+ */
1474
+ public function setBlobMetadata($containerName = '', $blobName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
1475
+ {
1476
+ if ($containerName === '') {
1477
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1478
+ }
1479
+ if (!self::isValidContainerName($containerName)) {
1480
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1481
+ }
1482
+ if ($blobName === '') {
1483
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1484
+ }
1485
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1486
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1487
+ }
1488
+ if (count($metadata) == 0) {
1489
+ return;
1490
+ }
1491
+
1492
+ // Create metadata headers
1493
+ $headers = array();
1494
+ if (!is_null($leaseId)) {
1495
+ $headers['x-ms-lease-id'] = $leaseId;
1496
+ }
1497
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
1498
+
1499
+ // Additional headers?
1500
+ foreach ($additionalHeaders as $key => $value) {
1501
+ $headers[$key] = $value;
1502
+ }
1503
+
1504
+ // Perform request
1505
+ $response = $this->_performRequest($containerName . '/' . $blobName, '?comp=metadata', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1506
+ if (!$response->isSuccessful()) {
1507
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1508
+ }
1509
+ }
1510
+
1511
+ /**
1512
+ * Set blob properties
1513
+ *
1514
+ * All available properties are listed at http://msdn.microsoft.com/en-us/library/ee691966.aspx and should be provided in the $additionalHeaders parameter.
1515
+ *
1516
+ * @param string $containerName Container name
1517
+ * @param string $blobName Blob name
1518
+ * @param string $leaseId Lease identifier
1519
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1520
+ * @throws Microsoft_WindowsAzure_Exception
1521
+ */
1522
+ public function setBlobProperties($containerName = '', $blobName = '', $leaseId = null, $additionalHeaders = array())
1523
+ {
1524
+ if ($containerName === '') {
1525
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1526
+ }
1527
+ if (!self::isValidContainerName($containerName)) {
1528
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1529
+ }
1530
+ if ($blobName === '') {
1531
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1532
+ }
1533
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1534
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1535
+ }
1536
+ if (count($additionalHeaders) == 0) {
1537
+ throw new Microsoft_WindowsAzure_Exception('No additional headers are specified.');
1538
+ }
1539
+
1540
+ // Create headers
1541
+ $headers = array();
1542
+
1543
+ // Lease set?
1544
+ if (!is_null($leaseId)) {
1545
+ $headers['x-ms-lease-id'] = $leaseId;
1546
+ }
1547
+
1548
+ // Additional headers?
1549
+ foreach ($additionalHeaders as $key => $value) {
1550
+ $headers[$key] = $value;
1551
+ }
1552
+
1553
+ // Perform request
1554
+ $response = $this->_performRequest($containerName . '/' . $blobName, '?comp=properties', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1555
+ if (!$response->isSuccessful()) {
1556
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1557
+ }
1558
+ }
1559
+
1560
+ /**
1561
+ * Get blob properties
1562
+ *
1563
+ * @param string $containerName Container name
1564
+ * @param string $blobName Blob name
1565
+ * @param string $snapshotId Snapshot identifier
1566
+ * @param string $leaseId Lease identifier
1567
+ * @return Microsoft_WindowsAzure_Storage_BlobInstance
1568
+ * @throws Microsoft_WindowsAzure_Exception
1569
+ */
1570
+ public function getBlobProperties($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null)
1571
+ {
1572
+ if ($containerName === '') {
1573
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1574
+ }
1575
+ if (!self::isValidContainerName($containerName)) {
1576
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1577
+ }
1578
+ if ($blobName === '') {
1579
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1580
+ }
1581
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1582
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1583
+ }
1584
+
1585
+ return $this->getBlobInstance($containerName, $blobName, $snapshotId, $leaseId);
1586
+ }
1587
+
1588
+ /**
1589
+ * Delete blob
1590
+ *
1591
+ * @param string $containerName Container name
1592
+ * @param string $blobName Blob name
1593
+ * @param string $snapshotId Snapshot identifier
1594
+ * @param string $leaseId Lease identifier
1595
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1596
+ * @throws Microsoft_WindowsAzure_Exception
1597
+ */
1598
+ public function deleteBlob($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1599
+ {
1600
+ if ($containerName === '') {
1601
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1602
+ }
1603
+ if (!self::isValidContainerName($containerName)) {
1604
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1605
+ }
1606
+ if ($blobName === '') {
1607
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1608
+ }
1609
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1610
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1611
+ }
1612
+
1613
+ // Build query string
1614
+ $queryString = array();
1615
+ if (!is_null($snapshotId)) {
1616
+ $queryString[] = 'snapshot=' . $snapshotId;
1617
+ }
1618
+ $queryString = self::createQueryStringFromArray($queryString);
1619
+
1620
+ // Additional headers?
1621
+ $headers = array();
1622
+ if (!is_null($leaseId)) {
1623
+ $headers['x-ms-lease-id'] = $leaseId;
1624
+ }
1625
+ foreach ($additionalHeaders as $key => $value) {
1626
+ $headers[$key] = $value;
1627
+ }
1628
+
1629
+ // Resource name
1630
+ $resourceName = self::createResourceName($containerName , $blobName);
1631
+
1632
+ // Perform request
1633
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::DELETE, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1634
+ if (!$response->isSuccessful()) {
1635
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1636
+ }
1637
+ }
1638
+
1639
+ /**
1640
+ * Snapshot blob
1641
+ *
1642
+ * @param string $containerName Container name
1643
+ * @param string $blobName Blob name
1644
+ * @param array $metadata Key/value pairs of meta data
1645
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1646
+ * @return string Date/Time value representing the snapshot identifier.
1647
+ * @throws Microsoft_WindowsAzure_Exception
1648
+ */
1649
+ public function snapshotBlob($containerName = '', $blobName = '', $metadata = array(), $additionalHeaders = array())
1650
+ {
1651
+ if ($containerName === '') {
1652
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1653
+ }
1654
+ if (!self::isValidContainerName($containerName)) {
1655
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1656
+ }
1657
+ if ($blobName === '') {
1658
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1659
+ }
1660
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1661
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1662
+ }
1663
+
1664
+ // Additional headers?
1665
+ $headers = array();
1666
+ foreach ($additionalHeaders as $key => $value) {
1667
+ $headers[$key] = $value;
1668
+ }
1669
+
1670
+ // Resource name
1671
+ $resourceName = self::createResourceName($containerName , $blobName);
1672
+
1673
+ // Perform request
1674
+ $response = $this->_performRequest($resourceName, '?comp=snapshot', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1675
+ if ($response->isSuccessful()) {
1676
+ return $response->getHeader('x-ms-snapshot');
1677
+ } else {
1678
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1679
+ }
1680
+ }
1681
+
1682
+ /**
1683
+ * Lease blob - See (http://msdn.microsoft.com/en-us/library/ee691972.aspx)
1684
+ *
1685
+ * @param string $containerName Container name
1686
+ * @param string $blobName Blob name
1687
+ * @param string $leaseAction Lease action (Microsoft_WindowsAzure_Storage_Blob::LEASE_*)
1688
+ * @param string $leaseId Lease identifier, required to renew the lease or to release the lease.
1689
+ * @return Microsoft_WindowsAzure_Storage_LeaseInstance Lease instance
1690
+ * @throws Microsoft_WindowsAzure_Exception
1691
+ */
1692
+ public function leaseBlob($containerName = '', $blobName = '', $leaseAction = self::LEASE_ACQUIRE, $leaseId = null)
1693
+ {
1694
+ if ($containerName === '') {
1695
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1696
+ }
1697
+ if (!self::isValidContainerName($containerName)) {
1698
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1699
+ }
1700
+ if ($blobName === '') {
1701
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1702
+ }
1703
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1704
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1705
+ }
1706
+
1707
+ // Additional headers?
1708
+ $headers = array();
1709
+ $headers['x-ms-lease-action'] = strtolower($leaseAction);
1710
+ if (!is_null($leaseId)) {
1711
+ $headers['x-ms-lease-id'] = $leaseId;
1712
+ }
1713
+
1714
+ // Resource name
1715
+ $resourceName = self::createResourceName($containerName , $blobName);
1716
+
1717
+ // Perform request
1718
+ $response = $this->_performRequest($resourceName, '?comp=lease', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1719
+ if ($response->isSuccessful()) {
1720
+ return new Microsoft_WindowsAzure_Storage_LeaseInstance(
1721
+ $containerName,
1722
+ $blobName,
1723
+ $response->getHeader('x-ms-lease-id'),
1724
+ $response->getHeader('x-ms-lease-time'));
1725
+ } else {
1726
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1727
+ }
1728
+ }
1729
+
1730
+ /**
1731
+ * List blobs
1732
+ *
1733
+ * @param string $containerName Container name
1734
+ * @param string $prefix Optional. Filters the results to return only blobs whose name begins with the specified prefix.
1735
+ * @param string $delimiter Optional. Delimiter, i.e. '/', for specifying folder hierarchy
1736
+ * @param int $maxResults Optional. Specifies the maximum number of blobs to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
1737
+ * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
1738
+ * @param string $include Optional. Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs'). Multiple values can be added separated with a comma (,)
1739
+ * @param int $currentResultCount Current result count (internal use)
1740
+ * @return array
1741
+ * @throws Microsoft_WindowsAzure_Exception
1742
+ */
1743
+ public function listBlobs($containerName = '', $prefix = '', $delimiter = '', $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
1744
+ {
1745
+ if ($containerName === '') {
1746
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1747
+ }
1748
+ if (!self::isValidContainerName($contai