WP External Links (nofollow new tab seo) - Version 1.01

Version Description

  • Solved bug after live testing
Download this release

Release Info

Developer freelancephp
Plugin Icon 128x128 WP External Links (nofollow new tab seo)
Version 1.01
Comparing to
See all releases

Code changes from version 0.35 to 1.01

Files changed (101) hide show
  1. css/tipsy.css +7 -0
  2. images/help-icon.png +0 -0
  3. images/icon-email-encoder-bundle-16.png +0 -0
  4. images/{icon-email-encoder-bundle.png → icon-email-encoder-bundle-32.png} +0 -0
  5. images/icon-wp-16.gif +0 -0
  6. images/icon-wp-external-links-16.png +0 -0
  7. images/{icon-wp-external-links.png → icon-wp-external-links-32.png} +0 -0
  8. images/icon-wp-mailto-links-16.png +0 -0
  9. images/{icon-wp-mailto-links.png → icon-wp-mailto-links-32.png} +0 -0
  10. images/tipsy.gif +0 -0
  11. includes/class-admin-external-links.php +498 -0
  12. includes/class-wp-external-links.php +261 -0
  13. includes/phpQuery/phpQuery.php +1342 -0
  14. includes/phpQuery/phpQuery/Callback.php +152 -0
  15. includes/phpQuery/phpQuery/DOMDocumentWrapper.php +677 -0
  16. includes/phpQuery/phpQuery/DOMEvent.php +107 -0
  17. includes/phpQuery/phpQuery/Zend/Exception.php +30 -0
  18. includes/phpQuery/phpQuery/Zend/Http/Client.php +1186 -0
  19. includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Exception.php +33 -0
  20. includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Interface.php +78 -0
  21. includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Proxy.php +268 -0
  22. includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Socket.php +332 -0
  23. includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Test.php +193 -0
  24. includes/phpQuery/phpQuery/Zend/Http/Client/Exception.php +33 -0
  25. includes/phpQuery/phpQuery/Zend/Http/Cookie.php +327 -0
  26. includes/phpQuery/phpQuery/Zend/Http/CookieJar.php +350 -0
  27. includes/phpQuery/phpQuery/Zend/Http/Exception.php +33 -0
  28. includes/phpQuery/phpQuery/Zend/Http/Response.php +625 -0
  29. includes/phpQuery/phpQuery/Zend/Json/Decoder.php +457 -0
  30. includes/phpQuery/phpQuery/Zend/Json/Encoder.php +431 -0
  31. includes/phpQuery/phpQuery/Zend/Json/Exception.php +36 -0
  32. includes/phpQuery/phpQuery/Zend/Loader.php +258 -0
  33. includes/phpQuery/phpQuery/Zend/Registry.php +195 -0
  34. includes/phpQuery/phpQuery/Zend/Uri.php +164 -0
  35. includes/phpQuery/phpQuery/Zend/Uri/Exception.php +37 -0
  36. includes/phpQuery/phpQuery/Zend/Uri/Http.php +702 -0
  37. includes/phpQuery/phpQuery/Zend/Validate/Abstract.php +348 -0
  38. includes/phpQuery/phpQuery/Zend/Validate/Alnum.php +120 -0
  39. includes/phpQuery/phpQuery/Zend/Validate/Alpha.php +120 -0
  40. includes/phpQuery/phpQuery/Zend/Validate/Barcode.php +99 -0
  41. includes/phpQuery/phpQuery/Zend/Validate/Barcode/Ean13.php +100 -0
  42. includes/phpQuery/phpQuery/Zend/Validate/Barcode/UpcA.php +100 -0
  43. includes/phpQuery/phpQuery/Zend/Validate/Between.php +200 -0
  44. includes/phpQuery/phpQuery/Zend/Validate/Ccnum.php +111 -0
  45. includes/phpQuery/phpQuery/Zend/Validate/Date.php +250 -0
  46. includes/phpQuery/phpQuery/Zend/Validate/Digits.php +100 -0
  47. includes/phpQuery/phpQuery/Zend/Validate/EmailAddress.php +245 -0
  48. includes/phpQuery/phpQuery/Zend/Validate/Exception.php +37 -0
  49. includes/phpQuery/phpQuery/Zend/Validate/File/Count.php +229 -0
  50. includes/phpQuery/phpQuery/Zend/Validate/File/Exists.php +192 -0
  51. includes/phpQuery/phpQuery/Zend/Validate/File/Extension.php +204 -0
  52. includes/phpQuery/phpQuery/Zend/Validate/File/FilesSize.php +156 -0
  53. includes/phpQuery/phpQuery/Zend/Validate/File/ImageSize.php +335 -0
  54. includes/phpQuery/phpQuery/Zend/Validate/File/MimeType.php +200 -0
  55. includes/phpQuery/phpQuery/Zend/Validate/File/NotExists.php +86 -0
  56. includes/phpQuery/phpQuery/Zend/Validate/File/Size.php +308 -0
  57. includes/phpQuery/phpQuery/Zend/Validate/File/Upload.php +216 -0
  58. includes/phpQuery/phpQuery/Zend/Validate/Float.php +75 -0
  59. includes/phpQuery/phpQuery/Zend/Validate/GreaterThan.php +114 -0
  60. includes/phpQuery/phpQuery/Zend/Validate/Hex.php +74 -0
  61. includes/phpQuery/phpQuery/Zend/Validate/Hostname.php +444 -0
  62. includes/phpQuery/phpQuery/Zend/Validate/Hostname/At.php +50 -0
  63. includes/phpQuery/phpQuery/Zend/Validate/Hostname/Ch.php +50 -0
  64. includes/phpQuery/phpQuery/Zend/Validate/Hostname/De.php +58 -0
  65. includes/phpQuery/phpQuery/Zend/Validate/Hostname/Fi.php +50 -0
  66. includes/phpQuery/phpQuery/Zend/Validate/Hostname/Hu.php +50 -0
  67. includes/phpQuery/phpQuery/Zend/Validate/Hostname/Interface.php +52 -0
  68. includes/phpQuery/phpQuery/Zend/Validate/Hostname/Li.php +50 -0
  69. includes/phpQuery/phpQuery/Zend/Validate/Hostname/No.php +52 -0
  70. includes/phpQuery/phpQuery/Zend/Validate/Hostname/Se.php +50 -0
  71. includes/phpQuery/phpQuery/Zend/Validate/Identical.php +117 -0
  72. includes/phpQuery/phpQuery/Zend/Validate/InArray.php +138 -0
  73. includes/phpQuery/phpQuery/Zend/Validate/Int.php +75 -0
  74. includes/phpQuery/phpQuery/Zend/Validate/Interface.php +71 -0
  75. includes/phpQuery/phpQuery/Zend/Validate/Ip.php +70 -0
  76. includes/phpQuery/phpQuery/Zend/Validate/LessThan.php +113 -0
  77. includes/phpQuery/phpQuery/Zend/Validate/NotEmpty.php +74 -0
  78. includes/phpQuery/phpQuery/Zend/Validate/Regex.php +125 -0
  79. includes/phpQuery/phpQuery/Zend/Validate/StringLength.php +180 -0
  80. includes/phpQuery/phpQuery/bootstrap.example.php +14 -0
  81. includes/phpQuery/phpQuery/compat/mbstring.php +88 -0
  82. includes/phpQuery/phpQuery/phpQueryEvents.php +158 -0
  83. includes/phpQuery/phpQuery/phpQueryObject.php +3180 -0
  84. includes/phpQuery/phpQuery/plugins/Scripts.php +72 -0
  85. includes/phpQuery/phpQuery/plugins/Scripts/__config.example.php +10 -0
  86. includes/phpQuery/phpQuery/plugins/Scripts/example.php +14 -0
  87. includes/phpQuery/phpQuery/plugins/Scripts/fix_webroot.php +16 -0
  88. includes/phpQuery/phpQuery/plugins/Scripts/google_login.php +47 -0
  89. includes/phpQuery/phpQuery/plugins/Scripts/print_source.php +9 -0
  90. includes/phpQuery/phpQuery/plugins/Scripts/print_websafe.php +13 -0
  91. includes/phpQuery/phpQuery/plugins/WebBrowser.php +405 -0
  92. includes/phpQuery/phpQuery/plugins/example.php +75 -0
  93. includes/wp-plugin-dev-classes/class-wp-meta-box-page.php +662 -0
  94. includes/wp-plugin-dev-classes/class-wp-option-forms.php +349 -0
  95. includes/wp-plugin-dev-classes/wp-option-forms.js +47 -0
  96. js/admin-external-links.js +50 -0
  97. js/external-links.js +23 -18
  98. js/jquery.tipsy.js +104 -0
  99. readme.txt +37 -42
  100. screenshot-2.png +0 -0
  101. wp-external-links.php +29 -556
css/tipsy.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ .tipsy { padding: 5px; font-size: 11px; opacity: 0.8; filter: alpha(opacity=80); background-repeat: no-repeat; background-image: url(../images/tipsy.gif); }
2
+ .tipsy-inner { padding: 5px 8px 4px 8px; background-color: black; color: white; max-width: 200px; text-align: center; }
3
+ .tipsy-inner { -moz-border-radius:3px; -webkit-border-radius:3px; }
4
+ .tipsy-north { background-position: top center; }
5
+ .tipsy-south { background-position: bottom center; }
6
+ .tipsy-east { background-position: right center; }
7
+ .tipsy-west { background-position: left center; }
images/help-icon.png ADDED
Binary file
images/icon-email-encoder-bundle-16.png ADDED
Binary file
images/{icon-email-encoder-bundle.png → icon-email-encoder-bundle-32.png} RENAMED
File without changes
images/icon-wp-16.gif ADDED
Binary file
images/icon-wp-external-links-16.png ADDED
Binary file
images/{icon-wp-external-links.png → icon-wp-external-links-32.png} RENAMED
File without changes
images/icon-wp-mailto-links-16.png ADDED
Binary file
images/{icon-wp-mailto-links.png → icon-wp-mailto-links-32.png} RENAMED
File without changes
images/tipsy.gif ADDED
Binary file
includes/class-admin-external-links.php ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php defined( 'ABSPATH' ) OR die( 'No direct access.' );
2
+ if ( ! class_exists( 'Admin_External_Links' ) ):
3
+
4
+ /**
5
+ * Class Admin_External_Links
6
+ * @category WordPress Plugins
7
+ */
8
+ final class Admin_External_Links {
9
+
10
+ /**
11
+ * Options to be saved and their default values
12
+ * @var array
13
+ */
14
+ protected $save_options = array(
15
+ 'general' => array(
16
+ 'target' => '_none',
17
+ 'use_js' => 1,
18
+ 'external' => 1,
19
+ 'nofollow' => 1,
20
+ 'title' => '%title%',
21
+ 'filter_page' => 1,
22
+ 'filter_posts' => 1,
23
+ 'filter_comments' => 1,
24
+ 'filter_widgets' => 1,
25
+ 'class_name' => 'ext-link',
26
+ 'filter_excl_sel' => '.excl-ext-link',
27
+ ),
28
+ 'style' => array(
29
+ 'icon' => 0,
30
+ 'no_icon_class' => 'no-ext-icon',
31
+ 'no_icon_same_window' => 0,
32
+ ),
33
+ 'screen' => array(
34
+ 'menu_position' => NULL,
35
+ ),
36
+ );
37
+
38
+ /**
39
+ * Meta box page object
40
+ * @var WP_Meta_Box_Page
41
+ */
42
+ public $meta_box_page = NULL;
43
+
44
+ /**
45
+ * Ajax form object
46
+ * @var WP_Ajax_Option_Form
47
+ */
48
+ public $form = NULL;
49
+
50
+
51
+ /**
52
+ * Constructor
53
+ */
54
+ public function __construct() {
55
+ // set meta box page
56
+ $this->meta_box_page = new WP_Meta_Box_Page_01();
57
+
58
+ // set ajax forms (also used by front-end)
59
+ $this->form = new WP_Option_Forms_01( WP_EXTERNAL_LINKS_KEY, $this->save_options );
60
+
61
+ // init admin
62
+ if ( is_admin() )
63
+ $this->init();
64
+ }
65
+
66
+ /**
67
+ * Initialize Admin
68
+ */
69
+ public function init() {
70
+ // load text domain for translations
71
+ load_plugin_textdomain( WP_EXTERNAL_LINKS_KEY, FALSE, dirname( plugin_basename( WP_EXTERNAL_LINKS_FILE ) ) . '/lang/' );
72
+
73
+ // set activation hook
74
+ register_activation_hook( WP_EXTERNAL_LINKS_FILE, array( $this, 'call_activation' ) );
75
+
76
+ // set deactivation hook
77
+ register_deactivation_hook( WP_EXTERNAL_LINKS_FILE, array( $this, 'call_deactivation' ) );
78
+
79
+ // set options for add_page_method
80
+ $menu_pos = $this->form->set_current_option( 'screen' )->value( 'menu_position' );
81
+
82
+ // init meta box page
83
+ $this->meta_box_page->init(
84
+ // settings
85
+ array(
86
+ 'menu_title' => $this->__( 'External Links' ),
87
+ 'page_slug' => strtolower( WP_EXTERNAL_LINKS_KEY ),
88
+ 'add_page_method' => ( ! empty( $menu_pos ) AND $menu_pos != 'admin.php' ) ? 'add_submenu_page' : 'add_menu_page',
89
+ 'parent_slug' => ( ! empty( $menu_pos ) AND $menu_pos != 'admin.php' ) ? $menu_pos : NULL,
90
+ 'column_widths' => array(
91
+ 1 => array( 99 ),
92
+ 2 => array( 69, 29 ),
93
+ ),
94
+ 'icon_url' => plugins_url( 'images/icon-wp-external-links-16.png', WP_EXTERNAL_LINKS_FILE ),
95
+ ),
96
+ // load callback
97
+ array( $this, 'call_load_meta_box' )
98
+ );
99
+ }
100
+
101
+ /**
102
+ * Translate text in current domain
103
+ * @param string $text
104
+ * @return string
105
+ */
106
+ public function __( $text ) {
107
+ return translate( $text, WP_EXTERNAL_LINKS_KEY );
108
+ }
109
+
110
+ /**
111
+ * Translate text in current domain
112
+ * @param string $text
113
+ * @return string
114
+ */
115
+ public function _e( $text ) {
116
+ echo translate( $text, WP_EXTERNAL_LINKS_KEY );
117
+ }
118
+
119
+ /**
120
+ * Load meta box action
121
+ */
122
+ public function call_load_meta_box( $meta_box ) {
123
+ // add filters
124
+ $meta_box->add_title_filter( array( $this, 'call_page_title' ) )
125
+ ->add_screen_settings_filter( array( $this, 'call_screen_settings' ) )
126
+ ->add_contextual_help_filter( array( $this, 'call_contextual_help' ) );
127
+
128
+ // add meta boxes
129
+ // add_meta_box( $title, $callback, $context = 'normal', $id = NULL, $priority = 'default', $callback_args = NULL )
130
+ $meta_box->add_meta_box( $this->__( 'General Settings' ), array( $this, 'call_box_general_settings' ), 1 )
131
+ ->add_meta_box( $this->__( 'Style Settings' ), array( $this, 'call_box_style_settings' ), 1 )
132
+ ->add_meta_box( $this->__( 'About this Plugin' ), array( $this, 'call_box_about' ), 2 )
133
+ ->add_meta_box( $this->__( 'Other Plugins' ), array( $this, 'call_box_other_plugins' ), 2 );
134
+
135
+ // stylesheets
136
+ wp_enqueue_style( 'jquery-tipsy', plugins_url( 'css/tipsy.css', WP_EXTERNAL_LINKS_FILE ), FALSE, WP_EXTERNAL_LINKS_VERSION );
137
+
138
+ // scripts
139
+ wp_enqueue_script( 'jquery-tipsy', plugins_url( '/js/jquery.tipsy.js', WP_EXTERNAL_LINKS_FILE ), array( 'jquery' ), WP_EXTERNAL_LINKS_VERSION );
140
+ wp_enqueue_script( 'admin-external-links', plugins_url( '/js/admin-external-links.js', WP_EXTERNAL_LINKS_FILE ), array( 'postbox', 'option-forms' ), WP_EXTERNAL_LINKS_VERSION );
141
+ }
142
+
143
+ /**
144
+ * Screen settings
145
+ * @param string $content
146
+ * @return string
147
+ */
148
+ public function call_screen_settings( $content ) {
149
+ $content .= '<h5>'. $this->__( 'Menu Setting' ) .'</h5>' . "\n";
150
+ $content .= '<div class="extra-prfs">' . "\n";
151
+ $content .= $this->__( 'Admin menu position' ) . ': ' . "\n";
152
+ $content .= $this->form->open_screen_option( 'screen', 'menu_position' );
153
+ $content .= $this->form->select( 'menu_position', array(
154
+ 'admin.php' => 'Main menu',
155
+ 'index.php' => $this->__( 'Subitem of Dashboard' ),
156
+ 'edit.php' => $this->__( 'Subitem of Posts' ),
157
+ 'upload.php' => $this->__( 'Subitem of Media' ),
158
+ 'link-manager.php' => $this->__( 'Subitem of Links' ),
159
+ 'edit.php?post_type=page' => $this->__( 'Subitem of Pages' ),
160
+ 'edit-comments.php' => $this->__( 'Subitem of Comments' ),
161
+ 'themes.php' => $this->__( 'Subitem of Appearance' ),
162
+ 'plugins.php' => $this->__( 'Subitem of Plugins' ),
163
+ 'users.php' => $this->__( 'Subitem of Users' ),
164
+ 'tools.php' => $this->__( 'Subitem of Tools' ),
165
+ 'options-general.php' => $this->__( 'Subitem of Settings' ),
166
+ )) . "\n";
167
+ $content .= '</div>' . "\n";
168
+
169
+ return $content;
170
+ }
171
+
172
+ /**
173
+ * Contextual_help (callback)
174
+ * @param string $content
175
+ * @return string
176
+ */
177
+ public function call_contextual_help( $content ) {
178
+ $help = '';
179
+ $help .= $this->meta_box_page->get_ob_callback( array( $this, 'call_box_about' ) );
180
+ $help .= $this->hr();
181
+ $help .= '<h4><img src="'. plugins_url( 'images/icon-wp-16.gif', WP_EXTERNAL_LINKS_FILE ) .'" width="16" height="16" /> '
182
+ . $this->__( 'WordPress' ) .'</h4>';
183
+ return $help . $content;
184
+ }
185
+
186
+ /**
187
+ * Add icon to page title
188
+ * @return string
189
+ */
190
+ public function call_page_title( $title ) {
191
+ // when updated set the update message
192
+ if ( $_GET[ 'settings-updated' ] == 'true' ) {
193
+ $title .= '<div class="updated settings-error" id="setting-error-settings_updated" style="display:none">'
194
+ . '<p><strong>' . __( 'Settings saved.' ) .'</strong></p>'
195
+ . '</div>';
196
+ }
197
+
198
+ $title = '<div class="icon32" id="icon-options-custom" style="background:url( '. plugins_url( 'images/icon-wp-external-links-32.png', WP_EXTERNAL_LINKS_FILE ) .' ) no-repeat 50% 50%"><br></div>'
199
+ . $title;
200
+
201
+ return $title;
202
+ }
203
+
204
+ /**
205
+ * Meta Box: General Settings
206
+ */
207
+ public function call_box_general_settings() {
208
+ echo $this->form->set_current_option( 'general' )->open_form();
209
+ ?>
210
+ <fieldset class="options">
211
+ <table class="form-table">
212
+ <tr>
213
+ <th style="width:300px;"><?php $this->_e( 'Set <code>target</code> for external links' ) ?>
214
+ <?php echo $this->tooltip_help( 'Specify the target (window or tab) for opening external links.' ) ?></th>
215
+ <td class="target_external_links">
216
+ <label><?php echo $this->form->radio( 'target', '_blank', array( 'class' => 'field_target' ) ); ?>
217
+ <span><?php $this->_e( '<code>_blank</code>, new window' ) ?></span></label>
218
+ <?php echo $this->tooltip_help( 'Open every external link in a new window or tab.' ) ?>
219
+ <br/>
220
+ <label><?php echo $this->form->radio( 'target', '_top', array( 'class' => 'field_target' ) ); ?>
221
+ <span><?php $this->_e( '<code>_top</code>, topmost frame' ) ?></span></label>
222
+ <?php echo $this->tooltip_help( 'Open in current window or tab, when framed in the topmost frame.' ) ?>
223
+ <br/>
224
+ <label><?php echo $this->form->radio( 'target', '_new', array( 'class' => 'field_target' ) ); ?>
225
+ <span><?php $this->_e( '<code>_new</code>, seperate window' ) ?></span></label>
226
+ <?php echo $this->tooltip_help( 'Open new window the first time and use this window for each external link.' ) ?>
227
+ <br/>
228
+ <label><?php echo $this->form->radio( 'target', '_none', array( 'class' => 'field_target' ) ); ?>
229
+ <span><?php $this->_e( '<code>_none</code>, current window' ) ?></span></label>
230
+ <?php echo $this->tooltip_help( 'Open in current window or tab, when framed in the same frame.' ) ?>
231
+ </td>
232
+ </tr>
233
+ <tr>
234
+ <th><?php $this->_e( 'Add to <code>rel</code>-attribute' ) ?>
235
+ <?php echo $this->tooltip_help( 'Set values for the "rel"-atribute of external links.' ) ?></th>
236
+ <td><label><?php echo $this->form->checkbox( 'external', 1 ); ?>
237
+ <span><?php $this->_e( 'Add <code>"external"</code>' ) ?></span></label>
238
+ <?php echo $this->tooltip_help( 'Add "external" to the "rel"-attribute of external links.' ) ?>
239
+ <br/><label><?php echo $this->form->checkbox( 'nofollow', 1 ); ?>
240
+ <span><?php $this->_e( 'Add <code>"nofollow"</code>' ) ?></span></label>
241
+ <?php echo $this->tooltip_help( 'Add "nofollow" to the "rel"-attribute of external links (unless link already has "follow").' ) ?>
242
+ </td>
243
+ </tr>
244
+ <tr>
245
+ <th><?php $this->_e( 'Add to <code>class</code>-attribute' ) ?>
246
+ <?php echo $this->tooltip_help( 'Add one or more extra classes to the external links, seperated by a space. It is optional, else just leave field blank.' ) ?></th>
247
+ <td><label><?php echo $this->form->text( 'class_name' ); ?></label></td>
248
+ </tr>
249
+ <tr>
250
+ <th><?php $this->_e( 'Set <code>title</code>-attribute' ) ?>
251
+ <?php echo $this->tooltip_help( 'Set title attribute for external links. Use %title% for the original title value.' ) ?></th>
252
+ <td><label><?php echo $this->form->text( 'title' ); ?>
253
+ <br/><span class="description"><?php _e( 'Use <code>%title%</code> for the original title value.' ) ?></span></label></td>
254
+ </tr>
255
+ </table>
256
+
257
+ <?php echo $this->hr(); ?>
258
+
259
+ <table class="form-table">
260
+ <tr>
261
+ <th style="width:300px;"><?php $this->_e( 'Valid XHTML Strict' ) ?>
262
+ <?php echo $this->tooltip_help( 'The "target"-attribute is not valid XHTML strict code. Enable this option to remove the target from external links and use the JavaScript method (built-in this plugin) for opening links.' ) ?></th>
263
+ <td>
264
+ <label><?php echo $this->form->checkbox( 'use_js', 1, array( 'class' => 'field_use_js' ) ); ?>
265
+ <span><?php $this->_e( 'Use JavaScript for opening links in given target, instead of setting <code>target</code>-attribute <em>(recommended)</em>' ) ?></span></label>
266
+ </td>
267
+ </tr>
268
+ </table>
269
+
270
+ <?php echo $this->hr(); ?>
271
+
272
+ <table class="form-table">
273
+ <tr>
274
+ <th style="width:300px;"><?php $this->_e( 'Apply settings to external links on...' ) ?>
275
+ <?php echo $this->tooltip_help( 'Choose contents for applying settings to external links.' ) ?></th>
276
+ <td>
277
+ <label><?php echo $this->form->checkbox( 'filter_page', 1 ); ?>
278
+ <span><?php $this->_e( 'All contents' ) ?></span></label>
279
+ <br/>&nbsp;&nbsp;<label><?php echo $this->form->checkbox( 'filter_posts', 1 ); ?>
280
+ <span><?php $this->_e( 'Post contents' ) ?></span></label>
281
+ <br/>&nbsp;&nbsp;<label><?php echo $this->form->checkbox( 'filter_comments', 1 ); ?>
282
+ <span><?php $this->_e( 'Comments' ) ?></span></label>
283
+ <br/>&nbsp;&nbsp;<label><?php echo $this->form->checkbox( 'filter_widgets', 1 ); ?>
284
+ <span><?php
285
+ if ( self::check_widget_content_filter() ):
286
+ $this->_e( 'All widgets' );
287
+ echo $this->tooltip_help( 'Applied to all widgets by using the "widget_content" filter of the Widget Logic plugin' );
288
+ else:
289
+ $this->_e( 'All text widgets' );
290
+ echo $this->tooltip_help( 'Only the text widget will be applied. To apply to all widget you should select "All contents" option.' );
291
+ endif;
292
+ ?></span></label>
293
+ </td>
294
+ </tr>
295
+ <tr class="filter_excl_sel">
296
+ <th><?php $this->_e( 'Do NOT apply settings on...' ) ?>
297
+ <?php echo $this->tooltip_help( 'The external links of these selection will be excluded for the settings of this plugin. Define the selection by using CSS selectors.' ) ?></th>
298
+ <td><label><?php echo $this->form->textarea( 'filter_excl_sel' ); ?>
299
+ <span class="description"><?php _e( 'Define selection by using CSS selectors, f.e.: <code>.excl-ext-link, .entry-title, #comments-title</code> (look <a href="http://code.google.com/p/phpquery/wiki/Selectors" target="_blank">here</a> for available selectors).' ) ?></span></label>
300
+ </td>
301
+ </tr>
302
+ </table>
303
+ </fieldset>
304
+
305
+ <p style="position:absolute;"><a id="admin_menu_position" href="#"><?php _e( 'Change menu position in "Screen Options"' ) ?></a></p>
306
+ <?php
307
+ echo $this->form->submit();
308
+ echo $this->form->close_form();
309
+ }
310
+
311
+ /**
312
+ * Meta Box: Style Settings
313
+ */
314
+ public function call_box_style_settings() {
315
+ echo $this->form->set_current_option( 'style' )->open_form();
316
+ ?>
317
+ <fieldset class="options">
318
+ <table class="form-table">
319
+ <tr>
320
+ <th style="width:300px;"><?php $this->_e( 'Set icon for external link' ) ?>
321
+ <?php echo $this->tooltip_help( 'Set an icon that wll be shown for external links. See example on the right side.' ) ?></th>
322
+ <td>
323
+ <div>
324
+ <div style="width:15%;float:left">
325
+ <label><?php echo $this->form->radio( 'icon', 0 ); ?>
326
+ <span><?php $this->_e( 'No icon' ) ?></span></label>
327
+ <?php for ( $x = 1; $x <= 20; $x++ ): ?>
328
+ <br/>
329
+ <label title="<?php echo sprintf( $this->__( 'Icon %1$s: choose this icon to show for all external links or add the class \'ext-icon-%1$s\' to a specific link.' ), $x ) ?>">
330
+ <?php echo $this->form->radio( 'icon', $x ); ?>
331
+ <img src="<?php echo plugins_url( 'images/external-'. $x .'.png', WP_EXTERNAL_LINKS_FILE ) ?>" /></label>
332
+ <?php if ( $x % 5 == 0 ): ?>
333
+ </div>
334
+ <div style="width:15%;float:left">
335
+ <?php endif; ?>
336
+ <?php endfor; ?>
337
+ </div>
338
+ <div style="width:29%;float:left;"><span class="description"><?php $this->_e( 'Example:' ) ?></span>
339
+ <br/><img src="<?php echo plugins_url( 'images/link-icon-example.png', WP_EXTERNAL_LINKS_FILE ) ?>" />
340
+ </div>
341
+ <br style="clear:both" />
342
+ </div>
343
+ </td>
344
+ </tr>
345
+ <tr>
346
+ <th style="width:300px;"><?php $this->_e( 'Set no-icon class' ) ?>
347
+ <?php echo $this->tooltip_help( 'Set this class for links, that should not have the external link icon.' ) ?></th>
348
+ <td><label><?php echo $this->form->text( 'no_icon_class', array( 'class' => '' ) ); ?></label>
349
+ <br/><label><?php echo $this->form->checkbox( 'no_icon_same_window', 1 ); ?>
350
+ <span><?php $this->_e( 'Always open links with no-icon class in same window or tab' ) ?></span></label>
351
+ <?php echo $this->tooltip_help( 'When enabled external links containing the no-icon class will always be opened in the current window or tab. No matter which target is set.' ) ?>
352
+ </td>
353
+ </tr>
354
+ </table>
355
+ </fieldset>
356
+ <?php
357
+ echo $this->form->submit();
358
+ echo $this->form->close_form();
359
+ }
360
+
361
+ /**
362
+ * Meta Box: About...
363
+ */
364
+ public function call_box_about() {
365
+ ?>
366
+ <h4><img src="<?php echo plugins_url( 'images/icon-wp-external-links-16.png', WP_EXTERNAL_LINKS_FILE ) ?>" width="16" height="16" /> <?php $this->_e( 'WP External Links' ) ?></h4>
367
+ <div>
368
+ <p><?php printf( $this->__( 'Current version: <strong>%1$s</strong>' ), WP_EXTERNAL_LINKS_VERSION ) ?></p>
369
+ <p><?php $this->_e( 'Manage external links on your site: open in new window/tab, set link icon, add "external", add "nofollow" and more.' ) ?></p>
370
+ <p><a href="http://www.freelancephp.net/contact/" target="_blank"><?php $this->_e( 'Questions or suggestions?' ) ?></a></p>
371
+ <p><?php $this->_e( 'If you like this plugin please send your rating at WordPress.org.' ) ?></p>
372
+ <p><?php _e( 'More info' ) ?>: <a href="http://wordpress.org/extend/plugins/wp-external-links/" target="_blank">WordPress.org</a> | <a href="http://www.freelancephp.net/wp-external-links-plugin/" target="_blank">FreelancePHP.net</a></p>
373
+ </div>
374
+ <?php
375
+ }
376
+
377
+ /**
378
+ * Meta Box: Other Plugins
379
+ */
380
+ public function call_box_other_plugins() {
381
+ ?>
382
+ <h4><img src="<?php echo plugins_url( 'images/icon-email-encoder-bundle-16.png', WP_EXTERNAL_LINKS_FILE ); ?>" width="16" height="16" /> Email Encoder Bundle</h4>
383
+ <div>
384
+ <?php if ( is_plugin_active( 'email-encoder-bundle/email-encoder-bundle.php' ) ): ?>
385
+ <p><?php $this->_e( 'This plugin is already activated.' ) ?> <a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/options-general.php?page=email-encoder-bundle/email-encoder-bundle.php"><?php $this->_e( 'Settings' ) ?></a></p>
386
+ <?php elseif( file_exists( WP_PLUGIN_DIR . '/email-encoder-bundle/email-encoder-bundle.php' ) ): ?>
387
+ <p><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugins.php?plugin_status=inactive"><?php $this->_e( 'Activate this plugin.' ) ?></a></p>
388
+ <?php else: ?>
389
+ <p><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugin-install.php?tab=search&type=term&s=Email+Encoder+Bundle+freelancephp&plugin-search-input=Search+Plugins"><?php $this->_e( 'Get this plugin now' ) ?></a></p>
390
+ <?php endif; ?>
391
+
392
+ <p><?php $this->_e( 'Protect email addresses on your site from spambots and being used for spamming by using one of the encoding methods.' ) ?></p>
393
+ <p><?php _e( 'More info' ) ?>: <a href="http://wordpress.org/extend/plugins/email-encoder-bundle/" target="_blank">WordPress.org</a> | <a href="http://www.freelancephp.net/email-encoder-php-class-wp-plugin/" target="_blank">FreelancePHP.net</a></p>
394
+ </div>
395
+
396
+ <?php echo $this->hr(); ?>
397
+
398
+ <h4><img src="<?php echo plugins_url( 'images/icon-wp-mailto-links-16.png', WP_EXTERNAL_LINKS_FILE ); ?>" width="16" height="16" /> WP Mailto Links</h4>
399
+ <div>
400
+ <?php if ( is_plugin_active( 'wp-mailto-links/wp-mailto-links.php' ) ): ?>
401
+ <p><?php $this->_e( 'This plugin is already activated.' ) ?> <a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/options-general.php?page=wp-mailto-links/wp-mailto-links.php"><?php $this->_e( 'Settings' ) ?></a></p>
402
+ <?php elseif( file_exists( WP_PLUGIN_DIR . '/wp-mailto-links/wp-mailto-links.php' ) ): ?>
403
+ <p><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugins.php?plugin_status=inactive"><?php $this->_e( 'Activate this plugin.' ) ?></a></p>
404
+ <?php else: ?>
405
+ <p><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugin-install.php?tab=search&type=term&s=WP+Mailto+Links+freelancephp&plugin-search-input=Search+Plugins"><?php $this->_e( 'Get this plugin now' ) ?></a></p>
406
+ <?php endif; ?>
407
+
408
+ <p><?php $this->_e( 'Manage mailto links on your site and protect emails from spambots, set mail icon and more.' ) ?></p>
409
+ <p><?php _e( 'More info' ) ?>: <a href="http://wordpress.org/extend/plugins/wp-mailto-links/" target="_blank">WordPress.org</a> | <a href="http://www.freelancephp.net/wp-mailto-links-plugin/" target="_blank">FreelancePHP.net</a></p>
410
+ </div>
411
+ <?php
412
+ }
413
+
414
+ /**
415
+ * Activation plugin callback
416
+ */
417
+ public function call_activation() {
418
+ // check for upgrading saved options to v1.00
419
+ $old_options = get_option( 'WP_External_Links_options' );
420
+
421
+ if ( ! empty( $old_options ) ) {
422
+ $new_options = $this->save_options;
423
+
424
+ foreach ( $old_options AS $option ) {
425
+ $new_options[ 'general' ][ 'target' ] = $old_options[ 'target' ];
426
+ $new_options[ 'general' ][ 'use_js' ] = $old_options[ 'use_js' ];
427
+ $new_options[ 'general' ][ 'external' ] = $old_options[ 'external' ];
428
+ $new_options[ 'general' ][ 'nofollow' ] = $old_options[ 'nofollow' ];
429
+ $new_options[ 'general' ][ 'filter_page' ] = $old_options[ 'filter_whole_page' ];
430
+ $new_options[ 'general' ][ 'filter_posts' ] = $old_options[ 'filter_posts' ];
431
+ $new_options[ 'general' ][ 'filter_comments' ] = $old_options[ 'filter_comments' ];
432
+ $new_options[ 'general' ][ 'filter_widgets' ] = $old_options[ 'filter_widgets' ];
433
+ $new_options[ 'general' ][ 'class_name' ] = $old_options[ 'class_name' ];
434
+ $new_options[ 'style' ][ 'icon' ] = $old_options[ 'icon' ];
435
+ $new_options[ 'style' ][ 'no_icon_class' ] = $old_options[ 'no_icon_class' ];
436
+ $new_options[ 'style' ][ 'no_icon_same_window' ] = $old_options[ 'no_icon_same_window' ];
437
+ }
438
+
439
+ // save new format option values
440
+ update_option( 'wp_external_links-general', $new_options[ 'general' ] );
441
+ update_option( 'wp_external_links-style', $new_options[ 'style' ] );
442
+
443
+ // delete old format option values
444
+ delete_option( 'WP_External_Links_options' );
445
+ unregister_setting( 'WP_External_Links', 'WP_External_Links_options' );
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Deactivation plugin callback
451
+ */
452
+ public function call_deactivation() {
453
+ $this->form->delete_options();
454
+ }
455
+
456
+ /**
457
+ * Set tooltip help
458
+ * @param string $text
459
+ * @return string
460
+ */
461
+ public function tooltip_help( $text ) {
462
+ $text = $this->__( $text );
463
+ $text = htmlentities( $text );
464
+
465
+ $html = '';
466
+ $html .= '<a href="#" class="tooltip-help" title="'. $text .'">';
467
+ $html .= '<img alt="" title="" src="'. plugins_url( '/images/help-icon.png', WP_EXTERNAL_LINKS_FILE ) .'" />';
468
+ $html .= '</a>';
469
+ return $html;
470
+ }
471
+
472
+ /**
473
+ * Get html seperator
474
+ * @return string
475
+ */
476
+ protected function hr() {
477
+ return '<hr style="border:1px solid #FFF; border-top:1px solid #EEE;" />';
478
+ }
479
+
480
+
481
+ /**
482
+ * Check if widget_content filter is available (Widget Logic Plugin)
483
+ * @return boolean
484
+ * @static
485
+ */
486
+ public static function check_widget_content_filter() {
487
+ // set widget_content filter of Widget Logic plugin
488
+ $widget_logic_opts = get_option( 'widget_logic' );
489
+
490
+ if ( function_exists( 'widget_logic_expand_control' ) AND is_array( $widget_logic_opts ) AND key_exists( 'widget_logic-options-filter', $widget_logic_opts ) )
491
+ return ( $widget_logic_opts[ 'widget_logic-options-filter' ] == 'checked' );
492
+
493
+ return FALSE;
494
+ }
495
+
496
+ } // End Admin_External_Links Class
497
+
498
+ endif;
includes/class-wp-external-links.php ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php defined( 'ABSPATH' ) OR die( 'No direct access.' );
2
+ if ( ! class_exists( 'WP_External_Links' ) ):
3
+
4
+ /**
5
+ * Class WP_External_Links
6
+ * @category WordPress Plugins
7
+ */
8
+ final class WP_External_Links {
9
+
10
+ /**
11
+ * Admin object
12
+ * @var Admin_External_Links
13
+ */
14
+ private $admin = NULL;
15
+
16
+
17
+ /**
18
+ * Constructor
19
+ */
20
+ public function __construct() {
21
+ // set admin object
22
+ $this->admin = new Admin_External_Links();
23
+
24
+ // add actions
25
+ add_action( 'wp', array( $this, 'call_wp' ) );
26
+ }
27
+
28
+ /**
29
+ * Quick helper method for getting saved option values
30
+ * @param string $key
31
+ * @param string $option_name Optional, default looking in 'general' settings
32
+ * @return mixed
33
+ */
34
+ public function get_opt( $key, $option_name = 'general' ) {
35
+ return $this->admin->form->value( $key, NULL, $option_name );
36
+ }
37
+
38
+ /**
39
+ * wp callback
40
+ */
41
+ public function call_wp() {
42
+ if ( ! is_admin() && ! is_feed() ) {
43
+ // Include phpQuery
44
+ require_once( 'phpQuery/phpQuery.php' );
45
+
46
+ // add wp_head for setting js vars and css style
47
+ add_action( 'wp_head', array( $this, 'call_wp_head' ) );
48
+
49
+ // add stylesheet
50
+ wp_enqueue_style( 'wp-external-links', plugins_url( 'css/external-links.css', WP_EXTERNAL_LINKS_FILE ), FALSE, WP_EXTERNAL_LINKS_VERSION );
51
+
52
+ // set js file
53
+ if ( $this->get_opt( 'use_js' ) )
54
+ wp_enqueue_script( 'wp-external-links', plugins_url( 'js/external-links.js', WP_EXTERNAL_LINKS_FILE ), array( 'jquery' ), WP_EXTERNAL_LINKS_VERSION );
55
+
56
+ // filters
57
+ if ( $this->get_opt( 'filter_page' ) ) {
58
+ // filter body
59
+ ob_start( array( $this, 'call_filter_content' ) );
60
+
61
+ } else {
62
+ // set filter priority
63
+ $priority = 1000000000;
64
+
65
+ // content
66
+ if ( $this->get_opt( 'filter_posts' ) ) {
67
+ add_filter( 'the_title', array( $this, 'call_filter_content' ), $priority );
68
+ add_filter( 'the_content', array( $this, 'call_filter_content' ), $priority );
69
+
70
+ add_filter( 'get_the_excerpt', array( $this, 'call_filter_content' ), $priority );
71
+ // redundant:
72
+ //add_filter( 'the_excerpt', array( $this, 'call_filter_content' ), $priority );
73
+ }
74
+
75
+ // comments
76
+ if ( $this->get_opt( 'filter_comments' ) ) {
77
+ add_filter( 'get_comment_text', array( $this, 'call_filter_content' ), $priority );
78
+ // redundant:
79
+ //add_filter( 'comment_text', array( $this, 'call_filter_content' ), $priority );
80
+
81
+ add_filter( 'comment_excerpt', array( $this, 'call_filter_content' ), $priority );
82
+ // redundant:
83
+ //add_filter( 'get_comment_excerpt', array( $this, 'call_filter_content' ), $priority );
84
+
85
+ add_filter( 'comment_url', array( $this, 'call_filter_content' ), $priority );
86
+ add_filter( 'get_comment_author_url', array( $this, 'call_filter_content' ), $priority );
87
+ add_filter( 'get_comment_author_link', array( $this, 'call_filter_content' ), $priority );
88
+ add_filter( 'get_comment_author_url_link', array( $this, 'call_filter_content' ), $priority );
89
+ }
90
+
91
+ // widgets
92
+ if ( $this->get_opt( 'filter_widgets' ) ) {
93
+ if ( $this->admin->check_widget_content_filter() ) {
94
+ // only if Widget Logic plugin is installed and 'widget_content' option is activated
95
+ add_filter( 'widget_content', array( $this, 'call_filter_content' ), $priority );
96
+ } else {
97
+ // filter text widgets
98
+ add_filter( 'widget_title', array( $this, 'call_filter_content' ), $priority );
99
+ add_filter( 'widget_text', array( $this, 'call_filter_content' ), $priority );
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ /**
107
+ * wp_head callback
108
+ */
109
+ public function call_wp_head() {
110
+ if ( $this->get_opt( 'use_js' ) AND $this->get_opt( 'target' ) != '_none' ):
111
+ // set exclude class
112
+ $excludeClass = ( $this->get_opt( 'no_icon_same_window', 'style' ) AND $this->get_opt( 'no_icon_class', 'style' ) )
113
+ ? $this->get_opt( 'no_icon_class', 'style' )
114
+ : '';
115
+ ?>
116
+ <script type="text/javascript">/* <![CDATA[ */
117
+ /* WP External Links Plugin */
118
+ var wpExtLinks = { baseUrl: '<?php echo get_bloginfo( 'url' ) ?>',target: '<?php echo $this->get_opt( 'target' ) ?>',excludeClass: '<?php echo $excludeClass ?>' };
119
+ /* ]]> */</script>
120
+ <?php
121
+ endif;
122
+ }
123
+
124
+ /**
125
+ * Filter content
126
+ * @param string $content
127
+ * @return string
128
+ */
129
+ public function call_filter_content( $content ) {
130
+ //phpQuery::$debug = true;
131
+ $doc = phpQuery::newDocument( $content );
132
+
133
+ // remove style when no icon classes are found
134
+ if ( strpos( $content, 'ext-icon-' ) === FALSE ) {
135
+ // remove icon css
136
+ $css = $doc->find( 'link#wp-external-links-css' )->eq(0);
137
+ $css->remove();
138
+ }
139
+
140
+ $excl_sel = $this->get_opt( 'filter_excl_sel' );
141
+
142
+ // set excludes
143
+ if ( ! empty( $excl_sel ) ) {
144
+ $excludes = $doc->find( $excl_sel );
145
+ $excludes->filter( 'a' )->attr( 'excluded', true );
146
+ $excludes->find( 'a' )->attr( 'excluded', true );
147
+ }
148
+
149
+ // get <a>-tags
150
+ $links = $doc->find( 'a' );
151
+
152
+ // set links
153
+ $count = count( $links );
154
+
155
+ for( $x = 0; $x < $count; $x++ ) {
156
+ $a = $links->eq( $x );
157
+
158
+ if ( ! $a->attr( 'excluded' ) )
159
+ $this->set_link( $links->eq( $x ) );
160
+ }
161
+
162
+ // remove excluded
163
+ if ( ! empty( $excl_sel ) ) {
164
+ $excludes = $doc->find( $excl_sel );
165
+ $excludes->filter( 'a' )->removeAttr( 'excluded' );
166
+ $excludes->find( 'a' )->removeAttr( 'excluded' );
167
+ }
168
+
169
+ return $doc;
170
+ }
171
+
172
+ /**
173
+ * Set link...
174
+ * @param Node $a
175
+ * @return Node
176
+ */
177
+ public function set_link( $a ) {
178
+ $href = strtolower( $a->attr( 'href' ) . '' );
179
+ $rel = strtolower( $a->attr( 'rel' ) . '' );
180
+
181
+ // check if it is an external link and not excluded
182
+ if ( ! $this->is_external( $href, $rel ) )
183
+ return $a;
184
+
185
+ // add "external" to rel-attribute
186
+ if ( $this->get_opt( 'external' ) ){
187
+ $this->add_attr_value( $a, 'rel', 'external' );
188
+ }
189
+
190
+ // add "nofollow" to rel-attribute, when doesn't have "follow"
191
+ if ( $this->get_opt( 'nofollow' ) AND strpos( $rel, 'follow' ) === FALSE ){
192
+ $this->add_attr_value( $a, 'rel', 'nofollow' );
193
+ }
194
+
195
+ // set title
196
+ $title = str_replace( '%title%', $a->attr( 'title' ), $this->get_opt( 'title' ) );
197
+ $a->attr( 'title', $title );
198
+
199
+ // add icon class, unless no-icon class isset or another icon class ('ext-icon-...') is found
200
+ if ( $this->get_opt( 'icon', 'style' ) > 0 AND ( ! $this->get_opt( 'no_icon_class', 'style' ) OR strpos( $a->attr( 'class' ), $this->get_opt( 'no_icon_class', 'style' ) ) === FALSE ) AND strpos( $a->attr( 'class' ), 'ext-icon-' ) === FALSE ){
201
+ $icon_class = 'ext-icon-'. $this->get_opt( 'icon', 'style' );
202
+ $a->addClass( $icon_class );
203
+ }
204
+
205
+ // add user-defined class
206
+ if ( $this->get_opt( 'class_name', 'style' ) ){
207
+ $a->addClass( $this->get_opt( 'class_name', 'style' ) );
208
+ }
209
+
210
+ // set target
211
+ if ( $this->get_opt( 'target' ) != '_none' AND ! $this->get_opt( 'use_js' ) AND ( ! $this->get_opt( 'no_icon_same_window', 'style' ) OR ! $this->get_opt( 'no_icon_class', 'style' ) OR strpos( $a->attr( 'class' ), $this->get_opt( 'no_icon_class', 'style' ) ) === FALSE ) )
212
+ $a->attr( 'target', $this->get_opt( 'target' ) );
213
+
214
+ return $a;
215
+ }
216
+
217
+ /**
218
+ * Add value to attribute
219
+ * @param Node $node
220
+ * @param string $attr
221
+ * @param string $value
222
+ * @return New value
223
+ */
224
+ private function add_attr_value( $node, $attr, $value ) {
225
+ $old_value = $node->attr( $attr );
226
+
227
+ if ( empty( $old_value ) )
228
+ $old_value = '';
229
+
230
+ $split = split( ' ', strtolower( $old_value ) );
231
+
232
+ if ( in_array( $value, $split ) ) {
233
+ $value = $old_value;
234
+ } else {
235
+ $value = ( empty( $old_value ) )
236
+ ? $value
237
+ : $old_value .' '. $value;
238
+ }
239
+
240
+ $node->attr( $attr, $value );
241
+
242
+ return $value;
243
+ }
244
+
245
+ /**
246
+ * Check if link is external
247
+ * @param string $href
248
+ * @param string $rel
249
+ * @return boolean
250
+ */
251
+ private function is_external( $href, $rel ) {
252
+ return ( isset( $href ) AND ( strpos( $rel, 'external' ) !== FALSE
253
+ OR ( strpos( $href, strtolower( get_bloginfo( 'url' ) ) ) === FALSE )
254
+ AND ( substr( $href, 0, 7 ) == 'http://'
255
+ OR substr( $href, 0, 8 ) == 'https://'
256
+ OR substr( $href, 0, 6 ) == 'ftp://' ) ) );
257
+ }
258
+
259
+ } // End WP_External_Links Class
260
+
261
+ endif;
includes/phpQuery/phpQuery.php ADDED
@@ -0,0 +1,1342 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * phpQuery is a server-side, chainable, CSS3 selector driven
4
+ * Document Object Model (DOM) API based on jQuery JavaScript Library.
5
+ *
6
+ * @version 0.9.5
7
+ * @link http://code.google.com/p/phpquery/
8
+ * @link http://phpquery-library.blogspot.com/
9
+ * @link http://jquery.com/
10
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
11
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
12
+ * @package phpQuery
13
+ */
14
+
15
+ // class names for instanceof
16
+ // TODO move them as class constants into phpQuery
17
+ define('DOMDOCUMENT', 'DOMDocument');
18
+ define('DOMELEMENT', 'DOMElement');
19
+ define('DOMNODELIST', 'DOMNodeList');
20
+ define('DOMNODE', 'DOMNode');
21
+ require_once(dirname(__FILE__).'/phpQuery/DOMEvent.php');
22
+ require_once(dirname(__FILE__).'/phpQuery/DOMDocumentWrapper.php');
23
+ require_once(dirname(__FILE__).'/phpQuery/phpQueryEvents.php');
24
+ require_once(dirname(__FILE__).'/phpQuery/Callback.php');
25
+ require_once(dirname(__FILE__).'/phpQuery/phpQueryObject.php');
26
+ require_once(dirname(__FILE__).'/phpQuery/compat/mbstring.php');
27
+ /**
28
+ * Static namespace for phpQuery functions.
29
+ *
30
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
31
+ * @package phpQuery
32
+ */
33
+ abstract class phpQuery {
34
+ /**
35
+ * XXX: Workaround for mbstring problems
36
+ *
37
+ * @var bool
38
+ */
39
+ public static $mbstringSupport = true;
40
+ public static $debug = false;
41
+ public static $documents = array();
42
+ public static $defaultDocumentID = null;
43
+ // public static $defaultDoctype = 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"';
44
+ /**
45
+ * Applies only to HTML.
46
+ *
47
+ * @var unknown_type
48
+ */
49
+ public static $defaultDoctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
50
+ "http://www.w3.org/TR/html4/loose.dtd">';
51
+ public static $defaultCharset = 'UTF-8';
52
+ /**
53
+ * Static namespace for plugins.
54
+ *
55
+ * @var object
56
+ */
57
+ public static $plugins = array();
58
+ /**
59
+ * List of loaded plugins.
60
+ *
61
+ * @var unknown_type
62
+ */
63
+ public static $pluginsLoaded = array();
64
+ public static $pluginsMethods = array();
65
+ public static $pluginsStaticMethods = array();
66
+ public static $extendMethods = array();
67
+ /**
68
+ * @TODO implement
69
+ */
70
+ public static $extendStaticMethods = array();
71
+ /**
72
+ * Hosts allowed for AJAX connections.
73
+ * Dot '.' means $_SERVER['HTTP_HOST'] (if any).
74
+ *
75
+ * @var array
76
+ */
77
+ public static $ajaxAllowedHosts = array(
78
+ '.'
79
+ );
80
+ /**
81
+ * AJAX settings.
82
+ *
83
+ * @var array
84
+ * XXX should it be static or not ?
85
+ */
86
+ public static $ajaxSettings = array(
87
+ 'url' => '',//TODO
88
+ 'global' => true,
89
+ 'type' => "GET",
90
+ 'timeout' => null,
91
+ 'contentType' => "application/x-www-form-urlencoded",
92
+ 'processData' => true,
93
+ // 'async' => true,
94
+ 'data' => null,
95
+ 'username' => null,
96
+ 'password' => null,
97
+ 'accepts' => array(
98
+ 'xml' => "application/xml, text/xml",
99
+ 'html' => "text/html",
100
+ 'script' => "text/javascript, application/javascript",
101
+ 'json' => "application/json, text/javascript",
102
+ 'text' => "text/plain",
103
+ '_default' => "*/*"
104
+ )
105
+ );
106
+ public static $lastModified = null;
107
+ public static $active = 0;
108
+ public static $dumpCount = 0;
109
+ /**
110
+ * Multi-purpose function.
111
+ * Use pq() as shortcut.
112
+ *
113
+ * In below examples, $pq is any result of pq(); function.
114
+ *
115
+ * 1. Import markup into existing document (without any attaching):
116
+ * - Import into selected document:
117
+ * pq('<div/>') // DOESNT accept text nodes at beginning of input string !
118
+ * - Import into document with ID from $pq->getDocumentID():
119
+ * pq('<div/>', $pq->getDocumentID())
120
+ * - Import into same document as DOMNode belongs to:
121
+ * pq('<div/>', DOMNode)
122
+ * - Import into document from phpQuery object:
123
+ * pq('<div/>', $pq)
124
+ *
125
+ * 2. Run query:
126
+ * - Run query on last selected document:
127
+ * pq('div.myClass')
128
+ * - Run query on document with ID from $pq->getDocumentID():
129
+ * pq('div.myClass', $pq->getDocumentID())
130
+ * - Run query on same document as DOMNode belongs to and use node(s)as root for query:
131
+ * pq('div.myClass', DOMNode)
132
+ * - Run query on document from phpQuery object
133
+ * and use object's stack as root node(s) for query:
134
+ * pq('div.myClass', $pq)
135
+ *
136
+ * @param string|DOMNode|DOMNodeList|array $arg1 HTML markup, CSS Selector, DOMNode or array of DOMNodes
137
+ * @param string|phpQueryObject|DOMNode $context DOM ID from $pq->getDocumentID(), phpQuery object (determines also query root) or DOMNode (determines also query root)
138
+ *
139
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery|QueryTemplatesPhpQuery|false
140
+ * phpQuery object or false in case of error.
141
+ */
142
+ public static function pq($arg1, $context = null) {
143
+ if ($arg1 instanceof DOMNODE && ! isset($context)) {
144
+ foreach(phpQuery::$documents as $documentWrapper) {
145
+ $compare = $arg1 instanceof DOMDocument
146
+ ? $arg1 : $arg1->ownerDocument;
147
+ if ($documentWrapper->document->isSameNode($compare))
148
+ $context = $documentWrapper->id;
149
+ }
150
+ }
151
+ if (! $context) {
152
+ $domId = self::$defaultDocumentID;
153
+ if (! $domId)
154
+ throw new Exception("Can't use last created DOM, because there isn't any. Use phpQuery::newDocument() first.");
155
+ // } else if (is_object($context) && ($context instanceof PHPQUERY || is_subclass_of($context, 'phpQueryObject')))
156
+ } else if (is_object($context) && $context instanceof phpQueryObject)
157
+ $domId = $context->getDocumentID();
158
+ else if ($context instanceof DOMDOCUMENT) {
159
+ $domId = self::getDocumentID($context);
160
+ if (! $domId) {
161
+ //throw new Exception('Orphaned DOMDocument');
162
+ $domId = self::newDocument($context)->getDocumentID();
163
+ }
164
+ } else if ($context instanceof DOMNODE) {
165
+ $domId = self::getDocumentID($context);
166
+ if (! $domId) {
167
+ throw new Exception('Orphaned DOMNode');
168
+ // $domId = self::newDocument($context->ownerDocument);
169
+ }
170
+ } else
171
+ $domId = $context;
172
+ if ($arg1 instanceof phpQueryObject) {
173
+ // if (is_object($arg1) && (get_class($arg1) == 'phpQueryObject' || $arg1 instanceof PHPQUERY || is_subclass_of($arg1, 'phpQueryObject'))) {
174
+ /**
175
+ * Return $arg1 or import $arg1 stack if document differs:
176
+ * pq(pq('<div/>'))
177
+ */
178
+ if ($arg1->getDocumentID() == $domId)
179
+ return $arg1;
180
+ $class = get_class($arg1);
181
+ // support inheritance by passing old object to overloaded constructor
182
+ $phpQuery = $class != 'phpQuery'
183
+ ? new $class($arg1, $domId)
184
+ : new phpQueryObject($domId);
185
+ $phpQuery->elements = array();
186
+ foreach($arg1->elements as $node)
187
+ $phpQuery->elements[] = $phpQuery->document->importNode($node, true);
188
+ return $phpQuery;
189
+ } else if ($arg1 instanceof DOMNODE || (is_array($arg1) && isset($arg1[0]) && $arg1[0] instanceof DOMNODE)) {
190
+ /*
191
+ * Wrap DOM nodes with phpQuery object, import into document when needed:
192
+ * pq(array($domNode1, $domNode2))
193
+ */
194
+ $phpQuery = new phpQueryObject($domId);
195
+ if (!($arg1 instanceof DOMNODELIST) && ! is_array($arg1))
196
+ $arg1 = array($arg1);
197
+ $phpQuery->elements = array();
198
+ foreach($arg1 as $node) {
199
+ $sameDocument = $node->ownerDocument instanceof DOMDOCUMENT
200
+ && ! $node->ownerDocument->isSameNode($phpQuery->document);
201
+ $phpQuery->elements[] = $sameDocument
202
+ ? $phpQuery->document->importNode($node, true)
203
+ : $node;
204
+ }
205
+ return $phpQuery;
206
+ } else if (self::isMarkup($arg1)) {
207
+ /**
208
+ * Import HTML:
209
+ * pq('<div/>')
210
+ */
211
+ $phpQuery = new phpQueryObject($domId);
212
+ return $phpQuery->newInstance(
213
+ $phpQuery->documentWrapper->import($arg1)
214
+ );
215
+ } else {
216
+ /**
217
+ * Run CSS query:
218
+ * pq('div.myClass')
219
+ */
220
+ $phpQuery = new phpQueryObject($domId);
221
+ // if ($context && ($context instanceof PHPQUERY || is_subclass_of($context, 'phpQueryObject')))
222
+ if ($context && $context instanceof phpQueryObject)
223
+ $phpQuery->elements = $context->elements;
224
+ else if ($context && $context instanceof DOMNODELIST) {
225
+ $phpQuery->elements = array();
226
+ foreach($context as $node)
227
+ $phpQuery->elements[] = $node;
228
+ } else if ($context && $context instanceof DOMNODE)
229
+ $phpQuery->elements = array($context);
230
+ return $phpQuery->find($arg1);
231
+ }
232
+ }
233
+ /**
234
+ * Sets default document to $id. Document has to be loaded prior
235
+ * to using this method.
236
+ * $id can be retrived via getDocumentID() or getDocumentIDRef().
237
+ *
238
+ * @param unknown_type $id
239
+ */
240
+ public static function selectDocument($id) {
241
+ $id = self::getDocumentID($id);
242
+ self::debug("Selecting document '$id' as default one");
243
+ self::$defaultDocumentID = self::getDocumentID($id);
244
+ }
245
+ /**
246
+ * Returns document with id $id or last used as phpQueryObject.
247
+ * $id can be retrived via getDocumentID() or getDocumentIDRef().
248
+ * Chainable.
249
+ *
250
+ * @see phpQuery::selectDocument()
251
+ * @param unknown_type $id
252
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
253
+ */
254
+ public static function getDocument($id = null) {
255
+ if ($id)
256
+ phpQuery::selectDocument($id);
257
+ else
258
+ $id = phpQuery::$defaultDocumentID;
259
+ return new phpQueryObject($id);
260
+ }
261
+ /**
262
+ * Creates new document from markup.
263
+ * Chainable.
264
+ *
265
+ * @param unknown_type $markup
266
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
267
+ */
268
+ public static function newDocument($markup = null, $contentType = null) {
269
+ if (! $markup)
270
+ $markup = '';
271
+ $documentID = phpQuery::createDocumentWrapper($markup, $contentType);
272
+ return new phpQueryObject($documentID);
273
+ }
274
+ /**
275
+ * Creates new document from markup.
276
+ * Chainable.
277
+ *
278
+ * @param unknown_type $markup
279
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
280
+ */
281
+ public static function newDocumentHTML($markup = null, $charset = null) {
282
+ $contentType = $charset
283
+ ? ";charset=$charset"
284
+ : '';
285
+ return self::newDocument($markup, "text/html{$contentType}");
286
+ }
287
+ /**
288
+ * Creates new document from markup.
289
+ * Chainable.
290
+ *
291
+ * @param unknown_type $markup
292
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
293
+ */
294
+ public static function newDocumentXML($markup = null, $charset = null) {
295
+ $contentType = $charset
296
+ ? ";charset=$charset"
297
+ : '';
298
+ return self::newDocument($markup, "text/xml{$contentType}");
299
+ }
300
+ /**
301
+ * Creates new document from markup.
302
+ * Chainable.
303
+ *
304
+ * @param unknown_type $markup
305
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
306
+ */
307
+ public static function newDocumentXHTML($markup = null, $charset = null) {
308
+ $contentType = $charset
309
+ ? ";charset=$charset"
310
+ : '';
311
+ return self::newDocument($markup, "application/xhtml+xml{$contentType}");
312
+ }
313
+ /**
314
+ * Creates new document from markup.
315
+ * Chainable.
316
+ *
317
+ * @param unknown_type $markup
318
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
319
+ */
320
+ public static function newDocumentPHP($markup = null, $contentType = "text/html") {
321
+ // TODO pass charset to phpToMarkup if possible (use DOMDocumentWrapper function)
322
+ $markup = phpQuery::phpToMarkup($markup, self::$defaultCharset);
323
+ return self::newDocument($markup, $contentType);
324
+ }
325
+ public static function phpToMarkup($php, $charset = 'utf-8') {
326
+ $regexes = array(
327
+ '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(\')([^\']*)<'.'?php?(.*?)(?:\\?>)([^\']*)\'@s',
328
+ '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(")([^"]*)<'.'?php?(.*?)(?:\\?>)([^"]*)"@s',
329
+ );
330
+ foreach($regexes as $regex)
331
+ while (preg_match($regex, $php, $matches)) {
332
+ $php = preg_replace_callback(
333
+ $regex,
334
+ // create_function('$m, $charset = "'.$charset.'"',
335
+ // 'return $m[1].$m[2]
336
+ // .htmlspecialchars("<"."?php".$m[4]."?".">", ENT_QUOTES|ENT_NOQUOTES, $charset)
337
+ // .$m[5].$m[2];'
338
+ // ),
339
+ array('phpQuery', '_phpToMarkupCallback'),
340
+ $php
341
+ );
342
+ }
343
+ $regex = '@(^|>[^<]*)+?(<\?php(.*?)(\?>))@s';
344
+ //preg_match_all($regex, $php, $matches);
345
+ //var_dump($matches);
346
+ $php = preg_replace($regex, '\\1<php><!-- \\3 --></php>', $php);
347
+ return $php;
348
+ }
349
+ public static function _phpToMarkupCallback($php, $charset = 'utf-8') {
350
+ return $m[1].$m[2]
351
+ .htmlspecialchars("<"."?php".$m[4]."?".">", ENT_QUOTES|ENT_NOQUOTES, $charset)
352
+ .$m[5].$m[2];
353
+ }
354
+ public static function _markupToPHPCallback($m) {
355
+ return "<"."?php ".htmlspecialchars_decode($m[1])." ?".">";
356
+ }
357
+ /**
358
+ * Converts document markup containing PHP code generated by phpQuery::php()
359
+ * into valid (executable) PHP code syntax.
360
+ *
361
+ * @param string|phpQueryObject $content
362
+ * @return string PHP code.
363
+ */
364
+ public static function markupToPHP($content) {
365
+ if ($content instanceof phpQueryObject)
366
+ $content = $content->markupOuter();
367
+ /* <php>...</php> to <?php...? > */
368
+ $content = preg_replace_callback(
369
+ '@<php>\s*<!--(.*?)-->\s*</php>@s',
370
+ // create_function('$m',
371
+ // 'return "<'.'?php ".htmlspecialchars_decode($m[1])." ?'.'>";'
372
+ // ),
373
+ array('phpQuery', '_markupToPHPCallback'),
374
+ $content
375
+ );
376
+ /* <node attr='< ?php ? >'> extra space added to save highlighters */
377
+ $regexes = array(
378
+ '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(\')([^\']*)(?:&lt;|%3C)\\?(?:php)?(.*?)(?:\\?(?:&gt;|%3E))([^\']*)\'@s',
379
+ '@(<(?!\\?)(?:[^>]|\\?>)+\\w+\\s*=\\s*)(")([^"]*)(?:&lt;|%3C)\\?(?:php)?(.*?)(?:\\?(?:&gt;|%3E))([^"]*)"@s',
380
+ );
381
+ foreach($regexes as $regex)
382
+ while (preg_match($regex, $content))
383
+ $content = preg_replace_callback(
384
+ $regex,
385
+ create_function('$m',
386
+ 'return $m[1].$m[2].$m[3]."<?php "
387
+ .str_replace(
388
+ array("%20", "%3E", "%09", "&#10;", "&#9;", "%7B", "%24", "%7D", "%22", "%5B", "%5D"),
389
+ array(" ", ">", " ", "\n", " ", "{", "$", "}", \'"\', "[", "]"),
390
+ htmlspecialchars_decode($m[4])
391
+ )
392
+ ." ?>".$m[5].$m[2];'
393
+ ),
394
+ $content
395
+ );
396
+ return $content;
397
+ }
398
+ /**
399
+ * Creates new document from file $file.
400
+ * Chainable.
401
+ *
402
+ * @param string $file URLs allowed. See File wrapper page at php.net for more supported sources.
403
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
404
+ */
405
+ public static function newDocumentFile($file, $contentType = null) {
406
+ $documentID = self::createDocumentWrapper(
407
+ file_get_contents($file), $contentType
408
+ );
409
+ return new phpQueryObject($documentID);
410
+ }
411
+ /**
412
+ * Creates new document from markup.
413
+ * Chainable.
414
+ *
415
+ * @param unknown_type $markup
416
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
417
+ */
418
+ public static function newDocumentFileHTML($file, $charset = null) {
419
+ $contentType = $charset
420
+ ? ";charset=$charset"
421
+ : '';
422
+ return self::newDocumentFile($file, "text/html{$contentType}");
423
+ }
424
+ /**
425
+ * Creates new document from markup.
426
+ * Chainable.
427
+ *
428
+ * @param unknown_type $markup
429
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
430
+ */
431
+ public static function newDocumentFileXML($file, $charset = null) {
432
+ $contentType = $charset
433
+ ? ";charset=$charset"
434
+ : '';
435
+ return self::newDocumentFile($file, "text/xml{$contentType}");
436
+ }
437
+ /**
438
+ * Creates new document from markup.
439
+ * Chainable.
440
+ *
441
+ * @param unknown_type $markup
442
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
443
+ */
444
+ public static function newDocumentFileXHTML($file, $charset = null) {
445
+ $contentType = $charset
446
+ ? ";charset=$charset"
447
+ : '';
448
+ return self::newDocumentFile($file, "application/xhtml+xml{$contentType}");
449
+ }
450
+ /**
451
+ * Creates new document from markup.
452
+ * Chainable.
453
+ *
454
+ * @param unknown_type $markup
455
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
456
+ */
457
+ public static function newDocumentFilePHP($file, $contentType = null) {
458
+ return self::newDocumentPHP(file_get_contents($file), $contentType);
459
+ }
460
+ /**
461
+ * Reuses existing DOMDocument object.
462
+ * Chainable.
463
+ *
464
+ * @param $document DOMDocument
465
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
466
+ * @TODO support DOMDocument
467
+ */
468
+ public static function loadDocument($document) {
469
+ // TODO
470
+ die('TODO loadDocument');
471
+ }
472
+ /**
473
+ * Enter description here...
474
+ *
475
+ * @param unknown_type $html
476
+ * @param unknown_type $domId
477
+ * @return unknown New DOM ID
478
+ * @todo support PHP tags in input
479
+ * @todo support passing DOMDocument object from self::loadDocument
480
+ */
481
+ protected static function createDocumentWrapper($html, $contentType = null, $documentID = null) {
482
+ if (function_exists('domxml_open_mem'))
483
+ throw new Exception("Old PHP4 DOM XML extension detected. phpQuery won't work until this extension is enabled.");
484
+ // $id = $documentID
485
+ // ? $documentID
486
+ // : md5(microtime());
487
+ $document = null;
488
+ if ($html instanceof DOMDOCUMENT) {
489
+ if (self::getDocumentID($html)) {
490
+ // document already exists in phpQuery::$documents, make a copy
491
+ $document = clone $html;
492
+ } else {
493
+ // new document, add it to phpQuery::$documents
494
+ $wrapper = new DOMDocumentWrapper($html, $contentType, $documentID);
495
+ }
496
+ } else {
497
+ $wrapper = new DOMDocumentWrapper($html, $contentType, $documentID);
498
+ }
499
+ // $wrapper->id = $id;
500
+ // bind document
501
+ phpQuery::$documents[$wrapper->id] = $wrapper;
502
+ // remember last loaded document
503
+ phpQuery::selectDocument($wrapper->id);
504
+ return $wrapper->id;
505
+ }
506
+ /**
507
+ * Extend class namespace.
508
+ *
509
+ * @param string|array $target
510
+ * @param array $source
511
+ * @TODO support string $source
512
+ * @return unknown_type
513
+ */
514
+ public static function extend($target, $source) {
515
+ switch($target) {
516
+ case 'phpQueryObject':
517
+ $targetRef = &self::$extendMethods;
518
+ $targetRef2 = &self::$pluginsMethods;
519
+ break;
520
+ case 'phpQuery':
521
+ $targetRef = &self::$extendStaticMethods;
522
+ $targetRef2 = &self::$pluginsStaticMethods;
523
+ break;
524
+ default:
525
+ throw new Exception("Unsupported \$target type");
526
+ }
527
+ if (is_string($source))
528
+ $source = array($source => $source);
529
+ foreach($source as $method => $callback) {
530
+ if (isset($targetRef[$method])) {
531
+ // throw new Exception
532
+ self::debug("Duplicate method '{$method}', can\'t extend '{$target}'");
533
+ continue;
534
+ }
535
+ if (isset($targetRef2[$method])) {
536
+ // throw new Exception
537
+ self::debug("Duplicate method '{$method}' from plugin '{$targetRef2[$method]}',"
538
+ ." can\'t extend '{$target}'");
539
+ continue;
540
+ }
541
+ $targetRef[$method] = $callback;
542
+ }
543
+ return true;
544
+ }
545
+ /**
546
+ * Extend phpQuery with $class from $file.
547
+ *
548
+ * @param string $class Extending class name. Real class name can be prepended phpQuery_.
549
+ * @param string $file Filename to include. Defaults to "{$class}.php".
550
+ */
551
+ public static function plugin($class, $file = null) {
552
+ // TODO $class checked agains phpQuery_$class
553
+ // if (strpos($class, 'phpQuery') === 0)
554
+ // $class = substr($class, 8);
555
+ if (in_array($class, self::$pluginsLoaded))
556
+ return true;
557
+ if (! $file)
558
+ $file = $class.'.php';
559
+ $objectClassExists = class_exists('phpQueryObjectPlugin_'.$class);
560
+ $staticClassExists = class_exists('phpQueryPlugin_'.$class);
561
+ if (! $objectClassExists && ! $staticClassExists)
562
+ require_once($file);
563
+ self::$pluginsLoaded[] = $class;
564
+ // static methods
565
+ if (class_exists('phpQueryPlugin_'.$class)) {
566
+ $realClass = 'phpQueryPlugin_'.$class;
567
+ $vars = get_class_vars($realClass);
568
+ $loop = isset($vars['phpQueryMethods'])
569
+ && ! is_null($vars['phpQueryMethods'])
570
+ ? $vars['phpQueryMethods']
571
+ : get_class_methods($realClass);
572
+ foreach($loop as $method) {
573
+ if ($method == '__initialize')
574
+ continue;
575
+ if (! is_callable(array($realClass, $method)))
576
+ continue;
577
+ if (isset(self::$pluginsStaticMethods[$method])) {
578
+ throw new Exception("Duplicate method '{$method}' from plugin '{$c}' conflicts with same method from plugin '".self::$pluginsStaticMethods[$method]."'");
579
+ return;
580
+ }
581
+ self::$pluginsStaticMethods[$method] = $class;
582
+ }
583
+ if (method_exists($realClass, '__initialize'))
584
+ call_user_func_array(array($realClass, '__initialize'), array());
585
+ }
586
+ // object methods
587
+ if (class_exists('phpQueryObjectPlugin_'.$class)) {
588
+ $realClass = 'phpQueryObjectPlugin_'.$class;
589
+ $vars = get_class_vars($realClass);
590
+ $loop = isset($vars['phpQueryMethods'])
591
+ && ! is_null($vars['phpQueryMethods'])
592
+ ? $vars['phpQueryMethods']
593
+ : get_class_methods($realClass);
594
+ foreach($loop as $method) {
595
+ if (! is_callable(array($realClass, $method)))
596
+ continue;
597
+ if (isset(self::$pluginsMethods[$method])) {
598
+ throw new Exception("Duplicate method '{$method}' from plugin '{$c}' conflicts with same method from plugin '".self::$pluginsMethods[$method]."'");
599
+ continue;
600
+ }
601
+ self::$pluginsMethods[$method] = $class;
602
+ }
603
+ }
604
+ return true;
605
+ }
606
+ /**
607
+ * Unloades all or specified document from memory.
608
+ *
609
+ * @param mixed $documentID @see phpQuery::getDocumentID() for supported types.
610
+ */
611
+ public static function unloadDocuments($id = null) {
612
+ if (isset($id)) {
613
+ if ($id = self::getDocumentID($id))
614
+ unset(phpQuery::$documents[$id]);
615
+ } else {
616
+ foreach(phpQuery::$documents as $k => $v) {
617
+ unset(phpQuery::$documents[$k]);
618
+ }
619
+ }
620
+ }
621
+ /**
622
+ * Parses phpQuery object or HTML result against PHP tags and makes them active.
623
+ *
624
+ * @param phpQuery|string $content
625
+ * @deprecated
626
+ * @return string
627
+ */
628
+ public static function unsafePHPTags($content) {
629
+ return self::markupToPHP($content);
630
+ }
631
+ public static function DOMNodeListToArray($DOMNodeList) {
632
+ $array = array();
633
+ if (! $DOMNodeList)
634
+ return $array;
635
+ foreach($DOMNodeList as $node)
636
+ $array[] = $node;
637
+ return $array;
638
+ }
639
+ /**
640
+ * Checks if $input is HTML string, which has to start with '<'.
641
+ *
642
+ * @deprecated
643
+ * @param String $input
644
+ * @return Bool
645
+ * @todo still used ?
646
+ */
647
+ public static function isMarkup($input) {
648
+ return ! is_array($input) && substr(trim($input), 0, 1) == '<';
649
+ }
650
+ public static function debug($text) {
651
+ if (self::$debug)
652
+ print var_dump($text);
653
+ }
654
+ /**
655
+ * Make an AJAX request.
656
+ *
657
+ * @param array See $options http://docs.jquery.com/Ajax/jQuery.ajax#toptions
658
+ * Additional options are:
659
+ * 'document' - document for global events, @see phpQuery::getDocumentID()
660
+ * 'referer' - implemented
661
+ * 'requested_with' - TODO; not implemented (X-Requested-With)
662
+ * @return Zend_Http_Client
663
+ * @link http://docs.jquery.com/Ajax/jQuery.ajax
664
+ *
665
+ * @TODO $options['cache']
666
+ * @TODO $options['processData']
667
+ * @TODO $options['xhr']
668
+ * @TODO $options['data'] as string
669
+ * @TODO XHR interface
670
+ */
671
+ public static function ajax($options = array(), $xhr = null) {
672
+ $options = array_merge(
673
+ self::$ajaxSettings, $options
674
+ );
675
+ $documentID = isset($options['document'])
676
+ ? self::getDocumentID($options['document'])
677
+ : null;
678
+ if ($xhr) {
679
+ // reuse existing XHR object, but clean it up
680
+ $client = $xhr;
681
+ // $client->setParameterPost(null);
682
+ // $client->setParameterGet(null);
683
+ $client->setAuth(false);
684
+ $client->setHeaders("If-Modified-Since", null);
685
+ $client->setHeaders("Referer", null);
686
+ $client->resetParameters();
687
+ } else {
688
+ // create new XHR object
689
+ require_once('Zend/Http/Client.php');
690
+ $client = new Zend_Http_Client();
691
+ $client->setCookieJar();
692
+ }
693
+ if (isset($options['timeout']))
694
+ $client->setConfig(array(
695
+ 'timeout' => $options['timeout'],
696
+ ));
697
+ // 'maxredirects' => 0,
698
+ foreach(self::$ajaxAllowedHosts as $k => $host)
699
+ if ($host == '.' && isset($_SERVER['HTTP_HOST']))
700
+ self::$ajaxAllowedHosts[$k] = $_SERVER['HTTP_HOST'];
701
+ $host = parse_url($options['url'], PHP_URL_HOST);
702
+ if (! in_array($host, self::$ajaxAllowedHosts)) {
703
+ throw new Exception("Request not permitted, host '$host' not present in "
704
+ ."phpQuery::\$ajaxAllowedHosts");
705
+ }
706
+ // JSONP
707
+ $jsre = "/=\\?(&|$)/";
708
+ if (isset($options['dataType']) && $options['dataType'] == 'jsonp') {
709
+ $jsonpCallbackParam = $options['jsonp']
710
+ ? $options['jsonp'] : 'callback';
711
+ if (strtolower($options['type']) == 'get') {
712
+ if (! preg_match($jsre, $options['url'])) {
713
+ $sep = strpos($options['url'], '?')
714
+ ? '&' : '?';
715
+ $options['url'] .= "$sep$jsonpCallbackParam=?";
716
+ }
717
+ } else if ($options['data']) {
718
+ $jsonp = false;
719
+ foreach($options['data'] as $n => $v) {
720
+ if ($v == '?')
721
+ $jsonp = true;
722
+ }
723
+ if (! $jsonp) {
724
+ $options['data'][$jsonpCallbackParam] = '?';
725
+ }
726
+ }
727
+ $options['dataType'] = 'json';
728
+ }
729
+ if (isset($options['dataType']) && $options['dataType'] == 'json') {
730
+ $jsonpCallback = 'json_'.md5(microtime());
731
+ $jsonpData = $jsonpUrl = false;
732
+ if ($options['data']) {
733
+ foreach($options['data'] as $n => $v) {
734
+ if ($v == '?')
735
+ $jsonpData = $n;
736
+ }
737
+ }
738
+ if (preg_match($jsre, $options['url']))
739
+ $jsonpUrl = true;
740
+ if ($jsonpData !== false || $jsonpUrl) {
741
+ // remember callback name for httpData()
742
+ $options['_jsonp'] = $jsonpCallback;
743
+ if ($jsonpData !== false)
744
+ $options['data'][$jsonpData] = $jsonpCallback;
745
+ if ($jsonpUrl)
746
+ $options['url'] = preg_replace($jsre, "=$jsonpCallback\\1", $options['url']);
747
+ }
748
+ }
749
+ $client->setUri($options['url']);
750
+ $client->setMethod(strtoupper($options['type']));
751
+ if (isset($options['referer']) && $options['referer'])
752
+ $client->setHeaders('Referer', $options['referer']);
753
+ $client->setHeaders(array(
754
+ // 'content-type' => $options['contentType'],
755
+ 'User-Agent' => 'Mozilla/5.0 (X11; U; Linux x86; en-US; rv:1.9.0.5) Gecko'
756
+ .'/2008122010 Firefox/3.0.5',
757
+ // TODO custom charset
758
+ 'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
759
+ // 'Connection' => 'keep-alive',
760
+ // 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
761
+ 'Accept-Language' => 'en-us,en;q=0.5',
762
+ ));
763
+ if ($options['username'])
764
+ $client->setAuth($options['username'], $options['password']);
765
+ if (isset($options['ifModified']) && $options['ifModified'])
766
+ $client->setHeaders("If-Modified-Since",
767
+ self::$lastModified
768
+ ? self::$lastModified
769
+ : "Thu, 01 Jan 1970 00:00:00 GMT"
770
+ );
771
+ $client->setHeaders("Accept",
772
+ isset($options['dataType'])
773
+ && isset(self::$ajaxSettings['accepts'][ $options['dataType'] ])
774
+ ? self::$ajaxSettings['accepts'][ $options['dataType'] ].", */*"
775
+ : self::$ajaxSettings['accepts']['_default']
776
+ );
777
+ // TODO $options['processData']
778
+ if ($options['data'] instanceof phpQueryObject) {
779
+ $serialized = $options['data']->serializeArray($options['data']);
780
+ $options['data'] = array();
781
+ foreach($serialized as $r)
782
+ $options['data'][ $r['name'] ] = $r['value'];
783
+ }
784
+ if (strtolower($options['type']) == 'get') {
785
+ $client->setParameterGet($options['data']);
786
+ } else if (strtolower($options['type']) == 'post') {
787
+ $client->setEncType($options['contentType']);
788
+ $client->setParameterPost($options['data']);
789
+ }
790
+ if (self::$active == 0 && $options['global'])
791
+ phpQueryEvents::trigger($documentID, 'ajaxStart');
792
+ self::$active++;
793
+ // beforeSend callback
794
+ if (isset($options['beforeSend']) && $options['beforeSend'])
795
+ phpQuery::callbackRun($options['beforeSend'], array($client));
796
+ // ajaxSend event
797
+ if ($options['global'])
798
+ phpQueryEvents::trigger($documentID, 'ajaxSend', array($client, $options));
799
+ if (phpQuery::$debug) {
800
+ self::debug("{$options['type']}: {$options['url']}\n");
801
+ self::debug("Options: <pre>".var_export($options, true)."</pre>\n");
802
+ // if ($client->getCookieJar())
803
+ // self::debug("Cookies: <pre>".var_export($client->getCookieJar()->getMatchingCookies($options['url']), true)."</pre>\n");
804
+ }
805
+ // request
806
+ $response = $client->request();
807
+ if (phpQuery::$debug) {
808
+ self::debug('Status: '.$response->getStatus().' / '.$response->getMessage());
809
+ self::debug($client->getLastRequest());
810
+ self::debug($response->getHeaders());
811
+ }
812
+ if ($response->isSuccessful()) {
813
+ // XXX tempolary
814
+ self::$lastModified = $response->getHeader('Last-Modified');
815
+ $data = self::httpData($response->getBody(), $options['dataType'], $options);
816
+ if (isset($options['success']) && $options['success'])
817
+ phpQuery::callbackRun($options['success'], array($data, $response->getStatus(), $options));
818
+ if ($options['global'])
819
+ phpQueryEvents::trigger($documentID, 'ajaxSuccess', array($client, $options));
820
+ } else {
821
+ if (isset($options['error']) && $options['error'])
822
+ phpQuery::callbackRun($options['error'], array($client, $response->getStatus(), $response->getMessage()));
823
+ if ($options['global'])
824
+ phpQueryEvents::trigger($documentID, 'ajaxError', array($client, /*$response->getStatus(),*/$response->getMessage(), $options));
825
+ }
826
+ if (isset($options['complete']) && $options['complete'])
827
+ phpQuery::callbackRun($options['complete'], array($client, $response->getStatus()));
828
+ if ($options['global'])
829
+ phpQueryEvents::trigger($documentID, 'ajaxComplete', array($client, $options));
830
+ if ($options['global'] && ! --self::$active)
831
+ phpQueryEvents::trigger($documentID, 'ajaxStop');
832
+ return $client;
833
+ // if (is_null($domId))
834
+ // $domId = self::$defaultDocumentID ? self::$defaultDocumentID : false;
835
+ // return new phpQueryAjaxResponse($response, $domId);
836
+ }
837
+ protected static function httpData($data, $type, $options) {
838
+ if (isset($options['dataFilter']) && $options['dataFilter'])
839
+ $data = self::callbackRun($options['dataFilter'], array($data, $type));
840
+ if (is_string($data)) {
841
+ if ($type == "json") {
842
+ if (isset($options['_jsonp']) && $options['_jsonp']) {
843
+ $data = preg_replace('/^\s*\w+\((.*)\)\s*$/s', '$1', $data);
844
+ }
845
+ $data = self::parseJSON($data);
846
+ }
847
+ }
848
+ return $data;
849
+ }
850
+ /**
851
+ * Enter description here...
852
+ *
853
+ * @param array|phpQuery $data
854
+ *
855
+ */
856
+ public static function param($data) {
857
+ return http_build_query($data, null, '&');
858
+ }
859
+ public static function get($url, $data = null, $callback = null, $type = null) {
860
+ if (!is_array($data)) {
861
+ $callback = $data;
862
+ $data = null;
863
+ }
864
+ // TODO some array_values on this shit
865
+ return phpQuery::ajax(array(
866
+ 'type' => 'GET',
867
+ 'url' => $url,
868
+ 'data' => $data,
869
+ 'success' => $callback,
870
+ 'dataType' => $type,
871
+ ));
872
+ }
873
+ public static function post($url, $data = null, $callback = null, $type = null) {
874
+ if (!is_array($data)) {
875
+ $callback = $data;
876
+ $data = null;
877
+ }
878
+ return phpQuery::ajax(array(
879
+ 'type' => 'POST',
880
+ 'url' => $url,
881
+ 'data' => $data,
882
+ 'success' => $callback,
883
+ 'dataType' => $type,
884
+ ));
885
+ }
886
+ public static function getJSON($url, $data = null, $callback = null) {
887
+ if (!is_array($data)) {
888
+ $callback = $data;
889
+ $data = null;
890
+ }
891
+ // TODO some array_values on this shit
892
+ return phpQuery::ajax(array(
893
+ 'type' => 'GET',
894
+ 'url' => $url,
895
+ 'data' => $data,
896
+ 'success' => $callback,
897
+ 'dataType' => 'json',
898
+ ));
899
+ }
900
+ public static function ajaxSetup($options) {
901
+ self::$ajaxSettings = array_merge(
902
+ self::$ajaxSettings,
903
+ $options
904
+ );
905
+ }
906
+ public static function ajaxAllowHost($host1, $host2 = null, $host3 = null) {
907
+ $loop = is_array($host1)
908
+ ? $host1
909
+ : func_get_args();
910
+ foreach($loop as $host) {
911
+ if ($host && ! in_array($host, phpQuery::$ajaxAllowedHosts)) {
912
+ phpQuery::$ajaxAllowedHosts[] = $host;
913
+ }
914
+ }
915
+ }
916
+ public static function ajaxAllowURL($url1, $url2 = null, $url3 = null) {
917
+ $loop = is_array($url1)
918
+ ? $url1
919
+ : func_get_args();
920
+ foreach($loop as $url)
921
+ phpQuery::ajaxAllowHost(parse_url($url, PHP_URL_HOST));
922
+ }
923
+ /**
924
+ * Returns JSON representation of $data.
925
+ *
926
+ * @static
927
+ * @param mixed $data
928
+ * @return string
929
+ */
930
+ public static function toJSON($data) {
931
+ if (function_exists('json_encode'))
932
+ return json_encode($data);
933
+ require_once('Zend/Json/Encoder.php');
934
+ return Zend_Json_Encoder::encode($data);
935
+ }
936
+ /**
937
+ * Parses JSON into proper PHP type.
938
+ *
939
+ * @static
940
+ * @param string $json
941
+ * @return mixed
942
+ */
943
+ public static function parseJSON($json) {
944
+ if (function_exists('json_decode')) {
945
+ $return = json_decode(trim($json), true);
946
+ // json_decode and UTF8 issues
947
+ if (isset($return))
948
+ return $return;
949
+ }
950
+ require_once('Zend/Json/Decoder.php');
951
+ return Zend_Json_Decoder::decode($json);
952
+ }
953
+ /**
954
+ * Returns source's document ID.
955
+ *
956
+ * @param $source DOMNode|phpQueryObject
957
+ * @return string
958
+ */
959
+ public static function getDocumentID($source) {
960
+ if ($source instanceof DOMDOCUMENT) {
961
+ foreach(phpQuery::$documents as $id => $document) {
962
+ if ($source->isSameNode($document->document))
963
+ return $id;
964
+ }
965
+ } else if ($source instanceof DOMNODE) {
966
+ foreach(phpQuery::$documents as $id => $document) {
967
+ if ($source->ownerDocument->isSameNode($document->document))
968
+ return $id;
969
+ }
970
+ } else if ($source instanceof phpQueryObject)
971
+ return $source->getDocumentID();
972
+ else if (is_string($source) && isset(phpQuery::$documents[$source]))
973
+ return $source;
974
+ }
975
+ /**
976
+ * Get DOMDocument object related to $source.
977
+ * Returns null if such document doesn't exist.
978
+ *
979
+ * @param $source DOMNode|phpQueryObject|string
980
+ * @return string
981
+ */
982
+ public static function getDOMDocument($source) {
983
+ if ($source instanceof DOMDOCUMENT)
984
+ return $source;
985
+ $source = self::getDocumentID($source);
986
+ return $source
987
+ ? self::$documents[$id]['document']
988
+ : null;
989
+ }
990
+
991
+ // UTILITIES
992
+ // http://docs.jquery.com/Utilities
993
+
994
+ /**
995
+ *
996
+ * @return unknown_type
997
+ * @link http://docs.jquery.com/Utilities/jQuery.makeArray
998
+ */
999
+ public static function makeArray($obj) {
1000
+ $array = array();
1001
+ if (is_object($object) && $object instanceof DOMNODELIST) {
1002
+ foreach($object as $value)
1003
+ $array[] = $value;
1004
+ } else if (is_object($object) && ! ($object instanceof Iterator)) {
1005
+ foreach(get_object_vars($object) as $name => $value)
1006
+ $array[0][$name] = $value;
1007
+ } else {
1008
+ foreach($object as $name => $value)
1009
+ $array[0][$name] = $value;
1010
+ }
1011
+ return $array;
1012
+ }
1013
+ public static function inArray($value, $array) {
1014
+ return in_array($value, $array);
1015
+ }
1016
+ /**
1017
+ *
1018
+ * @param $object
1019
+ * @param $callback
1020
+ * @return unknown_type
1021
+ * @link http://docs.jquery.com/Utilities/jQuery.each
1022
+ */
1023
+ public static function each($object, $callback, $param1 = null, $param2 = null, $param3 = null) {
1024
+ $paramStructure = null;
1025
+ if (func_num_args() > 2) {
1026
+ $paramStructure = func_get_args();
1027
+ $paramStructure = array_slice($paramStructure, 2);
1028
+ }
1029
+ if (is_object($object) && ! ($object instanceof Iterator)) {
1030
+ foreach(get_object_vars($object) as $name => $value)
1031
+ phpQuery::callbackRun($callback, array($name, $value), $paramStructure);
1032
+ } else {
1033
+ foreach($object as $name => $value)
1034
+ phpQuery::callbackRun($callback, array($name, $value), $paramStructure);
1035
+ }
1036
+ }
1037
+ /**
1038
+ *
1039
+ * @link http://docs.jquery.com/Utilities/jQuery.map
1040
+ */
1041
+ public static function map($array, $callback, $param1 = null, $param2 = null, $param3 = null) {
1042
+ $result = array();
1043
+ $paramStructure = null;
1044
+ if (func_num_args() > 2) {
1045
+ $paramStructure = func_get_args();
1046
+ $paramStructure = array_slice($paramStructure, 2);
1047
+ }
1048
+ foreach($array as $v) {
1049
+ $vv = phpQuery::callbackRun($callback, array($v), $paramStructure);
1050
+ // $callbackArgs = $args;
1051
+ // foreach($args as $i => $arg) {
1052
+ // $callbackArgs[$i] = $arg instanceof CallbackParam
1053
+ // ? $v
1054
+ // : $arg;
1055
+ // }
1056
+ // $vv = call_user_func_array($callback, $callbackArgs);
1057
+ if (is_array($vv)) {
1058
+ foreach($vv as $vvv)
1059
+ $result[] = $vvv;
1060
+ } else if ($vv !== null) {
1061
+ $result[] = $vv;
1062
+ }
1063
+ }
1064
+ return $result;
1065
+ }
1066
+ /**
1067
+ *
1068
+ * @param $callback Callback
1069
+ * @param $params
1070
+ * @param $paramStructure
1071
+ * @return unknown_type
1072
+ */
1073
+ public static function callbackRun($callback, $params = array(), $paramStructure = null) {
1074
+ if (! $callback)
1075
+ return;
1076
+ if ($callback instanceof CallbackParameterToReference) {
1077
+ // TODO support ParamStructure to select which $param push to reference
1078
+ if (isset($params[0]))
1079
+ $callback->callback = $params[0];
1080
+ return true;
1081
+ }
1082
+ if ($callback instanceof Callback) {
1083
+ $paramStructure = $callback->params;
1084
+ $callback = $callback->callback;
1085
+ }
1086
+ if (! $paramStructure)
1087
+ return call_user_func_array($callback, $params);
1088
+ $p = 0;
1089
+ foreach($paramStructure as $i => $v) {
1090
+ $paramStructure[$i] = $v instanceof CallbackParam
1091
+ ? $params[$p++]
1092
+ : $v;
1093
+ }
1094
+ return call_user_func_array($callback, $paramStructure);
1095
+ }
1096
+ /**
1097
+ * Merge 2 phpQuery objects.
1098
+ * @param array $one
1099
+ * @param array $two
1100
+ * @protected
1101
+ * @todo node lists, phpQueryObject
1102
+ */
1103
+ public static function merge($one, $two) {
1104
+ $elements = $one->elements;
1105
+ foreach($two->elements as $node) {
1106
+ $exists = false;
1107
+ foreach($elements as $node2) {
1108
+ if ($node2->isSameNode($node))
1109
+ $exists = true;
1110
+ }
1111
+ if (! $exists)
1112
+ $elements[] = $node;
1113
+ }
1114
+ return $elements;
1115
+ // $one = $one->newInstance();
1116
+ // $one->elements = $elements;
1117
+ // return $one;
1118
+ }
1119
+ /**
1120
+ *
1121
+ * @param $array
1122
+ * @param $callback
1123
+ * @param $invert
1124
+ * @return unknown_type
1125
+ * @link http://docs.jquery.com/Utilities/jQuery.grep
1126
+ */
1127
+ public static function grep($array, $callback, $invert = false) {
1128
+ $result = array();
1129
+ foreach($array as $k => $v) {
1130
+ $r = call_user_func_array($callback, array($v, $k));
1131
+ if ($r === !(bool)$invert)
1132
+ $result[] = $v;
1133
+ }
1134
+ return $result;
1135
+ }
1136
+ public static function unique($array) {
1137
+ return array_unique($array);
1138
+ }
1139
+ /**
1140
+ *
1141
+ * @param $function
1142
+ * @return unknown_type
1143
+ * @TODO there are problems with non-static methods, second parameter pass it
1144
+ * but doesnt verify is method is really callable
1145
+ */
1146
+ public static function isFunction($function) {
1147
+ return is_callable($function);
1148
+ }
1149
+ public static function trim($str) {
1150
+ return trim($str);
1151
+ }
1152
+ /* PLUGINS NAMESPACE */
1153
+ /**
1154
+ *
1155
+ * @param $url
1156
+ * @param $callback
1157
+ * @param $param1
1158
+ * @param $param2
1159
+ * @param $param3
1160
+ * @return phpQueryObject
1161
+ */
1162
+ public static function browserGet($url, $callback, $param1 = null, $param2 = null, $param3 = null) {
1163
+ if (self::plugin('WebBrowser')) {
1164
+ $params = func_get_args();
1165
+ return self::callbackRun(array(self::$plugins, 'browserGet'), $params);
1166
+ } else {
1167
+ self::debug('WebBrowser plugin not available...');
1168
+ }
1169
+ }
1170
+ /**
1171
+ *
1172
+ * @param $url
1173
+ * @param $data
1174
+ * @param $callback
1175
+ * @param $param1
1176
+ * @param $param2
1177
+ * @param $param3
1178
+ * @return phpQueryObject
1179
+ */
1180
+ public static function browserPost($url, $data, $callback, $param1 = null, $param2 = null, $param3 = null) {
1181
+ if (self::plugin('WebBrowser')) {
1182
+ $params = func_get_args();
1183
+ return self::callbackRun(array(self::$plugins, 'browserPost'), $params);
1184
+ } else {
1185
+ self::debug('WebBrowser plugin not available...');
1186
+ }
1187
+ }
1188
+ /**
1189
+ *
1190
+ * @param $ajaxSettings
1191
+ * @param $callback
1192
+ * @param $param1
1193
+ * @param $param2
1194
+ * @param $param3
1195
+ * @return phpQueryObject
1196
+ */
1197
+ public static function browser($ajaxSettings, $callback, $param1 = null, $param2 = null, $param3 = null) {
1198
+ if (self::plugin('WebBrowser')) {
1199
+ $params = func_get_args();
1200
+ return self::callbackRun(array(self::$plugins, 'browser'), $params);
1201
+ } else {
1202
+ self::debug('WebBrowser plugin not available...');
1203
+ }
1204
+ }
1205
+ /**
1206
+ *
1207
+ * @param $code
1208
+ * @return string
1209
+ */
1210
+ public static function php($code) {
1211
+ return self::code('php', $code);
1212
+ }
1213
+ /**
1214
+ *
1215
+ * @param $type
1216
+ * @param $code
1217
+ * @return string
1218
+ */
1219
+ public static function code($type, $code) {
1220
+ return "<$type><!-- ".trim($code)." --></$type>";
1221
+ }
1222
+
1223
+ public static function __callStatic($method, $params) {
1224
+ return call_user_func_array(
1225
+ array(phpQuery::$plugins, $method),
1226
+ $params
1227
+ );
1228
+ }
1229
+ protected static function dataSetupNode($node, $documentID) {
1230
+ // search are return if alredy exists
1231
+ foreach(phpQuery::$documents[$documentID]->dataNodes as $dataNode) {
1232
+ if ($node->isSameNode($dataNode))
1233
+ return $dataNode;
1234
+ }
1235
+ // if doesn't, add it
1236
+ phpQuery::$documents[$documentID]->dataNodes[] = $node;
1237
+ return $node;
1238
+ }
1239
+ protected static function dataRemoveNode($node, $documentID) {
1240
+ // search are return if alredy exists
1241
+ foreach(phpQuery::$documents[$documentID]->dataNodes as $k => $dataNode) {
1242
+ if ($node->isSameNode($dataNode)) {
1243
+ unset(self::$documents[$documentID]->dataNodes[$k]);
1244
+ unset(self::$documents[$documentID]->data[ $dataNode->dataID ]);
1245
+ }
1246
+ }
1247
+ }
1248
+ public static function data($node, $name, $data, $documentID = null) {
1249
+ if (! $documentID)
1250
+ // TODO check if this works
1251
+ $documentID = self::getDocumentID($node);
1252
+ $document = phpQuery::$documents[$documentID];
1253
+ $node = self::dataSetupNode($node, $documentID);
1254
+ if (! isset($node->dataID))
1255
+ $node->dataID = ++phpQuery::$documents[$documentID]->uuid;
1256
+ $id = $node->dataID;
1257
+ if (! isset($document->data[$id]))
1258
+ $document->data[$id] = array();
1259
+ if (! is_null($data))
1260
+ $document->data[$id][$name] = $data;
1261
+ if ($name) {
1262
+ if (isset($document->data[$id][$name]))
1263
+ return $document->data[$id][$name];
1264
+ } else
1265
+ return $id;
1266
+ }
1267
+ public static function removeData($node, $name, $documentID) {
1268
+ if (! $documentID)
1269
+ // TODO check if this works
1270
+ $documentID = self::getDocumentID($node);
1271
+ $document = phpQuery::$documents[$documentID];
1272
+ $node = self::dataSetupNode($node, $documentID);
1273
+ $id = $node->dataID;
1274
+ if ($name) {
1275
+ if (isset($document->data[$id][$name]))
1276
+ unset($document->data[$id][$name]);
1277
+ $name = null;
1278
+ foreach($document->data[$id] as $name)
1279
+ break;
1280
+ if (! $name)
1281
+ self::removeData($node, $name, $documentID);
1282
+ } else {
1283
+ self::dataRemoveNode($node, $documentID);
1284
+ }
1285
+ }
1286
+ }
1287
+ /**
1288
+ * Plugins static namespace class.
1289
+ *
1290
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
1291
+ * @package phpQuery
1292
+ * @todo move plugin methods here (as statics)
1293
+ */
1294
+ class phpQueryPlugins {
1295
+ public function __call($method, $args) {
1296
+ if (isset(phpQuery::$extendStaticMethods[$method])) {
1297
+ $return = call_user_func_array(
1298
+ phpQuery::$extendStaticMethods[$method],
1299
+ $args
1300
+ );
1301
+ } else if (isset(phpQuery::$pluginsStaticMethods[$method])) {
1302
+ $class = phpQuery::$pluginsStaticMethods[$method];
1303
+ $realClass = "phpQueryPlugin_$class";
1304
+ $return = call_user_func_array(
1305
+ array($realClass, $method),
1306
+ $args
1307
+ );
1308
+ return isset($return)
1309
+ ? $return
1310
+ : $this;
1311
+ } else
1312
+ throw new Exception("Method '{$method}' doesnt exist");
1313
+ }
1314
+ }
1315
+ /**
1316
+ * Shortcut to phpQuery::pq($arg1, $context)
1317
+ * Chainable.
1318
+ *
1319
+ * @see phpQuery::pq()
1320
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1321
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
1322
+ * @package phpQuery
1323
+ */
1324
+ function pq($arg1, $context = null) {
1325
+ $args = func_get_args();
1326
+ return call_user_func_array(
1327
+ array('phpQuery', 'pq'),
1328
+ $args
1329
+ );
1330
+ }
1331
+ // add plugins dir and Zend framework to include path
1332
+ set_include_path(
1333
+ get_include_path()
1334
+ .PATH_SEPARATOR.dirname(__FILE__).'/phpQuery/'
1335
+ .PATH_SEPARATOR.dirname(__FILE__).'/phpQuery/plugins/'
1336
+ );
1337
+ // why ? no __call nor __get for statics in php...
1338
+ // XXX __callStatic will be available in PHP 5.3
1339
+ phpQuery::$plugins = new phpQueryPlugins();
1340
+ // include bootstrap file (personal library config)
1341
+ if (file_exists(dirname(__FILE__).'/phpQuery/bootstrap.php'))
1342
+ require_once dirname(__FILE__).'/phpQuery/bootstrap.php';
includes/phpQuery/phpQuery/Callback.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ interface ICallbackNamed {
3
+ function hasName();
4
+ function getName();
5
+ }
6
+ /**
7
+ * Callback class introduces currying-like pattern.
8
+ *
9
+ * Example:
10
+ * function foo($param1, $param2, $param3) {
11
+ * var_dump($param1, $param2, $param3);
12
+ * }
13
+ * $fooCurried = new Callback('foo',
14
+ * 'param1 is now statically set',
15
+ * new CallbackParam, new CallbackParam
16
+ * );
17
+ * phpQuery::callbackRun($fooCurried,
18
+ * array('param2 value', 'param3 value'
19
+ * );
20
+ *
21
+ * Callback class is supported in all phpQuery methods which accepts callbacks.
22
+ *
23
+ * @link http://code.google.com/p/phpquery/wiki/Callbacks#Param_Structures
24
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
25
+ *
26
+ * @TODO??? return fake forwarding function created via create_function
27
+ * @TODO honor paramStructure
28
+ */
29
+ class Callback
30
+ implements ICallbackNamed {
31
+ public $callback = null;
32
+ public $params = null;
33
+ protected $name;
34
+ public function __construct($callback, $param1 = null, $param2 = null,
35
+ $param3 = null) {
36
+ $params = func_get_args();
37
+ $params = array_slice($params, 1);
38
+ if ($callback instanceof Callback) {
39
+ // TODO implement recurention
40
+ } else {
41
+ $this->callback = $callback;
42
+ $this->params = $params;
43
+ }
44
+ }
45
+ public function getName() {
46
+ return 'Callback: '.$this->name;
47
+ }
48
+ public function hasName() {
49
+ return isset($this->name) && $this->name;
50
+ }
51
+ public function setName($name) {
52
+ $this->name = $name;
53
+ return $this;
54
+ }
55
+ // TODO test me
56
+ // public function addParams() {
57
+ // $params = func_get_args();
58
+ // return new Callback($this->callback, $this->params+$params);
59
+ // }
60
+ }
61
+ /**
62
+ * Shorthand for new Callback(create_function(...), ...);
63
+ *
64
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
65
+ */
66
+ class CallbackBody extends Callback {
67
+ public function __construct($paramList, $code, $param1 = null, $param2 = null,
68
+ $param3 = null) {
69
+ $params = func_get_args();
70
+ $params = array_slice($params, 2);
71
+ $this->callback = create_function($paramList, $code);
72
+ $this->params = $params;
73
+ }
74
+ }
75
+ /**
76
+ * Callback type which on execution returns reference passed during creation.
77
+ *
78
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
79
+ */
80
+ class CallbackReturnReference extends Callback
81
+ implements ICallbackNamed {
82
+ protected $reference;
83
+ public function __construct(&$reference, $name = null){
84
+ $this->reference =& $reference;
85
+ $this->callback = array($this, 'callback');
86
+ }
87
+ public function callback() {
88
+ return $this->reference;
89
+ }
90
+ public function getName() {
91
+ return 'Callback: '.$this->name;
92
+ }
93
+ public function hasName() {
94
+ return isset($this->name) && $this->name;
95
+ }
96
+ }
97
+ /**
98
+ * Callback type which on execution returns value passed during creation.
99
+ *
100
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
101
+ */
102
+ class CallbackReturnValue extends Callback
103
+ implements ICallbackNamed {
104
+ protected $value;
105
+ protected $name;
106
+ public function __construct($value, $name = null){
107
+ $this->value =& $value;
108
+ $this->name = $name;
109
+ $this->callback = array($this, 'callback');
110
+ }
111
+ public function callback() {
112
+ return $this->value;
113
+ }
114
+ public function __toString() {
115
+ return $this->getName();
116
+ }
117
+ public function getName() {
118
+ return 'Callback: '.$this->name;
119
+ }
120
+ public function hasName() {
121
+ return isset($this->name) && $this->name;
122
+ }
123
+ }
124
+ /**
125
+ * CallbackParameterToReference can be used when we don't really want a callback,
126
+ * only parameter passed to it. CallbackParameterToReference takes first
127
+ * parameter's value and passes it to reference.
128
+ *
129
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
130
+ */
131
+ class CallbackParameterToReference extends Callback {
132
+ /**
133
+ * @param $reference
134
+ * @TODO implement $paramIndex;
135
+ * param index choose which callback param will be passed to reference
136
+ */
137
+ public function __construct(&$reference){
138
+ $this->callback =& $reference;
139
+ }
140
+ }
141
+ //class CallbackReference extends Callback {
142
+ // /**
143
+ // *
144
+ // * @param $reference
145
+ // * @param $paramIndex
146
+ // * @todo implement $paramIndex; param index choose which callback param will be passed to reference
147
+ // */
148
+ // public function __construct(&$reference, $name = null){
149
+ // $this->callback =& $reference;
150
+ // }
151
+ //}
152
+ class CallbackParam {}
includes/phpQuery/phpQuery/DOMDocumentWrapper.php ADDED
@@ -0,0 +1,677 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * DOMDocumentWrapper class simplifies work with DOMDocument.
4
+ *
5
+ * Know bug:
6
+ * - in XHTML fragments, <br /> changes to <br clear="none" />
7
+ *
8
+ * @todo check XML catalogs compatibility
9
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
10
+ * @package phpQuery
11
+ */
12
+ class DOMDocumentWrapper {
13
+ /**
14
+ * @var DOMDocument
15
+ */
16
+ public $document;
17
+ public $id;
18
+ /**
19
+ * @todo Rewrite as method and quess if null.
20
+ * @var unknown_type
21
+ */
22
+ public $contentType = '';
23
+ public $xpath;
24
+ public $uuid = 0;
25
+ public $data = array();
26
+ public $dataNodes = array();
27
+ public $events = array();
28
+ public $eventsNodes = array();
29
+ public $eventsGlobal = array();
30
+ /**
31
+ * @TODO iframes support http://code.google.com/p/phpquery/issues/detail?id=28
32
+ * @var unknown_type
33
+ */
34
+ public $frames = array();
35
+ /**
36
+ * Document root, by default equals to document itself.
37
+ * Used by documentFragments.
38
+ *
39
+ * @var DOMNode
40
+ */
41
+ public $root;
42
+ public $isDocumentFragment;
43
+ public $isXML = false;
44
+ public $isXHTML = false;
45
+ public $isHTML = false;
46
+ public $charset;
47
+ public function __construct($markup = null, $contentType = null, $newDocumentID = null) {
48
+ if (isset($markup))
49
+ $this->load($markup, $contentType, $newDocumentID);
50
+ $this->id = $newDocumentID
51
+ ? $newDocumentID
52
+ : md5(microtime());
53
+ }
54
+ public function load($markup, $contentType = null, $newDocumentID = null) {
55
+ // phpQuery::$documents[$id] = $this;
56
+ $this->contentType = strtolower($contentType);
57
+ if ($markup instanceof DOMDOCUMENT) {
58
+ $this->document = $markup;
59
+ $this->root = $this->document;
60
+ $this->charset = $this->document->encoding;
61
+ // TODO isDocumentFragment
62
+ } else {
63
+ $loaded = $this->loadMarkup($markup);
64
+ }
65
+ if ($loaded) {
66
+ // $this->document->formatOutput = true;
67
+ $this->document->preserveWhiteSpace = true;
68
+ $this->xpath = new DOMXPath($this->document);
69
+ $this->afterMarkupLoad();
70
+ return true;
71
+ // remember last loaded document
72
+ // return phpQuery::selectDocument($id);
73
+ }
74
+ return false;
75
+ }
76
+ protected function afterMarkupLoad() {
77
+ if ($this->isXHTML) {
78
+ $this->xpath->registerNamespace("html", "http://www.w3.org/1999/xhtml");
79
+ }
80
+ }
81
+ protected function loadMarkup($markup) {
82
+ $loaded = false;
83
+ if ($this->contentType) {
84
+ self::debug("Load markup for content type {$this->contentType}");
85
+ // content determined by contentType
86
+ list($contentType, $charset) = $this->contentTypeToArray($this->contentType);
87
+ switch($contentType) {
88
+ case 'text/html':
89
+ phpQuery::debug("Loading HTML, content type '{$this->contentType}'");
90
+ $loaded = $this->loadMarkupHTML($markup, $charset);
91
+ break;
92
+ case 'text/xml':
93
+ case 'application/xhtml+xml':
94
+ phpQuery::debug("Loading XML, content type '{$this->contentType}'");
95
+ $loaded = $this->loadMarkupXML($markup, $charset);
96
+ break;
97
+ default:
98
+ // for feeds or anything that sometimes doesn't use text/xml
99
+ if (strpos('xml', $this->contentType) !== false) {
100
+ phpQuery::debug("Loading XML, content type '{$this->contentType}'");
101
+ $loaded = $this->loadMarkupXML($markup, $charset);
102
+ } else
103
+ phpQuery::debug("Could not determine document type from content type '{$this->contentType}'");
104
+ }
105
+ } else {
106
+ // content type autodetection
107
+ if ($this->isXML($markup)) {
108
+ phpQuery::debug("Loading XML, isXML() == true");
109
+ $loaded = $this->loadMarkupXML($markup);
110
+ if (! $loaded && $this->isXHTML) {
111
+ phpQuery::debug('Loading as XML failed, trying to load as HTML, isXHTML == true');
112
+ $loaded = $this->loadMarkupHTML($markup);
113
+ }
114
+ } else {
115
+ phpQuery::debug("Loading HTML, isXML() == false");
116
+ $loaded = $this->loadMarkupHTML($markup);
117
+ }
118
+ }
119
+ return $loaded;
120
+ }
121
+ protected function loadMarkupReset() {
122
+ $this->isXML = $this->isXHTML = $this->isHTML = false;
123
+ }
124
+ protected function documentCreate($charset, $version = '1.0') {
125
+ if (! $version)
126
+ $version = '1.0';
127
+ $this->document = new DOMDocument($version, $charset);
128
+ $this->charset = $this->document->encoding;
129
+ // $this->document->encoding = $charset;
130
+ $this->document->formatOutput = true;
131
+ $this->document->preserveWhiteSpace = true;
132
+ }
133
+ protected function loadMarkupHTML($markup, $requestedCharset = null) {
134
+ if (phpQuery::$debug)
135
+ phpQuery::debug('Full markup load (HTML): '.substr($markup, 0, 250));
136
+ $this->loadMarkupReset();
137
+ $this->isHTML = true;
138
+ if (!isset($this->isDocumentFragment))
139
+ $this->isDocumentFragment = self::isDocumentFragmentHTML($markup);
140
+ $charset = null;
141
+ $documentCharset = $this->charsetFromHTML($markup);
142
+ $addDocumentCharset = false;
143
+ if ($documentCharset) {
144
+ $charset = $documentCharset;
145
+ $markup = $this->charsetFixHTML($markup);
146
+ } else if ($requestedCharset) {
147
+ $charset = $requestedCharset;
148
+ }
149
+ if (! $charset)
150
+ $charset = phpQuery::$defaultCharset;
151
+ // HTTP 1.1 says that the default charset is ISO-8859-1
152
+ // @see http://www.w3.org/International/O-HTTP-charset
153
+ if (! $documentCharset) {
154
+ $documentCharset = 'ISO-8859-1';
155
+ $addDocumentCharset = true;
156
+ }
157
+ // Should be careful here, still need 'magic encoding detection' since lots of pages have other 'default encoding'
158
+ // Worse, some pages can have mixed encodings... we'll try not to worry about that
159
+ $requestedCharset = strtoupper($requestedCharset);
160
+ $documentCharset = strtoupper($documentCharset);
161
+ phpQuery::debug("DOC: $documentCharset REQ: $requestedCharset");
162
+ if ($requestedCharset && $documentCharset && $requestedCharset !== $documentCharset) {
163
+ phpQuery::debug("CHARSET CONVERT");
164
+ // Document Encoding Conversion
165
+ // http://code.google.com/p/phpquery/issues/detail?id=86
166
+ if (function_exists('mb_detect_encoding')) {
167
+ $possibleCharsets = array($documentCharset, $requestedCharset, 'AUTO');
168
+ $docEncoding = mb_detect_encoding($markup, implode(', ', $possibleCharsets));
169
+ if (! $docEncoding)
170
+ $docEncoding = $documentCharset; // ok trust the document
171
+ phpQuery::debug("DETECTED '$docEncoding'");
172
+ // Detected does not match what document says...
173
+ if ($docEncoding !== $documentCharset) {
174
+ // Tricky..
175
+ }
176
+ if ($docEncoding !== $requestedCharset) {
177
+ phpQuery::debug("CONVERT $docEncoding => $requestedCharset");
178
+ $markup = mb_convert_encoding($markup, $requestedCharset, $docEncoding);
179
+ $markup = $this->charsetAppendToHTML($markup, $requestedCharset);
180
+ $charset = $requestedCharset;
181
+ }
182
+ } else {
183
+ phpQuery::debug("TODO: charset conversion without mbstring...");
184
+ }
185
+ }
186
+ $return = false;
187
+ if ($this->isDocumentFragment) {
188
+ phpQuery::debug("Full markup load (HTML), DocumentFragment detected, using charset '$charset'");
189
+ $return = $this->documentFragmentLoadMarkup($this, $charset, $markup);
190
+ } else {
191
+ if ($addDocumentCharset) {
192
+ phpQuery::debug("Full markup load (HTML), appending charset: '$charset'");
193
+ $markup = $this->charsetAppendToHTML($markup, $charset);
194
+ }
195
+ phpQuery::debug("Full markup load (HTML), documentCreate('$charset')");
196
+ $this->documentCreate($charset);
197
+ $return = phpQuery::$debug === 2
198
+ ? $this->document->loadHTML($markup)
199
+ : @$this->document->loadHTML($markup);
200
+ if ($return)
201
+ $this->root = $this->document;
202
+ }
203
+ if ($return && ! $this->contentType)
204
+ $this->contentType = 'text/html';
205
+ return $return;
206
+ }
207
+ protected function loadMarkupXML($markup, $requestedCharset = null) {
208
+ if (phpQuery::$debug)
209
+ phpQuery::debug('Full markup load (XML): '.substr($markup, 0, 250));
210
+ $this->loadMarkupReset();
211
+ $this->isXML = true;
212
+ // check agains XHTML in contentType or markup
213
+ $isContentTypeXHTML = $this->isXHTML();
214
+ $isMarkupXHTML = $this->isXHTML($markup);
215
+ if ($isContentTypeXHTML || $isMarkupXHTML) {
216
+ self::debug('Full markup load (XML), XHTML detected');
217
+ $this->isXHTML = true;
218
+ }
219
+ // determine document fragment
220
+ if (! isset($this->isDocumentFragment))
221
+ $this->isDocumentFragment = $this->isXHTML
222
+ ? self::isDocumentFragmentXHTML($markup)
223
+ : self::isDocumentFragmentXML($markup);
224
+ // this charset will be used
225
+ $charset = null;
226
+ // charset from XML declaration @var string
227
+ $documentCharset = $this->charsetFromXML($markup);
228
+ if (! $documentCharset) {
229
+ if ($this->isXHTML) {
230
+ // this is XHTML, try to get charset from content-type meta header
231
+ $documentCharset = $this->charsetFromHTML($markup);
232
+ if ($documentCharset) {
233
+ phpQuery::debug("Full markup load (XML), appending XHTML charset '$documentCharset'");
234
+ $this->charsetAppendToXML($markup, $documentCharset);
235
+ $charset = $documentCharset;
236
+ }
237
+ }
238
+ if (! $documentCharset) {
239
+ // if still no document charset...
240
+ $charset = $requestedCharset;
241
+ }
242
+ } else if ($requestedCharset) {
243
+ $charset = $requestedCharset;
244
+ }
245
+ if (! $charset) {
246
+ $charset = phpQuery::$defaultCharset;
247
+ }
248
+ if ($requestedCharset && $documentCharset && $requestedCharset != $documentCharset) {
249
+ // TODO place for charset conversion
250
+ // $charset = $requestedCharset;
251
+ }
252
+ $return = false;
253
+ if ($this->isDocumentFragment) {
254
+ phpQuery::debug("Full markup load (XML), DocumentFragment detected, using charset '$charset'");
255
+ $return = $this->documentFragmentLoadMarkup($this, $charset, $markup);
256
+ } else {
257
+ // FIXME ???
258
+ if ($isContentTypeXHTML && ! $isMarkupXHTML)
259
+ if (! $documentCharset) {
260
+ phpQuery::debug("Full markup load (XML), appending charset '$charset'");
261
+ $markup = $this->charsetAppendToXML($markup, $charset);
262
+ }
263
+ // see http://pl2.php.net/manual/en/book.dom.php#78929
264
+ // LIBXML_DTDLOAD (>= PHP 5.1)
265
+ // does XML ctalogues works with LIBXML_NONET
266
+ // $this->document->resolveExternals = true;
267
+ // TODO test LIBXML_COMPACT for performance improvement
268
+ // create document
269
+ $this->documentCreate($charset);
270
+ if (phpversion() < 5.1) {
271
+ $this->document->resolveExternals = true;
272
+ $return = phpQuery::$debug === 2
273
+ ? $this->document->loadXML($markup)
274
+ : @$this->document->loadXML($markup);
275
+ } else {
276
+ /** @link http://pl2.php.net/manual/en/libxml.constants.php */
277
+ $libxmlStatic = phpQuery::$debug === 2
278
+ ? LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET
279
+ : LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NONET|LIBXML_NOWARNING|LIBXML_NOERROR;
280
+ $return = $this->document->loadXML($markup, $libxmlStatic);
281
+ // if (! $return)
282
+ // $return = $this->document->loadHTML($markup);
283
+ }
284
+ if ($return)
285
+ $this->root = $this->document;
286
+ }
287
+ if ($return) {
288
+ if (! $this->contentType) {
289
+ if ($this->isXHTML)
290
+ $this->contentType = 'application/xhtml+xml';
291
+ else
292
+ $this->contentType = 'text/xml';
293
+ }
294
+ return $return;
295
+ } else {
296
+ throw new Exception("Error loading XML markup");
297
+ }
298
+ }
299
+ protected function isXHTML($markup = null) {
300
+ if (! isset($markup)) {
301
+ return strpos($this->contentType, 'xhtml') !== false;
302
+ }
303
+ // XXX ok ?
304
+ return strpos($markup, "<!DOCTYPE html") !== false;
305
+ // return stripos($doctype, 'xhtml') !== false;
306
+ // $doctype = isset($dom->doctype) && is_object($dom->doctype)
307
+ // ? $dom->doctype->publicId
308
+ // : self::$defaultDoctype;
309
+ }
310
+ protected function isXML($markup) {
311
+ // return strpos($markup, '<?xml') !== false && stripos($markup, 'xhtml') === false;
312
+ return strpos(substr($markup, 0, 100), '<'.'?xml') !== false;
313
+ }
314
+ protected function contentTypeToArray($contentType) {
315
+ $matches = explode(';', trim(strtolower($contentType)));
316
+ if (isset($matches[1])) {
317
+ $matches[1] = explode('=', $matches[1]);
318
+ // strip 'charset='
319
+ $matches[1] = isset($matches[1][1]) && trim($matches[1][1])
320
+ ? $matches[1][1]
321
+ : $matches[1][0];
322
+ } else
323
+ $matches[1] = null;
324
+ return $matches;
325
+ }
326
+ /**
327
+ *
328
+ * @param $markup
329
+ * @return array contentType, charset
330
+ */
331
+ protected function contentTypeFromHTML($markup) {
332
+ $matches = array();
333
+ // find meta tag
334
+ preg_match('@<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i',
335
+ $markup, $matches
336
+ );
337
+ if (! isset($matches[0]))
338
+ return array(null, null);
339
+ // get attr 'content'
340
+ preg_match('@content\\s*=\\s*(["|\'])(.+?)\\1@', $matches[0], $matches);
341
+ if (! isset($matches[0]))
342
+ return array(null, null);
343
+ return $this->contentTypeToArray($matches[2]);
344
+ }
345
+ protected function charsetFromHTML($markup) {
346
+ $contentType = $this->contentTypeFromHTML($markup);
347
+ return $contentType[1];
348
+ }
349
+ protected function charsetFromXML($markup) {
350
+ $matches;
351
+ // find declaration
352
+ preg_match('@<'.'?xml[^>]+encoding\\s*=\\s*(["|\'])(.*?)\\1@i',
353
+ $markup, $matches
354
+ );
355
+ return isset($matches[2])
356
+ ? strtolower($matches[2])
357
+ : null;
358
+ }
359
+ /**
360
+ * Repositions meta[type=charset] at the start of head. Bypasses DOMDocument bug.
361
+ *
362
+ * @link http://code.google.com/p/phpquery/issues/detail?id=80
363
+ * @param $html
364
+ */
365
+ protected function charsetFixHTML($markup) {
366
+ $matches = array();
367
+ // find meta tag
368
+ preg_match('@\s*<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i',
369
+ $markup, $matches, PREG_OFFSET_CAPTURE
370
+ );
371
+ if (! isset($matches[0]))
372
+ return;
373
+ $metaContentType = $matches[0][0];
374
+ $markup = substr($markup, 0, $matches[0][1])
375
+ .substr($markup, $matches[0][1]+strlen($metaContentType));
376
+ $headStart = stripos($markup, '<head>');
377
+ $markup = substr($markup, 0, $headStart+6).$metaContentType
378
+ .substr($markup, $headStart+6);
379
+ return $markup;
380
+ }
381
+ protected function charsetAppendToHTML($html, $charset, $xhtml = false) {
382
+ // remove existing meta[type=content-type]
383
+ $html = preg_replace('@\s*<meta[^>]+http-equiv\\s*=\\s*(["|\'])Content-Type\\1([^>]+?)>@i', '', $html);
384
+ $meta = '<meta http-equiv="Content-Type" content="text/html;charset='
385
+ .$charset.'" '
386
+ .($xhtml ? '/' : '')
387
+ .'>';
388
+ if (strpos($html, '<head') === false) {
389
+ if (strpos($hltml, '<html') === false) {
390
+ return $meta.$html;
391
+ } else {
392
+ return preg_replace(
393
+ '@<html(.*?)(?(?<!\?)>)@s',
394
+ "<html\\1><head>{$meta}</head>",
395
+ $html
396
+ );
397
+ }
398
+ } else {
399
+ return preg_replace(
400
+ '@<head(.*?)(?(?<!\?)>)@s',
401
+ '<head\\1>'.$meta,
402
+ $html
403
+ );
404
+ }
405
+ }
406
+ protected function charsetAppendToXML($markup, $charset) {
407
+ $declaration = '<'.'?xml version="1.0" encoding="'.$charset.'"?'.'>';
408
+ return $declaration.$markup;
409
+ }
410
+ public static function isDocumentFragmentHTML($markup) {
411
+ return stripos($markup, '<html') === false && stripos($markup, '<!doctype') === false;
412
+ }
413
+ public static function isDocumentFragmentXML($markup) {
414
+ return stripos($markup, '<'.'?xml') === false;
415
+ }
416
+ public static function isDocumentFragmentXHTML($markup) {
417
+ return self::isDocumentFragmentHTML($markup);
418
+ }
419
+ public function importAttr($value) {
420
+ // TODO
421
+ }
422
+ /**
423
+ *
424
+ * @param $source
425
+ * @param $target
426
+ * @param $sourceCharset
427
+ * @return array Array of imported nodes.
428
+ */
429
+ public function import($source, $sourceCharset = null) {
430
+ // TODO charset conversions
431
+ $return = array();
432
+ if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST))
433
+ $source = array($source);
434
+ // if (is_array($source)) {
435
+ // foreach($source as $node) {
436
+ // if (is_string($node)) {
437
+ // // string markup
438
+ // $fake = $this->documentFragmentCreate($node, $sourceCharset);
439
+ // if ($fake === false)
440
+ // throw new Exception("Error loading documentFragment markup");
441
+ // else
442
+ // $return = array_merge($return,
443
+ // $this->import($fake->root->childNodes)
444
+ // );
445
+ // } else {
446
+ // $return[] = $this->document->importNode($node, true);
447
+ // }
448
+ // }
449
+ // return $return;
450
+ // } else {
451
+ // // string markup
452
+ // $fake = $this->documentFragmentCreate($source, $sourceCharset);
453
+ // if ($fake === false)
454
+ // throw new Exception("Error loading documentFragment markup");
455
+ // else
456
+ // return $this->import($fake->root->childNodes);
457
+ // }
458
+ if (is_array($source) || $source instanceof DOMNODELIST) {
459
+ // dom nodes
460
+ self::debug('Importing nodes to document');
461
+ foreach($source as $node)
462
+ $return[] = $this->document->importNode($node, true);
463
+ } else {
464
+ // string markup
465
+ $fake = $this->documentFragmentCreate($source, $sourceCharset);
466
+ if ($fake === false)
467
+ throw new Exception("Error loading documentFragment markup");
468
+ else
469
+ return $this->import($fake->root->childNodes);
470
+ }
471
+ return $return;
472
+ }
473
+ /**
474
+ * Creates new document fragment.
475
+ *
476
+ * @param $source
477
+ * @return DOMDocumentWrapper
478
+ */
479
+ protected function documentFragmentCreate($source, $charset = null) {
480
+ $fake = new DOMDocumentWrapper();
481
+ $fake->contentType = $this->contentType;
482
+ $fake->isXML = $this->isXML;
483
+ $fake->isHTML = $this->isHTML;
484
+ $fake->isXHTML = $this->isXHTML;
485
+ $fake->root = $fake->document;
486
+ if (! $charset)
487
+ $charset = $this->charset;
488
+ // $fake->documentCreate($this->charset);
489
+ if ($source instanceof DOMNODE && !($source instanceof DOMNODELIST))
490
+ $source = array($source);
491
+ if (is_array($source) || $source instanceof DOMNODELIST) {
492
+ // dom nodes
493
+ // load fake document
494
+ if (! $this->documentFragmentLoadMarkup($fake, $charset))
495
+ return false;
496
+ $nodes = $fake->import($source);
497
+ foreach($nodes as $node)
498
+ $fake->root->appendChild($node);
499
+ } else {
500
+ // string markup
501
+ $this->documentFragmentLoadMarkup($fake, $charset, $source);
502
+ }
503
+ return $fake;
504
+ }
505
+ /**
506
+ *
507
+ * @param $document DOMDocumentWrapper
508
+ * @param $markup
509
+ * @return $document
510
+ */
511
+ private function documentFragmentLoadMarkup($fragment, $charset, $markup = null) {
512
+ // TODO error handling
513
+ // TODO copy doctype
514
+ // tempolary turn off
515
+ $fragment->isDocumentFragment = false;
516
+ if ($fragment->isXML) {
517
+ if ($fragment->isXHTML) {
518
+ // add FAKE element to set default namespace
519
+ $fragment->loadMarkupXML('<?xml version="1.0" encoding="'.$charset.'"?>'
520
+ .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
521
+ .'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
522
+ .'<fake xmlns="http://www.w3.org/1999/xhtml">'.$markup.'</fake>');
523
+ $fragment->root = $fragment->document->firstChild->nextSibling;
524
+ } else {
525
+ $fragment->loadMarkupXML('<?xml version="1.0" encoding="'.$charset.'"?><fake>'.$markup.'</fake>');
526
+ $fragment->root = $fragment->document->firstChild;
527
+ }
528
+ } else {
529
+ $markup2 = phpQuery::$defaultDoctype.'<html><head><meta http-equiv="Content-Type" content="text/html;charset='
530
+ .$charset.'"></head>';
531
+ $noBody = strpos($markup, '<body') === false;
532
+ if ($noBody)
533
+ $markup2 .= '<body>';
534
+ $markup2 .= $markup;
535
+ if ($noBody)
536
+ $markup2 .= '</body>';
537
+ $markup2 .= '</html>';
538
+ $fragment->loadMarkupHTML($markup2);
539
+ // TODO resolv body tag merging issue
540
+ $fragment->root = $noBody
541
+ ? $fragment->document->firstChild->nextSibling->firstChild->nextSibling
542
+ : $fragment->document->firstChild->nextSibling->firstChild->nextSibling;
543
+ }
544
+ if (! $fragment->root)
545
+ return false;
546
+ $fragment->isDocumentFragment = true;
547
+ return true;
548
+ }
549
+ protected function documentFragmentToMarkup($fragment) {
550
+ phpQuery::debug('documentFragmentToMarkup');
551
+ $tmp = $fragment->isDocumentFragment;
552
+ $fragment->isDocumentFragment = false;
553
+ $markup = $fragment->markup();
554
+ if ($fragment->isXML) {
555
+ $markup = substr($markup, 0, strrpos($markup, '</fake>'));
556
+ if ($fragment->isXHTML) {
557
+ $markup = substr($markup, strpos($markup, '<fake')+43);
558
+ } else {
559
+ $markup = substr($markup, strpos($markup, '<fake>')+6);
560
+ }
561
+ } else {
562
+ $markup = substr($markup, strpos($markup, '<body>')+6);
563
+ $markup = substr($markup, 0, strrpos($markup, '</body>'));
564
+ }
565
+ $fragment->isDocumentFragment = $tmp;
566
+ if (phpQuery::$debug)
567
+ phpQuery::debug('documentFragmentToMarkup: '.substr($markup, 0, 150));
568
+ return $markup;
569
+ }
570
+ /**
571
+ * Return document markup, starting with optional $nodes as root.
572
+ *
573
+ * @param $nodes DOMNode|DOMNodeList
574
+ * @return string
575
+ */
576
+ public function markup($nodes = null, $innerMarkup = false) {
577
+ if (isset($nodes) && count($nodes) == 1 && $nodes[0] instanceof DOMDOCUMENT)
578
+ $nodes = null;
579
+ if (isset($nodes)) {
580
+ $markup = '';
581
+ if (!is_array($nodes) && !($nodes instanceof DOMNODELIST) )
582
+ $nodes = array($nodes);
583
+ if ($this->isDocumentFragment && ! $innerMarkup)
584
+ foreach($nodes as $i => $node)
585
+ if ($node->isSameNode($this->root)) {
586
+ // var_dump($node);
587
+ $nodes = array_slice($nodes, 0, $i)
588
+ + phpQuery::DOMNodeListToArray($node->childNodes)
589
+ + array_slice($nodes, $i+1);
590
+ }
591
+ if ($this->isXML && ! $innerMarkup) {
592
+ self::debug("Getting outerXML with charset '{$this->charset}'");
593
+ // we need outerXML, so we can benefit from
594
+ // $node param support in saveXML()
595
+ foreach($nodes as $node)
596
+ $markup .= $this->document->saveXML($node);
597
+ } else {
598
+ $loop = array();
599
+ if ($innerMarkup)
600
+ foreach($nodes as $node) {
601
+ if ($node->childNodes)
602
+ foreach($node->childNodes as $child)
603
+ $loop[] = $child;
604
+ else
605
+ $loop[] = $node;
606
+ }
607
+ else
608
+ $loop = $nodes;
609
+ self::debug("Getting markup, moving selected nodes (".count($loop).") to new DocumentFragment");
610
+ $fake = $this->documentFragmentCreate($loop);
611
+ $markup = $this->documentFragmentToMarkup($fake);
612
+ }
613
+ if ($this->isXHTML) {
614
+ self::debug("Fixing XHTML");
615
+ $markup = self::markupFixXHTML($markup);
616
+ }
617
+ self::debug("Markup: ".substr($markup, 0, 250));
618
+ return $markup;
619
+ } else {
620
+ if ($this->isDocumentFragment) {
621
+ // documentFragment, html only...
622
+ self::debug("Getting markup, DocumentFragment detected");
623
+ // return $this->markup(
624
+ //// $this->document->getElementsByTagName('body')->item(0)
625
+ // $this->document->root, true
626
+ // );
627
+ $markup = $this->documentFragmentToMarkup($this);
628
+ // no need for markupFixXHTML, as it's done thought markup($nodes) method
629
+ return $markup;
630
+ } else {
631
+ self::debug("Getting markup (".($this->isXML?'XML':'HTML')."), final with charset '{$this->charset}'");
632
+ $markup = $this->isXML
633
+ ? $this->document->saveXML()
634
+ : $this->document->saveHTML();
635
+ if ($this->isXHTML) {
636
+ self::debug("Fixing XHTML");
637
+ $markup = self::markupFixXHTML($markup);
638
+ }
639
+ self::debug("Markup: ".substr($markup, 0, 250));
640
+ return $markup;
641
+ }
642
+ }
643
+ }
644
+ protected static function markupFixXHTML($markup) {
645
+ $markup = self::expandEmptyTag('script', $markup);
646
+ $markup = self::expandEmptyTag('select', $markup);
647
+ $markup = self::expandEmptyTag('textarea', $markup);
648
+ return $markup;
649
+ }
650
+ public static function debug($text) {
651
+ phpQuery::debug($text);
652
+ }
653
+ /**
654
+ * expandEmptyTag
655
+ *
656
+ * @param $tag
657
+ * @param $xml
658
+ * @return unknown_type
659
+ * @author mjaque at ilkebenson dot com
660
+ * @link http://php.net/manual/en/domdocument.savehtml.php#81256
661
+ */
662
+ public static function expandEmptyTag($tag, $xml){
663
+ $indice = 0;
664
+ while ($indice< strlen($xml)){
665
+ $pos = strpos($xml, "<$tag ", $indice);
666
+ if ($pos){
667
+ $posCierre = strpos($xml, ">", $pos);
668
+ if ($xml[$posCierre-1] == "/"){
669
+ $xml = substr_replace($xml, "></$tag>", $posCierre-1, 2);
670
+ }
671
+ $indice = $posCierre;
672
+ }
673
+ else break;
674
+ }
675
+ return $xml;
676
+ }
677
+ }
includes/phpQuery/phpQuery/DOMEvent.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * DOMEvent class.
4
+ *
5
+ * Based on
6
+ * @link http://developer.mozilla.org/En/DOM:event
7
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
8
+ * @package phpQuery
9
+ * @todo implement ArrayAccess ?
10
+ */
11
+ class DOMEvent {
12
+ /**
13
+ * Returns a boolean indicating whether the event bubbles up through the DOM or not.
14
+ *
15
+ * @var unknown_type
16
+ */
17
+ public $bubbles = true;
18
+ /**
19
+ * Returns a boolean indicating whether the event is cancelable.
20
+ *
21
+ * @var unknown_type
22
+ */
23
+ public $cancelable = true;
24
+ /**
25
+ * Returns a reference to the currently registered target for the event.
26
+ *
27
+ * @var unknown_type
28
+ */
29
+ public $currentTarget;
30
+ /**
31
+ * Returns detail about the event, depending on the type of event.
32
+ *
33
+ * @var unknown_type
34
+ * @link http://developer.mozilla.org/en/DOM/event.detail
35
+ */
36
+ public $detail; // ???
37
+ /**
38
+ * Used to indicate which phase of the event flow is currently being evaluated.
39
+ *
40
+ * NOT IMPLEMENTED
41
+ *
42
+ * @var unknown_type
43
+ * @link http://developer.mozilla.org/en/DOM/event.eventPhase
44
+ */
45
+ public $eventPhase; // ???
46
+ /**
47
+ * The explicit original target of the event (Mozilla-specific).
48
+ *
49
+ * NOT IMPLEMENTED
50
+ *
51
+ * @var unknown_type
52
+ */
53
+ public $explicitOriginalTarget; // moz only
54
+ /**
55
+ * The original target of the event, before any retargetings (Mozilla-specific).
56
+ *
57
+ * NOT IMPLEMENTED
58
+ *
59
+ * @var unknown_type
60
+ */
61
+ public $originalTarget; // moz only
62
+ /**
63
+ * Identifies a secondary target for the event.
64
+ *
65
+ * @var unknown_type
66
+ */
67
+ public $relatedTarget;
68
+ /**
69
+ * Returns a reference to the target to which the event was originally dispatched.
70
+ *
71
+ * @var unknown_type
72
+ */
73
+ public $target;
74
+ /**
75
+ * Returns the time that the event was created.
76
+ *
77
+ * @var unknown_type
78
+ */
79
+ public $timeStamp;
80
+ /**
81
+ * Returns the name of the event (case-insensitive).
82
+ */
83
+ public $type;
84
+ public $runDefault = true;
85
+ public $data = null;
86
+ public function __construct($data) {
87
+ foreach($data as $k => $v) {
88
+ $this->$k = $v;
89
+ }
90
+ if (! $this->timeStamp)
91
+ $this->timeStamp = time();
92
+ }
93
+ /**
94
+ * Cancels the event (if it is cancelable).
95
+ *
96
+ */
97
+ public function preventDefault() {
98
+ $this->runDefault = false;
99
+ }
100
+ /**
101
+ * Stops the propagation of events further along in the DOM.
102
+ *
103
+ */
104
+ public function stopPropagation() {
105
+ $this->bubbles = false;
106
+ }
107
+ }
includes/phpQuery/phpQuery/Zend/Exception.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /**
23
+ * @category Zend
24
+ * @package Zend
25
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
26
+ * @license http://framework.zend.com/license/new-bsd New BSD License
27
+ */
28
+ class Zend_Exception extends Exception
29
+ {}
30
+
includes/phpQuery/phpQuery/Zend/Http/Client.php ADDED
@@ -0,0 +1,1186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Http
18
+ * @subpackage Client
19
+ * @version $Id: Client.php 9906 2008-07-02 21:20:10Z shahar $
20
+ * @copyright Copyright (c) 2005-2008 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 Zend_Loader
26
+ */
27
+ require_once 'Zend/Loader.php';
28
+
29
+
30
+ /**
31
+ * @see Zend_Uri
32
+ */
33
+ require_once 'Zend/Uri.php';
34
+
35
+
36
+ /**
37
+ * @see Zend_Http_Client_Adapter_Interface
38
+ */
39
+ require_once 'Zend/Http/Client/Adapter/Interface.php';
40
+
41
+
42
+ /**
43
+ * @see Zend_Http_Response
44
+ */
45
+ require_once 'Zend/Http/Response.php';
46
+
47
+ /**
48
+ * Zend_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 Zend_Http_CookieJar object)
52
+ *
53
+ * @todo Implement proxy settings
54
+ * @category Zend
55
+ * @package Zend_Http
56
+ * @subpackage Client
57
+ * @throws Zend_Http_Client_Exception
58
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
59
+ * @license http://framework.zend.com/license/new-bsd New BSD License
60
+ */
61
+ class Zend_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
+
75
+ /**
76
+ * Supported HTTP Authentication methods
77
+ */
78
+ const AUTH_BASIC = 'basic';
79
+ //const AUTH_DIGEST = 'digest'; <-- not implemented yet
80
+
81
+ /**
82
+ * HTTP protocol versions
83
+ */
84
+ const HTTP_1 = '1.1';
85
+ const HTTP_0 = '1.0';
86
+
87
+ /**
88
+ * POST data encoding methods
89
+ */
90
+ const ENC_URLENCODED = 'application/x-www-form-urlencoded';
91
+ const ENC_FORMDATA = 'multipart/form-data';
92
+
93
+ /**
94
+ * Configuration array, set using the constructor or using ::setConfig()
95
+ *
96
+ * @var array
97
+ */
98
+ protected $config = array(
99
+ 'maxredirects' => 5,
100
+ 'strictredirects' => false,
101
+ 'useragent' => 'Zend_Http_Client',
102
+ 'timeout' => 10,
103
+ 'adapter' => 'Zend_Http_Client_Adapter_Socket',
104
+ 'httpversion' => self::HTTP_1,
105
+ 'keepalive' => false,
106
+ 'storeresponse' => true,
107
+ 'strict' => true
108
+ );
109
+
110
+ /**
111
+ * The adapter used to preform the actual connection to the server
112
+ *
113
+ * @var Zend_Http_Client_Adapter_Interface
114
+ */
115
+ protected $adapter = null;
116
+
117
+ /**
118
+ * Request URI
119
+ *
120
+ * @var Zend_Uri_Http
121
+ */
122
+ protected $uri;
123
+
124
+ /**
125
+ * Associative array of request headers
126
+ *
127
+ * @var array
128
+ */
129
+ protected $headers = array();
130
+
131
+ /**
132
+ * HTTP request method
133
+ *
134
+ * @var string
135
+ */
136
+ protected $method = self::GET;
137
+
138
+ /**
139
+ * Associative array of GET parameters
140
+ *
141
+ * @var array
142
+ */
143
+ protected $paramsGet = array();
144
+
145
+ /**
146
+ * Assiciative array of POST parameters
147
+ *
148
+ * @var array
149
+ */
150
+ protected $paramsPost = array();
151
+
152
+ /**
153
+ * Request body content type (for POST requests)
154
+ *
155
+ * @var string
156
+ */
157
+ protected $enctype = null;
158
+
159
+ /**
160
+ * The raw post data to send. Could be set by setRawData($data, $enctype).
161
+ *
162
+ * @var string
163
+ */
164
+ protected $raw_post_data = null;
165
+
166
+ /**
167
+ * HTTP Authentication settings
168
+ *
169
+ * Expected to be an associative array with this structure:
170
+ * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic')
171
+ * Where 'type' should be one of the supported authentication types (see the AUTH_*
172
+ * constants), for example 'basic' or 'digest'.
173
+ *
174
+ * If null, no authentication will be used.
175
+ *
176
+ * @var array|null
177
+ */
178
+ protected $auth;
179
+
180
+ /**
181
+ * File upload arrays (used in POST requests)
182
+ *
183
+ * An associative array, where each element is of the format:
184
+ * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents')
185
+ *
186
+ * @var array
187
+ */
188
+ protected $files = array();
189
+
190
+ /**
191
+ * The client's cookie jar
192
+ *
193
+ * @var Zend_Http_CookieJar
194
+ */
195
+ protected $cookiejar = null;
196
+
197
+ /**
198
+ * The last HTTP request sent by the client, as string
199
+ *
200
+ * @var string
201
+ */
202
+ protected $last_request = null;
203
+
204
+ /**
205
+ * The last HTTP response received by the client
206
+ *
207
+ * @var Zend_Http_Response
208
+ */
209
+ protected $last_response = null;
210
+
211
+ /**
212
+ * Redirection counter
213
+ *
214
+ * @var int
215
+ */
216
+ protected $redirectCounter = 0;
217
+
218
+ /**
219
+ * Fileinfo magic database resource
220
+ *
221
+ * This varaiable is populated the first time _detectFileMimeType is called
222
+ * and is then reused on every call to this method
223
+ *
224
+ * @var resource
225
+ */
226
+ static protected $_fileInfoDb = null;
227
+
228
+ /**
229
+ * Contructor method. Will create a new HTTP client. Accepts the target
230
+ * URL and optionally configuration array.
231
+ *
232
+ * @param Zend_Uri_Http|string $uri
233
+ * @param array $config Configuration key-value pairs.
234
+ */
235
+ public function __construct($uri = null, $config = null)
236
+ {
237
+ if ($uri !== null) $this->setUri($uri);
238
+ if ($config !== null) $this->setConfig($config);
239
+ }
240
+
241
+ /**
242
+ * Set the URI for the next request
243
+ *
244
+ * @param Zend_Uri_Http|string $uri
245
+ * @return Zend_Http_Client
246
+ * @throws Zend_Http_Client_Exception
247
+ */
248
+ public function setUri($uri)
249
+ {
250
+ if (is_string($uri)) {
251
+ $uri = Zend_Uri::factory($uri);
252
+ }
253
+
254
+ if (!$uri instanceof Zend_Uri_Http) {
255
+ /** @see Zend_Http_Client_Exception */
256
+ require_once 'Zend/Http/Client/Exception.php';
257
+ throw new Zend_Http_Client_Exception('Passed parameter is not a valid HTTP URI.');
258
+ }
259
+
260
+ // We have no ports, set the defaults
261
+ if (! $uri->getPort()) {
262
+ $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80));
263
+ }
264
+
265
+ $this->uri = $uri;
266
+
267
+ return $this;
268
+ }
269
+
270
+ /**
271
+ * Get the URI for the next request
272
+ *
273
+ * @param boolean $as_string If true, will return the URI as a string
274
+ * @return Zend_Uri_Http|string
275
+ */
276
+ public function getUri($as_string = false)
277
+ {
278
+ if ($as_string && $this->uri instanceof Zend_Uri_Http) {
279
+ return $this->uri->__toString();
280
+ } else {
281
+ return $this->uri;
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Set configuration parameters for this HTTP client
287
+ *
288
+ * @param array $config
289
+ * @return Zend_Http_Client
290
+ * @throws Zend_Http_Client_Exception
291
+ */
292
+ public function setConfig($config = array())
293
+ {
294
+ if (! is_array($config)) {
295
+ /** @see Zend_Http_Client_Exception */
296
+ require_once 'Zend/Http/Client/Exception.php';
297
+ throw new Zend_Http_Client_Exception('Expected array parameter, given ' . gettype($config));
298
+ }
299
+
300
+ foreach ($config as $k => $v)
301
+ $this->config[strtolower($k)] = $v;
302
+
303
+ return $this;
304
+ }
305
+
306
+ /**
307
+ * Set the next request's method
308
+ *
309
+ * Validated the passed method and sets it. If we have files set for
310
+ * POST requests, and the new method is not POST, the files are silently
311
+ * dropped.
312
+ *
313
+ * @param string $method
314
+ * @return Zend_Http_Client
315
+ * @throws Zend_Http_Client_Exception
316
+ */
317
+ public function setMethod($method = self::GET)
318
+ {
319
+ $regex = '/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/';
320
+ if (! preg_match($regex, $method)) {
321
+ /** @see Zend_Http_Client_Exception */
322
+ require_once 'Zend/Http/Client/Exception.php';
323
+ throw new Zend_Http_Client_Exception("'{$method}' is not a valid HTTP request method.");
324
+ }
325
+
326
+ if ($method == self::POST && $this->enctype === null)
327
+ $this->setEncType(self::ENC_URLENCODED);
328
+
329
+ $this->method = $method;
330
+
331
+ return $this;
332
+ }
333
+
334
+ /**
335
+ * Set one or more request headers
336
+ *
337
+ * This function can be used in several ways to set the client's request
338
+ * headers:
339
+ * 1. By providing two parameters: $name as the header to set (eg. 'Host')
340
+ * and $value as it's value (eg. 'www.example.com').
341
+ * 2. By providing a single header string as the only parameter
342
+ * eg. 'Host: www.example.com'
343
+ * 3. By providing an array of headers as the first parameter
344
+ * eg. array('host' => 'www.example.com', 'x-foo: bar'). In This case
345
+ * the function will call itself recursively for each array item.
346
+ *
347
+ * @param string|array $name Header name, full header string ('Header: value')
348
+ * or an array of headers
349
+ * @param mixed $value Header value or null
350
+ * @return Zend_Http_Client
351
+ * @throws Zend_Http_Client_Exception
352
+ */
353
+ public function setHeaders($name, $value = null)
354
+ {
355
+ // If we got an array, go recusive!
356
+ if (is_array($name)) {
357
+ foreach ($name as $k => $v) {
358
+ if (is_string($k)) {
359
+ $this->setHeaders($k, $v);
360
+ } else {
361
+ $this->setHeaders($v, null);
362
+ }
363
+ }
364
+ } else {
365
+ // Check if $name needs to be split
366
+ if ($value === null && (strpos($name, ':') > 0))
367
+ list($name, $value) = explode(':', $name, 2);
368
+
369
+ // Make sure the name is valid if we are in strict mode
370
+ if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) {
371
+ /** @see Zend_Http_Client_Exception */
372
+ require_once 'Zend/Http/Client/Exception.php';
373
+ throw new Zend_Http_Client_Exception("{$name} is not a valid HTTP header name");
374
+ }
375
+
376
+ $normalized_name = strtolower($name);
377
+
378
+ // If $value is null or false, unset the header
379
+ if ($value === null || $value === false) {
380
+ unset($this->headers[$normalized_name]);
381
+
382
+ // Else, set the header
383
+ } else {
384
+ // Header names are storred lowercase internally.
385
+ if (is_string($value)) $value = trim($value);
386
+ $this->headers[$normalized_name] = array($name, $value);
387
+ }
388
+ }
389
+
390
+ return $this;
391
+ }
392
+
393
+ /**
394
+ * Get the value of a specific header
395
+ *
396
+ * Note that if the header has more than one value, an array
397
+ * will be returned.
398
+ *
399
+ * @param string $key
400
+ * @return string|array|null The header value or null if it is not set
401
+ */
402
+ public function getHeader($key)
403
+ {
404
+ $key = strtolower($key);
405
+ if (isset($this->headers[$key])) {
406
+ return $this->headers[$key][1];
407
+ } else {
408
+ return null;
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Set a GET parameter for the request. Wrapper around _setParameter
414
+ *
415
+ * @param string|array $name
416
+ * @param string $value
417
+ * @return Zend_Http_Client
418
+ */
419
+ public function setParameterGet($name, $value = null)
420
+ {
421
+ if (is_array($name)) {
422
+ foreach ($name as $k => $v)
423
+ $this->_setParameter('GET', $k, $v);
424
+ } else {
425
+ $this->_setParameter('GET', $name, $value);
426
+ }
427
+
428
+ return $this;
429
+ }
430
+
431
+ /**
432
+ * Set a POST parameter for the request. Wrapper around _setParameter
433
+ *
434
+ * @param string|array $name
435
+ * @param string $value
436
+ * @return Zend_Http_Client
437
+ */
438
+ public function setParameterPost($name, $value = null)
439
+ {
440
+ if (is_array($name)) {
441
+ foreach ($name as $k => $v)
442
+ $this->_setParameter('POST', $k, $v);
443
+ } else {
444
+ $this->_setParameter('POST', $name, $value);
445
+ }
446
+
447
+ return $this;
448
+ }
449
+
450
+ /**
451
+ * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost
452
+ *
453
+ * @param string $type GET or POST
454
+ * @param string $name
455
+ * @param string $value
456
+ * @return null
457
+ */
458
+ protected function _setParameter($type, $name, $value)
459
+ {
460
+ $parray = array();
461
+ $type = strtolower($type);
462
+ switch ($type) {
463
+ case 'get':
464
+ $parray = &$this->paramsGet;
465
+ break;
466
+ case 'post':
467
+ $parray = &$this->paramsPost;
468
+ break;
469
+ }
470
+
471
+ if ($value === null) {
472
+ if (isset($parray[$name])) unset($parray[$name]);
473
+ } else {
474
+ $parray[$name] = $value;
475
+ }
476
+ }
477
+
478
+ /**
479
+ * Get the number of redirections done on the last request
480
+ *
481
+ * @return int
482
+ */
483
+ public function getRedirectionsCount()
484
+ {
485
+ return $this->redirectCounter;
486
+ }
487
+
488
+ /**
489
+ * Set HTTP authentication parameters
490
+ *
491
+ * $type should be one of the supported types - see the self::AUTH_*
492
+ * constants.
493
+ *
494
+ * To enable authentication:
495
+ * <code>
496
+ * $this->setAuth('shahar', 'secret', Zend_Http_Client::AUTH_BASIC);
497
+ * </code>
498
+ *
499
+ * To disable authentication:
500
+ * <code>
501
+ * $this->setAuth(false);
502
+ * </code>
503
+ *
504
+ * @see http://www.faqs.org/rfcs/rfc2617.html
505
+ * @param string|false $user User name or false disable authentication
506
+ * @param string $password Password
507
+ * @param string $type Authentication type
508
+ * @return Zend_Http_Client
509
+ * @throws Zend_Http_Client_Exception
510
+ */
511
+ public function setAuth($user, $password = '', $type = self::AUTH_BASIC)
512
+ {
513
+ // If we got false or null, disable authentication
514
+ if ($user === false || $user === null) {
515
+ $this->auth = null;
516
+
517
+ // Else, set up authentication
518
+ } else {
519
+ // Check we got a proper authentication type
520
+ if (! defined('self::AUTH_' . strtoupper($type))) {
521
+ /** @see Zend_Http_Client_Exception */
522
+ require_once 'Zend/Http/Client/Exception.php';
523
+ throw new Zend_Http_Client_Exception("Invalid or not supported authentication type: '$type'");
524
+ }
525
+
526
+ $this->auth = array(
527
+ 'user' => (string) $user,
528
+ 'password' => (string) $password,
529
+ 'type' => $type
530
+ );
531
+ }
532
+
533
+ return $this;
534
+ }
535
+
536
+ /**
537
+ * Set the HTTP client's cookie jar.
538
+ *
539
+ * A cookie jar is an object that holds and maintains cookies across HTTP requests
540
+ * and responses.
541
+ *
542
+ * @param Zend_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable
543
+ * @return Zend_Http_Client
544
+ * @throws Zend_Http_Client_Exception
545
+ */
546
+ public function setCookieJar($cookiejar = true)
547
+ {
548
+ if (! class_exists('Zend_Http_CookieJar'))
549
+ require_once 'Zend/Http/CookieJar.php';
550
+
551
+ if ($cookiejar instanceof Zend_Http_CookieJar) {
552
+ $this->cookiejar = $cookiejar;
553
+ } elseif ($cookiejar === true) {
554
+ $this->cookiejar = new Zend_Http_CookieJar();
555
+ } elseif (! $cookiejar) {
556
+ $this->cookiejar = null;
557
+ } else {
558
+ /** @see Zend_Http_Client_Exception */
559
+ require_once 'Zend/Http/Client/Exception.php';
560
+ throw new Zend_Http_Client_Exception('Invalid parameter type passed as CookieJar');
561
+ }
562
+
563
+ return $this;
564
+ }
565
+
566
+ /**
567
+ * Return the current cookie jar or null if none.
568
+ *
569
+ * @return Zend_Http_CookieJar|null
570
+ */
571
+ public function getCookieJar()
572
+ {
573
+ return $this->cookiejar;
574
+ }
575
+
576
+ /**
577
+ * Add a cookie to the request. If the client has no Cookie Jar, the cookies
578
+ * will be added directly to the headers array as "Cookie" headers.
579
+ *
580
+ * @param Zend_Http_Cookie|string $cookie
581
+ * @param string|null $value If "cookie" is a string, this is the cookie value.
582
+ * @return Zend_Http_Client
583
+ * @throws Zend_Http_Client_Exception
584
+ */
585
+ public function setCookie($cookie, $value = null)
586
+ {
587
+ if (! class_exists('Zend_Http_Cookie'))
588
+ require_once 'Zend/Http/Cookie.php';
589
+
590
+ if (is_array($cookie)) {
591
+ foreach ($cookie as $c => $v) {
592
+ if (is_string($c)) {
593
+ $this->setCookie($c, $v);
594
+ } else {
595
+ $this->setCookie($v);
596
+ }
597
+ }
598
+
599
+ return $this;
600
+ }
601
+
602
+ if ($value !== null) $value = urlencode($value);
603
+
604
+ if (isset($this->cookiejar)) {
605
+ if ($cookie instanceof Zend_Http_Cookie) {
606
+ $this->cookiejar->addCookie($cookie);
607
+ } elseif (is_string($cookie) && $value !== null) {
608
+ $cookie = Zend_Http_Cookie::fromString("{$cookie}={$value}", $this->uri);
609
+ $this->cookiejar->addCookie($cookie);
610
+ }
611
+ } else {
612
+ if ($cookie instanceof Zend_Http_Cookie) {
613
+ $name = $cookie->getName();
614
+ $value = $cookie->getValue();
615
+ $cookie = $name;
616
+ }
617
+
618
+ if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) {
619
+ /** @see Zend_Http_Client_Exception */
620
+ require_once 'Zend/Http/Client/Exception.php';
621
+ throw new Zend_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})");
622
+ }
623
+
624
+ $value = addslashes($value);
625
+
626
+ if (! isset($this->headers['cookie'])) $this->headers['cookie'] = array('Cookie', '');
627
+ $this->headers['cookie'][1] .= $cookie . '=' . $value . '; ';
628
+ }
629
+
630
+ return $this;
631
+ }
632
+
633
+ /**
634
+ * Set a file to upload (using a POST request)
635
+ *
636
+ * Can be used in two ways:
637
+ *
638
+ * 1. $data is null (default): $filename is treated as the name if a local file which
639
+ * will be read and sent. Will try to guess the content type using mime_content_type().
640
+ * 2. $data is set - $filename is sent as the file name, but $data is sent as the file
641
+ * contents and no file is read from the file system. In this case, you need to
642
+ * manually set the content-type ($ctype) or it will default to
643
+ * application/octet-stream.
644
+ *
645
+ * @param string $filename Name of file to upload, or name to save as
646
+ * @param string $formname Name of form element to send as
647
+ * @param string $data Data to send (if null, $filename is read and sent)
648
+ * @param string $ctype Content type to use (if $data is set and $ctype is
649
+ * null, will be application/octet-stream)
650
+ * @return Zend_Http_Client
651
+ * @throws Zend_Http_Client_Exception
652
+ */
653
+ public function setFileUpload($filename, $formname, $data = null, $ctype = null)
654
+ {
655
+ if ($data === null) {
656
+ if (($data = @file_get_contents($filename)) === false) {
657
+ /** @see Zend_Http_Client_Exception */
658
+ require_once 'Zend/Http/Client/Exception.php';
659
+ throw new Zend_Http_Client_Exception("Unable to read file '{$filename}' for upload");
660
+ }
661
+
662
+ if (! $ctype) $ctype = $this->_detectFileMimeType($filename);
663
+ }
664
+
665
+ // Force enctype to multipart/form-data
666
+ $this->setEncType(self::ENC_FORMDATA);
667
+
668
+ $this->files[$formname] = array(basename($filename), $ctype, $data);
669
+
670
+ return $this;
671
+ }
672
+
673
+ /**
674
+ * Set the encoding type for POST data
675
+ *
676
+ * @param string $enctype
677
+ * @return Zend_Http_Client
678
+ */
679
+ public function setEncType($enctype = self::ENC_URLENCODED)
680
+ {
681
+ $this->enctype = $enctype;
682
+
683
+ return $this;
684
+ }
685
+
686
+ /**
687
+ * Set the raw (already encoded) POST data.
688
+ *
689
+ * This function is here for two reasons:
690
+ * 1. For advanced user who would like to set their own data, already encoded
691
+ * 2. For backwards compatibilty: If someone uses the old post($data) method.
692
+ * this method will be used to set the encoded data.
693
+ *
694
+ * @param string $data
695
+ * @param string $enctype
696
+ * @return Zend_Http_Client
697
+ */
698
+ public function setRawData($data, $enctype = null)
699
+ {
700
+ $this->raw_post_data = $data;
701
+ $this->setEncType($enctype);
702
+
703
+ return $this;
704
+ }
705
+
706
+ /**
707
+ * Clear all GET and POST parameters
708
+ *
709
+ * Should be used to reset the request parameters if the client is
710
+ * used for several concurrent requests.
711
+ *
712
+ * @return Zend_Http_Client
713
+ */
714
+ public function resetParameters()
715
+ {
716
+ // Reset parameter data
717
+ $this->paramsGet = array();
718
+ $this->paramsPost = array();
719
+ $this->files = array();
720
+ $this->raw_post_data = null;
721
+
722
+ // Clear outdated headers
723
+ if (isset($this->headers['content-type'])) unset($this->headers['content-type']);
724
+ if (isset($this->headers['content-length'])) unset($this->headers['content-length']);
725
+
726
+ return $this;
727
+ }
728
+
729
+ /**
730
+ * Get the last HTTP request as string
731
+ *
732
+ * @return string
733
+ */
734
+ public function getLastRequest()
735
+ {
736
+ return $this->last_request;
737
+ }
738
+
739
+ /**
740
+ * Get the last HTTP response received by this client
741
+ *
742
+ * If $config['storeresponse'] is set to false, or no response was
743
+ * stored yet, will return null
744
+ *
745
+ * @return Zend_Http_Response or null if none
746
+ */
747
+ public function getLastResponse()
748
+ {
749
+ return $this->last_response;
750
+ }
751
+
752
+ /**
753
+ * Load the connection adapter
754
+ *
755
+ * While this method is not called more than one for a client, it is
756
+ * seperated from ->request() to preserve logic and readability
757
+ *
758
+ * @param Zend_Http_Client_Adapter_Interface|string $adapter
759
+ * @return null
760
+ * @throws Zend_Http_Client_Exception
761
+ */
762
+ public function setAdapter($adapter)
763
+ {
764
+ if (is_string($adapter)) {
765
+ try {
766
+ Zend_Loader::loadClass($adapter);
767
+ } catch (Zend_Exception $e) {
768
+ /** @see Zend_Http_Client_Exception */
769
+ require_once 'Zend/Http/Client/Exception.php';
770
+ throw new Zend_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}");
771
+ }
772
+
773
+ $adapter = new $adapter;
774
+ }
775
+
776
+ if (! $adapter instanceof Zend_Http_Client_Adapter_Interface) {
777
+ /** @see Zend_Http_Client_Exception */
778
+ require_once 'Zend/Http/Client/Exception.php';
779
+ throw new Zend_Http_Client_Exception('Passed adapter is not a HTTP connection adapter');
780
+ }
781
+
782
+ $this->adapter = $adapter;
783
+ $config = $this->config;
784
+ unset($config['adapter']);
785
+ $this->adapter->setConfig($config);
786
+ }
787
+
788
+ /**
789
+ * Send the HTTP request and return an HTTP response object
790
+ *
791
+ * @param string $method
792
+ * @return Zend_Http_Response
793
+ * @throws Zend_Http_Client_Exception
794
+ */
795
+ public function request($method = null)
796
+ {
797
+ if (! $this->uri instanceof Zend_Uri_Http) {
798
+ /** @see Zend_Http_Client_Exception */
799
+ require_once 'Zend/Http/Client/Exception.php';
800
+ throw new Zend_Http_Client_Exception('No valid URI has been passed to the client');
801
+ }
802
+
803
+ if ($method) $this->setMethod($method);
804
+ $this->redirectCounter = 0;
805
+ $response = null;
806
+
807
+ // Make sure the adapter is loaded
808
+ if ($this->adapter == null) $this->setAdapter($this->config['adapter']);
809
+
810
+ // Send the first request. If redirected, continue.
811
+ do {
812
+ // Clone the URI and add the additional GET parameters to it
813
+ $uri = clone $this->uri;
814
+ if (! empty($this->paramsGet)) {
815
+ $query = $uri->getQuery();
816
+ if (! empty($query)) $query .= '&';
817
+ $query .= http_build_query($this->paramsGet, null, '&');
818
+
819
+ $uri->setQuery($query);
820
+ }
821
+
822
+ $body = $this->_prepareBody();
823
+ $headers = $this->_prepareHeaders();
824
+
825
+ // Open the connection, send the request and read the response
826
+ $this->adapter->connect($uri->getHost(), $uri->getPort(),
827
+ ($uri->getScheme() == 'https' ? true : false));
828
+
829
+ $this->last_request = $this->adapter->write($this->method,
830
+ $uri, $this->config['httpversion'], $headers, $body);
831
+
832
+ $response = $this->adapter->read();
833
+ if (! $response) {
834
+ /** @see Zend_Http_Client_Exception */
835
+ require_once 'Zend/Http/Client/Exception.php';
836
+ throw new Zend_Http_Client_Exception('Unable to read response, or response is empty');
837
+ }
838
+
839
+ $response = Zend_Http_Response::fromString($response);
840
+ if ($this->config['storeresponse']) $this->last_response = $response;
841
+
842
+ // Load cookies into cookie jar
843
+ if (isset($this->cookiejar)) $this->cookiejar->addCookiesFromResponse($response, $uri);
844
+
845
+ // If we got redirected, look for the Location header
846
+ if ($response->isRedirect() && ($location = $response->getHeader('location'))) {
847
+
848
+ // Check whether we send the exact same request again, or drop the parameters
849
+ // and send a GET request
850
+ if ($response->getStatus() == 303 ||
851
+ ((! $this->config['strictredirects']) && ($response->getStatus() == 302 ||
852
+ $response->getStatus() == 301))) {
853
+
854
+ $this->resetParameters();
855
+ $this->setMethod(self::GET);
856
+ }
857
+
858
+ // If we got a well formed absolute URI
859
+ if (Zend_Uri_Http::check($location)) {
860
+ $this->setHeaders('host', null);
861
+ $this->setUri($location);
862
+
863
+ } else {
864
+
865
+ // Split into path and query and set the query
866
+ if (strpos($location, '?') !== false) {
867
+ list($location, $query) = explode('?', $location, 2);
868
+ } else {
869
+ $query = '';
870
+ }
871
+ $this->uri->setQuery($query);
872
+
873
+ // Else, if we got just an absolute path, set it
874
+ if(strpos($location, '/') === 0) {
875
+ $this->uri->setPath($location);
876
+
877
+ // Else, assume we have a relative path
878
+ } else {
879
+ // Get the current path directory, removing any trailing slashes
880
+ $path = $this->uri->getPath();
881
+ $path = rtrim(substr($path, 0, strrpos($path, '/')), "/");
882
+ $this->uri->setPath($path . '/' . $location);
883
+ }
884
+ }
885
+ ++$this->redirectCounter;
886
+
887
+ } else {
888
+ // If we didn't get any location, stop redirecting
889
+ break;
890
+ }
891
+
892
+ } while ($this->redirectCounter < $this->config['maxredirects']);
893
+
894
+ return $response;
895
+ }
896
+
897
+ /**
898
+ * Prepare the request headers
899
+ *
900
+ * @return array
901
+ */
902
+ protected function _prepareHeaders()
903
+ {
904
+ $headers = array();
905
+
906
+ // Set the host header
907
+ if (! isset($this->headers['host'])) {
908
+ $host = $this->uri->getHost();
909
+
910
+ // If the port is not default, add it
911
+ if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) ||
912
+ ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) {
913
+ $host .= ':' . $this->uri->getPort();
914
+ }
915
+
916
+ $headers[] = "Host: {$host}";
917
+ }
918
+
919
+ // Set the connection header
920
+ if (! isset($this->headers['connection'])) {
921
+ if (! $this->config['keepalive']) $headers[] = "Connection: close";
922
+ }
923
+
924
+ // Set the Accept-encoding header if not set - depending on whether
925
+ // zlib is available or not.
926
+ if (! isset($this->headers['accept-encoding'])) {
927
+ if (function_exists('gzinflate')) {
928
+ $headers[] = 'Accept-encoding: gzip, deflate';
929
+ } else {
930
+ $headers[] = 'Accept-encoding: identity';
931
+ }
932
+ }
933
+
934
+ // Set the content-type header
935
+ if ($this->method == self::POST &&
936
+ (! isset($this->headers['content-type']) && isset($this->enctype))) {
937
+
938
+ $headers[] = "Content-type: {$this->enctype}";
939
+ }
940
+
941
+ // Set the user agent header
942
+ if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) {
943
+ $headers[] = "User-agent: {$this->config['useragent']}";
944
+ }
945
+
946
+ // Set HTTP authentication if needed
947
+ if (is_array($this->auth)) {
948
+ $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']);
949
+ $headers[] = "Authorization: {$auth}";
950
+ }
951
+
952
+ // Load cookies from cookie jar
953
+ if (isset($this->cookiejar)) {
954
+ $cookstr = $this->cookiejar->getMatchingCookies($this->uri,
955
+ true, Zend_Http_CookieJar::COOKIE_STRING_CONCAT);
956
+
957
+ if ($cookstr) $headers[] = "Cookie: {$cookstr}";
958
+ }
959
+
960
+ // Add all other user defined headers
961
+ foreach ($this->headers as $header) {
962
+ list($name, $value) = $header;
963
+ if (is_array($value))
964
+ $value = implode(', ', $value);
965
+
966
+ $headers[] = "$name: $value";
967
+ }
968
+
969
+ return $headers;
970
+ }
971
+
972
+ /**
973
+ * Prepare the request body (for POST and PUT requests)
974
+ *
975
+ * @return string
976
+ * @throws Zend_Http_Client_Exception
977
+ */
978
+ protected function _prepareBody()
979
+ {
980
+ // According to RFC2616, a TRACE request should not have a body.
981
+ if ($this->method == self::TRACE) {
982
+ return '';
983
+ }
984
+
985
+ // If we have raw_post_data set, just use it as the body.
986
+ if (isset($this->raw_post_data)) {
987
+ $this->setHeaders('Content-length', strlen($this->raw_post_data));
988
+ return $this->raw_post_data;
989
+ }
990
+
991
+ $body = '';
992
+
993
+ // If we have files to upload, force enctype to multipart/form-data
994
+ if (count ($this->files) > 0) $this->setEncType(self::ENC_FORMDATA);
995
+
996
+ // If we have POST parameters or files, encode and add them to the body
997
+ if (count($this->paramsPost) > 0 || count($this->files) > 0) {
998
+ switch($this->enctype) {
999
+ case self::ENC_FORMDATA:
1000
+ // Encode body as multipart/form-data
1001
+ $boundary = '---ZENDHTTPCLIENT-' . md5(microtime());
1002
+ $this->setHeaders('Content-type', self::ENC_FORMDATA . "; boundary={$boundary}");
1003
+
1004
+ // Get POST parameters and encode them
1005
+ $params = $this->_getParametersRecursive($this->paramsPost);
1006
+ foreach ($params as $pp) {
1007
+ $body .= self::encodeFormData($boundary, $pp[0], $pp[1]);
1008
+ }
1009
+
1010
+ // Encode files
1011
+ foreach ($this->files as $name => $file) {
1012
+ $fhead = array('Content-type' => $file[1]);
1013
+ $body .= self::encodeFormData($boundary, $name, $file[2], $file[0], $fhead);
1014
+ }
1015
+
1016
+ $body .= "--{$boundary}--\r\n";
1017
+ break;
1018
+
1019
+ case self::ENC_URLENCODED:
1020
+ // Encode body as application/x-www-form-urlencoded
1021
+ $this->setHeaders('Content-type', self::ENC_URLENCODED);
1022
+ $body = http_build_query($this->paramsPost, '', '&');
1023
+ break;
1024
+
1025
+ default:
1026
+ /** @see Zend_Http_Client_Exception */
1027
+ require_once 'Zend/Http/Client/Exception.php';
1028
+ throw new Zend_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." .
1029
+ " Please use Zend_Http_Client::setRawData to send this kind of content.");
1030
+ break;
1031
+ }
1032
+ }
1033
+
1034
+ // Set the content-length if we have a body or if request is POST/PUT
1035
+ if ($body || $this->method == self::POST || $this->method == self::PUT) {
1036
+ $this->setHeaders('Content-length', strlen($body));
1037
+ }
1038
+
1039
+ return $body;
1040
+ }
1041
+
1042
+ /**
1043
+ * Helper method that gets a possibly multi-level parameters array (get or
1044
+ * post) and flattens it.
1045
+ *
1046
+ * The method returns an array of (key, value) pairs (because keys are not
1047
+ * necessarily unique. If one of the parameters in as array, it will also
1048
+ * add a [] suffix to the key.
1049
+ *
1050
+ * @param array $parray The parameters array
1051
+ * @param bool $urlencode Whether to urlencode the name and value
1052
+ * @return array
1053
+ */
1054
+ protected function _getParametersRecursive($parray, $urlencode = false)
1055
+ {
1056
+ if (! is_array($parray)) return $parray;
1057
+ $parameters = array();
1058
+
1059
+ foreach ($parray as $name => $value) {
1060
+ if ($urlencode) $name = urlencode($name);
1061
+
1062
+ // If $value is an array, iterate over it
1063
+ if (is_array($value)) {
1064
+ $name .= ($urlencode ? '%5B%5D' : '[]');
1065
+ foreach ($value as $subval) {
1066
+ if ($urlencode) $subval = urlencode($subval);
1067
+ $parameters[] = array($name, $subval);
1068
+ }
1069
+ } else {
1070
+ if ($urlencode) $value = urlencode($value);
1071
+ $parameters[] = array($name, $value);
1072
+ }
1073
+ }
1074
+
1075
+ return $parameters;
1076
+ }
1077
+
1078
+ /**
1079
+ * Attempt to detect the MIME type of a file using available extensions
1080
+ *
1081
+ * This method will try to detect the MIME type of a file. If the fileinfo
1082
+ * extension is available, it will be used. If not, the mime_magic
1083
+ * extension which is deprected but is still available in many PHP setups
1084
+ * will be tried.
1085
+ *
1086
+ * If neither extension is available, the default application/octet-stream
1087
+ * MIME type will be returned
1088
+ *
1089
+ * @param string $file File path
1090
+ * @return string MIME type
1091
+ */
1092
+ protected function _detectFileMimeType($file)
1093
+ {
1094
+ $type = null;
1095
+
1096
+ // First try with fileinfo functions
1097
+ if (function_exists('finfo_open')) {
1098
+ if (self::$_fileInfoDb === null) {
1099
+ self::$_fileInfoDb = @finfo_open(FILEINFO_MIME);
1100
+ }
1101
+
1102
+ if (self::$_fileInfoDb) {
1103
+ $type = finfo_file(self::$_fileInfoDb, $file);
1104
+ }
1105
+
1106
+ } elseif (function_exists('mime_content_type')) {
1107
+ $type = mime_content_type($file);
1108
+ }
1109
+
1110
+ // Fallback to the default application/octet-stream
1111
+ if (! $type) {
1112
+ $type = 'application/octet-stream';
1113
+ }
1114
+
1115
+ return $type;
1116
+ }
1117
+
1118
+ /**
1119
+ * Encode data to a multipart/form-data part suitable for a POST request.
1120
+ *
1121
+ * @param string $boundary
1122
+ * @param string $name
1123
+ * @param mixed $value
1124
+ * @param string $filename
1125
+ * @param array $headers Associative array of optional headers @example ("Content-transfer-encoding" => "binary")
1126
+ * @return string
1127
+ */
1128
+ public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) {
1129
+ $ret = "--{$boundary}\r\n" .
1130
+ 'Content-disposition: form-data; name="' . $name .'"';
1131
+
1132
+ if ($filename) $ret .= '; filename="' . $filename . '"';
1133
+ $ret .= "\r\n";
1134
+
1135
+ foreach ($headers as $hname => $hvalue) {
1136
+ $ret .= "{$hname}: {$hvalue}\r\n";
1137
+ }
1138
+ $ret .= "\r\n";
1139
+
1140
+ $ret .= "{$value}\r\n";
1141
+
1142
+ return $ret;
1143
+ }
1144
+
1145
+ /**
1146
+ * Create a HTTP authentication "Authorization:" header according to the
1147
+ * specified user, password and authentication method.
1148
+ *
1149
+ * @see http://www.faqs.org/rfcs/rfc2617.html
1150
+ * @param string $user
1151
+ * @param string $password
1152
+ * @param string $type
1153
+ * @return string
1154
+ * @throws Zend_Http_Client_Exception
1155
+ */
1156
+ public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC)
1157
+ {
1158
+ $authHeader = null;
1159
+
1160
+ switch ($type) {
1161
+ case self::AUTH_BASIC:
1162
+ // In basic authentication, the user name cannot contain ":"
1163
+ if (strpos($user, ':') !== false) {
1164
+ /** @see Zend_Http_Client_Exception */
1165
+ require_once 'Zend/Http/Client/Exception.php';
1166
+ throw new Zend_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication");
1167
+ }
1168
+
1169
+ $authHeader = 'Basic ' . base64_encode($user . ':' . $password);
1170
+ break;
1171
+
1172
+ //case self::AUTH_DIGEST:
1173
+ /**
1174
+ * @todo Implement digest authentication
1175
+ */
1176
+ // break;
1177
+
1178
+ default:
1179
+ /** @see Zend_Http_Client_Exception */
1180
+ require_once 'Zend/Http/Client/Exception.php';
1181
+ throw new Zend_Http_Client_Exception("Not a supported HTTP authentication type: '$type'");
1182
+ }
1183
+
1184
+ return $authHeader;
1185
+ }
1186
+ }
includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Exception.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Http
17
+ * @subpackage Client_Adapter_Exception
18
+ * @version $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once 'Zend/Http/Client/Exception.php';
24
+
25
+ /**
26
+ * @category Zend
27
+ * @package Zend_Http
28
+ * @subpackage Client_Adapter
29
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
30
+ * @license http://framework.zend.com/license/new-bsd New BSD License
31
+ */
32
+ class Zend_Http_Client_Adapter_Exception extends Zend_Http_Client_Exception
33
+ {}
includes/phpQuery/phpQuery/Zend/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 Zend
17
+ * @package Zend_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $
20
+ * @copyright Copyright (c) 2005-2008 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 Zend_Http_Client_Adapter classes.
26
+ *
27
+ * These classes are used as connectors for Zend_Http_Client, performing the
28
+ * tasks of connecting, writing, reading and closing connection to the server.
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Http
32
+ * @subpackage Client_Adapter
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ interface Zend_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 Zend_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
+ }
includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Proxy.php ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Proxy.php 9868 2008-07-02 06:47:38Z shahar $
20
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ require_once 'Zend/Uri/Http.php';
25
+ require_once 'Zend/Http/Client.php';
26
+ require_once 'Zend/Http/Client/Adapter/Socket.php';
27
+
28
+ /**
29
+ * HTTP Proxy-supporting Zend_Http_Client adapter class, based on the default
30
+ * socket based adapter.
31
+ *
32
+ * Should be used if proxy HTTP access is required. If no proxy is set, will
33
+ * fall back to Zend_Http_Client_Adapter_Socket behavior. Just like the
34
+ * default Socket adapter, this adapter does not require any special extensions
35
+ * installed.
36
+ *
37
+ * @category Zend
38
+ * @package Zend_Http
39
+ * @subpackage Client_Adapter
40
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
41
+ * @license http://framework.zend.com/license/new-bsd New BSD License
42
+ */
43
+ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
44
+ {
45
+ /**
46
+ * Parameters array
47
+ *
48
+ * @var array
49
+ */
50
+ protected $config = array(
51
+ 'ssltransport' => 'ssl',
52
+ 'proxy_host' => '',
53
+ 'proxy_port' => 8080,
54
+ 'proxy_user' => '',
55
+ 'proxy_pass' => '',
56
+ 'proxy_auth' => Zend_Http_Client::AUTH_BASIC,
57
+ 'persistent' => false
58
+ );
59
+
60
+ /**
61
+ * Whether HTTPS CONNECT was already negotiated with the proxy or not
62
+ *
63
+ * @var boolean
64
+ */
65
+ protected $negotiated = false;
66
+
67
+ /**
68
+ * Connect to the remote server
69
+ *
70
+ * Will try to connect to the proxy server. If no proxy was set, will
71
+ * fall back to the target server (behave like regular Socket adapter)
72
+ *
73
+ * @param string $host
74
+ * @param int $port
75
+ * @param boolean $secure
76
+ * @param int $timeout
77
+ */
78
+ public function connect($host, $port = 80, $secure = false)
79
+ {
80
+ // If no proxy is set, fall back to Socket adapter
81
+ if (! $this->config['proxy_host']) return parent::connect($host, $port, $secure);
82
+
83
+ // Go through a proxy - the connection is actually to the proxy server
84
+ $host = $this->config['proxy_host'];
85
+ $port = $this->config['proxy_port'];
86
+
87
+ // If we are connected to the wrong proxy, disconnect first
88
+ if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
89
+ if (is_resource($this->socket)) $this->close();
90
+ }
91
+
92
+ // Now, if we are not connected, connect
93
+ if (! is_resource($this->socket) || ! $this->config['keepalive']) {
94
+ $this->socket = @fsockopen($host, $port, $errno, $errstr, (int) $this->config['timeout']);
95
+ if (! $this->socket) {
96
+ $this->close();
97
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
98
+ throw new Zend_Http_Client_Adapter_Exception(
99
+ 'Unable to Connect to proxy server ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
100
+ }
101
+
102
+ // Set the stream timeout
103
+ if (!stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
104
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
105
+ throw new Zend_Http_Client_Adapter_Exception('Unable to set the connection timeout');
106
+ }
107
+
108
+ // Update connected_to
109
+ $this->connected_to = array($host, $port);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Send request to the proxy server
115
+ *
116
+ * @param string $method
117
+ * @param Zend_Uri_Http $uri
118
+ * @param string $http_ver
119
+ * @param array $headers
120
+ * @param string $body
121
+ * @return string Request as string
122
+ */
123
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
124
+ {
125
+ // If no proxy is set, fall back to default Socket adapter
126
+ if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body);
127
+
128
+ // Make sure we're properly connected
129
+ if (! $this->socket) {
130
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
131
+ throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
132
+ }
133
+
134
+ $host = $this->config['proxy_host'];
135
+ $port = $this->config['proxy_port'];
136
+
137
+ if ($this->connected_to[0] != $host || $this->connected_to[1] != $port) {
138
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
139
+ throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
140
+ }
141
+
142
+ // Add Proxy-Authorization header
143
+ if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization']))
144
+ $headers['proxy-authorization'] = Zend_Http_Client::encodeAuthHeader(
145
+ $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth']
146
+ );
147
+
148
+ // if we are proxying HTTPS, preform CONNECT handshake with the proxy
149
+ if ($uri->getScheme() == 'https' && (! $this->negotiated)) {
150
+ $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers);
151
+ $this->negotiated = true;
152
+ }
153
+
154
+ // Save request method for later
155
+ $this->method = $method;
156
+
157
+ // Build request headers
158
+ $request = "{$method} {$uri->__toString()} HTTP/{$http_ver}\r\n";
159
+
160
+ // Add all headers to the request string
161
+ foreach ($headers as $k => $v) {
162
+ if (is_string($k)) $v = "$k: $v";
163
+ $request .= "$v\r\n";
164
+ }
165
+
166
+ // Add the request body
167
+ $request .= "\r\n" . $body;
168
+
169
+ // Send the request
170
+ if (! @fwrite($this->socket, $request)) {
171
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
172
+ throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
173
+ }
174
+
175
+ return $request;
176
+ }
177
+
178
+ /**
179
+ * Preform handshaking with HTTPS proxy using CONNECT method
180
+ *
181
+ * @param string $host
182
+ * @param integer $port
183
+ * @param string $http_ver
184
+ * @param array $headers
185
+ */
186
+ protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
187
+ {
188
+ $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
189
+ "Host: " . $this->config['proxy_host'] . "\r\n";
190
+
191
+ // Add the user-agent header
192
+ if (isset($this->config['useragent'])) {
193
+ $request .= "User-agent: " . $this->config['useragent'] . "\r\n";
194
+ }
195
+
196
+ // If the proxy-authorization header is set, send it to proxy but remove
197
+ // it from headers sent to target host
198
+ if (isset($headers['proxy-authorization'])) {
199
+ $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n";
200
+ unset($headers['proxy-authorization']);
201
+ }
202
+
203
+ $request .= "\r\n";
204
+
205
+ // Send the request
206
+ if (! @fwrite($this->socket, $request)) {
207
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
208
+ throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
209
+ }
210
+
211
+ // Read response headers only
212
+ $response = '';
213
+ $gotStatus = false;
214
+ while ($line = @fgets($this->socket)) {
215
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
216
+ if ($gotStatus) {
217
+ $response .= $line;
218
+ if (!chop($line)) break;
219
+ }
220
+ }
221
+
222
+ // Check that the response from the proxy is 200
223
+ if (Zend_Http_Response::extractCode($response) != 200) {
224
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
225
+ throw new Zend_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
226
+ }
227
+
228
+ // If all is good, switch socket to secure mode. We have to fall back
229
+ // through the different modes
230
+ $modes = array(
231
+ STREAM_CRYPTO_METHOD_TLS_CLIENT,
232
+ STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
233
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
234
+ STREAM_CRYPTO_METHOD_SSLv2_CLIENT
235
+ );
236
+
237
+ $success = false;
238
+ foreach($modes as $mode) {
239
+ $success = stream_socket_enable_crypto($this->socket, true, $mode);
240
+ if ($success) break;
241
+ }
242
+
243
+ if (! $success) {
244
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
245
+ throw new Zend_Http_Client_Adapter_Exception("Unable to connect to" .
246
+ " HTTPS server through proxy: could not negotiate secure connection.");
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Close the connection to the server
252
+ *
253
+ */
254
+ public function close()
255
+ {
256
+ parent::close();
257
+ $this->negotiated = false;
258
+ }
259
+
260
+ /**
261
+ * Destructor: make sure the socket is disconnected
262
+ *
263
+ */
264
+ public function __destruct()
265
+ {
266
+ if ($this->socket) $this->close();
267
+ }
268
+ }
includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Socket.php ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Socket.php 9870 2008-07-02 07:28:04Z shahar $
20
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ require_once 'Zend/Uri/Http.php';
25
+ require_once 'Zend/Http/Client/Adapter/Interface.php';
26
+
27
+ /**
28
+ * A sockets based (stream_socket_client) adapter class for Zend_Http_Client. Can be used
29
+ * on almost every PHP environment, and does not require any special extensions.
30
+ *
31
+ * @category Zend
32
+ * @package Zend_Http
33
+ * @subpackage Client_Adapter
34
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
35
+ * @license http://framework.zend.com/license/new-bsd New BSD License
36
+ */
37
+ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interface
38
+ {
39
+ /**
40
+ * The socket for server connection
41
+ *
42
+ * @var resource|null
43
+ */
44
+ protected $socket = null;
45
+
46
+ /**
47
+ * What host/port are we connected to?
48
+ *
49
+ * @var array
50
+ */
51
+ protected $connected_to = array(null, null);
52
+
53
+ /**
54
+ * Parameters array
55
+ *
56
+ * @var array
57
+ */
58
+ protected $config = array(
59
+ 'persistent' => false,
60
+ 'ssltransport' => 'ssl',
61
+ 'sslcert' => null,
62
+ 'sslpassphrase' => null
63
+ );
64
+
65
+ /**
66
+ * Request method - will be set by write() and might be used by read()
67
+ *
68
+ * @var string
69
+ */
70
+ protected $method = null;
71
+
72
+ /**
73
+ * Adapter constructor, currently empty. Config is set using setConfig()
74
+ *
75
+ */
76
+ public function __construct()
77
+ {
78
+ }
79
+
80
+ /**
81
+ * Set the configuration array for the adapter
82
+ *
83
+ * @param array $config
84
+ */
85
+ public function setConfig($config = array())
86
+ {
87
+ if (! is_array($config)) {
88
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
89
+ throw new Zend_Http_Client_Adapter_Exception(
90
+ '$config expects an array, ' . gettype($config) . ' recieved.');
91
+ }
92
+
93
+ foreach ($config as $k => $v) {
94
+ $this->config[strtolower($k)] = $v;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Connect to the remote server
100
+ *
101
+ * @param string $host
102
+ * @param int $port
103
+ * @param boolean $secure
104
+ * @param int $timeout
105
+ */
106
+ public function connect($host, $port = 80, $secure = false)
107
+ {
108
+ // If the URI should be accessed via SSL, prepend the Hostname with ssl://
109
+ $host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
110
+
111
+ // If we are connected to the wrong host, disconnect first
112
+ if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
113
+ if (is_resource($this->socket)) $this->close();
114
+ }
115
+
116
+ // Now, if we are not connected, connect
117
+ if (! is_resource($this->socket) || ! $this->config['keepalive']) {
118
+ $context = stream_context_create();
119
+ if ($secure) {
120
+ if ($this->config['sslcert'] !== null) {
121
+ if (! stream_context_set_option($context, 'ssl', 'local_cert',
122
+ $this->config['sslcert'])) {
123
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
124
+ throw new Zend_Http_Client_Adapter_Exception('Unable to set sslcert option');
125
+ }
126
+ }
127
+ if ($this->config['sslpassphrase'] !== null) {
128
+ if (! stream_context_set_option($context, 'ssl', 'passphrase',
129
+ $this->config['sslpassphrase'])) {
130
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
131
+ throw new Zend_Http_Client_Adapter_Exception('Unable to set sslpassphrase option');
132
+ }
133
+ }
134
+ }
135
+
136
+ $flags = STREAM_CLIENT_CONNECT;
137
+ if ($this->config['persistent']) $flags |= STREAM_CLIENT_PERSISTENT;
138
+
139
+ $this->socket = @stream_socket_client($host . ':' . $port,
140
+ $errno,
141
+ $errstr,
142
+ (int) $this->config['timeout'],
143
+ $flags,
144
+ $context);
145
+ if (! $this->socket) {
146
+ $this->close();
147
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
148
+ throw new Zend_Http_Client_Adapter_Exception(
149
+ 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
150
+ }
151
+
152
+ // Set the stream timeout
153
+ if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
154
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
155
+ throw new Zend_Http_Client_Adapter_Exception('Unable to set the connection timeout');
156
+ }
157
+
158
+ // Update connected_to
159
+ $this->connected_to = array($host, $port);
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Send request to the remote server
165
+ *
166
+ * @param string $method
167
+ * @param Zend_Uri_Http $uri
168
+ * @param string $http_ver
169
+ * @param array $headers
170
+ * @param string $body
171
+ * @return string Request as string
172
+ */
173
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
174
+ {
175
+ // Make sure we're properly connected
176
+ if (! $this->socket) {
177
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
178
+ throw new Zend_Http_Client_Adapter_Exception('Trying to write but we are not connected');
179
+ }
180
+
181
+ $host = $uri->getHost();
182
+ $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
183
+ if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) {
184
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
185
+ throw new Zend_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host');
186
+ }
187
+
188
+ // Save request method for later
189
+ $this->method = $method;
190
+
191
+ // Build request headers
192
+ $path = $uri->getPath();
193
+ if ($uri->getQuery()) $path .= '?' . $uri->getQuery();
194
+ $request = "{$method} {$path} HTTP/{$http_ver}\r\n";
195
+ foreach ($headers as $k => $v) {
196
+ if (is_string($k)) $v = ucfirst($k) . ": $v";
197
+ $request .= "$v\r\n";
198
+ }
199
+
200
+ // Add the request body
201
+ $request .= "\r\n" . $body;
202
+
203
+ // Send the request
204
+ if (! @fwrite($this->socket, $request)) {
205
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
206
+ throw new Zend_Http_Client_Adapter_Exception('Error writing request to server');
207
+ }
208
+
209
+ return $request;
210
+ }
211
+
212
+ /**
213
+ * Read response from server
214
+ *
215
+ * @return string
216
+ */
217
+ public function read()
218
+ {
219
+ // First, read headers only
220
+ $response = '';
221
+ $gotStatus = false;
222
+ while ($line = @fgets($this->socket)) {
223
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
224
+ if ($gotStatus) {
225
+ $response .= $line;
226
+ if (!chop($line)) break;
227
+ }
228
+ }
229
+
230
+ $statusCode = Zend_Http_Response::extractCode($response);
231
+
232
+ // Handle 100 and 101 responses internally by restarting the read again
233
+ if ($statusCode == 100 || $statusCode == 101) return $this->read();
234
+
235
+ /**
236
+ * Responses to HEAD requests and 204 or 304 responses are not expected
237
+ * to have a body - stop reading here
238
+ */
239
+ if ($statusCode == 304 || $statusCode == 204 ||
240
+ $this->method == Zend_Http_Client::HEAD) return $response;
241
+
242
+ // Check headers to see what kind of connection / transfer encoding we have
243
+ $headers = Zend_Http_Response::extractHeaders($response);
244
+
245
+ // if the connection is set to close, just read until socket closes
246
+ if (isset($headers['connection']) && $headers['connection'] == 'close') {
247
+ while ($buff = @fread($this->socket, 8192)) {
248
+ $response .= $buff;
249
+ }
250
+
251
+ $this->close();
252
+
253
+ // Else, if we got a transfer-encoding header (chunked body)
254
+ } elseif (isset($headers['transfer-encoding'])) {
255
+ if ($headers['transfer-encoding'] == 'chunked') {
256
+ do {
257
+ $chunk = '';
258
+ $line = @fgets($this->socket);
259
+ $chunk .= $line;
260
+
261
+ $hexchunksize = ltrim(chop($line), '0');
262
+ $hexchunksize = strlen($hexchunksize) ? strtolower($hexchunksize) : 0;
263
+
264
+ $chunksize = hexdec(chop($line));
265
+ if (dechex($chunksize) != $hexchunksize) {
266
+ @fclose($this->socket);
267
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
268
+ throw new Zend_Http_Client_Adapter_Exception('Invalid chunk size "' .
269
+ $hexchunksize . '" unable to read chunked body');
270
+ }
271
+
272
+ $left_to_read = $chunksize;
273
+ while ($left_to_read > 0) {
274
+ $line = @fread($this->socket, $left_to_read);
275
+ $chunk .= $line;
276
+ $left_to_read -= strlen($line);
277
+ }
278
+
279
+ $chunk .= @fgets($this->socket);
280
+ $response .= $chunk;
281
+ } while ($chunksize > 0);
282
+ } else {
283
+ throw new Zend_Http_Client_Adapter_Exception('Cannot handle "' .
284
+ $headers['transfer-encoding'] . '" transfer encoding');
285
+ }
286
+
287
+ // Else, if we got the content-length header, read this number of bytes
288
+ } elseif (isset($headers['content-length'])) {
289
+ $left_to_read = $headers['content-length'];
290
+ $chunk = '';
291
+ while ($left_to_read > 0) {
292
+ $chunk = @fread($this->socket, $left_to_read);
293
+ $left_to_read -= strlen($chunk);
294
+ $response .= $chunk;
295
+ }
296
+
297
+ // Fallback: just read the response (should not happen)
298
+ } else {
299
+ while ($buff = @fread($this->socket, 8192)) {
300
+ $response .= $buff;
301
+ }
302
+
303
+ $this->close();
304
+ }
305
+
306
+ return $response;
307
+ }
308
+
309
+ /**
310
+ * Close the connection to the server
311
+ *
312
+ */
313
+ public function close()
314
+ {
315
+ if (is_resource($this->socket)) @fclose($this->socket);
316
+ $this->socket = null;
317
+ $this->connected_to = array(null, null);
318
+ }
319
+
320
+ /**
321
+ * Destructor: make sure the socket is disconnected
322
+ *
323
+ * If we are in persistent TCP mode, will not close the connection
324
+ *
325
+ */
326
+ public function __destruct()
327
+ {
328
+ if (! $this->config['persistent']) {
329
+ if ($this->socket) $this->close();
330
+ }
331
+ }
332
+ }
includes/phpQuery/phpQuery/Zend/Http/Client/Adapter/Test.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Http
17
+ * @subpackage Client_Adapter
18
+ * @version $Id: Test.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once 'Zend/Uri/Http.php';
24
+ require_once 'Zend/Http/Response.php';
25
+ require_once 'Zend/Http/Client/Adapter/Interface.php';
26
+
27
+ /**
28
+ * A testing-purposes adapter.
29
+ *
30
+ * Should be used to test all components that rely on Zend_Http_Client,
31
+ * without actually performing an HTTP request. You should instantiate this
32
+ * object manually, and then set it as the client's adapter. Then, you can
33
+ * set the expected response using the setResponse() method.
34
+ *
35
+ * @category Zend
36
+ * @package Zend_Http
37
+ * @subpackage Client_Adapter
38
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
39
+ * @license http://framework.zend.com/license/new-bsd New BSD License
40
+ */
41
+ class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interface
42
+ {
43
+ /**
44
+ * Parameters array
45
+ *
46
+ * @var array
47
+ */
48
+ protected $config = array();
49
+
50
+ /**
51
+ * Buffer of responses to be returned by the read() method. Can be
52
+ * set using setResponse() and addResponse().
53
+ *
54
+ * @var array
55
+ */
56
+ protected $responses = array("HTTP/1.1 400 Bad Request\r\n\r\n");
57
+
58
+ /**
59
+ * Current position in the response buffer
60
+ *
61
+ * @var integer
62
+ */
63
+ protected $responseIndex = 0;
64
+
65
+ /**
66
+ * Adapter constructor, currently empty. Config is set using setConfig()
67
+ *
68
+ */
69
+ public function __construct()
70
+ { }
71
+
72
+ /**
73
+ * Set the configuration array for the adapter
74
+ *
75
+ * @param array $config
76
+ */
77
+ public function setConfig($config = array())
78
+ {
79
+ if (! is_array($config)) {
80
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
81
+ throw new Zend_Http_Client_Adapter_Exception(
82
+ '$config expects an array, ' . gettype($config) . ' recieved.');
83
+ }
84
+
85
+ foreach ($config as $k => $v) {
86
+ $this->config[strtolower($k)] = $v;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Connect to the remote server
92
+ *
93
+ * @param string $host
94
+ * @param int $port
95
+ * @param boolean $secure
96
+ * @param int $timeout
97
+ */
98
+ public function connect($host, $port = 80, $secure = false)
99
+ { }
100
+
101
+ /**
102
+ * Send request to the remote server
103
+ *
104
+ * @param string $method
105
+ * @param Zend_Uri_Http $uri
106
+ * @param string $http_ver
107
+ * @param array $headers
108
+ * @param string $body
109
+ * @return string Request as string
110
+ */
111
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
112
+ {
113
+ $host = $uri->getHost();
114
+ $host = (strtolower($uri->getScheme()) == 'https' ? 'sslv2://' . $host : $host);
115
+
116
+ // Build request headers
117
+ $path = $uri->getPath();
118
+ if ($uri->getQuery()) $path .= '?' . $uri->getQuery();
119
+ $request = "{$method} {$path} HTTP/{$http_ver}\r\n";
120
+ foreach ($headers as $k => $v) {
121
+ if (is_string($k)) $v = ucfirst($k) . ": $v";
122
+ $request .= "$v\r\n";
123
+ }
124
+
125
+ // Add the request body
126
+ $request .= "\r\n" . $body;
127
+
128
+ // Do nothing - just return the request as string
129
+
130
+ return $request;
131
+ }
132
+
133
+ /**
134
+ * Return the response set in $this->setResponse()
135
+ *
136
+ * @return string
137
+ */
138
+ public function read()
139
+ {
140
+ if ($this->responseIndex >= count($this->responses)) {
141
+ $this->responseIndex = 0;
142
+ }
143
+ return $this->responses[$this->responseIndex++];
144
+ }
145
+
146
+ /**
147
+ * Close the connection (dummy)
148
+ *
149
+ */
150
+ public function close()
151
+ { }
152
+
153
+ /**
154
+ * Set the HTTP response(s) to be returned by this adapter
155
+ *
156
+ * @param Zend_Http_Response|array|string $response
157
+ */
158
+ public function setResponse($response)
159
+ {
160
+ if ($response instanceof Zend_Http_Response) {
161
+ $response = $response->asString();
162
+ }
163
+
164
+ $this->responses = (array)$response;
165
+ $this->responseIndex = 0;
166
+ }
167
+
168
+ /**
169
+ * Add another response to the response buffer.
170
+ *
171
+ * @param string $response
172
+ */
173
+ public function addResponse($response)
174
+ {
175
+ $this->responses[] = $response;
176
+ }
177
+
178
+ /**
179
+ * Sets the position of the response buffer. Selects which
180
+ * response will be returned on the next call to read().
181
+ *
182
+ * @param integer $index
183
+ */
184
+ public function setResponseIndex($index)
185
+ {
186
+ if ($index < 0 || $index >= count($this->responses)) {
187
+ require_once 'Zend/Http/Client/Adapter/Exception.php';
188
+ throw new Zend_Http_Client_Adapter_Exception(
189
+ 'Index out of range of response buffer size');
190
+ }
191
+ $this->responseIndex = $index;
192
+ }
193
+ }
includes/phpQuery/phpQuery/Zend/Http/Client/Exception.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Http
17
+ * @subpackage Client_Exception
18
+ * @version $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once 'Zend/Http/Exception.php';
24
+
25
+ /**
26
+ * @category Zend
27
+ * @package Zend_Http
28
+ * @subpackage Client
29
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
30
+ * @license http://framework.zend.com/license/new-bsd New BSD License
31
+ */
32
+ class Zend_Http_Client_Exception extends Zend_Http_Exception
33
+ {}
includes/phpQuery/phpQuery/Zend/Http/Cookie.php ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Http
17
+ * @subpackage Cookie
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com/)
19
+ * @version $Id: Cookie.php 9098 2008-03-30 19:29:10Z thomas $
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once 'Zend/Uri/Http.php';
24
+
25
+ /**
26
+ * Zend_Http_Cookie is a class describing an HTTP cookie and all it's parameters.
27
+ *
28
+ * Zend_Http_Cookie is a class describing an HTTP cookie and all it's parameters. The
29
+ * class also enables validating whether the cookie should be sent to the server in
30
+ * a specified scenario according to the request URI, the expiry time and whether
31
+ * session cookies should be used or not. Generally speaking cookies should be
32
+ * contained in a Cookiejar object, or instantiated manually and added to an HTTP
33
+ * request.
34
+ *
35
+ * See http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
36
+ *
37
+ * @category Zend
38
+ * @package Zend_Http
39
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com/)
40
+ * @license http://framework.zend.com/license/new-bsd New BSD License
41
+ */
42
+ class Zend_Http_Cookie
43
+ {
44
+ /**
45
+ * Cookie name
46
+ *
47
+ * @var string
48
+ */
49
+ protected $name;
50
+
51
+ /**
52
+ * Cookie value
53
+ *
54
+ * @var string
55
+ */
56
+ protected $value;
57
+
58
+ /**
59
+ * Cookie expiry date
60
+ *
61
+ * @var int
62
+ */
63
+ protected $expires;
64
+
65
+ /**
66
+ * Cookie domain
67
+ *
68
+ * @var string
69
+ */
70
+ protected $domain;
71
+
72
+ /**
73
+ * Cookie path
74
+ *
75
+ * @var string
76
+ */
77
+ protected $path;
78
+
79
+ /**
80
+ * Whether the cookie is secure or not
81
+ *
82
+ * @var boolean
83
+ */
84
+ protected $secure;
85
+
86
+ /**
87
+ * Cookie object constructor
88
+ *
89
+ * @todo Add validation of each one of the parameters (legal domain, etc.)
90
+ *
91
+ * @param string $name
92
+ * @param string $value
93
+ * @param int $expires
94
+ * @param string $domain
95
+ * @param string $path
96
+ * @param bool $secure
97
+ */
98
+ public function __construct($name, $value, $domain, $expires = null, $path = null, $secure = false)
99
+ {
100
+ if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
101
+ require_once 'Zend/Http/Exception.php';
102
+ throw new Zend_Http_Exception("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
103
+ }
104
+
105
+ if (! $this->name = (string) $name) {
106
+ require_once 'Zend/Http/Exception.php';
107
+ throw new Zend_Http_Exception('Cookies must have a name');
108
+ }
109
+
110
+ if (! $this->domain = (string) $domain) {
111
+ require_once 'Zend/Http/Exception.php';
112
+ throw new Zend_Http_Exception('Cookies must have a domain');
113
+ }
114
+
115
+ $this->value = (string) $value;
116
+ $this->expires = ($expires === null ? null : (int) $expires);
117
+ $this->path = ($path ? $path : '/');
118
+ $this->secure = $secure;
119
+ }
120
+
121
+ /**
122
+ * Get Cookie name
123
+ *
124
+ * @return string
125
+ */
126
+ public function getName()
127
+ {
128
+ return $this->name;
129
+ }
130
+
131
+ /**
132
+ * Get cookie value
133
+ *
134
+ * @return string
135
+ */
136
+ public function getValue()
137
+ {
138
+ return $this->value;
139
+ }
140
+
141
+ /**
142
+ * Get cookie domain
143
+ *
144
+ * @return string
145
+ */
146
+ public function getDomain()
147
+ {
148
+ return $this->domain;
149
+ }
150
+
151
+ /**
152
+ * Get the cookie path
153
+ *
154
+ * @return string
155
+ */
156
+ public function getPath()
157
+ {
158
+ return $this->path;
159
+ }
160
+
161
+ /**
162
+ * Get the expiry time of the cookie, or null if no expiry time is set
163
+ *
164
+ * @return int|null
165
+ */
166
+ public function getExpiryTime()
167
+ {
168
+ return $this->expires;
169
+ }
170
+
171
+ /**
172
+ * Check whether the cookie should only be sent over secure connections
173
+ *
174
+ * @return boolean
175
+ */
176
+ public function isSecure()
177
+ {
178
+ return $this->secure;
179
+ }
180
+
181
+ /**
182
+ * Check whether the cookie has expired
183
+ *
184
+ * Always returns false if the cookie is a session cookie (has no expiry time)
185
+ *
186
+ * @param int $now Timestamp to consider as "now"
187
+ * @return boolean
188
+ */
189
+ public function isExpired($now = null)
190
+ {
191
+ if ($now === null) $now = time();
192
+ if (is_int($this->expires) && $this->expires < $now) {
193
+ return true;
194
+ } else {
195
+ return false;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Check whether the cookie is a session cookie (has no expiry time set)
201
+ *
202
+ * @return boolean
203
+ */
204
+ public function isSessionCookie()
205
+ {
206
+ return ($this->expires === null);
207
+ }
208
+
209
+ /**
210
+ * Checks whether the cookie should be sent or not in a specific scenario
211
+ *
212
+ * @param string|Zend_Uri_Http $uri URI to check against (secure, domain, path)
213
+ * @param boolean $matchSessionCookies Whether to send session cookies
214
+ * @param int $now Override the current time when checking for expiry time
215
+ * @return boolean
216
+ */
217
+ public function match($uri, $matchSessionCookies = true, $now = null)
218
+ {
219
+ if (is_string ($uri)) {
220
+ $uri = Zend_Uri_Http::factory($uri);
221
+ }
222
+
223
+ // Make sure we have a valid Zend_Uri_Http object
224
+ if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) {
225
+ require_once 'Zend/Http/Exception.php';
226
+ throw new Zend_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI');
227
+ }
228
+
229
+ // Check that the cookie is secure (if required) and not expired
230
+ if ($this->secure && $uri->getScheme() != 'https') return false;
231
+ if ($this->isExpired($now)) return false;
232
+ if ($this->isSessionCookie() && ! $matchSessionCookies) return false;
233
+
234
+ // Validate domain and path
235
+ // Domain is validated using tail match, while path is validated using head match
236
+ $domain_preg = preg_quote($this->getDomain(), "/");
237
+ if (! preg_match("/{$domain_preg}$/", $uri->getHost())) return false;
238
+ $path_preg = preg_quote($this->getPath(), "/");
239
+ if (! preg_match("/^{$path_preg}/", $uri->getPath())) return false;
240
+
241
+ // If we didn't die until now, return true.
242
+ return true;
243
+ }
244
+
245
+ /**
246
+ * Get the cookie as a string, suitable for sending as a "Cookie" header in an
247
+ * HTTP request
248
+ *
249
+ * @return string
250
+ */
251
+ public function __toString()
252
+ {
253
+ return $this->name . '=' . urlencode($this->value) . ';';
254
+ }
255
+
256
+ /**
257
+ * Generate a new Cookie object from a cookie string
258
+ * (for example the value of the Set-Cookie HTTP header)
259
+ *
260
+ * @param string $cookieStr
261
+ * @param Zend_Uri_Http|string $ref_uri Reference URI for default values (domain, path)
262
+ * @return Zend_Http_Cookie A new Zend_Http_Cookie object or false on failure.
263
+ */
264
+ public static function fromString($cookieStr, $ref_uri = null)
265
+ {
266
+ // Set default values
267
+ if (is_string($ref_uri)) {
268
+ $ref_uri = Zend_Uri_Http::factory($ref_uri);
269
+ }
270
+
271
+ $name = '';
272
+ $value = '';
273
+ $domain = '';
274
+ $path = '';
275
+ $expires = null;
276
+ $secure = false;
277
+ $parts = explode(';', $cookieStr);
278
+
279
+ // If first part does not include '=', fail
280
+ if (strpos($parts[0], '=') === false) return false;
281
+
282
+ // Get the name and value of the cookie
283
+ list($name, $value) = explode('=', trim(array_shift($parts)), 2);
284
+ $name = trim($name);
285
+ $value = urldecode(trim($value));
286
+
287
+ // Set default domain and path
288
+ if ($ref_uri instanceof Zend_Uri_Http) {
289
+ $domain = $ref_uri->getHost();
290
+ $path = $ref_uri->getPath();
291
+ $path = substr($path, 0, strrpos($path, '/'));
292
+ }
293
+
294
+ // Set other cookie parameters
295
+ foreach ($parts as $part) {
296
+ $part = trim($part);
297
+ if (strtolower($part) == 'secure') {
298
+ $secure = true;
299
+ continue;
300
+ }
301
+
302
+ $keyValue = explode('=', $part, 2);
303
+ if (count($keyValue) == 2) {
304
+ list($k, $v) = $keyValue;
305
+ switch (strtolower($k)) {
306
+ case 'expires':
307
+ $expires = strtotime($v);
308
+ break;
309
+ case 'path':
310
+ $path = $v;
311
+ break;
312
+ case 'domain':
313
+ $domain = $v;
314
+ break;
315
+ default:
316
+ break;
317
+ }
318
+ }
319
+ }
320
+
321
+ if ($name !== '') {
322
+ return new Zend_Http_Cookie($name, $value, $domain, $expires, $path, $secure);
323
+ } else {
324
+ return false;
325
+ }
326
+ }
327
+ }
includes/phpQuery/phpQuery/Zend/Http/CookieJar.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Http
17
+ * @subpackage CookieJar
18
+ * @version $Id: CookieJar.php 9098 2008-03-30 19:29:10Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com/)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once "Zend/Uri.php";
24
+ require_once "Zend/Http/Cookie.php";
25
+ require_once "Zend/Http/Response.php";
26
+
27
+ /**
28
+ * A Zend_Http_CookieJar object is designed to contain and maintain HTTP cookies, and should
29
+ * be used along with Zend_Http_Client in order to manage cookies across HTTP requests and
30
+ * responses.
31
+ *
32
+ * The class contains an array of Zend_Http_Cookie objects. Cookies can be added to the jar
33
+ * automatically from a request or manually. Then, the jar can find and return the cookies
34
+ * needed for a specific HTTP request.
35
+ *
36
+ * A special parameter can be passed to all methods of this class that return cookies: Cookies
37
+ * can be returned either in their native form (as Zend_Http_Cookie objects) or as strings -
38
+ * the later is suitable for sending as the value of the "Cookie" header in an HTTP request.
39
+ * You can also choose, when returning more than one cookie, whether to get an array of strings
40
+ * (by passing Zend_Http_CookieJar::COOKIE_STRING_ARRAY) or one unified string for all cookies
41
+ * (by passing Zend_Http_CookieJar::COOKIE_STRING_CONCAT).
42
+ *
43
+ * @link http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
44
+ *
45
+ * @category Zend
46
+ * @package Zend_Http
47
+ * @subpackage CookieJar
48
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com/)
49
+ * @license http://framework.zend.com/license/new-bsd New BSD License
50
+ */
51
+ class Zend_Http_CookieJar
52
+ {
53
+ /**
54
+ * Return cookie(s) as a Zend_Http_Cookie object
55
+ *
56
+ */
57
+ const COOKIE_OBJECT = 0;
58
+
59
+ /**
60
+ * Return cookie(s) as a string (suitable for sending in an HTTP request)
61
+ *
62
+ */
63
+ const COOKIE_STRING_ARRAY = 1;
64
+
65
+ /**
66
+ * Return all cookies as one long string (suitable for sending in an HTTP request)
67
+ *
68
+ */
69
+ const COOKIE_STRING_CONCAT = 2;
70
+
71
+ /**
72
+ * Array storing cookies
73
+ *
74
+ * Cookies are stored according to domain and path:
75
+ * $cookies
76
+ * + www.mydomain.com
77
+ * + /
78
+ * - cookie1
79
+ * - cookie2
80
+ * + /somepath
81
+ * - othercookie
82
+ * + www.otherdomain.net
83
+ * + /
84
+ * - alsocookie
85
+ *
86
+ * @var array
87
+ */
88
+ protected $cookies = array();
89
+
90
+ /**
91
+ * Construct a new CookieJar object
92
+ *
93
+ */
94
+ public function __construct()
95
+ { }
96
+
97
+ /**
98
+ * Add a cookie to the jar. Cookie should be passed either as a Zend_Http_Cookie object
99
+ * or as a string - in which case an object is created from the string.
100
+ *
101
+ * @param Zend_Http_Cookie|string $cookie
102
+ * @param Zend_Uri_Http|string $ref_uri Optional reference URI (for domain, path, secure)
103
+ */
104
+ public function addCookie($cookie, $ref_uri = null)
105
+ {
106
+ if (is_string($cookie)) {
107
+ $cookie = Zend_Http_Cookie::fromString($cookie, $ref_uri);
108
+ }
109
+
110
+ if ($cookie instanceof Zend_Http_Cookie) {
111
+ $domain = $cookie->getDomain();
112
+ $path = $cookie->getPath();
113
+ if (! isset($this->cookies[$domain])) $this->cookies[$domain] = array();
114
+ if (! isset($this->cookies[$domain][$path])) $this->cookies[$domain][$path] = array();
115
+ $this->cookies[$domain][$path][$cookie->getName()] = $cookie;
116
+ } else {
117
+ require_once 'Zend/Http/Exception.php';
118
+ throw new Zend_Http_Exception('Supplient argument is not a valid cookie string or object');
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Parse an HTTP response, adding all the cookies set in that response
124
+ * to the cookie jar.
125
+ *
126
+ * @param Zend_Http_Response $response
127
+ * @param Zend_Uri_Http|string $ref_uri Requested URI
128
+ */
129
+ public function addCookiesFromResponse($response, $ref_uri)
130
+ {
131
+ if (! $response instanceof Zend_Http_Response) {
132
+ require_once 'Zend/Http/Exception.php';
133
+ throw new Zend_Http_Exception('$response is expected to be a Response object, ' .
134
+ gettype($response) . ' was passed');
135
+ }
136
+
137
+ $cookie_hdrs = $response->getHeader('Set-Cookie');
138
+
139
+ if (is_array($cookie_hdrs)) {
140
+ foreach ($cookie_hdrs as $cookie) {
141
+ $this->addCookie($cookie, $ref_uri);
142
+ }
143
+ } elseif (is_string($cookie_hdrs)) {
144
+ $this->addCookie($cookie_hdrs, $ref_uri);
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Get all cookies in the cookie jar as an array
150
+ *
151
+ * @param int $ret_as Whether to return cookies as objects of Zend_Http_Cookie or as strings
152
+ * @return array|string
153
+ */
154
+ public function getAllCookies($ret_as = self::COOKIE_OBJECT)
155
+ {
156
+ $cookies = $this->_flattenCookiesArray($this->cookies, $ret_as);
157
+ return $cookies;
158
+ }
159
+
160
+ /**
161
+ * Return an array of all cookies matching a specific request according to the request URI,
162
+ * whether session cookies should be sent or not, and the time to consider as "now" when
163
+ * checking cookie expiry time.
164
+ *
165
+ * @param string|Zend_Uri_Http $uri URI to check against (secure, domain, path)
166
+ * @param boolean $matchSessionCookies Whether to send session cookies
167
+ * @param int $ret_as Whether to return cookies as objects of Zend_Http_Cookie or as strings
168
+ * @param int $now Override the current time when checking for expiry time
169
+ * @return array|string
170
+ */
171
+ public function getMatchingCookies($uri, $matchSessionCookies = true,
172
+ $ret_as = self::COOKIE_OBJECT, $now = null)
173
+ {
174
+ if (is_string($uri)) $uri = Zend_Uri::factory($uri);
175
+ if (! $uri instanceof Zend_Uri_Http) {
176
+ require_once 'Zend/Http/Exception.php';
177
+ throw new Zend_Http_Exception("Invalid URI string or object passed");
178
+ }
179
+
180
+ // Set path
181
+ $path = $uri->getPath();
182
+ $path = substr($path, 0, strrpos($path, '/'));
183
+ if (! $path) $path = '/';
184
+
185
+ // First, reduce the array of cookies to only those matching domain and path
186
+ $cookies = $this->_matchDomain($uri->getHost());
187
+ $cookies = $this->_matchPath($cookies, $path);
188
+ $cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT);
189
+
190
+ // Next, run Cookie->match on all cookies to check secure, time and session mathcing
191
+ $ret = array();
192
+ foreach ($cookies as $cookie)
193
+ if ($cookie->match($uri, $matchSessionCookies, $now))
194
+ $ret[] = $cookie;
195
+
196
+ // Now, use self::_flattenCookiesArray again - only to convert to the return format ;)
197
+ $ret = $this->_flattenCookiesArray($ret, $ret_as);
198
+
199
+ return $ret;
200
+ }
201
+
202
+ /**
203
+ * Get a specific cookie according to a URI and name
204
+ *
205
+ * @param Zend_Uri_Http|string $uri The uri (domain and path) to match
206
+ * @param string $cookie_name The cookie's name
207
+ * @param int $ret_as Whether to return cookies as objects of Zend_Http_Cookie or as strings
208
+ * @return Zend_Http_Cookie|string
209
+ */
210
+ public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT)
211
+ {
212
+ if (is_string($uri)) {
213
+ $uri = Zend_Uri::factory($uri);
214
+ }
215
+
216
+ if (! $uri instanceof Zend_Uri_Http) {
217
+ require_once 'Zend/Http/Exception.php';
218
+ throw new Zend_Http_Exception('Invalid URI specified');
219
+ }
220
+
221
+ // Get correct cookie path
222
+ $path = $uri->getPath();
223
+ $path = substr($path, 0, strrpos($path, '/'));
224
+ if (! $path) $path = '/';
225
+
226
+ if (isset($this->cookies[$uri->getHost()][$path][$cookie_name])) {
227
+ $cookie = $this->cookies[$uri->getHost()][$path][$cookie_name];
228
+
229
+ switch ($ret_as) {
230
+ case self::COOKIE_OBJECT:
231
+ return $cookie;
232
+ break;
233
+
234
+ case self::COOKIE_STRING_ARRAY:
235
+ case self::COOKIE_STRING_CONCAT:
236
+ return $cookie->__toString();
237
+ break;
238
+
239
+ default:
240
+ require_once 'Zend/Http/Exception.php';
241
+ throw new Zend_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}");
242
+ break;
243
+ }
244
+ } else {
245
+ return false;
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Helper function to recursivly flatten an array. Shoud be used when exporting the
251
+ * cookies array (or parts of it)
252
+ *
253
+ * @param Zend_Http_Cookie|array $ptr
254
+ * @param int $ret_as What value to return
255
+ * @return array|string
256
+ */
257
+ protected function _flattenCookiesArray($ptr, $ret_as = self::COOKIE_OBJECT) {
258
+ if (is_array($ptr)) {
259
+ $ret = ($ret_as == self::COOKIE_STRING_CONCAT ? '' : array());
260
+ foreach ($ptr as $item) {
261
+ if ($ret_as == self::COOKIE_STRING_CONCAT) {
262
+ $ret .= $this->_flattenCookiesArray($item, $ret_as);
263
+ } else {
264
+ $ret = array_merge($ret, $this->_flattenCookiesArray($item, $ret_as));
265
+ }
266
+ }
267
+ return $ret;
268
+ } elseif ($ptr instanceof Zend_Http_Cookie) {
269
+ switch ($ret_as) {
270
+ case self::COOKIE_STRING_ARRAY:
271
+ return array($ptr->__toString());
272
+ break;
273
+
274
+ case self::COOKIE_STRING_CONCAT:
275
+ return $ptr->__toString();
276
+ break;
277
+
278
+ case self::COOKIE_OBJECT:
279
+ default:
280
+ return array($ptr);
281
+ break;
282
+ }
283
+ }
284
+
285
+ return null;
286
+ }
287
+
288
+ /**
289
+ * Return a subset of the cookies array matching a specific domain
290
+ *
291
+ * Returned array is actually an array of pointers to items in the $this->cookies array.
292
+ *
293
+ * @param string $domain
294
+ * @return array
295
+ */
296
+ protected function _matchDomain($domain) {
297
+ $ret = array();
298
+
299
+ foreach (array_keys($this->cookies) as $cdom) {
300
+ $regex = "/" . preg_quote($cdom, "/") . "$/i";
301
+ if (preg_match($regex, $domain)) $ret[$cdom] = &$this->cookies[$cdom];
302
+ }
303
+
304
+ return $ret;
305
+ }
306
+
307
+ /**
308
+ * Return a subset of a domain-matching cookies that also match a specified path
309
+ *
310
+ * Returned array is actually an array of pointers to items in the $passed array.
311
+ *
312
+ * @param array $dom_array
313
+ * @param string $path
314
+ * @return array
315
+ */
316
+ protected function _matchPath($domains, $path) {
317
+ $ret = array();
318
+ if (substr($path, -1) != '/') $path .= '/';
319
+
320
+ foreach ($domains as $dom => $paths_array) {
321
+ foreach (array_keys($paths_array) as $cpath) {
322
+ $regex = "|^" . preg_quote($cpath, "|") . "|i";
323
+ if (preg_match($regex, $path)) {
324
+ if (! isset($ret[$dom])) $ret[$dom] = array();
325
+ $ret[$dom][$cpath] = &$paths_array[$cpath];
326
+ }
327
+ }
328
+ }
329
+
330
+ return $ret;
331
+ }
332
+
333
+ /**
334
+ * Create a new CookieJar object and automatically load into it all the
335
+ * cookies set in an Http_Response object. If $uri is set, it will be
336
+ * considered as the requested URI for setting default domain and path
337
+ * of the cookie.
338
+ *
339
+ * @param Zend_Http_Response $response HTTP Response object
340
+ * @param Zend_Uri_Http|string $uri The requested URI
341
+ * @return Zend_Http_CookieJar
342
+ * @todo Add the $uri functionality.
343
+ */
344
+ public static function fromResponse(Zend_Http_Response $response, $ref_uri)
345
+ {
346
+ $jar = new self();
347
+ $jar->addCookiesFromResponse($response, $ref_uri);
348
+ return $jar;
349
+ }
350
+ }
includes/phpQuery/phpQuery/Zend/Http/Exception.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Http
17
+ * @subpackage Exception
18
+ * @version $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once 'Zend/Exception.php';
24
+
25
+ /**
26
+ * @category Zend
27
+ * @package Zend_Http
28
+ * @subpackage Client
29
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
30
+ * @license http://framework.zend.com/license/new-bsd New BSD License
31
+ */
32
+ class Zend_Http_Exception extends Zend_Exception
33
+ {}
includes/phpQuery/phpQuery/Zend/Http/Response.php ADDED
@@ -0,0 +1,625 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Http
18
+ * @subpackage Response
19
+ * @version $Id: Response.php 11175 2008-09-01 08:39:10Z yoshida@zend.co.jp $
20
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * Zend_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 Zend_Http
30
+ * @subpackage Response
31
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Zend_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 Zend_Http_Response::fromString to parse an HTTP
136
+ * response string and create a new Zend_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 Zend_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 'Zend/Http/Exception.php';
156
+ throw new Zend_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 'Zend/Http/Exception.php';
164
+ throw new Zend_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 'Zend/Http/Exception.php';
180
+ throw new Zend_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 ($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
+ * A convenience function that returns a text representation of
402
+ * HTTP response codes. Returns 'Unknown' for unknown codes.
403
+ * Returns array of all codes, if $code is not specified.
404
+ *
405
+ * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown')
406
+ * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference
407
+ *
408
+ * @param int $code HTTP response code
409
+ * @param boolean $http11 Use HTTP version 1.1
410
+ * @return string
411
+ */
412
+ public static function responseCodeAsText($code = null, $http11 = true)
413
+ {
414
+ $messages = self::$messages;
415
+ if (! $http11) $messages[302] = 'Moved Temporarily';
416
+
417
+ if ($code === null) {
418
+ return $messages;
419
+ } elseif (isset($messages[$code])) {
420
+ return $messages[$code];
421
+ } else {
422
+ return 'Unknown';
423
+ }
424
+ }
425
+
426
+ /**
427
+ * Extract the response code from a response string
428
+ *
429
+ * @param string $response_str
430
+ * @return int
431
+ */
432
+ public static function extractCode($response_str)
433
+ {
434
+ preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
435
+
436
+ if (isset($m[1])) {
437
+ return (int) $m[1];
438
+ } else {
439
+ return false;
440
+ }
441
+ }
442
+
443
+ /**
444
+ * Extract the HTTP message from a response
445
+ *
446
+ * @param string $response_str
447
+ * @return string
448
+ */
449
+ public static function extractMessage($response_str)
450
+ {
451
+ preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m);
452
+
453
+ if (isset($m[1])) {
454
+ return $m[1];
455
+ } else {
456
+ return false;
457
+ }
458
+ }
459
+
460
+ /**
461
+ * Extract the HTTP version from a response
462
+ *
463
+ * @param string $response_str
464
+ * @return string
465
+ */
466
+ public static function extractVersion($response_str)
467
+ {
468
+ preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m);
469
+
470
+ if (isset($m[1])) {
471
+ return $m[1];
472
+ } else {
473
+ return false;
474
+ }
475
+ }
476
+
477
+ /**
478
+ * Extract the headers from a response string
479
+ *
480
+ * @param string $response_str
481
+ * @return array
482
+ */
483
+ public static function extractHeaders($response_str)
484
+ {
485
+ $headers = array();
486
+
487
+ // First, split body and headers
488
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
489
+ if (! $parts[0]) return $headers;
490
+
491
+ // Split headers part to lines
492
+ $lines = explode("\n", $parts[0]);
493
+ unset($parts);
494
+ $last_header = null;
495
+
496
+ foreach($lines as $line) {
497
+ $line = trim($line, "\r\n");
498
+ if ($line == "") break;
499
+
500
+ if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) {
501
+ unset($last_header);
502
+ $h_name = strtolower($m[1]);
503
+ $h_value = $m[2];
504
+
505
+ if (isset($headers[$h_name])) {
506
+ if (! is_array($headers[$h_name])) {
507
+ $headers[$h_name] = array($headers[$h_name]);
508
+ }
509
+
510
+ $headers[$h_name][] = $h_value;
511
+ } else {
512
+ $headers[$h_name] = $h_value;
513
+ }
514
+ $last_header = $h_name;
515
+ } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) {
516
+ if (is_array($headers[$last_header])) {
517
+ end($headers[$last_header]);
518
+ $last_header_key = key($headers[$last_header]);
519
+ $headers[$last_header][$last_header_key] .= $m[1];
520
+ } else {
521
+ $headers[$last_header] .= $m[1];
522
+ }
523
+ }
524
+ }
525
+
526
+ return $headers;
527
+ }
528
+
529
+ /**
530
+ * Extract the body from a response string
531
+ *
532
+ * @param string $response_str
533
+ * @return string
534
+ */
535
+ public static function extractBody($response_str)
536
+ {
537
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
538
+ if (isset($parts[1])) {
539
+ return $parts[1];
540
+ } else {
541
+ return '';
542
+ }
543
+ }
544
+
545
+ /**
546
+ * Decode a "chunked" transfer-encoded body and return the decoded text
547
+ *
548
+ * @param string $body
549
+ * @return string
550
+ */
551
+ public static function decodeChunkedBody($body)
552
+ {
553
+ $decBody = '';
554
+
555
+ while (trim($body)) {
556
+ if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
557
+ require_once 'Zend/Http/Exception.php';
558
+ throw new Zend_Http_Exception("Error parsing body - doesn't seem to be a chunked message");
559
+ }
560
+
561
+ $length = hexdec(trim($m[1]));
562
+ $cut = strlen($m[0]);
563
+
564
+ $decBody .= substr($body, $cut, $length);
565
+ $body = substr($body, $cut + $length + 2);
566
+ }
567
+
568
+ return $decBody;
569
+ }
570
+
571
+ /**
572
+ * Decode a gzip encoded message (when Content-encoding = gzip)
573
+ *
574
+ * Currently requires PHP with zlib support
575
+ *
576
+ * @param string $body
577
+ * @return string
578
+ */
579
+ public static function decodeGzip($body)
580
+ {
581
+ if (! function_exists('gzinflate')) {
582
+ require_once 'Zend/Http/Exception.php';
583
+ throw new Zend_Http_Exception('Unable to decode gzipped response ' .
584
+ 'body: perhaps the zlib extension is not loaded?');
585
+ }
586
+
587
+ return gzinflate(substr($body, 10));
588
+ }
589
+
590
+ /**
591
+ * Decode a zlib deflated message (when Content-encoding = deflate)
592
+ *
593
+ * Currently requires PHP with zlib support
594
+ *
595
+ * @param string $body
596
+ * @return string
597
+ */
598
+ public static function decodeDeflate($body)
599
+ {
600
+ if (! function_exists('gzuncompress')) {
601
+ require_once 'Zend/Http/Exception.php';
602
+ throw new Zend_Http_Exception('Unable to decode deflated response ' .
603
+ 'body: perhaps the zlib extension is not loaded?');
604
+ }
605
+
606
+ return gzuncompress($body);
607
+ }
608
+
609
+ /**
610
+ * Create a new Zend_Http_Response object from a string
611
+ *
612
+ * @param string $response_str
613
+ * @return Zend_Http_Response
614
+ */
615
+ public static function fromString($response_str)
616
+ {
617
+ $code = self::extractCode($response_str);
618
+ $headers = self::extractHeaders($response_str);
619
+ $body = self::extractBody($response_str);
620
+ $version = self::extractVersion($response_str);
621
+ $message = self::extractMessage($response_str);
622
+
623
+ return new Zend_Http_Response($code, $headers, $body, $version, $message);
624
+ }
625
+ }
includes/phpQuery/phpQuery/Zend/Json/Decoder.php ADDED
@@ -0,0 +1,457 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Json
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+ /**
22
+ * @see Zend_Json
23
+ */
24
+ require_once 'Zend/Json.php';
25
+
26
+ /**
27
+ * @see Zend_Json_Exception
28
+ */
29
+ require_once 'Zend/Json/Exception.php';
30
+
31
+
32
+ /**
33
+ * Decode JSON encoded string to PHP variable constructs
34
+ *
35
+ * @category Zend
36
+ * @package Zend_Json
37
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
38
+ * @license http://framework.zend.com/license/new-bsd New BSD License
39
+ */
40
+ class Zend_Json_Decoder
41
+ {
42
+ /**
43
+ * Parse tokens used to decode the JSON object. These are not
44
+ * for public consumption, they are just used internally to the
45
+ * class.
46
+ */
47
+ const EOF = 0;
48
+ const DATUM = 1;
49
+ const LBRACE = 2;
50
+ const LBRACKET = 3;
51
+ const RBRACE = 4;
52
+ const RBRACKET = 5;
53
+ const COMMA = 6;
54
+ const COLON = 7;
55
+
56
+ /**
57
+ * Use to maintain a "pointer" to the source being decoded
58
+ *
59
+ * @var string
60
+ */
61
+ protected $_source;
62
+
63
+ /**
64
+ * Caches the source length
65
+ *
66
+ * @var int
67
+ */
68
+ protected $_sourceLength;
69
+
70
+ /**
71
+ * The offset within the souce being decoded
72
+ *
73
+ * @var int
74
+ *
75
+ */
76
+ protected $_offset;
77
+
78
+ /**
79
+ * The current token being considered in the parser cycle
80
+ *
81
+ * @var int
82
+ */
83
+ protected $_token;
84
+
85
+ /**
86
+ * Flag indicating how objects should be decoded
87
+ *
88
+ * @var int
89
+ * @access protected
90
+ */
91
+ protected $_decodeType;
92
+
93
+ /**
94
+ * Constructor
95
+ *
96
+ * @param string $source String source to decode
97
+ * @param int $decodeType How objects should be decoded -- see
98
+ * {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
99
+ * valid values
100
+ * @return void
101
+ */
102
+ protected function __construct($source, $decodeType)
103
+ {
104
+ // Set defaults
105
+ $this->_source = $source;
106
+ $this->_sourceLength = strlen($source);
107
+ $this->_token = self::EOF;
108
+ $this->_offset = 0;
109
+
110
+ // Normalize and set $decodeType
111
+ if (!in_array($decodeType, array(Zend_Json::TYPE_ARRAY, Zend_Json::TYPE_OBJECT)))
112
+ {
113
+ $decodeType = Zend_Json::TYPE_ARRAY;
114
+ }
115
+ $this->_decodeType = $decodeType;
116
+
117
+ // Set pointer at first token
118
+ $this->_getNextToken();
119
+ }
120
+
121
+ /**
122
+ * Decode a JSON source string
123
+ *
124
+ * Decodes a JSON encoded string. The value returned will be one of the
125
+ * following:
126
+ * - integer
127
+ * - float
128
+ * - boolean
129
+ * - null
130
+ * - StdClass
131
+ * - array
132
+ * - array of one or more of the above types
133
+ *
134
+ * By default, decoded objects will be returned as associative arrays; to
135
+ * return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
136
+ * the $objectDecodeType parameter.
137
+ *
138
+ * Throws a Zend_Json_Exception if the source string is null.
139
+ *
140
+ * @static
141
+ * @access public
142
+ * @param string $source String to be decoded
143
+ * @param int $objectDecodeType How objects should be decoded; should be
144
+ * either or {@link Zend_Json::TYPE_ARRAY} or
145
+ * {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
146
+ * @return mixed
147
+ * @throws Zend_Json_Exception
148
+ */
149
+ public static function decode($source = null, $objectDecodeType = Zend_Json::TYPE_ARRAY)
150
+ {
151
+ if (null === $source) {
152
+ throw new Zend_Json_Exception('Must specify JSON encoded source for decoding');
153
+ } elseif (!is_string($source)) {
154
+ throw new Zend_Json_Exception('Can only decode JSON encoded strings');
155
+ }
156
+
157
+ $decoder = new self($source, $objectDecodeType);
158
+
159
+ return $decoder->_decodeValue();
160
+ }
161
+
162
+
163
+ /**
164
+ * Recursive driving rountine for supported toplevel tops
165
+ *
166
+ * @return mixed
167
+ */
168
+ protected function _decodeValue()
169
+ {
170
+ switch ($this->_token) {
171
+ case self::DATUM:
172
+ $result = $this->_tokenValue;
173
+ $this->_getNextToken();
174
+ return($result);
175
+ break;
176
+ case self::LBRACE:
177
+ return($this->_decodeObject());
178
+ break;
179
+ case self::LBRACKET:
180
+ return($this->_decodeArray());
181
+ break;
182
+ default:
183
+ return null;
184
+ break;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Decodes an object of the form:
190
+ * { "attribute: value, "attribute2" : value,...}
191
+ *
192
+ * If Zend_Json_Encoder was used to encode the original object then
193
+ * a special attribute called __className which specifies a class
194
+ * name that should wrap the data contained within the encoded source.
195
+ *
196
+ * Decodes to either an array or StdClass object, based on the value of
197
+ * {@link $_decodeType}. If invalid $_decodeType present, returns as an
198
+ * array.
199
+ *
200
+ * @return array|StdClass
201
+ */
202
+ protected function _decodeObject()
203
+ {
204
+ $members = array();
205
+ $tok = $this->_getNextToken();
206
+
207
+ while ($tok && $tok != self::RBRACE) {
208
+ if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
209
+ throw new Zend_Json_Exception('Missing key in object encoding: ' . $this->_source);
210
+ }
211
+
212
+ $key = $this->_tokenValue;
213
+ $tok = $this->_getNextToken();
214
+
215
+ if ($tok != self::COLON) {
216
+ throw new Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
217
+ }
218
+
219
+ $tok = $this->_getNextToken();
220
+ $members[$key] = $this->_decodeValue();
221
+ $tok = $this->_token;
222
+
223
+ if ($tok == self::RBRACE) {
224
+ break;
225
+ }
226
+
227
+ if ($tok != self::COMMA) {
228
+ throw new Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
229
+ }
230
+
231
+ $tok = $this->_getNextToken();
232
+ }
233
+
234
+ switch ($this->_decodeType) {
235
+ case Zend_Json::TYPE_OBJECT:
236
+ // Create new StdClass and populate with $members
237
+ $result = new StdClass();
238
+ foreach ($members as $key => $value) {
239
+ $result->$key = $value;
240
+ }
241
+ break;
242
+ case Zend_Json::TYPE_ARRAY:
243
+ default:
244
+ $result = $members;
245
+ break;
246
+ }
247
+
248
+ $this->_getNextToken();
249
+ return $result;
250
+ }
251
+
252
+ /**
253
+ * Decodes a JSON array format:
254
+ * [element, element2,...,elementN]
255
+ *
256
+ * @return array
257
+ */
258
+ protected function _decodeArray()
259
+ {
260
+ $result = array();
261
+ $starttok = $tok = $this->_getNextToken(); // Move past the '['
262
+ $index = 0;
263
+
264
+ while ($tok && $tok != self::RBRACKET) {
265
+ $result[$index++] = $this->_decodeValue();
266
+
267
+ $tok = $this->_token;
268
+
269
+ if ($tok == self::RBRACKET || !$tok) {
270
+ break;
271
+ }
272
+
273
+ if ($tok != self::COMMA) {
274
+ throw new Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
275
+ }
276
+
277
+ $tok = $this->_getNextToken();
278
+ }
279
+
280
+ $this->_getNextToken();
281
+ return($result);
282
+ }
283
+
284
+
285
+ /**
286
+ * Removes whitepsace characters from the source input
287
+ */
288
+ protected function _eatWhitespace()
289
+ {
290
+ if (preg_match(
291
+ '/([\t\b\f\n\r ])*/s',
292
+ $this->_source,
293
+ $matches,
294
+ PREG_OFFSET_CAPTURE,
295
+ $this->_offset)
296
+ && $matches[0][1] == $this->_offset)
297
+ {
298
+ $this->_offset += strlen($matches[0][0]);
299
+ }
300
+ }
301
+
302
+
303
+ /**
304
+ * Retrieves the next token from the source stream
305
+ *
306
+ * @return int Token constant value specified in class definition
307
+ */
308
+ protected function _getNextToken()
309
+ {
310
+ $this->_token = self::EOF;
311
+ $this->_tokenValue = null;
312
+ $this->_eatWhitespace();
313
+
314
+ if ($this->_offset >= $this->_sourceLength) {
315
+ return(self::EOF);
316
+ }
317
+
318
+ $str = $this->_source;
319
+ $str_length = $this->_sourceLength;
320
+ $i = $this->_offset;
321
+ $start = $i;
322
+
323
+ switch ($str{$i}) {
324
+ case '{':
325
+ $this->_token = self::LBRACE;
326
+ break;
327
+ case '}':
328
+ $this->_token = self::RBRACE;
329
+ break;
330
+ case '[':
331
+ $this->_token = self::LBRACKET;
332
+ break;
333
+ case ']':
334
+ $this->_token = self::RBRACKET;
335
+ break;
336
+ case ',':
337
+ $this->_token = self::COMMA;
338
+ break;
339
+ case ':':
340
+ $this->_token = self::COLON;
341
+ break;
342
+ case '"':
343
+ $result = '';
344
+ do {
345
+ $i++;
346
+ if ($i >= $str_length) {
347
+ break;
348
+ }
349
+
350
+ $chr = $str{$i};
351
+ if ($chr == '\\') {
352
+ $i++;
353
+ if ($i >= $str_length) {
354
+ break;
355
+ }
356
+ $chr = $str{$i};
357
+ switch ($chr) {
358
+ case '"' :
359
+ $result .= '"';
360
+ break;
361
+ case '\\':
362
+ $result .= '\\';
363
+ break;
364
+ case '/' :
365
+ $result .= '/';
366
+ break;
367
+ case 'b' :
368
+ $result .= chr(8);
369
+ break;
370
+ case 'f' :
371
+ $result .= chr(12);
372
+ break;
373
+ case 'n' :
374
+ $result .= chr(10);
375
+ break;
376
+ case 'r' :
377
+ $result .= chr(13);
378
+ break;
379
+ case 't' :
380
+ $result .= chr(9);
381
+ break;
382
+ case '\'' :
383
+ $result .= '\'';
384
+ break;
385
+ default:
386
+ throw new Zend_Json_Exception("Illegal escape "
387
+ . "sequence '" . $chr . "'");
388
+ }
389
+ } elseif ($chr == '"') {
390
+ break;
391
+ } else {
392
+ $result .= $chr;
393
+ }
394
+ } while ($i < $str_length);
395
+
396
+ $this->_token = self::DATUM;
397
+ //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
398
+ $this->_tokenValue = $result;
399
+ break;
400
+ case 't':
401
+ if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
402
+ $this->_token = self::DATUM;
403
+ }
404
+ $this->_tokenValue = true;
405
+ $i += 3;
406
+ break;
407
+ case 'f':
408
+ if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
409
+ $this->_token = self::DATUM;
410
+ }
411
+ $this->_tokenValue = false;
412
+ $i += 4;
413
+ break;
414
+ case 'n':
415
+ if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
416
+ $this->_token = self::DATUM;
417
+ }
418
+ $this->_tokenValue = NULL;
419
+ $i += 3;
420
+ break;
421
+ }
422
+
423
+ if ($this->_token != self::EOF) {
424
+ $this->_offset = $i + 1; // Consume the last token character
425
+ return($this->_token);
426
+ }
427
+
428
+ $chr = $str{$i};
429
+ if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
430
+ if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
431
+ $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
432
+
433
+ $datum = $matches[0][0];
434
+
435
+ if (is_numeric($datum)) {
436
+ if (preg_match('/^0\d+$/', $datum)) {
437
+ throw new Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
438
+ } else {
439
+ $val = intval($datum);
440
+ $fVal = floatval($datum);
441
+ $this->_tokenValue = ($val == $fVal ? $val : $fVal);
442
+ }
443
+ } else {
444
+ throw new Zend_Json_Exception("Illegal number format: $datum");
445
+ }
446
+
447
+ $this->_token = self::DATUM;
448
+ $this->_offset = $start + strlen($datum);
449
+ }
450
+ } else {
451
+ throw new Zend_Json_Exception('Illegal Token');
452
+ }
453
+
454
+ return($this->_token);
455
+ }
456
+ }
457
+
includes/phpQuery/phpQuery/Zend/Json/Encoder.php ADDED
@@ -0,0 +1,431 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Json
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /**
23
+ * Zend_Json_Exception
24
+ */
25
+ require_once 'Zend/Json/Exception.php';
26
+
27
+
28
+ /**
29
+ * Encode PHP constructs to JSON
30
+ *
31
+ * @category Zend
32
+ * @package Zend_Json
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Json_Encoder
37
+ {
38
+ /**
39
+ * Whether or not to check for possible cycling
40
+ *
41
+ * @var boolean
42
+ */
43
+ protected $_cycleCheck;
44
+
45
+ /**
46
+ * Additional options used during encoding
47
+ *
48
+ * @var array
49
+ */
50
+ protected $_options = array();
51
+
52
+ /**
53
+ * Array of visited objects; used to prevent cycling.
54
+ *
55
+ * @var array
56
+ */
57
+ protected $_visited = array();
58
+
59
+ /**
60
+ * Constructor
61
+ *
62
+ * @param boolean $cycleCheck Whether or not to check for recursion when encoding
63
+ * @param array $options Additional options used during encoding
64
+ * @return void
65
+ */
66
+ protected function __construct($cycleCheck = false, $options = array())
67
+ {
68
+ $this->_cycleCheck = $cycleCheck;
69
+ $this->_options = $options;
70
+ }
71
+
72
+ /**
73
+ * Use the JSON encoding scheme for the value specified
74
+ *
75
+ * @param mixed $value The value to be encoded
76
+ * @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
77
+ * @param array $options Additional options used during encoding
78
+ * @return string The encoded value
79
+ */
80
+ public static function encode($value, $cycleCheck = false, $options = array())
81
+ {
82
+ $encoder = new self(($cycleCheck) ? true : false, $options);
83
+
84
+ return $encoder->_encodeValue($value);
85
+ }
86
+
87
+ /**
88
+ * Recursive driver which determines the type of value to be encoded
89
+ * and then dispatches to the appropriate method. $values are either
90
+ * - objects (returns from {@link _encodeObject()})
91
+ * - arrays (returns from {@link _encodeArray()})
92
+ * - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
93
+ *
94
+ * @param $value mixed The value to be encoded
95
+ * @return string Encoded value
96
+ */
97
+ protected function _encodeValue(&$value)
98
+ {
99
+ if (is_object($value)) {
100
+ return $this->_encodeObject($value);
101
+ } else if (is_array($value)) {
102
+ return $this->_encodeArray($value);
103
+ }
104
+
105
+ return $this->_encodeDatum($value);
106
+ }
107
+
108
+
109
+
110
+ /**
111
+ * Encode an object to JSON by encoding each of the public properties
112
+ *
113
+ * A special property is added to the JSON object called '__className'
114
+ * that contains the name of the class of $value. This is used to decode
115
+ * the object on the client into a specific class.
116
+ *
117
+ * @param $value object
118
+ * @return string
119
+ * @throws Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
120
+ */
121
+ protected function _encodeObject(&$value)
122
+ {
123
+ if ($this->_cycleCheck) {
124
+ if ($this->_wasVisited($value)) {
125
+
126
+ if (isset($this->_options['silenceCyclicalExceptions'])
127
+ && $this->_options['silenceCyclicalExceptions']===true) {
128
+
129
+ return '"* RECURSION (' . get_class($value) . ') *"';
130
+
131
+ } else {
132
+ throw new Zend_Json_Exception(
133
+ 'Cycles not supported in JSON encoding, cycle introduced by '
134
+ . 'class "' . get_class($value) . '"'
135
+ );
136
+ }
137
+ }
138
+
139
+ $this->_visited[] = $value;
140
+ }
141
+
142
+ $props = '';
143
+ foreach (get_object_vars($value) as $name => $propValue) {
144
+ if (isset($propValue)) {
145
+ $props .= ','
146
+ . $this->_encodeValue($name)
147
+ . ':'
148
+ . $this->_encodeValue($propValue);
149
+ }
150
+ }
151
+
152
+ return '{"__className":"' . get_class($value) . '"'
153
+ . $props . '}';
154
+ }
155
+
156
+
157
+ /**
158
+ * Determine if an object has been serialized already
159
+ *
160
+ * @param mixed $value
161
+ * @return boolean
162
+ */
163
+ protected function _wasVisited(&$value)
164
+ {
165
+ if (in_array($value, $this->_visited, true)) {
166
+ return true;
167
+ }
168
+
169
+ return false;
170
+ }
171
+
172
+
173
+ /**
174
+ * JSON encode an array value
175
+ *
176
+ * Recursively encodes each value of an array and returns a JSON encoded
177
+ * array string.
178
+ *
179
+ * Arrays are defined as integer-indexed arrays starting at index 0, where
180
+ * the last index is (count($array) -1); any deviation from that is
181
+ * considered an associative array, and will be encoded as such.
182
+ *
183
+ * @param $array array
184
+ * @return string
185
+ */
186
+ protected function _encodeArray(&$array)
187
+ {
188
+ $tmpArray = array();
189
+
190
+ // Check for associative array
191
+ if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
192
+ // Associative array
193
+ $result = '{';
194
+ foreach ($array as $key => $value) {
195
+ $key = (string) $key;
196
+ $tmpArray[] = $this->_encodeString($key)
197
+ . ':'
198
+ . $this->_encodeValue($value);
199
+ }
200
+ $result .= implode(',', $tmpArray);
201
+ $result .= '}';
202
+ } else {
203
+ // Indexed array
204
+ $result = '[';
205
+ $length = count($array);
206
+ for ($i = 0; $i < $length; $i++) {
207
+ $tmpArray[] = $this->_encodeValue($array[$i]);
208
+ }
209
+ $result .= implode(',', $tmpArray);
210
+ $result .= ']';
211
+ }
212
+
213
+ return $result;
214
+ }
215
+
216
+
217
+ /**
218
+ * JSON encode a basic data type (string, number, boolean, null)
219
+ *
220
+ * If value type is not a string, number, boolean, or null, the string
221
+ * 'null' is returned.
222
+ *
223
+ * @param $value mixed
224
+ * @return string
225
+ */
226
+ protected function _encodeDatum(&$value)
227
+ {
228
+ $result = 'null';
229
+
230
+ if (is_int($value) || is_float($value)) {
231
+ $result = (string)$value;
232
+ } elseif (is_string($value)) {
233
+ $result = $this->_encodeString($value);
234
+ } elseif (is_bool($value)) {
235
+ $result = $value ? 'true' : 'false';
236
+ }
237
+
238
+ return $result;
239
+ }
240
+
241
+
242
+ /**
243
+ * JSON encode a string value by escaping characters as necessary
244
+ *
245
+ * @param $value string
246
+ * @return string
247
+ */
248
+ protected function _encodeString(&$string)
249
+ {
250
+ // Escape these characters with a backslash:
251
+ // " \ / \n \r \t \b \f
252
+ $search = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
253
+ $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
254
+ $string = str_replace($search, $replace, $string);
255
+
256
+ // Escape certain ASCII characters:
257
+ // 0x08 => \b
258
+ // 0x0c => \f
259
+ $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
260
+
261
+ return '"' . $string . '"';
262
+ }
263
+
264
+
265
+ /**
266
+ * Encode the constants associated with the ReflectionClass
267
+ * parameter. The encoding format is based on the class2 format
268
+ *
269
+ * @param $cls ReflectionClass
270
+ * @return string Encoded constant block in class2 format
271
+ */
272
+ private static function _encodeConstants(ReflectionClass $cls)
273
+ {
274
+ $result = "constants : {";
275
+ $constants = $cls->getConstants();
276
+
277
+ $tmpArray = array();
278
+ if (!empty($constants)) {
279
+ foreach ($constants as $key => $value) {
280
+ $tmpArray[] = "$key: " . self::encode($value);
281
+ }
282
+
283
+ $result .= implode(', ', $tmpArray);
284
+ }
285
+
286
+ return $result . "}";
287
+ }
288
+
289
+
290
+ /**
291
+ * Encode the public methods of the ReflectionClass in the
292
+ * class2 format
293
+ *
294
+ * @param $cls ReflectionClass
295
+ * @return string Encoded method fragment
296
+ *
297
+ */
298
+ private static function _encodeMethods(ReflectionClass $cls)
299
+ {
300
+ $methods = $cls->getMethods();
301
+ $result = 'methods:{';
302
+
303
+ $started = false;
304
+ foreach ($methods as $method) {
305
+ if (! $method->isPublic() || !$method->isUserDefined()) {
306
+ continue;
307
+ }
308
+
309
+ if ($started) {
310
+ $result .= ',';
311
+ }
312
+ $started = true;
313
+
314
+ $result .= '' . $method->getName(). ':function(';
315
+
316
+ if ('__construct' != $method->getName()) {
317
+ $parameters = $method->getParameters();
318
+ $paramCount = count($parameters);
319
+ $argsStarted = false;
320
+
321
+ $argNames = "var argNames=[";
322
+ foreach ($parameters as $param) {
323
+ if ($argsStarted) {
324
+ $result .= ',';
325
+ }
326
+
327
+ $result .= $param->getName();
328
+
329
+ if ($argsStarted) {
330
+ $argNames .= ',';
331
+ }
332
+
333
+ $argNames .= '"' . $param->getName() . '"';
334
+
335
+ $argsStarted = true;
336
+ }
337
+ $argNames .= "];";
338
+
339
+ $result .= "){"
340
+ . $argNames
341
+ . 'var result = ZAjaxEngine.invokeRemoteMethod('
342
+ . "this, '" . $method->getName()
343
+ . "',argNames,arguments);"
344
+ . 'return(result);}';
345
+ } else {
346
+ $result .= "){}";
347
+ }
348
+ }
349
+
350
+ return $result . "}";
351
+ }
352
+
353
+
354
+ /**
355
+ * Encode the public properties of the ReflectionClass in the class2
356
+ * format.
357
+ *
358
+ * @param $cls ReflectionClass
359
+ * @return string Encode properties list
360
+ *
361
+ */
362
+ private static function _encodeVariables(ReflectionClass $cls)
363
+ {
364
+ $properties = $cls->getProperties();
365
+ $propValues = get_class_vars($cls->getName());
366
+ $result = "variables:{";
367
+ $cnt = 0;
368
+
369
+ $tmpArray = array();
370
+ foreach ($properties as $prop) {
371
+ if (! $prop->isPublic()) {
372
+ continue;
373
+ }
374
+
375
+ $tmpArray[] = $prop->getName()
376
+ . ':'
377
+ . self::encode($propValues[$prop->getName()]);
378
+ }
379
+ $result .= implode(',', $tmpArray);
380
+
381
+ return $result . "}";
382
+ }
383
+
384
+ /**
385
+ * Encodes the given $className into the class2 model of encoding PHP
386
+ * classes into JavaScript class2 classes.
387
+ * NOTE: Currently only public methods and variables are proxied onto
388
+ * the client machine
389
+ *
390
+ * @param $className string The name of the class, the class must be
391
+ * instantiable using a null constructor
392
+ * @param $package string Optional package name appended to JavaScript
393
+ * proxy class name
394
+ * @return string The class2 (JavaScript) encoding of the class
395
+ * @throws Zend_Json_Exception
396
+ */
397
+ public static function encodeClass($className, $package = '')
398
+ {
399
+ $cls = new ReflectionClass($className);
400
+ if (! $cls->isInstantiable()) {
401
+ throw new Zend_Json_Exception("$className must be instantiable");
402
+ }
403
+
404
+ return "Class.create('$package$className',{"
405
+ . self::_encodeConstants($cls) .","
406
+ . self::_encodeMethods($cls) .","
407
+ . self::_encodeVariables($cls) .'});';
408
+ }
409
+
410
+
411
+ /**
412
+ * Encode several classes at once
413
+ *
414
+ * Returns JSON encoded classes, using {@link encodeClass()}.
415
+ *
416
+ * @param array $classNames
417
+ * @param string $package
418
+ * @return string
419
+ */
420
+ public static function encodeClasses(array $classNames, $package = '')
421
+ {
422
+ $result = '';
423
+ foreach ($classNames as $className) {
424
+ $result .= self::encodeClass($className, $package);
425
+ }
426
+
427
+ return $result;
428
+ }
429
+
430
+ }
431
+
includes/phpQuery/phpQuery/Zend/Json/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 Zend
16
+ * @package Zend_Json
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /**
23
+ * Zend_Exception
24
+ */
25
+ require_once 'Zend/Exception.php';
26
+
27
+
28
+ /**
29
+ * @category Zend
30
+ * @package Zend_Json
31
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Zend_Json_Exception extends Zend_Exception
35
+ {}
36
+
includes/phpQuery/phpQuery/Zend/Loader.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Loader
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Loader.php 10454 2008-07-26 06:25:51Z ralph $
20
+ */
21
+
22
+ /**
23
+ * Static methods for loading classes and files.
24
+ *
25
+ * @category Zend
26
+ * @package Zend_Loader
27
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ class Zend_Loader
31
+ {
32
+ /**
33
+ * Loads a class from a PHP file. The filename must be formatted
34
+ * as "$class.php".
35
+ *
36
+ * If $dirs is a string or an array, it will search the directories
37
+ * in the order supplied, and attempt to load the first matching file.
38
+ *
39
+ * If $dirs is null, it will split the class name at underscores to
40
+ * generate a path hierarchy (e.g., "Zend_Example_Class" will map
41
+ * to "Zend/Example/Class.php").
42
+ *
43
+ * If the file was not found in the $dirs, or if no $dirs were specified,
44
+ * it will attempt to load it from PHP's include_path.
45
+ *
46
+ * @param string $class - The full class name of a Zend component.
47
+ * @param string|array $dirs - OPTIONAL Either a path or an array of paths
48
+ * to search.
49
+ * @return void
50
+ * @throws Zend_Exception
51
+ */
52
+ public static function loadClass($class, $dirs = null)
53
+ {
54
+ if (class_exists($class, false) || interface_exists($class, false)) {
55
+ return;
56
+ }
57
+
58
+ if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
59
+ require_once 'Zend/Exception.php';
60
+ throw new Zend_Exception('Directory argument must be a string or an array');
61
+ }
62
+
63
+ // autodiscover the path from the class name
64
+ $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
65
+ if (!empty($dirs)) {
66
+ // use the autodiscovered path
67
+ $dirPath = dirname($file);
68
+ if (is_string($dirs)) {
69
+ $dirs = explode(PATH_SEPARATOR, $dirs);
70
+ }
71
+ foreach ($dirs as $key => $dir) {
72
+ if ($dir == '.') {
73
+ $dirs[$key] = $dirPath;
74
+ } else {
75
+ $dir = rtrim($dir, '\\/');
76
+ $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
77
+ }
78
+ }
79
+ $file = basename($file);
80
+ self::loadFile($file, $dirs, true);
81
+ } else {
82
+ self::_securityCheck($file);
83
+ include_once $file;
84
+ }
85
+
86
+ if (!class_exists($class, false) && !interface_exists($class, false)) {
87
+ require_once 'Zend/Exception.php';
88
+ throw new Zend_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file");
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Loads a PHP file. This is a wrapper for PHP's include() function.
94
+ *
95
+ * $filename must be the complete filename, including any
96
+ * extension such as ".php". Note that a security check is performed that
97
+ * does not permit extended characters in the filename. This method is
98
+ * intended for loading Zend Framework files.
99
+ *
100
+ * If $dirs is a string or an array, it will search the directories
101
+ * in the order supplied, and attempt to load the first matching file.
102
+ *
103
+ * If the file was not found in the $dirs, or if no $dirs were specified,
104
+ * it will attempt to load it from PHP's include_path.
105
+ *
106
+ * If $once is TRUE, it will use include_once() instead of include().
107
+ *
108
+ * @param string $filename
109
+ * @param string|array $dirs - OPTIONAL either a path or array of paths
110
+ * to search.
111
+ * @param boolean $once
112
+ * @return boolean
113
+ * @throws Zend_Exception
114
+ */
115
+ public static function loadFile($filename, $dirs = null, $once = false)
116
+ {
117
+ self::_securityCheck($filename);
118
+
119
+ /**
120
+ * Search in provided directories, as well as include_path
121
+ */
122
+ $incPath = false;
123
+ if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) {
124
+ if (is_array($dirs)) {
125
+ $dirs = implode(PATH_SEPARATOR, $dirs);
126
+ }
127
+ $incPath = get_include_path();
128
+ set_include_path($dirs . PATH_SEPARATOR . $incPath);
129
+ }
130
+
131
+ /**
132
+ * Try finding for the plain filename in the include_path.
133
+ */
134
+ if ($once) {
135
+ include_once $filename;
136
+ } else {
137
+ include $filename;
138
+ }
139
+
140
+ /**
141
+ * If searching in directories, reset include_path
142
+ */
143
+ if ($incPath) {
144
+ set_include_path($incPath);
145
+ }
146
+
147
+ return true;
148
+ }
149
+
150
+ /**
151
+ * Returns TRUE if the $filename is readable, or FALSE otherwise.
152
+ * This function uses the PHP include_path, where PHP's is_readable()
153
+ * does not.
154
+ *
155
+ * @param string $filename
156
+ * @return boolean
157
+ */
158
+ public static function isReadable($filename)
159
+ {
160
+ if (!$fh = @fopen($filename, 'r', true)) {
161
+ return false;
162
+ }
163
+ @fclose($fh);
164
+ return true;
165
+ }
166
+
167
+ /**
168
+ * spl_autoload() suitable implementation for supporting class autoloading.
169
+ *
170
+ * Attach to spl_autoload() using the following:
171
+ * <code>
172
+ * spl_autoload_register(array('Zend_Loader', 'autoload'));
173
+ * </code>
174
+ *
175
+ * @param string $class
176
+ * @return string|false Class name on success; false on failure
177
+ */
178
+ public static function autoload($class)
179
+ {
180
+ try {
181
+ self::loadClass($class);
182
+ return $class;
183
+ } catch (Exception $e) {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Register {@link autoload()} with spl_autoload()
190
+ *
191
+ * @param string $class (optional)
192
+ * @param boolean $enabled (optional)
193
+ * @return void
194
+ * @throws Zend_Exception if spl_autoload() is not found
195
+ * or if the specified class does not have an autoload() method.
196
+ */
197
+ public static function registerAutoload($class = 'Zend_Loader', $enabled = true)
198
+ {
199
+ if (!function_exists('spl_autoload_register')) {
200
+ require_once 'Zend/Exception.php';
201
+ throw new Zend_Exception('spl_autoload does not exist in this PHP installation');
202
+ }
203
+
204
+ self::loadClass($class);
205
+ $methods = get_class_methods($class);
206
+ if (!in_array('autoload', (array) $methods)) {
207
+ require_once 'Zend/Exception.php';
208
+ throw new Zend_Exception("The class \"$class\" does not have an autoload() method");
209
+ }
210
+
211
+ if ($enabled === true) {
212
+ spl_autoload_register(array($class, 'autoload'));
213
+ } else {
214
+ spl_autoload_unregister(array($class, 'autoload'));
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Ensure that filename does not contain exploits
220
+ *
221
+ * @param string $filename
222
+ * @return void
223
+ * @throws Zend_Exception
224
+ */
225
+ protected static function _securityCheck($filename)
226
+ {
227
+ /**
228
+ * Security check
229
+ */
230
+ if (preg_match('/[^a-z0-9\\/\\\\_.-]/i', $filename)) {
231
+ require_once 'Zend/Exception.php';
232
+ throw new Zend_Exception('Security check: Illegal character in filename');
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Attempt to include() the file.
238
+ *
239
+ * include() is not prefixed with the @ operator because if
240
+ * the file is loaded and contains a parse error, execution
241
+ * will halt silently and this is difficult to debug.
242
+ *
243
+ * Always set display_errors = Off on production servers!
244
+ *
245
+ * @param string $filespec
246
+ * @param boolean $once
247
+ * @return boolean
248
+ * @deprecated Since 1.5.0; use loadFile() instead
249
+ */
250
+ protected static function _includeFile($filespec, $once = false)
251
+ {
252
+ if ($once) {
253
+ return include_once $filespec;
254
+ } else {
255
+ return include $filespec ;
256
+ }
257
+ }
258
+ }
includes/phpQuery/phpQuery/Zend/Registry.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Registry
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Registry.php 8064 2008-02-16 10:58:39Z thomas $
20
+ */
21
+
22
+ /**
23
+ * Generic storage class helps to manage global data.
24
+ *
25
+ * @category Zend
26
+ * @package Zend_Registry
27
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ class Zend_Registry extends ArrayObject
31
+ {
32
+ /**
33
+ * Class name of the singleton registry object.
34
+ * @var string
35
+ */
36
+ private static $_registryClassName = 'Zend_Registry';
37
+
38
+ /**
39
+ * Registry object provides storage for shared objects.
40
+ * @var Zend_Registry
41
+ */
42
+ private static $_registry = null;
43
+
44
+ /**
45
+ * Retrieves the default registry instance.
46
+ *
47
+ * @return Zend_Registry
48
+ */
49
+ public static function getInstance()
50
+ {
51
+ if (self::$_registry === null) {
52
+ self::init();
53
+ }
54
+
55
+ return self::$_registry;
56
+ }
57
+
58
+ /**
59
+ * Set the default registry instance to a specified instance.
60
+ *
61
+ * @param Zend_Registry $registry An object instance of type Zend_Registry,
62
+ * or a subclass.
63
+ * @return void
64
+ * @throws Zend_Exception if registry is already initialized.
65
+ */
66
+ public static function setInstance(Zend_Registry $registry)
67
+ {
68
+ if (self::$_registry !== null) {
69
+ require_once 'Zend/Exception.php';
70
+ throw new Zend_Exception('Registry is already initialized');
71
+ }
72
+
73
+ self::setClassName(get_class($registry));
74
+ self::$_registry = $registry;
75
+ }
76
+
77
+ /**
78
+ * Initialize the default registry instance.
79
+ *
80
+ * @return void
81
+ */
82
+ protected static function init()
83
+ {
84
+ self::setInstance(new self::$_registryClassName());
85
+ }
86
+
87
+ /**
88
+ * Set the class name to use for the default registry instance.
89
+ * Does not affect the currently initialized instance, it only applies
90
+ * for the next time you instantiate.
91
+ *
92
+ * @param string $registryClassName
93
+ * @return void
94
+ * @throws Zend_Exception if the registry is initialized or if the
95
+ * class name is not valid.
96
+ */
97
+ public static function setClassName($registryClassName = 'Zend_Registry')
98
+ {
99
+ if (self::$_registry !== null) {
100
+ require_once 'Zend/Exception.php';
101
+ throw new Zend_Exception('Registry is already initialized');
102
+ }
103
+
104
+ if (!is_string($registryClassName)) {
105
+ require_once 'Zend/Exception.php';
106
+ throw new Zend_Exception("Argument is not a class name");
107
+ }
108
+
109
+ /**
110
+ * @see Zend_Loader
111
+ */
112
+ require_once 'Zend/Loader.php';
113
+ Zend_Loader::loadClass($registryClassName);
114
+
115
+ self::$_registryClassName = $registryClassName;
116
+ }
117
+
118
+ /**
119
+ * Unset the default registry instance.
120
+ * Primarily used in tearDown() in unit tests.
121
+ * @returns void
122
+ */
123
+ public static function _unsetInstance()
124
+ {
125
+ self::$_registry = null;
126
+ }
127
+
128
+ /**
129
+ * getter method, basically same as offsetGet().
130
+ *
131
+ * This method can be called from an object of type Zend_Registry, or it
132
+ * can be called statically. In the latter case, it uses the default
133
+ * static instance stored in the class.
134
+ *
135
+ * @param string $index - get the value associated with $index
136
+ * @return mixed
137
+ * @throws Zend_Exception if no entry is registerd for $index.
138
+ */
139
+ public static function get($index)
140
+ {
141
+ $instance = self::getInstance();
142
+
143
+ if (!$instance->offsetExists($index)) {
144
+ require_once 'Zend/Exception.php';
145
+ throw new Zend_Exception("No entry is registered for key '$index'");
146
+ }
147
+
148
+ return $instance->offsetGet($index);
149
+ }
150
+
151
+ /**
152
+ * setter method, basically same as offsetSet().
153
+ *
154
+ * This method can be called from an object of type Zend_Registry, or it
155
+ * can be called statically. In the latter case, it uses the default
156
+ * static instance stored in the class.
157
+ *
158
+ * @param string $index The location in the ArrayObject in which to store
159
+ * the value.
160
+ * @param mixed $value The object to store in the ArrayObject.
161
+ * @return void
162
+ */
163
+ public static function set($index, $value)
164
+ {
165
+ $instance = self::getInstance();
166
+ $instance->offsetSet($index, $value);
167
+ }
168
+
169
+ /**
170
+ * Returns TRUE if the $index is a named value in the registry,
171
+ * or FALSE if $index was not found in the registry.
172
+ *
173
+ * @param string $index
174
+ * @return boolean
175
+ */
176
+ public static function isRegistered($index)
177
+ {
178
+ if (self::$_registry === null) {
179
+ return false;
180
+ }
181
+ return self::$_registry->offsetExists($index);
182
+ }
183
+
184
+ /**
185
+ * @param string $index
186
+ * @returns mixed
187
+ *
188
+ * Workaround for http://bugs.php.net/bug.php?id=40442 (ZF-960).
189
+ */
190
+ public function offsetExists($index)
191
+ {
192
+ return array_key_exists($index, $this);
193
+ }
194
+
195
+ }
includes/phpQuery/phpQuery/Zend/Uri.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Uri
17
+ * @copyright Copyright (c) 2005-2008 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 9656 2008-06-10 16:21:13Z dasprid $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Loader
24
+ */
25
+ require_once 'Zend/Loader.php';
26
+
27
+ /**
28
+ * Abstract class for all Zend_Uri handlers
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Uri
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ abstract class Zend_Uri
36
+ {
37
+ /**
38
+ * Scheme of this URI (http, ftp, etc.)
39
+ *
40
+ * @var string
41
+ */
42
+ protected $_scheme = '';
43
+
44
+ /**
45
+ * Return a string representation of this URI.
46
+ *
47
+ * @see getUri()
48
+ * @return string
49
+ */
50
+ public function __toString()
51
+ {
52
+ return $this->getUri();
53
+ }
54
+
55
+ /**
56
+ * Convenience function, checks that a $uri string is well-formed
57
+ * by validating it but not returning an object. Returns TRUE if
58
+ * $uri is a well-formed URI, or FALSE otherwise.
59
+ *
60
+ * @param string $uri The URI to check
61
+ * @return boolean
62
+ */
63
+ public static function check($uri)
64
+ {
65
+ try {
66
+ $uri = self::factory($uri);
67
+ } catch (Exception $e) {
68
+ return false;
69
+ }
70
+
71
+ return $uri->valid();
72
+ }
73
+
74
+ /**
75
+ * Create a new Zend_Uri object for a URI. If building a new URI, then $uri should contain
76
+ * only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI.
77
+ *
78
+ * @param string $uri The URI form which a Zend_Uri instance is created
79
+ * @throws Zend_Uri_Exception When an empty string was supplied for the scheme
80
+ * @throws Zend_Uri_Exception When an illegal scheme is supplied
81
+ * @throws Zend_Uri_Exception When the scheme is not supported
82
+ * @return Zend_Uri
83
+ * @link http://www.faqs.org/rfcs/rfc2396.html
84
+ */
85
+ public static function factory($uri = 'http')
86
+ {
87
+ // Separate the scheme from the scheme-specific parts
88
+ $uri = explode(':', $uri, 2);
89
+ $scheme = strtolower($uri[0]);
90
+ $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
91
+
92
+ if (strlen($scheme) === 0) {
93
+ require_once 'Zend/Uri/Exception.php';
94
+ throw new Zend_Uri_Exception('An empty string was supplied for the scheme');
95
+ }
96
+
97
+ // Security check: $scheme is used to load a class file, so only alphanumerics are allowed.
98
+ if (ctype_alnum($scheme) === false) {
99
+ require_once 'Zend/Uri/Exception.php';
100
+ throw new Zend_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted');
101
+ }
102
+
103
+ /**
104
+ * Create a new Zend_Uri object for the $uri. If a subclass of Zend_Uri exists for the
105
+ * scheme, return an instance of that class. Otherwise, a Zend_Uri_Exception is thrown.
106
+ */
107
+ switch ($scheme) {
108
+ case 'http':
109
+ // Break intentionally omitted
110
+ case 'https':
111
+ $className = 'Zend_Uri_Http';
112
+ break;
113
+
114
+ case 'mailto':
115
+ // TODO
116
+ default:
117
+ require_once 'Zend/Uri/Exception.php';
118
+ throw new Zend_Uri_Exception("Scheme \"$scheme\" is not supported");
119
+ break;
120
+ }
121
+
122
+ Zend_Loader::loadClass($className);
123
+ $schemeHandler = new $className($scheme, $schemeSpecific);
124
+
125
+ return $schemeHandler;
126
+ }
127
+
128
+ /**
129
+ * Get the URI's scheme
130
+ *
131
+ * @return string|false Scheme or false if no scheme is set.
132
+ */
133
+ public function getScheme()
134
+ {
135
+ if (empty($this->_scheme) === false) {
136
+ return $this->_scheme;
137
+ } else {
138
+ return false;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Zend_Uri and its subclasses cannot be instantiated directly.
144
+ * Use Zend_Uri::factory() to return a new Zend_Uri object.
145
+ *
146
+ * @param string $scheme The scheme of the URI
147
+ * @param string $schemeSpecific The scheme-specific part of the URI
148
+ */
149
+ abstract protected function __construct($scheme, $schemeSpecific = '');
150
+
151
+ /**
152
+ * Return a string representation of this URI.
153
+ *
154
+ * @return string
155
+ */
156
+ abstract public function getUri();
157
+
158
+ /**
159
+ * Returns TRUE if this URI is valid, or FALSE otherwise.
160
+ *
161
+ * @return boolean
162
+ */
163
+ abstract public function valid();
164
+ }
includes/phpQuery/phpQuery/Zend/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 Zend
16
+ * @package Zend_Uri
17
+ * @copyright Copyright (c) 2005-2008 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 9656 2008-06-10 16:21:13Z dasprid $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Exception
24
+ */
25
+ require_once 'Zend/Exception.php';
26
+
27
+ /**
28
+ * Exceptions for Zend_Uri
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Uri
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Uri_Exception extends Zend_Exception
36
+ {
37
+ }
includes/phpQuery/phpQuery/Zend/Uri/Http.php ADDED
@@ -0,0 +1,702 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Uri
17
+ * @copyright Copyright (c) 2005-2008 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 9656 2008-06-10 16:21:13Z dasprid $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Uri
24
+ */
25
+ require_once 'Zend/Uri.php';
26
+
27
+ /**
28
+ * @see Zend_Validate_Hostname
29
+ */
30
+ require_once 'Zend/Validate/Hostname.php';
31
+
32
+ /**
33
+ * HTTP(S) URI handler
34
+ *
35
+ * @category Zend
36
+ * @package Zend_Uri
37
+ * @uses Zend_Uri
38
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
39
+ * @license http://framework.zend.com/license/new-bsd New BSD License
40
+ */
41
+ class Zend_Uri_Http extends Zend_Uri
42
+ {
43
+ /**
44
+ * HTTP username
45
+ *
46
+ * @var string
47
+ */
48
+ protected $_username = '';
49
+
50
+ /**
51
+ * HTTP password
52
+ *
53
+ * @var string
54
+ */
55
+ protected $_password = '';
56
+
57
+ /**
58
+ * HTTP host
59
+ *
60
+ * @var string
61
+ */
62
+ protected $_host = '';
63
+
64
+ /**
65
+ * HTTP post
66
+ *
67
+ * @var string
68
+ */
69
+ protected $_port = '';
70
+
71
+ /**
72
+ * HTTP part
73
+ *
74
+ * @var string
75
+ */
76
+ protected $_path = '';
77
+
78
+ /**
79
+ * HTTP query
80
+ *
81
+ * @var string
82
+ */
83
+ protected $_query = '';
84
+
85
+ /**
86
+ * HTTP fragment
87
+ *
88
+ * @var string
89
+ */
90
+ protected $_fragment = '';
91
+
92
+ /**
93
+ * Regular expression grammar rules for validation; values added by constructor
94
+ *
95
+ * @var array
96
+ */
97
+ protected $_regex = array();
98
+
99
+ /**
100
+ * Constructor accepts a string $scheme (e.g., http, https) and a scheme-specific part of the URI
101
+ * (e.g., example.com/path/to/resource?query=param#fragment)
102
+ *
103
+ * @param string $scheme The scheme of the URI
104
+ * @param string $schemeSpecific The scheme-specific part of the URI
105
+ * @throws Zend_Uri_Exception When the URI is not valid
106
+ */
107
+ protected function __construct($scheme, $schemeSpecific = '')
108
+ {
109
+ // Set the scheme
110
+ $this->_scheme = $scheme;
111
+
112
+ // Set up grammar rules for validation via regular expressions. These
113
+ // are to be used with slash-delimited regular expression strings.
114
+ $this->_regex['alphanum'] = '[^\W_]';
115
+ $this->_regex['escaped'] = '(?:%[\da-fA-F]{2})';
116
+ $this->_regex['mark'] = '[-_.!~*\'()\[\]]';
117
+ $this->_regex['reserved'] = '[;\/?:@&=+$,]';
118
+ $this->_regex['unreserved'] = '(?:' . $this->_regex['alphanum'] . '|' . $this->_regex['mark'] . ')';
119
+ $this->_regex['segment'] = '(?:(?:' . $this->_regex['unreserved'] . '|' . $this->_regex['escaped']
120
+ . '|[:@&=+$,;])*)';
121
+ $this->_regex['path'] = '(?:\/' . $this->_regex['segment'] . '?)+';
122
+ $this->_regex['uric'] = '(?:' . $this->_regex['reserved'] . '|' . $this->_regex['unreserved'] . '|'
123
+ . $this->_regex['escaped'] . ')';
124
+ // If no scheme-specific part was supplied, the user intends to create
125
+ // a new URI with this object. No further parsing is required.
126
+ if (strlen($schemeSpecific) === 0) {
127
+ return;
128
+ }
129
+
130
+ // Parse the scheme-specific URI parts into the instance variables.
131
+ $this->_parseUri($schemeSpecific);
132
+
133
+ // Validate the URI
134
+ if ($this->valid() === false) {
135
+ require_once 'Zend/Uri/Exception.php';
136
+ throw new Zend_Uri_Exception('Invalid URI supplied');
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Creates a Zend_Uri_Http from the given string
142
+ *
143
+ * @param string $uri String to create URI from, must start with
144
+ * 'http://' or 'https://'
145
+ * @throws InvalidArgumentException When the given $uri is not a string or
146
+ * does not start with http:// or https://
147
+ * @throws Zend_Uri_Exception When the given $uri is invalid
148
+ * @return Zend_Uri_Http
149
+ */
150
+ public static function fromString($uri)
151
+ {
152
+ if (is_string($uri) === false) {
153
+ throw new InvalidArgumentException('$uri is not a string');
154
+ }
155
+
156
+ $uri = explode(':', $uri, 2);
157
+ $scheme = strtolower($uri[0]);
158
+ $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
159
+
160
+ if (in_array($scheme, array('http', 'https')) === false) {
161
+ throw new Zend_Uri_Exception("Invalid scheme: '$scheme'");
162
+ }
163
+
164
+ $schemeHandler = new Zend_Uri_Http($scheme, $schemeSpecific);
165
+ return $schemeHandler;
166
+ }
167
+
168
+ /**
169
+ * Parse the scheme-specific portion of the URI and place its parts into instance variables.
170
+ *
171
+ * @param string $schemeSpecific The scheme-specific portion to parse
172
+ * @throws Zend_Uri_Exception When scheme-specific decoposition fails
173
+ * @throws Zend_Uri_Exception When authority decomposition fails
174
+ * @return void
175
+ */
176
+ protected function _parseUri($schemeSpecific)
177
+ {
178
+ // High-level decomposition parser
179
+ $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
180
+ $status = @preg_match($pattern, $schemeSpecific, $matches);
181
+ if ($status === false) {
182
+ require_once 'Zend/Uri/Exception.php';
183
+ throw new Zend_Uri_Exception('Internal error: scheme-specific decomposition failed');
184
+ }
185
+
186
+ // Failed decomposition; no further processing needed
187
+ if ($status === false) {
188
+ return;
189
+ }
190
+
191
+ // Save URI components that need no further decomposition
192
+ $this->_path = isset($matches[4]) === true ? $matches[4] : '';
193
+ $this->_query = isset($matches[6]) === true ? $matches[6] : '';
194
+ $this->_fragment = isset($matches[8]) === true ? $matches[8] : '';
195
+
196
+ // Additional decomposition to get username, password, host, and port
197
+ $combo = isset($matches[3]) === true ? $matches[3] : '';
198
+ $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
199
+ $status = @preg_match($pattern, $combo, $matches);
200
+ if ($status === false) {
201
+ require_once 'Zend/Uri/Exception.php';
202
+ throw new Zend_Uri_Exception('Internal error: authority decomposition failed');
203
+ }
204
+
205
+ // Failed decomposition; no further processing needed
206
+ if ($status === false) {
207
+ return;
208
+ }
209
+
210
+ // Save remaining URI components
211
+ $this->_username = isset($matches[2]) === true ? $matches[2] : '';
212
+ $this->_password = isset($matches[4]) === true ? $matches[4] : '';
213
+ $this->_host = isset($matches[5]) === true ? $matches[5] : '';
214
+ $this->_port = isset($matches[7]) === true ? $matches[7] : '';
215
+
216
+ }
217
+
218
+ /**
219
+ * Returns a URI based on current values of the instance variables. If any
220
+ * part of the URI does not pass validation, then an exception is thrown.
221
+ *
222
+ * @throws Zend_Uri_Exception When one or more parts of the URI are invalid
223
+ * @return string
224
+ */
225
+ public function getUri()
226
+ {
227
+ if ($this->valid() === false) {
228
+ require_once 'Zend/Uri/Exception.php';
229
+ throw new Zend_Uri_Exception('One or more parts of the URI are invalid');
230
+ }
231
+
232
+ $password = strlen($this->_password) > 0 ? ":$this->_password" : '';
233
+ $auth = strlen($this->_username) > 0 ? "$this->_username$password@" : '';
234
+ $port = strlen($this->_port) > 0 ? ":$this->_port" : '';
235
+ $query = strlen($this->_query) > 0 ? "?$this->_query" : '';
236
+ $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : '';
237
+
238
+ return $this->_scheme
239
+ . '://'
240
+ . $auth
241
+ . $this->_host
242
+ . $port
243
+ . $this->_path
244
+ . $query
245
+ . $fragment;
246
+ }
247
+
248
+ /**
249
+ * Validate the current URI from the instance variables. Returns true if and only if all
250
+ * parts pass validation.
251
+ *
252
+ * @return boolean
253
+ */
254
+ public function valid()
255
+ {
256
+ // Return true if and only if all parts of the URI have passed validation
257
+ return $this->validateUsername()
258
+ and $this->validatePassword()
259
+ and $this->validateHost()
260
+ and $this->validatePort()
261
+ and $this->validatePath()
262
+ and $this->validateQuery()
263
+ and $this->validateFragment();
264
+ }
265
+
266
+ /**
267
+ * Returns the username portion of the URL, or FALSE if none.
268
+ *
269
+ * @return string
270
+ */
271
+ public function getUsername()
272
+ {
273
+ return strlen($this->_username) > 0 ? $this->_username : false;
274
+ }
275
+
276
+ /**
277
+ * Returns true if and only if the username passes validation. If no username is passed,
278
+ * then the username contained in the instance variable is used.
279
+ *
280
+ * @param string $username The HTTP username
281
+ * @throws Zend_Uri_Exception When username validation fails
282
+ * @return boolean
283
+ * @link http://www.faqs.org/rfcs/rfc2396.html
284
+ */
285
+ public function validateUsername($username = null)
286
+ {
287
+ if ($username === null) {
288
+ $username = $this->_username;
289
+ }
290
+
291
+ // If the username is empty, then it is considered valid
292
+ if (strlen($username) === 0) {
293
+ return true;
294
+ }
295
+
296
+ // Check the username against the allowed values
297
+ $status = @preg_match('/^(' . $this->_regex['alphanum'] . '|' . $this->_regex['mark'] . '|'
298
+ . $this->_regex['escaped'] . '|[;:&=+$,])+$/', $username);
299
+ if ($status === false) {
300
+ require_once 'Zend/Uri/Exception.php';
301
+ throw new Zend_Uri_Exception('Internal error: username validation failed');
302
+ }
303
+
304
+ return $status === 1;
305
+ }
306
+
307
+ /**
308
+ * Sets the username for the current URI, and returns the old username
309
+ *
310
+ * @param string $username The HTTP username
311
+ * @throws Zend_Uri_Exception When $username is not a valid HTTP username
312
+ * @return string
313
+ */
314
+ public function setUsername($username)
315
+ {
316
+ if ($this->validateUsername($username) === false) {
317
+ require_once 'Zend/Uri/Exception.php';
318
+ throw new Zend_Uri_Exception("Username \"$username\" is not a valid HTTP username");
319
+ }
320
+
321
+ $oldUsername = $this->_username;
322
+ $this->_username = $username;
323
+
324
+ return $oldUsername;
325
+ }
326
+
327
+ /**
328
+ * Returns the password portion of the URL, or FALSE if none.
329
+ *
330
+ * @return string
331
+ */
332
+ public function getPassword()
333
+ {
334
+ return strlen($this->_password) > 0 ? $this->_password : false;
335
+ }
336
+
337
+ /**
338
+ * Returns true if and only if the password passes validation. If no password is passed,
339
+ * then the password contained in the instance variable is used.
340
+ *
341
+ * @param string $password The HTTP password
342
+ * @throws Zend_Uri_Exception When password validation fails
343
+ * @return boolean
344
+ * @link http://www.faqs.org/rfcs/rfc2396.html
345
+ */
346
+ public function validatePassword($password = null)
347
+ {
348
+ if ($password === null) {
349
+ $password = $this->_password;
350
+ }
351
+
352
+ // If the password is empty, then it is considered valid
353
+ if (strlen($password) === 0) {
354
+ return true;
355
+ }
356
+
357
+ // If the password is nonempty, but there is no username, then it is considered invalid
358
+ if (strlen($password) > 0 and strlen($this->_username) === 0) {
359
+ return false;
360
+ }
361
+
362
+ // Check the password against the allowed values
363
+ $status = @preg_match('/^(' . $this->_regex['alphanum'] . '|' . $this->_regex['mark'] . '|'
364
+ . $this->_regex['escaped'] . '|[;:&=+$,])+$/', $password);
365
+ if ($status === false) {
366
+ require_once 'Zend/Uri/Exception.php';
367
+ throw new Zend_Uri_Exception('Internal error: password validation failed.');
368
+ }
369
+
370
+ return $status == 1;
371
+ }
372
+
373
+ /**
374
+ * Sets the password for the current URI, and returns the old password
375
+ *
376
+ * @param string $password The HTTP password
377
+ * @throws Zend_Uri_Exception When $password is not a valid HTTP password
378
+ * @return string
379
+ */
380
+ public function setPassword($password)
381
+ {
382
+ if ($this->validatePassword($password) === false) {
383
+ require_once 'Zend/Uri/Exception.php';
384
+ throw new Zend_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
385
+ }
386
+
387
+ $oldPassword = $this->_password;
388
+ $this->_password = $password;
389
+
390
+ return $oldPassword;
391
+ }
392
+
393
+ /**
394
+ * Returns the domain or host IP portion of the URL, or FALSE if none.
395
+ *
396
+ * @return string
397
+ */
398
+ public function getHost()
399
+ {
400
+ return strlen($this->_host) > 0 ? $this->_host : false;
401
+ }
402
+
403
+ /**
404
+ * Returns true if and only if the host string passes validation. If no host is passed,
405
+ * then the host contained in the instance variable is used.
406
+ *
407
+ * @param string $host The HTTP host
408
+ * @return boolean
409
+ * @uses Zend_Filter
410
+ */
411
+ public function validateHost($host = null)
412
+ {
413
+ if ($host === null) {
414
+ $host = $this->_host;
415
+ }
416
+
417
+ // If the host is empty, then it is considered invalid
418
+ if (strlen($host) === 0) {
419
+ return false;
420
+ }
421
+
422
+ // Check the host against the allowed values; delegated to Zend_Filter.
423
+ $validate = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL);
424
+
425
+ return $validate->isValid($host);
426
+ }
427
+
428
+ /**
429
+ * Sets the host for the current URI, and returns the old host
430
+ *
431
+ * @param string $host The HTTP host
432
+ * @throws Zend_Uri_Exception When $host is nota valid HTTP host
433
+ * @return string
434
+ */
435
+ public function setHost($host)
436
+ {
437
+ if ($this->validateHost($host) === false) {
438
+ require_once 'Zend/Uri/Exception.php';
439
+ throw new Zend_Uri_Exception("Host \"$host\" is not a valid HTTP host");
440
+ }
441
+
442
+ $oldHost = $this->_host;
443
+ $this->_host = $host;
444
+
445
+ return $oldHost;
446
+ }
447
+
448
+ /**
449
+ * Returns the TCP port, or FALSE if none.
450
+ *
451
+ * @return string
452
+ */
453
+ public function getPort()
454
+ {
455
+ return strlen($this->_port) > 0 ? $this->_port : false;
456
+ }
457
+
458
+ /**
459
+ * Returns true if and only if the TCP port string passes validation. If no port is passed,
460
+ * then the port contained in the instance variable is used.
461
+ *
462
+ * @param string $port The HTTP port
463
+ * @return boolean
464
+ */
465
+ public function validatePort($port = null)
466
+ {
467
+ if ($port === null) {
468
+ $port = $this->_port;
469
+ }
470
+
471
+ // If the port is empty, then it is considered valid
472
+ if (strlen($port) === 0) {
473
+ return true;
474
+ }
475
+
476
+ // Check the port against the allowed values
477
+ return ctype_digit((string) $port) and 1 <= $port and $port <= 65535;
478
+ }
479
+
480
+ /**
481
+ * Sets the port for the current URI, and returns the old port
482
+ *
483
+ * @param string $port The HTTP port
484
+ * @throws Zend_Uri_Exception When $port is not a valid HTTP port
485
+ * @return string
486
+ */
487
+ public function setPort($port)
488
+ {
489
+ if ($this->validatePort($port) === false) {
490
+ require_once 'Zend/Uri/Exception.php';
491
+ throw new Zend_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
492
+ }
493
+
494
+ $oldPort = $this->_port;
495
+ $this->_port = $port;
496
+
497
+ return $oldPort;
498
+ }
499
+
500
+ /**
501
+ * Returns the path and filename portion of the URL, or FALSE if none.
502
+ *
503
+ * @return string
504
+ */
505
+ public function getPath()
506
+ {
507
+ return strlen($this->_path) > 0 ? $this->_path : '/';
508
+ }
509
+
510
+ /**
511
+ * Returns true if and only if the path string passes validation. If no path is passed,
512
+ * then the path contained in the instance variable is used.
513
+ *
514
+ * @param string $path The HTTP path
515
+ * @throws Zend_Uri_Exception When path validation fails
516
+ * @return boolean
517
+ */
518
+ public function validatePath($path = null)
519
+ {
520
+ if ($path === null) {
521
+ $path = $this->_path;
522
+ }
523
+
524
+ // If the path is empty, then it is considered valid
525
+ if (strlen($path) === 0) {
526
+ return true;
527
+ }
528
+
529
+ // Determine whether the path is well-formed
530
+ $pattern = '/^' . $this->_regex['path'] . '$/';
531
+ $status = @preg_match($pattern, $path);
532
+ if ($status === false) {
533
+ require_once 'Zend/Uri/Exception.php';
534
+ throw new Zend_Uri_Exception('Internal error: path validation failed');
535
+ }
536
+
537
+ return (boolean) $status;
538
+ }
539
+
540
+ /**
541
+ * Sets the path for the current URI, and returns the old path
542
+ *
543
+ * @param string $path The HTTP path
544
+ * @throws Zend_Uri_Exception When $path is not a valid HTTP path
545
+ * @return string
546
+ */
547
+ public function setPath($path)
548
+ {
549
+ if ($this->validatePath($path) === false) {
550
+ require_once 'Zend/Uri/Exception.php';
551
+ throw new Zend_Uri_Exception("Path \"$path\" is not a valid HTTP path");
552
+ }
553
+
554
+ $oldPath = $this->_path;
555
+ $this->_path = $path;
556
+
557
+ return $oldPath;
558
+ }
559
+
560
+ /**
561
+ * Returns the query portion of the URL (after ?), or FALSE if none.
562
+ *
563
+ * @return string
564
+ */
565
+ public function getQuery()
566
+ {
567
+ return strlen($this->_query) > 0 ? $this->_query : false;
568
+ }
569
+
570
+ /**
571
+ * Returns true if and only if the query string passes validation. If no query is passed,
572
+ * then the query string contained in the instance variable is used.
573
+ *
574
+ * @param string $query The query to validate
575
+ * @throws Zend_Uri_Exception When query validation fails
576
+ * @return boolean
577
+ * @link http://www.faqs.org/rfcs/rfc2396.html
578
+ */
579
+ public function validateQuery($query = null)
580
+ {
581
+ if ($query === null) {
582
+ $query = $this->_query;
583
+ }
584
+
585
+ // If query is empty, it is considered to be valid
586
+ if (strlen($query) === 0) {
587
+ return true;
588
+ }
589
+
590
+ // Determine whether the query is well-formed
591
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
592
+ $status = @preg_match($pattern, $query);
593
+ if ($status === false) {
594
+ require_once 'Zend/Uri/Exception.php';
595
+ throw new Zend_Uri_Exception('Internal error: query validation failed');
596
+ }
597
+
598
+ return $status == 1;
599
+ }
600
+
601
+ /**
602
+ * Set the query string for the current URI, and return the old query
603
+ * string This method accepts both strings and arrays.
604
+ *
605
+ * @param string|array $query The query string or array
606
+ * @throws Zend_Uri_Exception When $query is not a valid query string
607
+ * @return string Old query string
608
+ */
609
+ public function setQuery($query)
610
+ {
611
+ $oldQuery = $this->_query;
612
+
613
+ // If query is empty, set an empty string
614
+ if (empty($query) === true) {
615
+ $this->_query = '';
616
+ return $oldQuery;
617
+ }
618
+
619
+ // If query is an array, make a string out of it
620
+ if (is_array($query) === true) {
621
+ $query = http_build_query($query, '', '&');
622
+ } else {
623
+ // If it is a string, make sure it is valid. If not parse and encode it
624
+ $query = (string) $query;
625
+ if ($this->validateQuery($query) === false) {
626
+ parse_str($query, $queryArray);
627
+ $query = http_build_query($queryArray, '', '&');
628
+ }
629
+ }
630
+
631
+ // Make sure the query is valid, and set it
632
+ if ($this->validateQuery($query) === false) {
633
+ require_once 'Zend/Uri/Exception.php';
634
+ throw new Zend_Uri_Exception("'$query' is not a valid query string");
635
+ }
636
+
637
+ $this->_query = $query;
638
+
639
+ return $oldQuery;
640
+ }
641
+
642
+ /**
643
+ * Returns the fragment portion of the URL (after #), or FALSE if none.
644
+ *
645
+ * @return string|false
646
+ */
647
+ public function getFragment()
648
+ {
649
+ return strlen($this->_fragment) > 0 ? $this->_fragment : false;
650
+ }
651
+
652
+ /**
653
+ * Returns true if and only if the fragment passes validation. If no fragment is passed,
654
+ * then the fragment contained in the instance variable is used.
655
+ *
656
+ * @param string $fragment Fragment of an URI
657
+ * @throws Zend_Uri_Exception When fragment validation fails
658
+ * @return boolean
659
+ * @link http://www.faqs.org/rfcs/rfc2396.html
660
+ */
661
+ public function validateFragment($fragment = null)
662
+ {
663
+ if ($fragment === null) {
664
+ $fragment = $this->_fragment;
665
+ }
666
+
667
+ // If fragment is empty, it is considered to be valid
668
+ if (strlen($fragment) === 0) {
669
+ return true;
670
+ }
671
+
672
+ // Determine whether the fragment is well-formed
673
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
674
+ $status = @preg_match($pattern, $fragment);
675
+ if ($status === false) {
676
+ require_once 'Zend/Uri/Exception.php';
677
+ throw new Zend_Uri_Exception('Internal error: fragment validation failed');
678
+ }
679
+
680
+ return (boolean) $status;
681
+ }
682
+
683
+ /**
684
+ * Sets the fragment for the current URI, and returns the old fragment
685
+ *
686
+ * @param string $fragment Fragment of the current URI
687
+ * @throws Zend_Uri_Exception When $fragment is not a valid HTTP fragment
688
+ * @return string
689
+ */
690
+ public function setFragment($fragment)
691
+ {
692
+ if ($this->validateFragment($fragment) === false) {
693
+ require_once 'Zend/Uri/Exception.php';
694
+ throw new Zend_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
695
+ }
696
+
697
+ $oldFragment = $this->_fragment;
698
+ $this->_fragment = $fragment;
699
+
700
+ return $oldFragment;
701
+ }
702
+ }
includes/phpQuery/phpQuery/Zend/Validate/Abstract.php ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Abstract.php 10648 2008-08-04 20:58:06Z matthew $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Interface
26
+ */
27
+ require_once 'Zend/Validate/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
37
+ {
38
+ /**
39
+ * The value to be validated
40
+ *
41
+ * @var mixed
42
+ */
43
+ protected $_value;
44
+
45
+ /**
46
+ * Additional variables available for validation failure messages
47
+ *
48
+ * @var array
49
+ */
50
+ protected $_messageVariables = array();
51
+
52
+ /**
53
+ * Validation failure message template definitions
54
+ *
55
+ * @var array
56
+ */
57
+ protected $_messageTemplates = array();
58
+
59
+ /**
60
+ * Array of validation failure messages
61
+ *
62
+ * @var array
63
+ */
64
+ protected $_messages = array();
65
+
66
+ /**
67
+ * Flag indidcating whether or not value should be obfuscated in error
68
+ * messages
69
+ * @var bool
70
+ */
71
+ protected $_obscureValue = false;
72
+
73
+ /**
74
+ * Array of validation failure message codes
75
+ *
76
+ * @var array
77
+ * @deprecated Since 1.5.0
78
+ */
79
+ protected $_errors = array();
80
+
81
+ /**
82
+ * Translation object
83
+ * @var Zend_Translate
84
+ */
85
+ protected $_translator;
86
+
87
+ /**
88
+ * Default translation object for all validate objects
89
+ * @var Zend_Translate
90
+ */
91
+ protected static $_defaultTranslator;
92
+
93
+ /**
94
+ * Returns array of validation failure messages
95
+ *
96
+ * @return array
97
+ */
98
+ public function getMessages()
99
+ {
100
+ return $this->_messages;
101
+ }
102
+
103
+ /**
104
+ * Returns an array of the names of variables that are used in constructing validation failure messages
105
+ *
106
+ * @return array
107
+ */
108
+ public function getMessageVariables()
109
+ {
110
+ return array_keys($this->_messageVariables);
111
+ }
112
+
113
+ /**
114
+ * Sets the validation failure message template for a particular key
115
+ *
116
+ * @param string $messageString
117
+ * @param string $messageKey OPTIONAL
118
+ * @return Zend_Validate_Abstract Provides a fluent interface
119
+ * @throws Zend_Validate_Exception
120
+ */
121
+ public function setMessage($messageString, $messageKey = null)
122
+ {
123
+ if ($messageKey === null) {
124
+ $keys = array_keys($this->_messageTemplates);
125
+ $messageKey = current($keys);
126
+ }
127
+ if (!isset($this->_messageTemplates[$messageKey])) {
128
+ require_once 'Zend/Validate/Exception.php';
129
+ throw new Zend_Validate_Exception("No message template exists for key '$messageKey'");
130
+ }
131
+ $this->_messageTemplates[$messageKey] = $messageString;
132
+ return $this;
133
+ }
134
+
135
+ /**
136
+ * Sets validation failure message templates given as an array, where the array keys are the message keys,
137
+ * and the array values are the message template strings.
138
+ *
139
+ * @param array $messages
140
+ * @return Zend_Validate_Abstract
141
+ */
142
+ public function setMessages(array $messages)
143
+ {
144
+ foreach ($messages as $key => $message) {
145
+ $this->setMessage($message, $key);
146
+ }
147
+ return $this;
148
+ }
149
+
150
+ /**
151
+ * Magic function returns the value of the requested property, if and only if it is the value or a
152
+ * message variable.
153
+ *
154
+ * @param string $property
155
+ * @return mixed
156
+ * @throws Zend_Validate_Exception
157
+ */
158
+ public function __get($property)
159
+ {
160
+ if ($property == 'value') {
161
+ return $this->_value;
162
+ }
163
+ if (array_key_exists($property, $this->_messageVariables)) {
164
+ return $this->{$this->_messageVariables[$property]};
165
+ }
166
+ /**
167
+ * @see Zend_Validate_Exception
168
+ */
169
+ require_once 'Zend/Validate/Exception.php';
170
+ throw new Zend_Validate_Exception("No property exists by the name '$property'");
171
+ }
172
+
173
+ /**
174
+ * Constructs and returns a validation failure message with the given message key and value.
175
+ *
176
+ * Returns null if and only if $messageKey does not correspond to an existing template.
177
+ *
178
+ * If a translator is available and a translation exists for $messageKey,
179
+ * the translation will be used.
180
+ *
181
+ * @param string $messageKey
182
+ * @param string $value
183
+ * @return string
184
+ */
185
+ protected function _createMessage($messageKey, $value)
186
+ {
187
+ if (!isset($this->_messageTemplates[$messageKey])) {
188
+ return null;
189
+ }
190
+
191
+ $message = $this->_messageTemplates[$messageKey];
192
+
193
+ if (null !== ($translator = $this->getTranslator())) {
194
+ if ($translator->isTranslated($message)) {
195
+ $message = $translator->translate($message);
196
+ } elseif ($translator->isTranslated($messageKey)) {
197
+ $message = $translator->translate($messageKey);
198
+ }
199
+ }
200
+
201
+ if ($this->getObscureValue()) {
202
+ $value = str_repeat('*', strlen($value));
203
+ }
204
+
205
+ $message = str_replace('%value%', (string) $value, $message);
206
+ foreach ($this->_messageVariables as $ident => $property) {
207
+ $message = str_replace("%$ident%", $this->$property, $message);
208
+ }
209
+ return $message;
210
+ }
211
+
212
+ /**
213
+ * @param string $messageKey OPTIONAL
214
+ * @param string $value OPTIONAL
215
+ * @return void
216
+ */
217
+ protected function _error($messageKey = null, $value = null)
218
+ {
219
+ if ($messageKey === null) {
220
+ $keys = array_keys($this->_messageTemplates);
221
+ $messageKey = current($keys);
222
+ }
223
+ if ($value === null) {
224
+ $value = $this->_value;
225
+ }
226
+ $this->_errors[] = $messageKey;
227
+ $this->_messages[$messageKey] = $this->_createMessage($messageKey, $value);
228
+ }
229
+
230
+ /**
231
+ * Sets the value to be validated and clears the messages and errors arrays
232
+ *
233
+ * @param mixed $value
234
+ * @return void
235
+ */
236
+ protected function _setValue($value)
237
+ {
238
+ $this->_value = $value;
239
+ $this->_messages = array();
240
+ $this->_errors = array();
241
+ }
242
+
243
+ /**
244
+ * Returns array of validation failure message codes
245
+ *
246
+ * @return array
247
+ * @deprecated Since 1.5.0
248
+ */
249
+ public function getErrors()
250
+ {
251
+ return $this->_errors;
252
+ }
253
+
254
+ /**
255
+ * Set flag indicating whether or not value should be obfuscated in messages
256
+ *
257
+ * @param bool $flag
258
+ * @return Zend_Validate_Abstract
259
+ */
260
+ public function setObscureValue($flag)
261
+ {
262
+ $this->_obscureValue = (bool) $flag;
263
+ return $this;
264
+ }
265
+
266
+ /**
267
+ * Retrieve flag indicating whether or not value should be obfuscated in
268
+ * messages
269
+ *
270
+ * @return bool
271
+ */
272
+ public function getObscureValue()
273
+ {
274
+ return $this->_obscureValue;
275
+ }
276
+
277
+ /**
278
+ * Set translation object
279
+ *
280
+ * @param Zend_Translate|Zend_Translate_Adapter|null $translator
281
+ * @return Zend_Validate_Abstract
282
+ */
283
+ public function setTranslator($translator = null)
284
+ {
285
+ if ((null === $translator) || ($translator instanceof Zend_Translate_Adapter)) {
286
+ $this->_translator = $translator;
287
+ } elseif ($translator instanceof Zend_Translate) {
288
+ $this->_translator = $translator->getAdapter();
289
+ } else {
290
+ require_once 'Zend/Validate/Exception.php';
291
+ throw new Zend_Validate_Exception('Invalid translator specified');
292
+ }
293
+ return $this;
294
+ }
295
+
296
+ /**
297
+ * Return translation object
298
+ *
299
+ * @return Zend_Translate_Adapter|null
300
+ */
301
+ public function getTranslator()
302
+ {
303
+ if (null === $this->_translator) {
304
+ return self::getDefaultTranslator();
305
+ }
306
+
307
+ return $this->_translator;
308
+ }
309
+
310
+ /**
311
+ * Set default translation object for all validate objects
312
+ *
313
+ * @param Zend_Translate|Zend_Translate_Adapter|null $translator
314
+ * @return void
315
+ */
316
+ public static function setDefaultTranslator($translator = null)
317
+ {
318
+ if ((null === $translator) || ($translator instanceof Zend_Translate_Adapter)) {
319
+ self::$_defaultTranslator = $translator;
320
+ } elseif ($translator instanceof Zend_Translate) {
321
+ self::$_defaultTranslator = $translator->getAdapter();
322
+ } else {
323
+ require_once 'Zend/Validate/Exception.php';
324
+ throw new Zend_Validate_Exception('Invalid translator specified');
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Get default translation object for all validate objects
330
+ *
331
+ * @return Zend_Translate_Adapter|null
332
+ */
333
+ public static function getDefaultTranslator()
334
+ {
335
+ if (null === self::$_defaultTranslator) {
336
+ require_once 'Zend/Registry.php';
337
+ if (Zend_Registry::isRegistered('Zend_Translate')) {
338
+ $translator = Zend_Registry::get('Zend_Translate');
339
+ if ($translator instanceof Zend_Translate_Adapter) {
340
+ return $translator;
341
+ } elseif ($translator instanceof Zend_Translate) {
342
+ return $translator->getAdapter();
343
+ }
344
+ }
345
+ }
346
+ return self::$_defaultTranslator;
347
+ }
348
+ }
includes/phpQuery/phpQuery/Zend/Validate/Alnum.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Alnum.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Alnum extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value contains non-alphabetic or non-digit characters
40
+ */
41
+ const NOT_ALNUM = 'notAlnum';
42
+
43
+ /**
44
+ * Validation failure message key for when the value is an empty string
45
+ */
46
+ const STRING_EMPTY = 'stringEmpty';
47
+
48
+ /**
49
+ * Whether to allow white space characters; off by default
50
+ *
51
+ * @var boolean
52
+ */
53
+ public $allowWhiteSpace;
54
+
55
+ /**
56
+ * Alphanumeric filter used for validation
57
+ *
58
+ * @var Zend_Filter_Alnum
59
+ */
60
+ protected static $_filter = null;
61
+
62
+ /**
63
+ * Validation failure message template definitions
64
+ *
65
+ * @var array
66
+ */
67
+ protected $_messageTemplates = array(
68
+ self::NOT_ALNUM => "'%value%' has not only alphabetic and digit characters",
69
+ self::STRING_EMPTY => "'%value%' is an empty string"
70
+ );
71
+
72
+ /**
73
+ * Sets default option values for this instance
74
+ *
75
+ * @param boolean $allowWhiteSpace
76
+ * @return void
77
+ */
78
+ public function __construct($allowWhiteSpace = false)
79
+ {
80
+ $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
81
+ }
82
+
83
+ /**
84
+ * Defined by Zend_Validate_Interface
85
+ *
86
+ * Returns true if and only if $value contains only alphabetic and digit characters
87
+ *
88
+ * @param string $value
89
+ * @return boolean
90
+ */
91
+ public function isValid($value)
92
+ {
93
+ $valueString = (string) $value;
94
+
95
+ $this->_setValue($valueString);
96
+
97
+ if ('' === $valueString) {
98
+ $this->_error(self::STRING_EMPTY);
99
+ return false;
100
+ }
101
+
102
+ if (null === self::$_filter) {
103
+ /**
104
+ * @see Zend_Filter_Alnum
105
+ */
106
+ require_once 'Zend/Filter/Alnum.php';
107
+ self::$_filter = new Zend_Filter_Alnum();
108
+ }
109
+
110
+ self::$_filter->allowWhiteSpace = $this->allowWhiteSpace;
111
+
112
+ if ($valueString !== self::$_filter->filter($valueString)) {
113
+ $this->_error(self::NOT_ALNUM);
114
+ return false;
115
+ }
116
+
117
+ return true;
118
+ }
119
+
120
+ }
includes/phpQuery/phpQuery/Zend/Validate/Alpha.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Alpha.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Alpha extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value contains non-alphabetic characters
40
+ */
41
+ const NOT_ALPHA = 'notAlpha';
42
+
43
+ /**
44
+ * Validation failure message key for when the value is an empty string
45
+ */
46
+ const STRING_EMPTY = 'stringEmpty';
47
+
48
+ /**
49
+ * Whether to allow white space characters; off by default
50
+ *
51
+ * @var boolean
52
+ */
53
+ public $allowWhiteSpace;
54
+
55
+ /**
56
+ * Alphabetic filter used for validation
57
+ *
58
+ * @var Zend_Filter_Alpha
59
+ */
60
+ protected static $_filter = null;
61
+
62
+ /**
63
+ * Validation failure message template definitions
64
+ *
65
+ * @var array
66
+ */
67
+ protected $_messageTemplates = array(
68
+ self::NOT_ALPHA => "'%value%' has not only alphabetic characters",
69
+ self::STRING_EMPTY => "'%value%' is an empty string"
70
+ );
71
+
72
+ /**
73
+ * Sets default option values for this instance
74
+ *
75
+ * @param boolean $allowWhiteSpace
76
+ * @return void
77
+ */
78
+ public function __construct($allowWhiteSpace = false)
79
+ {
80
+ $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
81
+ }
82
+
83
+ /**
84
+ * Defined by Zend_Validate_Interface
85
+ *
86
+ * Returns true if and only if $value contains only alphabetic characters
87
+ *
88
+ * @param string $value
89
+ * @return boolean
90
+ */
91
+ public function isValid($value)
92
+ {
93
+ $valueString = (string) $value;
94
+
95
+ $this->_setValue($valueString);
96
+
97
+ if ('' === $valueString) {
98
+ $this->_error(self::STRING_EMPTY);
99
+ return false;
100
+ }
101
+
102
+ if (null === self::$_filter) {
103
+ /**
104
+ * @see Zend_Filter_Alpha
105
+ */
106
+ require_once 'Zend/Filter/Alpha.php';
107
+ self::$_filter = new Zend_Filter_Alpha();
108
+ }
109
+
110
+ self::$_filter->allowWhiteSpace = $this->allowWhiteSpace;
111
+
112
+ if ($valueString !== self::$_filter->filter($valueString)) {
113
+ $this->_error(self::NOT_ALPHA);
114
+ return false;
115
+ }
116
+
117
+ return true;
118
+ }
119
+
120
+ }
includes/phpQuery/phpQuery/Zend/Validate/Barcode.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Barcode.php 8211 2008-02-20 14:29:24Z darby $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Barcode extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Barcode validator
40
+ *
41
+ * @var Zend_Validate_Abstract
42
+ */
43
+ protected $_barcodeValidator;
44
+
45
+ /**
46
+ * Generates the standard validator object
47
+ *
48
+ * @param string $barcodeType - Barcode validator to use
49
+ * @return void
50
+ * @throws Zend_Validate_Exception
51
+ */
52
+ public function __construct($barcodeType)
53
+ {
54
+ $this->setType($barcodeType);
55
+ }
56
+
57
+ /**
58
+ * Sets a new barcode validator
59
+ *
60
+ * @param string $barcodeType - Barcode validator to use
61
+ * @return void
62
+ * @throws Zend_Validate_Exception
63
+ */
64
+ public function setType($barcodeType)
65
+ {
66
+ switch (strtolower($barcodeType)) {
67
+ case 'upc':
68
+ case 'upc-a':
69
+ $className = 'UpcA';
70
+ break;
71
+ case 'ean13':
72
+ case 'ean-13':
73
+ $className = 'Ean13';
74
+ break;
75
+ default:
76
+ require_once 'Zend/Validate/Exception.php';
77
+ throw new Zend_Validate_Exception("Barcode type '$barcodeType' is not supported'");
78
+ break;
79
+ }
80
+
81
+ require_once 'Zend/Validate/Barcode/' . $className . '.php';
82
+
83
+ $class = 'Zend_Validate_Barcode_' . $className;
84
+ $this->_barcodeValidator = new $class;
85
+ }
86
+
87
+ /**
88
+ * Defined by Zend_Validate_Interface
89
+ *
90
+ * Returns true if and only if $value contains a valid barcode
91
+ *
92
+ * @param string $value
93
+ * @return boolean
94
+ */
95
+ public function isValid($value)
96
+ {
97
+ return call_user_func(array($this->_barcodeValidator, 'isValid'), $value);
98
+ }
99
+ }
includes/phpQuery/phpQuery/Zend/Validate/Barcode/Ean13.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Ean13.php 8210 2008-02-20 14:09:05Z andries $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Barcode_Ean13 extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value is
40
+ * an invalid barcode
41
+ */
42
+ const INVALID = 'invalid';
43
+
44
+ /**
45
+ * Validation failure message key for when the value is
46
+ * not 13 characters long
47
+ */
48
+ const INVALID_LENGTH = 'invalidLength';
49
+
50
+ /**
51
+ * Validation failure message template definitions
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_messageTemplates = array(
56
+ self::INVALID => "'%value%' is an invalid EAN-13 barcode",
57
+ self::INVALID_LENGTH => "'%value%' should be 13 characters",
58
+ );
59
+
60
+ /**
61
+ * Defined by Zend_Validate_Interface
62
+ *
63
+ * Returns true if and only if $value contains a valid barcode
64
+ *
65
+ * @param string $value
66
+ * @return boolean
67
+ */
68
+ public function isValid($value)
69
+ {
70
+ $valueString = (string) $value;
71
+ $this->_setValue($valueString);
72
+
73
+ if (strlen($valueString) !== 13) {
74
+ $this->_error(self::INVALID_LENGTH);
75
+ return false;
76
+ }
77
+
78
+ $barcode = strrev(substr($valueString, 0, -1));
79
+ $oddSum = 0;
80
+ $evenSum = 0;
81
+
82
+ for ($i = 0; $i < 12; $i++) {
83
+ if ($i % 2 === 0) {
84
+ $oddSum += $barcode[$i] * 3;
85
+ } elseif ($i % 2 === 1) {
86
+ $evenSum += $barcode[$i];
87
+ }
88
+ }
89
+
90
+ $calculation = ($oddSum + $evenSum) % 10;
91
+ $checksum = ($calculation === 0) ? 0 : 10 - $calculation;
92
+
93
+ if ($valueString[12] != $checksum) {
94
+ $this->_error(self::INVALID);
95
+ return false;
96
+ }
97
+
98
+ return true;
99
+ }
100
+ }
includes/phpQuery/phpQuery/Zend/Validate/Barcode/UpcA.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: UpcA.php 8210 2008-02-20 14:09:05Z andries $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Barcode_UpcA extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value is
40
+ * an invalid barcode
41
+ */
42
+ const INVALID = 'invalid';
43
+
44
+ /**
45
+ * Validation failure message key for when the value is
46
+ * not 12 characters long
47
+ */
48
+ const INVALID_LENGTH = 'invalidLength';
49
+
50
+ /**
51
+ * Validation failure message template definitions
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_messageTemplates = array(
56
+ self::INVALID => "'%value%' is an invalid UPC-A barcode",
57
+ self::INVALID_LENGTH => "'%value%' should be 12 characters",
58
+ );
59
+
60
+ /**
61
+ * Defined by Zend_Validate_Interface
62
+ *
63
+ * Returns true if and only if $value contains a valid barcode
64
+ *
65
+ * @param string $value
66
+ * @return boolean
67
+ */
68
+ public function isValid($value)
69
+ {
70
+ $valueString = (string) $value;
71
+ $this->_setValue($valueString);
72
+
73
+ if (strlen($valueString) !== 12) {
74
+ $this->_error(self::INVALID_LENGTH);
75
+ return false;
76
+ }
77
+
78
+ $barcode = substr($valueString, 0, -1);
79
+ $oddSum = 0;
80
+ $evenSum = 0;
81
+
82
+ for ($i = 0; $i < 11; $i++) {
83
+ if ($i % 2 === 0) {
84
+ $oddSum += $barcode[$i] * 3;
85
+ } elseif ($i % 2 === 1) {
86
+ $evenSum += $barcode[$i];
87
+ }
88
+ }
89
+
90
+ $calculation = ($oddSum + $evenSum) % 10;
91
+ $checksum = ($calculation === 0) ? 0 : 10 - $calculation;
92
+
93
+ if ($valueString[11] != $checksum) {
94
+ $this->_error(self::INVALID);
95
+ return false;
96
+ }
97
+
98
+ return true;
99
+ }
100
+ }
includes/phpQuery/phpQuery/Zend/Validate/Between.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Between.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Between extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value is not between the min and max, inclusively
40
+ */
41
+ const NOT_BETWEEN = 'notBetween';
42
+
43
+ /**
44
+ * Validation failure message key for when the value is not strictly between the min and max
45
+ */
46
+ const NOT_BETWEEN_STRICT = 'notBetweenStrict';
47
+
48
+ /**
49
+ * Validation failure message template definitions
50
+ *
51
+ * @var array
52
+ */
53
+ protected $_messageTemplates = array(
54
+ self::NOT_BETWEEN => "'%value%' is not between '%min%' and '%max%', inclusively",
55
+ self::NOT_BETWEEN_STRICT => "'%value%' is not strictly between '%min%' and '%max%'"
56
+ );
57
+
58
+ /**
59
+ * Additional variables available for validation failure messages
60
+ *
61
+ * @var array
62
+ */
63
+ protected $_messageVariables = array(
64
+ 'min' => '_min',
65
+ 'max' => '_max'
66
+ );
67
+
68
+ /**
69
+ * Minimum value
70
+ *
71
+ * @var mixed
72
+ */
73
+ protected $_min;
74
+
75
+ /**
76
+ * Maximum value
77
+ *
78
+ * @var mixed
79
+ */
80
+ protected $_max;
81
+
82
+ /**
83
+ * Whether to do inclusive comparisons, allowing equivalence to min and/or max
84
+ *
85
+ * If false, then strict comparisons are done, and the value may equal neither
86
+ * the min nor max options
87
+ *
88
+ * @var boolean
89
+ */
90
+ protected $_inclusive;
91
+
92
+ /**
93
+ * Sets validator options
94
+ *
95
+ * @param mixed $min
96
+ * @param mixed $max
97
+ * @param boolean $inclusive
98
+ * @return void
99
+ */
100
+ public function __construct($min, $max, $inclusive = true)
101
+ {
102
+ $this->setMin($min)
103
+ ->setMax($max)
104
+ ->setInclusive($inclusive);
105
+ }
106
+
107
+ /**
108
+ * Returns the min option
109
+ *
110
+ * @return mixed
111
+ */
112
+ public function getMin()
113
+ {
114
+ return $this->_min;
115
+ }
116
+
117
+ /**
118
+ * Sets the min option
119
+ *
120
+ * @param mixed $min
121
+ * @return Zend_Validate_Between Provides a fluent interface
122
+ */
123
+ public function setMin($min)
124
+ {
125
+ $this->_min = $min;
126
+ return $this;
127
+ }
128
+
129
+ /**
130
+ * Returns the max option
131
+ *
132
+ * @return mixed
133
+ */
134
+ public function getMax()
135
+ {
136
+ return $this->_max;
137
+ }
138
+
139
+ /**
140
+ * Sets the max option
141
+ *
142
+ * @param mixed $max
143
+ * @return Zend_Validate_Between Provides a fluent interface
144
+ */
145
+ public function setMax($max)
146
+ {
147
+ $this->_max = $max;
148
+ return $this;
149
+ }
150
+
151
+ /**
152
+ * Returns the inclusive option
153
+ *
154
+ * @return boolean
155
+ */
156
+ public function getInclusive()
157
+ {
158
+ return $this->_inclusive;
159
+ }
160
+
161
+ /**
162
+ * Sets the inclusive option
163
+ *
164
+ * @param boolean $inclusive
165
+ * @return Zend_Validate_Between Provides a fluent interface
166
+ */
167
+ public function setInclusive($inclusive)
168
+ {
169
+ $this->_inclusive = $inclusive;
170
+ return $this;
171
+ }
172
+
173
+ /**
174
+ * Defined by Zend_Validate_Interface
175
+ *
176
+ * Returns true if and only if $value is between min and max options, inclusively
177
+ * if inclusive option is true.
178
+ *
179
+ * @param mixed $value
180
+ * @return boolean
181
+ */
182
+ public function isValid($value)
183
+ {
184
+ $this->_setValue($value);
185
+
186
+ if ($this->_inclusive) {
187
+ if ($this->_min > $value || $value > $this->_max) {
188
+ $this->_error(self::NOT_BETWEEN);
189
+ return false;
190
+ }
191
+ } else {
192
+ if ($this->_min >= $value || $value >= $this->_max) {
193
+ $this->_error(self::NOT_BETWEEN_STRICT);
194
+ return false;
195
+ }
196
+ }
197
+ return true;
198
+ }
199
+
200
+ }
includes/phpQuery/phpQuery/Zend/Validate/Ccnum.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Ccnum.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Ccnum extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value is not of valid length
40
+ */
41
+ const LENGTH = 'ccnumLength';
42
+
43
+ /**
44
+ * Validation failure message key for when the value fails the mod-10 checksum
45
+ */
46
+ const CHECKSUM = 'ccnumChecksum';
47
+
48
+ /**
49
+ * Digits filter for input
50
+ *
51
+ * @var Zend_Filter_Digits
52
+ */
53
+ protected static $_filter = null;
54
+
55
+ /**
56
+ * Validation failure message template definitions
57
+ *
58
+ * @var array
59
+ */
60
+ protected $_messageTemplates = array(
61
+ self::LENGTH => "'%value%' must contain between 13 and 19 digits",
62
+ self::CHECKSUM => "Luhn algorithm (mod-10 checksum) failed on '%value%'"
63
+ );
64
+
65
+ /**
66
+ * Defined by Zend_Validate_Interface
67
+ *
68
+ * Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum)
69
+ *
70
+ * @param string $value
71
+ * @return boolean
72
+ */
73
+ public function isValid($value)
74
+ {
75
+ $this->_setValue($value);
76
+
77
+ if (null === self::$_filter) {
78
+ /**
79
+ * @see Zend_Filter_Digits
80
+ */
81
+ require_once 'Zend/Filter/Digits.php';
82
+ self::$_filter = new Zend_Filter_Digits();
83
+ }
84
+
85
+ $valueFiltered = self::$_filter->filter($value);
86
+
87
+ $length = strlen($valueFiltered);
88
+
89
+ if ($length < 13 || $length > 19) {
90
+ $this->_error(self::LENGTH);
91
+ return false;
92
+ }
93
+
94
+ $sum = 0;
95
+ $weight = 2;
96
+
97
+ for ($i = $length - 2; $i >= 0; $i--) {
98
+ $digit = $weight * $valueFiltered[$i];
99
+ $sum += floor($digit / 10) + $digit % 10;
100
+ $weight = $weight % 2 + 1;
101
+ }
102
+
103
+ if ((10 - $sum % 10) % 10 != $valueFiltered[$length - 1]) {
104
+ $this->_error(self::CHECKSUM, $valueFiltered);
105
+ return false;
106
+ }
107
+
108
+ return true;
109
+ }
110
+
111
+ }
includes/phpQuery/phpQuery/Zend/Validate/Date.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Date.php 11046 2008-08-25 13:58:52Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Date extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value does not follow the YYYY-MM-DD format
40
+ */
41
+ const NOT_YYYY_MM_DD = 'dateNotYYYY-MM-DD';
42
+
43
+ /**
44
+ * Validation failure message key for when the value does not appear to be a valid date
45
+ */
46
+ const INVALID = 'dateInvalid';
47
+
48
+ /**
49
+ * Validation failure message key for when the value does not fit the given dateformat or locale
50
+ */
51
+ const FALSEFORMAT = 'dateFalseFormat';
52
+
53
+ /**
54
+ * Validation failure message template definitions
55
+ *
56
+ * @var array
57
+ */
58
+ protected $_messageTemplates = array(
59
+ self::NOT_YYYY_MM_DD => "'%value%' is not of the format YYYY-MM-DD",
60
+ self::INVALID => "'%value%' does not appear to be a valid date",
61
+ self::FALSEFORMAT => "'%value%' does not fit given date format"
62
+ );
63
+
64
+ /**
65
+ * Optional format
66
+ *
67
+ * @var string|null
68
+ */
69
+ protected $_format;
70
+
71
+ /**
72
+ * Optional locale
73
+ *
74
+ * @var string|Zend_Locale|null
75
+ */
76
+ protected $_locale;
77
+
78
+ /**
79
+ * Sets validator options
80
+ *
81
+ * @param string $format OPTIONAL
82
+ * @param string|Zend_Locale $locale OPTIONAL
83
+ * @return void
84
+ */
85
+ public function __construct($format = null, $locale = null)
86
+ {
87
+ $this->setFormat($format);
88
+ $this->setLocale($locale);
89
+ }
90
+
91
+ /**
92
+ * Returns the locale option
93
+ *
94
+ * @return string|Zend_Locale|null
95
+ */
96
+ public function getLocale()
97
+ {
98
+ return $this->_locale;
99
+ }
100
+
101
+ /**
102
+ * Sets the locale option
103
+ *
104
+ * @param string|Zend_Locale $locale
105
+ * @return Zend_Validate_Date provides a fluent interface
106
+ */
107
+ public function setLocale($locale = null)
108
+ {
109
+ if ($locale === null) {
110
+ $this->_locale = null;
111
+ return $this;
112
+ }
113
+
114
+ require_once 'Zend/Locale.php';
115
+ if (!Zend_Locale::isLocale($locale, true)) {
116
+ if (!Zend_Locale::isLocale($locale, false)) {
117
+ require_once 'Zend/Validate/Exception.php';
118
+ throw new Zend_Validate_Exception("The locale '$locale' is no known locale");
119
+ }
120
+
121
+ $locale = new Zend_Locale($locale);
122
+ }
123
+
124
+ $this->_locale = (string) $locale;
125
+ return $this;
126
+ }
127
+
128
+ /**
129
+ * Returns the locale option
130
+ *
131
+ * @return string|null
132
+ */
133
+ public function getFormat()
134
+ {
135
+ return $this->_format;
136
+ }
137
+
138
+ /**
139
+ * Sets the format option
140
+ *
141
+ * @param string $format
142
+ * @return Zend_Validate_Date provides a fluent interface
143
+ */
144
+ public function setFormat($format = null)
145
+ {
146
+ $this->_format = $format;
147
+ return $this;
148
+ }
149
+
150
+ /**
151
+ * Defined by Zend_Validate_Interface
152
+ *
153
+ * Returns true if $value is a valid date of the format YYYY-MM-DD
154
+ * If optional $format or $locale is set the date format is checked
155
+ * according to Zend_Date, see Zend_Date::isDate()
156
+ *
157
+ * @param string $value
158
+ * @return boolean
159
+ */
160
+ public function isValid($value)
161
+ {
162
+ $valueString = (string) $value;
163
+
164
+ $this->_setValue($valueString);
165
+
166
+ if (($this->_format !== null) or ($this->_locale !== null)) {
167
+ require_once 'Zend/Date.php';
168
+ if (!Zend_Date::isDate($value, $this->_format, $this->_locale)) {
169
+ if ($this->_checkFormat($value) === false) {
170
+ $this->_error(self::FALSEFORMAT);
171
+ } else {
172
+ $this->_error(self::INVALID);
173
+ }
174
+ return false;
175
+ }
176
+ } else {
177
+ if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $valueString)) {
178
+ $this->_error(self::NOT_YYYY_MM_DD);
179
+ return false;
180
+ }
181
+
182
+ list($year, $month, $day) = sscanf($valueString, '%d-%d-%d');
183
+
184
+ if (!checkdate($month, $day, $year)) {
185
+ $this->_error(self::INVALID);
186
+ return false;
187
+ }
188
+ }
189
+
190
+ return true;
191
+ }
192
+
193
+ /**
194
+ * Check if the given date fits the given format
195
+ *
196
+ * @param string $value Date to check
197
+ * @return boolean False when date does not fit the format
198
+ */
199
+ private function _checkFormat($value)
200
+ {
201
+ try {
202
+ require_once 'Zend/Locale/Format.php';
203
+ $parsed = Zend_Locale_Format::getDate($value, array(
204
+ 'date_format' => $this->_format, 'format_type' => 'iso',
205
+ 'fix_date' => false));
206
+ if (isset($parsed['year']) and ((strpos(strtoupper($this->_format), 'YY') !== false) and
207
+ (strpos(strtoupper($this->_format), 'YYYY') === false))) {
208
+ $parsed['year'] = Zend_Date::_century($parsed['year']);
209
+ }
210
+ } catch (Exception $e) {
211
+ // Date can not be parsed
212
+ return false;
213
+ }
214
+
215
+ if (((strpos($this->_format, 'Y') !== false) or (strpos($this->_format, 'y') !== false)) and
216
+ (!isset($parsed['year']))) {
217
+ // Year expected but not found
218
+ return false;
219
+ }
220
+
221
+ if ((strpos($this->_format, 'M') !== false) and (!isset($parsed['month']))) {
222
+ // Month expected but not found
223
+ return false;
224
+ }
225
+
226
+ if ((strpos($this->_format, 'd') !== false) and (!isset($parsed['day']))) {
227
+ // Day expected but not found
228
+ return false;
229
+ }
230
+
231
+ if (((strpos($this->_format, 'H') !== false) or (strpos($this->_format, 'h') !== false)) and
232
+ (!isset($parsed['hour']))) {
233
+ // Hour expected but not found
234
+ return false;
235
+ }
236
+
237
+ if ((strpos($this->_format, 'm') !== false) and (!isset($parsed['minute']))) {
238
+ // Minute expected but not found
239
+ return false;
240
+ }
241
+
242
+ if ((strpos($this->_format, 's') !== false) and (!isset($parsed['second']))) {
243
+ // Second expected but not found
244
+ return false;
245
+ }
246
+
247
+ // Date fits the format
248
+ return true;
249
+ }
250
+ }
includes/phpQuery/phpQuery/Zend/Validate/Digits.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Digits.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Digits extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value contains non-digit characters
40
+ */
41
+ const NOT_DIGITS = 'notDigits';
42
+
43
+ /**
44
+ * Validation failure message key for when the value is an empty string
45
+ */
46
+ const STRING_EMPTY = 'stringEmpty';
47
+
48
+ /**
49
+ * Digits filter used for validation
50
+ *
51
+ * @var Zend_Filter_Digits
52
+ */
53
+ protected static $_filter = null;
54
+
55
+ /**
56
+ * Validation failure message template definitions
57
+ *
58
+ * @var array
59
+ */
60
+ protected $_messageTemplates = array(
61
+ self::NOT_DIGITS => "'%value%' contains not only digit characters",
62
+ self::STRING_EMPTY => "'%value%' is an empty string"
63
+ );
64
+
65
+ /**
66
+ * Defined by Zend_Validate_Interface
67
+ *
68
+ * Returns true if and only if $value only contains digit characters
69
+ *
70
+ * @param string $value
71
+ * @return boolean
72
+ */
73
+ public function isValid($value)
74
+ {
75
+ $valueString = (string) $value;
76
+
77
+ $this->_setValue($valueString);
78
+
79
+ if ('' === $valueString) {
80
+ $this->_error(self::STRING_EMPTY);
81
+ return false;
82
+ }
83
+
84
+ if (null === self::$_filter) {
85
+ /**
86
+ * @see Zend_Filter_Digits
87
+ */
88
+ require_once 'Zend/Filter/Digits.php';
89
+ self::$_filter = new Zend_Filter_Digits();
90
+ }
91
+
92
+ if ($valueString !== self::$_filter->filter($valueString)) {
93
+ $this->_error(self::NOT_DIGITS);
94
+ return false;
95
+ }
96
+
97
+ return true;
98
+ }
99
+
100
+ }
includes/phpQuery/phpQuery/Zend/Validate/EmailAddress.php ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: EmailAddress.php 8985 2008-03-21 21:37:24Z matthew $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @see Zend_Validate_Hostname
32
+ */
33
+ require_once 'Zend/Validate/Hostname.php';
34
+
35
+
36
+ /**
37
+ * @category Zend
38
+ * @package Zend_Validate
39
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
40
+ * @license http://framework.zend.com/license/new-bsd New BSD License
41
+ */
42
+ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
43
+ {
44
+
45
+ const INVALID = 'emailAddressInvalid';
46
+ const INVALID_HOSTNAME = 'emailAddressInvalidHostname';
47
+ const INVALID_MX_RECORD = 'emailAddressInvalidMxRecord';
48
+ const DOT_ATOM = 'emailAddressDotAtom';
49
+ const QUOTED_STRING = 'emailAddressQuotedString';
50
+ const INVALID_LOCAL_PART = 'emailAddressInvalidLocalPart';
51
+
52
+ /**
53
+ * @var array
54
+ */
55
+ protected $_messageTemplates = array(
56
+ self::INVALID => "'%value%' is not a valid email address in the basic format local-part@hostname",
57
+ self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for email address '%value%'",
58
+ self::INVALID_MX_RECORD => "'%hostname%' does not appear to have a valid MX record for the email address '%value%'",
59
+ self::DOT_ATOM => "'%localPart%' not matched against dot-atom format",
60
+ self::QUOTED_STRING => "'%localPart%' not matched against quoted-string format",
61
+ self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for email address '%value%'"
62
+ );
63
+
64
+ /**
65
+ * @var array
66
+ */
67
+ protected $_messageVariables = array(
68
+ 'hostname' => '_hostname',
69
+ 'localPart' => '_localPart'
70
+ );
71
+
72
+ /**
73
+ * Local object for validating the hostname part of an email address
74
+ *
75
+ * @var Zend_Validate_Hostname
76
+ */
77
+ public $hostnameValidator;
78
+
79
+ /**
80
+ * Whether we check for a valid MX record via DNS
81
+ *
82
+ * @var boolean
83
+ */
84
+ protected $_validateMx = false;
85
+
86
+ /**
87
+ * @var string
88
+ */
89
+ protected $_hostname;
90
+
91
+ /**
92
+ * @var string
93
+ */
94
+ protected $_localPart;
95
+
96
+ /**
97
+ * Instantiates hostname validator for local use
98
+ *
99
+ * You can pass a bitfield to determine what types of hostnames are allowed.
100
+ * These bitfields are defined by the ALLOW_* constants in Zend_Validate_Hostname
101
+ * The default is to allow DNS hostnames only
102
+ *
103
+ * @param integer $allow OPTIONAL
104
+ * @param bool $validateMx OPTIONAL
105
+ * @param Zend_Validate_Hostname $hostnameValidator OPTIONAL
106
+ * @return void
107
+ */
108
+ public function __construct($allow = Zend_Validate_Hostname::ALLOW_DNS, $validateMx = false, Zend_Validate_Hostname $hostnameValidator = null)
109
+ {
110
+ $this->setValidateMx($validateMx);
111
+ $this->setHostnameValidator($hostnameValidator, $allow);
112
+ }
113
+
114
+ /**
115
+ * @param Zend_Validate_Hostname $hostnameValidator OPTIONAL
116
+ * @param int $allow OPTIONAL
117
+ * @return void
118
+ */
119
+ public function setHostnameValidator(Zend_Validate_Hostname $hostnameValidator = null, $allow = Zend_Validate_Hostname::ALLOW_DNS)
120
+ {
121
+ if ($hostnameValidator === null) {
122
+ $hostnameValidator = new Zend_Validate_Hostname($allow);
123
+ }
124
+ $this->hostnameValidator = $hostnameValidator;
125
+ }
126
+
127
+ /**
128
+ * Whether MX checking via dns_get_mx is supported or not
129
+ *
130
+ * This currently only works on UNIX systems
131
+ *
132
+ * @return boolean
133
+ */
134
+ public function validateMxSupported()
135
+ {
136
+ return function_exists('dns_get_mx');
137
+ }
138
+
139
+ /**
140
+ * Set whether we check for a valid MX record via DNS
141
+ *
142
+ * This only applies when DNS hostnames are validated
143
+ *
144
+ * @param boolean $allowed Set allowed to true to validate for MX records, and false to not validate them
145
+ */
146
+ public function setValidateMx($allowed)
147
+ {
148
+ $this->_validateMx = (bool) $allowed;
149
+ }
150
+
151
+ /**
152
+ * Defined by Zend_Validate_Interface
153
+ *
154
+ * Returns true if and only if $value is a valid email address
155
+ * according to RFC2822
156
+ *
157
+ * @link http://www.ietf.org/rfc/rfc2822.txt RFC2822
158
+ * @link http://www.columbia.edu/kermit/ascii.html US-ASCII characters
159
+ * @param string $value
160
+ * @return boolean
161
+ */
162
+ public function isValid($value)
163
+ {
164
+ $valueString = (string) $value;
165
+
166
+ $this->_setValue($valueString);
167
+
168
+ // Split email address up
169
+ if (!preg_match('/^(.+)@([^@]+)$/', $valueString, $matches)) {
170
+ $this->_error(self::INVALID);
171
+ return false;
172
+ }
173
+
174
+ $this->_localPart = $matches[1];
175
+ $this->_hostname = $matches[2];
176
+
177
+ // Match hostname part
178
+ $hostnameResult = $this->hostnameValidator->setTranslator($this->getTranslator())
179
+ ->isValid($this->_hostname);
180
+ if (!$hostnameResult) {
181
+ $this->_error(self::INVALID_HOSTNAME);
182
+
183
+ // Get messages and errors from hostnameValidator
184
+ foreach ($this->hostnameValidator->getMessages() as $message) {
185
+ $this->_messages[] = $message;
186
+ }
187
+ foreach ($this->hostnameValidator->getErrors() as $error) {
188
+ $this->_errors[] = $error;
189
+ }
190
+ }
191
+
192
+ // MX check on hostname via dns_get_record()
193
+ if ($this->_validateMx) {
194
+ if ($this->validateMxSupported()) {
195
+ $result = dns_get_mx($this->_hostname, $mxHosts);
196
+ if (count($mxHosts) < 1) {
197
+ $hostnameResult = false;
198
+ $this->_error(self::INVALID_MX_RECORD);
199
+ }
200
+ } else {
201
+ /**
202
+ * MX checks are not supported by this system
203
+ * @see Zend_Validate_Exception
204
+ */
205
+ require_once 'Zend/Validate/Exception.php';
206
+ throw new Zend_Validate_Exception('Internal error: MX checking not available on this system');
207
+ }
208
+ }
209
+
210
+ // First try to match the local part on the common dot-atom format
211
+ $localResult = false;
212
+
213
+ // Dot-atom characters are: 1*atext *("." 1*atext)
214
+ // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
215
+ // "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
216
+ $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d';
217
+ if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) {
218
+ $localResult = true;
219
+ } else {
220
+ // Try quoted string format
221
+
222
+ // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE
223
+ // qtext: Non white space controls, and the rest of the US-ASCII characters not
224
+ // including "\" or the quote character
225
+ $noWsCtl = '\x01-\x08\x0b\x0c\x0e-\x1f\x7f';
226
+ $qtext = $noWsCtl . '\x21\x23-\x5b\x5d-\x7e';
227
+ $ws = '\x20\x09';
228
+ if (preg_match('/^\x22([' . $ws . $qtext . '])*[$ws]?\x22$/', $this->_localPart)) {
229
+ $localResult = true;
230
+ } else {
231
+ $this->_error(self::DOT_ATOM);
232
+ $this->_error(self::QUOTED_STRING);
233
+ $this->_error(self::INVALID_LOCAL_PART);
234
+ }
235
+ }
236
+
237
+ // If both parts valid, return true
238
+ if ($localResult && $hostnameResult) {
239
+ return true;
240
+ } else {
241
+ return false;
242
+ }
243
+ }
244
+
245
+ }
includes/phpQuery/phpQuery/Zend/Validate/Exception.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Exception
26
+ */
27
+ require_once 'Zend/Exception.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Exception extends Zend_Exception
37
+ {}
includes/phpQuery/phpQuery/Zend/Validate/File/Count.php ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator for counting all given files
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_Count extends Zend_Validate_Abstract
36
+ {
37
+ /**#@+
38
+ * @const string Error constants
39
+ */
40
+ const TOO_MUCH = 'fileCountTooMuch';
41
+ const TOO_LESS = 'fileCountTooLess';
42
+ /**#@-*/
43
+
44
+ /**
45
+ * @var array Error message templates
46
+ */
47
+ protected $_messageTemplates = array(
48
+ self::TOO_MUCH => "Too much files, only '%value%' are allowed",
49
+ self::TOO_LESS => "Too less files, minimum '%value%' must be given"
50
+ );
51
+
52
+ /**
53
+ * @var array Error message template variables
54
+ */
55
+ protected $_messageVariables = array(
56
+ 'min' => '_min',
57
+ 'max' => '_max'
58
+ );
59
+
60
+ /**
61
+ * Minimum file count
62
+ *
63
+ * If null, there is no minimum file count
64
+ *
65
+ * @var integer
66
+ */
67
+ protected $_min;
68
+
69
+ /**
70
+ * Maximum file count
71
+ *
72
+ * If null, there is no maximum file count
73
+ *
74
+ * @var integer|null
75
+ */
76
+ protected $_max;
77
+
78
+ /**
79
+ * Internal file array
80
+ * @var array
81
+ */
82
+ protected $_files;
83
+
84
+ /**
85
+ * Sets validator options
86
+ *
87
+ * Min limits the file count, when used with max=null it is the maximum file count
88
+ * It also accepts an array with the keys 'min' and 'max'
89
+ *
90
+ * @param integer|array $min Minimum file count
91
+ * @param integer $max Maximum file count
92
+ * @return void
93
+ */
94
+ public function __construct($min, $max = null)
95
+ {
96
+ $this->_files = array();
97
+ if (is_array($min) === true) {
98
+ if (isset($min['max']) === true) {
99
+ $max = $min['max'];
100
+ }
101
+
102
+ if (isset($min['min']) === true) {
103
+ $min = $min['min'];
104
+ }
105
+
106
+ if (isset($min[0]) === true) {
107
+ if (count($min) === 2) {
108
+ $max = $min[1];
109
+ $min = $min[0];
110
+ } else {
111
+ $max = $min[0];
112
+ $min = null;
113
+ }
114
+ }
115
+ }
116
+
117
+ if (empty($max) === true) {
118
+ $max = $min;
119
+ $min = null;
120
+ }
121
+
122
+ $this->setMin($min);
123
+ $this->setMax($max);
124
+ }
125
+
126
+ /**
127
+ * Returns the minimum file count
128
+ *
129
+ * @return integer
130
+ */
131
+ public function getMin()
132
+ {
133
+ $min = $this->_min;
134
+
135
+ return $min;
136
+ }
137
+
138
+ /**
139
+ * Sets the minimum file count
140
+ *
141
+ * @param integer $min The minimum file count
142
+ * @return Zend_Validate_File_Size Provides a fluent interface
143
+ * @throws Zend_Validate_Exception When min is greater than max
144
+ */
145
+ public function setMin($min)
146
+ {
147
+ if ($min === null) {
148
+ $this->_min = null;
149
+ } else if (($this->_max !== null) and ($min > $this->_max)) {
150
+ require_once 'Zend/Validate/Exception.php';
151
+ throw new Zend_Validate_Exception('The minimum must be less than or equal to the maximum file count, but '
152
+ . " {$min} > {$this->_max}");
153
+ } else {
154
+ $this->_min = max(0, (integer) $min);
155
+ }
156
+
157
+ return $this;
158
+ }
159
+
160
+ /**
161
+ * Returns the maximum file count
162
+ *
163
+ * @return integer|null
164
+ */
165
+ public function getMax()
166
+ {
167
+ return $this->_max;
168
+ }
169
+
170
+ /**
171
+ * Sets the maximum file count
172
+ *
173
+ * @param integer|null $max The maximum file count
174
+ * @throws Zend_Validate_Exception When max is smaller than min
175
+ * @return Zend_Validate_StringLength Provides a fluent interface
176
+ */
177
+ public function setMax($max)
178
+ {
179
+ if ($max === null) {
180
+ $this->_max = null;
181
+ } else if (($this->_min !== null) and ($max < $this->_min)) {
182
+ require_once 'Zend/Validate/Exception.php';
183
+ throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum file count, but "
184
+ . "{$max} < {$this->_min}");
185
+ } else {
186
+ $this->_max = (integer) $max;
187
+ }
188
+
189
+ return $this;
190
+ }
191
+
192
+ /**
193
+ * Defined by Zend_Validate_Interface
194
+ *
195
+ * Returns true if and only if the file count of all checked files is at least min and
196
+ * not bigger than max (when max is not null). Attention: When checking with set min you
197
+ * must give all files with the first call, otherwise you will get an false.
198
+ *
199
+ * @param string|array $value Filenames to check for count
200
+ * @param array $file File data from Zend_File_Transfer
201
+ * @return boolean
202
+ */
203
+ public function isValid($value, $file = null)
204
+ {
205
+ if (is_string($value)) {
206
+ $value = array($value);
207
+ }
208
+
209
+ foreach ($value as $file) {
210
+ if (!isset($this->_files[$file])) {
211
+ $this->_files[$file] = $file;
212
+ }
213
+ }
214
+
215
+ if (($this->_max !== null) && (count($this->_files) > $this->_max)) {
216
+ $this->_value = $this->_max;
217
+ $this->_error(self::TOO_MUCH);
218
+ return false;
219
+ }
220
+
221
+ if (($this->_min !== null) && (count($this->_files) < $this->_min)) {
222
+ $this->_value = $this->_min;
223
+ $this->_error(self::TOO_LESS);
224
+ return false;
225
+ }
226
+
227
+ return true;
228
+ }
229
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/Exists.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator which checks if the file already exists in the directory
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_Exists extends Zend_Validate_Abstract
36
+ {
37
+ /**
38
+ * @const string Error constants
39
+ */
40
+ const DOES_NOT_EXIST = 'fileExistsDoesNotExist';
41
+
42
+ /**
43
+ * @var array Error message templates
44
+ */
45
+ protected $_messageTemplates = array(
46
+ self::DOES_NOT_EXIST => "The file '%value%' does not exist"
47
+ );
48
+
49
+ /**
50
+ * Internal list of directories
51
+ * @var string
52
+ */
53
+ protected $_directory = '';
54
+
55
+ /**
56
+ * @var array Error message template variables
57
+ */
58
+ protected $_messageVariables = array(
59
+ 'directory' => '_directory'
60
+ );
61
+
62
+ /**
63
+ * Sets validator options
64
+ *
65
+ * @param string|array $directory
66
+ * @return void
67
+ */
68
+ public function __construct($directory = array())
69
+ {
70
+ $this->setDirectory($directory);
71
+ }
72
+
73
+ /**
74
+ * Returns the set file directories which are checked
75
+ *
76
+ * @param boolean $asArray Returns the values as array, when false an concated string is returned
77
+ * @return string
78
+ */
79
+ public function getDirectory($asArray = false)
80
+ {
81
+ $asArray = (bool) $asArray;
82
+ $directory = (string) $this->_directory;
83
+ if ($asArray) {
84
+ $directory = explode(',', $directory);
85
+ }
86
+
87
+ return $directory;
88
+ }
89
+
90
+ /**
91
+ * Sets the file directory which will be checked
92
+ *
93
+ * @param string|array $directory The directories to validate
94
+ * @return Zend_Validate_File_Extension Provides a fluent interface
95
+ */
96
+ public function setDirectory($directory)
97
+ {
98
+ $this->_directory = null;
99
+ $this->addDirectory($directory);
100
+ return $this;
101
+ }
102
+
103
+ /**
104
+ * Adds the file directory which will be checked
105
+ *
106
+ * @param string|array $directory The directory to add for validation
107
+ * @return Zend_Validate_File_Extension Provides a fluent interface
108
+ */
109
+ public function addDirectory($directory)
110
+ {
111
+ $directories = $this->getDirectory(true);
112
+ if (is_string($directory)) {
113
+ $directory = explode(',', $directory);
114
+ }
115
+
116
+ foreach ($directory as $content) {
117
+ if (empty($content) || !is_string($content)) {
118
+ continue;
119
+ }
120
+
121
+ $directories[] = trim($content);
122
+ }
123
+ $directories = array_unique($directories);
124
+
125
+ // Sanity check to ensure no empty values
126
+ foreach ($directories as $key => $dir) {
127
+ if (empty($dir)) {
128
+ unset($directories[$key]);
129
+ }
130
+ }
131
+
132
+ $this->_directory = implode(',', $directories);
133
+
134
+ return $this;
135
+ }
136
+
137
+ /**
138
+ * Defined by Zend_Validate_Interface
139
+ *
140
+ * Returns true if and only if the file already exists in the set directories
141
+ *
142
+ * @param string $value Real file to check for existance
143
+ * @param array $file File data from Zend_File_Transfer
144
+ * @return boolean
145
+ */
146
+ public function isValid($value, $file = null)
147
+ {
148
+ $directories = $this->getDirectory(true);
149
+ if (($file !== null) and (!empty($file['destination']))) {
150
+ $directories[] = $file['destination'];
151
+ } else if (!isset($file['name'])) {
152
+ $file['name'] = $value;
153
+ }
154
+
155
+ $check = false;
156
+ foreach ($directories as $directory) {
157
+ if (empty($directory)) {
158
+ continue;
159
+ }
160
+
161
+ $check = true;
162
+ if (!file_exists($directory . DIRECTORY_SEPARATOR . $file['name'])) {
163
+ $this->_throw($file, self::DOES_NOT_EXIST);
164
+ return false;
165
+ }
166
+ }
167
+
168
+ if (!$check) {
169
+ $this->_throw($file, self::DOES_NOT_EXIST);
170
+ return false;
171
+ }
172
+
173
+ return true;
174
+ }
175
+
176
+ /**
177
+ * Throws an error of the given type
178
+ *
179
+ * @param string $file
180
+ * @param string $errorType
181
+ * @return false
182
+ */
183
+ protected function _throw($file, $errorType)
184
+ {
185
+ if ($file !== null) {
186
+ $this->_value = $file['name'];
187
+ }
188
+
189
+ $this->_error($errorType);
190
+ return false;
191
+ }
192
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/Extension.php ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator for the file extension of a file
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_Extension extends Zend_Validate_Abstract
36
+ {
37
+ /**
38
+ * @const string Error constants
39
+ */
40
+ const FALSE_EXTENSION = 'fileExtensionFalse';
41
+ const NOT_FOUND = 'fileExtensionNotFound';
42
+
43
+ /**
44
+ * @var array Error message templates
45
+ */
46
+ protected $_messageTemplates = array(
47
+ self::FALSE_EXTENSION => "The file '%value%' has a false extension",
48
+ self::NOT_FOUND => "The file '%value%' was not found"
49
+ );
50
+
51
+ /**
52
+ * Internal list of extensions
53
+ * @var string
54
+ */
55
+ protected $_extension = '';
56
+
57
+ /**
58
+ * Validate case sensitive
59
+ *
60
+ * @var boolean
61
+ */
62
+ protected $_case = false;
63
+
64
+ /**
65
+ * @var array Error message template variables
66
+ */
67
+ protected $_messageVariables = array(
68
+ 'extension' => '_extension'
69
+ );
70
+
71
+ /**
72
+ * Sets validator options
73
+ *
74
+ * @param string|array $extension
75
+ * @param boolean $case If true validation is done case sensitive
76
+ * @return void
77
+ */
78
+ public function __construct($extension, $case = false)
79
+ {
80
+ $this->_case = (boolean) $case;
81
+ $this->setExtension($extension);
82
+ }
83
+
84
+ /**
85
+ * Returns the set file extension
86
+ *
87
+ * @param boolean $asArray Returns the values as array, when false an concated string is returned
88
+ * @return string
89
+ */
90
+ public function getExtension($asArray = false)
91
+ {
92
+ $asArray = (bool) $asArray;
93
+ $extension = (string) $this->_extension;
94
+ if ($asArray) {
95
+ $extension = explode(',', $extension);
96
+ }
97
+
98
+ return $extension;
99
+ }
100
+
101
+ /**
102
+ * Sets the file extensions
103
+ *
104
+ * @param string|array $extension The extensions to validate
105
+ * @return Zend_Validate_File_Extension Provides a fluent interface
106
+ */
107
+ public function setExtension($extension)
108
+ {
109
+ $this->_extension = null;
110
+ $this->addExtension($extension);
111
+ return $this;
112
+ }
113
+
114
+ /**
115
+ * Adds the file extensions
116
+ *
117
+ * @param string|array $extension The extensions to add for validation
118
+ * @return Zend_Validate_File_Extension Provides a fluent interface
119
+ */
120
+ public function addExtension($extension)
121
+ {
122
+ $extensions = $this->getExtension(true);
123
+ if (is_string($extension)) {
124
+ $extension = explode(',', $extension);
125
+ }
126
+
127
+ foreach ($extension as $content) {
128
+ if (empty($content) || !is_string($content)) {
129
+ continue;
130
+ }
131
+
132
+ $extensions[] = trim($content);
133
+ }
134
+ $extensions = array_unique($extensions);
135
+
136
+ // Sanity check to ensure no empty values
137
+ foreach ($extensions as $key => $ext) {
138
+ if (empty($ext)) {
139
+ unset($extensions[$key]);
140
+ }
141
+ }
142
+
143
+ $this->_extension = implode(',', $extensions);
144
+
145
+ return $this;
146
+ }
147
+
148
+ /**
149
+ * Defined by Zend_Validate_Interface
150
+ *
151
+ * Returns true if and only if the fileextension of $value is included in the
152
+ * set extension list
153
+ *
154
+ * @param string $value Real file to check for extension
155
+ * @param array $file File data from Zend_File_Transfer
156
+ * @return boolean
157
+ */
158
+ public function isValid($value, $file = null)
159
+ {
160
+ // Is file readable ?
161
+ if (!@is_readable($value)) {
162
+ $this->_throw($file, self::NOT_FOUND);
163
+ return false;
164
+ }
165
+
166
+ if ($file !== null) {
167
+ $info['extension'] = substr($file['name'], strpos($file['name'], '.') + 1);
168
+ } else {
169
+ $info = @pathinfo($value);
170
+ }
171
+
172
+ $extensions = $this->getExtension(true);
173
+
174
+ if ($this->_case and (in_array($info['extension'], $extensions))) {
175
+ return true;
176
+ } else if (!$this->_case) {
177
+ foreach ($extensions as $extension) {
178
+ if (strtolower($extension) == strtolower($info['extension'])) {
179
+ return true;
180
+ }
181
+ }
182
+ }
183
+
184
+ $this->_throw($file, self::FALSE_EXTENSION);
185
+ return false;
186
+ }
187
+
188
+ /**
189
+ * Throws an error of the given type
190
+ *
191
+ * @param string $file
192
+ * @param string $errorType
193
+ * @return false
194
+ */
195
+ protected function _throw($file, $errorType)
196
+ {
197
+ if ($file !== null) {
198
+ $this->_value = $file['name'];
199
+ }
200
+
201
+ $this->_error($errorType);
202
+ return false;
203
+ }
204
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/FilesSize.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_File_Size
24
+ */
25
+ require_once 'Zend/Validate/File/Size.php';
26
+
27
+ /**
28
+ * Validator for the size of all files which will be validated in sum
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
36
+ {
37
+ /**
38
+ * @const string Error constants
39
+ */
40
+ const TOO_BIG = 'fileFilesSizeTooBig';
41
+ const TOO_SMALL = 'fileFilesSizeTooSmall';
42
+ const NOT_READABLE = 'fileFilesSizeNotReadable';
43
+
44
+ /**
45
+ * @var array Error message templates
46
+ */
47
+ protected $_messageTemplates = array(
48
+ self::TOO_BIG => "The files in sum exceed the maximum allowed size",
49
+ self::TOO_SMALL => "All files are in sum smaller than required",
50
+ self::NOT_READABLE => "One or more files can not be read"
51
+ );
52
+
53
+ /**
54
+ * @var array Error message template variables
55
+ */
56
+ protected $_messageVariables = array(
57
+ 'min' => '_min',
58
+ 'max' => '_max'
59
+ );
60
+
61
+ /**
62
+ * Minimum filesize
63
+ *
64
+ * @var integer
65
+ */
66
+ protected $_min;
67
+
68
+ /**
69
+ * Maximum filesize
70
+ *
71
+ * @var integer|null
72
+ */
73
+ protected $_max;
74
+
75
+ /**
76
+ * Internal file array
77
+ *
78
+ * @var array
79
+ */
80
+ protected $_files;
81
+
82
+ /**
83
+ * Internal file size counter
84
+ *
85
+ * @var integer
86
+ */
87
+ protected $_size;
88
+
89
+ /**
90
+ * Sets validator options
91
+ *
92
+ * Min limits the used diskspace for all files, when used with max=null it is the maximum filesize
93
+ * It also accepts an array with the keys 'min' and 'max'
94
+ *
95
+ * @param integer|array $min Minimum diskspace for all files
96
+ * @param integer $max Maximum diskspace for all files
97
+ * @return void
98
+ */
99
+ public function __construct($min, $max = null)
100
+ {
101
+ $this->_files = array();
102
+ $this->_size = 0;
103
+ parent::__construct($min, $max);
104
+ }
105
+
106
+ /**
107
+ * Defined by Zend_Validate_Interface
108
+ *
109
+ * Returns true if and only if the disk usage of all files is at least min and
110
+ * not bigger than max (when max is not null).
111
+ *
112
+ * @param string|array $value Real file to check for size
113
+ * @param array $file File data from Zend_File_Transfer
114
+ * @return boolean
115
+ */
116
+ public function isValid($value, $file = null)
117
+ {
118
+ if (is_string($value)) {
119
+ $value = array($value);
120
+ }
121
+
122
+ foreach ($value as $files) {
123
+ // Is file readable ?
124
+ if (!@is_readable($files)) {
125
+ $this->_throw($file, self::NOT_READABLE);
126
+ return false;
127
+ }
128
+
129
+ if (!isset($this->_files[$files])) {
130
+ $this->_files[$files] = $files;
131
+ } else {
132
+ // file already counted... do not count twice
133
+ continue;
134
+ }
135
+
136
+ // limited to 2GB files
137
+ $size = @filesize($files);
138
+ $this->_size += $size;
139
+ $this->_setValue($this->_size);
140
+ if (($this->_max !== null) && ($this->_max < $this->_size)) {
141
+ $this->_throw($file, self::TOO_BIG);
142
+ }
143
+ }
144
+
145
+ // Check that aggregate files are >= minimum size
146
+ if (($this->_min !== null) && ($this->_size < $this->_min)) {
147
+ $this->_throw($file, self::TOO_SMALL);
148
+ }
149
+
150
+ if (count($this->_messages) > 0) {
151
+ return false;
152
+ } else {
153
+ return true;
154
+ }
155
+ }
156
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/ImageSize.php ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator for the image size of a image file
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
36
+ {
37
+ /**
38
+ * @const string Error constants
39
+ */
40
+ const WIDTH_TOO_BIG = 'fileImageSizeWidthTooBig';
41
+ const WIDTH_TOO_SMALL = 'fileImageSizeWidthTooSmall';
42
+ const HEIGHT_TOO_BIG = 'fileImageSizeHeightTooBig';
43
+ const HEIGHT_TOO_SMALL = 'fileImageSizeHeightTooSmall';
44
+ const NOT_DETECTED = 'fileImageSizeNotDetected';
45
+ const NOT_READABLE = 'fileImageSizeNotReadable';
46
+
47
+ /**
48
+ * @var array Error message template
49
+ */
50
+ protected $_messageTemplates = array(
51
+ self::WIDTH_TOO_BIG => "Width of the image '%value%' is bigger than allowed",
52
+ self::WIDTH_TOO_SMALL => "Width of the image '%value%' is smaller than allowed",
53
+ self::HEIGHT_TOO_BIG => "Height of the image '%value%' is bigger than allowed",
54
+ self::HEIGHT_TOO_SMALL => "Height of the image '%value%' is smaller than allowed",
55
+ self::NOT_DETECTED => "Size of the image '%value%' could not be detected",
56
+ self::NOT_READABLE => "The image '%value%' can not be read"
57
+ );
58
+
59
+ /**
60
+ * @var array Error message template variables
61
+ */
62
+ protected $_messageVariables = array(
63
+ 'minwidth' => '_minwidth',
64
+ 'maxwidth' => '_maxwidth',
65
+ 'minheight' => '_minheight',
66
+ 'maxheight' => '_maxheight'
67
+ );
68
+
69
+ /**
70
+ * Minimum image width
71
+ *
72
+ * @var integer
73
+ */
74
+ protected $_minwidth;
75
+
76
+ /**
77
+ * Maximum image width
78
+ *
79
+ * @var integer
80
+ */
81
+ protected $_maxwidth;
82
+
83
+ /**
84
+ * Minimum image height
85
+ *
86
+ * @var integer
87
+ */
88
+ protected $_minheight;
89
+
90
+ /**
91
+ * Maximum image height
92
+ *
93
+ * @var integer
94
+ */
95
+ protected $_maxheight;
96
+
97
+ /**
98
+ * Sets validator options
99
+ *
100
+ * Min limits the filesize, when used with max=null if is the maximum filesize
101
+ * It also accepts an array with the keys 'min' and 'max'
102
+ *
103
+ * @param integer|array $max Maximum filesize
104
+ * @param integer $max Maximum filesize
105
+ * @return void
106
+ */
107
+ public function __construct($minwidth = 0, $minheight = 0, $maxwidth = null, $maxheight = null)
108
+ {
109
+ if (is_array($minwidth) === true) {
110
+ if (isset($minwidth['maxheight']) === true) {
111
+ $maxheight = $minwidth['maxheight'];
112
+ }
113
+
114
+ if (isset($minwidth['minheight']) === true) {
115
+ $minheight = $minwidth['minheight'];
116
+ }
117
+
118
+ if (isset($minwidth['maxwidth']) === true) {
119
+ $maxwidth = $minwidth['maxwidth'];
120
+ }
121
+
122
+ if (isset($minwidth['minwidth']) === true) {
123
+ $minwidth = $minwidth['minwidth'];
124
+ }
125
+
126
+ if (isset($minwidth[0]) === true) {
127
+ $maxheight = $minwidth[3];
128
+ $maxwidth = $minwidth[2];
129
+ $minheight = $minwidth[1];
130
+ $minwidth = $minwidth[0];
131
+ }
132
+ }
133
+
134
+ $this->setImageMin($minwidth, $minheight);
135
+ $this->setImageMax($maxwidth, $maxheight);
136
+ }
137
+
138
+ /**
139
+ * Returns the set minimum image sizes
140
+ *
141
+ * @return array
142
+ */
143
+ public function getImageMin()
144
+ {
145
+ return array($this->_minwidth, $this->_minheight);
146
+ }
147
+
148
+ /**
149
+ * Returns the set maximum image sizes
150
+ *
151
+ * @return array
152
+ */
153
+ public function getImageMax()
154
+ {
155
+ return array($this->_maxwidth, $this->_maxheight);
156
+ }
157
+
158
+ /**
159
+ * Returns the set image width sizes
160
+ *
161
+ * @return array
162
+ */
163
+ public function getImageWidth()
164
+ {
165
+ return array($this->_minwidth, $this->_maxwidth);
166
+ }
167
+
168
+ /**
169
+ * Returns the set image height sizes
170
+ *
171
+ * @return array
172
+ */
173
+ public function getImageHeight()
174
+ {
175
+ return array($this->_minheight, $this->_maxheight);
176
+ }
177
+
178
+ /**
179
+ * Sets the minimum image size
180
+ *
181
+ * @param integer $minwidth The minimum image width
182
+ * @param integer $minheight The minimum image height
183
+ * @throws Zend_Validate_Exception When minwidth is greater than maxwidth
184
+ * @throws Zend_Validate_Exception When minheight is greater than maxheight
185
+ * @return Zend_Validate_File_ImageSize Provides a fluent interface
186
+ */
187
+ public function setImageMin($minwidth, $minheight)
188
+ {
189
+ if (($this->_maxwidth !== null) and ($minwidth > $this->_maxwidth)) {
190
+ require_once 'Zend/Validate/Exception.php';
191
+ throw new Zend_Validate_Exception("The minimum image width must be less than or equal to the "
192
+ . " maximum image width, but {$minwidth} > {$this->_maxwidth}");
193
+ }
194
+
195
+ if (($this->_maxheight !== null) and ($minheight > $this->_maxheight)) {
196
+ require_once 'Zend/Validate/Exception.php';
197
+ throw new Zend_Validate_Exception("The minimum image height must be less than or equal to the "
198
+ . " maximum image height, but {$minheight} > {$this->_maxheight}");
199
+ }
200
+
201
+ $this->_minwidth = max(0, (integer) $minwidth);
202
+ $this->_minheight = max(0, (integer) $minheight);
203
+ return $this;
204
+ }
205
+
206
+ /**
207
+ * Sets the maximum image size
208
+ *
209
+ * @param integer $maxwidth The maximum image width
210
+ * @param integer $maxheight The maximum image height
211
+ * @throws Zend_Validate_Exception When maxwidth is smaller than minwidth
212
+ * @throws Zend_Validate_Exception When maxheight is smaller than minheight
213
+ * @return Zend_Validate_StringLength Provides a fluent interface
214
+ */
215
+ public function setImageMax($maxwidth, $maxheight)
216
+ {
217
+ if ($maxwidth === null) {
218
+ $tempwidth = null;
219
+ } else if (($this->_minwidth !== null) and ($maxwidth < $this->_minwidth)) {
220
+ require_once 'Zend/Validate/Exception.php';
221
+ throw new Zend_Validate_Exception("The maximum image width must be greater than or equal to the "
222
+ . "minimum image width, but {$maxwidth} < {$this->_minwidth}");
223
+ } else {
224
+ $tempwidth = (integer) $maxwidth;
225
+ }
226
+
227
+ if ($maxheight === null) {
228
+ $tempheight = null;
229
+ } else if (($this->_minheight !== null) and ($maxheight < $this->_minheight)) {
230
+ require_once 'Zend/Validate/Exception.php';
231
+ throw new Zend_Validate_Exception("The maximum image height must be greater than or equal to the "
232
+ . "minimum image height, but {$maxheight} < {$this->_minwidth}");
233
+ } else {
234
+ $tempheight = (integer) $maxheight;
235
+ }
236
+
237
+ $this->_maxwidth = $tempwidth;
238
+ $this->_maxheight = $tempheight;
239
+ return $this;
240
+ }
241
+
242
+ /**
243
+ * Sets the mimimum and maximum image width
244
+ *
245
+ * @param integer $minwidth The minimum image width
246
+ * @param integer $maxwidth The maximum image width
247
+ * @return Zend_Validate_File_ImageSize Provides a fluent interface
248
+ */
249
+ public function setImageWidth($minwidth, $maxwidth)
250
+ {
251
+ $this->setImageMin($minwidth, $this->_minheight);
252
+ $this->setImageMax($maxwidth, $this->_maxheight);
253
+ return $this;
254
+ }
255
+
256
+ /**
257
+ * Sets the mimimum and maximum image height
258
+ *
259
+ * @param integer $minheight The minimum image height
260
+ * @param integer $maxheight The maximum image height
261
+ * @return Zend_Validate_File_ImageSize Provides a fluent interface
262
+ */
263
+ public function setImageHeight($minheight, $maxheight)
264
+ {
265
+ $this->setImageMin($this->_minwidth, $minheight);
266
+ $this->setImageMax($this->_maxwidth, $maxheight);
267
+ return $this;
268
+ }
269
+
270
+ /**
271
+ * Defined by Zend_Validate_Interface
272
+ *
273
+ * Returns true if and only if the imagesize of $value is at least min and
274
+ * not bigger than max
275
+ *
276
+ * @param string $value Real file to check for image size
277
+ * @param array $file File data from Zend_File_Transfer
278
+ * @return boolean
279
+ */
280
+ public function isValid($value, $file = null)
281
+ {
282
+ // Is file readable ?
283
+ if (@is_readable($value) === false) {
284
+ $this->_throw($file, self::NOT_READABLE);
285
+ return false;
286
+ }
287
+
288
+ $size = @getimagesize($value);
289
+ $this->_setValue($file);
290
+
291
+ if (empty($size) or ($size[0] === 0) or ($size[1] === 0)) {
292
+ $this->_throw($file, self::NOT_DETECTED);
293
+ return false;
294
+ }
295
+
296
+ if ($size[0] < $this->_minwidth) {
297
+ $this->_throw($file, self::WIDTH_TOO_SMALL);
298
+ }
299
+
300
+ if ($size[1] < $this->_minheight) {
301
+ $this->_throw($file, self::HEIGHT_TOO_SMALL);
302
+ }
303
+
304
+ if (($this->_maxwidth !== null) and ($this->_maxwidth < $size[0])) {
305
+ $this->_throw($file, self::WIDTH_TOO_BIG);
306
+ }
307
+
308
+ if (($this->_maxheight !== null) and ($this->_maxheight < $size[1])) {
309
+ $this->_throw($file, self::HEIGHT_TOO_BIG);
310
+ }
311
+
312
+ if (count($this->_messages) > 0) {
313
+ return false;
314
+ } else {
315
+ return true;
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Throws an error of the given type
321
+ *
322
+ * @param string $file
323
+ * @param string $errorType
324
+ * @return false
325
+ */
326
+ protected function _throw($file, $errorType)
327
+ {
328
+ if ($file !== null) {
329
+ $this->_value = $file['name'];
330
+ }
331
+
332
+ $this->_error($errorType);
333
+ return false;
334
+ }
335
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/MimeType.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator for the mime type of a file
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
36
+ {
37
+ const FALSE_TYPE = 'fileMimeTypeFalse';
38
+ const NOT_DETECTED = 'fileMimeTypeNotDetected';
39
+ const NOT_READABLE = 'fileMimeTypeNotReadable';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::FALSE_TYPE => "The file '%value%' has a false mimetype",
46
+ self::NOT_DETECTED => "The mimetype of file '%value%' has not been detected",
47
+ self::NOT_READABLE => "The file '%value%' can not be read"
48
+ );
49
+
50
+ /**
51
+ * @var array
52
+ */
53
+ protected $_messageVariables = array(
54
+ 'mimetype' => '_mimetype'
55
+ );
56
+
57
+ /**
58
+ * Mimetypes
59
+ *
60
+ * If null, there is no mimetype
61
+ *
62
+ * @var string|null
63
+ */
64
+ protected $_mimetype;
65
+
66
+ /**
67
+ * Sets validator options
68
+ *
69
+ * Mimetype to accept
70
+ *
71
+ * @param string|array $mimetype MimeType
72
+ * @return void
73
+ */
74
+ public function __construct($mimetype)
75
+ {
76
+ $this->setMimeType($mimetype);
77
+ }
78
+
79
+ /**
80
+ * Returns the set mimetypes
81
+ *
82
+ * @param boolean $asArray Returns the values as array, when false an concated string is returned
83
+ * @return integer
84
+ */
85
+ public function getMimeType($asArray = false)
86
+ {
87
+ $asArray = (bool) $asArray;
88
+ $mimetype = (string) $this->_mimetype;
89
+ if ($asArray) {
90
+ $mimetype = explode(',', $mimetype);
91
+ }
92
+
93
+ return $mimetype;
94
+ }
95
+
96
+ /**
97
+ * Sets the mimetypes
98
+ *
99
+ * @param string|array $mimetype The mimetypes to validate
100
+ * @return Zend_Validate_File_Extension Provides a fluent interface
101
+ */
102
+ public function setMimeType($mimetype)
103
+ {
104
+ $this->_mimetype = null;
105
+ $this->addMimeType($mimetype);
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Adds the mimetypes
111
+ *
112
+ * @param string|array $mimetype The mimetypes to add for validation
113
+ * @return Zend_Validate_File_Extension Provides a fluent interface
114
+ */
115
+ public function addMimeType($mimetype)
116
+ {
117
+ $mimetypes = $this->getMimeType(true);
118
+ if (is_string($mimetype)) {
119
+ $mimetype = explode(',', $mimetype);
120
+ }
121
+
122
+ foreach ($mimetype as $content) {
123
+ if (empty($content) || !is_string($content)) {
124
+ continue;
125
+ }
126
+ $mimetypes[] = trim($content);
127
+ }
128
+ $mimetypes = array_unique($mimetypes);
129
+
130
+ // Sanity check to ensure no empty values
131
+ foreach ($mimetypes as $key => $mt) {
132
+ if (empty($mt)) {
133
+ unset($mimetypes[$key]);
134
+ }
135
+ }
136
+
137
+ $this->_mimetype = implode(',', $mimetypes);
138
+
139
+ return $this;
140
+ }
141
+
142
+ /**
143
+ * Defined by Zend_Validate_Interface
144
+ *
145
+ * Returns true if the mimetype of the file matches the given ones. Also parts
146
+ * of mimetypes can be checked. If you give for example "image" all image
147
+ * mime types will be accepted like "image/gif", "image/jpeg" and so on.
148
+ *
149
+ * @param string $value Real file to check for mimetype
150
+ * @param array $file File data from Zend_File_Transfer
151
+ * @return boolean
152
+ */
153
+ public function isValid($value, $file = null)
154
+ {
155
+ // Is file readable ?
156
+ if (!@is_readable($value)) {
157
+ $this->_throw($file, self::NOT_READABLE);
158
+ return false;
159
+ }
160
+
161
+ if ($file !== null) {
162
+ $info['type'] = $file['type'];
163
+ } else {
164
+ $this->_throw($file, self::NOT_DETECTED);
165
+ return false;
166
+ }
167
+
168
+ $mimetype = $this->getMimeType(true);
169
+ if (in_array($info['type'], $mimetype)) {
170
+ return true;
171
+ }
172
+
173
+ foreach($mimetype as $mime) {
174
+ $types = explode('/', $info['type']);
175
+ if (in_array($mime, $types)) {
176
+ return true;
177
+ }
178
+ }
179
+
180
+ $this->_throw($file, self::FALSE_TYPE);
181
+ return false;
182
+ }
183
+
184
+ /**
185
+ * Throws an error of the given type
186
+ *
187
+ * @param string $file
188
+ * @param string $errorType
189
+ * @return false
190
+ */
191
+ protected function _throw($file, $errorType)
192
+ {
193
+ if ($file !== null) {
194
+ $this->_value = $file['name'];
195
+ }
196
+
197
+ $this->_error($errorType);
198
+ return false;
199
+ }
200
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/NotExists.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_File_Exists
24
+ */
25
+ require_once 'Zend/Validate/File/Exists.php';
26
+
27
+ /**
28
+ * Validator which checks if the destination file does not exist
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_NotExists extends Zend_Validate_File_Exists
36
+ {
37
+ /**
38
+ * @const string Error constants
39
+ */
40
+ const DOES_EXIST = 'fileNotExistsDoesExist';
41
+
42
+ /**
43
+ * @var array Error message templates
44
+ */
45
+ protected $_messageTemplates = array(
46
+ self::DOES_EXIST => "The file '%value%' does exist"
47
+ );
48
+
49
+ /**
50
+ * Defined by Zend_Validate_Interface
51
+ *
52
+ * Returns true if and only if the file does not exist in the set destinations
53
+ *
54
+ * @param string $value Real file to check for
55
+ * @param array $file File data from Zend_File_Transfer
56
+ * @return boolean
57
+ */
58
+ public function isValid($value, $file = null)
59
+ {
60
+ $directories = $this->getDirectory(true);
61
+ if (($file !== null) and (!empty($file['destination']))) {
62
+ $directories[] = $file['destination'];
63
+ } else if (!isset($file['name'])) {
64
+ $file['name'] = $value;
65
+ }
66
+
67
+ foreach ($directories as $directory) {
68
+ if (empty($directory)) {
69
+ continue;
70
+ }
71
+
72
+ $check = true;
73
+ if (file_exists($directory . DIRECTORY_SEPARATOR . $file['name'])) {
74
+ $this->_throw($file, self::DOES_EXIST);
75
+ return false;
76
+ }
77
+ }
78
+
79
+ if (!isset($check)) {
80
+ $this->_throw($file, self::DOES_EXIST);
81
+ return false;
82
+ }
83
+
84
+ return true;
85
+ }
86
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/Size.php ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator for the maximum size of a file up to a max of 2GB
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_Size extends Zend_Validate_Abstract
36
+ {
37
+ /**#@+
38
+ * @const string Error constants
39
+ */
40
+ const TOO_BIG = 'fileSizeTooBig';
41
+ const TOO_SMALL = 'fileSizeTooSmall';
42
+ const NOT_FOUND = 'fileSizeNotFound';
43
+ /**#@-*/
44
+
45
+ /**
46
+ * @var array Error message templates
47
+ */
48
+ protected $_messageTemplates = array(
49
+ self::TOO_BIG => "The file '%value%' is bigger than allowed",
50
+ self::TOO_SMALL => "The file '%value%' is smaller than allowed",
51
+ self::NOT_FOUND => "The file '%value%' could not be found"
52
+ );
53
+
54
+ /**
55
+ * @var array Error message template variables
56
+ */
57
+ protected $_messageVariables = array(
58
+ 'min' => '_min',
59
+ 'max' => '_max'
60
+ );
61
+
62
+ /**
63
+ * Minimum filesize
64
+ * @var integer
65
+ */
66
+ protected $_min;
67
+
68
+ /**
69
+ * Maximum filesize
70
+ *
71
+ * If null, there is no maximum filesize
72
+ *
73
+ * @var integer|null
74
+ */
75
+ protected $_max;
76
+
77
+ /**
78
+ * Sets validator options
79
+ *
80
+ * Min limits the filesize, when used with max=null it is the maximum filesize
81
+ * It also accepts an array with the keys 'min' and 'max'
82
+ *
83
+ * @param integer|array $min Minimum filesize
84
+ * @param integer $max Maximum filesize
85
+ * @return void
86
+ */
87
+ public function __construct($min, $max = null)
88
+ {
89
+ if (is_array($min)) {
90
+ $count = count($min);
91
+ if (array_key_exists('min', $min)) {
92
+ if (array_key_exists('max', $min)) {
93
+ $max = $min['max'];
94
+ }
95
+
96
+ $min = $min['min'];
97
+ } elseif ($count === 2) {
98
+ $minValue = array_shift($min);
99
+ $max = array_shift($min);
100
+ $min = $minValue;
101
+ } elseif($count === 1) {
102
+ $min = array_shift($min);
103
+ $max = null;
104
+ } else {
105
+ $min = 0;
106
+ $max = null;
107
+ }
108
+ }
109
+
110
+ if (empty($max)) {
111
+ $max = $min;
112
+ $min = 0;
113
+ }
114
+
115
+ $this->setMin($min);
116
+ $this->setMax($max);
117
+ }
118
+
119
+ /**
120
+ * Returns the minimum filesize
121
+ *
122
+ * @param boolean $unit Return the value with unit, when false the plan bytes will be returned
123
+ * @return integer
124
+ */
125
+ public function getMin($unit = true)
126
+ {
127
+ $unit = (bool) $unit;
128
+ $min = $this->_min;
129
+ if ($unit) {
130
+ $min = $this->_toByteString($min);
131
+ }
132
+ return $min;
133
+ }
134
+
135
+ /**
136
+ * Sets the minimum filesize
137
+ *
138
+ * @param integer $min The minimum filesize
139
+ * @return Zend_Validate_File_Size Provides a fluent interface
140
+ * @throws Zend_Validate_Exception When min is greater than max
141
+ */
142
+ public function setMin($min)
143
+ {
144
+ $min = (integer) $this->_fromByteString($min);
145
+ if (($this->_max !== null) && ($min > $this->_max)) {
146
+ require_once 'Zend/Validate/Exception.php';
147
+ throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum filesize, but $min >"
148
+ . " {$this->_max}");
149
+ }
150
+
151
+ $this->_min = max(0, $min);
152
+ return $this;
153
+ }
154
+
155
+ /**
156
+ * Returns the maximum filesize
157
+ *
158
+ * @param boolean $unit Return the value with unit, when false the plan bytes will be returned
159
+ * @return integer|null
160
+ */
161
+ public function getMax($unit = true)
162
+ {
163
+ $unit = (bool) $unit;
164
+ $max = $this->_max;
165
+ if ($unit) {
166
+ $max = $this->_toByteString($max);
167
+ }
168
+ return $max;
169
+ }
170
+
171
+ /**
172
+ * Sets the maximum filesize
173
+ *
174
+ * @param integer|null $max The maximum filesize
175
+ * @return Zend_Validate_StringLength Provides a fluent interface
176
+ * @throws Zend_Validate_Exception When max is smaller than min
177
+ */
178
+ public function setMax($max)
179
+ {
180
+ $max = (integer) $this->_fromByteString($max);
181
+ if (($this->_min !== null) && ($max < $this->_min)) {
182
+ require_once 'Zend/Validate/Exception.php';
183
+ throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum filesize, but "
184
+ . "$max < {$this->_min}");
185
+ } else {
186
+ $this->_max = $max;
187
+ }
188
+
189
+ return $this;
190
+ }
191
+
192
+ /**
193
+ * Defined by Zend_Validate_Interface
194
+ *
195
+ * Returns true if and only if the filesize of $value is at least min and
196
+ * not bigger than max (when max is not null).
197
+ *
198
+ * @param string $value Real file to check for size
199
+ * @param array $file File data from Zend_File_Transfer
200
+ * @return boolean
201
+ */
202
+ public function isValid($value, $file = null)
203
+ {
204
+ // Is file readable ?
205
+ if (!@is_readable($value)) {
206
+ $this->_throw($file, self::NOT_FOUND);
207
+ return false;
208
+ }
209
+
210
+ // limited to 4GB files
211
+ $size = sprintf("%u",@filesize($value));
212
+ $this->_setValue($size);
213
+
214
+ // Check to see if it's smaller than min size
215
+ if (($this->_min !== null) && ($size < $this->_min)) {
216
+ $this->_throw($file, self::TOO_SMALL);
217
+ }
218
+
219
+ // Check to see if it's larger than max size
220
+ if (($this->_max !== null) && ($this->_max < $size)) {
221
+ $this->_throw($file, self::TOO_BIG);
222
+ }
223
+
224
+ if (count($this->_messages) > 0) {
225
+ return false;
226
+ } else {
227
+ return true;
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Returns the formatted size
233
+ *
234
+ * @param integer $size
235
+ * @return string
236
+ */
237
+ protected function _toByteString($size)
238
+ {
239
+ $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
240
+ for ($i=0; $size > 1024 && $i < 9; $i++) {
241
+ $size /= 1024;
242
+ }
243
+ return round($size, 2).$sizes[$i];
244
+ }
245
+
246
+ /**
247
+ * Returns the unformatted size
248
+ *
249
+ * @param string $size
250
+ * @return integer
251
+ */
252
+ protected function _fromByteString($size)
253
+ {
254
+ if (is_numeric($size)) {
255
+ return (integer) $size;
256
+ }
257
+
258
+ $type = trim(substr($size, -2));
259
+ $value = substr($size, 0, -2);
260
+ switch (strtoupper($type)) {
261
+ case 'YB':
262
+ $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024);
263
+ break;
264
+ case 'ZB':
265
+ $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024);
266
+ break;
267
+ case 'EB':
268
+ $value *= (1024 * 1024 * 1024 * 1024 * 1024 * 1024);
269
+ break;
270
+ case 'PB':
271
+ $value *= (1024 * 1024 * 1024 * 1024 * 1024);
272
+ break;
273
+ case 'TB':
274
+ $value *= (1024 * 1024 * 1024 * 1024);
275
+ break;
276
+ case 'GB':
277
+ $value *= (1024 * 1024 * 1024);
278
+ break;
279
+ case 'MB':
280
+ $value *= (1024 * 1024);
281
+ break;
282
+ case 'KB':
283
+ $value *= 1024;
284
+ break;
285
+ default:
286
+ break;
287
+ }
288
+
289
+ return $value;
290
+ }
291
+
292
+ /**
293
+ * Throws an error of the given type
294
+ *
295
+ * @param string $file
296
+ * @param string $errorType
297
+ * @return false
298
+ */
299
+ protected function _throw($file, $errorType)
300
+ {
301
+ if ($file !== null) {
302
+ $this->_value = $file['name'];
303
+ }
304
+
305
+ $this->_error($errorType);
306
+ return false;
307
+ }
308
+ }
includes/phpQuery/phpQuery/Zend/Validate/File/Upload.php ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: $
20
+ */
21
+
22
+ /**
23
+ * @see Zend_Validate_Abstract
24
+ */
25
+ require_once 'Zend/Validate/Abstract.php';
26
+
27
+ /**
28
+ * Validator for the maximum size of a file up to a max of 2GB
29
+ *
30
+ * @category Zend
31
+ * @package Zend_Validate
32
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Zend_Validate_File_Upload extends Zend_Validate_Abstract
36
+ {
37
+ /**@#+
38
+ * @const string Error constants
39
+ */
40
+ const INI_SIZE = 'fileUploadErrorIniSize';
41
+ const FORM_SIZE = 'fileUploadErrorFormSize';
42
+ const PARTIAL = 'fileUploadErrorPartial';
43
+ const NO_FILE = 'fileUploadErrorNoFile';
44
+ const NO_TMP_DIR = 'fileUploadErrorNoTmpDir';
45
+ const CANT_WRITE = 'fileUploadErrorCantWrite';
46
+ const EXTENSION = 'fileUploadErrorExtension';
47
+ const ATTACK = 'fileUploadErrorAttack';
48
+ const FILE_NOT_FOUND = 'fileUploadErrorFileNotFound';
49
+ const UNKNOWN = 'fileUploadErrorUnknown';
50
+ /**@#-*/
51
+
52
+ /**
53
+ * @var array Error message templates
54
+ */
55
+ protected $_messageTemplates = array(
56
+ self::INI_SIZE => "The file '%value%' exceeds the defined ini size",
57
+ self::FORM_SIZE => "The file '%value%' exceeds the defined form size",
58
+ self::PARTIAL => "The file '%value%' was only partially uploaded",
59
+ self::NO_FILE => "The file '%value%' was not uploaded",
60
+ self::NO_TMP_DIR => "No temporary directory was found for the file '%value%'",
61
+ self::CANT_WRITE => "The file '%value%' can't be written",
62
+ self::EXTENSION => "The extension returned an error while uploading the file '%value%'",
63
+ self::ATTACK => "The file '%value%' was illegal uploaded, possible attack",
64
+ self::FILE_NOT_FOUND => "The file '%value%' was not found",
65
+ self::UNKNOWN => "Unknown error while uploading the file '%value%'"
66
+ );
67
+
68
+ /**
69
+ * Internal array of files
70
+ * @var array
71
+ */
72
+ protected $_files = array();
73
+
74
+ /**
75
+ * Sets validator options
76
+ *
77
+ * The array $files must be given in syntax of Zend_File_Transfer to be checked
78
+ * If no files are given the $_FILES array will be used automatically.
79
+ * NOTE: This validator will only work with HTTP POST uploads!
80
+ *
81
+ * @param array $files Array of files in syntax of Zend_File_Transfer
82
+ * @return void
83
+ */
84
+ public function __construct($files = array())
85
+ {
86
+ $this->setFiles($files);
87
+ }
88
+
89
+ /**
90
+ * Returns the array of set files
91
+ *
92
+ * @param string $files (Optional) The file to return in detail
93
+ * @return array
94
+ * @throws Zend_Validate_Exception If file is not found
95
+ */
96
+ public function getFiles($file = null)
97
+ {
98
+ if ($file !== null) {
99
+ $return = array();
100
+ foreach ($this->_files as $name => $content) {
101
+ if ($name === $file) {
102
+ $return[$file] = $this->_files[$name];
103
+ }
104
+
105
+ if ($content['name'] === $file) {
106
+ $return[$name] = $this->_files[$name];
107
+ }
108
+ }
109
+
110
+ if (count($return) === 0) {
111
+ require_once 'Zend/Validate/Exception.php';
112
+ throw new Zend_Validate_Exception("The file '$file' was not found");
113
+ }
114
+
115
+ return $return;
116
+ }
117
+
118
+ return $this->_files;
119
+ }
120
+
121
+ /**
122
+ * Sets the minimum filesize
123
+ *
124
+ * @param array $files The files to check in syntax of Zend_File_Transfer
125
+ * @return Zend_Validate_File_Upload Provides a fluent interface
126
+ */
127
+ public function setFiles($files = array())
128
+ {
129
+ if (count($files) === 0) {
130
+ $this->_files = $_FILES;
131
+ } else {
132
+ $this->_files = $files;
133
+ }
134
+ return $this;
135
+ }
136
+
137
+ /**
138
+ * Defined by Zend_Validate_Interface
139
+ *
140
+ * Returns true if and only if the file was uploaded without errors
141
+ *
142
+ * @param string $value Single file to check for upload errors, when giving null the $_FILES array
143
+ * from initialization will be used
144
+ * @return boolean
145
+ */
146
+ public function isValid($value)
147
+ {
148
+ if (array_key_exists($value, $this->_files)) {
149
+ $files[$value] = $this->_files[$value];
150
+ } else {
151
+ foreach ($this->_files as $file => $content) {
152
+ if ($content['name'] === $value) {
153
+ $files[$file] = $this->_files[$file];
154
+ }
155
+
156
+ if ($content['tmp_name'] === $value) {
157
+ $files[$file] = $this->_files[$file];
158
+ }
159
+ }
160
+ }
161
+
162
+ if (empty($files)) {
163
+ $this->_error(self::FILE_NOT_FOUND);
164
+ return false;
165
+ }
166
+
167
+ foreach ($files as $file => $content) {
168
+ $this->_value = $file;
169
+ switch($content['error']) {
170
+ case 0:
171
+ if (!is_uploaded_file($content['tmp_name'])) {
172
+ $this->_error(self::ATTACK);
173
+ }
174
+ break;
175
+
176
+ case 1:
177
+ $this->_error(self::INI_SIZE);
178
+ break;
179
+
180
+ case 2:
181
+ $this->_error(self::FORM_SIZE);
182
+ break;
183
+
184
+ case 3:
185
+ $this->_error(self::PARTIAL);
186
+ break;
187
+
188
+ case 4:
189
+ $this->_error(self::NO_FILE);
190
+ break;
191
+
192
+ case 6:
193
+ $this->_error(self::NO_TMP_DIR);
194
+ break;
195
+
196
+ case 7:
197
+ $this->_error(self::CANT_WRITE);
198
+ break;
199
+
200
+ case 8:
201
+ $this->_error(self::EXTENSION);
202
+ break;
203
+
204
+ default:
205
+ $this->_error(self::UNKNOWN);
206
+ break;
207
+ }
208
+ }
209
+
210
+ if (count($this->_messages) > 0) {
211
+ return false;
212
+ } else {
213
+ return true;
214
+ }
215
+ }
216
+ }
includes/phpQuery/phpQuery/Zend/Validate/Float.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Float.php 8714 2008-03-09 20:03:45Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Float extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_FLOAT = 'notFloat';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_FLOAT => "'%value%' does not appear to be a float"
46
+ );
47
+
48
+ /**
49
+ * Defined by Zend_Validate_Interface
50
+ *
51
+ * Returns true if and only if $value is a floating-point value
52
+ *
53
+ * @param string $value
54
+ * @return boolean
55
+ */
56
+ public function isValid($value)
57
+ {
58
+ $valueString = (string) $value;
59
+
60
+ $this->_setValue($valueString);
61
+
62
+ $locale = localeconv();
63
+
64
+ $valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
65
+ $valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
66
+
67
+ if (strval(floatval($valueFiltered)) != $valueFiltered) {
68
+ $this->_error();
69
+ return false;
70
+ }
71
+
72
+ return true;
73
+ }
74
+
75
+ }
includes/phpQuery/phpQuery/Zend/Validate/GreaterThan.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: GreaterThan.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_GreaterThan extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_GREATER = 'notGreaterThan';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_GREATER => "'%value%' is not greater than '%min%'"
46
+ );
47
+
48
+ /**
49
+ * @var array
50
+ */
51
+ protected $_messageVariables = array(
52
+ 'min' => '_min'
53
+ );
54
+
55
+ /**
56
+ * Minimum value
57
+ *
58
+ * @var mixed
59
+ */
60
+ protected $_min;
61
+
62
+ /**
63
+ * Sets validator options
64
+ *
65
+ * @param mixed $min
66
+ * @return void
67
+ */
68
+ public function __construct($min)
69
+ {
70
+ $this->setMin($min);
71
+ }
72
+
73
+ /**
74
+ * Returns the min option
75
+ *
76
+ * @return mixed
77
+ */
78
+ public function getMin()
79
+ {
80
+ return $this->_min;
81
+ }
82
+
83
+ /**
84
+ * Sets the min option
85
+ *
86
+ * @param mixed $min
87
+ * @return Zend_Validate_GreaterThan Provides a fluent interface
88
+ */
89
+ public function setMin($min)
90
+ {
91
+ $this->_min = $min;
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Defined by Zend_Validate_Interface
97
+ *
98
+ * Returns true if and only if $value is greater than min option
99
+ *
100
+ * @param mixed $value
101
+ * @return boolean
102
+ */
103
+ public function isValid($value)
104
+ {
105
+ $this->_setValue($value);
106
+
107
+ if ($this->_min >= $value) {
108
+ $this->_error();
109
+ return false;
110
+ }
111
+ return true;
112
+ }
113
+
114
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hex.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Hex.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hex extends Zend_Validate_Abstract
37
+ {
38
+ /**
39
+ * Validation failure message key for when the value contains characters other than hexadecimal digits
40
+ */
41
+ const NOT_HEX = 'notHex';
42
+
43
+ /**
44
+ * Validation failure message template definitions
45
+ *
46
+ * @var array
47
+ */
48
+ protected $_messageTemplates = array(
49
+ self::NOT_HEX => "'%value%' has not only hexadecimal digit characters"
50
+ );
51
+
52
+ /**
53
+ * Defined by Zend_Validate_Interface
54
+ *
55
+ * Returns true if and only if $value contains only hexadecimal digit characters
56
+ *
57
+ * @param string $value
58
+ * @return boolean
59
+ */
60
+ public function isValid($value)
61
+ {
62
+ $valueString = (string) $value;
63
+
64
+ $this->_setValue($valueString);
65
+
66
+ if (!ctype_xdigit($valueString)) {
67
+ $this->_error();
68
+ return false;
69
+ }
70
+
71
+ return true;
72
+ }
73
+
74
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname.php ADDED
@@ -0,0 +1,444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Hostname.php 9195 2008-04-10 17:35:30Z jokke $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+ /**
30
+ * @see Zend_Loader
31
+ */
32
+ require_once 'Zend/Loader.php';
33
+
34
+ /**
35
+ * @see Zend_Validate_Ip
36
+ */
37
+ require_once 'Zend/Validate/Ip.php';
38
+
39
+ /**
40
+ * Please note there are two standalone test scripts for testing IDN characters due to problems
41
+ * with file encoding.
42
+ *
43
+ * The first is tests/Zend/Validate/HostnameTestStandalone.php which is designed to be run on
44
+ * the command line.
45
+ *
46
+ * The second is tests/Zend/Validate/HostnameTestForm.php which is designed to be run via HTML
47
+ * to allow users to test entering UTF-8 characters in a form.
48
+ *
49
+ * @category Zend
50
+ * @package Zend_Validate
51
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
52
+ * @license http://framework.zend.com/license/new-bsd New BSD License
53
+ */
54
+ class Zend_Validate_Hostname extends Zend_Validate_Abstract
55
+ {
56
+
57
+ const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed';
58
+ const UNKNOWN_TLD = 'hostnameUnknownTld';
59
+ const INVALID_DASH = 'hostnameDashCharacter';
60
+ const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema';
61
+ const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld';
62
+ const INVALID_HOSTNAME = 'hostnameInvalidHostname';
63
+ const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName';
64
+ const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed';
65
+
66
+ /**
67
+ * @var array
68
+ */
69
+ protected $_messageTemplates = array(
70
+ self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed",
71
+ self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list",
72
+ self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash (-) in an invalid position",
73
+ self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'",
74
+ self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part",
75
+ self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname",
76
+ self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name",
77
+ self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed"
78
+ );
79
+
80
+ /**
81
+ * @var array
82
+ */
83
+ protected $_messageVariables = array(
84
+ 'tld' => '_tld'
85
+ );
86
+
87
+ /**
88
+ * Allows Internet domain names (e.g., example.com)
89
+ */
90
+ const ALLOW_DNS = 1;
91
+
92
+ /**
93
+ * Allows IP addresses
94
+ */
95
+ const ALLOW_IP = 2;
96
+
97
+ /**
98
+ * Allows local network names (e.g., localhost, www.localdomain)
99
+ */
100
+ const ALLOW_LOCAL = 4;
101
+
102
+ /**
103
+ * Allows all types of hostnames
104
+ */
105
+ const ALLOW_ALL = 7;
106
+
107
+ /**
108
+ * Whether IDN domains are validated
109
+ *
110
+ * @var boolean
111
+ */
112
+ private $_validateIdn = true;
113
+
114
+ /**
115
+ * Whether TLDs are validated against a known list
116
+ *
117
+ * @var boolean
118
+ */
119
+ private $_validateTld = true;
120
+
121
+ /**
122
+ * Bit field of ALLOW constants; determines which types of hostnames are allowed
123
+ *
124
+ * @var integer
125
+ */
126
+ protected $_allow;
127
+
128
+ /**
129
+ * Bit field of CHECK constants; determines what additional hostname checks to make
130
+ *
131
+ * @var unknown_type
132
+ */
133
+ // protected $_check;
134
+
135
+ /**
136
+ * Array of valid top-level-domains
137
+ *
138
+ * @var array
139
+ * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain
140
+ */
141
+ protected $_validTlds = array(
142
+ 'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao',
143
+ 'aq', 'ar', 'arpa', 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb',
144
+ 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'biz', 'bj', 'bm', 'bn', 'bo',
145
+ 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', 'cd',
146
+ 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop',
147
+ 'cr', 'cu', 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do',
148
+ 'dz', 'ec', 'edu', 'ee', 'eg', 'er', 'es', 'et', 'eu', 'fi', 'fj',
149
+ 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh',
150
+ 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu',
151
+ 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il',
152
+ 'im', 'in', 'info', 'int', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm',
153
+ 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw',
154
+ 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu',
155
+ 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm',
156
+ 'mn', 'mo', 'mobi', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv',
157
+ 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 'ne', 'net', 'nf', 'ng',
158
+ 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe',
159
+ 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt',
160
+ 'pw', 'py', 'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd',
161
+ 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr',
162
+ 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', 'tj',
163
+ 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw',
164
+ 'tz', 'ua', 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've',
165
+ 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'yt', 'yu', 'za', 'zm',
166
+ 'zw'
167
+ );
168
+
169
+ /**
170
+ * @var string
171
+ */
172
+ protected $_tld;
173
+
174
+ /**
175
+ * Sets validator options
176
+ *
177
+ * @param integer $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS)
178
+ * @param boolean $validateIdn OPTIONAL Set whether IDN domains are validated (default true)
179
+ * @param boolean $validateTld OPTIONAL Set whether the TLD element of a hostname is validated (default true)
180
+ * @param Zend_Validate_Ip $ipValidator OPTIONAL
181
+ * @return void
182
+ * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs
183
+ */
184
+ public function __construct($allow = self::ALLOW_DNS, $validateIdn = true, $validateTld = true, Zend_Validate_Ip $ipValidator = null)
185
+ {
186
+ // Set allow options
187
+ $this->setAllow($allow);
188
+
189
+ // Set validation options
190
+ $this->_validateIdn = $validateIdn;
191
+ $this->_validateTld = $validateTld;
192
+
193
+ $this->setIpValidator($ipValidator);
194
+ }
195
+
196
+ /**
197
+ * @param Zend_Validate_Ip $ipValidator OPTIONAL
198
+ * @return void;
199
+ */
200
+ public function setIpValidator(Zend_Validate_Ip $ipValidator = null)
201
+ {
202
+ if ($ipValidator === null) {
203
+ $ipValidator = new Zend_Validate_Ip();
204
+ }
205
+ $this->_ipValidator = $ipValidator;
206
+ }
207
+
208
+ /**
209
+ * Returns the allow option
210
+ *
211
+ * @return integer
212
+ */
213
+ public function getAllow()
214
+ {
215
+ return $this->_allow;
216
+ }
217
+
218
+ /**
219
+ * Sets the allow option
220
+ *
221
+ * @param integer $allow
222
+ * @return Zend_Validate_Hostname Provides a fluent interface
223
+ */
224
+ public function setAllow($allow)
225
+ {
226
+ $this->_allow = $allow;
227
+ return $this;
228
+ }
229
+
230
+ /**
231
+ * Set whether IDN domains are validated
232
+ *
233
+ * This only applies when DNS hostnames are validated
234
+ *
235
+ * @param boolean $allowed Set allowed to true to validate IDNs, and false to not validate them
236
+ */
237
+ public function setValidateIdn ($allowed)
238
+ {
239
+ $this->_validateIdn = (bool) $allowed;
240
+ }
241
+
242
+ /**
243
+ * Set whether the TLD element of a hostname is validated
244
+ *
245
+ * This only applies when DNS hostnames are validated
246
+ *
247
+ * @param boolean $allowed Set allowed to true to validate TLDs, and false to not validate them
248
+ */
249
+ public function setValidateTld ($allowed)
250
+ {
251
+ $this->_validateTld = (bool) $allowed;
252
+ }
253
+
254
+ /**
255
+ * Sets the check option
256
+ *
257
+ * @param integer $check
258
+ * @return Zend_Validate_Hostname Provides a fluent interface
259
+ */
260
+ /*
261
+ public function setCheck($check)
262
+ {
263
+ $this->_check = $check;
264
+ return $this;
265
+ }
266
+ */
267
+
268
+ /**
269
+ * Defined by Zend_Validate_Interface
270
+ *
271
+ * Returns true if and only if the $value is a valid hostname with respect to the current allow option
272
+ *
273
+ * @param string $value
274
+ * @throws Zend_Validate_Exception if a fatal error occurs for validation process
275
+ * @return boolean
276
+ */
277
+ public function isValid($value)
278
+ {
279
+ $valueString = (string) $value;
280
+
281
+ $this->_setValue($valueString);
282
+
283
+ // Check input against IP address schema
284
+ if ($this->_ipValidator->setTranslator($this->getTranslator())->isValid($valueString)) {
285
+ if (!($this->_allow & self::ALLOW_IP)) {
286
+ $this->_error(self::IP_ADDRESS_NOT_ALLOWED);
287
+ return false;
288
+ } else{
289
+ return true;
290
+ }
291
+ }
292
+
293
+ // Check input against DNS hostname schema
294
+ $domainParts = explode('.', $valueString);
295
+ if ((count($domainParts) > 1) && (strlen($valueString) >= 4) && (strlen($valueString) <= 254)) {
296
+ $status = false;
297
+
298
+ do {
299
+ // First check TLD
300
+ if (preg_match('/([a-z]{2,10})$/i', end($domainParts), $matches)) {
301
+
302
+ reset($domainParts);
303
+
304
+ // Hostname characters are: *(label dot)(label dot label); max 254 chars
305
+ // label: id-prefix [*ldh{61} id-prefix]; max 63 chars
306
+ // id-prefix: alpha / digit
307
+ // ldh: alpha / digit / dash
308
+
309
+ // Match TLD against known list
310
+ $this->_tld = strtolower($matches[1]);
311
+ if ($this->_validateTld) {
312
+ if (!in_array($this->_tld, $this->_validTlds)) {
313
+ $this->_error(self::UNKNOWN_TLD);
314
+ $status = false;
315
+ break;
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Match against IDN hostnames
321
+ * @see Zend_Validate_Hostname_Interface
322
+ */
323
+ $labelChars = 'a-z0-9';
324
+ $utf8 = false;
325
+ $classFile = 'Zend/Validate/Hostname/' . ucfirst($this->_tld) . '.php';
326
+ if ($this->_validateIdn) {
327
+ if (Zend_Loader::isReadable($classFile)) {
328
+
329
+ // Load additional characters
330
+ $className = 'Zend_Validate_Hostname_' . ucfirst($this->_tld);
331
+ Zend_Loader::loadClass($className);
332
+ $labelChars .= call_user_func(array($className, 'getCharacters'));
333
+ $utf8 = true;
334
+ }
335
+ }
336
+
337
+ // Keep label regex short to avoid issues with long patterns when matching IDN hostnames
338
+ $regexLabel = '/^[' . $labelChars . '\x2d]{1,63}$/i';
339
+ if ($utf8) {
340
+ $regexLabel .= 'u';
341
+ }
342
+
343
+ // Check each hostname part
344
+ $valid = true;
345
+ foreach ($domainParts as $domainPart) {
346
+
347
+ // Check dash (-) does not start, end or appear in 3rd and 4th positions
348
+ if (strpos($domainPart, '-') === 0 ||
349
+ (strlen($domainPart) > 2 && strpos($domainPart, '-', 2) == 2 && strpos($domainPart, '-', 3) == 3) ||
350
+ strrpos($domainPart, '-') === strlen($domainPart) - 1) {
351
+
352
+ $this->_error(self::INVALID_DASH);
353
+ $status = false;
354
+ break 2;
355
+ }
356
+
357
+ // Check each domain part
358
+ $status = @preg_match($regexLabel, $domainPart);
359
+ if ($status === false) {
360
+ /**
361
+ * Regex error
362
+ * @see Zend_Validate_Exception
363
+ */
364
+ require_once 'Zend/Validate/Exception.php';
365
+ throw new Zend_Validate_Exception('Internal error: DNS validation failed');
366
+ } elseif ($status === 0) {
367
+ $valid = false;
368
+ }
369
+ }
370
+
371
+ // If all labels didn't match, the hostname is invalid
372
+ if (!$valid) {
373
+ $this->_error(self::INVALID_HOSTNAME_SCHEMA);
374
+ $status = false;
375
+ }
376
+
377
+ } else {
378
+ // Hostname not long enough
379
+ $this->_error(self::UNDECIPHERABLE_TLD);
380
+ $status = false;
381
+ }
382
+ } while (false);
383
+
384
+ // If the input passes as an Internet domain name, and domain names are allowed, then the hostname
385
+ // passes validation
386
+ if ($status && ($this->_allow & self::ALLOW_DNS)) {
387
+ return true;
388
+ }
389
+ } else {
390
+ $this->_error(self::INVALID_HOSTNAME);
391
+ }
392
+
393
+ // Check input against local network name schema; last chance to pass validation
394
+ $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/';
395
+ $status = @preg_match($regexLocal, $valueString);
396
+ if (false === $status) {
397
+ /**
398
+ * Regex error
399
+ * @see Zend_Validate_Exception
400
+ */
401
+ require_once 'Zend/Validate/Exception.php';
402
+ throw new Zend_Validate_Exception('Internal error: local network name validation failed');
403
+ }
404
+
405
+ // If the input passes as a local network name, and local network names are allowed, then the
406
+ // hostname passes validation
407
+ $allowLocal = $this->_allow & self::ALLOW_LOCAL;
408
+ if ($status && $allowLocal) {
409
+ return true;
410
+ }
411
+
412
+ // If the input does not pass as a local network name, add a message
413
+ if (!$status) {
414
+ $this->_error(self::INVALID_LOCAL_NAME);
415
+ }
416
+
417
+ // If local network names are not allowed, add a message
418
+ if ($status && !$allowLocal) {
419
+ $this->_error(self::LOCAL_NAME_NOT_ALLOWED);
420
+ }
421
+
422
+ return false;
423
+ }
424
+
425
+ /**
426
+ * Throws an exception if a regex for $type does not exist
427
+ *
428
+ * @param string $type
429
+ * @throws Zend_Validate_Exception
430
+ * @return Zend_Validate_Hostname Provides a fluent interface
431
+ */
432
+ /*
433
+ protected function _checkRegexType($type)
434
+ {
435
+ if (!isset($this->_regex[$type])) {
436
+ require_once 'Zend/Validate/Exception.php';
437
+ throw new Zend_Validate_Exception("'$type' must be one of ('" . implode(', ', array_keys($this->_regex))
438
+ . "')");
439
+ }
440
+ return $this;
441
+ }
442
+ */
443
+
444
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/At.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: At.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_At implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.nic.at/en/service/technical_information/idn/charset_converter/ Austria (.AT)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00EO}-\x{00F6}\x{00F8}-\x{00FF}\x{0153}\x{0161}\x{017E}';
48
+ }
49
+
50
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/Ch.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Ch.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_Ch implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 Switzerland (.CH)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00EO}-\x{00F6}\x{00F8}-\x{00FF}\x{0153}';
48
+ }
49
+
50
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/De.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: De.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_De implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.denic.de/en/domains/idns/liste.html Germany (.DE) alllowed characters
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E1}\x{00E0}\x{0103}\x{00E2}\x{00E5}\x{00E4}\x{00E3}\x{0105}\x{0101}\x{00E6}\x{0107}' .
48
+ '\x{0109}\x{010D}\x{010B}\x{00E7}\x{010F}\x{0111}\x{00E9}\x{00E8}\x{0115}\x{00EA}\x{011B}' .
49
+ '\x{00EB}\x{0117}\x{0119}\x{0113}\x{011F}\x{011D}\x{0121}\x{0123}\x{0125}\x{0127}\x{00ED}' .
50
+ '\x{00EC}\x{012D}\x{00EE}\x{00EF}\x{0129}\x{012F}\x{012B}\x{0131}\x{0135}\x{0137}\x{013A}' .
51
+ '\x{013E}\x{013C}\x{0142}\x{0144}\x{0148}\x{00F1}\x{0146}\x{014B}\x{00F3}\x{00F2}\x{014F}' .
52
+ '\x{00F4}\x{00F6}\x{0151}\x{00F5}\x{00F8}\x{014D}\x{0153}\x{0138}\x{0155}\x{0159}\x{0157}' .
53
+ '\x{015B}\x{015D}\x{0161}\x{015F}\x{0165}\x{0163}\x{0167}\x{00FA}\x{00F9}\x{016D}\x{00FB}' .
54
+ '\x{016F}\x{00FC}\x{0171}\x{0169}\x{0173}\x{016B}\x{0175}\x{00FD}\x{0177}\x{00FF}\x{017A}' .
55
+ '\x{017E}\x{017C}\x{00F0}\x{00FE}';
56
+ }
57
+
58
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/Fi.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Fi.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_Fi implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html Finland (.FI)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E5}\x{00E4}\x{00F6}';
48
+ }
49
+
50
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/Hu.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Hu.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_Hu implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.domain.hu/domain/English/szabalyzat.html Hungary (.HU)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E1}\x{00E9}\x{00ED}\x{00F3}\x{00F6}\x{0151}\x{00FA}\x{00FC}\x{0171}';
48
+ }
49
+
50
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/Interface.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @category Zend
26
+ * @package Zend_Validate
27
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ interface Zend_Validate_Hostname_Interface
31
+ {
32
+
33
+ /**
34
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
35
+ *
36
+ * UTF-8 characters should be written as four character hex codes \x{XXXX}
37
+ * For example é (lowercase e with acute) is represented by the hex code \x{00E9}
38
+ *
39
+ * You only need to include lower-case equivalents of characters since the hostname
40
+ * check is case-insensitive
41
+ *
42
+ * Please document the supported TLDs in the documentation file at:
43
+ * manual/en/module_specs/Zend_Validate-Hostname.xml
44
+ *
45
+ * @see http://en.wikipedia.org/wiki/Internationalized_domain_name
46
+ * @see http://www.iana.org/cctld/ Country-Code Top-Level Domains (TLDs)
47
+ * @see http://www.columbia.edu/kermit/utf8-t1.html UTF-8 characters
48
+ * @return string
49
+ */
50
+ static function getCharacters();
51
+
52
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/Li.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Li.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_Li implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 Liechtenstein (.LI)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00EO}-\x{00F6}\x{00F8}-\x{00FF}\x{0153}';
48
+ }
49
+
50
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/No.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: No.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_No implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html Norway (.NO)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x00E1\x00E0\x00E4\x010D\x00E7\x0111\x00E9\x00E8\x00EA\x\x014B' .
48
+ '\x0144\x00F1\x00F3\x00F2\x00F4\x00F6\x0161\x0167\x00FC\x017E\x00E6' .
49
+ '\x00F8\x00E5';
50
+ }
51
+
52
+ }
includes/phpQuery/phpQuery/Zend/Validate/Hostname/Se.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Se.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Hostname_Interface
26
+ */
27
+ require_once 'Zend/Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Hostname_Se implements Zend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.iis.se/english/IDN_campaignsite.shtml?lang=en Sweden (.SE)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E5}\x{00E4}\x{00F6}\x{00FC}\x{00E9}';
48
+ }
49
+
50
+ }
includes/phpQuery/phpQuery/Zend/Validate/Identical.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
16
+ * @package Zend_Validate
17
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Identical.php 8118 2008-02-18 16:10:32Z matthew $
20
+ */
21
+
22
+ /** Zend_Validate_Abstract */
23
+ require_once 'Zend/Validate/Abstract.php';
24
+
25
+ /**
26
+ * @category Zend
27
+ * @package Zend_Validate
28
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
29
+ * @license http://framework.zend.com/license/new-bsd New BSD License
30
+ */
31
+ class Zend_Validate_Identical extends Zend_Validate_Abstract
32
+ {
33
+ /**#@+
34
+ * Error codes
35
+ * @const string
36
+ */
37
+ const NOT_SAME = 'notSame';
38
+ const MISSING_TOKEN = 'missingToken';
39
+ /**#@-*/
40
+
41
+ /**
42
+ * Error messages
43
+ * @var array
44
+ */
45
+ protected $_messageTemplates = array(
46
+ self::NOT_SAME => 'Tokens do not match',
47
+ self::MISSING_TOKEN => 'No token was provided to match against',
48
+ );
49
+
50
+ /**
51
+ * Original token against which to validate
52
+ * @var string
53
+ */
54
+ protected $_token;
55
+
56
+ /**
57
+ * Sets validator options
58
+ *
59
+ * @param string $token
60
+ * @return void
61
+ */
62
+ public function __construct($token = null)
63
+ {
64
+ if (null !== $token) {
65
+ $this->setToken($token);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Set token against which to compare
71
+ *
72
+ * @param string $token
73
+ * @return Zend_Validate_Identical
74
+ */
75
+ public function setToken($token)
76
+ {
77
+ $this->_token = (string) $token;
78
+ return $this;
79
+ }
80
+
81
+ /**
82
+ * Retrieve token
83
+ *
84
+ * @return string
85
+ */
86
+ public function getToken()
87
+ {
88
+ return $this->_token;
89
+ }
90
+
91
+ /**
92
+ * Defined by Zend_Validate_Interface
93
+ *
94
+ * Returns true if and only if a token has been set and the provided value
95
+ * matches that token.
96
+ *
97
+ * @param string $value
98
+ * @return boolean
99
+ */
100
+ public function isValid($value)
101
+ {
102
+ $this->_setValue($value);
103
+ $token = $this->getToken();
104
+
105
+ if (empty($token)) {
106
+ $this->_error(self::MISSING_TOKEN);
107
+ return false;
108
+ }
109
+
110
+ if ($value !== $token) {
111
+ $this->_error(self::NOT_SAME);
112
+ return false;
113
+ }
114
+
115
+ return true;
116
+ }
117
+ }
includes/phpQuery/phpQuery/Zend/Validate/InArray.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: InArray.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_InArray extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_IN_ARRAY = 'notInArray';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_IN_ARRAY => "'%value%' was not found in the haystack"
46
+ );
47
+
48
+ /**
49
+ * Haystack of possible values
50
+ *
51
+ * @var array
52
+ */
53
+ protected $_haystack;
54
+
55
+ /**
56
+ * Whether a strict in_array() invocation is used
57
+ *
58
+ * @var boolean
59
+ */
60
+ protected $_strict;
61
+
62
+ /**
63
+ * Sets validator options
64
+ *
65
+ * @param array $haystack
66
+ * @param boolean $strict
67
+ * @return void
68
+ */
69
+ public function __construct(array $haystack, $strict = false)
70
+ {
71
+ $this->setHaystack($haystack)
72
+ ->setStrict($strict);
73
+ }
74
+
75
+ /**
76
+ * Returns the haystack option
77
+ *
78
+ * @return mixed
79
+ */
80
+ public function getHaystack()
81
+ {
82
+ return $this->_haystack;
83
+ }
84
+
85
+ /**
86
+ * Sets the haystack option
87
+ *
88
+ * @param mixed $haystack
89
+ * @return Zend_Validate_InArray Provides a fluent interface
90
+ */
91
+ public function setHaystack(array $haystack)
92
+ {
93
+ $this->_haystack = $haystack;
94
+ return $this;
95
+ }
96
+
97
+ /**
98
+ * Returns the strict option
99
+ *
100
+ * @return boolean
101
+ */
102
+ public function getStrict()
103
+ {
104
+ return $this->_strict;
105
+ }
106
+
107
+ /**
108
+ * Sets the strict option
109
+ *
110
+ * @param boolean $strict
111
+ * @return Zend_Validate_InArray Provides a fluent interface
112
+ */
113
+ public function setStrict($strict)
114
+ {
115
+ $this->_strict = $strict;
116
+ return $this;
117
+ }
118
+
119
+ /**
120
+ * Defined by Zend_Validate_Interface
121
+ *
122
+ * Returns true if and only if $value is contained in the haystack option. If the strict
123
+ * option is true, then the type of $value is also checked.
124
+ *
125
+ * @param mixed $value
126
+ * @return boolean
127
+ */
128
+ public function isValid($value)
129
+ {
130
+ $this->_setValue($value);
131
+ if (!in_array($value, $this->_haystack, $this->_strict)) {
132
+ $this->_error();
133
+ return false;
134
+ }
135
+ return true;
136
+ }
137
+
138
+ }
includes/phpQuery/phpQuery/Zend/Validate/Int.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Int.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Int extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_INT = 'notInt';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_INT => "'%value%' does not appear to be an integer"
46
+ );
47
+
48
+ /**
49
+ * Defined by Zend_Validate_Interface
50
+ *
51
+ * Returns true if and only if $value is a valid integer
52
+ *
53
+ * @param string $value
54
+ * @return boolean
55
+ */
56
+ public function isValid($value)
57
+ {
58
+ $valueString = (string) $value;
59
+
60
+ $this->_setValue($valueString);
61
+
62
+ $locale = localeconv();
63
+
64
+ $valueFiltered = str_replace($locale['decimal_point'], '.', $valueString);
65
+ $valueFiltered = str_replace($locale['thousands_sep'], '', $valueFiltered);
66
+
67
+ if (strval(intval($valueFiltered)) != $valueFiltered) {
68
+ $this->_error();
69
+ return false;
70
+ }
71
+
72
+ return true;
73
+ }
74
+
75
+ }
includes/phpQuery/phpQuery/Zend/Validate/Interface.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @category Zend
26
+ * @package Zend_Validate
27
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ interface Zend_Validate_Interface
31
+ {
32
+ /**
33
+ * Returns true if and only if $value meets the validation requirements
34
+ *
35
+ * If $value fails validation, then this method returns false, and
36
+ * getMessages() will return an array of messages that explain why the
37
+ * validation failed.
38
+ *
39
+ * @param mixed $value
40
+ * @return boolean
41
+ * @throws Zend_Valid_Exception If validation of $value is impossible
42
+ */
43
+ public function isValid($value);
44
+
45
+ /**
46
+ * Returns an array of messages that explain why the most recent isValid()
47
+ * call returned false. The array keys are validation failure message identifiers,
48
+ * and the array values are the corresponding human-readable message strings.
49
+ *
50
+ * If isValid() was never called or if the most recent isValid() call
51
+ * returned true, then this method returns an empty array.
52
+ *
53
+ * @return array
54
+ */
55
+ public function getMessages();
56
+
57
+ /**
58
+ * Returns an array of message codes that explain why a previous isValid() call
59
+ * returned false.
60
+ *
61
+ * If isValid() was never called or if the most recent isValid() call
62
+ * returned true, then this method returns an empty array.
63
+ *
64
+ * This is now the same as calling array_keys() on the return value from getMessages().
65
+ *
66
+ * @return array
67
+ * @deprecated Since 1.5.0
68
+ */
69
+ public function getErrors();
70
+
71
+ }
includes/phpQuery/phpQuery/Zend/Validate/Ip.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Ip.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Ip extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_IP_ADDRESS = 'notIpAddress';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_IP_ADDRESS => "'%value%' does not appear to be a valid IP address"
46
+ );
47
+
48
+ /**
49
+ * Defined by Zend_Validate_Interface
50
+ *
51
+ * Returns true if and only if $value is a valid IP address
52
+ *
53
+ * @param mixed $value
54
+ * @return boolean
55
+ */
56
+ public function isValid($value)
57
+ {
58
+ $valueString = (string) $value;
59
+
60
+ $this->_setValue($valueString);
61
+
62
+ if (ip2long($valueString) === false) {
63
+ $this->_error();
64
+ return false;
65
+ }
66
+
67
+ return true;
68
+ }
69
+
70
+ }
includes/phpQuery/phpQuery/Zend/Validate/LessThan.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: LessThan.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_LessThan extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_LESS = 'notLessThan';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_LESS => "'%value%' is not less than '%max%'"
46
+ );
47
+
48
+ /**
49
+ * @var array
50
+ */
51
+ protected $_messageVariables = array(
52
+ 'max' => '_max'
53
+ );
54
+
55
+ /**
56
+ * Maximum value
57
+ *
58
+ * @var mixed
59
+ */
60
+ protected $_max;
61
+
62
+ /**
63
+ * Sets validator options
64
+ *
65
+ * @param mixed $max
66
+ * @return void
67
+ */
68
+ public function __construct($max)
69
+ {
70
+ $this->setMax($max);
71
+ }
72
+
73
+ /**
74
+ * Returns the max option
75
+ *
76
+ * @return mixed
77
+ */
78
+ public function getMax()
79
+ {
80
+ return $this->_max;
81
+ }
82
+
83
+ /**
84
+ * Sets the max option
85
+ *
86
+ * @param mixed $max
87
+ * @return Zend_Validate_LessThan Provides a fluent interface
88
+ */
89
+ public function setMax($max)
90
+ {
91
+ $this->_max = $max;
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Defined by Zend_Validate_Interface
97
+ *
98
+ * Returns true if and only if $value is less than max option
99
+ *
100
+ * @param mixed $value
101
+ * @return boolean
102
+ */
103
+ public function isValid($value)
104
+ {
105
+ $this->_setValue($value);
106
+ if ($this->_max <= $value) {
107
+ $this->_error();
108
+ return false;
109
+ }
110
+ return true;
111
+ }
112
+
113
+ }
includes/phpQuery/phpQuery/Zend/Validate/NotEmpty.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: NotEmpty.php 10356 2008-07-24 15:14:56Z matthew $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const IS_EMPTY = 'isEmpty';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::IS_EMPTY => "Value is empty, but a non-empty value is required"
46
+ );
47
+
48
+ /**
49
+ * Defined by Zend_Validate_Interface
50
+ *
51
+ * Returns true if and only if $value is not an empty value.
52
+ *
53
+ * @param string $value
54
+ * @return boolean
55
+ */
56
+ public function isValid($value)
57
+ {
58
+ $this->_setValue((string) $value);
59
+
60
+ if (is_string($value)
61
+ && (('' === $value)
62
+ || preg_match('/^\s+$/s', $value))
63
+ ) {
64
+ $this->_error();
65
+ return false;
66
+ } elseif (!is_string($value) && empty($value)) {
67
+ $this->_error();
68
+ return false;
69
+ }
70
+
71
+ return true;
72
+ }
73
+
74
+ }
includes/phpQuery/phpQuery/Zend/Validate/Regex.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Regex.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_Regex extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_MATCH = 'regexNotMatch';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_MATCH => "'%value%' does not match against pattern '%pattern%'"
46
+ );
47
+
48
+ /**
49
+ * @var array
50
+ */
51
+ protected $_messageVariables = array(
52
+ 'pattern' => '_pattern'
53
+ );
54
+
55
+ /**
56
+ * Regular expression pattern
57
+ *
58
+ * @var string
59
+ */
60
+ protected $_pattern;
61
+
62
+ /**
63
+ * Sets validator options
64
+ *
65
+ * @param string $pattern
66
+ * @return void
67
+ */
68
+ public function __construct($pattern)
69
+ {
70
+ $this->setPattern($pattern);
71
+ }
72
+
73
+ /**
74
+ * Returns the pattern option
75
+ *
76
+ * @return string
77
+ */
78
+ public function getPattern()
79
+ {
80
+ return $this->_pattern;
81
+ }
82
+
83
+ /**
84
+ * Sets the pattern option
85
+ *
86
+ * @param string $pattern
87
+ * @return Zend_Validate_Regex Provides a fluent interface
88
+ */
89
+ public function setPattern($pattern)
90
+ {
91
+ $this->_pattern = (string) $pattern;
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Defined by Zend_Validate_Interface
97
+ *
98
+ * Returns true if and only if $value matches against the pattern option
99
+ *
100
+ * @param string $value
101
+ * @throws Zend_Validate_Exception if there is a fatal error in pattern matching
102
+ * @return boolean
103
+ */
104
+ public function isValid($value)
105
+ {
106
+ $valueString = (string) $value;
107
+
108
+ $this->_setValue($valueString);
109
+
110
+ $status = @preg_match($this->_pattern, $valueString);
111
+ if (false === $status) {
112
+ /**
113
+ * @see Zend_Validate_Exception
114
+ */
115
+ require_once 'Zend/Validate/Exception.php';
116
+ throw new Zend_Validate_Exception("Internal error matching pattern '$this->_pattern' against value '$valueString'");
117
+ }
118
+ if (!$status) {
119
+ $this->_error();
120
+ return false;
121
+ }
122
+ return true;
123
+ }
124
+
125
+ }
includes/phpQuery/phpQuery/Zend/Validate/StringLength.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 Zend
17
+ * @package Zend_Validate
18
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: StringLength.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see Zend_Validate_Abstract
26
+ */
27
+ require_once 'Zend/Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category Zend
32
+ * @package Zend_Validate
33
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Zend_Validate_StringLength extends Zend_Validate_Abstract
37
+ {
38
+
39
+ const TOO_SHORT = 'stringLengthTooShort';
40
+ const TOO_LONG = 'stringLengthTooLong';
41
+
42
+ /**
43
+ * @var array
44
+ */
45
+ protected $_messageTemplates = array(
46
+ self::TOO_SHORT => "'%value%' is less than %min% characters long",
47
+ self::TOO_LONG => "'%value%' is greater than %max% characters long"
48
+ );
49
+
50
+ /**
51
+ * @var array
52
+ */
53
+ protected $_messageVariables = array(
54
+ 'min' => '_min',
55
+ 'max' => '_max'
56
+ );
57
+
58
+ /**
59
+ * Minimum length
60
+ *
61
+ * @var integer
62
+ */
63
+ protected $_min;
64
+
65
+ /**
66
+ * Maximum length
67
+ *
68
+ * If null, there is no maximum length
69
+ *
70
+ * @var integer|null
71
+ */
72
+ protected $_max;
73
+
74
+ /**
75
+ * Sets validator options
76
+ *
77
+ * @param integer $min
78
+ * @param integer $max
79
+ * @return void
80
+ */
81
+ public function __construct($min = 0, $max = null)
82
+ {
83
+ $this->setMin($min);
84
+ $this->setMax($max);
85
+ }
86
+
87
+ /**
88
+ * Returns the min option
89
+ *
90
+ * @return integer
91
+ */
92
+ public function getMin()
93
+ {
94
+ return $this->_min;
95
+ }
96
+
97
+ /**
98
+ * Sets the min option
99
+ *
100
+ * @param integer $min
101
+ * @throws Zend_Validate_Exception
102
+ * @return Zend_Validate_StringLength Provides a fluent interface
103
+ */
104
+ public function setMin($min)
105
+ {
106
+ if (null !== $this->_max && $min > $this->_max) {
107
+ /**
108
+ * @see Zend_Validate_Exception
109
+ */
110
+ require_once 'Zend/Validate/Exception.php';
111
+ throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum length, but $min >"
112
+ . " $this->_max");
113
+ }
114
+ $this->_min = max(0, (integer) $min);
115
+ return $this;
116
+ }
117
+
118
+ /**
119
+ * Returns the max option
120
+ *
121
+ * @return integer|null
122
+ */
123
+ public function getMax()
124
+ {
125
+ return $this->_max;
126
+ }
127
+
128
+ /**
129
+ * Sets the max option
130
+ *
131
+ * @param integer|null $max
132
+ * @throws Zend_Validate_Exception
133
+ * @return Zend_Validate_StringLength Provides a fluent interface
134
+ */
135
+ public function setMax($max)
136
+ {
137
+ if (null === $max) {
138
+ $this->_max = null;
139
+ } else if ($max < $this->_min) {
140
+ /**
141
+ * @see Zend_Validate_Exception
142
+ */
143
+ require_once 'Zend/Validate/Exception.php';
144
+ throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum length, but "
145
+ . "$max < $this->_min");
146
+ } else {
147
+ $this->_max = (integer) $max;
148
+ }
149
+
150
+ return $this;
151
+ }
152
+
153
+ /**
154
+ * Defined by Zend_Validate_Interface
155
+ *
156
+ * Returns true if and only if the string length of $value is at least the min option and
157
+ * no greater than the max option (when the max option is not null).
158
+ *
159
+ * @param string $value
160
+ * @return boolean
161
+ */
162
+ public function isValid($value)
163
+ {
164
+ $valueString = (string) $value;
165
+ $this->_setValue($valueString);
166
+ $length = iconv_strlen($valueString);
167
+ if ($length < $this->_min) {
168
+ $this->_error(self::TOO_SHORT);
169
+ }
170
+ if (null !== $this->_max && $this->_max < $length) {
171
+ $this->_error(self::TOO_LONG);
172
+ }
173
+ if (count($this->_messages)) {
174
+ return false;
175
+ } else {
176
+ return true;
177
+ }
178
+ }
179
+
180
+ }
includes/phpQuery/phpQuery/bootstrap.example.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Example of phpQuery bootstrap file.
4
+ *
5
+ * This file is executed everytime phpQuery is included. Use it to set all
6
+ * your personal needs in the library.
7
+ *
8
+ * To activate this file, delete '.example' from filename.
9
+ */
10
+ // probably you want to use one of those functions here
11
+ //phpQuery::ajaxAllowHost();
12
+ //phpQuery::ajaxAllowURL();
13
+ //phpQuery::plugin();
14
+ ?>
includes/phpQuery/phpQuery/compat/mbstring.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // -- Multibyte Compatibility functions ---------------------------------------
3
+ // http://svn.iphonewebdev.com/lace/lib/mb_compat.php
4
+
5
+ /**
6
+ * mb_internal_encoding()
7
+ *
8
+ * Included for mbstring pseudo-compatability.
9
+ */
10
+ if (!function_exists('mb_internal_encoding'))
11
+ {
12
+ function mb_internal_encoding($enc) {return true; }
13
+ }
14
+
15
+ /**
16
+ * mb_regex_encoding()
17
+ *
18
+ * Included for mbstring pseudo-compatability.
19
+ */
20
+ if (!function_exists('mb_regex_encoding'))
21
+ {
22
+ function mb_regex_encoding($enc) {return true; }
23
+ }
24
+
25
+ /**
26
+ * mb_strlen()
27
+ *
28
+ * Included for mbstring pseudo-compatability.
29
+ */
30
+ if (!function_exists('mb_strlen'))
31
+ {
32
+ function mb_strlen($str)
33
+ {
34
+ return strlen($str);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * mb_strpos()
40
+ *
41
+ * Included for mbstring pseudo-compatability.
42
+ */
43
+ if (!function_exists('mb_strpos'))
44
+ {
45
+ function mb_strpos($haystack, $needle, $offset=0)
46
+ {
47
+ return strpos($haystack, $needle, $offset);
48
+ }
49
+ }
50
+ /**
51
+ * mb_stripos()
52
+ *
53
+ * Included for mbstring pseudo-compatability.
54
+ */
55
+ if (!function_exists('mb_stripos'))
56
+ {
57
+ function mb_stripos($haystack, $needle, $offset=0)
58
+ {
59
+ return stripos($haystack, $needle, $offset);
60
+ }
61
+ }
62
+
63
+ /**
64
+ * mb_substr()
65
+ *
66
+ * Included for mbstring pseudo-compatability.
67
+ */
68
+ if (!function_exists('mb_substr'))
69
+ {
70
+ function mb_substr($str, $start, $length=0)
71
+ {
72
+ return substr($str, $start, $length);
73
+ }
74
+ }
75
+
76
+ /**
77
+ * mb_substr_count()
78
+ *
79
+ * Included for mbstring pseudo-compatability.
80
+ */
81
+ if (!function_exists('mb_substr_count'))
82
+ {
83
+ function mb_substr_count($haystack, $needle)
84
+ {
85
+ return substr_count($haystack, $needle);
86
+ }
87
+ }
88
+
includes/phpQuery/phpQuery/phpQueryEvents.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Event handling class.
4
+ *
5
+ * @author Tobiasz Cudnik
6
+ * @package phpQuery
7
+ * @static
8
+ */
9
+ abstract class phpQueryEvents {
10
+ /**
11
+ * Trigger a type of event on every matched element.
12
+ *
13
+ * @param DOMNode|phpQueryObject|string $document
14
+ * @param unknown_type $type
15
+ * @param unknown_type $data
16
+ *
17
+ * @TODO exclusive events (with !)
18
+ * @TODO global events (test)
19
+ * @TODO support more than event in $type (space-separated)
20
+ */
21
+ public static function trigger($document, $type, $data = array(), $node = null) {
22
+ // trigger: function(type, data, elem, donative, extra) {
23
+ $documentID = phpQuery::getDocumentID($document);
24
+ $namespace = null;
25
+ if (strpos($type, '.') !== false)
26
+ list($name, $namespace) = explode('.', $type);
27
+ else
28
+ $name = $type;
29
+ if (! $node) {
30
+ if (self::issetGlobal($documentID, $type)) {
31
+ $pq = phpQuery::getDocument($documentID);
32
+ // TODO check add($pq->document)
33
+ $pq->find('*')->add($pq->document)
34
+ ->trigger($type, $data);
35
+ }
36
+ } else {
37
+ if (isset($data[0]) && $data[0] instanceof DOMEvent) {
38
+ $event = $data[0];
39
+ $event->relatedTarget = $event->target;
40
+ $event->target = $node;
41
+ $data = array_slice($data, 1);
42
+ } else {
43
+ $event = new DOMEvent(array(
44
+ 'type' => $type,
45
+ 'target' => $node,
46
+ 'timeStamp' => time(),
47
+ ));
48
+ }
49
+ $i = 0;
50
+ while($node) {
51
+ // TODO whois
52
+ phpQuery::debug("Triggering ".($i?"bubbled ":'')."event '{$type}' on "
53
+ ."node \n");//.phpQueryObject::whois($node)."\n");
54
+ $event->currentTarget = $node;
55
+ $eventNode = self::getNode($documentID, $node);
56
+ if (isset($eventNode->eventHandlers)) {
57
+ foreach($eventNode->eventHandlers as $eventType => $handlers) {
58
+ $eventNamespace = null;
59
+ if (strpos($type, '.') !== false)
60
+ list($eventName, $eventNamespace) = explode('.', $eventType);
61
+ else
62
+ $eventName = $eventType;
63
+ if ($name != $eventName)
64
+ continue;
65
+ if ($namespace && $eventNamespace && $namespace != $eventNamespace)
66
+ continue;
67
+ foreach($handlers as $handler) {
68
+ phpQuery::debug("Calling event handler\n");
69
+ $event->data = $handler['data']
70
+ ? $handler['data']
71
+ : null;
72
+ $params = array_merge(array($event), $data);
73
+ $return = phpQuery::callbackRun($handler['callback'], $params);
74
+ if ($return === false) {
75
+ $event->bubbles = false;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ // to bubble or not to bubble...
81
+ if (! $event->bubbles)
82
+ break;
83
+ $node = $node->parentNode;
84
+ $i++;
85
+ }
86
+ }
87
+ }
88
+ /**
89
+ * Binds a handler to one or more events (like click) for each matched element.
90
+ * Can also bind custom events.
91
+ *
92
+ * @param DOMNode|phpQueryObject|string $document
93
+ * @param unknown_type $type
94
+ * @param unknown_type $data Optional
95
+ * @param unknown_type $callback
96
+ *
97
+ * @TODO support '!' (exclusive) events
98
+ * @TODO support more than event in $type (space-separated)
99
+ * @TODO support binding to global events
100
+ */
101
+ public static function add($document, $node, $type, $data, $callback = null) {
102
+ phpQuery::debug("Binding '$type' event");
103
+ $documentID = phpQuery::getDocumentID($document);
104
+ // if (is_null($callback) && is_callable($data)) {
105
+ // $callback = $data;
106
+ // $data = null;
107
+ // }
108
+ $eventNode = self::getNode($documentID, $node);
109
+ if (! $eventNode)
110
+ $eventNode = self::setNode($documentID, $node);
111
+ if (!isset($eventNode->eventHandlers[$type]))
112
+ $eventNode->eventHandlers[$type] = array();
113
+ $eventNode->eventHandlers[$type][] = array(
114
+ 'callback' => $callback,
115
+ 'data' => $data,
116
+ );
117
+ }
118
+ /**
119
+ * Enter description here...
120
+ *
121
+ * @param DOMNode|phpQueryObject|string $document
122
+ * @param unknown_type $type
123
+ * @param unknown_type $callback
124
+ *
125
+ * @TODO namespace events
126
+ * @TODO support more than event in $type (space-separated)
127
+ */
128
+ public static function remove($document, $node, $type = null, $callback = null) {
129
+ $documentID = phpQuery::getDocumentID($document);
130
+ $eventNode = self::getNode($documentID, $node);
131
+ if (is_object($eventNode) && isset($eventNode->eventHandlers[$type])) {
132
+ if ($callback) {
133
+ foreach($eventNode->eventHandlers[$type] as $k => $handler)
134
+ if ($handler['callback'] == $callback)
135
+ unset($eventNode->eventHandlers[$type][$k]);
136
+ } else {
137
+ unset($eventNode->eventHandlers[$type]);
138
+ }
139
+ }
140
+ }
141
+ protected static function getNode($documentID, $node) {
142
+ foreach(phpQuery::$documents[$documentID]->eventsNodes as $eventNode) {
143
+ if ($node->isSameNode($eventNode))
144
+ return $eventNode;
145
+ }
146
+ }
147
+ protected static function setNode($documentID, $node) {
148
+ phpQuery::$documents[$documentID]->eventsNodes[] = $node;
149
+ return phpQuery::$documents[$documentID]->eventsNodes[
150
+ count(phpQuery::$documents[$documentID]->eventsNodes)-1
151
+ ];
152
+ }
153
+ protected static function issetGlobal($documentID, $type) {
154
+ return isset(phpQuery::$documents[$documentID])
155
+ ? in_array($type, phpQuery::$documents[$documentID]->eventsGlobal)
156
+ : false;
157
+ }
158
+ }
includes/phpQuery/phpQuery/phpQueryObject.php ADDED
@@ -0,0 +1,3180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class representing phpQuery objects.
4
+ *
5
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
6
+ * @package phpQuery
7
+ * @method phpQueryObject clone() clone()
8
+ * @method phpQueryObject empty() empty()
9
+ * @method phpQueryObject next() next($selector = null)
10
+ * @method phpQueryObject prev() prev($selector = null)
11
+ * @property Int $length
12
+ */
13
+ class phpQueryObject
14
+ implements Iterator, Countable, ArrayAccess {
15
+ public $documentID = null;
16
+ /**
17
+ * DOMDocument class.
18
+ *
19
+ * @var DOMDocument
20
+ */
21
+ public $document = null;
22
+ public $charset = null;
23
+ /**
24
+ *
25
+ * @var DOMDocumentWrapper
26
+ */
27
+ public $documentWrapper = null;
28
+ /**
29
+ * XPath interface.
30
+ *
31
+ * @var DOMXPath
32
+ */
33
+ public $xpath = null;
34
+ /**
35
+ * Stack of selected elements.
36
+ * @TODO refactor to ->nodes
37
+ * @var array
38
+ */
39
+ public $elements = array();
40
+ /**
41
+ * @access private
42
+ */
43
+ protected $elementsBackup = array();
44
+ /**
45
+ * @access private
46
+ */
47
+ protected $previous = null;
48
+ /**
49
+ * @access private
50
+ * @TODO deprecate
51
+ */
52
+ protected $root = array();
53
+ /**
54
+ * Indicated if doument is just a fragment (no <html> tag).
55
+ *
56
+ * Every document is realy a full document, so even documentFragments can
57
+ * be queried against <html>, but getDocument(id)->htmlOuter() will return
58
+ * only contents of <body>.
59
+ *
60
+ * @var bool
61
+ */
62
+ public $documentFragment = true;
63
+ /**
64
+ * Iterator interface helper
65
+ * @access private
66
+ */
67
+ protected $elementsInterator = array();
68
+ /**
69
+ * Iterator interface helper
70
+ * @access private
71
+ */
72
+ protected $valid = false;
73
+ /**
74
+ * Iterator interface helper
75
+ * @access private
76
+ */
77
+ protected $current = null;
78
+ /**
79
+ * Enter description here...
80
+ *
81
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
82
+ */
83
+ public function __construct($documentID) {
84
+ // if ($documentID instanceof self)
85
+ // var_dump($documentID->getDocumentID());
86
+ $id = $documentID instanceof self
87
+ ? $documentID->getDocumentID()
88
+ : $documentID;
89
+ // var_dump($id);
90
+ if (! isset(phpQuery::$documents[$id] )) {
91
+ // var_dump(phpQuery::$documents);
92
+ throw new Exception("Document with ID '{$id}' isn't loaded. Use phpQuery::newDocument(\$html) or phpQuery::newDocumentFile(\$file) first.");
93
+ }
94
+ $this->documentID = $id;
95
+ $this->documentWrapper =& phpQuery::$documents[$id];
96
+ $this->document =& $this->documentWrapper->document;
97
+ $this->xpath =& $this->documentWrapper->xpath;
98
+ $this->charset =& $this->documentWrapper->charset;
99
+ $this->documentFragment =& $this->documentWrapper->isDocumentFragment;
100
+ // TODO check $this->DOM->documentElement;
101
+ // $this->root = $this->document->documentElement;
102
+ $this->root =& $this->documentWrapper->root;
103
+ // $this->toRoot();
104
+ $this->elements = array($this->root);
105
+ }
106
+ /**
107
+ *
108
+ * @access private
109
+ * @param $attr
110
+ * @return unknown_type
111
+ */
112
+ public function __get($attr) {
113
+ switch($attr) {
114
+ // FIXME doesnt work at all ?
115
+ case 'length':
116
+ return $this->size();
117
+ break;
118
+ default:
119
+ return $this->$attr;
120
+ }
121
+ }
122
+ /**
123
+ * Saves actual object to $var by reference.
124
+ * Useful when need to break chain.
125
+ * @param phpQueryObject $var
126
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
127
+ */
128
+ public function toReference(&$var) {
129
+ return $var = $this;
130
+ }
131
+ public function documentFragment($state = null) {
132
+ if ($state) {
133
+ phpQuery::$documents[$this->getDocumentID()]['documentFragment'] = $state;
134
+ return $this;
135
+ }
136
+ return $this->documentFragment;
137
+ }
138
+ /**
139
+ * @access private
140
+ * @TODO documentWrapper
141
+ */
142
+ protected function isRoot( $node) {
143
+ // return $node instanceof DOMDOCUMENT || $node->tagName == 'html';
144
+ return $node instanceof DOMDOCUMENT
145
+ || ($node instanceof DOMELEMENT && $node->tagName == 'html')
146
+ || $this->root->isSameNode($node);
147
+ }
148
+ /**
149
+ * @access private
150
+ */
151
+ protected function stackIsRoot() {
152
+ return $this->size() == 1 && $this->isRoot($this->elements[0]);
153
+ }
154
+ /**
155
+ * Enter description here...
156
+ * NON JQUERY METHOD
157
+ *
158
+ * Watch out, it doesn't creates new instance, can be reverted with end().
159
+ *
160
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
161
+ */
162
+ public function toRoot() {
163
+ $this->elements = array($this->root);
164
+ return $this;
165
+ // return $this->newInstance(array($this->root));
166
+ }
167
+ /**
168
+ * Saves object's DocumentID to $var by reference.
169
+ * <code>
170
+ * $myDocumentId;
171
+ * phpQuery::newDocument('<div/>')
172
+ * ->getDocumentIDRef($myDocumentId)
173
+ * ->find('div')->...
174
+ * </code>
175
+ *
176
+ * @param unknown_type $domId
177
+ * @see phpQuery::newDocument
178
+ * @see phpQuery::newDocumentFile
179
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
180
+ */
181
+ public function getDocumentIDRef(&$documentID) {
182
+ $documentID = $this->getDocumentID();
183
+ return $this;
184
+ }
185
+ /**
186
+ * Returns object with stack set to document root.
187
+ *
188
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
189
+ */
190
+ public function getDocument() {
191
+ return phpQuery::getDocument($this->getDocumentID());
192
+ }
193
+ /**
194
+ *
195
+ * @return DOMDocument
196
+ */
197
+ public function getDOMDocument() {
198
+ return $this->document;
199
+ }
200
+ /**
201
+ * Get object's Document ID.
202
+ *
203
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
204
+ */
205
+ public function getDocumentID() {
206
+ return $this->documentID;
207
+ }
208
+ /**
209
+ * Unloads whole document from memory.
210
+ * CAUTION! None further operations will be possible on this document.
211
+ * All objects refering to it will be useless.
212
+ *
213
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
214
+ */
215
+ public function unloadDocument() {
216
+ phpQuery::unloadDocuments($this->getDocumentID());
217
+ }
218
+ public function isHTML() {
219
+ return $this->documentWrapper->isHTML;
220
+ }
221
+ public function isXHTML() {
222
+ return $this->documentWrapper->isXHTML;
223
+ }
224
+ public function isXML() {
225
+ return $this->documentWrapper->isXML;
226
+ }
227
+ /**
228
+ * Enter description here...
229
+ *
230
+ * @link http://docs.jquery.com/Ajax/serialize
231
+ * @return string
232
+ */
233
+ public function serialize() {
234
+ return phpQuery::param($this->serializeArray());
235
+ }
236
+ /**
237
+ * Enter description here...
238
+ *
239
+ * @link http://docs.jquery.com/Ajax/serializeArray
240
+ * @return array
241
+ */
242
+ public function serializeArray($submit = null) {
243
+ $source = $this->filter('form, input, select, textarea')
244
+ ->find('input, select, textarea')
245
+ ->andSelf()
246
+ ->not('form');
247
+ $return = array();
248
+ // $source->dumpDie();
249
+ foreach($source as $input) {
250
+ $input = phpQuery::pq($input);
251
+ if ($input->is('[disabled]'))
252
+ continue;
253
+ if (!$input->is('[name]'))
254
+ continue;
255
+ if ($input->is('[type=checkbox]') && !$input->is('[checked]'))
256
+ continue;
257
+ // jquery diff
258
+ if ($submit && $input->is('[type=submit]')) {
259
+ if ($submit instanceof DOMELEMENT && ! $input->elements[0]->isSameNode($submit))
260
+ continue;
261
+ else if (is_string($submit) && $input->attr('name') != $submit)
262
+ continue;
263
+ }
264
+ $return[] = array(
265
+ 'name' => $input->attr('name'),
266
+ 'value' => $input->val(),
267
+ );
268
+ }
269
+ return $return;
270
+ }
271
+ /**
272
+ * @access private
273
+ */
274
+ protected function debug($in) {
275
+ if (! phpQuery::$debug )
276
+ return;
277
+ print('<pre>');
278
+ print_r($in);
279
+ // file debug
280
+ // file_put_contents(dirname(__FILE__).'/phpQuery.log', print_r($in, true)."\n", FILE_APPEND);
281
+ // quite handy debug trace
282
+ // if ( is_array($in))
283
+ // print_r(array_slice(debug_backtrace(), 3));
284
+ print("</pre>\n");
285
+ }
286
+ /**
287
+ * @access private
288
+ */
289
+ protected function isRegexp($pattern) {
290
+ return in_array(
291
+ $pattern[ mb_strlen($pattern)-1 ],
292
+ array('^','*','$')
293
+ );
294
+ }
295
+ /**
296
+ * Determines if $char is really a char.
297
+ *
298
+ * @param string $char
299
+ * @return bool
300
+ * @todo rewrite me to charcode range ! ;)
301
+ * @access private
302
+ */
303
+ protected function isChar($char) {
304
+ return extension_loaded('mbstring') && phpQuery::$mbstringSupport
305
+ ? mb_eregi('\w', $char)
306
+ : preg_match('@\w@', $char);
307
+ }
308
+ /**
309
+ * @access private
310
+ */
311
+ protected function parseSelector($query) {
312
+ // clean spaces
313
+ // TODO include this inside parsing ?
314
+ $query = trim(
315
+ preg_replace('@\s+@', ' ',
316
+ preg_replace('@\s*(>|\\+|~)\s*@', '\\1', $query)
317
+ )
318
+ );
319
+ $queries = array(array());
320
+ if (! $query)
321
+ return $queries;
322
+ $return =& $queries[0];
323
+ $specialChars = array('>',' ');
324
+ // $specialCharsMapping = array('/' => '>');
325
+ $specialCharsMapping = array();
326
+ $strlen = mb_strlen($query);
327
+ $classChars = array('.', '-');
328
+ $pseudoChars = array('-');
329
+ $tagChars = array('*', '|', '-');
330
+ // split multibyte string
331
+ // http://code.google.com/p/phpquery/issues/detail?id=76
332
+ $_query = array();
333
+ for ($i=0; $i<$strlen; $i++)
334
+ $_query[] = mb_substr($query, $i, 1);
335
+ $query = $_query;
336
+ // it works, but i dont like it...
337
+ $i = 0;
338
+ while( $i < $strlen) {
339
+ $c = $query[$i];
340
+ $tmp = '';
341
+ // TAG
342
+ if ($this->isChar($c) || in_array($c, $tagChars)) {
343
+ while(isset($query[$i])
344
+ && ($this->isChar($query[$i]) || in_array($query[$i], $tagChars))) {
345
+ $tmp .= $query[$i];
346
+ $i++;
347
+ }
348
+ $return[] = $tmp;
349
+ // IDs
350
+ } else if ( $c == '#') {
351
+ $i++;
352
+ while( isset($query[$i]) && ($this->isChar($query[$i]) || $query[$i] == '-')) {
353
+ $tmp .= $query[$i];
354
+ $i++;
355
+ }
356
+ $return[] = '#'.$tmp;
357
+ // SPECIAL CHARS
358
+ } else if (in_array($c, $specialChars)) {
359
+ $return[] = $c;
360
+ $i++;
361
+ // MAPPED SPECIAL MULTICHARS
362
+ // } else if ( $c.$query[$i+1] == '//') {
363
+ // $return[] = ' ';
364
+ // $i = $i+2;
365
+ // MAPPED SPECIAL CHARS
366
+ } else if ( isset($specialCharsMapping[$c])) {
367
+ $return[] = $specialCharsMapping[$c];
368
+ $i++;
369
+ // COMMA
370
+ } else if ( $c == ',') {
371
+ $queries[] = array();
372
+ $return =& $queries[ count($queries)-1 ];
373
+ $i++;
374
+ while( isset($query[$i]) && $query[$i] == ' ')
375
+ $i++;
376
+ // CLASSES
377
+ } else if ($c == '.') {
378
+ while( isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $classChars))) {
379
+ $tmp .= $query[$i];
380
+ $i++;
381
+ }
382
+ $return[] = $tmp;
383
+ // ~ General Sibling Selector
384
+ } else if ($c == '~') {
385
+ $spaceAllowed = true;
386
+ $tmp .= $query[$i++];
387
+ while( isset($query[$i])
388
+ && ($this->isChar($query[$i])
389
+ || in_array($query[$i], $classChars)
390
+ || $query[$i] == '*'
391
+ || ($query[$i] == ' ' && $spaceAllowed)
392
+ )) {
393
+ if ($query[$i] != ' ')
394
+ $spaceAllowed = false;
395
+ $tmp .= $query[$i];
396
+ $i++;
397
+ }
398
+ $return[] = $tmp;
399
+ // + Adjacent sibling selectors
400
+ } else if ($c == '+') {
401
+ $spaceAllowed = true;
402
+ $tmp .= $query[$i++];
403
+ while( isset($query[$i])
404
+ && ($this->isChar($query[$i])
405
+ || in_array($query[$i], $classChars)
406
+ || $query[$i] == '*'
407
+ || ($spaceAllowed && $query[$i] == ' ')
408
+ )) {
409
+ if ($query[$i] != ' ')
410
+ $spaceAllowed = false;
411
+ $tmp .= $query[$i];
412
+ $i++;
413
+ }
414
+ $return[] = $tmp;
415
+ // ATTRS
416
+ } else if ($c == '[') {
417
+ $stack = 1;
418
+ $tmp .= $c;
419
+ while( isset($query[++$i])) {
420
+ $tmp .= $query[$i];
421
+ if ( $query[$i] == '[') {
422
+ $stack++;
423
+ } else if ( $query[$i] == ']') {
424
+ $stack--;
425
+ if (! $stack )
426
+ break;
427
+ }
428
+ }
429
+ $return[] = $tmp;
430
+ $i++;
431
+ // PSEUDO CLASSES
432
+ } else if ($c == ':') {
433
+ $stack = 1;
434
+ $tmp .= $query[$i++];
435
+ while( isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $pseudoChars))) {
436
+ $tmp .= $query[$i];
437
+ $i++;
438
+ }
439
+ // with arguments ?
440
+ if ( isset($query[$i]) && $query[$i] == '(') {
441
+ $tmp .= $query[$i];
442
+ $stack = 1;
443
+ while( isset($query[++$i])) {
444
+ $tmp .= $query[$i];
445
+ if ( $query[$i] == '(') {
446
+ $stack++;
447
+ } else if ( $query[$i] == ')') {
448
+ $stack--;
449
+ if (! $stack )
450
+ break;
451
+ }
452
+ }
453
+ $return[] = $tmp;
454
+ $i++;
455
+ } else {
456
+ $return[] = $tmp;
457
+ }
458
+ } else {
459
+ $i++;
460
+ }
461
+ }
462
+ foreach($queries as $k => $q) {
463
+ if (isset($q[0])) {
464
+ if (isset($q[0][0]) && $q[0][0] == ':')
465
+ array_unshift($queries[$k], '*');
466
+ if ($q[0] != '>')
467
+ array_unshift($queries[$k], ' ');
468
+ }
469
+ }
470
+ return $queries;
471
+ }
472
+ /**
473
+ * Return matched DOM nodes.
474
+ *
475
+ * @param int $index
476
+ * @return array|DOMElement Single DOMElement or array of DOMElement.
477
+ */
478
+ public function get($index = null, $callback1 = null, $callback2 = null, $callback3 = null) {
479
+ $return = isset($index)
480
+ ? (isset($this->elements[$index]) ? $this->elements[$index] : null)
481
+ : $this->elements;
482
+ // pass thou callbacks
483
+ $args = func_get_args();
484
+ $args = array_slice($args, 1);
485
+ foreach($args as $callback) {
486
+ if (is_array($return))
487
+ foreach($return as $k => $v)
488
+ $return[$k] = phpQuery::callbackRun($callback, array($v));
489
+ else
490
+ $return = phpQuery::callbackRun($callback, array($return));
491
+ }
492
+ return $return;
493
+ }
494
+ /**
495
+ * Return matched DOM nodes.
496
+ * jQuery difference.
497
+ *
498
+ * @param int $index
499
+ * @return array|string Returns string if $index != null
500
+ * @todo implement callbacks
501
+ * @todo return only arrays ?
502
+ * @todo maybe other name...
503
+ */
504
+ public function getString($index = null, $callback1 = null, $callback2 = null, $callback3 = null) {
505
+ if ($index)
506
+ $return = $this->eq($index)->text();
507
+ else {
508
+ $return = array();
509
+ for($i = 0; $i < $this->size(); $i++) {
510
+ $return[] = $this->eq($i)->text();
511
+ }
512
+ }
513
+ // pass thou callbacks
514
+ $args = func_get_args();
515
+ $args = array_slice($args, 1);
516
+ foreach($args as $callback) {
517
+ $return = phpQuery::callbackRun($callback, array($return));
518
+ }
519
+ return $return;
520
+ }
521
+ /**
522
+ * Return matched DOM nodes.
523
+ * jQuery difference.
524
+ *
525
+ * @param int $index
526
+ * @return array|string Returns string if $index != null
527
+ * @todo implement callbacks
528
+ * @todo return only arrays ?
529
+ * @todo maybe other name...
530
+ */
531
+ public function getStrings($index = null, $callback1 = null, $callback2 = null, $callback3 = null) {
532
+ if ($index)
533
+ $return = $this->eq($index)->text();
534
+ else {
535
+ $return = array();
536
+ for($i = 0; $i < $this->size(); $i++) {
537
+ $return[] = $this->eq($i)->text();
538
+ }
539
+ // pass thou callbacks
540
+ $args = func_get_args();
541
+ $args = array_slice($args, 1);
542
+ }
543
+ foreach($args as $callback) {
544
+ if (is_array($return))
545
+ foreach($return as $k => $v)
546
+ $return[$k] = phpQuery::callbackRun($callback, array($v));
547
+ else
548
+ $return = phpQuery::callbackRun($callback, array($return));
549
+ }
550
+ return $return;
551
+ }
552
+ /**
553
+ * Returns new instance of actual class.
554
+ *
555
+ * @param array $newStack Optional. Will replace old stack with new and move old one to history.c
556
+ */
557
+ public function newInstance($newStack = null) {
558
+ $class = get_class($this);
559
+ // support inheritance by passing old object to overloaded constructor
560
+ $new = $class != 'phpQuery'
561
+ ? new $class($this, $this->getDocumentID())
562
+ : new phpQueryObject($this->getDocumentID());
563
+ $new->previous = $this;
564
+ if (is_null($newStack)) {
565
+ $new->elements = $this->elements;
566
+ if ($this->elementsBackup)
567
+ $this->elements = $this->elementsBackup;
568
+ } else if (is_string($newStack)) {
569
+ $new->elements = phpQuery::pq($newStack, $this->getDocumentID())->stack();
570
+ } else {
571
+ $new->elements = $newStack;
572
+ }
573
+ return $new;
574
+ }
575
+ /**
576
+ * Enter description here...
577
+ *
578
+ * In the future, when PHP will support XLS 2.0, then we would do that this way:
579
+ * contains(tokenize(@class, '\s'), "something")
580
+ * @param unknown_type $class
581
+ * @param unknown_type $node
582
+ * @return boolean
583
+ * @access private
584
+ */
585
+ protected function matchClasses($class, $node) {
586
+ // multi-class
587
+ if ( mb_strpos($class, '.', 1)) {
588
+ $classes = explode('.', substr($class, 1));
589
+ $classesCount = count( $classes );
590
+ $nodeClasses = explode(' ', $node->getAttribute('class') );
591
+ $nodeClassesCount = count( $nodeClasses );
592
+ if ( $classesCount > $nodeClassesCount )
593
+ return false;
594
+ $diff = count(
595
+ array_diff(
596
+ $classes,
597
+ $nodeClasses
598
+ )
599
+ );
600
+ if (! $diff )
601
+ return true;
602
+ // single-class
603
+ } else {
604
+ return in_array(
605
+ // strip leading dot from class name
606
+ substr($class, 1),
607
+ // get classes for element as array
608
+ explode(' ', $node->getAttribute('class') )
609
+ );
610
+ }
611
+ }
612
+ /**
613
+ * @access private
614
+ */
615
+ protected function runQuery($XQuery, $selector = null, $compare = null) {
616
+ if ($compare && ! method_exists($this, $compare))
617
+ return false;
618
+ $stack = array();
619
+ if (! $this->elements)
620
+ $this->debug('Stack empty, skipping...');
621
+ // var_dump($this->elements[0]->nodeType);
622
+ // element, document
623
+ foreach($this->stack(array(1, 9, 13)) as $k => $stackNode) {
624
+ $detachAfter = false;
625
+ // to work on detached nodes we need temporary place them somewhere
626
+ // thats because context xpath queries sucks ;]
627
+ $testNode = $stackNode;
628
+ while ($testNode) {
629
+ if (! $testNode->parentNode && ! $this->isRoot($testNode)) {
630
+ $this->root->appendChild($testNode);
631
+ $detachAfter = $testNode;
632
+ break;
633
+ }
634
+ $testNode = isset($testNode->parentNode)
635
+ ? $testNode->parentNode
636
+ : null;
637
+ }
638
+ // XXX tmp ?
639
+ $xpath = $this->documentWrapper->isXHTML
640
+ ? $this->getNodeXpath($stackNode, 'html')
641
+ : $this->getNodeXpath($stackNode);
642
+ // FIXME pseudoclasses-only query, support XML
643
+ $query = $XQuery == '//' && $xpath == '/html[1]'
644
+ ? '//*'
645
+ : $xpath.$XQuery;
646
+ $this->debug("XPATH: {$query}");
647
+ // run query, get elements
648
+ $nodes = $this->xpath->query($query);
649
+ $this->debug("QUERY FETCHED");
650
+ if (! $nodes->length )
651
+ $this->debug('Nothing found');
652
+ $debug = array();
653
+ foreach($nodes as $node) {
654
+ $matched = false;
655
+ if ( $compare) {
656
+ phpQuery::$debug ?
657
+ $this->debug("Found: ".$this->whois( $node ).", comparing with {$compare}()")
658
+ : null;
659
+ $phpQueryDebug = phpQuery::$debug;
660
+ phpQuery::$debug = false;
661
+ // TODO ??? use phpQuery::callbackRun()
662
+ if (call_user_func_array(array($this, $compare), array($selector, $node)))
663
+ $matched = true;
664
+ phpQuery::$debug = $phpQueryDebug;
665
+ } else {
666
+ $matched = true;
667
+ }
668
+ if ( $matched) {
669
+ if (phpQuery::$debug)
670
+ $debug[] = $this->whois( $node );
671
+ $stack[] = $node;
672
+ }
673
+ }
674
+ if (phpQuery::$debug) {
675
+ $this->debug("Matched ".count($debug).": ".implode(', ', $debug));
676
+ }
677
+ if ($detachAfter)
678
+ $this->root->removeChild($detachAfter);
679
+ }
680
+ $this->elements = $stack;
681
+ }
682
+ /**
683
+ * Enter description here...
684
+ *
685
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
686
+ */
687
+ public function find($selectors, $context = null, $noHistory = false) {
688
+ if (!$noHistory)
689
+ // backup last stack /for end()/
690
+ $this->elementsBackup = $this->elements;
691
+ // allow to define context
692
+ // TODO combine code below with phpQuery::pq() context guessing code
693
+ // as generic function
694
+ if ($context) {
695
+ if (! is_array($context) && $context instanceof DOMELEMENT)
696
+ $this->elements = array($context);
697
+ else if (is_array($context)) {
698
+ $this->elements = array();
699
+ foreach ($context as $c)
700
+ if ($c instanceof DOMELEMENT)
701
+ $this->elements[] = $c;
702
+ } else if ( $context instanceof self )
703
+ $this->elements = $context->elements;
704
+ }
705
+ $queries = $this->parseSelector($selectors);
706
+ $this->debug(array('FIND', $selectors, $queries));
707
+ $XQuery = '';
708
+ // remember stack state because of multi-queries
709
+ $oldStack = $this->elements;
710
+ // here we will be keeping found elements
711
+ $stack = array();
712
+ foreach($queries as $selector) {
713
+ $this->elements = $oldStack;
714
+ $delimiterBefore = false;
715
+ foreach($selector as $s) {
716
+ // TAG
717
+ $isTag = extension_loaded('mbstring') && phpQuery::$mbstringSupport
718
+ ? mb_ereg_match('^[\w|\||-]+$', $s) || $s == '*'
719
+ : preg_match('@^[\w|\||-]+$@', $s) || $s == '*';
720
+ if ($isTag) {
721
+ if ($this->isXML()) {
722
+ // namespace support
723
+ if (mb_strpos($s, '|') !== false) {
724
+ $ns = $tag = null;
725
+ list($ns, $tag) = explode('|', $s);
726
+ $XQuery .= "$ns:$tag";
727
+ } else if ($s == '*') {
728
+ $XQuery .= "*";
729
+ } else {
730
+ $XQuery .= "*[local-name()='$s']";
731
+ }
732
+ } else {
733
+ $XQuery .= $s;
734
+ }
735
+ // ID
736
+ } else if ($s[0] == '#') {
737
+ if ($delimiterBefore)
738
+ $XQuery .= '*';
739
+ $XQuery .= "[@id='".substr($s, 1)."']";
740
+ // ATTRIBUTES
741
+ } else if ($s[0] == '[') {
742
+ if ($delimiterBefore)
743
+ $XQuery .= '*';
744
+ // strip side brackets
745
+ $attr = trim($s, '][');
746
+ $execute = false;
747
+ // attr with specifed value
748
+ if (mb_strpos($s, '=')) {
749
+ $value = null;
750
+ list($attr, $value) = explode('=', $attr);
751
+ $value = trim($value, "'\"");
752
+ if ($this->isRegexp($attr)) {
753
+ // cut regexp character
754
+ $attr = substr($attr, 0, -1);
755
+ $execute = true;
756
+ $XQuery .= "[@{$attr}]";
757
+ } else {
758
+ $XQuery .= "[@{$attr}='{$value}']";
759
+ }
760
+ // attr without specified value
761
+ } else {
762
+ $XQuery .= "[@{$attr}]";
763
+ }
764
+ if ($execute) {
765
+ $this->runQuery($XQuery, $s, 'is');
766
+ $XQuery = '';
767
+ if (! $this->length())
768
+ break;
769
+ }
770
+ // CLASSES
771
+ } else if ($s[0] == '.') {
772
+ // TODO use return $this->find("./self::*[contains(concat(\" \",@class,\" \"), \" $class \")]");
773
+ // thx wizDom ;)
774
+ if ($delimiterBefore)
775
+ $XQuery .= '*';
776
+ $XQuery .= '[@class]';
777
+ $this->runQuery($XQuery, $s, 'matchClasses');
778
+ $XQuery = '';
779
+ if (! $this->length() )
780
+ break;
781
+ // ~ General Sibling Selector
782
+ } else if ($s[0] == '~') {
783
+ $this->runQuery($XQuery);
784
+ $XQuery = '';
785
+ $this->elements = $this
786
+ ->siblings(
787
+ substr($s, 1)
788
+ )->elements;
789
+ if (! $this->length() )
790
+ break;
791
+ // + Adjacent sibling selectors
792
+ } else if ($s[0] == '+') {
793
+ // TODO /following-sibling::
794
+ $this->runQuery($XQuery);
795
+ $XQuery = '';
796
+ $subSelector = substr($s, 1);
797
+ $subElements = $this->elements;
798
+ $this->elements = array();
799
+ foreach($subElements as $node) {
800
+ // search first DOMElement sibling
801
+ $test = $node->nextSibling;
802
+ while($test && ! ($test instanceof DOMELEMENT))
803
+ $test = $test->nextSibling;
804
+ if ($test && $this->is($subSelector, $test))
805
+ $this->elements[] = $test;
806
+ }
807
+ if (! $this->length() )
808
+ break;
809
+ // PSEUDO CLASSES
810
+ } else if ($s[0] == ':') {
811
+ // TODO optimization for :first :last
812
+ if ($XQuery) {
813
+ $this->runQuery($XQuery);
814
+ $XQuery = '';
815
+ }
816
+ if (! $this->length())
817
+ break;
818
+ $this->pseudoClasses($s);
819
+ if (! $this->length())
820
+ break;
821
+ // DIRECT DESCENDANDS
822
+ } else if ($s == '>') {
823
+ $XQuery .= '/';
824
+ $delimiterBefore = 2;
825
+ // ALL DESCENDANDS
826
+ } else if ($s == ' ') {
827
+ $XQuery .= '//';
828
+ $delimiterBefore = 2;
829
+ // ERRORS
830
+ } else {
831
+ phpQuery::debug("Unrecognized token '$s'");
832
+ }
833
+ $delimiterBefore = $delimiterBefore === 2;
834
+ }
835
+ // run query if any
836
+ if ($XQuery && $XQuery != '//') {
837
+ $this->runQuery($XQuery);
838
+ $XQuery = '';
839
+ }
840
+ foreach($this->elements as $node)
841
+ if (! $this->elementsContainsNode($node, $stack))
842
+ $stack[] = $node;
843
+ }
844
+ $this->elements = $stack;
845
+ return $this->newInstance();
846
+ }
847
+ /**
848
+ * @todo create API for classes with pseudoselectors
849
+ * @access private
850
+ */
851
+ protected function pseudoClasses($class) {
852
+ // TODO clean args parsing ?
853
+ $class = ltrim($class, ':');
854
+ $haveArgs = mb_strpos($class, '(');
855
+ if ($haveArgs !== false) {
856
+ $args = substr($class, $haveArgs+1, -1);
857
+ $class = substr($class, 0, $haveArgs);
858
+ }
859
+ switch($class) {
860
+ case 'even':
861
+ case 'odd':
862
+ $stack = array();
863
+ foreach($this->elements as $i => $node) {
864
+ if ($class == 'even' && ($i%2) == 0)
865
+ $stack[] = $node;
866
+ else if ( $class == 'odd' && $i % 2 )
867
+ $stack[] = $node;
868
+ }
869
+ $this->elements = $stack;
870
+ break;
871
+ case 'eq':
872
+ $k = intval($args);
873
+ $this->elements = isset( $this->elements[$k] )
874
+ ? array( $this->elements[$k] )
875
+ : array();
876
+ break;
877
+ case 'gt':
878
+ $this->elements = array_slice($this->elements, $args+1);
879
+ break;
880
+ case 'lt':
881
+ $this->elements = array_slice($this->elements, 0, $args+1);
882
+ break;
883
+ case 'first':
884
+ if (isset($this->elements[0]))
885
+ $this->elements = array($this->elements[0]);
886
+ break;
887
+ case 'last':
888
+ if ($this->elements)
889
+ $this->elements = array($this->elements[count($this->elements)-1]);
890
+ break;
891
+ /*case 'parent':
892
+ $stack = array();
893
+ foreach($this->elements as $node) {
894
+ if ( $node->childNodes->length )
895
+ $stack[] = $node;
896
+ }
897
+ $this->elements = $stack;
898
+ break;*/
899
+ case 'contains':
900
+ $text = trim($args, "\"'");
901
+ $stack = array();
902
+ foreach($this->elements as $node) {
903
+ if (mb_stripos($node->textContent, $text) === false)
904
+ continue;
905
+ $stack[] = $node;
906
+ }
907
+ $this->elements = $stack;
908
+ break;
909
+ case 'not':
910
+ $selector = self::unQuote($args);
911
+ $this->elements = $this->not($selector)->stack();
912
+ break;
913
+ case 'slice':
914
+ // TODO jQuery difference ?
915
+ $args = explode(',',
916
+ str_replace(', ', ',', trim($args, "\"'"))
917
+ );
918
+ $start = $args[0];
919
+ $end = isset($args[1])
920
+ ? $args[1]
921
+ : null;
922
+ if ($end > 0)
923
+ $end = $end-$start;
924
+ $this->elements = array_slice($this->elements, $start, $end);
925
+ break;
926
+ case 'has':
927
+ $selector = trim($args, "\"'");
928
+ $stack = array();
929
+ foreach($this->stack(1) as $el) {
930
+ if ($this->find($selector, $el, true)->length)
931
+ $stack[] = $el;
932
+ }
933
+ $this->elements = $stack;
934
+ break;
935
+ case 'submit':
936
+ case 'reset':
937
+ $this->elements = phpQuery::merge(
938
+ $this->map(array($this, 'is'),
939
+ "input[type=$class]", new CallbackParam()
940
+ ),
941
+ $this->map(array($this, 'is'),
942
+ "button[type=$class]", new CallbackParam()
943
+ )
944
+ );
945
+ break;
946
+ // $stack = array();
947
+ // foreach($this->elements as $node)
948
+ // if ($node->is('input[type=submit]') || $node->is('button[type=submit]'))
949
+ // $stack[] = $el;
950
+ // $this->elements = $stack;
951
+ case 'input':
952
+ $this->elements = $this->map(
953
+ array($this, 'is'),
954
+ 'input', new CallbackParam()
955
+ )->elements;
956
+ break;
957
+ case 'password':
958
+ case 'checkbox':
959
+ case 'radio':
960
+ case 'hidden':
961
+ case 'image':
962
+ case 'file':
963
+ $this->elements = $this->map(
964
+ array($this, 'is'),
965
+ "input[type=$class]", new CallbackParam()
966
+ )->elements;
967
+ break;
968
+ case 'parent':
969
+ $this->elements = $this->map(
970
+ create_function('$node', '
971
+ return $node instanceof DOMELEMENT && $node->childNodes->length
972
+ ? $node : null;')
973
+ )->elements;
974
+ break;
975
+ case 'empty':
976
+ $this->elements = $this->map(
977
+ create_function('$node', '
978
+ return $node instanceof DOMELEMENT && $node->childNodes->length
979
+ ? null : $node;')
980
+ )->elements;
981
+ break;
982
+ case 'disabled':
983
+ case 'selected':
984
+ case 'checked':
985
+ $this->elements = $this->map(
986
+ array($this, 'is'),
987
+ "[$class]", new CallbackParam()
988
+ )->elements;
989
+ break;
990
+ case 'enabled':
991
+ $this->elements = $this->map(
992
+ create_function('$node', '
993
+ return pq($node)->not(":disabled") ? $node : null;')
994
+ )->elements;
995
+ break;
996
+ case 'header':
997
+ $this->elements = $this->map(
998
+ create_function('$node',
999
+ '$isHeader = isset($node->tagName) && in_array($node->tagName, array(
1000
+ "h1", "h2", "h3", "h4", "h5", "h6", "h7"
1001
+ ));
1002
+ return $isHeader
1003
+ ? $node
1004
+ : null;')
1005
+ )->elements;
1006
+ // $this->elements = $this->map(
1007
+ // create_function('$node', '$node = pq($node);
1008
+ // return $node->is("h1")
1009
+ // || $node->is("h2")
1010
+ // || $node->is("h3")
1011
+ // || $node->is("h4")
1012
+ // || $node->is("h5")
1013
+ // || $node->is("h6")
1014
+ // || $node->is("h7")
1015
+ // ? $node
1016
+ // : null;')
1017
+ // )->elements;
1018
+ break;
1019
+ case 'only-child':
1020
+ $this->elements = $this->map(
1021
+ create_function('$node',
1022
+ 'return pq($node)->siblings()->size() == 0 ? $node : null;')
1023
+ )->elements;
1024
+ break;
1025
+ case 'first-child':
1026
+ $this->elements = $this->map(
1027
+ create_function('$node', 'return pq($node)->prevAll()->size() == 0 ? $node : null;')
1028
+ )->elements;
1029
+ break;
1030
+ case 'last-child':
1031
+ $this->elements = $this->map(
1032
+ create_function('$node', 'return pq($node)->nextAll()->size() == 0 ? $node : null;')
1033
+ )->elements;
1034
+ break;
1035
+ case 'nth-child':
1036
+ $param = trim($args, "\"'");
1037
+ if (! $param)
1038
+ break;
1039
+ // nth-child(n+b) to nth-child(1n+b)
1040
+ if ($param{0} == 'n')
1041
+ $param = '1'.$param;
1042
+ // :nth-child(index/even/odd/equation)
1043
+ if ($param == 'even' || $param == 'odd')
1044
+ $mapped = $this->map(
1045
+ create_function('$node, $param',
1046
+ '$index = pq($node)->prevAll()->size()+1;
1047
+ if ($param == "even" && ($index%2) == 0)
1048
+ return $node;
1049
+ else if ($param == "odd" && $index%2 == 1)
1050
+ return $node;
1051
+ else
1052
+ return null;'),
1053
+ new CallbackParam(), $param
1054
+ );
1055
+ else if (mb_strlen($param) > 1 && $param{1} == 'n')
1056
+ // an+b
1057
+ $mapped = $this->map(
1058
+ create_function('$node, $param',
1059
+ '$prevs = pq($node)->prevAll()->size();
1060
+ $index = 1+$prevs;
1061
+ $b = mb_strlen($param) > 3
1062
+ ? $param{3}
1063
+ : 0;
1064
+ $a = $param{0};
1065
+ if ($b && $param{2} == "-")
1066
+ $b = -$b;
1067
+ if ($a > 0) {
1068
+ return ($index-$b)%$a == 0
1069
+ ? $node
1070
+ : null;
1071
+ phpQuery::debug($a."*".floor($index/$a)."+$b-1 == ".($a*floor($index/$a)+$b-1)." ?= $prevs");
1072
+ return $a*floor($index/$a)+$b-1 == $prevs
1073
+ ? $node
1074
+ : null;
1075
+ } else if ($a == 0)
1076
+ return $index == $b
1077
+ ? $node
1078
+ : null;
1079
+ else
1080
+ // negative value
1081
+ return $index <= $b
1082
+ ? $node
1083
+ : null;
1084
+ // if (! $b)
1085
+ // return $index%$a == 0
1086
+ // ? $node
1087
+ // : null;
1088
+ // else
1089
+ // return ($index-$b)%$a == 0
1090
+ // ? $node
1091
+ // : null;
1092
+ '),
1093
+ new CallbackParam(), $param
1094
+ );
1095
+ else
1096
+ // index
1097
+ $mapped = $this->map(
1098
+ create_function('$node, $index',
1099
+ '$prevs = pq($node)->prevAll()->size();
1100
+ if ($prevs && $prevs == $index-1)
1101
+ return $node;
1102
+ else if (! $prevs && $index == 1)
1103
+ return $node;
1104
+ else
1105
+ return null;'),
1106
+ new CallbackParam(), $param
1107
+ );
1108
+ $this->elements = $mapped->elements;
1109
+ break;
1110
+ default:
1111
+ $this->debug("Unknown pseudoclass '{$class}', skipping...");
1112
+ }
1113
+ }
1114
+ /**
1115
+ * @access private
1116
+ */
1117
+ protected function __pseudoClassParam($paramsString) {
1118
+ // TODO;
1119
+ }
1120
+ /**
1121
+ * Enter description here...
1122
+ *
1123
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1124
+ */
1125
+ public function is($selector, $nodes = null) {
1126
+ phpQuery::debug(array("Is:", $selector));
1127
+ if (! $selector)
1128
+ return false;
1129
+ $oldStack = $this->elements;
1130
+ $returnArray = false;
1131
+ if ($nodes && is_array($nodes)) {
1132
+ $this->elements = $nodes;
1133
+ } else if ($nodes)
1134
+ $this->elements = array($nodes);
1135
+ $this->filter($selector, true);
1136
+ $stack = $this->elements;
1137
+ $this->elements = $oldStack;
1138
+ if ($nodes)
1139
+ return $stack ? $stack : null;
1140
+ return (bool)count($stack);
1141
+ }
1142
+ /**
1143
+ * Enter description here...
1144
+ * jQuery difference.
1145
+ *
1146
+ * Callback:
1147
+ * - $index int
1148
+ * - $node DOMNode
1149
+ *
1150
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1151
+ * @link http://docs.jquery.com/Traversing/filter
1152
+ */
1153
+ public function filterCallback($callback, $_skipHistory = false) {
1154
+ if (! $_skipHistory) {
1155
+ $this->elementsBackup = $this->elements;
1156
+ $this->debug("Filtering by callback");
1157
+ }
1158
+ $newStack = array();
1159
+ foreach($this->elements as $index => $node) {
1160
+ $result = phpQuery::callbackRun($callback, array($index, $node));
1161
+ if (is_null($result) || (! is_null($result) && $result))
1162
+ $newStack[] = $node;
1163
+ }
1164
+ $this->elements = $newStack;
1165
+ return $_skipHistory
1166
+ ? $this
1167
+ : $this->newInstance();
1168
+ }
1169
+ /**
1170
+ * Enter description here...
1171
+ *
1172
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1173
+ * @link http://docs.jquery.com/Traversing/filter
1174
+ */
1175
+ public function filter($selectors, $_skipHistory = false) {
1176
+ if ($selectors instanceof Callback OR $selectors instanceof Closure)
1177
+ return $this->filterCallback($selectors, $_skipHistory);
1178
+ if (! $_skipHistory)
1179
+ $this->elementsBackup = $this->elements;
1180
+ $notSimpleSelector = array(' ', '>', '~', '+', '/');
1181
+ if (! is_array($selectors))
1182
+ $selectors = $this->parseSelector($selectors);
1183
+ if (! $_skipHistory)
1184
+ $this->debug(array("Filtering:", $selectors));
1185
+ $finalStack = array();
1186
+ foreach($selectors as $selector) {
1187
+ $stack = array();
1188
+ if (! $selector)
1189
+ break;
1190
+ // avoid first space or /
1191
+ if (in_array($selector[0], $notSimpleSelector))
1192
+ $selector = array_slice($selector, 1);
1193
+ // PER NODE selector chunks
1194
+ foreach($this->stack() as $node) {
1195
+ $break = false;
1196
+ foreach($selector as $s) {
1197
+ if (!($node instanceof DOMELEMENT)) {
1198
+ // all besides DOMElement
1199
+ if ( $s[0] == '[') {
1200
+ $attr = trim($s, '[]');
1201
+ if ( mb_strpos($attr, '=')) {
1202
+ list( $attr, $val ) = explode('=', $attr);
1203
+ if ($attr == 'nodeType' && $node->nodeType != $val)
1204
+ $break = true;
1205
+ }
1206
+ } else
1207
+ $break = true;
1208
+ } else {
1209
+ // DOMElement only
1210
+ // ID
1211
+ if ( $s[0] == '#') {
1212
+ if ( $node->getAttribute('id') != substr($s, 1) )
1213
+ $break = true;
1214
+ // CLASSES
1215
+ } else if ( $s[0] == '.') {
1216
+ if (! $this->matchClasses( $s, $node ) )
1217
+ $break = true;
1218
+ // ATTRS
1219
+ } else if ( $s[0] == '[') {
1220
+ // strip side brackets
1221
+ $attr = trim($s, '[]');
1222
+ if (mb_strpos($attr, '=')) {
1223
+ list($attr, $val) = explode('=', $attr);
1224
+ $val = self::unQuote($val);
1225
+ if ($attr == 'nodeType') {
1226
+ if ($val != $node->nodeType)
1227
+ $break = true;
1228
+ } else if ($this->isRegexp($attr)) {
1229
+ $val = extension_loaded('mbstring') && phpQuery::$mbstringSupport
1230
+ ? quotemeta(trim($val, '"\''))
1231
+ : preg_quote(trim($val, '"\''), '@');
1232
+ // switch last character
1233
+ switch( substr($attr, -1)) {
1234
+ // quotemeta used insted of preg_quote
1235
+ // http://code.google.com/p/phpquery/issues/detail?id=76
1236
+ case '^':
1237
+ $pattern = '^'.$val;
1238
+ break;
1239
+ case '*':
1240
+ $pattern = '.*'.$val.'.*';
1241
+ break;
1242
+ case '$':
1243
+ $pattern = '.*'.$val.'$';
1244
+ break;
1245
+ }
1246
+ // cut last character
1247
+ $attr = substr($attr, 0, -1);
1248
+ $isMatch = extension_loaded('mbstring') && phpQuery::$mbstringSupport
1249
+ ? mb_ereg_match($pattern, $node->getAttribute($attr))
1250
+ : preg_match("@{$pattern}@", $node->getAttribute($attr));
1251
+ if (! $isMatch)
1252
+ $break = true;
1253
+ } else if ($node->getAttribute($attr) != $val)
1254
+ $break = true;
1255
+ } else if (! $node->hasAttribute($attr))
1256
+ $break = true;
1257
+ // PSEUDO CLASSES
1258
+ } else if ( $s[0] == ':') {
1259
+ // skip
1260
+ // TAG
1261
+ } else if (trim($s)) {
1262
+ if ($s != '*') {
1263
+ // TODO namespaces
1264
+ if (isset($node->tagName)) {
1265
+ if ($node->tagName != $s)
1266
+ $break = true;
1267
+ } else if ($s == 'html' && ! $this->isRoot($node))
1268
+ $break = true;
1269
+ }
1270
+ // AVOID NON-SIMPLE SELECTORS
1271
+ } else if (in_array($s, $notSimpleSelector)) {
1272
+ $break = true;
1273
+ $this->debug(array('Skipping non simple selector', $selector));
1274
+ }
1275
+ }
1276
+ if ($break)
1277
+ break;
1278
+ }
1279
+ // if element passed all chunks of selector - add it to new stack
1280
+ if (! $break )
1281
+ $stack[] = $node;
1282
+ }
1283
+ $tmpStack = $this->elements;
1284
+ $this->elements = $stack;
1285
+ // PER ALL NODES selector chunks
1286
+ foreach($selector as $s)
1287
+ // PSEUDO CLASSES
1288
+ if ($s[0] == ':')
1289
+ $this->pseudoClasses($s);
1290
+ foreach($this->elements as $node)
1291
+ // XXX it should be merged without duplicates
1292
+ // but jQuery doesnt do that
1293
+ $finalStack[] = $node;
1294
+ $this->elements = $tmpStack;
1295
+ }
1296
+ $this->elements = $finalStack;
1297
+ if ($_skipHistory) {
1298
+ return $this;
1299
+ } else {
1300
+ $this->debug("Stack length after filter(): ".count($finalStack));
1301
+ return $this->newInstance();
1302
+ }
1303
+ }
1304
+ /**
1305
+ *
1306
+ * @param $value
1307
+ * @return unknown_type
1308
+ * @TODO implement in all methods using passed parameters
1309
+ */
1310
+ protected static function unQuote($value) {
1311
+ return $value[0] == '\'' || $value[0] == '"'
1312
+ ? substr($value, 1, -1)
1313
+ : $value;
1314
+ }
1315
+ /**
1316
+ * Enter description here...
1317
+ *
1318
+ * @link http://docs.jquery.com/Ajax/load
1319
+ * @return phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1320
+ * @todo Support $selector
1321
+ */
1322
+ public function load($url, $data = null, $callback = null) {
1323
+ if ($data && ! is_array($data)) {
1324
+ $callback = $data;
1325
+ $data = null;
1326
+ }
1327
+ if (mb_strpos($url, ' ') !== false) {
1328
+ $matches = null;
1329
+ if (extension_loaded('mbstring') && phpQuery::$mbstringSupport)
1330
+ mb_ereg('^([^ ]+) (.*)$', $url, $matches);
1331
+ else
1332
+ preg_match('^([^ ]+) (.*)$', $url, $matches);
1333
+ $url = $matches[1];
1334
+ $selector = $matches[2];
1335
+ // FIXME this sucks, pass as callback param
1336
+ $this->_loadSelector = $selector;
1337
+ }
1338
+ $ajax = array(
1339
+ 'url' => $url,
1340
+ 'type' => $data ? 'POST' : 'GET',
1341
+ 'data' => $data,
1342
+ 'complete' => $callback,
1343
+ 'success' => array($this, '__loadSuccess')
1344
+ );
1345
+ phpQuery::ajax($ajax);
1346
+ return $this;
1347
+ }
1348
+ /**
1349
+ * @access private
1350
+ * @param $html
1351
+ * @return unknown_type
1352
+ */
1353
+ public function __loadSuccess($html) {
1354
+ if ($this->_loadSelector) {
1355
+ $html = phpQuery::newDocument($html)->find($this->_loadSelector);
1356
+ unset($this->_loadSelector);
1357
+ }
1358
+ foreach($this->stack(1) as $node) {
1359
+ phpQuery::pq($node, $this->getDocumentID())
1360
+ ->markup($html);
1361
+ }
1362
+ }
1363
+ /**
1364
+ * Enter description here...
1365
+ *
1366
+ * @return phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1367
+ * @todo
1368
+ */
1369
+ public function css() {
1370
+ // TODO
1371
+ return $this;
1372
+ }
1373
+ /**
1374
+ * @todo
1375
+ *
1376
+ */
1377
+ public function show(){
1378
+ // TODO
1379
+ return $this;
1380
+ }
1381
+ /**
1382
+ * @todo
1383
+ *
1384
+ */
1385
+ public function hide(){
1386
+ // TODO
1387
+ return $this;
1388
+ }
1389
+ /**
1390
+ * Trigger a type of event on every matched element.
1391
+ *
1392
+ * @param unknown_type $type
1393
+ * @param unknown_type $data
1394
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1395
+ * @TODO support more than event in $type (space-separated)
1396
+ */
1397
+ public function trigger($type, $data = array()) {
1398
+ foreach($this->elements as $node)
1399
+ phpQueryEvents::trigger($this->getDocumentID(), $type, $data, $node);
1400
+ return $this;
1401
+ }
1402
+ /**
1403
+ * This particular method triggers all bound event handlers on an element (for a specific event type) WITHOUT executing the browsers default actions.
1404
+ *
1405
+ * @param unknown_type $type
1406
+ * @param unknown_type $data
1407
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1408
+ * @TODO
1409
+ */
1410
+ public function triggerHandler($type, $data = array()) {
1411
+ // TODO;
1412
+ }
1413
+ /**
1414
+ * Binds a handler to one or more events (like click) for each matched element.
1415
+ * Can also bind custom events.
1416
+ *
1417
+ * @param unknown_type $type
1418
+ * @param unknown_type $data Optional
1419
+ * @param unknown_type $callback
1420
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1421
+ * @TODO support '!' (exclusive) events
1422
+ * @TODO support more than event in $type (space-separated)
1423
+ */
1424
+ public function bind($type, $data, $callback = null) {
1425
+ // TODO check if $data is callable, not using is_callable
1426
+ if (! isset($callback)) {
1427
+ $callback = $data;
1428
+ $data = null;
1429
+ }
1430
+ foreach($this->elements as $node)
1431
+ phpQueryEvents::add($this->getDocumentID(), $node, $type, $data, $callback);
1432
+ return $this;
1433
+ }
1434
+ /**
1435
+ * Enter description here...
1436
+ *
1437
+ * @param unknown_type $type
1438
+ * @param unknown_type $callback
1439
+ * @return unknown
1440
+ * @TODO namespace events
1441
+ * @TODO support more than event in $type (space-separated)
1442
+ */
1443
+ public function unbind($type = null, $callback = null) {
1444
+ foreach($this->elements as $node)
1445
+ phpQueryEvents::remove($this->getDocumentID(), $node, $type, $callback);
1446
+ return $this;
1447
+ }
1448
+ /**
1449
+ * Enter description here...
1450
+ *
1451
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1452
+ */
1453
+ public function change($callback = null) {
1454
+ if ($callback)
1455
+ return $this->bind('change', $callback);
1456
+ return $this->trigger('change');
1457
+ }
1458
+ /**
1459
+ * Enter description here...
1460
+ *
1461
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1462
+ */
1463
+ public function submit($callback = null) {
1464
+ if ($callback)
1465
+ return $this->bind('submit', $callback);
1466
+ return $this->trigger('submit');
1467
+ }
1468
+ /**
1469
+ * Enter description here...
1470
+ *
1471
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1472
+ */
1473
+ public function click($callback = null) {
1474
+ if ($callback)
1475
+ return $this->bind('click', $callback);
1476
+ return $this->trigger('click');
1477
+ }
1478
+ /**
1479
+ * Enter description here...
1480
+ *
1481
+ * @param String|phpQuery
1482
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1483
+ */
1484
+ public function wrapAllOld($wrapper) {
1485
+ $wrapper = pq($wrapper)->_clone();
1486
+ if (! $wrapper->length() || ! $this->length() )
1487
+ return $this;
1488
+ $wrapper->insertBefore($this->elements[0]);
1489
+ $deepest = $wrapper->elements[0];
1490
+ while($deepest->firstChild && $deepest->firstChild instanceof DOMELEMENT)
1491
+ $deepest = $deepest->firstChild;
1492
+ pq($deepest)->append($this);
1493
+ return $this;
1494
+ }
1495
+ /**
1496
+ * Enter description here...
1497
+ *
1498
+ * TODO testme...
1499
+ * @param String|phpQuery
1500
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1501
+ */
1502
+ public function wrapAll($wrapper) {
1503
+ if (! $this->length())
1504
+ return $this;
1505
+ return phpQuery::pq($wrapper, $this->getDocumentID())
1506
+ ->clone()
1507
+ ->insertBefore($this->get(0))
1508
+ ->map(array($this, '___wrapAllCallback'))
1509
+ ->append($this);
1510
+ }
1511
+ /**
1512
+ *
1513
+ * @param $node
1514
+ * @return unknown_type
1515
+ * @access private
1516
+ */
1517
+ public function ___wrapAllCallback($node) {
1518
+ $deepest = $node;
1519
+ while($deepest->firstChild && $deepest->firstChild instanceof DOMELEMENT)
1520
+ $deepest = $deepest->firstChild;
1521
+ return $deepest;
1522
+ }
1523
+ /**
1524
+ * Enter description here...
1525
+ * NON JQUERY METHOD
1526
+ *
1527
+ * @param String|phpQuery
1528
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1529
+ */
1530
+ public function wrapAllPHP($codeBefore, $codeAfter) {
1531
+ return $this
1532
+ ->slice(0, 1)
1533
+ ->beforePHP($codeBefore)
1534
+ ->end()
1535
+ ->slice(-1)
1536
+ ->afterPHP($codeAfter)
1537
+ ->end();
1538
+ }
1539
+ /**
1540
+ * Enter description here...
1541
+ *
1542
+ * @param String|phpQuery
1543
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1544
+ */
1545
+ public function wrap($wrapper) {
1546
+ foreach($this->stack() as $node)
1547
+ phpQuery::pq($node, $this->getDocumentID())->wrapAll($wrapper);
1548
+ return $this;
1549
+ }
1550
+ /**
1551
+ * Enter description here...
1552
+ *
1553
+ * @param String|phpQuery
1554
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1555
+ */
1556
+ public function wrapPHP($codeBefore, $codeAfter) {
1557
+ foreach($this->stack() as $node)
1558
+ phpQuery::pq($node, $this->getDocumentID())->wrapAllPHP($codeBefore, $codeAfter);
1559
+ return $this;
1560
+ }
1561
+ /**
1562
+ * Enter description here...
1563
+ *
1564
+ * @param String|phpQuery
1565
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1566
+ */
1567
+ public function wrapInner($wrapper) {
1568
+ foreach($this->stack() as $node)
1569
+ phpQuery::pq($node, $this->getDocumentID())->contents()->wrapAll($wrapper);
1570
+ return $this;
1571
+ }
1572
+ /**
1573
+ * Enter description here...
1574
+ *
1575
+ * @param String|phpQuery
1576
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1577
+ */
1578
+ public function wrapInnerPHP($codeBefore, $codeAfter) {
1579
+ foreach($this->stack(1) as $node)
1580
+ phpQuery::pq($node, $this->getDocumentID())->contents()
1581
+ ->wrapAllPHP($codeBefore, $codeAfter);
1582
+ return $this;
1583
+ }
1584
+ /**
1585
+ * Enter description here...
1586
+ *
1587
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1588
+ * @testme Support for text nodes
1589
+ */
1590
+ public function contents() {
1591
+ $stack = array();
1592
+ foreach($this->stack(1) as $el) {
1593
+ // FIXME (fixed) http://code.google.com/p/phpquery/issues/detail?id=56
1594
+ // if (! isset($el->childNodes))
1595
+ // continue;
1596
+ foreach($el->childNodes as $node) {
1597
+ $stack[] = $node;
1598
+ }
1599
+ }
1600
+ return $this->newInstance($stack);
1601
+ }
1602
+ /**
1603
+ * Enter description here...
1604
+ *
1605
+ * jQuery difference.
1606
+ *
1607
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1608
+ */
1609
+ public function contentsUnwrap() {
1610
+ foreach($this->stack(1) as $node) {
1611
+ if (! $node->parentNode )
1612
+ continue;
1613
+ $childNodes = array();
1614
+ // any modification in DOM tree breaks childNodes iteration, so cache them first
1615
+ foreach($node->childNodes as $chNode )
1616
+ $childNodes[] = $chNode;
1617
+ foreach($childNodes as $chNode )
1618
+ // $node->parentNode->appendChild($chNode);
1619
+ $node->parentNode->insertBefore($chNode, $node);
1620
+ $node->parentNode->removeChild($node);
1621
+ }
1622
+ return $this;
1623
+ }
1624
+ /**
1625
+ * Enter description here...
1626
+ *
1627
+ * jQuery difference.
1628
+ */
1629
+ public function switchWith($markup) {
1630
+ $markup = pq($markup, $this->getDocumentID());
1631
+ $content = null;
1632
+ foreach($this->stack(1) as $node) {
1633
+ pq($node)
1634
+ ->contents()->toReference($content)->end()
1635
+ ->replaceWith($markup->clone()->append($content));
1636
+ }
1637
+ return $this;
1638
+ }
1639
+ /**
1640
+ * Enter description here...
1641
+ *
1642
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1643
+ */
1644
+ public function eq($num) {
1645
+ $oldStack = $this->elements;
1646
+ $this->elementsBackup = $this->elements;
1647
+ $this->elements = array();
1648
+ if ( isset($oldStack[$num]) )
1649
+ $this->elements[] = $oldStack[$num];
1650
+ return $this->newInstance();
1651
+ }
1652
+ /**
1653
+ * Enter description here...
1654
+ *
1655
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1656
+ */
1657
+ public function size() {
1658
+ return count($this->elements);
1659
+ }
1660
+ /**
1661
+ * Enter description here...
1662
+ *
1663
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1664
+ * @deprecated Use length as attribute
1665
+ */
1666
+ public function length() {
1667
+ return $this->size();
1668
+ }
1669
+ public function count() {
1670
+ return $this->size();
1671
+ }
1672
+ /**
1673
+ * Enter description here...
1674
+ *
1675
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1676
+ * @todo $level
1677
+ */
1678
+ public function end($level = 1) {
1679
+ // $this->elements = array_pop( $this->history );
1680
+ // return $this;
1681
+ // $this->previous->DOM = $this->DOM;
1682
+ // $this->previous->XPath = $this->XPath;
1683
+ return $this->previous
1684
+ ? $this->previous
1685
+ : $this;
1686
+ }
1687
+ /**
1688
+ * Enter description here...
1689
+ * Normal use ->clone() .
1690
+ *
1691
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1692
+ * @access private
1693
+ */
1694
+ public function _clone() {
1695
+ $newStack = array();
1696
+ //pr(array('copy... ', $this->whois()));
1697
+ //$this->dumpHistory('copy');
1698
+ $this->elementsBackup = $this->elements;
1699
+ foreach($this->elements as $node) {
1700
+ $newStack[] = $node->cloneNode(true);
1701
+ }
1702
+ $this->elements = $newStack;
1703
+ return $this->newInstance();
1704
+ }
1705
+ /**
1706
+ * Enter description here...
1707
+ *
1708
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1709
+ */
1710
+ public function replaceWithPHP($code) {
1711
+ return $this->replaceWith(phpQuery::php($code));
1712
+ }
1713
+ /**
1714
+ * Enter description here...
1715
+ *
1716
+ * @param String|phpQuery $content
1717
+ * @link http://docs.jquery.com/Manipulation/replaceWith#content
1718
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1719
+ */
1720
+ public function replaceWith($content) {
1721
+ return $this->after($content)->remove();
1722
+ }
1723
+ /**
1724
+ * Enter description here...
1725
+ *
1726
+ * @param String $selector
1727
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1728
+ * @todo this works ?
1729
+ */
1730
+ public function replaceAll($selector) {
1731
+ foreach(phpQuery::pq($selector, $this->getDocumentID()) as $node)
1732
+ phpQuery::pq($node, $this->getDocumentID())
1733
+ ->after($this->_clone())
1734
+ ->remove();
1735
+ return $this;
1736
+ }
1737
+ /**
1738
+ * Enter description here...
1739
+ *
1740
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1741
+ */
1742
+ public function remove($selector = null) {
1743
+ $loop = $selector
1744
+ ? $this->filter($selector)->elements
1745
+ : $this->elements;
1746
+ foreach($loop as $node) {
1747
+ if (! $node->parentNode )
1748
+ continue;
1749
+ if (isset($node->tagName))
1750
+ $this->debug("Removing '{$node->tagName}'");
1751
+ $node->parentNode->removeChild($node);
1752
+ // Mutation event
1753
+ $event = new DOMEvent(array(
1754
+ 'target' => $node,
1755
+ 'type' => 'DOMNodeRemoved'
1756
+ ));
1757
+ phpQueryEvents::trigger($this->getDocumentID(),
1758
+ $event->type, array($event), $node
1759
+ );
1760
+ }
1761
+ return $this;
1762
+ }
1763
+ protected function markupEvents($newMarkup, $oldMarkup, $node) {
1764
+ if ($node->tagName == 'textarea' && $newMarkup != $oldMarkup) {
1765
+ $event = new DOMEvent(array(
1766
+ 'target' => $node,
1767
+ 'type' => 'change'
1768
+ ));
1769
+ phpQueryEvents::trigger($this->getDocumentID(),
1770
+ $event->type, array($event), $node
1771
+ );
1772
+ }
1773
+ }
1774
+ /**
1775
+ * jQuey difference
1776
+ *
1777
+ * @param $markup
1778
+ * @return unknown_type
1779
+ * @TODO trigger change event for textarea
1780
+ */
1781
+ public function markup($markup = null, $callback1 = null, $callback2 = null, $callback3 = null) {
1782
+ $args = func_get_args();
1783
+ if ($this->documentWrapper->isXML)
1784
+ return call_user_func_array(array($this, 'xml'), $args);
1785
+ else
1786
+ return call_user_func_array(array($this, 'html'), $args);
1787
+ }
1788
+ /**
1789
+ * jQuey difference
1790
+ *
1791
+ * @param $markup
1792
+ * @return unknown_type
1793
+ */
1794
+ public function markupOuter($callback1 = null, $callback2 = null, $callback3 = null) {
1795
+ $args = func_get_args();
1796
+ if ($this->documentWrapper->isXML)
1797
+ return call_user_func_array(array($this, 'xmlOuter'), $args);
1798
+ else
1799
+ return call_user_func_array(array($this, 'htmlOuter'), $args);
1800
+ }
1801
+ /**
1802
+ * Enter description here...
1803
+ *
1804
+ * @param unknown_type $html
1805
+ * @return string|phpQuery|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1806
+ * @TODO force html result
1807
+ */
1808
+ public function html($html = null, $callback1 = null, $callback2 = null, $callback3 = null) {
1809
+ if (isset($html)) {
1810
+ // INSERT
1811
+ $nodes = $this->documentWrapper->import($html);
1812
+ $this->empty();
1813
+ foreach($this->stack(1) as $alreadyAdded => $node) {
1814
+ // for now, limit events for textarea
1815
+ if (($this->isXHTML() || $this->isHTML()) && $node->tagName == 'textarea')
1816
+ $oldHtml = pq($node, $this->getDocumentID())->markup();
1817
+ foreach($nodes as $newNode) {
1818
+ $node->appendChild($alreadyAdded
1819
+ ? $newNode->cloneNode(true)
1820
+ : $newNode
1821
+ );
1822
+ }
1823
+ // for now, limit events for textarea
1824
+ if (($this->isXHTML() || $this->isHTML()) && $node->tagName == 'textarea')
1825
+ $this->markupEvents($html, $oldHtml, $node);
1826
+ }
1827
+ return $this;
1828
+ } else {
1829
+ // FETCH
1830
+ $return = $this->documentWrapper->markup($this->elements, true);
1831
+ $args = func_get_args();
1832
+ foreach(array_slice($args, 1) as $callback) {
1833
+ $return = phpQuery::callbackRun($callback, array($return));
1834
+ }
1835
+ return $return;
1836
+ }
1837
+ }
1838
+ /**
1839
+ * @TODO force xml result
1840
+ */
1841
+ public function xml($xml = null, $callback1 = null, $callback2 = null, $callback3 = null) {
1842
+ $args = func_get_args();
1843
+ return call_user_func_array(array($this, 'html'), $args);
1844
+ }
1845
+ /**
1846
+ * Enter description here...
1847
+ * @TODO force html result
1848
+ *
1849
+ * @return String
1850
+ */
1851
+ public function htmlOuter($callback1 = null, $callback2 = null, $callback3 = null) {
1852
+ $markup = $this->documentWrapper->markup($this->elements);
1853
+ // pass thou callbacks
1854
+ $args = func_get_args();
1855
+ foreach($args as $callback) {
1856
+ $markup = phpQuery::callbackRun($callback, array($markup));
1857
+ }
1858
+ return $markup;
1859
+ }
1860
+ /**
1861
+ * @TODO force xml result
1862
+ */
1863
+ public function xmlOuter($callback1 = null, $callback2 = null, $callback3 = null) {
1864
+ $args = func_get_args();
1865
+ return call_user_func_array(array($this, 'htmlOuter'), $args);
1866
+ }
1867
+ public function __toString() {
1868
+ return $this->markupOuter();
1869
+ }
1870
+ /**
1871
+ * Just like html(), but returns markup with VALID (dangerous) PHP tags.
1872
+ *
1873
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1874
+ * @todo support returning markup with PHP tags when called without param
1875
+ */
1876
+ public function php($code = null) {
1877
+ return $this->markupPHP($code);
1878
+ }
1879
+ /**
1880
+ * Enter description here...
1881
+ *
1882
+ * @param $code
1883
+ * @return unknown_type
1884
+ */
1885
+ public function markupPHP($code = null) {
1886
+ return isset($code)
1887
+ ? $this->markup(phpQuery::php($code))
1888
+ : phpQuery::markupToPHP($this->markup());
1889
+ }
1890
+ /**
1891
+ * Enter description here...
1892
+ *
1893
+ * @param $code
1894
+ * @return unknown_type
1895
+ */
1896
+ public function markupOuterPHP() {
1897
+ return phpQuery::markupToPHP($this->markupOuter());
1898
+ }
1899
+ /**
1900
+ * Enter description here...
1901
+ *
1902
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1903
+ */
1904
+ public function children($selector = null) {
1905
+ $stack = array();
1906
+ foreach($this->stack(1) as $node) {
1907
+ // foreach($node->getElementsByTagName('*') as $newNode) {
1908
+ foreach($node->childNodes as $newNode) {
1909
+ if ($newNode->nodeType != 1)
1910
+ continue;
1911
+ if ($selector && ! $this->is($selector, $newNode))
1912
+ continue;
1913
+ if ($this->elementsContainsNode($newNode, $stack))
1914
+ continue;
1915
+ $stack[] = $newNode;
1916
+ }
1917
+ }
1918
+ $this->elementsBackup = $this->elements;
1919
+ $this->elements = $stack;
1920
+ return $this->newInstance();
1921
+ }
1922
+ /**
1923
+ * Enter description here...
1924
+ *
1925
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1926
+ */
1927
+ public function ancestors($selector = null) {
1928
+ return $this->children( $selector );
1929
+ }
1930
+ /**
1931
+ * Enter description here...
1932
+ *
1933
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1934
+ */
1935
+ public function append( $content) {
1936
+ return $this->insert($content, __FUNCTION__);
1937
+ }
1938
+ /**
1939
+ * Enter description here...
1940
+ *
1941
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1942
+ */
1943
+ public function appendPHP( $content) {
1944
+ return $this->insert("<php><!-- {$content} --></php>", 'append');
1945
+ }
1946
+ /**
1947
+ * Enter description here...
1948
+ *
1949
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1950
+ */
1951
+ public function appendTo( $seletor) {
1952
+ return $this->insert($seletor, __FUNCTION__);
1953
+ }
1954
+ /**
1955
+ * Enter description here...
1956
+ *
1957
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1958
+ */
1959
+ public function prepend( $content) {
1960
+ return $this->insert($content, __FUNCTION__);
1961
+ }
1962
+ /**
1963
+ * Enter description here...
1964
+ *
1965
+ * @todo accept many arguments, which are joined, arrays maybe also
1966
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1967
+ */
1968
+ public function prependPHP( $content) {
1969
+ return $this->insert("<php><!-- {$content} --></php>", 'prepend');
1970
+ }
1971
+ /**
1972
+ * Enter description here...
1973
+ *
1974
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1975
+ */
1976
+ public function prependTo( $seletor) {
1977
+ return $this->insert($seletor, __FUNCTION__);
1978
+ }
1979
+ /**
1980
+ * Enter description here...
1981
+ *
1982
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1983
+ */
1984
+ public function before($content) {
1985
+ return $this->insert($content, __FUNCTION__);
1986
+ }
1987
+ /**
1988
+ * Enter description here...
1989
+ *
1990
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
1991
+ */
1992
+ public function beforePHP( $content) {
1993
+ return $this->insert("<php><!-- {$content} --></php>", 'before');
1994
+ }
1995
+ /**
1996
+ * Enter description here...
1997
+ *
1998
+ * @param String|phpQuery
1999
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2000
+ */
2001
+ public function insertBefore( $seletor) {
2002
+ return $this->insert($seletor, __FUNCTION__);
2003
+ }
2004
+ /**
2005
+ * Enter description here...
2006
+ *
2007
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2008
+ */
2009
+ public function after( $content) {
2010
+ return $this->insert($content, __FUNCTION__);
2011
+ }
2012
+ /**
2013
+ * Enter description here...
2014
+ *
2015
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2016
+ */
2017
+ public function afterPHP( $content) {
2018
+ return $this->insert("<php><!-- {$content} --></php>", 'after');
2019
+ }
2020
+ /**
2021
+ * Enter description here...
2022
+ *
2023
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2024
+ */
2025
+ public function insertAfter( $seletor) {
2026
+ return $this->insert($seletor, __FUNCTION__);
2027
+ }
2028
+ /**
2029
+ * Internal insert method. Don't use it.
2030
+ *
2031
+ * @param unknown_type $target
2032
+ * @param unknown_type $type
2033
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2034
+ * @access private
2035
+ */
2036
+ public function insert($target, $type) {
2037
+ $this->debug("Inserting data with '{$type}'");
2038
+ $to = false;
2039
+ switch( $type) {
2040
+ case 'appendTo':
2041
+ case 'prependTo':
2042
+ case 'insertBefore':
2043
+ case 'insertAfter':
2044
+ $to = true;
2045
+ }
2046
+ switch(gettype($target)) {
2047
+ case 'string':
2048
+ $insertFrom = $insertTo = array();
2049
+ if ($to) {
2050
+ // INSERT TO
2051
+ $insertFrom = $this->elements;
2052
+ if (phpQuery::isMarkup($target)) {
2053
+ // $target is new markup, import it
2054
+ $insertTo = $this->documentWrapper->import($target);
2055
+ // insert into selected element
2056
+ } else {
2057
+ // $tagret is a selector
2058
+ $thisStack = $this->elements;
2059
+ $this->toRoot();
2060
+ $insertTo = $this->find($target)->elements;
2061
+ $this->elements = $thisStack;
2062
+ }
2063
+ } else {
2064
+ // INSERT FROM
2065
+ $insertTo = $this->elements;
2066
+ $insertFrom = $this->documentWrapper->import($target);
2067
+ }
2068
+ break;
2069
+ case 'object':
2070
+ $insertFrom = $insertTo = array();
2071
+ // phpQuery
2072
+ if ($target instanceof self) {
2073
+ if ($to) {
2074
+ $insertTo = $target->elements;
2075
+ if ($this->documentFragment && $this->stackIsRoot())
2076
+ // get all body children
2077
+ // $loop = $this->find('body > *')->elements;
2078
+ // TODO test it, test it hard...
2079
+ // $loop = $this->newInstance($this->root)->find('> *')->elements;
2080
+ $loop = $this->root->childNodes;
2081
+ else
2082
+ $loop = $this->elements;
2083
+ // import nodes if needed
2084
+ $insertFrom = $this->getDocumentID() == $target->getDocumentID()
2085
+ ? $loop
2086
+ : $target->documentWrapper->import($loop);
2087
+ } else {
2088
+ $insertTo = $this->elements;
2089
+ if ( $target->documentFragment && $target->stackIsRoot() )
2090
+ // get all body children
2091
+ // $loop = $target->find('body > *')->elements;
2092
+ $loop = $target->root->childNodes;
2093
+ else
2094
+ $loop = $target->elements;
2095
+ // import nodes if needed
2096
+ $insertFrom = $this->getDocumentID() == $target->getDocumentID()
2097
+ ? $loop
2098
+ : $this->documentWrapper->import($loop);
2099
+ }
2100
+ // DOMNODE
2101
+ } elseif ($target instanceof DOMNODE) {
2102
+ // import node if needed
2103
+ // if ( $target->ownerDocument != $this->DOM )
2104
+ // $target = $this->DOM->importNode($target, true);
2105
+ if ( $to) {
2106
+ $insertTo = array($target);
2107
+ if ($this->documentFragment && $this->stackIsRoot())
2108
+ // get all body children
2109
+ $loop = $this->root->childNodes;
2110
+ // $loop = $this->find('body > *')->elements;
2111
+ else
2112
+ $loop = $this->elements;
2113
+ foreach($loop as $fromNode)
2114
+ // import nodes if needed
2115
+ $insertFrom[] = ! $fromNode->ownerDocument->isSameNode($target->ownerDocument)
2116
+ ? $target->ownerDocument->importNode($fromNode, true)
2117
+ : $fromNode;
2118
+ } else {
2119
+ // import node if needed
2120
+ if (! $target->ownerDocument->isSameNode($this->document))
2121
+ $target = $this->document->importNode($target, true);
2122
+ $insertTo = $this->elements;
2123
+ $insertFrom[] = $target;
2124
+ }
2125
+ }
2126
+ break;
2127
+ }
2128
+ phpQuery::debug("From ".count($insertFrom)."; To ".count($insertTo)." nodes");
2129
+ foreach($insertTo as $insertNumber => $toNode) {
2130
+ // we need static relative elements in some cases
2131
+ switch( $type) {
2132
+ case 'prependTo':
2133
+ case 'prepend':
2134
+ $firstChild = $toNode->firstChild;
2135
+ break;
2136
+ case 'insertAfter':
2137
+ case 'after':
2138
+ $nextSibling = $toNode->nextSibling;
2139
+ break;
2140
+ }
2141
+ foreach($insertFrom as $fromNode) {
2142
+ // clone if inserted already before
2143
+ $insert = $insertNumber
2144
+ ? $fromNode->cloneNode(true)
2145
+ : $fromNode;
2146
+ switch($type) {
2147
+ case 'appendTo':
2148
+ case 'append':
2149
+ // $toNode->insertBefore(
2150
+ // $fromNode,
2151
+ // $toNode->lastChild->nextSibling
2152
+ // );
2153
+ $toNode->appendChild($insert);
2154
+ $eventTarget = $insert;
2155
+ break;
2156
+ case 'prependTo':
2157
+ case 'prepend':
2158
+ $toNode->insertBefore(
2159
+ $insert,
2160
+ $firstChild
2161
+ );
2162
+ break;
2163
+ case 'insertBefore':
2164
+ case 'before':
2165
+ if (! $toNode->parentNode)
2166
+ throw new Exception("No parentNode, can't do {$type}()");
2167
+ else
2168
+ $toNode->parentNode->insertBefore(
2169
+ $insert,
2170
+ $toNode
2171
+ );
2172
+ break;
2173
+ case 'insertAfter':
2174
+ case 'after':
2175
+ if (! $toNode->parentNode)
2176
+ throw new Exception("No parentNode, can't do {$type}()");
2177
+ else
2178
+ $toNode->parentNode->insertBefore(
2179
+ $insert,
2180
+ $nextSibling
2181
+ );
2182
+ break;
2183
+ }
2184
+ // Mutation event
2185
+ $event = new DOMEvent(array(
2186
+ 'target' => $insert,
2187
+ 'type' => 'DOMNodeInserted'
2188
+ ));
2189
+ phpQueryEvents::trigger($this->getDocumentID(),
2190
+ $event->type, array($event), $insert
2191
+ );
2192
+ }
2193
+ }
2194
+ return $this;
2195
+ }
2196
+ /**
2197
+ * Enter description here...
2198
+ *
2199
+ * @return Int
2200
+ */
2201
+ public function index($subject) {
2202
+ $index = -1;
2203
+ $subject = $subject instanceof phpQueryObject
2204
+ ? $subject->elements[0]
2205
+ : $subject;
2206
+ foreach($this->newInstance() as $k => $node) {
2207
+ if ($node->isSameNode($subject))
2208
+ $index = $k;
2209
+ }
2210
+ return $index;
2211
+ }
2212
+ /**
2213
+ * Enter description here...
2214
+ *
2215
+ * @param unknown_type $start
2216
+ * @param unknown_type $end
2217
+ *
2218
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2219
+ * @testme
2220
+ */
2221
+ public function slice($start, $end = null) {
2222
+ // $last = count($this->elements)-1;
2223
+ // $end = $end
2224
+ // ? min($end, $last)
2225
+ // : $last;
2226
+ // if ($start < 0)
2227
+ // $start = $last+$start;
2228
+ // if ($start > $last)
2229
+ // return array();
2230
+ if ($end > 0)
2231
+ $end = $end-$start;
2232
+ return $this->newInstance(
2233
+ array_slice($this->elements, $start, $end)
2234
+ );
2235
+ }
2236
+ /**
2237
+ * Enter description here...
2238
+ *
2239
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2240
+ */
2241
+ public function reverse() {
2242
+ $this->elementsBackup = $this->elements;
2243
+ $this->elements = array_reverse($this->elements);
2244
+ return $this->newInstance();
2245
+ }
2246
+ /**
2247
+ * Return joined text content.
2248
+ * @return String
2249
+ */
2250
+ public function text($text = null, $callback1 = null, $callback2 = null, $callback3 = null) {
2251
+ if (isset($text))
2252
+ return $this->html(htmlspecialchars($text));
2253
+ $args = func_get_args();
2254
+ $args = array_slice($args, 1);
2255
+ $return = '';
2256
+ foreach($this->elements as $node) {
2257
+ $text = $node->textContent;
2258
+ if (count($this->elements) > 1 && $text)
2259
+ $text .= "\n";
2260
+ foreach($args as $callback) {
2261
+ $text = phpQuery::callbackRun($callback, array($text));
2262
+ }
2263
+ $return .= $text;
2264
+ }
2265
+ return $return;
2266
+ }
2267
+ /**
2268
+ * Enter description here...
2269
+ *
2270
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2271
+ */
2272
+ public function plugin($class, $file = null) {
2273
+ phpQuery::plugin($class, $file);
2274
+ return $this;
2275
+ }
2276
+ /**
2277
+ * Deprecated, use $pq->plugin() instead.
2278
+ *
2279
+ * @deprecated
2280
+ * @param $class
2281
+ * @param $file
2282
+ * @return unknown_type
2283
+ */
2284
+ public static function extend($class, $file = null) {
2285
+ return $this->plugin($class, $file);
2286
+ }
2287
+ /**
2288
+ *
2289
+ * @access private
2290
+ * @param $method
2291
+ * @param $args
2292
+ * @return unknown_type
2293
+ */
2294
+ public function __call($method, $args) {
2295
+ $aliasMethods = array('clone', 'empty');
2296
+ if (isset(phpQuery::$extendMethods[$method])) {
2297
+ array_unshift($args, $this);
2298
+ return phpQuery::callbackRun(
2299
+ phpQuery::$extendMethods[$method], $args
2300
+ );
2301
+ } else if (isset(phpQuery::$pluginsMethods[$method])) {
2302
+ array_unshift($args, $this);
2303
+ $class = phpQuery::$pluginsMethods[$method];
2304
+ $realClass = "phpQueryObjectPlugin_$class";
2305
+ $return = call_user_func_array(
2306
+ array($realClass, $method),
2307
+ $args
2308
+ );
2309
+ // XXX deprecate ?
2310
+ return is_null($return)
2311
+ ? $this
2312
+ : $return;
2313
+ } else if (in_array($method, $aliasMethods)) {
2314
+ return call_user_func_array(array($this, '_'.$method), $args);
2315
+ } else
2316
+ throw new Exception("Method '{$method}' doesnt exist");
2317
+ }
2318
+ /**
2319
+ * Safe rename of next().
2320
+ *
2321
+ * Use it ONLY when need to call next() on an iterated object (in same time).
2322
+ * Normaly there is no need to do such thing ;)
2323
+ *
2324
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2325
+ * @access private
2326
+ */
2327
+ public function _next($selector = null) {
2328
+ return $this->newInstance(
2329
+ $this->getElementSiblings('nextSibling', $selector, true)
2330
+ );
2331
+ }
2332
+ /**
2333
+ * Use prev() and next().
2334
+ *
2335
+ * @deprecated
2336
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2337
+ * @access private
2338
+ */
2339
+ public function _prev($selector = null) {
2340
+ return $this->prev($selector);
2341
+ }
2342
+ /**
2343
+ * Enter description here...
2344
+ *
2345
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2346
+ */
2347
+ public function prev($selector = null) {
2348
+ return $this->newInstance(
2349
+ $this->getElementSiblings('previousSibling', $selector, true)
2350
+ );
2351
+ }
2352
+ /**
2353
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2354
+ * @todo
2355
+ */
2356
+ public function prevAll($selector = null) {
2357
+ return $this->newInstance(
2358
+ $this->getElementSiblings('previousSibling', $selector)
2359
+ );
2360
+ }
2361
+ /**
2362
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2363
+ * @todo FIXME: returns source elements insted of next siblings
2364
+ */
2365
+ public function nextAll($selector = null) {
2366
+ return $this->newInstance(
2367
+ $this->getElementSiblings('nextSibling', $selector)
2368
+ );
2369
+ }
2370
+ /**
2371
+ * @access private
2372
+ */
2373
+ protected function getElementSiblings($direction, $selector = null, $limitToOne = false) {
2374
+ $stack = array();
2375
+ $count = 0;
2376
+ foreach($this->stack() as $node) {
2377
+ $test = $node;
2378
+ while( isset($test->{$direction}) && $test->{$direction}) {
2379
+ $test = $test->{$direction};
2380
+ if (! $test instanceof DOMELEMENT)
2381
+ continue;
2382
+ $stack[] = $test;
2383
+ if ($limitToOne)
2384
+ break;
2385
+ }
2386
+ }
2387
+ if ($selector) {
2388
+ $stackOld = $this->elements;
2389
+ $this->elements = $stack;
2390
+ $stack = $this->filter($selector, true)->stack();
2391
+ $this->elements = $stackOld;
2392
+ }
2393
+ return $stack;
2394
+ }
2395
+ /**
2396
+ * Enter description here...
2397
+ *
2398
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2399
+ */
2400
+ public function siblings($selector = null) {
2401
+ $stack = array();
2402
+ $siblings = array_merge(
2403
+ $this->getElementSiblings('previousSibling', $selector),
2404
+ $this->getElementSiblings('nextSibling', $selector)
2405
+ );
2406
+ foreach($siblings as $node) {
2407
+ if (! $this->elementsContainsNode($node, $stack))
2408
+ $stack[] = $node;
2409
+ }
2410
+ return $this->newInstance($stack);
2411
+ }
2412
+ /**
2413
+ * Enter description here...
2414
+ *
2415
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2416
+ */
2417
+ public function not($selector = null) {
2418
+ if (is_string($selector))
2419
+ phpQuery::debug(array('not', $selector));
2420
+ else
2421
+ phpQuery::debug('not');
2422
+ $stack = array();
2423
+ if ($selector instanceof self || $selector instanceof DOMNODE) {
2424
+ foreach($this->stack() as $node) {
2425
+ if ($selector instanceof self) {
2426
+ $matchFound = false;
2427
+ foreach($selector->stack() as $notNode) {
2428
+ if ($notNode->isSameNode($node))
2429
+ $matchFound = true;
2430
+ }
2431
+ if (! $matchFound)
2432
+ $stack[] = $node;
2433
+ } else if ($selector instanceof DOMNODE) {
2434
+ if (! $selector->isSameNode($node))
2435
+ $stack[] = $node;
2436
+ } else {
2437
+ if (! $this->is($selector))
2438
+ $stack[] = $node;
2439
+ }
2440
+ }
2441
+ } else {
2442
+ $orgStack = $this->stack();
2443
+ $matched = $this->filter($selector, true)->stack();
2444
+ // $matched = array();
2445
+ // // simulate OR in filter() instead of AND 5y
2446
+ // foreach($this->parseSelector($selector) as $s) {
2447
+ // $matched = array_merge($matched,
2448
+ // $this->filter(array($s))->stack()
2449
+ // );
2450
+ // }
2451
+ foreach($orgStack as $node)
2452
+ if (! $this->elementsContainsNode($node, $matched))
2453
+ $stack[] = $node;
2454
+ }
2455
+ return $this->newInstance($stack);
2456
+ }
2457
+ /**
2458
+ * Enter description here...
2459
+ *
2460
+ * @param string|phpQueryObject
2461
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2462
+ */
2463
+ public function add($selector = null) {
2464
+ if (! $selector)
2465
+ return $this;
2466
+ $stack = array();
2467
+ $this->elementsBackup = $this->elements;
2468
+ $found = phpQuery::pq($selector, $this->getDocumentID());
2469
+ $this->merge($found->elements);
2470
+ return $this->newInstance();
2471
+ }
2472
+ /**
2473
+ * @access private
2474
+ */
2475
+ protected function merge() {
2476
+ foreach(func_get_args() as $nodes)
2477
+ foreach($nodes as $newNode )
2478
+ if (! $this->elementsContainsNode($newNode) )
2479
+ $this->elements[] = $newNode;
2480
+ }
2481
+ /**
2482
+ * @access private
2483
+ * TODO refactor to stackContainsNode
2484
+ */
2485
+ protected function elementsContainsNode($nodeToCheck, $elementsStack = null) {
2486
+ $loop = ! is_null($elementsStack)
2487
+ ? $elementsStack
2488
+ : $this->elements;
2489
+ foreach($loop as $node) {
2490
+ if ( $node->isSameNode( $nodeToCheck ) )
2491
+ return true;
2492
+ }
2493
+ return false;
2494
+ }
2495
+ /**
2496
+ * Enter description here...
2497
+ *
2498
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2499
+ */
2500
+ public function parent($selector = null) {
2501
+ $stack = array();
2502
+ foreach($this->elements as $node )
2503
+ if ( $node->parentNode && ! $this->elementsContainsNode($node->parentNode, $stack) )
2504
+ $stack[] = $node->parentNode;
2505
+ $this->elementsBackup = $this->elements;
2506
+ $this->elements = $stack;
2507
+ if ( $selector )
2508
+ $this->filter($selector, true);
2509
+ return $this->newInstance();
2510
+ }
2511
+ /**
2512
+ * Enter description here...
2513
+ *
2514
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2515
+ */
2516
+ public function parents($selector = null) {
2517
+ $stack = array();
2518
+ if (! $this->elements )
2519
+ $this->debug('parents() - stack empty');
2520
+ foreach($this->elements as $node) {
2521
+ $test = $node;
2522
+ while( $test->parentNode) {
2523
+ $test = $test->parentNode;
2524
+ if ($this->isRoot($test))
2525
+ break;
2526
+ if (! $this->elementsContainsNode($test, $stack)) {
2527
+ $stack[] = $test;
2528
+ continue;
2529
+ }
2530
+ }
2531
+ }
2532
+ $this->elementsBackup = $this->elements;
2533
+ $this->elements = $stack;
2534
+ if ( $selector )
2535
+ $this->filter($selector, true);
2536
+ return $this->newInstance();
2537
+ }
2538
+ /**
2539
+ * Internal stack iterator.
2540
+ *
2541
+ * @access private
2542
+ */
2543
+ public function stack($nodeTypes = null) {
2544
+ if (!isset($nodeTypes))
2545
+ return $this->elements;
2546
+ if (!is_array($nodeTypes))
2547
+ $nodeTypes = array($nodeTypes);
2548
+ $return = array();
2549
+ foreach($this->elements as $node) {
2550
+ if (in_array($node->nodeType, $nodeTypes))
2551
+ $return[] = $node;
2552
+ }
2553
+ return $return;
2554
+ }
2555
+ // TODO phpdoc; $oldAttr is result of hasAttribute, before any changes
2556
+ protected function attrEvents($attr, $oldAttr, $oldValue, $node) {
2557
+ // skip events for XML documents
2558
+ if (! $this->isXHTML() && ! $this->isHTML())
2559
+ return;
2560
+ $event = null;
2561
+ // identify
2562
+ $isInputValue = $node->tagName == 'input'
2563
+ && (
2564
+ in_array($node->getAttribute('type'),
2565
+ array('text', 'password', 'hidden'))
2566
+ || !$node->getAttribute('type')
2567
+ );
2568
+ $isRadio = $node->tagName == 'input'
2569
+ && $node->getAttribute('type') == 'radio';
2570
+ $isCheckbox = $node->tagName == 'input'
2571
+ && $node->getAttribute('type') == 'checkbox';
2572
+ $isOption = $node->tagName == 'option';
2573
+ if ($isInputValue && $attr == 'value' && $oldValue != $node->getAttribute($attr)) {
2574
+ $event = new DOMEvent(array(
2575
+ 'target' => $node,
2576
+ 'type' => 'change'
2577
+ ));
2578
+ } else if (($isRadio || $isCheckbox) && $attr == 'checked' && (
2579
+ // check
2580
+ (! $oldAttr && $node->hasAttribute($attr))
2581
+ // un-check
2582
+ || (! $node->hasAttribute($attr) && $oldAttr)
2583
+ )) {
2584
+ $event = new DOMEvent(array(
2585
+ 'target' => $node,
2586
+ 'type' => 'change'
2587
+ ));
2588
+ } else if ($isOption && $node->parentNode && $attr == 'selected' && (
2589
+ // select
2590
+ (! $oldAttr && $node->hasAttribute($attr))
2591
+ // un-select
2592
+ || (! $node->hasAttribute($attr) && $oldAttr)
2593
+ )) {
2594
+ $event = new DOMEvent(array(
2595
+ 'target' => $node->parentNode,
2596
+ 'type' => 'change'
2597
+ ));
2598
+ }
2599
+ if ($event) {
2600
+ phpQueryEvents::trigger($this->getDocumentID(),
2601
+ $event->type, array($event), $node
2602
+ );
2603
+ }
2604
+ }
2605
+ public function attr($attr = null, $value = null) {
2606
+ foreach($this->stack(1) as $node) {
2607
+ if (! is_null($value)) {
2608
+ $loop = $attr == '*'
2609
+ ? $this->getNodeAttrs($node)
2610
+ : array($attr);
2611
+ foreach($loop as $a) {
2612
+ $oldValue = $node->getAttribute($a);
2613
+ $oldAttr = $node->hasAttribute($a);
2614
+ // TODO raises an error when charset other than UTF-8
2615
+ // while document's charset is also not UTF-8
2616
+ @$node->setAttribute($a, $value);
2617
+ $this->attrEvents($a, $oldAttr, $oldValue, $node);
2618
+ }
2619
+ } else if ($attr == '*') {
2620
+ // jQuery difference
2621
+ $return = array();
2622
+ foreach($node->attributes as $n => $v)
2623
+ $return[$n] = $v->value;
2624
+ return $return;
2625
+ } else
2626
+ return $node->hasAttribute($attr)
2627
+ ? $node->getAttribute($attr)
2628
+ : null;
2629
+ }
2630
+ return is_null($value)
2631
+ ? '' : $this;
2632
+ }
2633
+ /**
2634
+ * @access private
2635
+ */
2636
+ protected function getNodeAttrs($node) {
2637
+ $return = array();
2638
+ foreach($node->attributes as $n => $o)
2639
+ $return[] = $n;
2640
+ return $return;
2641
+ }
2642
+ /**
2643
+ * Enter description here...
2644
+ *
2645
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2646
+ * @todo check CDATA ???
2647
+ */
2648
+ public function attrPHP($attr, $code) {
2649
+ if (! is_null($code)) {
2650
+ $value = '<'.'?php '.$code.' ?'.'>';
2651
+ // TODO tempolary solution
2652
+ // http://code.google.com/p/phpquery/issues/detail?id=17
2653
+ // if (function_exists('mb_detect_encoding') && mb_detect_encoding($value) == 'ASCII')
2654
+ // $value = mb_convert_encoding($value, 'UTF-8', 'HTML-ENTITIES');
2655
+ }
2656
+ foreach($this->stack(1) as $node) {
2657
+ if (! is_null($code)) {
2658
+ // $attrNode = $this->DOM->createAttribute($attr);
2659
+ $node->setAttribute($attr, $value);
2660
+ // $attrNode->value = $value;
2661
+ // $node->appendChild($attrNode);
2662
+ } else if ( $attr == '*') {
2663
+ // jQuery diff
2664
+ $return = array();
2665
+ foreach($node->attributes as $n => $v)
2666
+ $return[$n] = $v->value;
2667
+ return $return;
2668
+ } else
2669
+ return $node->getAttribute($attr);
2670
+ }
2671
+ return $this;
2672
+ }
2673
+ /**
2674
+ * Enter description here...
2675
+ *
2676
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2677
+ */
2678
+ public function removeAttr($attr) {
2679
+ foreach($this->stack(1) as $node) {
2680
+ $loop = $attr == '*'
2681
+ ? $this->getNodeAttrs($node)
2682
+ : array($attr);
2683
+ foreach($loop as $a) {
2684
+ $oldValue = $node->getAttribute($a);
2685
+ $node->removeAttribute($a);
2686
+ $this->attrEvents($a, $oldValue, null, $node);
2687
+ }
2688
+ }
2689
+ return $this;
2690
+ }
2691
+ /**
2692
+ * Return form element value.
2693
+ *
2694
+ * @return String Fields value.
2695
+ */
2696
+ public function val($val = null) {
2697
+ if (! isset($val)) {
2698
+ if ($this->eq(0)->is('select')) {
2699
+ $selected = $this->eq(0)->find('option[selected=selected]');
2700
+ if ($selected->is('[value]'))
2701
+ return $selected->attr('value');
2702
+ else
2703
+ return $selected->text();
2704
+ } else if ($this->eq(0)->is('textarea'))
2705
+ return $this->eq(0)->markup();
2706
+ else
2707
+ return $this->eq(0)->attr('value');
2708
+ } else {
2709
+ $_val = null;
2710
+ foreach($this->stack(1) as $node) {
2711
+ $node = pq($node, $this->getDocumentID());
2712
+ if (is_array($val) && in_array($node->attr('type'), array('checkbox', 'radio'))) {
2713
+ $isChecked = in_array($node->attr('value'), $val)
2714
+ || in_array($node->attr('name'), $val);
2715
+ if ($isChecked)
2716
+ $node->attr('checked', 'checked');
2717
+ else
2718
+ $node->removeAttr('checked');
2719
+ } else if ($node->get(0)->tagName == 'select') {
2720
+ if (! isset($_val)) {
2721
+ $_val = array();
2722
+ if (! is_array($val))
2723
+ $_val = array((string)$val);
2724
+ else
2725
+ foreach($val as $v)
2726
+ $_val[] = $v;
2727
+ }
2728
+ foreach($node['option']->stack(1) as $option) {
2729
+ $option = pq($option, $this->getDocumentID());
2730
+ $selected = false;
2731
+ // XXX: workaround for string comparsion, see issue #96
2732
+ // http://code.google.com/p/phpquery/issues/detail?id=96
2733
+ $selected = is_null($option->attr('value'))
2734
+ ? in_array($option->markup(), $_val)
2735
+ : in_array($option->attr('value'), $_val);
2736
+ // $optionValue = $option->attr('value');
2737
+ // $optionText = $option->text();
2738
+ // $optionTextLenght = mb_strlen($optionText);
2739
+ // foreach($_val as $v)
2740
+ // if ($optionValue == $v)
2741
+ // $selected = true;
2742
+ // else if ($optionText == $v && $optionTextLenght == mb_strlen($v))
2743
+ // $selected = true;
2744
+ if ($selected)
2745
+ $option->attr('selected', 'selected');
2746
+ else
2747
+ $option->removeAttr('selected');
2748
+ }
2749
+ } else if ($node->get(0)->tagName == 'textarea')
2750
+ $node->markup($val);
2751
+ else
2752
+ $node->attr('value', $val);
2753
+ }
2754
+ }
2755
+ return $this;
2756
+ }
2757
+ /**
2758
+ * Enter description here...
2759
+ *
2760
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2761
+ */
2762
+ public function andSelf() {
2763
+ if ( $this->previous )
2764
+ $this->elements = array_merge($this->elements, $this->previous->elements);
2765
+ return $this;
2766
+ }
2767
+ /**
2768
+ * Enter description here...
2769
+ *
2770
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2771
+ */
2772
+ public function addClass( $className) {
2773
+ if (! $className)
2774
+ return $this;
2775
+ foreach($this->stack(1) as $node) {
2776
+ if (! $this->is(".$className", $node))
2777
+ $node->setAttribute(
2778
+ 'class',
2779
+ trim($node->getAttribute('class').' '.$className)
2780
+ );
2781
+ }
2782
+ return $this;
2783
+ }
2784
+ /**
2785
+ * Enter description here...
2786
+ *
2787
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2788
+ */
2789
+ public function addClassPHP( $className) {
2790
+ foreach($this->stack(1) as $node) {
2791
+ $classes = $node->getAttribute('class');
2792
+ $newValue = $classes
2793
+ ? $classes.' <'.'?php '.$className.' ?'.'>'
2794
+ : '<'.'?php '.$className.' ?'.'>';
2795
+ $node->setAttribute('class', $newValue);
2796
+ }
2797
+ return $this;
2798
+ }
2799
+ /**
2800
+ * Enter description here...
2801
+ *
2802
+ * @param string $className
2803
+ * @return bool
2804
+ */
2805
+ public function hasClass($className) {
2806
+ foreach($this->stack(1) as $node) {
2807
+ if ( $this->is(".$className", $node))
2808
+ return true;
2809
+ }
2810
+ return false;
2811
+ }
2812
+ /**
2813
+ * Enter description here...
2814
+ *
2815
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2816
+ */
2817
+ public function removeClass($className) {
2818
+ foreach($this->stack(1) as $node) {
2819
+ $classes = explode( ' ', $node->getAttribute('class'));
2820
+ if ( in_array($className, $classes)) {
2821
+ $classes = array_diff($classes, array($className));
2822
+ if ( $classes )
2823
+ $node->setAttribute('class', implode(' ', $classes));
2824
+ else
2825
+ $node->removeAttribute('class');
2826
+ }
2827
+ }
2828
+ return $this;
2829
+ }
2830
+ /**
2831
+ * Enter description here...
2832
+ *
2833
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2834
+ */
2835
+ public function toggleClass($className) {
2836
+ foreach($this->stack(1) as $node) {
2837
+ if ( $this->is( $node, '.'.$className ))
2838
+ $this->removeClass($className);
2839
+ else
2840
+ $this->addClass($className);
2841
+ }
2842
+ return $this;
2843
+ }
2844
+ /**
2845
+ * Proper name without underscore (just ->empty()) also works.
2846
+ *
2847
+ * Removes all child nodes from the set of matched elements.
2848
+ *
2849
+ * Example:
2850
+ * pq("p")._empty()
2851
+ *
2852
+ * HTML:
2853
+ * <p>Hello, <span>Person</span> <a href="#">and person</a></p>
2854
+ *
2855
+ * Result:
2856
+ * [ <p></p> ]
2857
+ *
2858
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2859
+ * @access private
2860
+ */
2861
+ public function _empty() {
2862
+ foreach($this->stack(1) as $node) {
2863
+ // thx to 'dave at dgx dot cz'
2864
+ $node->nodeValue = '';
2865
+ }
2866
+ return $this;
2867
+ }
2868
+ /**
2869
+ * Enter description here...
2870
+ *
2871
+ * @param array|string $callback Expects $node as first param, $index as second
2872
+ * @param array $scope External variables passed to callback. Use compact('varName1', 'varName2'...) and extract($scope)
2873
+ * @param array $arg1 Will ba passed as third and futher args to callback.
2874
+ * @param array $arg2 Will ba passed as fourth and futher args to callback, and so on...
2875
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2876
+ */
2877
+ public function each($callback, $param1 = null, $param2 = null, $param3 = null) {
2878
+ $paramStructure = null;
2879
+ if (func_num_args() > 1) {
2880
+ $paramStructure = func_get_args();
2881
+ $paramStructure = array_slice($paramStructure, 1);
2882
+ }
2883
+ foreach($this->elements as $v)
2884
+ phpQuery::callbackRun($callback, array($v), $paramStructure);
2885
+ return $this;
2886
+ }
2887
+ /**
2888
+ * Run callback on actual object.
2889
+ *
2890
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2891
+ */
2892
+ public function callback($callback, $param1 = null, $param2 = null, $param3 = null) {
2893
+ $params = func_get_args();
2894
+ $params[0] = $this;
2895
+ phpQuery::callbackRun($callback, $params);
2896
+ return $this;
2897
+ }
2898
+ /**
2899
+ * Enter description here...
2900
+ *
2901
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2902
+ * @todo add $scope and $args as in each() ???
2903
+ */
2904
+ public function map($callback, $param1 = null, $param2 = null, $param3 = null) {
2905
+ // $stack = array();
2906
+ //// foreach($this->newInstance() as $node) {
2907
+ // foreach($this->newInstance() as $node) {
2908
+ // $result = call_user_func($callback, $node);
2909
+ // if ($result)
2910
+ // $stack[] = $result;
2911
+ // }
2912
+ $params = func_get_args();
2913
+ array_unshift($params, $this->elements);
2914
+ return $this->newInstance(
2915
+ call_user_func_array(array('phpQuery', 'map'), $params)
2916
+ // phpQuery::map($this->elements, $callback)
2917
+ );
2918
+ }
2919
+ /**
2920
+ * Enter description here...
2921
+ *
2922
+ * @param <type> $key
2923
+ * @param <type> $value
2924
+ */
2925
+ public function data($key, $value = null) {
2926
+ if (! isset($value)) {
2927
+ // TODO? implement specific jQuery behavior od returning parent values
2928
+ // is child which we look up doesn't exist
2929
+ return phpQuery::data($this->get(0), $key, $value, $this->getDocumentID());
2930
+ } else {
2931
+ foreach($this as $node)
2932
+ phpQuery::data($node, $key, $value, $this->getDocumentID());
2933
+ return $this;
2934
+ }
2935
+ }
2936
+ /**
2937
+ * Enter description here...
2938
+ *
2939
+ * @param <type> $key
2940
+ */
2941
+ public function removeData($key) {
2942
+ foreach($this as $node)
2943
+ phpQuery::removeData($node, $key, $this->getDocumentID());
2944
+ return $this;
2945
+ }
2946
+ // INTERFACE IMPLEMENTATIONS
2947
+
2948
+ // ITERATOR INTERFACE
2949
+ /**
2950
+ * @access private
2951
+ */
2952
+ public function rewind(){
2953
+ $this->debug('iterating foreach');
2954
+ // phpQuery::selectDocument($this->getDocumentID());
2955
+ $this->elementsBackup = $this->elements;
2956
+ $this->elementsInterator = $this->elements;
2957
+ $this->valid = isset( $this->elements[0] )
2958
+ ? 1 : 0;
2959
+ // $this->elements = $this->valid
2960
+ // ? array($this->elements[0])
2961
+ // : array();
2962
+ $this->current = 0;
2963
+ }
2964
+ /**
2965
+ * @access private
2966
+ */
2967
+ public function current(){
2968
+ return $this->elementsInterator[ $this->current ];
2969
+ }
2970
+ /**
2971
+ * @access private
2972
+ */
2973
+ public function key(){
2974
+ return $this->current;
2975
+ }
2976
+ /**
2977
+ * Double-function method.
2978
+ *
2979
+ * First: main iterator interface method.
2980
+ * Second: Returning next sibling, alias for _next().
2981
+ *
2982
+ * Proper functionality is choosed automagicaly.
2983
+ *
2984
+ * @see phpQueryObject::_next()
2985
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
2986
+ */
2987
+ public function next($cssSelector = null){
2988
+ // if ($cssSelector || $this->valid)
2989
+ // return $this->_next($cssSelector);
2990
+ $this->valid = isset( $this->elementsInterator[ $this->current+1 ] )
2991
+ ? true
2992
+ : false;
2993
+ if (! $this->valid && $this->elementsInterator) {
2994
+ $this->elementsInterator = null;
2995
+ } else if ($this->valid) {
2996
+ $this->current++;
2997
+ } else {
2998
+ return $this->_next($cssSelector);
2999
+ }
3000
+ }
3001
+ /**
3002
+ * @access private
3003
+ */
3004
+ public function valid(){
3005
+ return $this->valid;
3006
+ }
3007
+ // ITERATOR INTERFACE END
3008
+ // ARRAYACCESS INTERFACE
3009
+ /**
3010
+ * @access private
3011
+ */
3012
+ public function offsetExists($offset) {
3013
+ return $this->find($offset)->size() > 0;
3014
+ }
3015
+ /**
3016
+ * @access private
3017
+ */
3018
+ public function offsetGet($offset) {
3019
+ return $this->find($offset);
3020
+ }
3021
+ /**
3022
+ * @access private
3023
+ */
3024
+ public function offsetSet($offset, $value) {
3025
+ // $this->find($offset)->replaceWith($value);
3026
+ $this->find($offset)->html($value);
3027
+ }
3028
+ /**
3029
+ * @access private
3030
+ */
3031
+ public function offsetUnset($offset) {
3032
+ // empty
3033
+ throw new Exception("Can't do unset, use array interface only for calling queries and replacing HTML.");
3034
+ }
3035
+ // ARRAYACCESS INTERFACE END
3036
+ /**
3037
+ * Returns node's XPath.
3038
+ *
3039
+ * @param unknown_type $oneNode
3040
+ * @return string
3041
+ * @TODO use native getNodePath is avaible
3042
+ * @access private
3043
+ */
3044
+ protected function getNodeXpath($oneNode = null, $namespace = null) {
3045
+ $return = array();
3046
+ $loop = $oneNode
3047
+ ? array($oneNode)
3048
+ : $this->elements;
3049
+ // if ($namespace)
3050
+ // $namespace .= ':';
3051
+ foreach($loop as $node) {
3052
+ if ($node instanceof DOMDOCUMENT) {
3053
+ $return[] = '';
3054
+ continue;
3055
+ }
3056
+ $xpath = array();
3057
+ while(! ($node instanceof DOMDOCUMENT)) {
3058
+ $i = 1;
3059
+ $sibling = $node;
3060
+ while($sibling->previousSibling) {
3061
+ $sibling = $sibling->previousSibling;
3062
+ $isElement = $sibling instanceof DOMELEMENT;
3063
+ if ($isElement && $sibling->tagName == $node->tagName)
3064
+ $i++;
3065
+ }
3066
+ $xpath[] = $this->isXML()
3067
+ ? "*[local-name()='{$node->tagName}'][{$i}]"
3068
+ : "{$node->tagName}[{$i}]";
3069
+ $node = $node->parentNode;
3070
+ }
3071
+ $xpath = join('/', array_reverse($xpath));
3072
+ $return[] = '/'.$xpath;
3073
+ }
3074
+ return $oneNode
3075
+ ? $return[0]
3076
+ : $return;
3077
+ }
3078
+ // HELPERS
3079
+ public function whois($oneNode = null) {
3080
+ $return = array();
3081
+ $loop = $oneNode
3082
+ ? array( $oneNode )
3083
+ : $this->elements;
3084
+ foreach($loop as $node) {
3085
+ if (isset($node->tagName)) {
3086
+ $tag = in_array($node->tagName, array('php', 'js'))
3087
+ ? strtoupper($node->tagName)
3088
+ : $node->tagName;
3089
+ $return[] = $tag
3090
+ .($node->getAttribute('id')
3091
+ ? '#'.$node->getAttribute('id'):'')
3092
+ .($node->getAttribute('class')
3093
+ ? '.'.join('.', split(' ', $node->getAttribute('class'))):'')
3094
+ .($node->getAttribute('name')
3095
+ ? '[name="'.$node->getAttribute('name').'"]':'')
3096
+ .($node->getAttribute('value') && strpos($node->getAttribute('value'), '<'.'?php') === false
3097
+ ? '[value="'.substr(str_replace("\n", '', $node->getAttribute('value')), 0, 15).'"]':'')
3098
+ .($node->getAttribute('value') && strpos($node->getAttribute('value'), '<'.'?php') !== false
3099
+ ? '[value=PHP]':'')
3100
+ .($node->getAttribute('selected')
3101
+ ? '[selected]':'')
3102
+ .($node->getAttribute('checked')
3103
+ ? '[checked]':'')
3104
+ ;
3105
+ } else if ($node instanceof DOMTEXT) {
3106
+ if (trim($node->textContent))
3107
+ $return[] = 'Text:'.substr(str_replace("\n", ' ', $node->textContent), 0, 15);
3108
+ } else {
3109
+
3110
+ }
3111
+ }
3112
+ return $oneNode && isset($return[0])
3113
+ ? $return[0]
3114
+ : $return;
3115
+ }
3116
+ /**
3117
+ * Dump htmlOuter and preserve chain. Usefull for debugging.
3118
+ *
3119
+ * @return phpQueryObject|QueryTemplatesSource|QueryTemplatesParse|QueryTemplatesSourceQuery
3120
+ *
3121
+ */
3122
+ public function dump() {
3123
+ print 'DUMP #'.(phpQuery::$dumpCount++).' ';
3124
+ $debug = phpQuery::$debug;
3125
+ phpQuery::$debug = false;
3126
+ // print __FILE__.':'.__LINE__."\n";
3127
+ var_dump($this->htmlOuter());
3128
+ return $this;
3129
+ }
3130
+ public function dumpWhois() {
3131
+ print 'DUMP #'.(phpQuery::$dumpCount++).' ';
3132
+ $debug = phpQuery::$debug;
3133
+ phpQuery::$debug = false;
3134
+ // print __FILE__.':'.__LINE__."\n";
3135
+ var_dump('whois', $this->whois());
3136
+ phpQuery::$debug = $debug;
3137
+ return $this;
3138
+ }
3139
+ public function dumpLength() {
3140
+ print 'DUMP #'.(phpQuery::$dumpCount++).' ';
3141
+ $debug = phpQuery::$debug;
3142
+ phpQuery::$debug = false;
3143
+ // print __FILE__.':'.__LINE__."\n";
3144
+ var_dump('length', $this->length());
3145
+ phpQuery::$debug = $debug;
3146
+ return $this;
3147
+ }
3148
+ public function dumpTree($html = true, $title = true) {
3149
+ $output = $title
3150
+ ? 'DUMP #'.(phpQuery::$dumpCount++)." \n" : '';
3151
+ $debug = phpQuery::$debug;
3152
+ phpQuery::$debug = false;
3153
+ foreach($this->stack() as $node)
3154
+ $output .= $this->__dumpTree($node);
3155
+ phpQuery::$debug = $debug;
3156
+ print $html
3157
+ ? nl2br(str_replace(' ', '&nbsp;', $output))
3158
+ : $output;
3159
+ return $this;
3160
+ }
3161
+ private function __dumpTree($node, $intend = 0) {
3162
+ $whois = $this->whois($node);
3163
+ $return = '';
3164
+ if ($whois)
3165
+ $return .= str_repeat(' - ', $intend).$whois."\n";
3166
+ if (isset($node->childNodes))
3167
+ foreach($node->childNodes as $chNode)
3168
+ $return .= $this->__dumpTree($chNode, $intend+1);
3169
+ return $return;
3170
+ }
3171
+ /**
3172
+ * Dump htmlOuter and stop script execution. Usefull for debugging.
3173
+ *
3174
+ */
3175
+ public function dumpDie() {
3176
+ print __FILE__.':'.__LINE__;
3177
+ var_dump($this->htmlOuter());
3178
+ die();
3179
+ }
3180
+ }
includes/phpQuery/phpQuery/plugins/Scripts.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * phpQuery plugin class extending phpQuery object.
4
+ * Methods from this class are callable on every phpQuery object.
5
+ *
6
+ * Class name prefix 'phpQueryObjectPlugin_' must be preserved.
7
+ */
8
+ abstract class phpQueryObjectPlugin_Scripts {
9
+ /**
10
+ * Limit binded methods.
11
+ *
12
+ * null means all public.
13
+ * array means only specified ones.
14
+ *
15
+ * @var array|null
16
+ */
17
+ public static $phpQueryMethods = null;
18
+ public static $config = array();
19
+ /**
20
+ * Enter description here...
21
+ *
22
+ * @param phpQueryObject $self
23
+ */
24
+ public static function script($self, $arg1) {
25
+ $params = func_get_args();
26
+ $params = array_slice($params, 2);
27
+ $return = null;
28
+ $config = self::$config;
29
+ if (phpQueryPlugin_Scripts::$scriptMethods[$arg1]) {
30
+ phpQuery::callbackRun(
31
+ phpQueryPlugin_Scripts::$scriptMethods[$arg1],
32
+ array($self, $params, &$return, $config)
33
+ );
34
+ } else if ($arg1 != '__config' && file_exists(dirname(__FILE__)."/Scripts/$arg1.php")) {
35
+ phpQuery::debug("Loading script '$arg1'");
36
+ require dirname(__FILE__)."/Scripts/$arg1.php";
37
+ } else {
38
+ phpQuery::debug("Requested script '$arg1' doesn't exist");
39
+ }
40
+ return $return
41
+ ? $return
42
+ : $self;
43
+ }
44
+ }
45
+ abstract class phpQueryPlugin_Scripts {
46
+ public static $scriptMethods = array();
47
+ public static function __initialize() {
48
+ if (file_exists(dirname(__FILE__)."/Scripts/__config.php")) {
49
+ include dirname(__FILE__)."/Scripts/__config.php";
50
+ phpQueryObjectPlugin_Scripts::$config = $config;
51
+ }
52
+ }
53
+ /**
54
+ * Extend scripts' namespace with $name related with $callback.
55
+ *
56
+ * Callback parameter order looks like this:
57
+ * - $this
58
+ * - $params
59
+ * - &$return
60
+ * - $config
61
+ *
62
+ * @param $name
63
+ * @param $callback
64
+ * @return bool
65
+ */
66
+ public static function script($name, $callback) {
67
+ if (phpQueryPlugin_Scripts::$scriptMethods[$name])
68
+ throw new Exception("Script name conflict - '$name'");
69
+ phpQueryPlugin_Scripts::$scriptMethods[$name] = $callback;
70
+ }
71
+ }
72
+ ?>
includes/phpQuery/phpQuery/plugins/Scripts/__config.example.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file hosts config for Scripts plugin.
4
+ *
5
+ * To active this file, selete '.example' from filename.
6
+ */
7
+ $config = array(
8
+ 'google_login' => array('login@mail', 'password'),
9
+ );
10
+ ?>
includes/phpQuery/phpQuery/plugins/Scripts/example.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Example script for phpQuery Script plugin
4
+ *
5
+ * Avaible are 4 variables:
6
+ * - $self Represents $this
7
+ * - $params Represents parameters passed to script() method (without script name)
8
+ * - $return If not null, will be used as method result
9
+ * - $config Content of __config.php file
10
+ *
11
+ * By default each script returns $self aka $this.
12
+ */
13
+ $return = $self->find($params[0]);
14
+ ?>
includes/phpQuery/phpQuery/plugins/Scripts/fix_webroot.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $selector = 'img[src], link[href], script[src]';
3
+ $filter = ':not([href^=<?php])'
4
+ .':not([src^=<?php])'
5
+ .':not([href^=http://])'
6
+ .':not([src^=http://])'
7
+ .':not([src^=/])';
8
+ foreach($self[$selector]->filter($filter) as $el) {
9
+ $el = pq($el, $self->getDocumentID());
10
+ // imgs and scripts
11
+ if ( $el->is('img') || $el->is('script') )
12
+ $el->attr('src', $params[0].$el->attr('src'));
13
+ // css
14
+ if ( $el->is('link') )
15
+ $el->attr('href', $params[0].$el->attr('href'));
16
+ }
includes/phpQuery/phpQuery/plugins/Scripts/google_login.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Automated google account login.
4
+ * Uses __config.php to keep login data.
5
+ *
6
+ * @package phpQuery.Plugins.Scripts
7
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
8
+ */
9
+ phpQuery::ajaxAllowHost(
10
+ 'code.google.com',
11
+ 'google.com', 'www.google.com',
12
+ 'mail.google.com',
13
+ 'docs.google.com',
14
+ 'reader.google.com'
15
+ );
16
+ if (! function_exists('ndfasui8923')) {
17
+ function ndfasui8923($browser, $scope) {
18
+ extract($scope);
19
+ $browser
20
+ ->WebBrowser()
21
+ ->find('#Email')
22
+ ->val($config['google_login'][0])->end()
23
+ ->find('#Passwd')
24
+ ->val($config['google_login'][1])
25
+ ->parents('form')
26
+ ->submit();
27
+ }
28
+ $ndfasui8923 = new Callback('ndfasui8923', new CallbackParam, compact(
29
+ 'config', 'self', 'return', 'params'
30
+ ));
31
+ }
32
+ phpQuery::plugin('WebBrowser');
33
+ $self->document->xhr = phpQuery::$plugins->browserGet(
34
+ 'https://www.google.com/accounts/Login',
35
+ $ndfasui8923
36
+ );
37
+ //$self->document->xhr = phpQuery::$plugins->browserGet('https://www.google.com/accounts/Login', create_function('$browser', "
38
+ // \$browser
39
+ // ->WebBrowser()
40
+ // ->find('#Email')
41
+ // ->val('{$config['google_login'][0]}')->end()
42
+ // ->find('#Passwd')
43
+ // ->val('".str_replace("'", "\\'", $config['google_login'][1])."')
44
+ // ->parents('form')
45
+ // ->submit();"
46
+ //));
47
+ ?>
includes/phpQuery/phpQuery/plugins/Scripts/print_source.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Script outputs document markup and changes HTML special chars to entities.
4
+ *
5
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
6
+ */
7
+ /** @var phpQueryObject */
8
+ $self = $self;
9
+ $return = htmlspecialchars($self);
includes/phpQuery/phpQuery/plugins/Scripts/print_websafe.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Script makes content safe for printing as web page and not redirecting client.
4
+ *
5
+ * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com>
6
+ */
7
+ /** @var phpQueryObject */
8
+ $self = $self;
9
+ $self
10
+ ->find('script')
11
+ ->add('meta[http-equiv=refresh]')
12
+ ->add('meta[http-equiv=Refresh]')
13
+ ->remove();
includes/phpQuery/phpQuery/plugins/WebBrowser.php ADDED
@@ -0,0 +1,405 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WebBrowser plugin.
4
+ *
5
+ */
6
+ class phpQueryObjectPlugin_WebBrowser {
7
+ /**
8
+ * Limit binded methods to specified ones.
9
+ *
10
+ * @var array
11
+ */
12
+ public static $phpQueryMethods = null;
13
+ /**
14
+ * Enter description here...
15
+ *
16
+ * @param phpQueryObject $self
17
+ * @todo support 'reset' event
18
+ */
19
+ public static function WebBrowser($self, $callback = null, $location = null) {
20
+ $self = $self->_clone()->toRoot();
21
+ $location = $location
22
+ ? $location
23
+ // TODO use document.location
24
+ : $self->document->xhr->getUri(true);
25
+ // FIXME tmp
26
+ $self->document->WebBrowserCallback = $callback;
27
+ if (! $location)
28
+ throw new Exception('Location needed to activate WebBrowser plugin !');
29
+ else {
30
+ $self->bind('click', array($location, $callback), array('phpQueryPlugin_WebBrowser', 'hadleClick'));
31
+ $self->bind('submit', array($location, $callback), array('phpQueryPlugin_WebBrowser', 'handleSubmit'));
32
+ }
33
+ }
34
+ public static function browser($self, $callback = null, $location = null) {
35
+ return $self->WebBrowser($callback, $location);
36
+ }
37
+ public static function downloadTo($self, $dir = null, $filename = null) {
38
+ $url = null;
39
+ if ($self->is('a[href]'))
40
+ $url = $self->attr('href');
41
+ else if ($self->find('a')->length)
42
+ $url = $self->find('a')->attr('href');
43
+ if ($url) {
44
+ $url = resolve_url($self->document->location, $url);
45
+ if (! $dir)
46
+ $dir = getcwd();
47
+ // TODO resolv name from response headers
48
+ if (! $filename) {
49
+ $matches = null;
50
+ preg_match('@/([^/]+)$@', $url, $matches);
51
+ $filename = $matches[1];
52
+ }
53
+ //print $url;
54
+ $path = rtrim($dir, '/').'/'.$filename;
55
+ phpQuery::debug("Requesting download of $url\n");
56
+ // TODO use AJAX instead of file_get_contents
57
+ file_put_contents($path, file_get_contents($url));
58
+ }
59
+ return $self;
60
+ }
61
+ /**
62
+ * Method changing browser location.
63
+ * Fires callback registered with WebBrowser(), if any.
64
+ * @param $self
65
+ * @param $url
66
+ * @return unknown_type
67
+ */
68
+ public static function location($self, $url = null) {
69
+ // TODO if ! $url return actual location ???
70
+ $xhr = isset($self->document->xhr)
71
+ ? $self->document->xhr
72
+ : null;
73
+ $xhr = phpQuery::ajax(array(
74
+ 'url' => $url,
75
+ ), $xhr);
76
+ $return = false;
77
+ if ($xhr->getLastResponse()->isSuccessful()) {
78
+ $return = phpQueryPlugin_WebBrowser::browserReceive($xhr);
79
+ if (isset($self->document->WebBrowserCallback))
80
+ phpQuery::callbackRun(
81
+ $self->document->WebBrowserCallback,
82
+ array($return)
83
+ );
84
+ }
85
+ return $return;
86
+ }
87
+ }
88
+ class phpQueryPlugin_WebBrowser {
89
+ /**
90
+ *
91
+ * @param $url
92
+ * @param $callback
93
+ * @param $param1
94
+ * @param $param2
95
+ * @param $param3
96
+ * @return Zend_Http_Client
97
+ */
98
+ public static function browserGet($url, $callback,
99
+ $param1 = null, $param2 = null, $param3 = null) {
100
+ phpQuery::debug("[WebBrowser] GET: $url");
101
+ self::authorizeHost($url);
102
+ $xhr = phpQuery::ajax(array(
103
+ 'type' => 'GET',
104
+ 'url' => $url,
105
+ 'dataType' => 'html',
106
+ ));
107
+ $paramStructure = null;
108
+ if (func_num_args() > 2) {
109
+ $paramStructure = func_get_args();
110
+ $paramStructure = array_slice($paramStructure, 2);
111
+ }
112
+ if ($xhr->getLastResponse()->isSuccessful()) {
113
+ phpQuery::callbackRun($callback,
114
+ array(self::browserReceive($xhr)->WebBrowser()),
115
+ $paramStructure
116
+ );
117
+ // phpQuery::callbackRun($callback, array(
118
+ // self::browserReceive($xhr)//->WebBrowser($callback)
119
+ // ));
120
+ return $xhr;
121
+ } else {
122
+ throw new Exception("[WebBrowser] GET request failed; url: $url");
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ *
128
+ * @param $url
129
+ * @param $data
130
+ * @param $callback
131
+ * @param $param1
132
+ * @param $param2
133
+ * @param $param3
134
+ * @return Zend_Http_Client
135
+ */
136
+ public static function browserPost($url, $data, $callback,
137
+ $param1 = null, $param2 = null, $param3 = null) {
138
+ self::authorizeHost($url);
139
+ $xhr = phpQuery::ajax(array(
140
+ 'type' => 'POST',
141
+ 'url' => $url,
142
+ 'dataType' => 'html',
143
+ 'data' => $data,
144
+ ));
145
+ $paramStructure = null;
146
+ if (func_num_args() > 3) {
147
+ $paramStructure = func_get_args();
148
+ $paramStructure = array_slice($paramStructure, 3);
149
+ }
150
+ if ($xhr->getLastResponse()->isSuccessful()) {
151
+ phpQuery::callbackRun($callback,
152
+ array(self::browserReceive($xhr)->WebBrowser()),
153
+ $paramStructure
154
+ );
155
+ // phpQuery::callbackRun($callback, array(
156
+ // self::browserReceive($xhr)//->WebBrowser($callback)
157
+ // ));
158
+ return $xhr;
159
+ } else
160
+ return false;
161
+ }
162
+ /**
163
+ *
164
+ * @param $ajaxSettings
165
+ * @param $callback
166
+ * @param $param1
167
+ * @param $param2
168
+ * @param $param3
169
+ * @return Zend_Http_Client
170
+ */
171
+ public static function browser($ajaxSettings, $callback,
172
+ $param1 = null, $param2 = null, $param3 = null) {
173
+ self::authorizeHost($ajaxSettings['url']);
174
+ $xhr = phpQuery::ajax(
175
+ self::ajaxSettingsPrepare($ajaxSettings)
176
+ );
177
+ $paramStructure = null;
178
+ if (func_num_args() > 2) {
179
+ $paramStructure = func_get_args();
180
+ $paramStructure = array_slice($paramStructure, 2);
181
+ }
182
+ if ($xhr->getLastResponse()->isSuccessful()) {
183
+ phpQuery::callbackRun($callback,
184
+ array(self::browserReceive($xhr)->WebBrowser()),
185
+ $paramStructure
186
+ );
187
+ // phpQuery::callbackRun($callback, array(
188
+ // self::browserReceive($xhr)//->WebBrowser($callback)
189
+ // ));
190
+ return $xhr;
191
+ } else
192
+ return false;
193
+ }
194
+ protected static function authorizeHost($url) {
195
+ $host = parse_url($url, PHP_URL_HOST);
196
+ if ($host)
197
+ phpQuery::ajaxAllowHost($host);
198
+ }
199
+ protected static function ajaxSettingsPrepare($settings) {
200
+ unset($settings['success']);
201
+ unset($settings['error']);
202
+ return $settings;
203
+ }
204
+ /**
205
+ * @param Zend_Http_Client $xhr
206
+ */
207
+ public static function browserReceive($xhr) {
208
+ phpQuery::debug("[WebBrowser] Received from ".$xhr->getUri(true));
209
+ // TODO handle meta redirects
210
+ $body = $xhr->getLastResponse()->getBody();
211
+
212
+ // XXX error ???
213
+ if (strpos($body, '<!doctype html>') !== false) {
214
+ $body = '<html>'
215
+ .str_replace('<!doctype html>', '', $body)
216
+ .'</html>';
217
+ }
218
+ $pq = phpQuery::newDocument($body);
219
+ $pq->document->xhr = $xhr;
220
+ $pq->document->location = $xhr->getUri(true);
221
+ $refresh = $pq->find('meta[http-equiv=refresh]')
222
+ ->add('meta[http-equiv=Refresh]');
223
+ if ($refresh->size()) {
224
+ // print htmlspecialchars(var_export($xhr->getCookieJar()->getAllCookies(), true));
225
+ // print htmlspecialchars(var_export($xhr->getLastResponse()->getHeader('Set-Cookie'), true));
226
+ phpQuery::debug("Meta redirect... '{$refresh->attr('content')}'\n");
227
+ // there is a refresh, so get the new url
228
+ $content = $refresh->attr('content');
229
+ $urlRefresh = substr($content, strpos($content, '=')+1);
230
+ $urlRefresh = trim($urlRefresh, '\'"');
231
+ // XXX not secure ?!
232
+ phpQuery::ajaxAllowURL($urlRefresh);
233
+ // $urlRefresh = urldecode($urlRefresh);
234
+ // make ajax call, passing last $xhr object to preserve important stuff
235
+ $xhr = phpQuery::ajax(array(
236
+ 'type' => 'GET',
237
+ 'url' => $urlRefresh,
238
+ 'dataType' => 'html',
239
+ ), $xhr);
240
+ if ($xhr->getLastResponse()->isSuccessful()) {
241
+ // if all is ok, repeat this method...
242
+ return call_user_func_array(
243
+ array('phpQueryPlugin_WebBrowser', 'browserReceive'), array($xhr)
244
+ );
245
+ }
246
+ } else
247
+ return $pq;
248
+ }
249
+ /**
250
+ *
251
+ * @param $e
252
+ * @param $callback
253
+ * @return unknown_type
254
+ */
255
+ public static function hadleClick($e, $callback = null) {
256
+ $node = phpQuery::pq($e->target);
257
+ $type = null;
258
+ if ($node->is('a[href]')) {
259
+ // TODO document.location
260
+ $xhr = isset($node->document->xhr)
261
+ ? $node->document->xhr
262
+ : null;
263
+ $xhr = phpQuery::ajax(array(
264
+ 'url' => resolve_url($e->data[0], $node->attr('href')),
265
+ 'referer' => $node->document->location,
266
+ ), $xhr);
267
+ if ((! $callback || !($callback instanceof Callback)) && $e->data[1])
268
+ $callback = $e->data[1];
269
+ if ($xhr->getLastResponse()->isSuccessful() && $callback)
270
+ phpQuery::callbackRun($callback, array(
271
+ self::browserReceive($xhr)
272
+ ));
273
+ } else if ($node->is(':submit') && $node->parents('form')->size())
274
+ $node->parents('form')->trigger('submit', array($e));
275
+ }
276
+ /**
277
+ * Enter description here...
278
+ *
279
+ * @param unknown_type $e
280
+ * @TODO trigger submit for form after form's submit button has a click event
281
+ */
282
+ public static function handleSubmit($e, $callback = null) {
283
+ $node = phpQuery::pq($e->target);
284
+ if (!$node->is('form') || !$node->is('[action]'))
285
+ return;
286
+ // TODO document.location
287
+ $xhr = isset($node->document->xhr)
288
+ ? $node->document->xhr
289
+ : null;
290
+ $submit = pq($e->relatedTarget)->is(':submit')
291
+ ? $e->relatedTarget
292
+ // will this work ?
293
+ // : $node->find(':submit:first')->get(0);
294
+ : $node->find('*:submit:first')->get(0);
295
+ $data = array();
296
+ foreach($node->serializeArray($submit) as $r)
297
+ // XXXt.c maybe $node->not(':submit')->add($sumit) would be better ?
298
+ // foreach($node->serializeArray($submit) as $r)
299
+ $data[ $r['name'] ] = $r['value'];
300
+ $options = array(
301
+ 'type' => $node->attr('method')
302
+ ? $node->attr('method')
303
+ : 'GET',
304
+ 'url' => resolve_url($e->data[0], $node->attr('action')),
305
+ 'data' => $data,
306
+ 'referer' => $node->document->location,
307
+ // 'success' => $e->data[1],
308
+ );
309
+ if ($node->attr('enctype'))
310
+ $options['contentType'] = $node->attr('enctype');
311
+ $xhr = phpQuery::ajax($options, $xhr);
312
+ if ((! $callback || !($callback instanceof Callback)) && $e->data[1])
313
+ $callback = $e->data[1];
314
+ if ($xhr->getLastResponse()->isSuccessful() && $callback)
315
+ phpQuery::callbackRun($callback, array(
316
+ self::browserReceive($xhr)
317
+ ));
318
+ }
319
+ }
320
+ /**
321
+ *
322
+ * @param unknown_type $parsed
323
+ * @return unknown
324
+ * @link http://www.php.net/manual/en/function.parse-url.php
325
+ * @author stevenlewis at hotmail dot com
326
+ */
327
+ function glue_url($parsed)
328
+ {
329
+ if (! is_array($parsed)) return false;
330
+ $uri = isset($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): '';
331
+ $uri .= isset($parsed['user']) ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':'';
332
+ $uri .= isset($parsed['host']) ? $parsed['host'] : '';
333
+ $uri .= isset($parsed['port']) ? ':'.$parsed['port'] : '';
334
+ if(isset($parsed['path']))
335
+ {
336
+ $uri .= (substr($parsed['path'],0,1) == '/')?$parsed['path']:'/'.$parsed['path'];
337
+ }
338
+ $uri .= isset($parsed['query']) ? '?'.$parsed['query'] : '';
339
+ $uri .= isset($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
340
+ return $uri;
341
+ }
342
+ /**
343
+ * Enter description here...
344
+ *
345
+ * @param unknown_type $base
346
+ * @param unknown_type $url
347
+ * @return unknown
348
+ * @author adrian-php at sixfingeredman dot net
349
+ */
350
+ function resolve_url($base, $url) {
351
+ if (!strlen($base)) return $url;
352
+ // Step 2
353
+ if (!strlen($url)) return $base;
354
+ // Step 3
355
+ if (preg_match('!^[a-z]+:!i', $url)) return $url;
356
+ $base = parse_url($base);
357
+ if ($url{0} == "#") {
358
+ // Step 2 (fragment)
359
+ $base['fragment'] = substr($url, 1);
360
+ return unparse_url($base);
361
+ }
362
+ unset($base['fragment']);
363
+ unset($base['query']);
364
+ if (substr($url, 0, 2) == "//") {
365
+ // Step 4
366
+ return unparse_url(array(
367
+ 'scheme'=>$base['scheme'],
368
+ 'path'=>substr($url,2),
369
+ ));
370
+ } else if ($url{0} == "/") {
371
+ // Step 5
372
+ $base['path'] = $url;
373
+ } else {
374
+ // Step 6
375
+ $path = explode('/', $base['path']);
376
+ $url_path = explode('/', $url);
377
+ // Step 6a: drop file from base
378
+ array_pop($path);
379
+ // Step 6b, 6c, 6e: append url while removing "." and ".." from
380
+ // the directory portion
381
+ $end = array_pop($url_path);
382
+ foreach ($url_path as $segment) {
383
+ if ($segment == '.') {
384
+ // skip
385
+ } else if ($segment == '..' && $path && $path[sizeof($path)-1] != '..') {
386
+ array_pop($path);
387
+ } else {
388
+ $path[] = $segment;
389
+ }
390
+ }
391
+ // Step 6d, 6f: remove "." and ".." from file portion
392
+ if ($end == '.') {
393
+ $path[] = '';
394
+ } else if ($end == '..' && $path && $path[sizeof($path)-1] != '..') {
395
+ $path[sizeof($path)-1] = '';
396
+ } else {
397
+ $path[] = $end;
398
+ }
399
+ // Step 6h
400
+ $base['path'] = join('/', $path);
401
+
402
+ }
403
+ // Step 7
404
+ return glue_url($base);
405
+ }
includes/phpQuery/phpQuery/plugins/example.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Example of phpQuery plugin.
4
+ *
5
+ * Load it like this:
6
+ * phpQuery::plugin('example')
7
+ * phpQuery::plugin('example', 'example.php')
8
+ * pq('ul')->plugin('example')
9
+ * pq('ul')->plugin('example', 'example.php')
10
+ *
11
+ * Plugin classes are never intialized, just method calls are forwarded
12
+ * in static way from phpQuery.
13
+ *
14
+ * Have fun writing plugins :)
15
+ */
16
+
17
+ /**
18
+ * phpQuery plugin class extending phpQuery object.
19
+ * Methods from this class are callable on every phpQuery object.
20
+ *
21
+ * Class name prefix 'phpQueryObjectPlugin_' must be preserved.
22
+ */
23
+ abstract class phpQueryObjectPlugin_example {
24
+ /**
25
+ * Limit binded methods.
26
+ *
27
+ * null means all public.
28
+ * array means only specified ones.
29
+ *
30
+ * @var array|null
31
+ */
32
+ public static $phpQueryMethods = null;
33
+ /**
34
+ * Enter description here...
35
+ *
36
+ * @param phpQueryObject $self
37
+ */
38
+ public static function example($self, $arg1) {
39
+ // this method can be called on any phpQuery object, like this:
40
+ // pq('div')->example('$arg1 Value')
41
+
42
+ // do something
43
+ $self->append('Im just an example !');
44
+ // change stack of result object
45
+ return $self->find('div');
46
+ }
47
+ protected static function helperFunction() {
48
+ // this method WONT be avaible as phpQuery method,
49
+ // because it isn't publicly callable
50
+ }
51
+ }
52
+
53
+ /**
54
+ * phpQuery plugin class extending phpQuery static namespace.
55
+ * Methods from this class are callable as follows:
56
+ * phpQuery::$plugins->staticMethod()
57
+ *
58
+ * Class name prefix 'phpQueryPlugin_' must be preserved.
59
+ */
60
+ abstract class phpQueryPlugin_example {
61
+ /**
62
+ * Limit binded methods.
63
+ *
64
+ * null means all public.
65
+ * array means only specified ones.
66
+ *
67
+ * @var array|null
68
+ */
69
+ public static $phpQueryMethods = null;
70
+ public static function staticMethod() {
71
+ // this method can be called within phpQuery class namespace, like this:
72
+ // phpQuery::$plugins->staticMethod()
73
+ }
74
+ }
75
+ ?>
includes/wp-plugin-dev-classes/class-wp-meta-box-page.php ADDED
@@ -0,0 +1,662 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php defined( 'ABSPATH' ) OR die( 'No direct access.' );
2
+ if ( ! class_exists( 'WP_Meta_Box_Page_01' ) ):
3
+ /**
4
+ * WP_Meta_Box_Page_01 Class
5
+ *
6
+ * Creating a dashboard-like admin page with meta boxes
7
+ *
8
+ * Requires WordPress 3.0+ and PHP 5.2+
9
+ *
10
+ * Custom Actions:
11
+ * - load action params: (1) this object
12
+ * - meta_box_load
13
+ * - meta_box_load-[page_slug]
14
+ *
15
+ * Custom Filters:
16
+ * - page_title filter params: (1) default content, (2) this object
17
+ * - meta_box_page_title
18
+ * - meta_box_page_title-[page_slug]
19
+ *
20
+ * - page_content filter params: (1) default content, (2) this object
21
+ * - meta_box_page_content
22
+ * - meta_box_page_content-[page_slug]
23
+ *
24
+ * - screen_settings filter params: (1) default content, (2) current screen object, (3) this object
25
+ * - meta_box_screen_settings
26
+ * - meta_box_screen_settings-[page_slug]
27
+ *
28
+ * - contextual_help filter params: (1) default content, (2) current screen id, (3) current screen object, (4) this object
29
+ * - meta_box_contextual_help
30
+ * - meta_box_contextual_help-[page_slug]
31
+ *
32
+ * @version 0.1
33
+ * @author Victor Villaverde Laan
34
+ * @link http://www.freelancephp.net/
35
+ * @license Dual licensed under the MIT and GPL licenses
36
+ */
37
+ class WP_Meta_Box_Page_01 {
38
+
39
+ /**
40
+ * Default settings
41
+ * @var array
42
+ */
43
+ private static $default_settings = array(
44
+ // Page title
45
+ 'page_title' => NULL, // Default will be set equal to $menu_title
46
+
47
+ // Menu title
48
+ 'menu_title' => NULL, // Default will be set equal to $page_title
49
+
50
+ // Page slug
51
+ 'page_slug' => NULL, // Default will be set to: sanitize_title_with_dashes( $menu_title )
52
+
53
+ // Default number of columns
54
+ 'default_columns' => 2,
55
+
56
+ // Column widths
57
+ 'column_widths' => array(
58
+ 1 => array( 99 ),
59
+ 2 => array( 49, 49 ),
60
+ 3 => array( 32.33, 32.33, 32.33 ),
61
+ 4 => array( 24, 24, 24, 24 ),
62
+ ),
63
+
64
+ // Add page method
65
+ 'add_page_method' => 'add_options_page', // OR: add_menu_page, add_object_page, add_submenu_page
66
+
67
+ // Extra params for the add_page_method
68
+
69
+ // Capability
70
+ 'capability' => 'manage_options', // Optional for all methods
71
+
72
+ // Parent slug
73
+ 'parent_slug' => NULL, // Nescessary when using "add_submenu_page"
74
+
75
+ // Url to the icon to be used for the menu ( around 20 x 20 pixels )
76
+ 'icon_url' => NULL, // Only for "add_menu_page" or "add_object_page"
77
+
78
+ // The position in the menu order this menu should appear
79
+ 'position' => NULL, // Only for "add_menu_page", default on bottom of the menu
80
+ );
81
+
82
+ /**
83
+ * Settings
84
+ * @var array
85
+ */
86
+ private $settings = array();
87
+
88
+ /**
89
+ * Meta boxes
90
+ * @var array
91
+ */
92
+ private $meta_boxes = array();
93
+
94
+ /**
95
+ * Pagehook ( will be set when page is created )
96
+ * @var string
97
+ */
98
+ protected $pagehook = NULL;
99
+
100
+
101
+ /**
102
+ * Initialize
103
+ * @param array $settings Optional
104
+ */
105
+ public function init( $settings = NULL, $load_callback = NULL ) {
106
+ // get settings of child class
107
+ $child_settings = $this->settings;
108
+
109
+ // set settings in 3 steps...
110
+ // (1) first set the default options
111
+ $this->set_setting( self::$default_settings );
112
+
113
+ // (2) set child settings
114
+ if ( ! empty( $child_settings ) )
115
+ $this->set_setting( $child_settings );
116
+
117
+ // (3) set param settings
118
+ if ( $settings !== NULL )
119
+ $this->set_setting( $settings );
120
+
121
+ // actions
122
+ add_action( 'admin_menu', array( $this, 'call_admin_menu' ) );
123
+
124
+ // add load action
125
+ if ( $load_callback !== NULL )
126
+ add_action( 'meta_box_load-'. $this->get_setting( 'page_slug' ), $load_callback );
127
+ }
128
+
129
+ /**
130
+ * Set default setting value
131
+ * @param mixed $key Also possible to give an array of key/value pairs
132
+ * @param mixed $value Optional
133
+ * @static
134
+ */
135
+ public static function set_default_setting( $key, $value = NULL ) {
136
+ if ( is_array( $key ) ) {
137
+ foreach ( $key AS $k => $v )
138
+ self::set_default_setting( $k, $v );
139
+ } else {
140
+ self::$default_settings[ $key ] = $value;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Set setting value
146
+ * @param mixed $key Also possible to give an array of key/value pairs
147
+ * @param mixed $value Optional
148
+ * @return $this For chaining
149
+ */
150
+ public function set_setting( $key, $value = NULL ) {
151
+ if ( is_array( $key ) ) {
152
+ foreach ( $key AS $k => $v )
153
+ $this->set_setting( $k, $v );
154
+ } else {
155
+ $this->settings[ $key ] = $value;
156
+ }
157
+
158
+ // auto-set related prop values
159
+ if ( $value !== NULL ) {
160
+ if ( $key == 'menu_title' AND $this->get_setting( 'page_title' ) === NULL )
161
+ $this->set_setting( 'page_title', $value );
162
+
163
+ if ( $key == 'page_title' AND $this->get_setting( 'menu_title' ) === NULL )
164
+ $this->set_setting( 'menu_title', $value );
165
+
166
+ if ( ( $key == 'menu_title' OR $key == 'page_title' ) AND $this->get_setting( 'page_slug' ) === NULL ) {
167
+ $new_val = $value;
168
+ $new_val = sanitize_title_with_dashes( $new_val );
169
+ $new_val = strtolower( $new_val );
170
+
171
+ // check for valid page_slug
172
+ if ( ! preg_match( '/^[a-z_-]+$/', $new_val ) ) {
173
+ $new_val = str_replace(
174
+ array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ),
175
+ array( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ),
176
+ $new_val
177
+ );
178
+
179
+ $new_val = ereg_replace( '[^a-z_-]', '', $new_val );
180
+ }
181
+
182
+ $this->set_setting( 'page_slug', $new_val );
183
+ }
184
+ }
185
+
186
+ return $this;
187
+ }
188
+
189
+ /**
190
+ * Get setting value
191
+ * @param string $key Optional, when NULL will return array of all options
192
+ * @param mixed $default Optional, return default when key cannot be found OR is NULL
193
+ * @return mixed
194
+ */
195
+ public function get_setting( $key = NULL, $default = NULL ) {
196
+ if ( $key === NULL )
197
+ return $this->settings;
198
+
199
+ if ( key_exists( $key, $this->settings ) )
200
+ return ( $this->settings[ $key ] === NULL ) ? $default : $this->settings[ $key ];
201
+
202
+ return $default;
203
+ }
204
+
205
+ /**
206
+ * Helper for adding a meta box
207
+ * @param string $title Title of the meta box
208
+ * @param string $callback Callback for the meta box content
209
+ * @param mixed $context Optional, add meta box to this column (normal = 1, side = 2, column3 = 3, column4 = 4)
210
+ * @param string $priority Optional, the priority within the context where the boxes should show ( 'high', 'core', 'default' or 'low' )
211
+ * @return $this For chaining
212
+ */
213
+ public function add_meta_box( $title, $callback, $context = 'normal', $id = NULL, $priority = 'default' ) {
214
+ $this->meta_boxes[] = array(
215
+ 'id' => $id,
216
+ 'title' => $title,
217
+ 'callback' => $callback,
218
+ 'context' => $context,
219
+ 'priority' => $priority,
220
+ );
221
+
222
+ return $this;
223
+ }
224
+
225
+ /**
226
+ * Add callback to "meta_box_load-[page]" action, only applied for this page/object
227
+ * @param mixed $callback Callback function
228
+ * @return $this
229
+ */
230
+ public function add_load_action( $callback ) {
231
+ add_filter( 'meta_box_load-' . $this->get_setting( 'page_slug' ), $callback );
232
+ return $this;
233
+ }
234
+
235
+ /**
236
+ * Add callback to "meta_box_load" action, applied to all instances of this class
237
+ * @param mixed $callback Callback function
238
+ * @static
239
+ */
240
+ public static function add_global_load_action( $callback ) {
241
+ add_filter( 'meta_box_load', $callback );
242
+ }
243
+
244
+ /**
245
+ * Add callback to "meta_box_screen_settings-[page]" filter, only applied for this page/object
246
+ * @param mixed $callback Callback function
247
+ * @return $this
248
+ */
249
+ public function add_screen_settings_filter( $callback ) {
250
+ add_filter( 'meta_box_screen_settings-' . $this->get_setting( 'page_slug' ), $callback );
251
+ return $this;
252
+ }
253
+
254
+ /**
255
+ * Add callback to "meta_box_contextual_help-[page]" filter, only applied for this page/object
256
+ * @param mixed $callback Callback function
257
+ * @return $this
258
+ */
259
+ public function add_contextual_help_filter( $callback ) {
260
+ add_filter( 'meta_box_contextual_help-' . $this->get_setting( 'page_slug' ), $callback );
261
+ return $this;
262
+ }
263
+
264
+ /**
265
+ * Add callback to "meta_box_page_title-[page]" filter, only applied for this page/object
266
+ * @param mixed $callback Callback function
267
+ * @return $this
268
+ */
269
+ public function add_title_filter( $callback ) {
270
+ add_filter( 'meta_box_page_title-' . $this->get_setting( 'page_slug' ), $callback );
271
+ return $this;
272
+ }
273
+
274
+ /**
275
+ * Add callback to "meta_box_page_content" filter, applied to all instances of this class
276
+ * @param mixed $callback Callback function
277
+ * @static
278
+ */
279
+ public static function add_global_title_filter( $callback ) {
280
+ add_filter( 'meta_box_page_title', $callback );
281
+ }
282
+
283
+ /**
284
+ * Add callback to "meta_box_page_content-[page]" filter, only applied for this page/object
285
+ * @param mixed $callback Callback function
286
+ * @return $this
287
+ */
288
+ public function add_content_filter( $callback ) {
289
+ add_filter( 'meta_box_page_title-' . $this->get_setting( 'page_slug' ), $callback );
290
+ return $this;
291
+ }
292
+
293
+ /**
294
+ * Add callback to "meta_box_page_content" filter, applied to all instances of this class
295
+ * @param mixed $callback Callback function
296
+ * @static
297
+ */
298
+ public static function add_global_content_filter( $callback ) {
299
+ add_filter( 'meta_box_page_title', $callback );
300
+ }
301
+
302
+ /**
303
+ * Admin menu callback
304
+ */
305
+ public function call_admin_menu() {
306
+ // add page
307
+ switch ( $this->get_setting( 'add_page_method' ) ) {
308
+ case 'add_menu_page':
309
+ $this->pagehook = add_menu_page(
310
+ $this->get_setting( 'page_title' ),
311
+ $this->get_setting( 'menu_title' ),
312
+ $this->get_setting( 'capability' ),
313
+ $this->get_setting( 'page_slug' ),
314
+ array( $this, 'call_page_content' ),
315
+ $this->get_setting( 'icon_url' ),
316
+ $this->get_setting( 'position' )
317
+ );
318
+ break;
319
+
320
+ case 'add_object_page':
321
+ $this->pagehook = add_object_page(
322
+ $this->get_setting( 'page_title' ),
323
+ $this->get_setting( 'menu_title' ),
324
+ $this->get_setting( 'capability' ),
325
+ $this->get_setting( 'page_slug' ),
326
+ array( $this, 'call_page_content' ),
327
+ $this->get_setting( 'icon_url' )
328
+ );
329
+ break;
330
+
331
+ case 'add_submenu_page':
332
+ $this->pagehook = add_submenu_page(
333
+ $this->get_setting( 'parent_slug' ),
334
+ $this->get_setting( 'page_title' ),
335
+ $this->get_setting( 'menu_title' ),
336
+ $this->get_setting( 'capability' ),
337
+ $this->get_setting( 'page_slug' ),
338
+ array( $this, 'call_page_content' )
339
+ );
340
+ break;
341
+
342
+ case 'add_options_page':
343
+ default:
344
+ $this->pagehook = add_options_page(
345
+ $this->get_setting( 'page_title' ),
346
+ $this->get_setting( 'menu_title' ),
347
+ $this->get_setting( 'capability' ),
348
+ $this->get_setting( 'page_slug' ),
349
+ array( $this, 'call_page_content' )
350
+ );
351
+ break;
352
+
353
+ }
354
+
355
+ // execute action
356
+ do_action( 'meta_box_load', $this );
357
+
358
+ // load page
359
+ add_action( 'load-' . $this->pagehook, array( $this, 'call_load_page' ) );
360
+ }
361
+
362
+ /**
363
+ * Admin head callback
364
+ */
365
+ public function call_admin_head() {
366
+ ?>
367
+ <style type="text/css">
368
+ .postbox-container { padding-right:1%; float:left ; /* for WP < 3.1 */ }
369
+ .postbox-container .meta-box-sortables { min-height:200px; }
370
+ .postbox-container .postbox { min-width:0; }
371
+ .postbox-container .postbox .inside { margin:10px 0 ; padding:0 10px; } /* for WP < 3.2 */
372
+ </style>
373
+ <?php
374
+ }
375
+
376
+ /**
377
+ * Load page callback
378
+ */
379
+ public function call_load_page() {
380
+ // execute action
381
+ do_action( 'meta_box_load-' . $this->get_setting( 'page_slug' ), $this );
382
+
383
+ // add script for meta boxes
384
+ wp_enqueue_script( 'postbox' );
385
+
386
+ // add to admin head
387
+ add_action( 'admin_head', array( $this, 'call_admin_head' ) );
388
+
389
+ // add screen settings filter
390
+ add_filter( 'screen_settings', array( $this, 'call_screen_settings') );
391
+
392
+ // add help text
393
+ add_filter( 'contextual_help', array( $this, 'call_contextual_help' ) );
394
+
395
+ // columns
396
+ if ( function_exists( 'add_screen_option' ) ) {
397
+ $count = count( $this->get_setting( 'column_widths' ) );
398
+
399
+ add_screen_option( 'layout_columns', array(
400
+ 'max' => $count,
401
+ 'default' => min( $count, $this->get_setting( 'default_columns' ) )
402
+ ));
403
+ }
404
+
405
+ // add meta boxes
406
+ $nr = 0;
407
+ foreach ( $this->meta_boxes AS $box ) {
408
+ $title = $box[ 'title' ];
409
+ $id = ( isset( $box[ 'id' ] ) ) ? $box[ 'id' ] : sanitize_title_with_dashes( $title .'-'. ++$nr, 'meta-box-' . $nr );
410
+ $callback = ( method_exists( $this, $box[ 'callback' ] ) ) ? array( $this, $box[ 'callback' ] ) : $box[ 'callback' ];
411
+ $context = $box[ 'context' ];
412
+ $priority = $box[ 'priority' ];
413
+
414
+ // set context
415
+ if ( $context == 2 OR strtolower( $context ) == 'side' ) {
416
+ $context = 'side';
417
+ } elseif ( $context == 3 OR strtolower( $context ) == 'column3' ) {
418
+ $context = 'column3';
419
+ } elseif ( $context == 4 OR strtolower( $context ) == 'column4' ) {
420
+ $context = 'column4';
421
+ } else { // default
422
+ $context = 'normal';
423
+ }
424
+
425
+ // add meta box
426
+ add_meta_box( $id, $title, $callback, $this->pagehook, $context, $priority ); // $callback_args, doesn't seem to work
427
+ }
428
+ }
429
+
430
+ /**
431
+ * Screen settings (callback)
432
+ * @param string $content
433
+ * @return string
434
+ */
435
+ public function call_screen_settings( $content ) {
436
+ if ( self::get_current_screen()->id == convert_to_screen( $this->pagehook )->id ) {
437
+ // apply filters for this meta box page
438
+ $content = apply_filters( 'meta_box_screen_settings-' . $this->get_setting( 'page_slug' ), $content, $this->get_current_screen(), $this );
439
+ }
440
+
441
+ return $content;
442
+ }
443
+
444
+ /**
445
+ * Contextual help (callback)
446
+ * @param string $content
447
+ * @return string
448
+ */
449
+ public function call_contextual_help( $content ) {
450
+ $current_screen = $this->get_current_screen();
451
+
452
+ if ( $current_screen->id == convert_to_screen( $this->pagehook )->id ) {
453
+ // apply filters for this meta box page
454
+ $content = apply_filters( 'meta_box_contextual_help-' . $this->get_setting( 'page_slug' ), $content, $current_screen->id, $current_screen, $this );
455
+ }
456
+
457
+ return $content;
458
+ }
459
+
460
+ /**
461
+ * Display admin page content (callback)
462
+ */
463
+ public function call_page_content() {
464
+ echo '<div class="wrap">';
465
+
466
+ // page title
467
+ $meta_boxes_page_title = apply_filters( 'meta_box_page_title', $this->get_page_title(), $this );
468
+ echo apply_filters( 'meta_box_page_title-' . $this->get_setting( 'page_slug' ), $meta_boxes_page_title, $this );
469
+
470
+ // page content
471
+ $meta_boxes_content = apply_filters( 'meta_box_page_content', $this->get_page_content(), $this );
472
+ echo apply_filters( 'meta_box_page_content-' . $this->get_setting( 'page_slug' ), $meta_boxes_content, $this );
473
+
474
+ echo '</div>';
475
+ }
476
+
477
+ /**
478
+ * Get page title
479
+ * Can be changed by using adding filters, see add_title_filter()
480
+ * @return string
481
+ */
482
+ private function get_page_title() {
483
+ return '<h2>' . get_admin_page_title() . '</h2>';
484
+ }
485
+
486
+ /**
487
+ * Get meta boxes content. Can be changed by adding filters, see add_content_filter()
488
+ * @return string
489
+ */
490
+ private function get_page_content() {
491
+ return self::get_ob_callback( array( $this, 'show_meta_boxes' ) );
492
+ }
493
+
494
+ /**
495
+ * Display meta boxes content
496
+ */
497
+ private function show_meta_boxes() {
498
+ $opt_column_widths = $this->get_setting( 'column_widths' );
499
+ $hide2 = $hide3 = $hide4 = '';
500
+ switch ( self::get_screen_layout_columns( $this->get_setting( 'default_columns' ) ) ) {
501
+ case 4:
502
+ $column_widths = $opt_column_widths[ 4 ];
503
+ break;
504
+ case 3:
505
+ $column_widths = $opt_column_widths[ 3 ];
506
+ $hide4 = 'display:none;';
507
+ break;
508
+ case 2:
509
+ $column_widths = $opt_column_widths[ 2 ];
510
+ $hide3 = $hide4 = 'display:none;';
511
+ break;
512
+ default:
513
+ $column_widths = $opt_column_widths[ 1 ];
514
+ $hide2 = $hide3 = $hide4 = 'display:none;';
515
+ }
516
+
517
+ $column_widths = array_pad( $column_widths, 4, 0 );
518
+ ?>
519
+ <div id='<?php echo $this->pagehook ?>-widgets' class='metabox-holder'>
520
+ <div class='postbox-container' style='width:<?php echo $column_widths[0] ?>%'>
521
+ <?php do_meta_boxes( $this->pagehook, 'normal', '' ); ?>
522
+ </div>
523
+
524
+ <div class='postbox-container' style='<?php echo $hide2 ?>width:<?php echo $column_widths[1] ?>%'>
525
+ <?php do_meta_boxes( $this->pagehook, 'side', '' ); ?>
526
+ </div>
527
+
528
+ <div class='postbox-container' style='<?php echo $hide3 ?>width:<?php echo $column_widths[2] ?>%'>
529
+ <?php do_meta_boxes( $this->pagehook, 'column3', '' ); ?>
530
+ </div>
531
+
532
+ <div class='postbox-container' style='<?php echo $hide4 ?>width:<?php echo $column_widths[3] ?>%'>
533
+ <?php do_meta_boxes( $this->pagehook, 'column4', '' ); ?>
534
+ </div>
535
+ </div>
536
+
537
+ <form style="display:none" method="get" action="">
538
+ <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
539
+ <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
540
+ </form>
541
+
542
+ <script type="text/javascript">
543
+ //<![CDATA[
544
+ jQuery( document ).ready( function( $ ){
545
+ var columnWidths = <?php echo json_encode( $opt_column_widths ) ?>,
546
+ $boxes = $( '.postbox-container' ),
547
+ setColumnWidths = function () {
548
+ var c = $( 'input[name="screen_columns"]:checked' ).val();
549
+
550
+ // first hide all boxes
551
+ $boxes.hide();
552
+
553
+ // set width and show boxes
554
+ for ( var x = 0; x < columnWidths[ c ].length; x++ ) {
555
+ $boxes.eq( x )
556
+ .css( 'width', columnWidths[ c ][ x ]+ '%' )
557
+ .show();
558
+ }
559
+ };
560
+
561
+ // radio screen columns
562
+ $( 'input[name="screen_columns"]' )
563
+ .click(function(){
564
+ if ( $( 'input[name="screen_columns"]:checked' ).val() == $( this ).val() ) {
565
+ setTimeout(function(){
566
+ setColumnWidths();
567
+ }, 1 );
568
+ }
569
+ })
570
+ .change(function( e ){
571
+ setColumnWidths();
572
+
573
+ // prevent
574
+ e.stopImmediatePropagation();
575
+ });
576
+
577
+ // trigger change event of selected column
578
+ $( 'input[name="screen_columns"]:checked' ).change();
579
+
580
+ <?php if ( self::wp_version( '3.2', '<' ) ): ?>
581
+ // for WP < 3.2
582
+
583
+ // close postboxes that should be closed
584
+ $( '.if-js-closed' ).removeClass( 'if-js-closed' ).addClass( 'closed' );
585
+
586
+ // Loading saved screen settings
587
+ postboxes.add_postbox_toggles( '<?php echo $this->pagehook ?>' );
588
+ <?php endif; ?>
589
+ });
590
+ //]]>
591
+ </script>
592
+ <?php
593
+ }
594
+
595
+ /**
596
+ * Static helpers
597
+ */
598
+
599
+ /**
600
+ * Get content displayed by given callback
601
+ * @param mixed $callback
602
+ * @return string
603
+ * @static
604
+ */
605
+ public static function get_ob_callback( $callback ) {
606
+ // start output buffer
607
+ ob_start();
608
+
609
+ // call callback
610
+ call_user_func( $callback );
611
+
612
+ // get the view content
613
+ $content = ob_get_contents();
614
+
615
+ // clean output buffer
616
+ ob_end_clean();
617
+
618
+ return $content;
619
+ }
620
+
621
+ /**
622
+ * Get current version of WP or compare versions
623
+ * @global string $wp_version
624
+ * @return mixed
625
+ * @static
626
+ */
627
+ public static function wp_version( $compare_version = NULL, $operator = NULL ) {
628
+ global $wp_version;
629
+ $cur_wp_version = preg_replace( '/-.*$/', '', $wp_version );
630
+
631
+ if ( $compare_version === NULL )
632
+ return $cur_wp_version;
633
+
634
+ // check comparison
635
+ return version_compare( $cur_wp_version, $compare_version, $operator );
636
+ }
637
+
638
+ /**
639
+ * Return global WP value of $screen_layout_columns
640
+ * @global integer $screen_layout_columns
641
+ * @return integer
642
+ * @static
643
+ */
644
+ public static function get_screen_layout_columns( $default = NULL ) {
645
+ global $screen_layout_columns;
646
+ return ( empty( $screen_layout_columns ) ) ? $default : $screen_layout_columns;
647
+ }
648
+
649
+ /**
650
+ * Return global WP value of $current_screen
651
+ * @global string $current_screen
652
+ * @return string
653
+ * @static
654
+ */
655
+ public static function get_current_screen( $default = NULL ) {
656
+ global $current_screen;
657
+ return $current_screen;
658
+ }
659
+
660
+ } // End WP_Meta_Box_Page_01 Class
661
+
662
+ endif;
includes/wp-plugin-dev-classes/class-wp-option-forms.php ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php defined( 'ABSPATH' ) OR die( 'No direct access.' );
2
+ if ( ! class_exists( 'WP_Option_Forms_01' ) ):
3
+ /**
4
+ * WP_Option_Forms_01 Class
5
+ *
6
+ * Simple class for creating option forms of a the same option_group.
7
+ * Also with Ajax save support.
8
+ *
9
+ * Requires WordPress 3.0+ and PHP 5.2+
10
+ *
11
+ * @version 0.1
12
+ * @author Victor Villaverde Laan
13
+ * @link http://www.freelancephp.net/
14
+ * @license Dual licensed under the MIT and GPL licenses
15
+ */
16
+ class WP_Option_Forms_01 {
17
+
18
+ /**
19
+ * Name used as prefix for saving option names
20
+ * @var string
21
+ */
22
+ protected $name = NULL;
23
+
24
+ /**
25
+ * Option names and values
26
+ * @var string
27
+ */
28
+ protected $options = array();
29
+
30
+ /**
31
+ * Current option name
32
+ * @var string
33
+ */
34
+ protected $current_option = NULL;
35
+
36
+
37
+ /**
38
+ * Constructor
39
+ * @param array $name
40
+ * @param array $options Optional
41
+ */
42
+ public function __construct( $name, $options = array() ) {
43
+ $this->name = sanitize_title_with_dashes( $name );
44
+
45
+ // set option names
46
+ foreach ( $options AS $option_name => $values )
47
+ $this->add_option( $option_name, $values );
48
+
49
+ // actions
50
+ add_action( 'wp_ajax_wpof_update_options', array( $this, 'call_wp_ajax' ) );
51
+ add_action( 'admin_menu', array( $this, 'call_admin_menu' ) );
52
+ }
53
+
54
+ /**
55
+ * Admin menu callback
56
+ */
57
+ public function call_admin_menu() {
58
+ // Register settings
59
+ foreach ( $this->options AS $option_name => $values )
60
+ register_setting( $option_name, $option_name );
61
+
62
+ // script
63
+ wp_enqueue_script( 'option-forms', plugins_url( 'wp-option-forms.js', __FILE__ ), array( 'jquery' ), '1.0' );
64
+ }
65
+
66
+ /**
67
+ * Ajax call for saving option values
68
+ */
69
+ public function call_wp_ajax() {
70
+ check_ajax_referer( 'wpof_update_options', 'wpof-nonce' );
71
+
72
+ $option_name = $_POST[ 'ajax_option_name' ];
73
+ $value = NULL;
74
+
75
+ if ( isset( $_POST[ $option_name ] ) )
76
+ $value = $_POST[ $option_name ];
77
+
78
+ if ( ! is_array( $value ) )
79
+ $value = trim( $value );
80
+
81
+ $value = stripslashes_deep( $value );
82
+
83
+ update_option( $option_name, $value );
84
+
85
+ die( '1' );
86
+ }
87
+
88
+ /**
89
+ * Add option (or reset option when already exists)
90
+ * @param string $option_name
91
+ * @param array $default_values Optional
92
+ * @return this
93
+ */
94
+ public function add_option( $option_name, $default_values = array() ) {
95
+ // set values
96
+ $saved_values = get_option( $this->name .'-'. $option_name );
97
+
98
+ if ( empty( $saved_values ) ) {
99
+ foreach ( $default_values AS $key => $value )
100
+ $values[ $key ] = $value;
101
+ } else {
102
+ foreach ( $default_values AS $key => $value )
103
+ $values[ $key ] = '';
104
+
105
+ foreach ( $saved_values AS $key => $value )
106
+ $values[ $key ] = $value;
107
+ }
108
+
109
+ // option and values
110
+ $this->options[ $this->name .'-'. $option_name ] = $values;
111
+ return $this;
112
+ }
113
+
114
+ /**
115
+ * Set current option to use
116
+ * @param string $option_name
117
+ * @return this
118
+ */
119
+ public function set_current_option( $option_name ) {
120
+ $this->current_option = $this->name .'-'. $option_name;
121
+ return $this;
122
+ }
123
+
124
+ /**
125
+ * Get opening form with all nescessary WP fields
126
+ * @param boolean $ajaxSave Optional
127
+ * @param array $attrs Optional
128
+ * @return string
129
+ */
130
+ public function open_form( $ajaxSave = TRUE, $attrs = array() ) {
131
+ // set class for ajax or non-ajax form
132
+ $attrs[ 'class' ] = ( ( $ajaxSave ) ? 'ajax-form' : 'no-ajax-form' )
133
+ . ( ( key_exists( 'class', $attrs ) ) ? ' '. $attrs[ 'class' ] : '' );
134
+
135
+ // show start form
136
+ $html = '';
137
+ $html .= '<form method="post" action="options.php" '. $this->attrs( $attrs ) .'>';
138
+
139
+ if ( $ajaxSave ) {
140
+ $html .= wp_nonce_field( 'wpof_update_options', 'wpof-nonce', FALSE, FALSE );
141
+ $html .= '<input type="hidden" name="action" value="wpof_update_options" />';
142
+ $html .= '<input type="hidden" name="ajax_option_name" value="'. $this->current_option .'" />';
143
+ } else {
144
+ // instead of using settings_fields();
145
+ $html .= '<input type="hidden" name="option_page" value="' . esc_attr( $this->current_option ) . '" />';
146
+ $html .= '<input type="hidden" name="action" value="update" />';
147
+ $html .= wp_nonce_field( $this->current_option . '-options', '_wpnonce', TRUE, FALSE );
148
+ }
149
+
150
+ return $html;
151
+ }
152
+
153
+ /**
154
+ * Get script for saving screen option
155
+ * @param string $option_name
156
+ * @param string $key
157
+ * @return string
158
+ */
159
+ public function open_screen_option( $option_name, $key ) {
160
+ $this->set_current_option( $option_name );
161
+
162
+ $html = '';
163
+ $html .= '<script type="text/javascript">' . "\n";
164
+ $html .= '//<![CDATA[' . "\n";
165
+ $html .= 'jQuery( document ).ready( function( $ ){' . "\n";
166
+ $html .= "\t" . '// save screen option' . "\n";
167
+ $html .= "\t" . '$( "#screen-meta #'. $key .'" )' . "\n";
168
+ $html .= "\t\t" . '.change(function(){' . "\n";
169
+ $html .= "\t\t\t" . 'var self = this;' . "\n";
170
+ $html .= "\t\t\t" . '$.post( ajaxurl, {' . "\n";
171
+ $html .= "\t\t\t\t" . 'action: "wpof_update_options",' . "\n";
172
+ $html .= "\t\t\t\t" . '"wpof-nonce": "'. wp_create_nonce( 'wpof_update_options' ) .'",' . "\n";
173
+ $html .= "\t\t\t\t" . 'ajax_option_name: "'. $this->current_option .'",' . "\n";
174
+ $html .= "\t\t\t\t" . '"'. $this->field_name( $key ) .'": $( this ).val()' . "\n";
175
+ $html .= "\t\t\t" . '}, function () {' . "\n";
176
+ $html .= "\t\t\t\t" . '$( self ).trigger( "ajax_updated" );' . "\n";
177
+ $html .= "\t\t\t" . '});' . "\n";
178
+ $html .= "\t\t" . '});' . "\n";
179
+ $html .= '});' . "\n";
180
+ $html .= '//]]>' . "\n";
181
+ $html .= '</script>' . "\n";
182
+
183
+ return $html;
184
+ }
185
+
186
+ /**
187
+ * Get closing form
188
+ * @return string
189
+ */
190
+ public function close_form() {
191
+ return '</form>';
192
+ }
193
+
194
+ /**
195
+ * Text field
196
+ * @param string $key
197
+ * @param array $attrs Optional
198
+ * @return string
199
+ */
200
+ public function text( $key, $attrs = array() ) {
201
+ if ( ! key_exists( 'class', $attrs ) )
202
+ $attrs[ 'class' ] = 'regular-text';
203
+
204
+ return '<input type="text" '. $this->attrs( $attrs, $key, $this->value( $key ) ) .' />';
205
+ }
206
+
207
+ /**
208
+ * Text field
209
+ * @param string $key
210
+ * @param array $attrs Optional
211
+ * @return string
212
+ */
213
+ public function textarea( $key, $attrs = array() ) {
214
+ if ( ! key_exists( 'class', $attrs ) )
215
+ $attrs[ 'class' ] = 'large-text';
216
+
217
+ return '<textarea '. $this->attrs( $attrs, $key ) .'>'. $this->value( $key ) .'</textarea>';
218
+ }
219
+
220
+ /**
221
+ * Radio field
222
+ * @param string $key
223
+ * @param mixed $value
224
+ * @param array $attrs Optional
225
+ * @return string
226
+ */
227
+ public function radio( $key, $value, $attrs = array() ) {
228
+ $checked = ( $value == $this->value( $key ) ) ? ' checked="checked"' : '';
229
+ return '<input type="radio" '. $this->attrs( $attrs, $key, $value )
230
+ . $checked . ' />';
231
+ }
232
+
233
+ /**
234
+ * Checkbox field
235
+ * @param string $key
236
+ * @param mixed $value
237
+ * @param array $attrs Optional
238
+ * @return string
239
+ */
240
+ public function checkbox( $key, $value, $attrs = array() ) {
241
+ $checked = ( $value == $this->value( $key ) ) ? ' checked="checked"' : '';
242
+ return '<input type="checkbox" '. $this->attrs( $attrs, $key, $value )
243
+ . $checked . ' />';
244
+ }
245
+
246
+ /**
247
+ * Select field
248
+ * @param string $key
249
+ * @param array $options Optional
250
+ * @param array $attrs Optional
251
+ * @return string
252
+ */
253
+ public function select( $key, $options = array(), $attrs = array() ) {
254
+ $html = '<select '. $this->attrs( $attrs, $key, $value ) .'>';
255
+
256
+ foreach ( $options AS $value => $label ) {
257
+ $selected = ( $value == $this->value( $key ) ) ? ' selected="selected"' : '';
258
+ $html .= '<option value="'. $value .'"'. $selected .'>'. $label .'</option>';
259
+ }
260
+
261
+ $html .= '</select>';
262
+ return $html;
263
+ }
264
+
265
+ /**
266
+ * Submit button
267
+ * @param array $attrs Optional
268
+ * @return string
269
+ */
270
+ public function submit( $attrs = array() ) {
271
+ // set class attr
272
+ $attrs[ 'class' ] = 'button-primary'. ( ( key_exists( 'class', $attrs ) ) ? ' '. $attrs[ 'class' ] : '' );
273
+
274
+ // show submit
275
+ $html = '';
276
+ $html .= '<p class="button-controls" style="text-align:right;">';
277
+ $html .= '<img alt="" title="" class="ajax-feedback" src="'. get_bloginfo( 'url' ) .'/wp-admin/images/wpspin_light.gif" style="visibility: hidden;" />';
278
+ $html .= '<input type="submit" '. $this->attrs( $attrs, $key, __( 'Save Changes' ) ) .' />';
279
+ $html .= '</p>';
280
+ return $html;
281
+ }
282
+
283
+ /**
284
+ * Get field name of given key
285
+ * @param string $key
286
+ * @return string
287
+ */
288
+ public function field_name( $key ) {
289
+ return $this->current_option . '[' . $key . ']';
290
+ }
291
+
292
+ /**
293
+ * Get value of given option key
294
+ * @param string $key
295
+ * @param mixed $default_value Optional
296
+ * @param boolean $option_name Optional, search in given option_name instead of the current option
297
+ * @return mixed
298
+ */
299
+ public function value( $key, $default_value = NULL, $option_name = NULL ) {
300
+ if ( $option_name === NULL ) {
301
+ $option = $this->current_option;
302
+ } else {
303
+ $option = $this->name . '-' . $option_name;
304
+ }
305
+
306
+ $values = $this->options[ $option ];
307
+
308
+ return ( is_array( $values ) AND key_exists( $key, $values ) AND $values[ $key ] !== NULL ) ? $values[ $key ] : $default_value;
309
+ }
310
+
311
+ /**
312
+ * Delete and unregister option
313
+ */
314
+ public function delete_options() {
315
+ foreach ( $this->options AS $option_name => $values ) {
316
+ delete_option( $option_name );
317
+ unregister_setting( $option_name, $option_name );
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Get string of given attributes
323
+ * @param array $attrs
324
+ * @param string $key Optional
325
+ * @param mixed $value Optional
326
+ * @return string
327
+ */
328
+ protected function attrs( $attrs, $key = NULL, $value = NULL ) {
329
+ $str = '';
330
+
331
+ // set name, id, value attr
332
+ if ( $key !== NULL ) {
333
+ $str .= 'name="' . $this->field_name( $key ) .'" ';
334
+ if ( ! key_exists( 'id', $attrs ) )
335
+ $str .= 'id="' . $key .'" ';
336
+ }
337
+
338
+ if ( $value !== NULL )
339
+ $str .= 'value="' . $value .'" ';
340
+
341
+ foreach ( $attrs AS $attr => $value )
342
+ $str .= $attr .'="'. $value .'" ';
343
+
344
+ return $str;
345
+ }
346
+
347
+ } // End WP_Option_Forms_01
348
+
349
+ endif;
includes/wp-plugin-dev-classes/wp-option-forms.js ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* WP Option Form */
2
+ jQuery( document ).ready( function( $ ){
3
+
4
+ // save function
5
+ function saveAjaxForm( target ) {
6
+ var $this = $( target ),
7
+ $form = $this.parents( 'form' ),
8
+ vals = $form.serializeArray();
9
+
10
+ // disable button
11
+ $this.attr( 'disabled', true );
12
+
13
+ // show ajax loader
14
+ $form.find( '.ajax-feedback' ).css( 'visibility', 'visible' );
15
+
16
+ // save option values
17
+ $.post( ajaxurl, vals, function ( result ) {
18
+ var $msg = $( '<strong>' ).insertBefore( $this );
19
+
20
+ if ( result == '1' ) {
21
+ $msg.html( 'Saved' );
22
+ } else {
23
+ $msg.html( 'Error: could NOT save.' )
24
+ .css({ color: '#f00' });
25
+ }
26
+
27
+ $msg.css({ margin: '0 5px' })
28
+ .delay( 1000 )
29
+ .fadeOut(function(){
30
+ $( this ).remove();
31
+ });
32
+
33
+ // enable button
34
+ $this.attr( 'disabled', false );
35
+
36
+ // hide ajax loader
37
+ $form.find( '.ajax-feedback' ).css( 'visibility', 'hidden' );
38
+ });
39
+ };
40
+
41
+ // add ajax post
42
+ $( 'form.ajax-form input[type="submit"]' ).click(function( e ){
43
+ saveAjaxForm( this );
44
+ e.preventDefault();
45
+ });
46
+
47
+ });
js/admin-external-links.js ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Admin External Links */
2
+ jQuery(function( $ ){
3
+
4
+ // option filter page
5
+ $( 'input#filter_page' )
6
+ .change(function(){
7
+ var $i = $( 'input#filter_posts, input#filter_comments, input#filter_widgets' );
8
+
9
+ if ( $( this ).attr( 'checked' ) ) {
10
+ $i.attr( 'disabled', true )
11
+ .attr( 'checked', true );
12
+ } else {
13
+ $i.attr( 'disabled', false )
14
+ }
15
+ })
16
+ .change();
17
+
18
+ // refresh page when updated menu position screen option
19
+ $( '#screen-meta #menu_position' ).bind( 'ajax_updated', function(){
20
+ var s = $( this ).val() || '';
21
+ window.location.href = s + ( s.indexOf( '?' ) > -1 ? '&' : '?' ) + 'page=wp_external_links&settings-updated=true';
22
+ });
23
+
24
+ // set menu position
25
+ $( '#admin_menu_position' ).click(function(){
26
+ $( '#show-settings-link' ).click();
27
+ });
28
+
29
+ // set tooltips
30
+ $( '.tooltip-help' ).css( 'margin', '0 5px' ).tipsy({ fade:true, live:true, fallback: 'No help text.' });
31
+
32
+ // slide postbox
33
+ $( '.postbox' ).find( '.handlediv, .hndle' ).click(function(){
34
+ var $inside = $( this ).parent().find( '.inside' );
35
+
36
+ if ( $inside.css( 'display' ) == 'block' ) {
37
+ $inside.css({ display:'block' }).fadeOut();
38
+ } else {
39
+ $inside.css({ display:'none' }).fadeIn();
40
+ }
41
+ });
42
+
43
+ // remove message
44
+ $( '.settings-error:first' )
45
+ .slideDown()
46
+ .delay( 3000 )
47
+ .slideUp()
48
+ .fadeOut();
49
+
50
+ });
js/external-links.js CHANGED
@@ -1,16 +1,20 @@
1
  /* WP External Links Plugin */
2
- (function( w, $ ){
3
 
4
- var addEvt = function ( el, evt, fn ) {
5
- if ( el.attachEvent ) {
6
- // IE method
7
- el.attachEvent( 'on'+ evt, fn );
8
- } else if ( el.addEventListener ) {
9
- // Standard JS method
10
- el.addEventListener( evt, fn, false );
11
- }
12
- };
 
 
 
13
 
 
14
  function openExtLink( a, opts, e ) {
15
  var options = opts ? opts : wpExtLinks,
16
  href = a.href ? a.href.toLowerCase() : '',
@@ -23,19 +27,20 @@
23
  ( href.substr( 0, 7 ) == 'http://'
24
  || href.substr( 0, 8 ) == 'https://'
25
  || href.substr( 0, 6 ) == 'ftp://' ) ) ) ) {
26
-
27
  // open link in a new window
28
- n = w.open( a.href, options.target );
29
  n.focus();
30
 
31
  // prevent default event action
32
  if ( e ) {
33
- e.returnValue = false;
34
- if ( e.preventDefault )
35
  e.preventDefault();
 
 
 
36
  }
37
  }
38
- }
39
 
40
  if ( $ ) {
41
  // jQuery DOMready method
@@ -46,8 +51,8 @@
46
  });
47
  } else {
48
  // use onload when jQuery not available
49
- addEvt( w, 'load', function () {
50
- var links = w.document.getElementsByTagName( 'a' ),
51
  a;
52
 
53
  // check each <a> element
@@ -64,4 +69,4 @@
64
  });
65
  }
66
 
67
- })( window, typeof jQuery == 'undefined' ? null : jQuery );
1
  /* WP External Links Plugin */
2
+ (function(){
3
 
4
+ var $ = typeof jQuery == 'undefined' ? null : jQuery;
5
+
6
+ // add event handler
7
+ function addEvt ( el, evt, fn ) {
8
+ if ( el.attachEvent ) {
9
+ // IE method
10
+ el.attachEvent( 'on'+ evt, fn );
11
+ } else if ( el.addEventListener ) {
12
+ // Standard JS method
13
+ el.addEventListener( evt, fn, false );
14
+ }
15
+ };
16
 
17
+ // open external link
18
  function openExtLink( a, opts, e ) {
19
  var options = opts ? opts : wpExtLinks,
20
  href = a.href ? a.href.toLowerCase() : '',
27
  ( href.substr( 0, 7 ) == 'http://'
28
  || href.substr( 0, 8 ) == 'https://'
29
  || href.substr( 0, 6 ) == 'ftp://' ) ) ) ) {
 
30
  // open link in a new window
31
+ n = window.open( a.href, options.target );
32
  n.focus();
33
 
34
  // prevent default event action
35
  if ( e ) {
36
+ if ( e.preventDefault ) {
 
37
  e.preventDefault();
38
+ } else {
39
+ e.returnValue = false;
40
+ }
41
  }
42
  }
43
+ };
44
 
45
  if ( $ ) {
46
  // jQuery DOMready method
51
  });
52
  } else {
53
  // use onload when jQuery not available
54
+ addEvt( window, 'load', function () {
55
+ var links = window.document.getElementsByTagName( 'a' ),
56
  a;
57
 
58
  // check each <a> element
69
  });
70
  }
71
 
72
+ })();
js/jquery.tipsy.js ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ $.fn.tipsy = function(options) {
3
+
4
+ options = $.extend({}, $.fn.tipsy.defaults, options);
5
+
6
+ return this.each(function() {
7
+
8
+ var opts = $.fn.tipsy.elementOptions(this, options);
9
+
10
+ $(this).hover(function() {
11
+
12
+ $.data(this, 'cancel.tipsy', true);
13
+
14
+ var tip = $.data(this, 'active.tipsy');
15
+ if (!tip) {
16
+ tip = $('<div class="tipsy"><div class="tipsy-inner"/></div>');
17
+ tip.css({position: 'absolute', zIndex: 100000});
18
+ $.data(this, 'active.tipsy', tip);
19
+ }
20
+
21
+ if ($(this).attr('title') || typeof($(this).attr('original-title')) != 'string') {
22
+ $(this).attr('original-title', $(this).attr('title') || '').removeAttr('title');
23
+ }
24
+
25
+ var title;
26
+ if (typeof opts.title == 'string') {
27
+ title = $(this).attr(opts.title == 'title' ? 'original-title' : opts.title);
28
+ } else if (typeof opts.title == 'function') {
29
+ title = opts.title.call(this);
30
+ }
31
+
32
+ tip.find('.tipsy-inner')[opts.html ? 'html' : 'text'](title || opts.fallback);
33
+
34
+ var pos = $.extend({}, $(this).offset(), {width: this.offsetWidth, height: this.offsetHeight});
35
+ tip.get(0).className = 'tipsy'; // reset classname in case of dynamic gravity
36
+ tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
37
+ var actualWidth = tip[0].offsetWidth, actualHeight = tip[0].offsetHeight;
38
+ var gravity = (typeof opts.gravity == 'function') ? opts.gravity.call(this) : opts.gravity;
39
+
40
+ switch (gravity.charAt(0)) {
41
+ case 'n':
42
+ tip.css({top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}).addClass('tipsy-north');
43
+ break;
44
+ case 's':
45
+ tip.css({top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}).addClass('tipsy-south');
46
+ break;
47
+ case 'e':
48
+ tip.css({top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}).addClass('tipsy-east');
49
+ break;
50
+ case 'w':
51
+ tip.css({top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}).addClass('tipsy-west');
52
+ break;
53
+ }
54
+
55
+ if (opts.fade) {
56
+ tip.css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: 0.8});
57
+ } else {
58
+ tip.css({visibility: 'visible'});
59
+ }
60
+
61
+ }, function() {
62
+ $.data(this, 'cancel.tipsy', false);
63
+ var self = this;
64
+ setTimeout(function() {
65
+ if ($.data(this, 'cancel.tipsy')) return;
66
+ var tip = $.data(self, 'active.tipsy');
67
+ if (opts.fade) {
68
+ tip.stop().fadeOut(function() { $(this).remove(); });
69
+ } else {
70
+ tip.remove();
71
+ }
72
+ }, 100);
73
+
74
+ });
75
+
76
+ });
77
+
78
+ };
79
+
80
+ // Overwrite this method to provide options on a per-element basis.
81
+ // For example, you could store the gravity in a 'tipsy-gravity' attribute:
82
+ // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
83
+ // (remember - do not modify 'options' in place!)
84
+ $.fn.tipsy.elementOptions = function(ele, options) {
85
+ return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
86
+ };
87
+
88
+ $.fn.tipsy.defaults = {
89
+ fade: false,
90
+ fallback: '',
91
+ gravity: 'n',
92
+ html: false,
93
+ title: 'title'
94
+ };
95
+
96
+ $.fn.tipsy.autoNS = function() {
97
+ return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
98
+ };
99
+
100
+ $.fn.tipsy.autoWE = function() {
101
+ return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
102
+ };
103
+
104
+ })(jQuery);
readme.txt CHANGED
@@ -1,48 +1,35 @@
1
  === WP External Links ===
2
  Contributors: freelancephp
3
- Tags: links, external, new window, icon, target, _blank, _new, _top, _none, rel, nofollow, javascript, xhtml strict
4
- Requires at least: 2.7.0
5
- Tested up to: 3.1.3
6
- Stable tag: 0.35
7
 
8
- Manage external links on your site: open in new window/tab, set link icon, add "external", add "nofollow" and more.
9
 
10
  == Description ==
11
 
12
- Manage the external links on your site.
13
 
14
  = Features =
15
- * Open in a new window/tab
16
- * Set link icon
17
- * Add "external"
18
- * Add "nofollow"
 
19
  * Set no-icon class
20
- * Set additional classes (for your own styling)
21
 
22
- Supports PHP4.3+ and up to latest WP version.
23
 
24
  == Installation ==
25
  1. Go to `Plugins` in the Admin menu
26
  1. Click on the button `Add new`
27
- 1. Search for `WP External Links` and click 'Install Now' or click on the `upload` link to upload `wp-external-links.zip`
28
  1. Click on `Activate plugin`
29
 
30
  == Frequently Asked Questions ==
31
 
32
- = I have a problem when defining links with JavaScript. What to do? =
33
- When having problems defining links in JavaScript like:
34
- `document.write( "<a href=\"http:://google.com\">Google</a>" );`
35
-
36
- You could use single quotes for defining the string and therefore remove the double quotes, like:
37
- `document.write( '<a href="http:://google.com">Google</a>' );`
38
-
39
- Or you could prevent the plugin filtering the link by escaping the last slash (`</a>`) like:
40
- `document.write( '<a href="http:://google.com">Google<\/a>' );`
41
-
42
- This can be done automatically when enabling the option "Auto-fix javascript problem".
43
-
44
- In the last case when using the JavaScript method and jQuery the link would still be opened in the target given on the options page.
45
-
46
  [Do you have a question? Please ask me](http://www.freelancephp.net/contact/)
47
 
48
  == Screenshots ==
@@ -52,14 +39,28 @@ In the last case when using the JavaScript method and jQuery the link would stil
52
 
53
  == Other notes ==
54
 
55
- = TODO =
56
- * Add a way to exclude links from being filtered
57
-
58
  = Credits =
59
- * Title icon on Admin Options Page was made by [FatCow Web Hosting](http://www.fatcow.com/) taken form [iconfinder](http://findicons.com/icon/164579/link_go?id=427009)
 
 
60
 
61
  == Changelog ==
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  = 0.35 =
64
  * Widget Logic options bug
65
 
@@ -110,14 +111,8 @@ In the last case when using the JavaScript method and jQuery the link would stil
110
 
111
  == Upgrade Notice ==
112
 
113
- = 0.34 =
114
- * Solved some issues
115
-
116
- = 0.33 =
117
- * Add option to fix js problem
118
- * Fixed PHP / WP notices
119
-
120
- = 0.32 =
121
- * For jQuery uses live() function so also opens dynamicly created links in given target
122
- * Fixed bug of changing `<abbr>` tag
123
- * Small cosmetical adjustments
1
  === WP External Links ===
2
  Contributors: freelancephp
3
+ Tags: links, external, icon, target, _blank, _new, _none, rel, nofollow, new window, new tab, javascript, xhtml, seo
4
+ Requires at least: 3.0.0
5
+ Tested up to: 3.2.1
6
+ Stable tag: 1.01
7
 
8
+ Open external links in a new window/tab, add "external" / "nofollow" to rel-attribute, set icon, XHTML strict, SEO friendly...
9
 
10
  == Description ==
11
 
12
+ Set options for external links, like:
13
 
14
  = Features =
15
+ * Set target for opening external links
16
+ * Add "external" / "nofollow" to rel-attribute
17
+ * Set title
18
+ * Set icon
19
+ * Add class(es)
20
  * Set no-icon class
21
+ * XHTML strict and SEO friendly
22
 
23
+ This latest version requires PHP 5.2+ and WP 3.0+.
24
 
25
  == Installation ==
26
  1. Go to `Plugins` in the Admin menu
27
  1. Click on the button `Add new`
28
+ 1. Search for `WP External Links` and click 'Install Now' OR click on the `upload` link to upload `wp-external-links.zip`
29
  1. Click on `Activate plugin`
30
 
31
  == Frequently Asked Questions ==
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  [Do you have a question? Please ask me](http://www.freelancephp.net/contact/)
34
 
35
  == Screenshots ==
39
 
40
  == Other notes ==
41
 
 
 
 
42
  = Credits =
43
+ * [phpQuery](http://code.google.com/p/phpquery/) made by [Tobiasz Cudnik](http://tobiasz123.wordpress.com)
44
+ * [jQuery Tipsy Plugin](http://plugins.jquery.com/project/tipsy) made by [Jason Frame](http://onehackoranother.com/)
45
+ * [Icon](http://findicons.com/icon/164579/link_go?id=427009) made by [FatCow Web Hosting](http://www.fatcow.com/)
46
 
47
  == Changelog ==
48
 
49
+ = 1.01 =
50
+ * Solved bug after live testing
51
+
52
+ = 1.00 =
53
+ * Added option for setting title-attribute
54
+ * Added option for excluding filtering certain external links
55
+ * Added Admin help tooltips using jQuery Tipsy Plugin
56
+ * Reorginized files and refactored code to PHP5 (no support for PHP4)
57
+ * Added WP built-in meta box functionallity (using the `WP_Meta_Box_Page` Class)
58
+ * Reorganized saving options and added Ajax save method (using the `WP_Option_Forms` Class)
59
+ * Removed Regexp and using phpQuery
60
+ * Choose menu position for this plugin (see "Screen Options")
61
+ * Removed possibility to convert all `<a>` tags to xhtml clean code (so only external links will be converted)
62
+ * Removed "Solve problem" options
63
+
64
  = 0.35 =
65
  * Widget Logic options bug
66
 
111
 
112
  == Upgrade Notice ==
113
 
114
+ = 1.01 =
115
+ * This version requires PHP5.2+ and WP3.0+
116
+ * Added option for setting title-attribute
117
+ * Added option for excluding certain links
118
+ * Improved Admin page
 
 
 
 
 
 
screenshot-2.png CHANGED
Binary file
wp-external-links.php CHANGED
@@ -1,574 +1,47 @@
1
- <?php
2
  /*
3
  Plugin Name: WP External Links
4
  Plugin URI: http://www.freelancephp.net/wp-external-links-plugin
5
- Description: Manage external links on your site: open in new window/tab, set link icon, add "external", add "nofollow" and more.
6
  Author: Victor Villaverde Laan
7
- Version: 0.35
8
  Author URI: http://www.freelancephp.net
9
  License: Dual licensed under the MIT and GPL licenses
10
  */
11
 
12
- /**
13
- * Class WP_External_Links
14
- * @category WordPress Plugins
15
- */
16
- class WP_External_Links {
17
 
18
- /**
19
- * Current version
20
- * @var string
21
- */
22
- var $version = '0.35';
23
 
24
- /**
25
- * Used as prefix for options entry and could be used as text domain (for translations)
26
- * @var string
27
- */
28
- var $domain = 'WP_External_Links';
29
 
30
- /**
31
- * Name of the options
32
- * @var string
33
- */
34
- var $options_name = 'WP_External_Links_options';
35
 
36
- /**
37
- * Options to be saved
38
- * @var array
39
- */
40
- var $options = array(
41
- 'target' => '_none',
42
- 'use_js' => 1,
43
- 'external' => 1,
44
- 'nofollow' => 1,
45
- 'filter_whole_page' => 1,
46
- 'filter_posts' => 1,
47
- 'filter_comments' => 1,
48
- 'filter_widgets' => 1,
49
- 'fix_js' => 0,
50
- 'fix_xhtml' => 0,
51
- 'icon' => 0,
52
- 'no_icon_class' => 'no-ext-icon',
53
- 'no_icon_same_window' => 0,
54
- 'class_name' => 'ext-link',
55
- 'widget_logic_filter' => 0,
56
- );
57
 
58
- /**
59
- * Regexp
60
- * @var array
61
- */
62
- var $regexp_patterns = array(
63
- 'a' => '/<a[^A-Za-z](.*?)>(.*?)<\/a[\s+]*>/is',
64
- 'css' => '/<link(.*?)wp-external-links-css(.*?)\/>[\s+]*/i',
65
- 'body' => '/<body(.*?)>(.*?)<\/body[\s+]*>/is',
66
- 'script' => '/<script(.*?)>(.*?)<\/script[\s+]*>/is',
67
- );
68
 
 
 
69
 
70
- /**
71
- * PHP4 constructor
72
- */
73
- function WP_External_Links() {
74
- $this->__construct();
75
- }
76
-
77
- /**
78
- * PHP5 constructor
79
- */
80
- function __construct() {
81
- // set option values
82
- $this->_set_options();
83
-
84
- // load text domain for translations
85
- load_plugin_textdomain( $this->domain, FALSE, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
86
-
87
- // set uninstall hook
88
- if ( function_exists( 'register_deactivation_hook' ) )
89
- register_deactivation_hook( __FILE__, array( $this, 'deactivation' ));
90
-
91
- // add actions
92
- add_action( 'wp', array( $this, 'wp' ) );
93
- add_action( 'admin_init', array( $this, 'admin_init' ) );
94
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
95
- }
96
-
97
- /**
98
- * Callback wp
99
- */
100
- function wp() {
101
- if ( ! is_admin() && ! is_feed() ) {
102
- // add wp_head for setting js vars and css style
103
- add_action( 'wp_head', array( $this, 'wp_head' ) );
104
-
105
- // add stylesheet
106
- wp_enqueue_style( 'wp-external-links', plugins_url( 'css/external-links.css', __FILE__ ), FALSE, $this->version );
107
-
108
- // set js file
109
- if ( $this->options[ 'use_js' ] ) {
110
- wp_enqueue_script( 'wp-external-links', plugins_url( 'js/external-links.js', __FILE__ ), array( 'jquery' ), $this->version );
111
- }
112
 
113
- if ( $this->options[ 'filter_whole_page' ] ) {
114
- ob_start( array( $this, 'filter_page' ) );
115
- } else {
116
- // set filter priority
117
- $priority = 1000000000;
118
-
119
- // content
120
- if ( $this->options[ 'filter_posts' ] ) {
121
- add_filter( 'the_title', array( $this, 'filter_content' ), $priority );
122
- add_filter( 'the_content', array( $this, 'filter_content' ), $priority );
123
- add_filter( 'the_excerpt', array( $this, 'filter_content' ), $priority );
124
- add_filter( 'get_the_excerpt', array( $this, 'filter_content' ), $priority );
125
- }
126
-
127
- // comments
128
- if ( $this->options[ 'filter_comments' ] ) {
129
- add_filter( 'comment_text', array( $this, 'filter_content' ), $priority );
130
- add_filter( 'comment_excerpt', array( $this, 'filter_content' ), $priority );
131
- add_filter( 'comment_url', array( $this, 'filter_content' ), $priority );
132
- add_filter( 'get_comment_author_url', array( $this, 'filter_content' ), $priority );
133
- add_filter( 'get_comment_author_link', array( $this, 'filter_content' ), $priority );
134
- add_filter( 'get_comment_author_url_link', array( $this, 'filter_content' ), $priority );
135
- }
136
-
137
- // widgets ( only text widgets )
138
- if ( $this->options[ 'filter_widgets' ] ) {
139
- add_filter( 'widget_title', array( $this, 'filter_content' ), $priority );
140
- add_filter( 'widget_text', array( $this, 'filter_content' ), $priority );
141
-
142
- // Only if Widget Logic plugin is installed and 'widget_content' option is activated
143
- add_filter( 'widget_content', array( $this, 'filter_content' ), $priority );
144
- }
145
- }
146
- }
147
  }
 
148
 
149
- /**
150
- * Callback admin_menu
151
- */
152
- function admin_menu() {
153
- if ( function_exists( 'add_options_page' ) AND current_user_can( 'manage_options' ) ) {
154
- // add options page
155
- $page = add_options_page( __( 'External Links', $this->domain ), __( 'External Links', $this->domain ),
156
- 'manage_options', __FILE__, array( $this, 'options_page' ) );
157
- }
158
- }
159
-
160
- /**
161
- * Callback wp_head
162
- */
163
- function wp_head() {
164
- if ( $this->options[ 'use_js' ] AND $this->options[ 'target' ] != '_none' ):
165
- $excludeClass = ( $this->options[ 'no_icon_same_window' ] AND ! empty( $this->options[ 'no_icon_class' ] ) )
166
- ? $this->options[ 'no_icon_class' ]
167
- : '';
168
- ?>
169
- <script type="text/javascript">/* <![CDATA[ */
170
- /* WP External Links Plugin */
171
- var wpExtLinks = { baseUrl: '<?php echo get_bloginfo( 'url' ) ?>',target: '<?php echo $this->options[ 'target' ] ?>',excludeClass: '<?php echo $excludeClass ?>' };
172
- /* ]]> */</script>
173
- <?php
174
- endif;
175
- }
176
-
177
- /**
178
- * Filter complete html page
179
- * @param array $match
180
- * @return string
181
- */
182
- function filter_page( $content ) {
183
- // only replace links in <body> part
184
- return preg_replace_callback( $this->regexp_patterns[ 'body' ], array( $this, '_callback_page_filter' ), $content );
185
- }
186
-
187
- function _callback_page_filter( $match ) {
188
- return $this->filter_content( $match[ 0 ] );
189
- }
190
-
191
- /**
192
- * Filter content
193
- * @param string $content
194
- * @return string
195
- */
196
- function filter_content( $content ) {
197
- if ( $this->options[ 'fix_js' ] ) {
198
- // fix js proble by replacing </a> by <\/a>
199
- $content = preg_replace_callback( $this->regexp_patterns[ 'script' ], array( $this, 'fix_js' ), $content );
200
- }
201
-
202
- // replace links in body
203
- $content = preg_replace_callback( $this->regexp_patterns[ 'a' ], array( $this, 'parse_link' ), $content );
204
-
205
- // remove style when no icon classes are found
206
- if ( strpos( $content, 'ext-icon-' ) === FALSE ) {
207
- // remove style with id wp-external-links-css
208
- $content = preg_replace( $this->regexp_patterns[ 'css' ], '', $content );
209
- }
210
-
211
- return $content;
212
- }
213
-
214
- function fix_js( $match ) {
215
- return str_replace( '</a>', '<\/a>', $match[ 0 ] );
216
- }
217
-
218
- /**
219
- * Make a clean <a> code
220
- * @param array $match Result of a preg call in filter_content()
221
- * @return string Clean <a> code
222
- */
223
- function parse_link( $match ) {
224
- $attrs = $match[ 1 ];
225
- $attrs = stripslashes( $attrs );
226
- $attrs = shortcode_parse_atts( $attrs );
227
-
228
- $href_tolower = strtolower( $attrs[ 'href' ] );
229
- $rel_tolower = ( isset( $attrs[ 'rel' ] ) ) ? strtolower( $attrs[ 'rel' ] ) : '';
230
-
231
- // check url
232
- if ( isset( $attrs[ 'href' ] ) AND ( strpos( $rel_tolower, 'external' ) !== FALSE
233
- OR ( strpos( $href_tolower, strtolower( get_bloginfo( 'url' ) ) ) === FALSE )
234
- AND ( substr( $href_tolower, 0, 7 ) == 'http://'
235
- OR substr( $href_tolower, 0, 8 ) == 'https://'
236
- OR substr( $href_tolower, 0, 6 ) == 'ftp://' ) ) ){
237
- // set rel="external" (when not already set)
238
- if ( $this->options[ 'external' ] AND strpos( $rel_tolower, 'external' ) === FALSE ){
239
- $attrs[ 'rel' ] = ( empty( $attrs[ 'rel' ] ) )
240
- ? 'external'
241
- : $attrs[ 'rel' ] .' external';
242
- }
243
-
244
- // set rel="nofollow" when doesn't have "follow" (or already "nofollow")
245
- if ( $this->options[ 'nofollow' ] AND strpos( $rel_tolower, 'follow' ) === FALSE ){
246
- $attrs[ 'rel' ] = ( empty( $attrs[ 'rel' ] ) )
247
- ? 'nofollow'
248
- : $attrs[ 'rel' ] .' nofollow';
249
- }
250
-
251
- // set icon class, unless no-icon class isset or another icon class ('ext-icon-...') is found
252
- if ( $this->options[ 'icon' ] > 0 AND ( empty( $this->options[ 'no_icon_class' ] ) OR strpos( $attrs[ 'class' ], $this->options[ 'no_icon_class' ] ) === FALSE ) AND strpos( $attrs[ 'class' ], 'ext-icon-' ) === FALSE ){
253
- $icon_class = 'ext-icon-'. $this->options[ 'icon' ];
254
-
255
- $attrs[ 'class' ] = ( empty( $attrs[ 'class' ] ) )
256
- ? $icon_class
257
- : $attrs[ 'class' ] .' '. $icon_class;
258
- }
259
-
260
- // set user-defined class
261
- if ( ! empty( $this->options[ 'class_name' ] ) AND ( empty( $attrs[ 'class' ] ) OR strpos( $attrs[ 'class' ], $this->options[ 'class_name' ] ) === FALSE ) ){
262
- $attrs[ 'class' ] = ( empty( $attrs[ 'class' ] ) )
263
- ? $this->options[ 'class_name' ]
264
- : $attrs[ 'class' ] .' '. $this->options[ 'class_name' ];
265
- }
266
-
267
- // set target
268
- if ( $this->options[ 'target' ] != '_none' AND ! $this->options[ 'use_js' ] AND ( ! $this->options[ 'no_icon_same_window' ] OR empty( $this->options[ 'no_icon_class' ] ) OR strpos( $attrs[ 'class' ], $this->options[ 'no_icon_class' ] ) === FALSE ) )
269
- $attrs[ 'target' ] = $this->options[ 'target' ];
270
-
271
- } elseif ( $this->options[ 'fix_xhtml' ] ) {
272
- return $match[ 0 ];
273
- }
274
-
275
- // create element code
276
- $link = '<a ';
277
-
278
- foreach ( $attrs AS $key => $value )
279
- $link .= $key .'="'. $value .'" ';
280
-
281
- // remove last space
282
- $link = substr( $link, 0, -1 );
283
-
284
- $link .= '>'. $match[ 2 ] .'</a>';
285
-
286
- return $link;
287
- }
288
-
289
- /**
290
- * Callback admin_init
291
- */
292
- function admin_init() {
293
- // register settings
294
- register_setting( $this->domain, $this->options_name );
295
-
296
- // set dashboard postbox
297
- wp_admin_css( 'dashboard' );
298
- wp_enqueue_script( 'dashboard' );
299
- }
300
-
301
- /**
302
- * Admin options page
303
- */
304
- function options_page() {
305
- ?>
306
- <script type="text/javascript">
307
- jQuery(function( $ ){
308
- // remove message
309
- $( '.settings-error' )
310
- .hide()
311
- .slideDown( 600 )
312
- .delay( 3000 )
313
- .slideUp( 600 );
314
-
315
- // option filter whole page
316
- $( 'input#filter_whole_page' )
317
- .change(function(){
318
- var $i = $( 'input#filter_posts, input#filter_comments, input#filter_widgets' );
319
-
320
- if ( $( this ).attr( 'checked' ) ) {
321
- $i.attr( 'disabled', true )
322
- .attr( 'checked', true );
323
- } else {
324
- $i.attr( 'disabled', false )
325
- }
326
- })
327
- .change();
328
-
329
- // slide postbox
330
- $( '.postbox' ).find( '.handlediv, .hndle' ).click(function(){
331
- var $inside = $( this ).parent().find( '.inside' );
332
-
333
- if ( $inside.css( 'display' ) == 'block' ) {
334
- $inside.css({ display:'block' }).slideUp();
335
- } else {
336
- $inside.css({ display:'none' }).slideDown();
337
- }
338
- });
339
-
340
- // note
341
- $( '#fix_xhtml' ).change(function(){
342
- $( '#xhtml_convert_all' ).css( 'display', $( this ).attr( 'checked' ) ? 'none' : 'block' );
343
- }).change();
344
- });
345
- </script>
346
- <div class="wrap">
347
- <div class="icon32" id="icon-options-custom" style="background:url( <?php echo plugins_url( 'images/icon-wp-external-links.png', __FILE__ ) ?> ) no-repeat 50% 50%"><br></div>
348
- <h2><?php _e( 'External Links Settings' ) ?></h2>
349
-
350
- <form method="post" action="options.php">
351
- <?php
352
- settings_fields( $this->domain );
353
- $this->_set_options();
354
- $options = $this->options;
355
- ?>
356
-
357
- <div class="postbox-container metabox-holder meta-box-sortables" style="width:69%;">
358
- <div style="margin:0 5px;">
359
- <div class="postbox">
360
- <div class="handlediv" title="<?php _e( 'Click to toggle' ) ?>"><br/></div>
361
- <h3 class="hndle"><?php _e( 'General Settings', $this->domain ) ?></h3>
362
- <div class="inside">
363
- <fieldset class="options">
364
- <table class="form-table">
365
- <tr>
366
- <th><?php _e( 'Set target for external links', $this->domain ) ?></th>
367
- <td class="target_external_links">
368
- <label><input type="radio" name="<?php echo $this->options_name ?>[target]" class="field_target" value="_blank" <?php checked( '_blank', $options['target'] ); ?> />
369
- <span><?php _e( '<code>_blank</code>, open every external link in a new window or tab', $this->domain ) ?></span></label>
370
- <br/><label><input type="radio" name="<?php echo $this->options_name ?>[target]" class="field_target" value="_top" <?php checked( '_top', $options['target'] ); ?> />
371
- <span><?php _e( '<code>_top</code>, open in current window or tab, with no frames', $this->domain ) ?></span></label>
372
- <br/><label><input type="radio" name="<?php echo $this->options_name ?>[target]" class="field_target" value="_new" <?php checked( '_new', $options['target'] ); ?> />
373
- <span><?php _e( '<code>_new</code>, open new window the first time and use this window for each external link', $this->domain ) ?></span></label>
374
- <br/><label><input type="radio" name="<?php echo $this->options_name ?>[target]" class="field_target" value="_none" <?php checked( '_none', $options['target'] ); ?> />
375
- <span><?php _e( '<code>_none</code>, open in current window or tab', $this->domain ) ?></span></label>
376
- </td>
377
- </tr>
378
- <tr>
379
- <th>&nbsp;</th>
380
- <td>
381
- <label><input type="checkbox" name="<?php echo $this->options_name ?>[use_js]" class="field_use_js" value="1" <?php checked( '1', (int) $options['use_js'] ); ?> />
382
- <span><?php _e( 'Use JavaScript method (recommended, XHTML Strict compliant)', $this->domain ) ?></span></label>
383
- </td>
384
- </tr>
385
- <tr>
386
- <th><?php _e( 'Add to "rel" attribute', $this->domain ) ?></th>
387
- <td><label><input type="checkbox" id="<?php echo $this->options_name ?>[external]" name="<?php echo $this->options_name ?>[external]" value="1" <?php checked('1', (int) $options['external']); ?> />
388
- <span><?php _e( 'Add <code>"external"</code> to the rel-attribute of external links', $this->domain ) ?></span></label>
389
- <br/><label><input type="checkbox" id="<?php echo $this->options_name ?>[nofollow]" name="<?php echo $this->options_name ?>[nofollow]" value="1" <?php checked('1', (int) $options['nofollow']); ?> />
390
- <span><?php _e( 'Add <code>"nofollow"</code> to the rel-attribute of external links (unless link has <code>"follow"</code>)', $this->domain ) ?></span></label>
391
- </td>
392
- </tr>
393
- <tr>
394
- <th><?php _e( 'Options have effect on', $this->domain ) ?></th>
395
- <td>
396
- <label><input type="checkbox" name="<?php echo $this->options_name ?>[filter_whole_page]" id="filter_whole_page" value="1" <?php checked( '1', (int) $options['filter_whole_page'] ); ?> />
397
- <span><?php _e( 'All contents (the whole <code>&lt;body&gt;</code>)', $this->domain ) ?></span></label>
398
- <br/>&nbsp;&nbsp;<label><input type="checkbox" name="<?php echo $this->options_name ?>[filter_posts]" id="filter_posts" value="1" <?php checked( '1', (int) $options['filter_posts'] ); ?> />
399
- <span><?php _e( 'Post contents', $this->domain ) ?></span></label>
400
- <br/>&nbsp;&nbsp;<label><input type="checkbox" name="<?php echo $this->options_name ?>[filter_comments]" id="filter_comments" value="1" <?php checked( '1', (int) $options['filter_comments'] ); ?> />
401
- <span><?php _e( 'Comments', $this->domain ) ?></span></label>
402
- <br/>&nbsp;&nbsp;<label><input type="checkbox" name="<?php echo $this->options_name ?>[filter_widgets]" id="filter_widgets" value="1" <?php checked( '1', (int) $options['filter_widgets'] ); ?> />
403
- <span><?php if ( $this->options[ 'widget_logic_filter' ] ) { _e( 'All widgets (uses the <code>widget_content</code> filter of the Widget Logic plugin)', $this->domain ); } else { _e( 'All text widgets', $this->domain ); } ?></span></label>
404
- </td>
405
- </tr>
406
- <tr>
407
- <th><?php _e( 'Solve problems...', $this->domain ) ?></th>
408
- <td><label><input type="checkbox" name="<?php echo $this->options_name ?>[fix_js]" id="fix_js" value="1" <?php checked( '1', (int) $options['fix_js'] ); ?> />
409
- <span><?php _e( 'Auto-fix javascript problem (by replacing <code>&lt;/a&gt;</code> with <code>&lt;\/a&gt;</code> in js)', $this->domain ) ?></span></label>
410
- <br/><label><input type="checkbox" name="<?php echo $this->options_name ?>[fix_xhtml]" id="fix_xhtml" value="1" <?php checked( '1', (int) $options['fix_xhtml'] ); ?> />
411
- <span><?php _e( 'Only convert <strong>external</strong> links of the selected content to valid XHTML code (instead of all &lt;a&gt;-tags)', $this->domain ) ?></span></label>
412
- <br/>
413
- <br/><span id="xhtml_convert_all" class="description"><?php _e( 'Note: all <code>&lt;a&gt;</code> tags in the selected contents will be converted to XHTML valid code' ) ?></span>
414
- </td>
415
- </tr>
416
- </table>
417
- </fieldset>
418
- <p class="submit">
419
- <input class="button-primary" type="submit" value="<?php _e( 'Save Changes' ) ?>" />
420
- </p>
421
- </div>
422
- </div>
423
-
424
- <div class="postbox">
425
- <div class="handlediv" title="<?php _e( 'Click to toggle' ) ?>"><br/></div>
426
- <h3 class="hndle"><?php _e( 'Style Settings', $this->domain ) ?></h3>
427
- <div class="inside">
428
- <fieldset class="options">
429
- <table class="form-table">
430
- <tr>
431
- <th><?php _e( 'Show icon', $this->domain ) ?>
432
- </th>
433
- <td>
434
- <div>
435
- <div style="width:15%;float:left">
436
- <label><input type="radio" name="<?php echo $this->options_name ?>[icon]" value="0" <?php checked('0', (int) $options['icon']); ?> />
437
- <span><?php _e( 'No icon', $this->domain ) ?></span></label>
438
- <?php for ( $x = 1; $x <= 20; $x++ ): ?>
439
- <br/>
440
- <label title="<?php echo sprintf( __( 'Icon %1$s: choose this icon to show for all external links or add the class \'ext-icon-%1$s\' to a specific link.' ), $x ) ?>"><input type="radio" name="<?php echo $this->options_name ?>[icon]" value="<?php echo $x ?>" <?php checked( $x, (int) $options['icon'] ); ?> />
441
- <img src="<?php echo plugins_url( 'images/external-'. $x .'.png', __FILE__ ) ?>" /></label>
442
- <?php if ( $x % 5 == 0 ): ?>
443
- </div>
444
- <div style="width:15%;float:left">
445
- <?php endif; ?>
446
- <?php endfor; ?>
447
- </div>
448
- <div style="width:29%;float:left;"><span class="description"><?php _e( 'Example:', $this->domain ) ?></span>
449
- <br/><img src="<?php echo plugins_url( 'images/link-icon-example.png', __FILE__ ) ?>" />
450
- </div>
451
- <br style="clear:both" />
452
- </div>
453
- </td>
454
- </tr>
455
- <tr>
456
- <th><?php _e( 'No-Icon Class', $this->domain ) ?></th>
457
- <td><label><input type="text" id="<?php echo $this->options_name ?>[no_icon_class]" name="<?php echo $this->options_name ?>[no_icon_class]" value="<?php echo $options['no_icon_class']; ?>" />
458
- <span><?php _e( 'Use this class when a link should not show any icon', $this->domain ) ?></span></label>
459
- <br/><label><input type="checkbox" name="<?php echo $this->options_name ?>[no_icon_same_window]" id="no_icon_same_window" value="1" <?php checked( '1', (int) $options['no_icon_same_window'] ); ?> />
460
- <span><?php _e( 'Always open no-icon links in current window', $this->domain ) ?></span></label>
461
- </td>
462
- </tr>
463
- <tr>
464
- <th><?php _e( 'Additional Classes (optional)', $this->domain ) ?></th>
465
- <td><label><input type="text" id="<?php echo $this->options_name ?>[class_name]" name="<?php echo $this->options_name ?>[class_name]" value="<?php echo $options['class_name']; ?>" />
466
- <span><?php _e( 'Add extra classes to external links (or leave blank)', $this->domain ) ?></span></label></td>
467
- </tr>
468
- </table>
469
- </fieldset>
470
- <p class="submit">
471
- <input class="button-primary" type="submit" value="<?php _e( 'Save Changes' ) ?>" />
472
- </p>
473
- </div>
474
- </div>
475
- </div>
476
- </div>
477
-
478
- <div class="postbox-container metabox-holder meta-box-sortables" style="width:29%;">
479
- <div style="margin:0 5px;">
480
- <div class="postbox">
481
- <div class="handlediv" title="<?php _e( 'Click to toggle' ) ?>"><br/></div>
482
- <h3 class="hndle"><?php _e( 'About' ) ?>...</h3>
483
- <div class="inside">
484
- <h4><img src="<?php echo plugins_url( 'images/icon-wp-external-links.png', __FILE__ ) ?>" width="16" height="16" /> WP External Links (v<?php echo $this->version ?>)</h4>
485
- <p><?php _e( 'Manage external links on your site: open in new window/tab, set link icon, add "external", add "nofollow" and more.', $this->domain ) ?></p>
486
- <ul>
487
- <li><a href="http://www.freelancephp.net/contact/" target="_blank"><?php _e( 'Questions or suggestions?', $this->domain ) ?></a></li>
488
- <li><?php _e( 'If you like this plugin please send your rating at WordPress.org.' ) ?></li>
489
- <li><a href="http://wordpress.org/extend/plugins/wp-external-links/" target="_blank">WordPress.org</a> | <a href="http://www.freelancephp.net/wp-external-links-plugin/" target="_blank">FreelancePHP.net</a></li>
490
- </ul>
491
- </div>
492
- </div>
493
-
494
- <div class="postbox">
495
- <div class="handlediv" title="<?php _e( 'Click to toggle' ) ?>"><br/></div>
496
- <h3 class="hndle"><?php _e( 'Other Plugins', $this->domain ) ?></h3>
497
- <div class="inside">
498
- <h4><img src="<?php echo plugins_url( 'images/icon-wp-mailto-links.png', __FILE__ ) ?>" width="16" height="16" /> WP Mailto Links</h4>
499
- <p><?php _e( 'Manage mailto links on your site and protect emails from spambots, set mail icon and more.', $this->domain ) ?></p>
500
- <ul>
501
- <?php if ( is_plugin_active( 'wp-mailto-links/wp-mailto-links.php' ) ): ?>
502
- <li><?php _e( 'This plugin is already activated.', $this->domain ) ?> <a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/options-general.php?page=wp-mailto-links/wp-mailto-links.php"><?php _e( 'Settings' ) ?></a></li>
503
- <?php elseif( file_exists( WP_PLUGIN_DIR . '/wp-mailto-links/wp-mailto-links.php' ) ): ?>
504
- <li><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugins.php?plugin_status=inactive"><?php _e( 'Activate this plugin.', $this->domain ) ?></a></li>
505
- <?php else: ?>
506
- <li><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugin-install.php?tab=search&type=term&s=WP+Mailto+Links+freelancephp&plugin-search-input=Search+Plugins"><?php _e( 'Get this plugin now', $this->domain ) ?></a></li>
507
- <?php endif; ?>
508
- <li><a href="http://wordpress.org/extend/plugins/wp-mailto-links/" target="_blank">WordPress.org</a> | <a href="http://www.freelancephp.net/wp-mailto-links-plugin/" target="_blank">FreelancePHP.net</a></li>
509
- </ul>
510
-
511
- <h4><img src="<?php echo plugins_url( 'images/icon-email-encoder-bundle.png', __FILE__ ) ?>" width="16" height="16" /> Email Encoder Bundle</h4>
512
- <p><?php _e( 'Protect email addresses on your site from spambots and being used for spamming by using one of the encoding methods.', $this->domain ) ?></p>
513
- <ul>
514
- <?php if ( is_plugin_active( 'email-encoder-bundle/email-encoder-bundle.php' ) ): ?>
515
- <li><?php _e( 'This plugin is already activated.', $this->domain ) ?> <a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/options-general.php?page=email-encoder-bundle/email-encoder-bundle.php"><?php _e( 'Settings' ) ?></a></li>
516
- <?php elseif( file_exists( WP_PLUGIN_DIR . '/email-encoder-bundle/email-encoder-bundle.php' ) ): ?>
517
- <li><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugins.php?plugin_status=inactive"><?php _e( 'Activate this plugin.', $this->domain ) ?></a></li>
518
- <?php else: ?>
519
- <li><a href="<?php echo get_bloginfo( 'url' ) ?>/wp-admin/plugin-install.php?tab=search&type=term&s=Email+Encoder+Bundle+freelancephp&plugin-search-input=Search+Plugins"><?php _e( 'Get this plugin now', $this->domain ) ?></a></li>
520
- <?php endif; ?>
521
- <li><a href="http://wordpress.org/extend/plugins/email-encoder-bundle/" target="_blank">WordPress.org</a> | <a href="http://www.freelancephp.net/email-encoder-php-class-wp-plugin/" target="_blank">FreelancePHP.net</a></li>
522
- </ul>
523
- </div>
524
- </div>
525
- </div>
526
- </div>
527
- </form>
528
- <div class="clear"></div>
529
- </div>
530
- <?php
531
- }
532
-
533
- /**
534
- * Deactivation plugin method
535
- */
536
- function deactivation() {
537
- delete_option( $this->options_name );
538
- unregister_setting( $this->domain, $this->options_name );
539
- }
540
-
541
- /**
542
- * Set options from save values or defaults
543
- */
544
- function _set_options() {
545
- // set options
546
- $saved_options = get_option( $this->options_name );
547
-
548
- // set all options
549
- if ( ! empty( $saved_options ) ) {
550
- foreach ( $this->options AS $key => $option ) {
551
- // skip when no saved value for radio 'target'
552
- if ( ! isset( $saved_options[ $key ] ) AND $key == 'target' )
553
- continue;
554
-
555
- $this->options[ $key ] = ( empty( $saved_options[ $key ] ) ) ? '' : $saved_options[ $key ];
556
- }
557
- }
558
-
559
- // set widget_content filter of Widget Logic plugin
560
- $widget_logic_opts = get_option( 'widget_logic' );
561
- if ( is_array( $widget_logic_opts ) AND key_exists( 'widget_logic-options-filter', $widget_logic_opts ) ) {
562
- $this->options[ 'widget_logic_filter' ] = ( $widget_logic_opts[ 'widget_logic-options-filter' ] == 'checked' ) ? 1 : 0;
563
- }
564
- }
565
-
566
- } // end class WP_External_Links
567
-
568
-
569
- /**
570
- * Create WP_External_Links instance
571
- */
572
- $WP_External_Links = new WP_External_Links;
573
-
574
- /*?> // ommit closing tag, to prevent unwanted whitespace at the end of the parts generated by the included files */
1
+ <?php defined( 'ABSPATH' ) OR die( 'No direct access.' );
2
  /*
3
  Plugin Name: WP External Links
4
  Plugin URI: http://www.freelancephp.net/wp-external-links-plugin
5
+ Description: Open external links in a new window/tab, add "external" / "nofollow" to rel-attribute, set icon, XHTML strict, SEO friendly...
6
  Author: Victor Villaverde Laan
7
+ Version: 1.01
8
  Author URI: http://www.freelancephp.net
9
  License: Dual licensed under the MIT and GPL licenses
10
  */
11
 
12
+ // plugin version
13
+ define( 'WP_EXTERNAL_LINKS_VERSION', '1.01' );
 
 
 
14
 
15
+ // plugin key (used as translation domain, option_group, page_slug etc)
16
+ define( 'WP_EXTERNAL_LINKS_KEY', 'wp_external_links' );
 
 
 
17
 
18
+ // plugin file
19
+ define( 'WP_EXTERNAL_LINKS_FILE', __FILE__ );
 
 
 
20
 
 
 
 
 
 
21
 
22
+ // check plugin compatibility
23
+ if ( isset( $wp_version ) AND version_compare( preg_replace( '/-.*$/', '', $wp_version ), '3.0', '>=' )
24
+ AND version_compare( phpversion(), '5.2', '>=' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ // include classes
27
+ require_once( 'includes/wp-plugin-dev-classes/class-wp-meta-box-page.php' );
28
+ require_once( 'includes/wp-plugin-dev-classes/class-wp-option-forms.php' );
29
+ require_once( 'includes/class-admin-external-links.php' );
30
+ require_once( 'includes/class-wp-external-links.php' );
 
 
 
 
 
31
 
32
+ // create WP_External_Links instance
33
+ $WP_External_Links = new WP_External_Links();
34
 
35
+ } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ // set error message
38
+ function wp_external_links_error_notice() {
39
+ echo '<div class="error">'
40
+ . __( '<p>Warning - <strong>WP External Links Plugin</strong> requires PHP 5.2+ and WP 3.0+.'
41
+ . '<br/>Please upgrade your configuration or use an older version of this plugin. '
42
+ . 'Disable the plugin to remove this message.</p>', WP_EXTERNAL_LINKS_KEY )
43
+ . '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
+ add_action( 'admin_notices', 'wp_external_links_error_notice' );
46
 
47
+ }