├── .gitignore
├── .htaccess
├── LICENSE.txt
├── README.md
├── SlimJim.png
├── admin
├── .htaccess
├── css
│ ├── bootstrap.css
│ └── slimjim.css
├── index.php
└── templates
│ ├── home.php
│ ├── layouts
│ ├── default.php
│ └── login.php
│ ├── loginForm.php
│ ├── profile
│ └── profile.php
│ ├── projects
│ ├── addProject.php
│ └── projects.php
│ └── settings
│ ├── addSetting.php
│ └── settings.php
├── config.sample.php
├── deploy.php
├── index.php
├── libs
├── Paris
│ ├── idiorm.php
│ └── paris.php
├── Slim
│ ├── CustomView.php
│ ├── Environment.php
│ ├── Exception
│ │ ├── Pass.php
│ │ ├── RequestSlash.php
│ │ └── Stop.php
│ ├── Http
│ │ ├── Headers.php
│ │ ├── Request.php
│ │ ├── Response.php
│ │ └── Util.php
│ ├── Log.php
│ ├── LogFileWriter.php
│ ├── Middleware.php
│ ├── Middleware
│ │ ├── ContentTypes.php
│ │ ├── Flash.php
│ │ ├── MethodOverride.php
│ │ ├── PrettyExceptions.php
│ │ └── SessionCookie.php
│ ├── Route.php
│ ├── Router.php
│ ├── Slim.php
│ └── View.php
└── spyc.php
├── models
├── Admin.php
├── Project.php
└── Setting.php
├── requests
└── empty
└── slimjim.sql
/.gitignore:
--------------------------------------------------------------------------------
1 | # Numerous always-ignore extensions
2 | *.diff
3 | *.err
4 | *.orig
5 | *.log
6 | *.rej
7 | *.swo
8 | *.swp
9 | *.vi
10 | *~
11 | *.sass-cache
12 |
13 | # OS or Editor folders
14 | .DS_Store
15 | Thumbs.db
16 | .cache
17 | .project
18 | .settings
19 | .tmproj
20 | *.esproj
21 | nbproject
22 |
23 | # Dreamweaver added files
24 | _notes
25 | dwsync.xml
26 |
27 | # Komodo
28 | *.komodoproject
29 | .komodotools
30 |
31 | # Folders to ignore
32 | .hg
33 | .svn
34 | .CVS
35 | intermediate
36 | publish
37 | .idea
38 | requests/*
39 |
40 | # Custom configuration to ignore
41 | /config.php
--------------------------------------------------------------------------------
/.htaccess:
--------------------------------------------------------------------------------
1 | # Disable MultiViews, If this is not turned off it may cause
2 | # the redirection of /deploy to go to /deploy.php
3 | Options -MultiViews
4 |
5 | RewriteEngine On
6 |
7 | # Some hosts may require you to use the `RewriteBase` directive.
8 | # If you need to use the `RewriteBase` directive, it should be the
9 | # absolute physical path to the directory that contains this htaccess file.
10 | #
11 | # RewriteBase /
12 |
13 | RewriteCond %{REQUEST_FILENAME} !-f
14 | RewriteRule ^ index.php [QSA,L]
15 |
16 | # Deny access to config.php
17 |
18 | Order Allow,Deny
19 | Deny from all
20 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Jesal Gadhia
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SlimJim
2 | =======
3 |
4 | ### WHY?
5 |
6 | SlimJim was born out of a need for a simple auto update script which would update multiple development/test environments every time someone commits to their respective GitHub or BitBucket repositories.
7 |
8 | I know there are many deployment/build scripts out there like whiskey_disk, Vlad and Capistrano which can do this if coupled with a CI server like cijoe, Jenkins, etc.
9 |
10 | But I found them to be more complicated to setup just for a basic need i.e to simply update a development/test environment using a post-receive hook without any manual user interaction on behalf of the committer besides ``git push...``
11 |
12 | 
13 |
14 | ### INSTALLATION
15 |
16 | To configure SlimJim on your server just follow these 4 steps:
17 |
18 | 1) **Setup site and DB**
19 |
20 | Basic LAMP website setup should suffice. Everything you need is in this repo. I'm using a PHP micro-framework called Slim (thus the name!) which requires PHP 5.3.0 or newer.
21 |
22 | Run `slimjim.sql` on your MySql server.
23 |
24 | Copy `config.sample.php` to `config.php` in the root folder and modify the following variables as needed:
25 |
26 | class CUSTOM_CONFIG {
27 | /* Paths */
28 | public static $ROOT_PATH = '/srv/www/slimjim.yourcompany.com/public_html/';
29 |
30 | /* MySQL */
31 | public static $DB_NAME = 'slimjim';
32 | public static $DB_HOST = 'localhost';
33 | public static $DB_USER = 'root';
34 | public static $DB_PASS = '';
35 | }
36 |
37 | For all the projects that you want to auto-update, add the name of the github repo, branch and the physical path on your server to the projects table.
38 |
39 | Alternatively, you can also manage projects and other settings by going to the administrative interface located at /admin
40 |
41 | 2) **Install & setup [incron](http://inotify.aiken.cz/?section=incron&page=about&lang=en)**
42 |
43 | When the site receives a payload from the post-receive hook it will drop a request in the /requests folder. Incron is needed to listen for that event and trigger the deploy script.
44 |
45 | ``root@yourhost:/# apt-get install incron``
46 |
47 | Add the root user to your allow list
48 |
49 | ``root@yourhost:/# vi /etc/incron.allow``
50 |
51 | Add this, save and quit:
52 |
53 | ``root``
54 |
55 | Now watch your requests directory for updates
56 |
57 | ``root@yourhost:/# incrontab -e``
58 |
59 | Add this, save and quit:
60 |
61 | ``/srv/www/slimjim.yourcompany.com/public_html/requests/ IN_CLOSE_WRITE php /srv/www/slimjim.yourcompany.com/public_html/deploy.php $#``
62 |
63 | 3) **Permissions**
64 |
65 | Give execute permissions to the deploy script
66 |
67 | ``root@yourhost:/# chmod +x deploy.php``
68 |
69 | Allow writing to the requests folder
70 |
71 | ``root@yourhost:/# chmod 777 /srv/www/slimjim.yourcompany.com/public_html/requests``
72 |
73 | Give permissions to pull from github to the root user (make sure to leave the password empty)
74 |
75 | ``root@yourhost:/# ssh-keygen -t rsa -C "root@yourhost"``
76 |
77 | Copy the contents from ~/.ssh/id_rsa.pub and [add to GitHub][1] or [add to BitBucket][2]
78 |
79 | 4) **Add Post-Receive Webhook**
80 |
81 | Finally, add the appropriate one of these URLs as a webhook into your repository settings:
82 |
83 | For GitHub: ``http://slimjim.yourcompany.com/gh_hook``
84 |
85 | For BitBucket: ``http://slimjim.yourcompany.com/bb_hook``
86 |
87 | That's it! Now sit back and watch SlimJim do the tedious work! :)
88 |
89 | ### CONTRIBUTE!
90 |
91 | Now if you like what this does, feel free to improve upon code. Just follow these steps to contribute:
92 |
93 | 1. Fork it
94 | 2. Create your feature branch (``git checkout -b my-new-feature``)
95 | 3. Commit your changes (``git commit -am 'Add some feature'``)
96 | 4. Push to the branch (``git push origin my-new-feature``)
97 | 5. Issue a [pull request](https://help.github.com/articles/using-pull-requests) to my **develop** branch
98 | 6. I will test out your cool feature on develop and do a release to master soon thereafter! :)
99 |
100 |
101 | [1]: https://help.github.com/articles/generating-ssh-keys
102 | [2]: https://confluence.atlassian.com/display/BITBUCKET/Add+an+SSH+key+to+an+account
--------------------------------------------------------------------------------
/SlimJim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jesalg/SlimJim/5908cccf2b496496c1bb4a0fecca9e4f7d337458/SlimJim.png
--------------------------------------------------------------------------------
/admin/.htaccess:
--------------------------------------------------------------------------------
1 | RewriteEngine On
2 |
3 | # Some hosts may require you to use the `RewriteBase` directive.
4 | # If you need to use the `RewriteBase` directive, it should be the
5 | # absolute physical path to the directory that contains this htaccess file.
6 | #
7 | # RewriteBase /
8 |
9 | RewriteCond %{REQUEST_FILENAME} !-f
10 | RewriteRule ^ index.php [QSA,L]
--------------------------------------------------------------------------------
/admin/css/slimjim.css:
--------------------------------------------------------------------------------
1 | /*
2 | Document : slimjim
3 | Created on : Sep 13, 2012, 3:11:48 PM
4 | Author : atorres
5 | Description:
6 | Purpose of the stylesheet follows.
7 | */
8 |
9 | .header:after {
10 | bottom: 0;
11 | content: "";
12 | display: block;
13 | left: 0;
14 | opacity: 0.4;
15 | position: absolute;
16 | right: 0;
17 | top: 0;
18 | }
19 | .masthead {
20 | color: #FFFFFF;
21 | margin-bottom: 0;
22 | padding: 70px 0 80px;
23 | }
24 | .header {
25 | background: -moz-linear-gradient(45deg, #020031 0%, #6D3353 100%) repeat scroll 0 0 transparent; background: -webkit-linear-gradient(45deg, #020031 0%, #6D3353 100%) repeat scroll 0 0 transparent;
26 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.2) inset, 0 -3px 7px rgba(0, 0, 0, 0.2) inset;
27 | color: #FFFFFF;
28 | padding: 40px 0;
29 | position: relative;
30 | text-align: center;
31 | text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 0 30px rgba(0, 0, 0, 0.075);
32 | }
33 |
34 | #data-content{
35 | max-width: 950px;
36 | margin: 0px auto;
37 | margin-top: 100px;
38 | margin-bottom: 100px;
39 | }
40 |
41 | #footer {
42 | position:fixed;
43 | bottom:0;
44 | width:100%;
45 | background: -moz-linear-gradient(45deg, #020031 0%, #6D3353 100%) repeat scroll 0 0 transparent; background: -webkit-linear-gradient(45deg, #020031 0%, #6D3353 100%) repeat scroll 0 0 transparent;
46 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.2) inset, 0 -3px 7px rgba(0, 0, 0, 0.2) inset;
47 | color: #FFFFFF;
48 | padding: 10px;
49 | text-align: center;
50 | }
51 |
52 | #flash-message{
53 | text-align: center;
54 | margin-top: 10px;
55 | margin-bottom: 10px;
56 | }
57 |
58 | #flash-message .success{
59 | padding: 10px;
60 | background-color: #DFF0D8;
61 | }
62 |
63 | #flash-message .error{
64 | padding: 10px;
65 | background-color: #F2DEDE;
66 | }
67 |
68 |
69 |
--------------------------------------------------------------------------------
/admin/index.php:
--------------------------------------------------------------------------------
1 | new CustomView()
21 | ));
22 |
23 | $app->add(new Slim_Middleware_SessionCookie(array(
24 | 'expires' => '1440 minutes',
25 | 'name' => 'slim_session',
26 | 'secret' => 'slimjim'
27 | )));
28 |
29 | $app->add(new Slim_Middleware_Flash());
30 |
31 | //default layout
32 | CustomView::set_layout('/layouts/default.php');
33 |
34 | //Set base URL
35 | $app->hook('slim.before', function () use ($app) {
36 | if(isset($_SERVER['HTTP_HOST'])){
37 | $base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
38 | $base_url .= '://'. $_SERVER['HTTP_HOST'];
39 | $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
40 | }else{
41 | $base_url = 'http://localhost';
42 | }
43 |
44 | define('base_url', $base_url);
45 | });
46 |
47 | // Auth Check.
48 | $authCheck = function() use ($app) {
49 | if (!isset($_SESSION['username'])) {
50 | CustomView::set_layout('/layouts/login.php');
51 | $app->render('loginForm.php', array());
52 | exit;
53 | }
54 | };
55 |
56 | //Admin Home
57 | $app->get('/', $authCheck, function () use ($app) {
58 | $data['currNav'] = 'home';
59 |
60 | $app->render('home.php', array('data' => $data));
61 | });
62 |
63 | //Validate the username and password
64 | $app->post('/login', function () use ($app) {
65 | if($app->request()->isPost()){
66 | $req = $app->request();
67 | $inputUsername = $req->post('username');
68 | $inputpassword = $req->post('password');
69 |
70 | $user = Model::factory('Admin')
71 | ->where_equal('username', $inputUsername)
72 | ->where_equal('password', md5($inputpassword))
73 | ->find_one();
74 | if(isset($user->username)){
75 | if($user->username == $inputUsername){
76 | $_SESSION['username'] = $inputUsername;
77 | $app->flash('success', 'Welcome ' . $inputUsername);
78 | }
79 | }else{
80 | $app->flash('error', 'User does not exist!');
81 | }
82 | }else{
83 | $app->flash('error', 'you must insert your credentials!');
84 | }
85 |
86 | $app->redirect('/admin');
87 | });
88 |
89 | //Logout
90 | $app->get('/logout', function () use ($app) {
91 | $_SESSION = array();
92 |
93 | $data['currNav'] = 'home';
94 | $app->flash('error', 'You are logged out!');
95 | $app->redirect('/admin', array('data' => $data));
96 | });
97 |
98 | //Show Projects
99 | $app->get('/projects', $authCheck, function () use ($app) {
100 | $data['projects'] = Model::factory('Project')->find_many();
101 | $data['currNav'] = 'projects';
102 | $app->render('projects/projects.php', array('data' => $data));
103 | });
104 |
105 | //Add and edit project
106 | $app->get('/projects/add/:id', $authCheck, function ($id = 0) use ($app) {
107 | $data['currNav'] = 'projects';
108 |
109 | //Edit
110 | if($id > 0){
111 | $data['project'] = ORM::for_table('projects')->find_one($id);
112 | }
113 |
114 | $app->render('projects/addProject.php', array('data' => $data));
115 | });
116 |
117 | //Create new project or edit it
118 | $app->post('/projects/add', $authCheck, function () use ($app) {
119 | $data['currNav'] = 'projects';
120 | $data['projects'] = Model::factory('Project')->find_many();
121 |
122 | //Validate
123 | if($app->request()->post('clone_url')){
124 |
125 | //Edit
126 | if($app->request()->post('id')){
127 | $project = ORM::for_table('projects')->find_one($app->request()->post('id'));
128 | $app->flash('success', 'Project updated!');
129 |
130 | }else{ //New Item
131 | $project = ORM::for_table('projects')->create();
132 | $app->flash('success', 'Project created!');
133 | }
134 |
135 | $project->clone_url = $app->request()->post('clone_url');
136 | $project->name = $app->request()->post('name');
137 | $project->branch = $app->request()->post('branch');
138 | $project->path = $app->request()->post('path');
139 | $project->save();
140 | }else{
141 | $app->flash('error', 'Project could not be created!');
142 | }
143 |
144 | $app->redirect('/admin/projects', array('data' => $data));
145 | });
146 |
147 | //Remove the project
148 | $app->get('/projects/delete/:id', $authCheck, function ($id) use ($app){
149 | $data['currNav'] = 'projects';
150 | $data['projects'] = Model::factory('Project')->find_many();
151 |
152 | $project = ORM::for_table('projects')->find_one($id);
153 | $project->delete();
154 |
155 | $app->flash('error', 'Project Removed!');
156 |
157 | $app->redirect('/admin/projects', array('data' => $data));
158 | });
159 |
160 | //Show settings
161 | $app->get('/settings', $authCheck, function () use ($app) {
162 | $data['currNav'] = 'settings';
163 | $data['settings'] = Model::factory('Setting')->find_many();
164 |
165 | $app->render('settings/settings.php', array('data' => $data));
166 | });
167 |
168 | //Add and edit settings form
169 | $app->get('/settings/add/:id', $authCheck, function ($id) use ($app) {
170 | $data['currNav'] = 'settings';
171 |
172 | //Edit
173 | if($id > 0){
174 | $data['setting'] = ORM::for_table('settings')->find_one($id);
175 | }
176 |
177 | $app->render('settings/addSetting.php', array('data' => $data));
178 | });
179 |
180 | //Create new setting or edit it
181 | $app->post('/settings/add', $authCheck, function () use ($app) {
182 | $data['currNav'] = 'settings';
183 | $data['settings'] = Model::factory('Setting')->find_many();
184 |
185 | //Validate
186 | if($app->request()->post('key') != ''){
187 |
188 | //Edit
189 | if($app->request()->post('id')){
190 | $setting = ORM::for_table('settings')->find_one($app->request()->post('id'));
191 | $app->flash('success', 'Setting updated!');
192 |
193 | }else{ //New Item
194 | $setting = ORM::for_table('settings')->create();
195 | $app->flash('success', 'Setting created!');
196 | }
197 |
198 | $setting->key = $app->request()->post('key');
199 | $setting->value = $app->request()->post('value');
200 | $setting->save();
201 | }else{
202 | $app->flash('error', 'Setting could not be created!');
203 | }
204 |
205 | $app->redirect('/admin/settings', array('data' => $data));
206 | });
207 |
208 | //Remove the setting
209 | $app->get('/settings/delete/:id', $authCheck, function ($id) use ($app){
210 | $data['currNav'] = 'settings';
211 | $data['settings'] = Model::factory('Setting')->find_many();
212 |
213 | $setting = ORM::for_table('settings')->find_one($id);
214 | $setting->delete();
215 |
216 | $app->flash('success', 'Setting Removed!');
217 |
218 | $app->redirect('/admin/settings', array('data' => $data));
219 | });
220 |
221 | //Show change password form
222 | $app->get('/profile', $authCheck, function () use ($app) {
223 | $data['currNav'] = 'profile';
224 | $app->render('profile/profile.php', array('data' => $data));
225 | });
226 |
227 | //Change the password
228 | $app->post('/profile', $authCheck, function () use ($app) {
229 | $data['currNav'] = 'profile';
230 | if($app->request()->post('password') == '' || $app->request()->post('repassword') == ''){
231 | $app->flashNow('error', 'Please inset a valid password!');
232 | }elseif($app->request()->post('password') == $app->request()->post('repassword')){
233 | $user = ORM::for_table('admins')->where('username', 'admin')->find_one();
234 | $user->password = md5($app->request()->post('password'));
235 |
236 | $user->save();
237 | $app->flashNow('success', 'Password Saved!');
238 | }else{
239 | $app->flashNow('error', 'Password did not match, Please try again!');
240 | }
241 |
242 | $app->render('profile/profile.php', array('data' => $data));
243 | });
244 |
245 |
246 | $app->run();
247 |
248 | ?>
249 |
--------------------------------------------------------------------------------
/admin/templates/home.php:
--------------------------------------------------------------------------------
1 |
2 |
Welcome = $_SESSION['username']?>! Add your project information and project settings and watch SlimJim do the work for you.
3 |
Please click Projects to manage your projects information, you can add, edit or delete information
4 |
Modify your Settings in this link.
5 |
Do not forget to change your default password here
6 |
--------------------------------------------------------------------------------
/admin/templates/layouts/default.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SlimJim CMS
6 |
7 |
8 |
9 |
10 |
11 |
12 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | = $flash['error']?>
54 |
55 |
56 |
57 |
58 | = $flash['success']?>
59 |
60 |
61 |
62 |
63 | = $_html?>
64 |
65 |
66 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/admin/templates/layouts/login.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SlimJim CMS
6 |
7 |
8 |
9 |
10 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 | = $flash['error']?>
24 |
25 |
26 |
27 |
28 | = $flash['success']?>
29 |
30 |
31 |
32 |
33 | = $_html?>
34 |
35 |
36 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/admin/templates/loginForm.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/templates/profile/profile.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/templates/projects/addProject.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/templates/projects/projects.php:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | clone_url |
9 | name |
10 | branch |
11 | path |
12 | actions |
13 |
14 |
15 |
16 |
17 |
18 | = $project->clone_url?> |
19 | = $project->name?> |
20 | = $project->branch?> |
21 | = $project->path?> |
22 | Edit Remove |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/admin/templates/settings/addSetting.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/templates/settings/settings.php:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | key |
9 | value |
10 | actions |
11 |
12 |
13 |
14 |
15 |
16 | = $setting->key?> |
17 | = $setting->value?> |
18 | Edit Remove |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/config.sample.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/deploy.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | &1"));
30 | }
31 |
32 | sleep(1);
33 |
34 | $hooks = @ Spyc::YAMLLoad($request_data['hook_path']) ?: array();
35 |
36 | syslog(LOG_INFO, serialize($hooks));
37 |
38 | if(isset($hooks['writable'])) {
39 | foreach($hooks['writable'] AS $make_writeable) {
40 | $cmd = "chmod 777 -R " . $make_writeable . " 2>&1";
41 | syslog(LOG_INFO, $cmd);
42 | syslog(LOG_INFO, "===== " . shell_exec($cmd));
43 | }
44 | }
45 |
46 | if(isset($hooks['after_deploy'])) {
47 | foreach($hooks['after_deploy'] AS $after_deploy) {
48 | $cmd = $after_deploy . " 2>&1";
49 | syslog(LOG_INFO, $cmd);
50 | syslog(LOG_INFO, "===== " . shell_exec($cmd));
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | find_many() ?: array()) AS $obj) {
16 | $settings[$obj->key] = $obj->value;
17 | }
18 |
19 | $app = new Slim(array(
20 | 'settings' => $settings
21 | ));
22 |
23 | function get_github_meta() {
24 | $curl_handle=curl_init();
25 | curl_setopt($curl_handle, CURLOPT_URL,'https://api.github.com/meta');
26 | curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
27 | curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
28 | curl_setopt($curl_handle, CURLOPT_USERAGENT, 'SlimJim');
29 | /* Curl SSL verification can be bypassed, e.g. for a server with self-signed certificates without ca-chain. */
30 | $curl_ssl_verification = (isset(CUSTOM_CONFIG::$GITHUB_CURL_SSL_VERIFICATION)) ? (bool)CUSTOM_CONFIG::$GITHUB_CURL_SSL_VERIFICATION : true;
31 | curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, ($curl_ssl_verification ? 2 : false));
32 | curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, $curl_ssl_verification);
33 | $response = curl_exec($curl_handle);
34 | $github_meta = json_decode($response);
35 | curl_close($curl_handle);
36 | return $github_meta;
37 | };
38 |
39 | function cidr_match($ip, $cidrs) {
40 | $result = false;
41 | foreach($cidrs as $cidr) {
42 | list($subnet, $mask) = explode('/', $cidr);
43 | if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1) ) == ip2long($subnet)) {
44 | $result = true;
45 | }
46 | }
47 | return $result;
48 | };
49 |
50 | function create_request($repo_name, $repo_branch, $after_sha) {
51 | global $app;
52 | $deploy_settings = $app->config('settings');
53 |
54 | $arrProjects = Model::factory('Project')
55 | ->where_equal('name', $repo_name)
56 | ->where_equal('branch', $repo_branch)
57 | ->find_many();
58 |
59 | foreach ($arrProjects as $project) {
60 | if($project) {
61 | file_put_contents('requests/' . $project->id . "_" . $after_sha . '.txt', serialize(array(
62 | 'name' => $project->name,
63 | 'clone_url' => $project->clone_url,
64 | 'path' => $project->path,
65 | 'branch' => $project->branch,
66 | 'hook_path' => $project->path . $deploy_settings['hook_file']
67 | )), LOCK_EX);
68 | }
69 | }
70 | };
71 |
72 | $app->get('/', function() use ($app) {
73 | echo "Silence is golden";
74 | });
75 |
76 | $app->post('/gh_hook', function() use ($app) {
77 |
78 | if (!isset(CUSTOM_CONFIG::$GITHUB_CIDR_VERIFICATION) || CUSTOM_CONFIG::$GITHUB_CIDR_VERIFICATION) {
79 |
80 | $github_meta = get_github_meta();
81 | $cidrs = isset($github_meta->hooks) ? $github_meta->hooks : array();
82 |
83 | if(!cidr_match($app->request()->getIp(), $cidrs)) {
84 | $app->halt(401);
85 | }
86 |
87 | }
88 |
89 | if(!($payload = $app->request()->params('payload'))) {
90 | $app->halt(403);
91 | }
92 |
93 | $payload = json_decode($payload);
94 |
95 | if(isset($payload->repository) && isset($payload->ref)) {
96 | $payload_branch = explode("/", $payload->ref);
97 | //Allow branches with slashes, such as implemented by git-flow (e.g. release/v1.1)
98 | $payload_branch = substr($payload->ref, strlen($payload_branch[0]."/".$payload_branch[1])+1);
99 | create_request($payload->repository->name, $payload_branch, $payload->after);
100 | } else {
101 | $app->halt(400);
102 | }
103 | });
104 |
105 | $app->post('/bb_hook', function() use ($app) {
106 | $bitbucket_ips = array('131.103.20.165','131.103.20.166');
107 |
108 | if(!in_array($app->request()->getIp(), $bitbucket_ips)) {
109 | $app->halt(401);
110 | }
111 |
112 | if(!($payload = $app->request()->params('payload'))) {
113 | $app->halt(403);
114 | }
115 |
116 | $payload = json_decode($payload);
117 |
118 | if(isset($payload->repository)) {
119 | $payload_branch = $payload->commits[0]->branch;
120 | $after_sha = $payload->commits[0]->parents[0];
121 | create_request($payload->repository->slug, $payload_branch, $after_sha);
122 | } else {
123 | $app->halt(400);
124 | }
125 | });
126 |
127 | $app->run();
--------------------------------------------------------------------------------
/libs/Paris/paris.php:
--------------------------------------------------------------------------------
1 | _class_name = $class_name;
66 | }
67 |
68 | /**
69 | * Add a custom filter to the method chain specified on the
70 | * model class. This allows custom queries to be added
71 | * to models. The filter should take an instance of the
72 | * ORM wrapper as its first argument and return an instance
73 | * of the ORM wrapper. Any arguments passed to this method
74 | * after the name of the filter will be passed to the called
75 | * filter function as arguments after the ORM class.
76 | */
77 | public function filter() {
78 | $args = func_get_args();
79 | $filter_function = array_shift($args);
80 | array_unshift($args, $this);
81 | if (method_exists($this->_class_name, $filter_function)) {
82 | return call_user_func_array(array($this->_class_name, $filter_function), $args);
83 | }
84 | }
85 |
86 | /**
87 | * Factory method, return an instance of this
88 | * class bound to the supplied table name.
89 | */
90 | public static function for_table($table_name) {
91 | self::_setup_db();
92 | return new self($table_name);
93 | }
94 |
95 | /**
96 | * Method to create an instance of the model class
97 | * associated with this wrapper and populate
98 | * it with the supplied Idiorm instance.
99 | */
100 | protected function _create_model_instance($orm) {
101 | if ($orm === false) {
102 | return false;
103 | }
104 | $model = new $this->_class_name();
105 | $model->set_orm($orm);
106 | return $model;
107 | }
108 |
109 | /**
110 | * Wrap Idiorm's find_one method to return
111 | * an instance of the class associated with
112 | * this wrapper instead of the raw ORM class.
113 | */
114 | public function find_one($id=null) {
115 | return $this->_create_model_instance(parent::find_one($id));
116 | }
117 |
118 | /**
119 | * Wrap Idiorm's find_many method to return
120 | * an array of instances of the class associated
121 | * with this wrapper instead of the raw ORM class.
122 | */
123 | public function find_many() {
124 | return array_map(array($this, '_create_model_instance'), parent::find_many());
125 | }
126 |
127 | /**
128 | * Wrap Idiorm's create method to return an
129 | * empty instance of the class associated with
130 | * this wrapper instead of the raw ORM class.
131 | */
132 | public function create($data=null) {
133 | return $this->_create_model_instance(parent::create($data));
134 | }
135 | }
136 |
137 | /**
138 | * Model base class. Your model objects should extend
139 | * this class. A minimal subclass would look like:
140 | *
141 | * class Widget extends Model {
142 | * }
143 | *
144 | */
145 | class Model {
146 |
147 | // Default ID column for all models. Can be overridden by adding
148 | // a public static _id_column property to your model classes.
149 | const DEFAULT_ID_COLUMN = 'id';
150 |
151 | // Default foreign key suffix used by relationship methods
152 | const DEFAULT_FOREIGN_KEY_SUFFIX = '_id';
153 |
154 | /**
155 | * The ORM instance used by this model
156 | * instance to communicate with the database.
157 | */
158 | public $orm;
159 |
160 | /**
161 | * Retrieve the value of a static property on a class. If the
162 | * class or the property does not exist, returns the default
163 | * value supplied as the third argument (which defaults to null).
164 | */
165 | protected static function _get_static_property($class_name, $property, $default=null) {
166 | if (!class_exists($class_name) || !property_exists($class_name, $property)) {
167 | return $default;
168 | }
169 | $properties = get_class_vars($class_name);
170 | return $properties[$property];
171 | }
172 |
173 | /**
174 | * Static method to get a table name given a class name.
175 | * If the supplied class has a public static property
176 | * named $_table, the value of this property will be
177 | * returned. If not, the class name will be converted using
178 | * the _class_name_to_table_name method method.
179 | */
180 | protected static function _get_table_name($class_name) {
181 | $specified_table_name = self::_get_static_property($class_name, '_table');
182 | if (is_null($specified_table_name)) {
183 | return self::_class_name_to_table_name($class_name);
184 | }
185 | return $specified_table_name;
186 | }
187 |
188 | /**
189 | * Static method to convert a class name in CapWords
190 | * to a table name in lowercase_with_underscores.
191 | * For example, CarTyre would be converted to car_tyre.
192 | */
193 | protected static function _class_name_to_table_name($class_name) {
194 | return strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $class_name));
195 | }
196 |
197 | /**
198 | * Return the ID column name to use for this class. If it is
199 | * not set on the class, returns null.
200 | */
201 | protected static function _get_id_column_name($class_name) {
202 | return self::_get_static_property($class_name, '_id_column', self::DEFAULT_ID_COLUMN);
203 | }
204 |
205 | /**
206 | * Build a foreign key based on a table name. If the first argument
207 | * (the specified foreign key column name) is null, returns the second
208 | * argument (the name of the table) with the default foreign key column
209 | * suffix appended.
210 | */
211 | protected static function _build_foreign_key_name($specified_foreign_key_name, $table_name) {
212 | if (!is_null($specified_foreign_key_name)) {
213 | return $specified_foreign_key_name;
214 | }
215 | return $table_name . self::DEFAULT_FOREIGN_KEY_SUFFIX;
216 | }
217 |
218 | /**
219 | * Factory method used to acquire instances of the given class.
220 | * The class name should be supplied as a string, and the class
221 | * should already have been loaded by PHP (or a suitable autoloader
222 | * should exist). This method actually returns a wrapped ORM object
223 | * which allows a database query to be built. The wrapped ORM object is
224 | * responsible for returning instances of the correct class when
225 | * its find_one or find_many methods are called.
226 | */
227 | public static function factory($class_name) {
228 | $table_name = self::_get_table_name($class_name);
229 | $wrapper = ORMWrapper::for_table($table_name);
230 | $wrapper->set_class_name($class_name);
231 | $wrapper->use_id_column(self::_get_id_column_name($class_name));
232 | return $wrapper;
233 | }
234 |
235 | /**
236 | * Internal method to construct the queries for both the has_one and
237 | * has_many methods. These two types of association are identical; the
238 | * only difference is whether find_one or find_many is used to complete
239 | * the method chain.
240 | */
241 | protected function _has_one_or_many($associated_class_name, $foreign_key_name=null) {
242 | $base_table_name = self::_get_table_name(get_class($this));
243 | $foreign_key_name = self::_build_foreign_key_name($foreign_key_name, $base_table_name);
244 | return self::factory($associated_class_name)->where($foreign_key_name, $this->id());
245 | }
246 |
247 | /**
248 | * Helper method to manage one-to-one relations where the foreign
249 | * key is on the associated table.
250 | */
251 | protected function has_one($associated_class_name, $foreign_key_name=null) {
252 | return $this->_has_one_or_many($associated_class_name, $foreign_key_name);
253 | }
254 |
255 | /**
256 | * Helper method to manage one-to-many relations where the foreign
257 | * key is on the associated table.
258 | */
259 | protected function has_many($associated_class_name, $foreign_key_name=null) {
260 | return $this->_has_one_or_many($associated_class_name, $foreign_key_name);
261 | }
262 |
263 | /**
264 | * Helper method to manage one-to-one and one-to-many relations where
265 | * the foreign key is on the base table.
266 | */
267 | protected function belongs_to($associated_class_name, $foreign_key_name=null) {
268 | $associated_table_name = self::_get_table_name($associated_class_name);
269 | $foreign_key_name = self::_build_foreign_key_name($foreign_key_name, $associated_table_name);
270 | $associated_object_id = $this->$foreign_key_name;
271 | return self::factory($associated_class_name)->where_id_is($associated_object_id);
272 | }
273 |
274 | /**
275 | * Helper method to manage many-to-many relationships via an intermediate model. See
276 | * README for a full explanation of the parameters.
277 | */
278 | protected function has_many_through($associated_class_name, $join_class_name=null, $key_to_base_table=null, $key_to_associated_table=null) {
279 | $base_class_name = get_class($this);
280 |
281 | // The class name of the join model, if not supplied, is
282 | // formed by concatenating the names of the base class
283 | // and the associated class, in alphabetical order.
284 | if (is_null($join_class_name)) {
285 | $class_names = array($base_class_name, $associated_class_name);
286 | sort($class_names, SORT_STRING);
287 | $join_class_name = join("", $class_names);
288 | }
289 |
290 | // Get table names for each class
291 | $base_table_name = self::_get_table_name($base_class_name);
292 | $associated_table_name = self::_get_table_name($associated_class_name);
293 | $join_table_name = self::_get_table_name($join_class_name);
294 |
295 | // Get ID column names
296 | $base_table_id_column = self::_get_id_column_name($base_class_name);
297 | $associated_table_id_column = self::_get_id_column_name($associated_class_name);
298 |
299 | // Get the column names for each side of the join table
300 | $key_to_base_table = self::_build_foreign_key_name($key_to_base_table, $base_table_name);
301 | $key_to_associated_table = self::_build_foreign_key_name($key_to_associated_table, $associated_table_name);
302 |
303 | return self::factory($associated_class_name)
304 | ->select("{$associated_table_name}.*")
305 | ->join($join_table_name, array("{$associated_table_name}.{$associated_table_id_column}", '=', "{$join_table_name}.{$key_to_associated_table}"))
306 | ->where("{$join_table_name}.{$key_to_base_table}", $this->id());
307 | }
308 |
309 | /**
310 | * Set the wrapped ORM instance associated with this Model instance.
311 | */
312 | public function set_orm($orm) {
313 | $this->orm = $orm;
314 | }
315 |
316 | /**
317 | * Magic getter method, allows $model->property access to data.
318 | */
319 | public function __get($property) {
320 | return $this->orm->get($property);
321 | }
322 |
323 | /**
324 | * Magic setter method, allows $model->property = 'value' access to data.
325 | */
326 | public function __set($property, $value) {
327 | $this->orm->set($property, $value);
328 | }
329 |
330 | /**
331 | * Magic isset method, allows isset($model->property) to work correctly.
332 | */
333 | public function __isset($property) {
334 | return $this->orm->__isset($property);
335 | }
336 |
337 | /**
338 | * Getter method, allows $model->get('property') access to data
339 | */
340 | public function get($property) {
341 | return $this->orm->get($property);
342 | }
343 |
344 | /**
345 | * Setter method, allows $model->set('property', 'value') access to data.
346 | */
347 | public function set($property, $value) {
348 | $this->orm->set($property, $value);
349 | }
350 |
351 | /**
352 | * Check whether the given field has changed since the object was created or saved
353 | */
354 | public function is_dirty($property) {
355 | return $this->orm->is_dirty($property);
356 | }
357 |
358 | /**
359 | * Wrapper for Idiorm's as_array method.
360 | */
361 | public function as_array() {
362 | $args = func_get_args();
363 | return call_user_func_array(array($this->orm, 'as_array'), $args);
364 | }
365 |
366 | /**
367 | * Save the data associated with this model instance to the database.
368 | */
369 | public function save() {
370 | return $this->orm->save();
371 | }
372 |
373 | /**
374 | * Delete the database row associated with this model instance.
375 | */
376 | public function delete() {
377 | return $this->orm->delete();
378 | }
379 |
380 | /**
381 | * Get the database ID of this model instance.
382 | */
383 | public function id() {
384 | return $this->orm->id();
385 | }
386 |
387 | /**
388 | * Hydrate this model instance with an associative array of data.
389 | * WARNING: The keys in the array MUST match with columns in the
390 | * corresponding database table. If any keys are supplied which
391 | * do not match up with columns, the database will throw an error.
392 | */
393 | public function hydrate($data) {
394 | $this->orm->hydrate($data)->force_all_dirty();
395 | }
396 | }
397 |
--------------------------------------------------------------------------------
/libs/Slim/CustomView.php:
--------------------------------------------------------------------------------
1 | data);
15 | $templatePath = $this->getTemplatesDirectory() . '/' . ltrim($template, '/');
16 | if ( !file_exists($templatePath) ) {
17 | throw new RuntimeException('View cannot render template `' . $templatePath . '`. Template does not exist.');
18 | }
19 | ob_start();
20 | require $templatePath;
21 | $html = ob_get_clean();
22 | return $this->_render_layout($html);
23 | }
24 |
25 | public function _render_layout($_html)
26 | {
27 | extract($this->data);
28 | if(isset($_SERVER['HTTP_HOST'])){
29 | $data['base_url'] = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
30 | $data['base_url'] .= '://'. $_SERVER['HTTP_HOST'];
31 | $data['base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
32 | }else{
33 | $data['base_url'] = 'http://localhost';
34 | }
35 |
36 | if(self::$_layout !== NULL)
37 | {
38 | $layout_path = $this->getTemplatesDirectory() . '/' . ltrim(self::$_layout, '/');
39 | if ( !file_exists($layout_path) ) {
40 | throw new RuntimeException('View cannot render layout `' . $layout_path . '`. Layout does not exist.');
41 | }
42 | ob_start();
43 | require $layout_path;
44 | $_html = ob_get_clean();
45 | }
46 | return $_html;
47 | }
48 | }
--------------------------------------------------------------------------------
/libs/Slim/Environment.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Environment
36 | *
37 | * This class creates and returns a key/value array of common
38 | * environment variables for the current HTTP request.
39 | *
40 | * This is a singleton class; derived environment variables will
41 | * be common across multiple Slim applications.
42 | *
43 | * This class matches the Rack (Ruby) specification as closely
44 | * as possible. More information available below.
45 | *
46 | * @package Slim
47 | * @author Josh Lockhart
48 | * @since 1.6.0
49 | */
50 | class Slim_Environment implements ArrayAccess, IteratorAggregate {
51 | /**
52 | * @var array
53 | */
54 | protected $properties;
55 |
56 | /**
57 | * @var Slim_Environment
58 | */
59 | protected static $environment;
60 |
61 | /**
62 | * Get environment instance (singleton)
63 | *
64 | * This creates and/or returns an Environment instance (singleton)
65 | * derived from $_SERVER variables. You may override the global server
66 | * variables by using `Environment::mock()` instead.
67 | *
68 | * @param bool $refresh Refresh properties using global server variables?
69 | * @return Slim_Environment
70 | */
71 | public static function getInstance( $refresh = false ) {
72 | if ( is_null(self::$environment) || $refresh ) {
73 | self::$environment = new self();
74 | }
75 | return self::$environment;
76 | }
77 |
78 | /**
79 | * Get mock environment instance
80 | *
81 | * @param array $userSettings
82 | * @return Environment
83 | */
84 | public static function mock( $userSettings = array() ) {
85 | self::$environment = new self(array_merge(array(
86 | 'REQUEST_METHOD' => 'GET',
87 | 'SCRIPT_NAME' => '',
88 | 'PATH_INFO' => '',
89 | 'QUERY_STRING' => '',
90 | 'SERVER_NAME' => 'localhost',
91 | 'SERVER_PORT' => 80,
92 | 'ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
93 | 'ACCEPT_LANGUAGE' => 'en-US,en;q=0.8',
94 | 'ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
95 | 'USER_AGENT' => 'Slim Framework',
96 | 'REMOTE_ADDR' => '127.0.0.1',
97 | 'slim.url_scheme' => 'http',
98 | 'slim.input' => '',
99 | 'slim.errors' => @fopen('php://stderr', 'w')
100 | ), $userSettings));
101 | return self::$environment;
102 | }
103 |
104 | /**
105 | * Constructor (private access)
106 | *
107 | * @param array|null $settings If present, these are used instead of global server variables
108 | * @return void
109 | */
110 | private function __construct( $settings = null ) {
111 | if ( $settings ) {
112 | $this->properties = $settings;
113 | } else {
114 | $env = array();
115 |
116 | //The HTTP request method
117 | $env['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD'];
118 |
119 | //The IP
120 | $env['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
121 |
122 | /**
123 | * Application paths
124 | *
125 | * This derives two paths: SCRIPT_NAME and PATH_INFO. The SCRIPT_NAME
126 | * is the real, physical path to the application, be it in the root
127 | * directory or a subdirectory of the public document root. The PATH_INFO is the
128 | * virtual path to the requested resource within the application context.
129 | *
130 | * With htaccess, the SCRIPT_NAME will be an absolute path (without file name);
131 | * if not using htaccess, it will also include the file name. If it is "/",
132 | * it is set to an empty string (since it cannot have a trailing slash).
133 | *
134 | * The PATH_INFO will be an absolute path with a leading slash; this will be
135 | * used for application routing.
136 | */
137 | if ( strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === 0 ) {
138 | $env['SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME']; //Without URL rewrite
139 | } else {
140 | $env['SCRIPT_NAME'] = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']) ); //With URL rewrite
141 | }
142 | $env['PATH_INFO'] = substr_replace($_SERVER['REQUEST_URI'], '', 0, strlen($env['SCRIPT_NAME']));
143 | if ( strpos($env['PATH_INFO'], '?') !== false ) {
144 | $env['PATH_INFO'] = substr_replace($env['PATH_INFO'], '', strpos($env['PATH_INFO'], '?')); //query string is not removed automatically
145 | }
146 | $env['SCRIPT_NAME'] = rtrim($env['SCRIPT_NAME'], '/');
147 | $env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/');
148 |
149 | //The portion of the request URI following the '?'
150 | $env['QUERY_STRING'] = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
151 |
152 | //Name of server host that is running the script
153 | $env['SERVER_NAME'] = $_SERVER['SERVER_NAME'];
154 |
155 | //Number of server port that is running the script
156 | $env['SERVER_PORT'] = $_SERVER['SERVER_PORT'];
157 |
158 | //HTTP request headers
159 | $specialHeaders = array('CONTENT_TYPE', 'CONTENT_LENGTH', 'PHP_AUTH_USER', 'PHP_AUTH_PW', 'PHP_AUTH_DIGEST', 'AUTH_TYPE');
160 | foreach ( $_SERVER as $key => $value ) {
161 | $value = is_string($value) ? trim($value) : $value;
162 | if ( strpos($key, 'HTTP_') === 0 ) {
163 | $env[substr($key, 5)] = $value;
164 | } else if ( strpos($key, 'X_') === 0 || in_array($key, $specialHeaders) ) {
165 | $env[$key] = $value;
166 | }
167 | }
168 |
169 | //Is the application running under HTTPS or HTTP protocol?
170 | $env['slim.url_scheme'] = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https';
171 |
172 | //Input stream (readable one time only; not available for mutipart/form-data requests)
173 | $rawInput = @file_get_contents('php://input');
174 | if ( !$rawInput ) {
175 | $rawInput = '';
176 | }
177 | $env['slim.input'] = $rawInput;
178 |
179 | //Error stream
180 | $env['slim.errors'] = fopen('php://stderr', 'w');
181 |
182 | $this->properties = $env;
183 | }
184 | }
185 |
186 | /**
187 | * Array Access: Offset Exists
188 | */
189 | public function offsetExists( $offset ) {
190 | return isset($this->properties[$offset]);
191 | }
192 |
193 | /**
194 | * Array Access: Offset Get
195 | */
196 | public function offsetGet( $offset ) {
197 | if ( isset($this->properties[$offset]) ) {
198 | return $this->properties[$offset];
199 | } else {
200 | return null;
201 | }
202 | }
203 |
204 | /**
205 | * Array Access: Offset Set
206 | */
207 | public function offsetSet( $offset, $value ) {
208 | $this->properties[$offset] = $value;
209 | }
210 |
211 | /**
212 | * Array Access: Offset Unset
213 | */
214 | public function offsetUnset( $offset ) {
215 | unset($this->properties[$offset]);
216 | }
217 |
218 | /**
219 | * IteratorAggregate
220 | *
221 | * @return ArrayIterator
222 | */
223 | public function getIterator() {
224 | return new ArrayIterator($this->properties);
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/libs/Slim/Exception/Pass.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Pass Exception
36 | *
37 | * This Exception will cause the Router::dispatch method
38 | * to skip the current matching route and continue to the next
39 | * matching route. If no subsequent routes are found, a
40 | * HTTP 404 Not Found response will be sent to the client.
41 | *
42 | * @package Slim
43 | * @author Josh Lockhart
44 | * @since 1.0.0
45 | */
46 | class Slim_Exception_Pass extends Exception {}
--------------------------------------------------------------------------------
/libs/Slim/Exception/RequestSlash.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Request Slash Exception
36 | *
37 | * This Exception is thrown when Slim detects a matching route
38 | * (defined with a trailing slash) and the HTTP request
39 | * matches the route but does not have a trailing slash. This
40 | * exception will be caught in `Slim::run` and trigger a 301 redirect
41 | * to the same resource URI with a trailing slash.
42 | *
43 | * @package Slim
44 | * @author Josh Lockhart
45 | * @since 1.0.0
46 | */
47 | class Slim_Exception_RequestSlash extends Exception {}
--------------------------------------------------------------------------------
/libs/Slim/Exception/Stop.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Stop Exception
36 | *
37 | * This Exception is thrown when the Slim application needs to abort
38 | * processing and return control flow to the outer PHP script.
39 | *
40 | * @package Slim
41 | * @author Josh Lockhart
42 | * @since 1.0.0
43 | */
44 | class Slim_Exception_Stop extends Exception {}
--------------------------------------------------------------------------------
/libs/Slim/Http/Headers.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * HTTP Headers
36 | *
37 | * This class is an abstraction of the HTTP response headers and
38 | * provides array access to the header list while automatically
39 | * stores and retrieves headers with lowercase canonical keys regardless
40 | * of the input format.
41 | *
42 | * This class also implements the `Iterator` and `Countable`
43 | * interfaces for even more convenient usage.
44 | *
45 | * @package Slim
46 | * @author Josh Lockhart
47 | * @since 1.6.0
48 | */
49 | class Slim_Http_Headers implements ArrayAccess, Iterator, Countable {
50 | /**
51 | * @var array HTTP headers
52 | */
53 | protected $headers;
54 |
55 | /**
56 | * @var array Map canonical header name to original header name
57 | */
58 | protected $map;
59 |
60 | /**
61 | * Constructor
62 | * @param array $headers
63 | * @return void
64 | */
65 | public function __construct( $headers = array() ) {
66 | $this->merge($headers);
67 | }
68 |
69 | /**
70 | * Merge Headers
71 | * @param array $headers
72 | * @return void
73 | */
74 | public function merge( $headers ) {
75 | foreach ( $headers as $name => $value ) {
76 | $this[$name] = $value;
77 | }
78 | }
79 |
80 | /**
81 | * Transform header name into canonical form
82 | * @param string $name
83 | * @return string
84 | */
85 | protected function canonical( $name ) {
86 | return strtolower(trim($name));
87 | }
88 |
89 | /**
90 | * Array Access: Offset Exists
91 | */
92 | public function offsetExists( $offset ) {
93 | return isset($this->headers[$this->canonical($offset)]);
94 | }
95 |
96 | /**
97 | * Array Access: Offset Get
98 | */
99 | public function offsetGet( $offset ) {
100 | $canonical = $this->canonical($offset);
101 | if ( isset($this->headers[$canonical]) ) {
102 | return $this->headers[$canonical];
103 | } else {
104 | return null;
105 | }
106 | }
107 |
108 | /**
109 | * Array Access: Offset Set
110 | */
111 | public function offsetSet( $offset, $value ) {
112 | $canonical = $this->canonical($offset);
113 | $this->headers[$canonical] = $value;
114 | $this->map[$canonical] = $offset;
115 | }
116 |
117 | /**
118 | * Array Access: Offset Unset
119 | */
120 | public function offsetUnset( $offset ) {
121 | $canonical = $this->canonical($offset);
122 | unset($this->headers[$canonical], $this->map[$canonical]);
123 | }
124 |
125 | /**
126 | * Countable: Count
127 | */
128 | public function count() {
129 | return count($this->headers);
130 | }
131 |
132 | /**
133 | * Iterator: Rewind
134 | */
135 | public function rewind() {
136 | reset($this->headers);
137 | }
138 |
139 | /**
140 | * Iterator: Current
141 | */
142 | public function current() {
143 | return current($this->headers);
144 | }
145 |
146 | /**
147 | * Iterator: Key
148 | */
149 | public function key() {
150 | $key = key($this->headers);
151 | return $this->map[$key];
152 | }
153 |
154 | /**
155 | * Iterator: Next
156 | */
157 | public function next() {
158 | return next($this->headers);
159 | }
160 |
161 | /**
162 | * Iterator: Valid
163 | */
164 | public function valid() {
165 | return current($this->headers) !== false;
166 | }
167 | }
--------------------------------------------------------------------------------
/libs/Slim/Http/Request.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Slim HTTP Request
36 | *
37 | * This class provides a human-friendly interface to the Slim environment variables;
38 | * environment variables are passed by reference and will be modified directly.
39 | *
40 | * @package Slim
41 | * @author Josh Lockhart
42 | * @since 1.0.0
43 | */
44 | class Slim_Http_Request {
45 | const METHOD_HEAD = 'HEAD';
46 | const METHOD_GET = 'GET';
47 | const METHOD_POST = 'POST';
48 | const METHOD_PUT = 'PUT';
49 | const METHOD_DELETE = 'DELETE';
50 | const METHOD_OPTIONS = 'OPTIONS';
51 | const METHOD_OVERRIDE = '_METHOD';
52 |
53 | /**
54 | * @var array
55 | */
56 | protected static $formDataMediaTypes = array('application/x-www-form-urlencoded');
57 |
58 | /**
59 | * @var array
60 | */
61 | protected $env;
62 |
63 | /**
64 | * Constructor
65 | * @param array $env
66 | * @see Slim_Environment
67 | */
68 | public function __construct( $env ) {
69 | $this->env = $env;
70 | }
71 |
72 | /**
73 | * Get HTTP method
74 | * @return string
75 | */
76 | public function getMethod() {
77 | return $this->env['REQUEST_METHOD'];
78 | }
79 |
80 | /**
81 | * Is this a GET request?
82 | * @return bool
83 | */
84 | public function isGet() {
85 | return $this->getMethod() === self::METHOD_GET;
86 | }
87 |
88 | /**
89 | * Is this a POST request?
90 | * @return bool
91 | */
92 | public function isPost() {
93 | return $this->getMethod() === self::METHOD_POST;
94 | }
95 |
96 | /**
97 | * Is this a PUT request?
98 | * @return bool
99 | */
100 | public function isPut() {
101 | return $this->getMethod() === self::METHOD_PUT;
102 | }
103 |
104 | /**
105 | * Is this a DELETE request?
106 | * @return bool
107 | */
108 | public function isDelete() {
109 | return $this->getMethod() === self::METHOD_DELETE;
110 | }
111 |
112 | /**
113 | * Is this a HEAD request?
114 | * @return bool
115 | */
116 | public function isHead() {
117 | return $this->getMethod() === self::METHOD_HEAD;
118 | }
119 |
120 | /**
121 | * Is this a OPTIONS request?
122 | * @return bool
123 | */
124 | public function isOptions() {
125 | return $this->getMethod() === self::METHOD_OPTIONS;
126 | }
127 |
128 | /**
129 | * Is this an AJAX request?
130 | * @return bool
131 | */
132 | public function isAjax() {
133 | if ( $this->params('isajax') ) {
134 | return true;
135 | } else if ( isset($this->env['X_REQUESTED_WITH']) && $this->env['X_REQUESTED_WITH'] === 'XMLHttpRequest' ) {
136 | return true;
137 | } else {
138 | return false;
139 | }
140 | }
141 |
142 | /**
143 | * Is this an XHR request? (alias of Slim_Http_Request::isAjax)
144 | * @return bool
145 | */
146 | public function isXhr() {
147 | return $this->isAjax();
148 | }
149 |
150 | /**
151 | * Fetch GET and POST data
152 | *
153 | * This method returns a union of GET and POST data as a key-value array, or the value
154 | * of the array key if requested; if the array key does not exist, NULL is returned.
155 | *
156 | * @param string $key
157 | * @return array|mixed|null
158 | */
159 | public function params( $key = null ) {
160 | $union = array_merge($this->get(), $this->post());
161 | if ( $key ) {
162 | if ( isset($union[$key]) ) {
163 | return $union[$key];
164 | } else {
165 | return null;
166 | }
167 | } else {
168 | return $union;
169 | }
170 | }
171 |
172 | /**
173 | * Fetch GET data
174 | *
175 | * This method returns a key-value array of data sent in the HTTP request query string, or
176 | * the value of the array key if requested; if the array key does not exist, NULL is returned.
177 | *
178 | * @param string $key
179 | * @return array|mixed|null
180 | */
181 | public function get( $key = null ) {
182 | if ( !isset($this->env['slim.request.query_hash']) ) {
183 | $output = array();
184 | if ( function_exists('mb_parse_str') && !isset($this->env['slim.tests.ignore_multibyte']) ) {
185 | mb_parse_str($this->env['QUERY_STRING'], $output);
186 | } else {
187 | parse_str($this->env['QUERY_STRING'], $output);
188 | }
189 | $this->env['slim.request.query_hash'] = Slim_Http_Util::stripSlashesIfMagicQuotes($output);
190 | }
191 | if ( $key ) {
192 | if ( isset($this->env['slim.request.query_hash'][$key]) ) {
193 | return $this->env['slim.request.query_hash'][$key];
194 | } else {
195 | return null;
196 | }
197 | } else {
198 | return $this->env['slim.request.query_hash'];
199 | }
200 | }
201 |
202 | /**
203 | * Fetch POST data
204 | *
205 | * This method returns a key-value array of data sent in the HTTP request body, or
206 | * the value of a hash key if requested; if the array key does not exist, NULL is returned.
207 | *
208 | * @param string $key
209 | * @return array|mixed|null
210 | * @throws RuntimeException If environment input is not available
211 | */
212 | public function post( $key = null ) {
213 | if ( !isset($this->env['slim.input']) ) {
214 | throw new RuntimeException('Missing slim.input in environment variables');
215 | }
216 | if ( !isset($this->env['slim.request.form_hash']) ) {
217 | $this->env['slim.request.form_hash'] = array();
218 | if ( $this->isFormData() ) {
219 | $output = array();
220 | if ( function_exists('mb_parse_str') && !isset($this->env['slim.tests.ignore_multibyte']) ) {
221 | mb_parse_str($this->env['slim.input'], $output);
222 | } else {
223 | parse_str($this->env['slim.input'], $output);
224 | }
225 | $this->env['slim.request.form_hash'] = Slim_Http_Util::stripSlashesIfMagicQuotes($output);
226 | } else {
227 | $this->env['slim.request.form_hash'] = Slim_Http_Util::stripSlashesIfMagicQuotes($_POST);
228 | }
229 | }
230 | if ( $key ) {
231 | if ( isset($this->env['slim.request.form_hash'][$key]) ) {
232 | return $this->env['slim.request.form_hash'][$key];
233 | } else {
234 | return null;
235 | }
236 | } else {
237 | return $this->env['slim.request.form_hash'];
238 | }
239 | }
240 |
241 | /**
242 | * Fetch PUT data (alias for Slim_Http_Request::post)
243 | * @param string $key
244 | * @return array|mixed|null
245 | */
246 | public function put( $key = null ) {
247 | return $this->post($key);
248 | }
249 |
250 | /**
251 | * Fetch DELETE data (alias for Slim_Http_Request::post)
252 | * @param string $key
253 | * @return array|mixed|null
254 | */
255 | public function delete( $key = null ) {
256 | return $this->post($key);
257 | }
258 |
259 | /**
260 | * Fetch COOKIE data
261 | *
262 | * This method returns a key-value array of Cookie data sent in the HTTP request, or
263 | * the value of a array key if requested; if the array key does not exist, NULL is returned.
264 | *
265 | * @param string $key
266 | * @return array|string|null
267 | */
268 | public function cookies( $key = null ) {
269 | if ( !isset($this->env['slim.request.cookie_hash']) ) {
270 | $cookieHeader = isset($this->env['COOKIE']) ? $this->env['COOKIE'] : '';
271 | $this->env['slim.request.cookie_hash'] = Slim_Http_Util::parseCookieHeader($cookieHeader);
272 | }
273 | if ( $key ) {
274 | if ( isset($this->env['slim.request.cookie_hash'][$key]) ) {
275 | return $this->env['slim.request.cookie_hash'][$key];
276 | } else {
277 | return null;
278 | }
279 | } else {
280 | return $this->env['slim.request.cookie_hash'];
281 | }
282 | }
283 |
284 | /**
285 | * Does the Request body contain parseable form data?
286 | * @return bool
287 | */
288 | public function isFormData() {
289 | $method = isset($this->env['slim.method_override.original_method']) ? $this->env['slim.method_override.original_method'] : $this->getMethod();
290 | return ( $method === self::METHOD_POST && is_null($this->getContentType()) ) || in_array($this->getMediaType(), self::$formDataMediaTypes);
291 | }
292 |
293 | /**
294 | * Get Headers
295 | *
296 | * This method returns a key-value array of headers sent in the HTTP request, or
297 | * the value of a hash key if requested; if the array key does not exist, NULL is returned.
298 | *
299 | * @param string $key
300 | * @param mixed $default The default value returned if the requested header is not available
301 | * @return mixed
302 | */
303 | public function headers( $key = null, $default = null ) {
304 | if ( $key ) {
305 | $key = strtoupper($key);
306 | $key = str_replace('-', '_', $key);
307 | $key = preg_replace('@^HTTP_@', '', $key);
308 | if ( isset($this->env[$key]) ) {
309 | return $this->env[$key];
310 | } else {
311 | return $default;
312 | }
313 | } else {
314 | $headers = array();
315 | foreach ( $this->env as $key => $value ) {
316 | if ( strpos($key, 'slim.') !== 0 ) {
317 | $headers[$key] = $value;
318 | }
319 | }
320 | return $headers;
321 | }
322 | }
323 |
324 | /**
325 | * Get Body
326 | * @return string
327 | */
328 | public function getBody() {
329 | return $this->env['slim.input'];
330 | }
331 |
332 | /**
333 | * Get Content Type
334 | * @return string
335 | */
336 | public function getContentType() {
337 | if ( isset($this->env['CONTENT_TYPE']) ) {
338 | return $this->env['CONTENT_TYPE'];
339 | } else {
340 | return null;
341 | }
342 | }
343 |
344 | /**
345 | * Get Media Type (type/subtype within Content Type header)
346 | * @return string|null
347 | */
348 | public function getMediaType() {
349 | $contentType = $this->getContentType();
350 | if ( $contentType ) {
351 | $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
352 | return strtolower($contentTypeParts[0]);
353 | } else {
354 | return null;
355 | }
356 | }
357 |
358 | /**
359 | * Get Media Type Params
360 | * @return array
361 | */
362 | public function getMediaTypeParams() {
363 | $contentType = $this->getContentType();
364 | $contentTypeParams = array();
365 | if ( $contentType ) {
366 | $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType);
367 | $contentTypePartsLength = count($contentTypeParts);
368 | for ( $i = 1; $i < $contentTypePartsLength; $i++ ) {
369 | $paramParts = explode('=', $contentTypeParts[$i]);
370 | $contentTypeParams[strtolower($paramParts[0])] = $paramParts[1];
371 | }
372 | }
373 | return $contentTypeParams;
374 | }
375 |
376 | /**
377 | * Get Content Charset
378 | * @return string|null
379 | */
380 | public function getContentCharset() {
381 | $mediaTypeParams = $this->getMediaTypeParams();
382 | if ( isset($mediaTypeParams['charset']) ) {
383 | return $mediaTypeParams['charset'];
384 | } else {
385 | return null;
386 | }
387 | }
388 |
389 | /**
390 | * Get Content-Length
391 | * @return int
392 | */
393 | public function getContentLength() {
394 | if ( isset($this->env['CONTENT_LENGTH']) ) {
395 | return (int)$this->env['CONTENT_LENGTH'];
396 | } else {
397 | return 0;
398 | }
399 | }
400 |
401 | /**
402 | * Get Host
403 | * @return string
404 | */
405 | public function getHost() {
406 | if ( isset($this->env['HOST']) ) {
407 | if ( strpos($this->env['HOST'], ':') !== false ) {
408 | $hostParts = explode(':', $this->env['HOST']);
409 | return $hostParts[0];
410 | }
411 | return $this->env['HOST'];
412 | } else {
413 | return $this->env['SERVER_NAME'];
414 | }
415 | }
416 |
417 | /**
418 | * Get Host with Port
419 | * @return string
420 | */
421 | public function getHostWithPort() {
422 | return sprintf('%s:%s', $this->getHost(), $this->getPort());
423 | }
424 |
425 | /**
426 | * Get Port
427 | * @return int
428 | */
429 | public function getPort() {
430 | return (int)$this->env['SERVER_PORT'];
431 | }
432 |
433 | /**
434 | * Get Scheme (https or http)
435 | * @return string
436 | */
437 | public function getScheme() {
438 | return $this->env['slim.url_scheme'];
439 | }
440 |
441 | /**
442 | * Get Script Name (physical path)
443 | * @return string
444 | */
445 | public function getScriptName() {
446 | return $this->env['SCRIPT_NAME'];
447 | }
448 |
449 | /**
450 | * LEGACY: Get Root URI (alias for Slim_Http_Request::getScriptName)
451 | * @return string
452 | */
453 | public function getRootUri() {
454 | return $this->getScriptName();
455 | }
456 |
457 | /**
458 | * Get Path (physical path + virtual path)
459 | * @return string
460 | */
461 | public function getPath() {
462 | return $this->getScriptName() . $this->getPathInfo();
463 | }
464 |
465 | /**
466 | * Get Path Info (virtual path)
467 | * @return string
468 | */
469 | public function getPathInfo() {
470 | return $this->env['PATH_INFO'];
471 | }
472 |
473 | /**
474 | * LEGACY: Get Resource URI (alias for Slim_Http_Request::getPathInfo)
475 | * @return string
476 | */
477 | public function getResourceUri() {
478 | return $this->getPathInfo();
479 | }
480 |
481 | /**
482 | * Get URL (scheme + host [ + port if non-standard ])
483 | * @return string
484 | */
485 | public function getUrl() {
486 | $url = $this->getScheme() . '://' . $this->getHost();
487 | if ( ( $this->getScheme() === 'https' && $this->getPort() !== 443 ) || ( $this->getScheme() === 'http' && $this->getPort() !== 80 ) ) {
488 | $url .= sprintf(':%s', $this->getPort());
489 | }
490 | return $url;
491 | }
492 |
493 | /**
494 | * Get IP
495 | * @return string
496 | */
497 | public function getIp() {
498 | if ( isset($this->env['X_FORWARDED_FOR']) ) {
499 | return $this->env['X_FORWARDED_FOR'];
500 | } else if ( isset($this->env['CLIENT_IP']) ) {
501 | return $this->env['CLIENT_IP'];
502 | }
503 | return $this->env['REMOTE_ADDR'];
504 | }
505 |
506 | /**
507 | * Get Referrer
508 | * @return string|null
509 | */
510 | public function getReferrer() {
511 | if ( isset($this->env['REFERER']) ) {
512 | return $this->env['REFERER'];
513 | } else {
514 | return null;
515 | }
516 | }
517 |
518 | /**
519 | * Get Referer (for those who can't spell)
520 | * @return string|null
521 | */
522 | public function getReferer() {
523 | return $this->getReferrer();
524 | }
525 |
526 | /**
527 | * Get User Agent
528 | * @return string|null
529 | */
530 | public function getUserAgent() {
531 | if ( isset($this->env['USER_AGENT']) ) {
532 | return $this->env['USER_AGENT'];
533 | } else {
534 | return null;
535 | }
536 | }
537 | }
538 |
--------------------------------------------------------------------------------
/libs/Slim/Http/Response.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Response
36 | *
37 | * This is a simple abstraction over top an HTTP response. This
38 | * provides methods to set the HTTP status, the HTTP headers,
39 | * and the HTTP body.
40 | *
41 | * @package Slim
42 | * @author Josh Lockhart
43 | * @since 1.0.0
44 | */
45 | class Slim_Http_Response implements ArrayAccess, Countable, IteratorAggregate {
46 | /**
47 | * @var int HTTP status code
48 | */
49 | protected $status;
50 |
51 | /**
52 | * @var Slim_Http_Headers List of HTTP response headers
53 | * @see Slim_Http_Headers
54 | */
55 | protected $header;
56 |
57 | /**
58 | * @var string HTTP response body
59 | */
60 | protected $body;
61 |
62 | /**
63 | * @var int Length of HTTP response body
64 | */
65 | protected $length;
66 |
67 | /**
68 | * @var array HTTP response codes and messages
69 | */
70 | protected static $messages = array(
71 | //Informational 1xx
72 | 100 => '100 Continue',
73 | 101 => '101 Switching Protocols',
74 | //Successful 2xx
75 | 200 => '200 OK',
76 | 201 => '201 Created',
77 | 202 => '202 Accepted',
78 | 203 => '203 Non-Authoritative Information',
79 | 204 => '204 No Content',
80 | 205 => '205 Reset Content',
81 | 206 => '206 Partial Content',
82 | //Redirection 3xx
83 | 300 => '300 Multiple Choices',
84 | 301 => '301 Moved Permanently',
85 | 302 => '302 Found',
86 | 303 => '303 See Other',
87 | 304 => '304 Not Modified',
88 | 305 => '305 Use Proxy',
89 | 306 => '306 (Unused)',
90 | 307 => '307 Temporary Redirect',
91 | //Client Error 4xx
92 | 400 => '400 Bad Request',
93 | 401 => '401 Unauthorized',
94 | 402 => '402 Payment Required',
95 | 403 => '403 Forbidden',
96 | 404 => '404 Not Found',
97 | 405 => '405 Method Not Allowed',
98 | 406 => '406 Not Acceptable',
99 | 407 => '407 Proxy Authentication Required',
100 | 408 => '408 Request Timeout',
101 | 409 => '409 Conflict',
102 | 410 => '410 Gone',
103 | 411 => '411 Length Required',
104 | 412 => '412 Precondition Failed',
105 | 413 => '413 Request Entity Too Large',
106 | 414 => '414 Request-URI Too Long',
107 | 415 => '415 Unsupported Media Type',
108 | 416 => '416 Requested Range Not Satisfiable',
109 | 417 => '417 Expectation Failed',
110 | 422 => '422 Unprocessable Entity',
111 | 423 => '423 Locked',
112 | //Server Error 5xx
113 | 500 => '500 Internal Server Error',
114 | 501 => '501 Not Implemented',
115 | 502 => '502 Bad Gateway',
116 | 503 => '503 Service Unavailable',
117 | 504 => '504 Gateway Timeout',
118 | 505 => '505 HTTP Version Not Supported'
119 | );
120 |
121 | /**
122 | * Constructor
123 | * @param string $body The HTTP response body
124 | * @param int $status The HTTP response status
125 | * @param Slim_Http_Headers|array $header The HTTP response headers
126 | */
127 | public function __construct( $body = '', $status = 200, $header = array() ) {
128 | $this->status = (int)$status;
129 | $headers = array();
130 | foreach ( $header as $key => $value ) {
131 | $headers[$key] = $value;
132 | }
133 | $this->header = new Slim_Http_Headers(array_merge(array('Content-Type' => 'text/html'), $headers));
134 | $this->body = '';
135 | $this->write($body);
136 | }
137 |
138 | /**
139 | * Get and set status
140 | * @param int|null $status
141 | * @return int
142 | */
143 | public function status( $status = null ) {
144 | if ( !is_null($status) ) {
145 | $this->status = (int)$status;
146 | }
147 | return $this->status;
148 | }
149 |
150 | /**
151 | * Get and set header
152 | * @param string $name Header name
153 | * @param string|null $value Header value
154 | * @return string Header value
155 | */
156 | public function header( $name, $value = null ) {
157 | if ( !is_null($value) ) {
158 | $this[$name] = $value;
159 | }
160 | return $this[$name];
161 | }
162 |
163 | /**
164 | * Get headers
165 | * @return Slim_Http_Headers
166 | */
167 | public function headers() {
168 | return $this->header;
169 | }
170 |
171 | /**
172 | * Get and set body
173 | * @param string|null $body Content of HTTP response body
174 | * @return string
175 | */
176 | public function body( $body = null ) {
177 | if ( !is_null($body) ) {
178 | $this->write($body, true);
179 | }
180 | return $this->body;
181 | }
182 |
183 | /**
184 | * Get and set length
185 | * @param int|null $length
186 | * @return int
187 | */
188 | public function length( $length = null ) {
189 | if ( !is_null($length) ) {
190 | $this->length = (int)$length;
191 | }
192 | return $this->length;
193 | }
194 |
195 | /**
196 | * Append HTTP response body
197 | * @param string $body Content to append to the current HTTP response body
198 | * @param bool $replace Overwrite existing response body?
199 | * @return string The updated HTTP response body
200 | */
201 | public function write( $body, $replace = false ) {
202 | if ( $replace ) {
203 | $this->body = $body;
204 | } else {
205 | $this->body .= (string)$body;
206 | }
207 | $this->length = strlen($this->body);
208 | return $this->body;
209 | }
210 |
211 | /**
212 | * Finalize
213 | *
214 | * This prepares this response and returns an array
215 | * of [status, headers, body]. This array is passed to outer middleware
216 | * if available or directly to the Slim run method.
217 | *
218 | * @return array[int status, array headers, string body]
219 | */
220 | public function finalize() {
221 | if ( in_array($this->status, array(204, 304)) ) {
222 | unset($this['Content-Type'], $this['Content-Length']);
223 | return array($this->status, $this->header, '');
224 | } else {
225 | return array($this->status, $this->header, $this->body);
226 | }
227 | }
228 |
229 | /**
230 | * Set cookie
231 | *
232 | * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
233 | * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
234 | * response's header is passed by reference to the utility class and is directly modified. By not
235 | * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
236 | * analyze the raw header before the response is ultimately delivered to the HTTP client.
237 | *
238 | * @param string $name The name of the cookie
239 | * @param string|array $value If string, the value of cookie; if array, properties for
240 | * cookie including: value, expire, path, domain, secure, httponly
241 | */
242 | public function setCookie( $name, $value ) {
243 | Slim_Http_Util::setCookieHeader($this->header, $name, $value);
244 | }
245 |
246 | /**
247 | * Delete cookie
248 | *
249 | * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie`
250 | * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This
251 | * response's header is passed by reference to the utility class and is directly modified. By not
252 | * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or
253 | * analyze the raw header before the response is ultimately delivered to the HTTP client.
254 | *
255 | * This method will set a cookie with the given name that has an expiration time in the past; this will
256 | * prompt the HTTP client to invalidate and remove the client-side cookie. Optionally, you may
257 | * also pass a key/value array as the second argument. If the "domain" key is present in this
258 | * array, only the Cookie with the given name AND domain will be removed. The invalidating cookie
259 | * sent with this response will adopt all properties of the second argument.
260 | *
261 | * @param string $name The name of the cookie
262 | * @param array $value Properties for cookie including: value, expire, path, domain, secure, httponly
263 | */
264 | public function deleteCookie( $name, $value = array() ) {
265 | Slim_Http_Util::deleteCookieHeader($this->header, $name, $value);
266 | }
267 |
268 | /**
269 | * Redirect
270 | *
271 | * This method prepares this response to return an HTTP Redirect response
272 | * to the HTTP client.
273 | *
274 | * @param string $url The redirect destination
275 | * @param int $status The redirect HTTP status code
276 | */
277 | public function redirect ( $url, $status = 302 ) {
278 | $this->status = $status;
279 | $this['Location'] = $url;
280 | }
281 |
282 | /**
283 | * Helpers: Empty?
284 | * @return bool
285 | */
286 | public function isEmpty() {
287 | return in_array($this->status, array(201, 204, 304));
288 | }
289 |
290 | /**
291 | * Helpers: Informational?
292 | * @return bool
293 | */
294 | public function isInformational() {
295 | return $this->status >= 100 && $this->status < 200;
296 | }
297 |
298 | /**
299 | * Helpers: OK?
300 | * @return bool
301 | */
302 | public function isOk() {
303 | return $this->status === 200;
304 | }
305 |
306 | /**
307 | * Helpers: Successful?
308 | * @return bool
309 | */
310 | public function isSuccessful() {
311 | return $this->status >= 200 && $this->status < 300;
312 | }
313 |
314 | /**
315 | * Helpers: Redirect?
316 | * @return bool
317 | */
318 | public function isRedirect() {
319 | return in_array($this->status, array(301, 302, 303, 307));
320 | }
321 |
322 | /**
323 | * Helpers: Redirection?
324 | * @return bool
325 | */
326 | public function isRedirection() {
327 | return $this->status >= 300 && $this->status < 400;
328 | }
329 |
330 | /**
331 | * Helpers: Forbidden?
332 | * @return bool
333 | */
334 | public function isForbidden() {
335 | return $this->status === 403;
336 | }
337 |
338 | /**
339 | * Helpers: Not Found?
340 | * @return bool
341 | */
342 | public function isNotFound() {
343 | return $this->status === 404;
344 | }
345 |
346 | /**
347 | * Helpers: Client error?
348 | * @return bool
349 | */
350 | public function isClientError() {
351 | return $this->status >= 400 && $this->status < 500;
352 | }
353 |
354 | /**
355 | * Helpers: Server Error?
356 | * @return bool
357 | */
358 | public function isServerError() {
359 | return $this->status >= 500 && $this->status < 600;
360 | }
361 |
362 | /**
363 | * Array Access: Offset Exists
364 | */
365 | public function offsetExists( $offset ) {
366 | return isset($this->header[$offset]);
367 | }
368 |
369 | /**
370 | * Array Access: Offset Get
371 | */
372 | public function offsetGet( $offset ) {
373 | if ( isset($this->header[$offset]) ) {
374 | return $this->header[$offset];
375 | } else {
376 | return null;
377 | }
378 | }
379 |
380 | /**
381 | * Array Access: Offset Set
382 | */
383 | public function offsetSet( $offset, $value ) {
384 | $this->header[$offset] = $value;
385 | }
386 |
387 | /**
388 | * Array Access: Offset Unset
389 | */
390 | public function offsetUnset( $offset ) {
391 | unset($this->header[$offset]);
392 | }
393 |
394 | /**
395 | * Countable: Count
396 | */
397 | public function count() {
398 | return count($this->header);
399 | }
400 |
401 | /**
402 | * Get Iterator
403 | *
404 | * This returns the contained `Slim_Http_Headers` instance which
405 | * is itself iterable.
406 | *
407 | * @return Slim_Http_Headers
408 | */
409 | public function getIterator() {
410 | return $this->header;
411 | }
412 |
413 | /**
414 | * Get message for HTTP status code
415 | * @return string|null
416 | */
417 | public static function getMessageForCode( $status ) {
418 | if ( isset(self::$messages[$status]) ) {
419 | return self::$messages[$status];
420 | } else {
421 | return null;
422 | }
423 | }
424 | }
--------------------------------------------------------------------------------
/libs/Slim/Http/Util.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Slim HTTP Utilities
36 | *
37 | * This class provides useful methods for handling HTTP requests.
38 | *
39 | * @package Slim
40 | * @author Josh Lockhart
41 | * @since 1.0.0
42 | */
43 | class Slim_Http_Util {
44 | /**
45 | * Strip slashes from string or array
46 | *
47 | * This method strips slashes from its input. By default, this method will only
48 | * strip slashes from its input if magic quotes are enabled. Otherwise, you may
49 | * override the magic quotes setting with either TRUE or FALSE as the send argument
50 | * to force this method to strip or not strip slashes from its input.
51 | *
52 | * @var array|string $rawData
53 | * @return array|string
54 | */
55 | public static function stripSlashesIfMagicQuotes( $rawData, $overrideStripSlashes = null ) {
56 | $strip = is_null($overrideStripSlashes) ? get_magic_quotes_gpc() : $overrideStripSlashes;
57 | if ( $strip ) {
58 | return self::_stripSlashes($rawData);
59 | } else {
60 | return $rawData;
61 | }
62 | }
63 |
64 | /**
65 | * Strip slashes from string or array
66 | * @param array|string $rawData
67 | * @return array|string
68 | */
69 | protected static function _stripSlashes( $rawData ) {
70 | return is_array($rawData) ? array_map(array('self', '_stripSlashes'), $rawData) : stripslashes($rawData);
71 | }
72 |
73 | /**
74 | * Encrypt data
75 | *
76 | * This method will encrypt data using a given key, vector, and cipher.
77 | * By default, this will encrypt data using the RIJNDAEL/AES 256 bit cipher. You
78 | * may override the default cipher and cipher mode by passing your own desired
79 | * cipher and cipher mode as the final key-value array argument.
80 | *
81 | * @param string $data The unencrypted data
82 | * @param string $key The encryption key
83 | * @param string $iv The encryption initialization vector
84 | * @param array $settings Optional key-value array with custom algorithm and mode
85 | * @return string
86 | */
87 | public static function encrypt( $data, $key, $iv, $settings = array() ) {
88 | if ( $data === '' || !extension_loaded('mcrypt') ) {
89 | return $data;
90 | }
91 |
92 | //Merge settings with defaults
93 | $settings = array_merge(array(
94 | 'algorithm' => MCRYPT_RIJNDAEL_256,
95 | 'mode' => MCRYPT_MODE_CBC
96 | ), $settings);
97 |
98 | //Get module
99 | $module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
100 |
101 | //Validate IV
102 | $ivSize = mcrypt_enc_get_iv_size($module);
103 | if ( strlen($iv) > $ivSize ) {
104 | $iv = substr($iv, 0, $ivSize);
105 | }
106 |
107 | //Validate key
108 | $keySize = mcrypt_enc_get_key_size($module);
109 | if ( strlen($key) > $keySize ) {
110 | $key = substr($key, 0, $keySize);
111 | }
112 |
113 | //Encrypt value
114 | mcrypt_generic_init($module, $key, $iv);
115 | $res = @mcrypt_generic($module, $data);
116 | mcrypt_generic_deinit($module);
117 |
118 | return $res;
119 | }
120 |
121 | /**
122 | * Decrypt data
123 | *
124 | * This method will decrypt data using a given key, vector, and cipher.
125 | * By default, this will decrypt data using the RIJNDAEL/AES 256 bit cipher. You
126 | * may override the default cipher and cipher mode by passing your own desired
127 | * cipher and cipher mode as the final key-value array argument.
128 | *
129 | * @param string $data The encrypted data
130 | * @param string $key The encryption key
131 | * @param string $iv The encryption initialization vector
132 | * @param array $settings Optional key-value array with custom algorithm and mode
133 | * @return string
134 | */
135 | public static function decrypt( $data, $key, $iv, $settings = array() ) {
136 | if ( $data === '' || !extension_loaded('mcrypt') ) {
137 | return $data;
138 | }
139 |
140 | //Merge settings with defaults
141 | $settings = array_merge(array(
142 | 'algorithm' => MCRYPT_RIJNDAEL_256,
143 | 'mode' => MCRYPT_MODE_CBC
144 | ), $settings);
145 |
146 | //Get module
147 | $module = mcrypt_module_open($settings['algorithm'], '', $settings['mode'], '');
148 |
149 | //Validate IV
150 | $ivSize = mcrypt_enc_get_iv_size($module);
151 | if ( strlen($iv) > $ivSize ) {
152 | $iv = substr($iv, 0, $ivSize);
153 | }
154 |
155 | //Validate key
156 | $keySize = mcrypt_enc_get_key_size($module);
157 | if ( strlen($key) > $keySize ) {
158 | $key = substr($key, 0, $keySize);
159 | }
160 |
161 | //Decrypt value
162 | mcrypt_generic_init($module, $key, $iv);
163 | $decryptedData = @mdecrypt_generic($module, $data);
164 | $res = str_replace("\x0", '', $decryptedData);
165 | mcrypt_generic_deinit($module);
166 |
167 | return $res;
168 | }
169 |
170 | /**
171 | * Encode secure cookie value
172 | *
173 | * This method will create the secure value of an HTTP cookie. The
174 | * cookie value is encrypted and hashed so that its value is
175 | * secure and checked for integrity when read in subsequent requests.
176 | *
177 | * @param string $value The unsecure HTTP cookie value
178 | * @param int $expires The UNIX timestamp at which this cookie will expire
179 | * @param string $secret The secret key used to hash the cookie value
180 | * @param int $algorithm The algorithm to use for encryption
181 | * @param int $mode The algorithm mode to use for encryption
182 | * @param string
183 | */
184 | public static function encodeSecureCookie( $value, $expires, $secret, $algorithm, $mode ) {
185 | $key = hash_hmac('sha1', $expires, $secret);
186 | $iv = self::get_iv($expires, $secret);
187 | $secureString = base64_encode(self::encrypt($value, $key, $iv, array(
188 | 'algorithm' => $algorithm,
189 | 'mode' => $mode
190 | )));
191 | $verificationString = hash_hmac('sha1', $expires . $value, $key);
192 | return implode('|', array($expires, $secureString, $verificationString));
193 | }
194 |
195 | /**
196 | * Decode secure cookie value
197 | *
198 | * This method will decode the secure value of an HTTP cookie. The
199 | * cookie value is encrypted and hashed so that its value is
200 | * secure and checked for integrity when read in subsequent requests.
201 | *
202 | * @param string $value The secure HTTP cookie value
203 | * @param int $expires The UNIX timestamp at which this cookie will expire
204 | * @param string $secret The secret key used to hash the cookie value
205 | * @param int $algorithm The algorithm to use for encryption
206 | * @param int $mode The algorithm mode to use for encryption
207 | * @param string
208 | */
209 | public static function decodeSecureCookie( $value, $secret, $algorithm, $mode ) {
210 | if ( $value ) {
211 | $value = explode('|', $value);
212 | if ( count($value) === 3 && ( (int)$value[0] === 0 || (int)$value[0] > time() ) ) {
213 | $key = hash_hmac('sha1', $value[0], $secret);
214 | $iv = self::get_iv($value[0], $secret);
215 | $data = self::decrypt(base64_decode($value[1]), $key, $iv, array(
216 | 'algorithm' => $algorithm,
217 | 'mode' => $mode
218 | ));
219 | $verificationString = hash_hmac('sha1', $value[0] . $data, $key);
220 | if ( $verificationString === $value[2] ) {
221 | return $data;
222 | }
223 | }
224 | }
225 | return false;
226 | }
227 |
228 | /**
229 | * Set HTTP cookie header
230 | *
231 | * This method will construct and set the HTTP `Set-Cookie` header. Slim
232 | * uses this method instead of PHP's native `setcookie` method. This allows
233 | * more control of the HTTP header irrespective of the native implementation's
234 | * dependency on PHP versions.
235 | *
236 | * This method accepts the Slim_Http_Headers object by reference as its
237 | * first argument; this method directly modifies this object instead of
238 | * returning a value.
239 | *
240 | * @param array $header
241 | * @param string $name
242 | * @param string $value
243 | * @return void
244 | */
245 | public static function setCookieHeader( &$header, $name, $value ) {
246 | //Build cookie header
247 | if ( is_array($value) ) {
248 | $domain = '';
249 | $path = '';
250 | $expires = '';
251 | $secure = '';
252 | $httponly = '';
253 | if ( isset($value['domain']) && $value['domain'] ) {
254 | $domain = '; domain=' . $value['domain'];
255 | }
256 | if ( isset($value['path']) && $value['path'] ) {
257 | $path = '; path=' . $value['path'];
258 | }
259 | if ( isset($value['expires']) ) {
260 | if ( is_string($value['expires']) ) {
261 | $timestamp = strtotime($value['expires']);
262 | } else {
263 | $timestamp = (int)$value['expires'];
264 | }
265 | if ( $timestamp !== 0 ) {
266 | $expires = '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp);
267 | }
268 | }
269 | if ( isset($value['secure']) && $value['secure'] ) {
270 | $secure = '; secure';
271 | }
272 | if ( isset($value['httponly']) && $value['httponly'] ) {
273 | $httponly = '; HttpOnly';
274 | }
275 | $cookie = sprintf('%s=%s%s', urlencode($name), urlencode((string)$value['value']), $domain . $path . $expires . $secure . $httponly);
276 | } else {
277 | $cookie = sprintf('%s=%s', urlencode($name), urlencode((string)$value));
278 | }
279 |
280 | //Set cookie header
281 | if ( !isset($header['Set-Cookie']) || $header['Set-Cookie'] === '' ) {
282 | $header['Set-Cookie'] = $cookie;
283 | } else {
284 | $header['Set-Cookie'] = implode("\n", array($header['Set-Cookie'], $cookie));
285 | }
286 | }
287 |
288 | /**
289 | * Delete HTTP cookie header
290 | *
291 | * This method will construct and set the HTTP `Set-Cookie` header to invalidate
292 | * a client-side HTTP cookie. If a cookie with the same name (and, optionally, domain)
293 | * is already set in the HTTP response, it will also be removed. Slim uses this method
294 | * instead of PHP's native `setcookie` method. This allows more control of the HTTP header
295 | * irrespective of PHP's native implementation's dependency on PHP versions.
296 | *
297 | * This method accepts the Slim_Http_Headers object by reference as its
298 | * first argument; this method directly modifies this object instead of
299 | * returning a value.
300 | *
301 | * @param array $header
302 | * @param string $name
303 | * @param string $value
304 | * @return void
305 | */
306 | public static function deleteCookieHeader( &$header, $name, $value = array() ) {
307 | //Remove affected cookies from current response header
308 | $cookiesOld = array();
309 | $cookiesNew = array();
310 | if ( isset($header['Set-Cookie']) ) {
311 | $cookiesOld = explode("\n", $header['Set-Cookie']);
312 | }
313 | foreach ( $cookiesOld as $c ) {
314 | if ( isset($value['domain']) && $value['domain'] ) {
315 | $regex = sprintf('@%s=.*domain=%s@', urlencode($name), preg_quote($value['domain']));
316 | } else {
317 | $regex = sprintf('@%s=@', urlencode($name));
318 | }
319 | if ( preg_match($regex, $c) === 0 ) {
320 | $cookiesNew[] = $c;
321 | }
322 | }
323 | if ( $cookiesNew ) {
324 | $header['Set-Cookie'] = implode("\n", $cookiesNew);
325 | } else {
326 | unset($header['Set-Cookie']);
327 | }
328 |
329 | //Set invalidating cookie to clear client-side cookie
330 | self::setCookieHeader($header, $name, array_merge(array('value' => '', 'path' => null, 'domain' => null, 'expires' => time() - 100), $value));
331 | }
332 |
333 | /**
334 | * Parse cookie header
335 | *
336 | * This method will parse the HTTP requst's `Cookie` header
337 | * and extract cookies into an associative array.
338 | *
339 | * @param string
340 | * @return array
341 | */
342 | public static function parseCookieHeader( $header ) {
343 | $cookies = array();
344 | $header = rtrim($header, "\r\n");
345 | $headerPieces = preg_split('@\s*;\s*@', $header);
346 | foreach ( $headerPieces as $c ) {
347 | $cParts = explode('=', $c);
348 | if ( count($cParts) === 2 ) {
349 | $key = urldecode($cParts[0]);
350 | $value = urldecode($cParts[1]);
351 | if ( isset($cookies[$key]) ) {
352 | if ( is_array($cookies[$key]) ) {
353 | $cookies[$key][] = $value;
354 | } else {
355 | $cookies[$key] = array($cookies[$key], $value);
356 | }
357 | } else {
358 | $cookies[$key] = $value;
359 | }
360 | }
361 | }
362 | return $cookies;
363 | }
364 |
365 | /**
366 | * Generate a random IV
367 | *
368 | * This method will generate a non-predictable IV for use with
369 | * the cookie encryption
370 | *
371 | * @param int $expires The UNIX timestamp at which this cookie will expire
372 | * @param string $secret The secret key used to hash the cookie value
373 | * @return binary string with length 40
374 | */
375 | private static function get_iv($expires, $secret) {
376 | $data1 = hash_hmac('sha1', 'a'.$expires.'b', $secret);
377 | $data2 = hash_hmac('sha1', 'z'.$expires.'y', $secret);
378 | return pack("h*", $data1.$data2);
379 | }
380 |
381 | }
--------------------------------------------------------------------------------
/libs/Slim/Log.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Log
36 | *
37 | * This is the primary logger for a Slim application. You may provide
38 | * a Log Writer in conjunction with this Log to write to various output
39 | * destinations (e.g. a file). This class provides this interface:
40 | *
41 | * debug( mixed $object )
42 | * info( mixed $object )
43 | * warn( mixed $object )
44 | * error( mixed $object )
45 | * fatal( mixed $object )
46 | *
47 | * This class assumes only that your Log Writer has a public `write()` method
48 | * that accepts any object as its one and only argument. The Log Writer
49 | * class may write or send its argument anywhere: a file, STDERR,
50 | * a remote web API, etc. The possibilities are endless.
51 | *
52 | * @package Slim
53 | * @author Josh Lockhart
54 | * @since 1.0.0
55 | */
56 | class Slim_Log {
57 | /**
58 | * @var array
59 | */
60 | static protected $levels = array(
61 | 0 => 'FATAL',
62 | 1 => 'ERROR',
63 | 2 => 'WARN',
64 | 3 => 'INFO',
65 | 4 => 'DEBUG'
66 | );
67 |
68 | /**
69 | * @var mixed
70 | */
71 | protected $writer;
72 |
73 | /**
74 | * @var bool
75 | */
76 | protected $enabled;
77 |
78 | /**
79 | * @var int
80 | */
81 | protected $level;
82 |
83 | /**
84 | * Constructor
85 | * @param mixed $writer
86 | * @return void
87 | */
88 | public function __construct( $writer ) {
89 | $this->writer = $writer;
90 | $this->enabled = true;
91 | $this->level = 4;
92 | }
93 |
94 | /**
95 | * Is logging enabled?
96 | * @return bool
97 | */
98 | public function getEnabled() {
99 | return $this->enabled;
100 | }
101 |
102 | /**
103 | * Enable or disable logging
104 | * @param bool $enabled
105 | * @return void
106 | */
107 | public function setEnabled( $enabled ) {
108 | if ( $enabled ) {
109 | $this->enabled = true;
110 | } else {
111 | $this->enabled = false;
112 | }
113 | }
114 |
115 | /**
116 | * Set level
117 | * @param int $level
118 | * @return void
119 | * @throws InvalidArgumentException
120 | */
121 | public function setLevel( $level ) {
122 | if ( !isset(self::$levels[$level]) ) {
123 | throw new InvalidArgumentException('Invalid log level');
124 | }
125 | $this->level = $level;
126 | }
127 |
128 | /**
129 | * Get level
130 | * @return int
131 | */
132 | public function getLevel() {
133 | return $this->level;
134 | }
135 |
136 | /**
137 | * Set writer
138 | * @param mixed $writer
139 | * @return void
140 | */
141 | public function setWriter( $writer ) {
142 | $this->writer = $writer;
143 | }
144 |
145 | /**
146 | * Get writer
147 | * @return mixed
148 | */
149 | public function getWriter() {
150 | return $this->writer;
151 | }
152 |
153 | /**
154 | * Is logging enabled?
155 | * @return bool
156 | */
157 | public function isEnabled() {
158 | return $this->enabled;
159 | }
160 |
161 | /**
162 | * Log debug message
163 | * @param mixed $object
164 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled
165 | */
166 | public function debug( $object ) {
167 | return $this->log($object, 4);
168 | }
169 |
170 | /**
171 | * Log info message
172 | * @param mixed $object
173 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled
174 | */
175 | public function info( $object ) {
176 | return $this->log($object, 3);
177 | }
178 |
179 | /**
180 | * Log warn message
181 | * @param mixed $object
182 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled
183 | */
184 | public function warn( $object ) {
185 | return $this->log($object, 2);
186 | }
187 |
188 | /**
189 | * Log error message
190 | * @param mixed $object
191 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled
192 | */
193 | public function error( $object ) {
194 | return $this->log($object, 1);
195 | }
196 |
197 | /**
198 | * Log fatal message
199 | * @param mixed $object
200 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled
201 | */
202 | public function fatal( $object ) {
203 | return $this->log($object, 0);
204 | }
205 |
206 | /**
207 | * Log message
208 | * @param mixed The object to log
209 | * @param int The message level
210 | * @return int|false
211 | */
212 | protected function log( $object, $level ) {
213 | if ( $this->enabled && $this->writer && $level <= $this->level ) {
214 | return $this->writer->write($object, $level);
215 | } else {
216 | return false;
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/libs/Slim/LogFileWriter.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Log File Writer
36 | *
37 | * This class is used by Slim_Log to write log messages to a valid, writable
38 | * resource handle (e.g. a file or STDERR).
39 | *
40 | * @package Slim
41 | * @author Josh Lockhart
42 | * @since 1.5.2
43 | */
44 | class Slim_LogFileWriter {
45 | /**
46 | * @var resource
47 | */
48 | protected $resource;
49 |
50 | /**
51 | * Constructor
52 | * @param resource $resource
53 | * @return void
54 | * @throws InvalidArgumentException
55 | */
56 | public function __construct( $resource ) {
57 | if ( !is_resource($resource) ) {
58 | throw new InvalidArgumentException('Cannot create LogFileWriter. Invalid resource handle.');
59 | }
60 | $this->resource = $resource;
61 | }
62 |
63 | /**
64 | * Write message
65 | * @param mixed $message
66 | * @param int $level
67 | * @return int|false
68 | */
69 | public function write( $message, $level = null ) {
70 | return fwrite($this->resource, (string)$message . PHP_EOL);
71 | }
72 | }
--------------------------------------------------------------------------------
/libs/Slim/Middleware.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Middleware
36 | *
37 | * @package Slim
38 | * @author Josh Lockhart
39 | * @since 1.6.0
40 | */
41 | abstract class Slim_Middleware {
42 | /**
43 | * @var Slim Reference to the primary Slim application instance
44 | */
45 | protected $app;
46 |
47 | /**
48 | * @var mixed Reference to the next downstream middleware
49 | */
50 | protected $next;
51 |
52 | /**
53 | * Set application
54 | *
55 | * This method injects the primary Slim application instance into
56 | * this middleware.
57 | *
58 | * @param Slim $application
59 | * @return void
60 | */
61 | final public function setApplication( $application ) {
62 | $this->app = $application;
63 | }
64 |
65 | /**
66 | * Get application
67 | *
68 | * This method retrieves the application previously injected
69 | * into this middleware.
70 | *
71 | * @return Slim
72 | */
73 | final public function getApplication() {
74 | return $this->app;
75 | }
76 |
77 | /**
78 | * Set next middleware
79 | *
80 | * This method injects the next downstream middleware into
81 | * this middleware so that it may optionally be called
82 | * when appropriate.
83 | *
84 | * @param Slim|Slim_Middleware
85 | * @return void
86 | */
87 | final public function setNextMiddleware( $nextMiddleware ) {
88 | $this->next = $nextMiddleware;
89 | }
90 |
91 | /**
92 | * Get next middleware
93 | *
94 | * This method retrieves the next downstream middleware
95 | * previously injected into this middleware.
96 | *
97 | * @return Slim|Slim_Middleware
98 | */
99 | final public function getNextMiddleware() {
100 | return $this->next;
101 | }
102 |
103 | /**
104 | * Call
105 | *
106 | * Perform actions specific to this middleware and optionally
107 | * call the next downstream middleware.
108 | *
109 | * @return void
110 | */
111 | abstract public function call();
112 | }
--------------------------------------------------------------------------------
/libs/Slim/Middleware/ContentTypes.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Content Types
36 | *
37 | * This is middleware for a Slim application that intercepts
38 | * the HTTP request body and parses it into the appropriate
39 | * PHP data structure if possible; else it returns the HTTP
40 | * request body unchanged. This is particularly useful
41 | * for preparing the HTTP request body for an XML or JSON API.
42 | *
43 | * @package Slim
44 | * @author Josh Lockhart
45 | * @since 1.5.2
46 | */
47 | class Slim_Middleware_ContentTypes extends Slim_Middleware {
48 | /**
49 | * @var array
50 | */
51 | protected $contentTypes;
52 |
53 | /**
54 | * Constructor
55 | * @param array $settings
56 | */
57 | public function __construct( $settings = array() ) {
58 | $this->contentTypes = array_merge(array(
59 | 'application/json' => array($this, 'parseJson'),
60 | 'application/xml' => array($this, 'parseXml'),
61 | 'text/xml' => array($this, 'parseXml'),
62 | 'text/csv' => array($this, 'parseCsv')
63 | ), $settings);
64 | }
65 |
66 | /**
67 | * Call
68 | * @return void
69 | */
70 | public function call() {
71 | $mediaType = $this->app->request()->getMediaType();
72 | if ( $mediaType ) {
73 | $env = $this->app->environment();
74 | $env['slim.input_original'] = $env['slim.input'];
75 | $env['slim.input'] = $this->parse($env['slim.input'], $mediaType);
76 | }
77 | $this->next->call();
78 | }
79 |
80 | /**
81 | * Parse input
82 | *
83 | * This method will attempt to parse the request body
84 | * based on its content type if available.
85 | *
86 | * @param string $input
87 | * @param string $contentType
88 | * @return mixed
89 | */
90 | protected function parse ( $input, $contentType ) {
91 | if ( isset($this->contentTypes[$contentType]) && is_callable($this->contentTypes[$contentType]) ) {
92 | $result = call_user_func($this->contentTypes[$contentType], $input);
93 | if ( $result ) {
94 | return $result;
95 | }
96 | }
97 | return $input;
98 | }
99 |
100 | /**
101 | * Parse JSON
102 | *
103 | * This method converts the raw JSON input
104 | * into an associative array.
105 | *
106 | * @param string $input
107 | * @return array|string
108 | */
109 | protected function parseJson( $input ) {
110 | if ( function_exists('json_decode') ) {
111 | $result = json_decode($input, true);
112 | if ( $result ) {
113 | return $result;
114 | }
115 | }
116 | }
117 |
118 | /**
119 | * Parse XML
120 | *
121 | * This method creates a SimpleXMLElement
122 | * based upon the XML input. If the SimpleXML
123 | * extension is not available, the raw input
124 | * will be returned unchanged.
125 | *
126 | * @param string $input
127 | * @return SimpleXMLElement|string
128 | */
129 | protected function parseXml( $input ) {
130 | if ( class_exists('SimpleXMLElement') ) {
131 | try {
132 | return new SimpleXMLElement($input);
133 | } catch ( Exception $e ) {}
134 | }
135 | return $input;
136 | }
137 |
138 | /**
139 | * Parse CSV
140 | *
141 | * This method parses CSV content into a numeric array
142 | * containing an array of data for each CSV line.
143 | *
144 | * @param string $input
145 | * @return array
146 | */
147 | protected function parseCsv( $input ) {
148 | $temp = fopen('php://memory', 'rw');
149 | fwrite($temp, $input);
150 | fseek($temp, 0);
151 | $res = array();
152 | while ( ($data = fgetcsv($temp)) !== false ) {
153 | $res[] = $data;
154 | }
155 | fclose($temp);
156 | return $res;
157 | }
158 | }
--------------------------------------------------------------------------------
/libs/Slim/Middleware/Flash.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Flash
36 | *
37 | * This is middleware for a Slim application that enables
38 | * Flash messaging between HTTP requests. This allows you
39 | * set Flash messages for the current request, for the next request,
40 | * or to retain messages from the previous request through to
41 | * the next request.
42 | *
43 | * @package Slim
44 | * @author Josh Lockhart
45 | * @since 1.5.2
46 | */
47 | class Slim_Middleware_Flash extends Slim_Middleware implements ArrayAccess {
48 | /**
49 | * @var array
50 | */
51 | protected $settings;
52 |
53 | /**
54 | * @var array
55 | */
56 | protected $messages;
57 |
58 | /**
59 | * Constructor
60 | * @param Slim $app
61 | * @param array $settings
62 | * @return void
63 | */
64 | public function __construct( $settings = array() ) {
65 | $this->settings = array_merge(array('key' => 'slim.flash'), $settings);
66 | $this->messages = array(
67 | 'prev' => array(), //flash messages from prev request (loaded when middleware called)
68 | 'next' => array(), //flash messages for next request
69 | 'now' => array() //flash messages for current request
70 | );
71 | }
72 |
73 | /**
74 | * Call
75 | * @return void
76 | */
77 | public function call() {
78 | //Read flash messaging from previous request if available
79 | $this->loadMessages();
80 |
81 | //Prepare flash messaging for current request
82 | $env = $this->app->environment();
83 | $env['slim.flash'] = $this;
84 | $this->next->call();
85 | $this->save();
86 | }
87 |
88 | /**
89 | * Now
90 | *
91 | * Specify a flash message for a given key to be shown for the current request
92 | *
93 | * @param string $key
94 | * @param string $value
95 | * @return void
96 | */
97 | public function now( $key, $value ) {
98 | $this->messages['now'][(string)$key] = $value;
99 | }
100 |
101 | /**
102 | * Set
103 | *
104 | * Specify a flash message for a given key to be shown for the next request
105 | *
106 | * @param string $key
107 | * @param string $value
108 | * @return void
109 | */
110 | public function set( $key, $value ) {
111 | $this->messages['next'][(string)$key] = $value;
112 | }
113 |
114 | /**
115 | * Keep
116 | *
117 | * Retain flash messages from the previous request for the next request
118 | *
119 | * @return void
120 | */
121 | public function keep() {
122 | foreach ( $this->messages['prev'] as $key => $val ) {
123 | $this->messages['next'][$key] = $val;
124 | }
125 | }
126 |
127 | /**
128 | * Save
129 | */
130 | public function save() {
131 | $_SESSION[$this->settings['key']] = $this->messages['next'];
132 | }
133 |
134 | /**
135 | * Load messages
136 | *
137 | * Load messages from previous request if available
138 | */
139 | public function loadMessages() {
140 | if ( isset($_SESSION[$this->settings['key']]) ) {
141 | $this->messages['prev'] = $_SESSION[$this->settings['key']];
142 | }
143 | }
144 |
145 | /**
146 | * Get messages
147 | *
148 | * Return array of flash messages to be shown for the current request
149 | *
150 | * @return array
151 | */
152 | public function getMessages() {
153 | return array_merge($this->messages['prev'], $this->messages['now']);
154 | }
155 |
156 | /**
157 | * Array Access: Offset Exists
158 | */
159 | public function offsetExists( $offset ) {
160 | $messages = $this->getMessages();
161 | return isset($messages[$offset]);
162 | }
163 |
164 | /**
165 | * Array Access: Offset Get
166 | */
167 | public function offsetGet( $offset ) {
168 | $messages = $this->getMessages();
169 | return isset($messages[$offset]) ? $messages[$offset] : null;
170 | }
171 |
172 | /**
173 | * Array Access: Offset Set
174 | */
175 | public function offsetSet( $offset, $value ) {
176 | $this->now($offset, $value);
177 | }
178 |
179 | /**
180 | * Array Access: Offset Unset
181 | */
182 | public function offsetUnset( $offset ) {
183 | unset($this->messages['prev'][$offset], $this->messages['now'][$offset]);
184 | }
185 | }
--------------------------------------------------------------------------------
/libs/Slim/Middleware/MethodOverride.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * HTTP Method Override
36 | *
37 | * This is middleware for a Slim application that allows traditional
38 | * desktop browsers to submit psuedo PUT and DELETE requests by relying
39 | * on a pre-determined request parameter. Without this middleware,
40 | * desktop browsers are only able to submit GET and POST requests.
41 | *
42 | * This middleware is included automatically!
43 | *
44 | * @package Slim
45 | * @author Josh Lockhart
46 | * @since 1.5.2
47 | */
48 | class Slim_Middleware_MethodOverride extends Slim_Middleware {
49 | /**
50 | * @var array
51 | */
52 | protected $settings;
53 |
54 | /**
55 | * Constructor
56 | * @param Slim $app
57 | * @param array $settings
58 | * @return void
59 | */
60 | public function __construct( $settings = array() ) {
61 | $this->settings = array_merge(array('key' => '_METHOD'), $settings);
62 | }
63 |
64 | /**
65 | * Call
66 | *
67 | * Implements Slim middleware interface. This method is invoked and passed
68 | * an array of environemnt variables. This middleware inspects the environment
69 | * variables for the HTTP method override parameter; if found, this middleware
70 | * modifies the environment settings so downstream middleware and/or the Slim
71 | * application will treat the request with the desired HTTP method.
72 | *
73 | * @param array $env
74 | * @return array[status, header, body]
75 | */
76 | public function call() {
77 | $env = $this->app->environment();
78 | if ( isset($env['X_HTTP_METHOD_OVERRIDE']) ) {
79 | // Header commonly used by Backbone.js and others
80 | $env['slim.method_override.original_method'] = $env['REQUEST_METHOD'];
81 | $env['REQUEST_METHOD'] = strtoupper($env['X_HTTP_METHOD_OVERRIDE']);
82 | } else if ( isset($env['REQUEST_METHOD']) && $env['REQUEST_METHOD'] === 'POST' ) {
83 | // HTML Form Override
84 | $req = new Slim_Http_Request($env);
85 | $method = $req->post($this->settings['key']);
86 | if ( $method ) {
87 | $env['slim.method_override.original_method'] = $env['REQUEST_METHOD'];
88 | $env['REQUEST_METHOD'] = strtoupper($method);
89 | }
90 | }
91 | $this->next->call();
92 | }
93 | }
--------------------------------------------------------------------------------
/libs/Slim/Middleware/PrettyExceptions.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Pretty Exceptions
36 | *
37 | * This middleware catches any Exception thrown by the surrounded
38 | * application and displays a developer-friendly diagnostic screen.
39 | *
40 | * @package Slim
41 | * @author Josh Lockhart
42 | * @since 1.0.0
43 | */
44 | class Slim_Middleware_PrettyExceptions extends Slim_Middleware {
45 | /**
46 | * @var array
47 | */
48 | protected $settings;
49 |
50 | /**
51 | * Constructor
52 | * @param Slim|middleware $app
53 | * @param array $settings
54 | */
55 | public function __construct( $settings = array() ) {
56 | $this->settings = $settings;
57 | }
58 |
59 | /**
60 | * Call
61 | * @return void
62 | */
63 | public function call() {
64 | try {
65 | $this->next->call();
66 | } catch ( Exception $e ) {
67 | $env = $this->app->environment();
68 | $env['slim.log']->error($e);
69 | $this->app->response()->status(500);
70 | $this->app->response()->body($this->renderBody($env, $e));
71 | }
72 | }
73 |
74 | /**
75 | * Render response body
76 | * @param array $env
77 | * @param Exception $exception
78 | * @return string
79 | */
80 | protected function renderBody( &$env, $exception ) {
81 | $title = 'Slim Application Error';
82 | $code = $exception->getCode();
83 | $message = $exception->getMessage();
84 | $file = $exception->getFile();
85 | $line = $exception->getLine();
86 | $trace = $exception->getTraceAsString();
87 | $html = sprintf('%s
', $title);
88 | $html .= 'The application could not run because of the following error:
';
89 | $html .= 'Details
';
90 | if ( $code ) {
91 | $html .= sprintf('Code: %s
', $code);
92 | }
93 | if ( $message ) {
94 | $html .= sprintf('Message: %s
', $message);
95 | }
96 | if ( $file ) {
97 | $html .= sprintf('File: %s
', $file);
98 | }
99 | if ( $line ) {
100 | $html .= sprintf('Line: %s
', $line);
101 | }
102 | if ( $trace ) {
103 | $html .= 'Trace
';
104 | $html .= sprintf('%s
', $trace);
105 | }
106 | return sprintf("%s%s", $title, $html);
107 | }
108 | }
--------------------------------------------------------------------------------
/libs/Slim/Middleware/SessionCookie.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Session Cookie
36 | *
37 | * This class provides an HTTP cookie storage mechanism
38 | * for session data. This class avoids using a PHP session
39 | * and instead serializes/unserializes the $_SESSION global
40 | * variable to/from an HTTP cookie.
41 | *
42 | * If a secret key is provided with this middleware, the HTTP
43 | * cookie will be checked for integrity to ensure the client-side
44 | * cookie is not changed.
45 | *
46 | * You should NEVER store sensitive data in a client-side cookie
47 | * in any format, encrypted or not. If you need to store sensitive
48 | * user information in a session, you should rely on PHP's native
49 | * session implementation, or use other middleware to store
50 | * session data in a database or alternative server-side cache.
51 | *
52 | * Because this class stores serialized session data in an HTTP cookie,
53 | * you are inherently limtied to 4 Kb. If you attempt to store
54 | * more than this amount, serialization will fail.
55 | *
56 | * @package Slim
57 | * @author Josh Lockhart
58 | * @since 1.5.2
59 | */
60 | class Slim_Middleware_SessionCookie extends Slim_Middleware {
61 | /**
62 | * @var array
63 | */
64 | protected $settings;
65 |
66 | /**
67 | * Constructor
68 | *
69 | * @param array $settings
70 | * @return void
71 | */
72 | public function __construct( $settings = array() ) {
73 | $this->settings = array_merge(array(
74 | 'expires' => '20 minutes',
75 | 'path' => '/',
76 | 'domain' => null,
77 | 'secure' => false,
78 | 'httponly' => false,
79 | 'name' => 'slim_session',
80 | 'secret' => 'CHANGE_ME',
81 | 'cipher' => MCRYPT_RIJNDAEL_256,
82 | 'cipher_mode' => MCRYPT_MODE_CBC
83 | ), $settings);
84 | if ( is_string($this->settings['expires']) ) {
85 | $this->settings['expires'] = strtotime($this->settings['expires']);
86 | }
87 | }
88 |
89 | /**
90 | * Call
91 | * @return void
92 | */
93 | public function call() {
94 | $this->loadSession();
95 | $this->next->call();
96 | $this->saveSession();
97 | }
98 |
99 | /**
100 | * Load session
101 | * @param array $env
102 | * @return void
103 | */
104 | protected function loadSession() {
105 | session_start();
106 | $value = Slim_Http_Util::decodeSecureCookie(
107 | $this->app->request()->cookies($this->settings['name']),
108 | $this->settings['secret'],
109 | $this->settings['cipher'],
110 | $this->settings['cipher_mode']
111 | );
112 | if ( $value ) {
113 | $_SESSION = unserialize($value);
114 | } else {
115 | $_SESSION = array();
116 | }
117 | }
118 |
119 | /**
120 | * Save session
121 | * @return void
122 | */
123 | protected function saveSession() {
124 | $value = Slim_Http_Util::encodeSecureCookie(
125 | serialize($_SESSION),
126 | $this->settings['expires'],
127 | $this->settings['secret'],
128 | $this->settings['cipher'],
129 | $this->settings['cipher_mode']
130 | );
131 | if ( strlen($value) > 4096 ) {
132 | $this->app->getLog()->error('WARNING! Slim_Middleware_SessionCookie data size is larger than 4KB. Content save failed.');
133 | } else {
134 | $this->app->response()->setCookie($this->settings['name'], array(
135 | 'value' => $value,
136 | 'domain' => $this->settings['domain'],
137 | 'path' => $this->settings['path'],
138 | 'expires' => $this->settings['expires'],
139 | 'secure' => $this->settings['secure'],
140 | 'httponly' => $this->settings['httponly']
141 | ));
142 | }
143 | session_destroy();
144 | }
145 | }
--------------------------------------------------------------------------------
/libs/Slim/Route.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Route
36 | * @package Slim
37 | * @author Josh Lockhart
38 | * @since 1.0.0
39 | */
40 | class Slim_Route {
41 | /**
42 | * @var string The route pattern (ie. "/books/:id")
43 | */
44 | protected $pattern;
45 |
46 | /**
47 | * @var mixed The callable associated with this route
48 | */
49 | protected $callable;
50 |
51 | /**
52 | * @var array Conditions for this route's URL parameters
53 | */
54 | protected $conditions = array();
55 |
56 | /**
57 | * @var array Default conditions applied to all Route instances
58 | */
59 | protected static $defaultConditions = array();
60 |
61 | /**
62 | * @var string The name of this route (optional)
63 | */
64 | protected $name;
65 |
66 | /**
67 | * @var array Key-value array of URL parameters
68 | */
69 | protected $params = array();
70 |
71 | /**
72 | * @var array HTTP methods supported by this Route
73 | */
74 | protected $methods = array();
75 |
76 | /**
77 | * @var Slim_Router The Router to which this Route belongs
78 | */
79 | protected $router;
80 |
81 | /**
82 | * @var array[Callable] Middleware
83 | */
84 | protected $middleware = array();
85 |
86 | /**
87 | * Constructor
88 | * @param string $pattern The URL pattern (ie. "/books/:id")
89 | * @param mixed $callable Anything that returns TRUE for is_callable()
90 | */
91 | public function __construct( $pattern, $callable ) {
92 | $this->setPattern($pattern);
93 | $this->setCallable($callable);
94 | $this->setConditions(self::getDefaultConditions());
95 | }
96 |
97 | /**
98 | * Set default route conditions for all instances
99 | * @param array $defaultConditions
100 | * @return void
101 | */
102 | public static function setDefaultConditions( array $defaultConditions ) {
103 | self::$defaultConditions = $defaultConditions;
104 | }
105 |
106 | /**
107 | * Get default route conditions for all instances
108 | * @return array
109 | */
110 | public static function getDefaultConditions() {
111 | return self::$defaultConditions;
112 | }
113 |
114 | /**
115 | * Get route pattern
116 | * @return string
117 | */
118 | public function getPattern() {
119 | return $this->pattern;
120 | }
121 |
122 | /**
123 | * Set route pattern
124 | * @param string $pattern
125 | * @return void
126 | */
127 | public function setPattern( $pattern ) {
128 | $this->pattern = str_replace(')', ')?', (string)$pattern);
129 | }
130 |
131 | /**
132 | * Get route callable
133 | * @return mixed
134 | */
135 | public function getCallable() {
136 | return $this->callable;
137 | }
138 |
139 | /**
140 | * Set route callable
141 | * @param mixed $callable
142 | * @return void
143 | */
144 | public function setCallable($callable) {
145 | $this->callable = $callable;
146 | }
147 |
148 | /**
149 | * Get route conditions
150 | * @return array
151 | */
152 | public function getConditions() {
153 | return $this->conditions;
154 | }
155 |
156 | /**
157 | * Set route conditions
158 | * @param array $conditions
159 | * @return void
160 | */
161 | public function setConditions( array $conditions ) {
162 | $this->conditions = $conditions;
163 | }
164 |
165 | /**
166 | * Get route name
167 | * @return string|null
168 | */
169 | public function getName() {
170 | return $this->name;
171 | }
172 |
173 | /**
174 | * Set route name
175 | * @param string $name
176 | * @return void
177 | */
178 | public function setName( $name ) {
179 | $this->name = (string)$name;
180 | $this->router->addNamedRoute($this->name, $this);
181 | }
182 |
183 | /**
184 | * Get route parameters
185 | * @return array
186 | */
187 | public function getParams() {
188 | return $this->params;
189 | }
190 |
191 | /**
192 | * Add supported HTTP method(s)
193 | * @return void
194 | */
195 | public function setHttpMethods() {
196 | $args = func_get_args();
197 | $this->methods = $args;
198 | }
199 |
200 | /**
201 | * Get supported HTTP methods
202 | * @return array
203 | */
204 | public function getHttpMethods() {
205 | return $this->methods;
206 | }
207 |
208 | /**
209 | * Append supported HTTP methods
210 | * @return void
211 | */
212 | public function appendHttpMethods() {
213 | $args = func_get_args();
214 | $this->methods = array_merge($this->methods, $args);
215 | }
216 |
217 | /**
218 | * Append supported HTTP methods (alias for Route::appendHttpMethods)
219 | * @return Slim_Route
220 | */
221 | public function via() {
222 | $args = func_get_args();
223 | $this->methods = array_merge($this->methods, $args);
224 | return $this;
225 | }
226 |
227 | /**
228 | * Detect support for an HTTP method
229 | * @return bool
230 | */
231 | public function supportsHttpMethod( $method ) {
232 | return in_array($method, $this->methods);
233 | }
234 |
235 | /**
236 | * Get router
237 | * @return Slim_Router
238 | */
239 | public function getRouter() {
240 | return $this->router;
241 | }
242 |
243 | /**
244 | * Set router
245 | * @param Slim_Router $router
246 | * @return void
247 | */
248 | public function setRouter( Slim_Router $router ) {
249 | $this->router = $router;
250 | }
251 |
252 | /**
253 | * Get middleware
254 | * @return array[Callable]
255 | */
256 | public function getMiddleware() {
257 | return $this->middleware;
258 | }
259 |
260 | /**
261 | * Set middleware
262 | *
263 | * This method allows middleware to be assigned to a specific Route.
264 | * If the method argument `is_callable` (including callable arrays!),
265 | * we directly append the argument to `$this->middleware`. Else, we
266 | * assume the argument is an array of callables and merge the array
267 | * with `$this->middleware`. Even if non-callables are included in the
268 | * argument array, we still merge them; we lazily check each item
269 | * against `is_callable` during Route::dispatch().
270 | *
271 | * @param Callable|array[Callable]
272 | * @return Slim_Route
273 | * @throws InvalidArgumentException If argument is not callable or not an array
274 | */
275 | public function setMiddleware( $middleware ) {
276 | if ( is_callable($middleware) ) {
277 | $this->middleware[] = $middleware;
278 | } else if ( is_array($middleware) ) {
279 | $this->middleware = array_merge($this->middleware, $middleware);
280 | } else {
281 | throw new InvalidArgumentException('Route middleware must be callable or an array of callables');
282 | }
283 | return $this;
284 | }
285 |
286 | /**
287 | * Matches URI?
288 | *
289 | * Parse this route's pattern, and then compare it to an HTTP resource URI
290 | * This method was modeled after the techniques demonstrated by Dan Sosedoff at:
291 | *
292 | * http://blog.sosedoff.com/2009/09/20/rails-like-php-url-router/
293 | *
294 | * @param string $resourceUri A Request URI
295 | * @return bool
296 | */
297 | public function matches( $resourceUri ) {
298 | //Extract URL params
299 | preg_match_all('@:([\w]+)@', $this->pattern, $paramNames, PREG_PATTERN_ORDER);
300 | $paramNames = $paramNames[0];
301 |
302 | //Convert URL params into regex patterns, construct a regex for this route
303 | $patternAsRegex = preg_replace_callback('@:[\w]+@', array($this, 'convertPatternToRegex'), $this->pattern);
304 | if ( substr($this->pattern, -1) === '/' ) {
305 | $patternAsRegex = $patternAsRegex . '?';
306 | }
307 | $patternAsRegex = '@^' . $patternAsRegex . '$@';
308 |
309 | //Cache URL params' names and values if this route matches the current HTTP request
310 | if ( preg_match($patternAsRegex, $resourceUri, $paramValues) ) {
311 | array_shift($paramValues);
312 | foreach ( $paramNames as $index => $value ) {
313 | $val = substr($value, 1);
314 | if ( isset($paramValues[$val]) ) {
315 | $this->params[$val] = urldecode($paramValues[$val]);
316 | }
317 | }
318 | return true;
319 | } else {
320 | return false;
321 | }
322 | }
323 |
324 | /**
325 | * Convert a URL parameter (ie. ":id") into a regular expression
326 | * @param array URL parameters
327 | * @return string Regular expression for URL parameter
328 | */
329 | protected function convertPatternToRegex( $matches ) {
330 | $key = str_replace(':', '', $matches[0]);
331 | if ( array_key_exists($key, $this->conditions) ) {
332 | return '(?P<' . $key . '>' . $this->conditions[$key] . ')';
333 | } else {
334 | return '(?P<' . $key . '>[a-zA-Z0-9_\-\.\!\~\*\\\'\(\)\:\@\&\=\$\+,%]+)';
335 | }
336 | }
337 |
338 | /**
339 | * Set route name
340 | * @param string $name The name of the route
341 | * @return Slim_Route
342 | */
343 | public function name( $name ) {
344 | $this->setName($name);
345 | return $this;
346 | }
347 |
348 | /**
349 | * Merge route conditions
350 | * @param array $conditions Key-value array of URL parameter conditions
351 | * @return Slim_Route
352 | */
353 | public function conditions( array $conditions ) {
354 | $this->conditions = array_merge($this->conditions, $conditions);
355 | return $this;
356 | }
357 |
358 | /**
359 | * Dispatch route
360 | *
361 | * This method invokes this route's callable. If middleware is
362 | * registered for this route, each callable middleware is invoked in
363 | * the order specified.
364 | *
365 | * This method is smart about trailing slashes on the route pattern.
366 | * If this route's pattern is defined with a trailing slash, and if the
367 | * current request URI does not have a trailing slash but otherwise
368 | * matches this route's pattern, a Slim_Exception_RequestSlash
369 | * will be thrown triggering an HTTP 301 Permanent Redirect to the same
370 | * URI _with_ a trailing slash. This Exception is caught in the
371 | * `Slim::run` loop. If this route's pattern is defined without a
372 | * trailing slash, and if the current request URI does have a trailing
373 | * slash, this route will not be matched and a 404 Not Found
374 | * response will be sent if no subsequent matching routes are found.
375 | *
376 | * @return bool Was route callable invoked successfully?
377 | * @throws Slim_Exception_RequestSlash
378 | */
379 | public function dispatch() {
380 | if ( substr($this->pattern, -1) === '/' && substr($this->router->getRequest()->getResourceUri(), -1) !== '/' ) {
381 | throw new Slim_Exception_RequestSlash();
382 | }
383 |
384 | //Invoke middleware
385 | $req = $this->router->getRequest();
386 | $res = $this->router->getResponse();
387 | foreach ( $this->middleware as $mw ) {
388 | if ( is_callable($mw) ) {
389 | call_user_func_array($mw, array($req, $res, $this));
390 | }
391 | }
392 |
393 | //Invoke callable
394 | if ( is_callable($this->getCallable()) ) {
395 | call_user_func_array($this->callable, array_values($this->params));
396 | return true;
397 | }
398 | return false;
399 | }
400 | }
--------------------------------------------------------------------------------
/libs/Slim/Router.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Router
36 | *
37 | * This class organizes Route objects and, upon request, will
38 | * return an iterator for routes that match the HTTP request URI.
39 | *
40 | * @package Slim
41 | * @author Josh Lockhart
42 | * @since 1.0.0
43 | */
44 | class Slim_Router implements IteratorAggregate {
45 | /**
46 | * @var Slim_Http_Request
47 | */
48 | protected $request;
49 |
50 | /**
51 | * @var Slim_Http_Response
52 | */
53 | protected $response;
54 |
55 | /**
56 | * @var array Lookup hash of all routes
57 | */
58 | protected $routes;
59 |
60 | /**
61 | * @var array Lookup hash of named routes, keyed by route name
62 | */
63 | protected $namedRoutes;
64 |
65 | /**
66 | * @var array Array of routes that match the Request URI (lazy-loaded)
67 | */
68 | protected $matchedRoutes;
69 |
70 | /**
71 | * @var mixed Callable to be invoked if no matching routes are found
72 | */
73 | protected $notFound;
74 |
75 | /**
76 | * @var mixed Callable to be invoked if application error
77 | */
78 | protected $error;
79 |
80 | /**
81 | * Constructor
82 | * @param Slim_Http_Request $request The HTTP request object
83 | * @param Slim_Http_Response $response The HTTP response object
84 | */
85 | public function __construct( Slim_Http_Request $request, Slim_Http_Response $response ) {
86 | $this->request = $request;
87 | $this->response = $response;
88 | $this->routes = array();
89 | $this->namedRoutes = array();
90 | }
91 |
92 | /**
93 | * Get Iterator
94 | * @return ArrayIterator
95 | */
96 | public function getIterator() {
97 | return new ArrayIterator($this->getMatchedRoutes());
98 | }
99 |
100 | /**
101 | * Get Request
102 | * @return Slim_Http_Request
103 | */
104 | public function getRequest() {
105 | return $this->request;
106 | }
107 |
108 | /**
109 | * Get Response
110 | * @return Slim_Http_Response
111 | */
112 | public function getResponse() {
113 | return $this->response;
114 | }
115 |
116 | /**
117 | * Return routes that match the current request
118 | * @return array[Slim_Route]
119 | */
120 | public function getMatchedRoutes( $reload = false ) {
121 | if ( $reload || is_null($this->matchedRoutes) ) {
122 | $this->matchedRoutes = array();
123 | foreach ( $this->routes as $route ) {
124 | if ( $route->matches($this->request->getResourceUri()) ) {
125 | $this->matchedRoutes[] = $route;
126 | }
127 | }
128 | }
129 | return $this->matchedRoutes;
130 | }
131 |
132 | /**
133 | * Map a route to a callback function
134 | * @param string $pattern The URL pattern (ie. "/books/:id")
135 | * @param mixed $callable Anything that returns TRUE for is_callable()
136 | * @return Slim_Route
137 | */
138 | public function map( $pattern, $callable ) {
139 | $route = new Slim_Route($pattern, $callable);
140 | $route->setRouter($this);
141 | $this->routes[] = $route;
142 | return $route;
143 | }
144 |
145 | /**
146 | * Get URL for named route
147 | * @param string $name The name of the route
148 | * @param array Associative array of URL parameter names and values
149 | * @throws RuntimeException If named route not found
150 | * @return string The URL for the given route populated with the given parameters
151 | */
152 | public function urlFor( $name, $params = array() ) {
153 | if ( !$this->hasNamedRoute($name) ) {
154 | throw new RuntimeException('Named route not found for name: ' . $name);
155 | }
156 | $pattern = $this->getNamedRoute($name)->getPattern();
157 | $search = $replace = array();
158 | foreach ( $params as $key => $value ) {
159 | $search[] = ':' . $key;
160 | $replace[] = $value;
161 | }
162 | $pattern = str_replace($search, $replace, $pattern);
163 | //Remove remnants of unpopulated, trailing optional pattern segments
164 | return preg_replace(array(
165 | '@\(\/?:.+\/??\)\??@',
166 | '@\?|\(|\)@'
167 | ), '', $this->request->getRootUri() . $pattern);
168 | }
169 |
170 | /**
171 | * Add named route
172 | * @param string $name The route name
173 | * @param Slim_Route $route The route object
174 | * @throws RuntimeException If a named route already exists with the same name
175 | * @return void
176 | */
177 | public function addNamedRoute( $name, Slim_Route $route ) {
178 | if ( $this->hasNamedRoute($name) ) {
179 | throw new RuntimeException('Named route already exists with name: ' . $name);
180 | }
181 | $this->namedRoutes[(string)$name] = $route;
182 | }
183 |
184 | /**
185 | * Has named route
186 | * @param string $name The route name
187 | * @return bool
188 | */
189 | public function hasNamedRoute( $name ) {
190 | return isset($this->namedRoutes[(string)$name]);
191 | }
192 |
193 | /**
194 | * Get named route
195 | * @param string $name
196 | * @return Slim_Route|null
197 | */
198 | public function getNamedRoute( $name ) {
199 | if ( $this->hasNamedRoute($name) ) {
200 | return $this->namedRoutes[(string)$name];
201 | } else {
202 | return null;
203 | }
204 | }
205 |
206 | /**
207 | * Get named routes
208 | * @return ArrayIterator
209 | */
210 | public function getNamedRoutes() {
211 | return new ArrayIterator($this->namedRoutes);
212 | }
213 |
214 | /**
215 | * Register a 404 Not Found callback
216 | * @param mixed $callable Anything that returns TRUE for is_callable()
217 | * @return mixed
218 | */
219 | public function notFound( $callable = null ) {
220 | if ( is_callable($callable) ) {
221 | $this->notFound = $callable;
222 | }
223 | return $this->notFound;
224 | }
225 |
226 | /**
227 | * Register a 500 Error callback
228 | * @param mixed $callable Anything that returns TRUE for is_callable()
229 | * @return mixed
230 | */
231 | public function error( $callable = null ) {
232 | if ( is_callable($callable) ) {
233 | $this->error = $callable;
234 | }
235 | return $this->error;
236 | }
237 | }
--------------------------------------------------------------------------------
/libs/Slim/View.php:
--------------------------------------------------------------------------------
1 |
6 | * @copyright 2011 Josh Lockhart
7 | * @link http://www.slimframework.com
8 | * @license http://www.slimframework.com/license
9 | * @version 1.6.0
10 | * @package Slim
11 | *
12 | * MIT LICENSE
13 | *
14 | * Permission is hereby granted, free of charge, to any person obtaining
15 | * a copy of this software and associated documentation files (the
16 | * "Software"), to deal in the Software without restriction, including
17 | * without limitation the rights to use, copy, modify, merge, publish,
18 | * distribute, sublicense, and/or sell copies of the Software, and to
19 | * permit persons to whom the Software is furnished to do so, subject to
20 | * the following conditions:
21 | *
22 | * The above copyright notice and this permission notice shall be
23 | * included in all copies or substantial portions of the Software.
24 | *
25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 | */
33 |
34 | /**
35 | * Slim View
36 | *
37 | * The View is responsible for rendering and/or displaying a template.
38 | * It is recommended that you subclass View and re-implement the
39 | * `View::render` method to use a custom templating engine such as
40 | * Smarty, Twig, Mustache, etc. It is important that `View::render`
41 | * `return` the final template output. Do not `echo` the output.
42 | *
43 | * @package Slim
44 | * @author Josh Lockhart
45 | * @since 1.0.0
46 | */
47 | class Slim_View {
48 | /**
49 | * @var array Key-value array of data available to the template
50 | */
51 | protected $data = array();
52 |
53 | /**
54 | * @var string Absolute or relative path to the templates directory
55 | */
56 | protected $templatesDirectory;
57 |
58 | /**
59 | * Constructor
60 | *
61 | * This is empty but may be overridden in a subclass
62 | */
63 | public function __construct() {}
64 |
65 | /**
66 | * Get data
67 | * @param string $key
68 | * @return array|mixed|null All View data if no $key, value of datum
69 | * if $key, or NULL if $key but datum
70 | * does not exist.
71 | */
72 | public function getData( $key = null ) {
73 | if ( !is_null($key) ) {
74 | return isset($this->data[$key]) ? $this->data[$key] : null;
75 | } else {
76 | return $this->data;
77 | }
78 | }
79 |
80 | /**
81 | * Set data
82 | *
83 | * This method is overloaded to accept two different method signatures.
84 | * You may use this to set a specific key with a specfic value,
85 | * or you may use this to set all data to a specific array.
86 | *
87 | * USAGE:
88 | *
89 | * View::setData('color', 'red');
90 | * View::setData(array('color' => 'red', 'number' => 1));
91 | *
92 | * @param string|array
93 | * @param mixed Optional. Only use if first argument is a string.
94 | * @return void
95 | * @throws InvalidArgumentException If incorrect method signature
96 | */
97 | public function setData() {
98 | $args = func_get_args();
99 | if ( count($args) === 1 && is_array($args[0]) ) {
100 | $this->data = $args[0];
101 | } else if ( count($args) === 2 ) {
102 | $this->data[(string)$args[0]] = $args[1];
103 | } else {
104 | throw new InvalidArgumentException('Cannot set View data with provided arguments. Usage: `View::setData( $key, $value );` or `View::setData([ key => value, ... ]);`');
105 | }
106 | }
107 |
108 | /**
109 | * Append data to existing View data
110 | * @param array $data
111 | * @return void
112 | */
113 | public function appendData( array $data ) {
114 | $this->data = array_merge($this->data, $data);
115 | }
116 |
117 | /**
118 | * Get templates directory
119 | * @return string|null Path to templates directory without trailing slash
120 | */
121 | public function getTemplatesDirectory() {
122 | return $this->templatesDirectory;
123 | }
124 |
125 | /**
126 | * Set templates directory
127 | * @param string $dir
128 | * @return void
129 | * @throws RuntimeException If directory is not a directory or does not exist
130 | */
131 | public function setTemplatesDirectory( $dir ) {
132 | $this->templatesDirectory = rtrim($dir, '/');
133 | }
134 |
135 | /**
136 | * Display template
137 | *
138 | * This method echoes the rendered template to the current output buffer
139 | *
140 | * @param string $template Path to template file relative to templates directoy
141 | * @return void
142 | */
143 | public function display( $template ) {
144 | echo $this->render($template);
145 | }
146 |
147 | /**
148 | * Render template
149 | * @param string $template Path to template file relative to templates directory
150 | * @return string Rendered template
151 | * @throws RuntimeException If template does not exist
152 | */
153 | public function render( $template ) {
154 | extract($this->data);
155 | $templatePath = $this->getTemplatesDirectory() . '/' . ltrim($template, '/');
156 | if ( !file_exists($templatePath) ) {
157 | throw new RuntimeException('View cannot render template `' . $templatePath . '`. Template does not exist.');
158 | }
159 | ob_start();
160 | require $templatePath;
161 | return ob_get_clean();
162 | }
163 |
164 | }
--------------------------------------------------------------------------------
/libs/spyc.php:
--------------------------------------------------------------------------------
1 |
6 | * @author Chris Wanstrath
7 | * @link http://code.google.com/p/spyc/
8 | * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen
9 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
10 | * @package Spyc
11 | */
12 |
13 | if (!function_exists('spyc_load')) {
14 | /**
15 | * Parses YAML to array.
16 | * @param string $string YAML string.
17 | * @return array
18 | */
19 | function spyc_load ($string) {
20 | return Spyc::YAMLLoadString($string);
21 | }
22 | }
23 |
24 | if (!function_exists('spyc_load_file')) {
25 | /**
26 | * Parses YAML to array.
27 | * @param string $file Path to YAML file.
28 | * @return array
29 | */
30 | function spyc_load_file ($file) {
31 | return Spyc::YAMLLoad($file);
32 | }
33 | }
34 |
35 | /**
36 | * The Simple PHP YAML Class.
37 | *
38 | * This class can be used to read a YAML file and convert its contents
39 | * into a PHP array. It currently supports a very limited subsection of
40 | * the YAML spec.
41 | *
42 | * Usage:
43 | *
44 | * $Spyc = new Spyc;
45 | * $array = $Spyc->load($file);
46 | *
47 | * or:
48 | *
49 | * $array = Spyc::YAMLLoad($file);
50 | *
51 | * or:
52 | *
53 | * $array = spyc_load_file($file);
54 | *
55 | * @package Spyc
56 | */
57 | class Spyc {
58 |
59 | // SETTINGS
60 |
61 | const REMPTY = "\0\0\0\0\0";
62 |
63 | /**
64 | * Setting this to true will force YAMLDump to enclose any string value in
65 | * quotes. False by default.
66 | *
67 | * @var bool
68 | */
69 | public $setting_dump_force_quotes = false;
70 |
71 | /**
72 | * Setting this to true will forse YAMLLoad to use syck_load function when
73 | * possible. False by default.
74 | * @var bool
75 | */
76 | public $setting_use_syck_is_possible = false;
77 |
78 |
79 |
80 | /**#@+
81 | * @access private
82 | * @var mixed
83 | */
84 | private $_dumpIndent;
85 | private $_dumpWordWrap;
86 | private $_containsGroupAnchor = false;
87 | private $_containsGroupAlias = false;
88 | private $path;
89 | private $result;
90 | private $LiteralPlaceHolder = '___YAML_Literal_Block___';
91 | private $SavedGroups = array();
92 | private $indent;
93 | /**
94 | * Path modifier that should be applied after adding current element.
95 | * @var array
96 | */
97 | private $delayedPath = array();
98 |
99 | /**#@+
100 | * @access public
101 | * @var mixed
102 | */
103 | public $_nodeId;
104 |
105 | /**
106 | * Load a valid YAML string to Spyc.
107 | * @param string $input
108 | * @return array
109 | */
110 | public function load ($input) {
111 | return $this->__loadString($input);
112 | }
113 |
114 | /**
115 | * Load a valid YAML file to Spyc.
116 | * @param string $file
117 | * @return array
118 | */
119 | public function loadFile ($file) {
120 | return $this->__load($file);
121 | }
122 |
123 | /**
124 | * Load YAML into a PHP array statically
125 | *
126 | * The load method, when supplied with a YAML stream (string or file),
127 | * will do its best to convert YAML in a file into a PHP array. Pretty
128 | * simple.
129 | * Usage:
130 | *
131 | * $array = Spyc::YAMLLoad('lucky.yaml');
132 | * print_r($array);
133 | *
134 | * @access public
135 | * @return array
136 | * @param string $input Path of YAML file or string containing YAML
137 | */
138 | public static function YAMLLoad($input) {
139 | $Spyc = new Spyc;
140 | return $Spyc->__load($input);
141 | }
142 |
143 | /**
144 | * Load a string of YAML into a PHP array statically
145 | *
146 | * The load method, when supplied with a YAML string, will do its best
147 | * to convert YAML in a string into a PHP array. Pretty simple.
148 | *
149 | * Note: use this function if you don't want files from the file system
150 | * loaded and processed as YAML. This is of interest to people concerned
151 | * about security whose input is from a string.
152 | *
153 | * Usage:
154 | *
155 | * $array = Spyc::YAMLLoadString("---\n0: hello world\n");
156 | * print_r($array);
157 | *
158 | * @access public
159 | * @return array
160 | * @param string $input String containing YAML
161 | */
162 | public static function YAMLLoadString($input) {
163 | $Spyc = new Spyc;
164 | return $Spyc->__loadString($input);
165 | }
166 |
167 | /**
168 | * Dump YAML from PHP array statically
169 | *
170 | * The dump method, when supplied with an array, will do its best
171 | * to convert the array into friendly YAML. Pretty simple. Feel free to
172 | * save the returned string as nothing.yaml and pass it around.
173 | *
174 | * Oh, and you can decide how big the indent is and what the wordwrap
175 | * for folding is. Pretty cool -- just pass in 'false' for either if
176 | * you want to use the default.
177 | *
178 | * Indent's default is 2 spaces, wordwrap's default is 40 characters. And
179 | * you can turn off wordwrap by passing in 0.
180 | *
181 | * @access public
182 | * @return string
183 | * @param array $array PHP array
184 | * @param int $indent Pass in false to use the default, which is 2
185 | * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
186 | */
187 | public static function YAMLDump($array,$indent = false,$wordwrap = false) {
188 | $spyc = new Spyc;
189 | return $spyc->dump($array,$indent,$wordwrap);
190 | }
191 |
192 |
193 | /**
194 | * Dump PHP array to YAML
195 | *
196 | * The dump method, when supplied with an array, will do its best
197 | * to convert the array into friendly YAML. Pretty simple. Feel free to
198 | * save the returned string as tasteful.yaml and pass it around.
199 | *
200 | * Oh, and you can decide how big the indent is and what the wordwrap
201 | * for folding is. Pretty cool -- just pass in 'false' for either if
202 | * you want to use the default.
203 | *
204 | * Indent's default is 2 spaces, wordwrap's default is 40 characters. And
205 | * you can turn off wordwrap by passing in 0.
206 | *
207 | * @access public
208 | * @return string
209 | * @param array $array PHP array
210 | * @param int $indent Pass in false to use the default, which is 2
211 | * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
212 | */
213 | public function dump($array,$indent = false,$wordwrap = false) {
214 | // Dumps to some very clean YAML. We'll have to add some more features
215 | // and options soon. And better support for folding.
216 |
217 | // New features and options.
218 | if ($indent === false or !is_numeric($indent)) {
219 | $this->_dumpIndent = 2;
220 | } else {
221 | $this->_dumpIndent = $indent;
222 | }
223 |
224 | if ($wordwrap === false or !is_numeric($wordwrap)) {
225 | $this->_dumpWordWrap = 40;
226 | } else {
227 | $this->_dumpWordWrap = $wordwrap;
228 | }
229 |
230 | // New YAML document
231 | $string = "---\n";
232 |
233 | // Start at the base of the array and move through it.
234 | if ($array) {
235 | $array = (array)$array;
236 | $previous_key = -1;
237 | foreach ($array as $key => $value) {
238 | if (!isset($first_key)) $first_key = $key;
239 | $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array);
240 | $previous_key = $key;
241 | }
242 | }
243 | return $string;
244 | }
245 |
246 | /**
247 | * Attempts to convert a key / value array item to YAML
248 | * @access private
249 | * @return string
250 | * @param $key The name of the key
251 | * @param $value The value of the item
252 | * @param $indent The indent of the current node
253 | */
254 | private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) {
255 | if (is_array($value)) {
256 | if (empty ($value))
257 | return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array);
258 | // It has children. What to do?
259 | // Make it the right kind of item
260 | $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array);
261 | // Add the indent
262 | $indent += $this->_dumpIndent;
263 | // Yamlize the array
264 | $string .= $this->_yamlizeArray($value,$indent);
265 | } elseif (!is_array($value)) {
266 | // It doesn't have children. Yip.
267 | $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array);
268 | }
269 | return $string;
270 | }
271 |
272 | /**
273 | * Attempts to convert an array to YAML
274 | * @access private
275 | * @return string
276 | * @param $array The array you want to convert
277 | * @param $indent The indent of the current level
278 | */
279 | private function _yamlizeArray($array,$indent) {
280 | if (is_array($array)) {
281 | $string = '';
282 | $previous_key = -1;
283 | foreach ($array as $key => $value) {
284 | if (!isset($first_key)) $first_key = $key;
285 | $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array);
286 | $previous_key = $key;
287 | }
288 | return $string;
289 | } else {
290 | return false;
291 | }
292 | }
293 |
294 | /**
295 | * Returns YAML from a key and a value
296 | * @access private
297 | * @return string
298 | * @param $key The name of the key
299 | * @param $value The value of the item
300 | * @param $indent The indent of the current node
301 | */
302 | private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) {
303 | // do some folding here, for blocks
304 | if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false ||
305 | strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, ' ') !== false ||
306 | strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 ||
307 | substr ($value, -1, 1) == ':')
308 | ) {
309 | $value = $this->_doLiteralBlock($value,$indent);
310 | } else {
311 | $value = $this->_doFolding($value,$indent);
312 | }
313 |
314 | if ($value === array()) $value = '[ ]';
315 | if (in_array ($value, array ('true', 'TRUE', 'false', 'FALSE', 'y', 'Y', 'n', 'N', 'null', 'NULL'), true)) {
316 | $value = $this->_doLiteralBlock($value,$indent);
317 | }
318 | if (trim ($value) != $value)
319 | $value = $this->_doLiteralBlock($value,$indent);
320 |
321 | if (is_bool($value)) {
322 | $value = ($value) ? "true" : "false";
323 | }
324 |
325 | if ($value === null) $value = 'null';
326 | if ($value === "'" . self::REMPTY . "'") $value = null;
327 |
328 | $spaces = str_repeat(' ',$indent);
329 |
330 | //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) {
331 | if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) {
332 | // It's a sequence
333 | $string = $spaces.'- '.$value."\n";
334 | } else {
335 | // if ($first_key===0) throw new Exception('Keys are all screwy. The first one was zero, now it\'s "'. $key .'"');
336 | // It's mapped
337 | if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; }
338 | $string = rtrim ($spaces.$key.': '.$value)."\n";
339 | }
340 | return $string;
341 | }
342 |
343 | /**
344 | * Creates a literal block for dumping
345 | * @access private
346 | * @return string
347 | * @param $value
348 | * @param $indent int The value of the indent
349 | */
350 | private function _doLiteralBlock($value,$indent) {
351 | if ($value === "\n") return '\n';
352 | if (strpos($value, "\n") === false && strpos($value, "'") === false) {
353 | return sprintf ("'%s'", $value);
354 | }
355 | if (strpos($value, "\n") === false && strpos($value, '"') === false) {
356 | return sprintf ('"%s"', $value);
357 | }
358 | $exploded = explode("\n",$value);
359 | $newValue = '|';
360 | $indent += $this->_dumpIndent;
361 | $spaces = str_repeat(' ',$indent);
362 | foreach ($exploded as $line) {
363 | $newValue .= "\n" . $spaces . ($line);
364 | }
365 | return $newValue;
366 | }
367 |
368 | /**
369 | * Folds a string of text, if necessary
370 | * @access private
371 | * @return string
372 | * @param $value The string you wish to fold
373 | */
374 | private function _doFolding($value,$indent) {
375 | // Don't do anything if wordwrap is set to 0
376 |
377 | if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) {
378 | $indent += $this->_dumpIndent;
379 | $indent = str_repeat(' ',$indent);
380 | $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
381 | $value = ">\n".$indent.$wrapped;
382 | } else {
383 | if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY)
384 | $value = '"' . $value . '"';
385 | }
386 |
387 |
388 | return $value;
389 | }
390 |
391 | // LOADING FUNCTIONS
392 |
393 | private function __load($input) {
394 | $Source = $this->loadFromSource($input);
395 | return $this->loadWithSource($Source);
396 | }
397 |
398 | private function __loadString($input) {
399 | $Source = $this->loadFromString($input);
400 | return $this->loadWithSource($Source);
401 | }
402 |
403 | private function loadWithSource($Source) {
404 | if (empty ($Source)) return array();
405 | if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) {
406 | $array = syck_load (implode ('', $Source));
407 | return is_array($array) ? $array : array();
408 | }
409 |
410 | $this->path = array();
411 | $this->result = array();
412 |
413 | $cnt = count($Source);
414 | for ($i = 0; $i < $cnt; $i++) {
415 | $line = $Source[$i];
416 |
417 | $this->indent = strlen($line) - strlen(ltrim($line));
418 | $tempPath = $this->getParentPathByIndent($this->indent);
419 | $line = self::stripIndent($line, $this->indent);
420 | if (self::isComment($line)) continue;
421 | if (self::isEmpty($line)) continue;
422 | $this->path = $tempPath;
423 |
424 | $literalBlockStyle = self::startsLiteralBlock($line);
425 | if ($literalBlockStyle) {
426 | $line = rtrim ($line, $literalBlockStyle . " \n");
427 | $literalBlock = '';
428 | $line .= $this->LiteralPlaceHolder;
429 | $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1]));
430 | while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) {
431 | $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent);
432 | }
433 | $i--;
434 | }
435 |
436 | while (++$i < $cnt && self::greedilyNeedNextLine($line)) {
437 | $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t");
438 | }
439 | $i--;
440 |
441 |
442 |
443 | if (strpos ($line, '#')) {
444 | if (strpos ($line, '"') === false && strpos ($line, "'") === false)
445 | $line = preg_replace('/\s+#(.+)$/','',$line);
446 | }
447 |
448 | $lineArray = $this->_parseLine($line);
449 |
450 | if ($literalBlockStyle)
451 | $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock);
452 |
453 | $this->addArray($lineArray, $this->indent);
454 |
455 | foreach ($this->delayedPath as $indent => $delayedPath)
456 | $this->path[$indent] = $delayedPath;
457 |
458 | $this->delayedPath = array();
459 |
460 | }
461 | return $this->result;
462 | }
463 |
464 | private function loadFromSource ($input) {
465 | if (!empty($input) && strpos($input, "\n") === false && file_exists($input))
466 | return file($input);
467 |
468 | return $this->loadFromString($input);
469 | }
470 |
471 | private function loadFromString ($input) {
472 | $lines = explode("\n",$input);
473 | foreach ($lines as $k => $_) {
474 | $lines[$k] = rtrim ($_, "\r");
475 | }
476 | return $lines;
477 | }
478 |
479 | /**
480 | * Parses YAML code and returns an array for a node
481 | * @access private
482 | * @return array
483 | * @param string $line A line from the YAML file
484 | */
485 | private function _parseLine($line) {
486 | if (!$line) return array();
487 | $line = trim($line);
488 | if (!$line) return array();
489 |
490 | $array = array();
491 |
492 | $group = $this->nodeContainsGroup($line);
493 | if ($group) {
494 | $this->addGroup($line, $group);
495 | $line = $this->stripGroup ($line, $group);
496 | }
497 |
498 | if ($this->startsMappedSequence($line))
499 | return $this->returnMappedSequence($line);
500 |
501 | if ($this->startsMappedValue($line))
502 | return $this->returnMappedValue($line);
503 |
504 | if ($this->isArrayElement($line))
505 | return $this->returnArrayElement($line);
506 |
507 | if ($this->isPlainArray($line))
508 | return $this->returnPlainArray($line);
509 |
510 |
511 | return $this->returnKeyValuePair($line);
512 |
513 | }
514 |
515 | /**
516 | * Finds the type of the passed value, returns the value as the new type.
517 | * @access private
518 | * @param string $value
519 | * @return mixed
520 | */
521 | private function _toType($value) {
522 | if ($value === '') return null;
523 | $first_character = $value[0];
524 | $last_character = substr($value, -1, 1);
525 |
526 | $is_quoted = false;
527 | do {
528 | if (!$value) break;
529 | if ($first_character != '"' && $first_character != "'") break;
530 | if ($last_character != '"' && $last_character != "'") break;
531 | $is_quoted = true;
532 | } while (0);
533 |
534 | if ($is_quoted)
535 | return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\'\'' => '\'', '\\\'' => '\''));
536 |
537 | if (strpos($value, ' #') !== false && !$is_quoted)
538 | $value = preg_replace('/\s+#(.+)$/','',$value);
539 |
540 | if (!$is_quoted) $value = str_replace('\n', "\n", $value);
541 |
542 | if ($first_character == '[' && $last_character == ']') {
543 | // Take out strings sequences and mappings
544 | $innerValue = trim(substr ($value, 1, -1));
545 | if ($innerValue === '') return array();
546 | $explode = $this->_inlineEscape($innerValue);
547 | // Propagate value array
548 | $value = array();
549 | foreach ($explode as $v) {
550 | $value[] = $this->_toType($v);
551 | }
552 | return $value;
553 | }
554 |
555 | if (strpos($value,': ')!==false && $first_character != '{') {
556 | $array = explode(': ',$value);
557 | $key = trim($array[0]);
558 | array_shift($array);
559 | $value = trim(implode(': ',$array));
560 | $value = $this->_toType($value);
561 | return array($key => $value);
562 | }
563 |
564 | if ($first_character == '{' && $last_character == '}') {
565 | $innerValue = trim(substr ($value, 1, -1));
566 | if ($innerValue === '') return array();
567 | // Inline Mapping
568 | // Take out strings sequences and mappings
569 | $explode = $this->_inlineEscape($innerValue);
570 | // Propagate value array
571 | $array = array();
572 | foreach ($explode as $v) {
573 | $SubArr = $this->_toType($v);
574 | if (empty($SubArr)) continue;
575 | if (is_array ($SubArr)) {
576 | $array[key($SubArr)] = $SubArr[key($SubArr)]; continue;
577 | }
578 | $array[] = $SubArr;
579 | }
580 | return $array;
581 | }
582 |
583 | if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') {
584 | return null;
585 | }
586 |
587 | if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){
588 | $intvalue = (int)$value;
589 | if ($intvalue != PHP_INT_MAX)
590 | $value = $intvalue;
591 | return $value;
592 | }
593 |
594 | if (in_array($value,
595 | array('true', 'on', '+', 'yes', 'y', 'True', 'TRUE', 'On', 'ON', 'YES', 'Yes', 'Y'))) {
596 | return true;
597 | }
598 |
599 | if (in_array(strtolower($value),
600 | array('false', 'off', '-', 'no', 'n'))) {
601 | return false;
602 | }
603 |
604 | if (is_numeric($value)) {
605 | if ($value === '0') return 0;
606 | if (rtrim ($value, 0) === $value)
607 | $value = (float)$value;
608 | return $value;
609 | }
610 |
611 | return $value;
612 | }
613 |
614 | /**
615 | * Used in inlines to check for more inlines or quoted strings
616 | * @access private
617 | * @return array
618 | */
619 | private function _inlineEscape($inline) {
620 | // There's gotta be a cleaner way to do this...
621 | // While pure sequences seem to be nesting just fine,
622 | // pure mappings and mappings with sequences inside can't go very
623 | // deep. This needs to be fixed.
624 |
625 | $seqs = array();
626 | $maps = array();
627 | $saved_strings = array();
628 |
629 | // Check for strings
630 | $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
631 | if (preg_match_all($regex,$inline,$strings)) {
632 | $saved_strings = $strings[0];
633 | $inline = preg_replace($regex,'YAMLString',$inline);
634 | }
635 | unset($regex);
636 |
637 | $i = 0;
638 | do {
639 |
640 | // Check for sequences
641 | while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) {
642 | $seqs[] = $matchseqs[0];
643 | $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1);
644 | }
645 |
646 | // Check for mappings
647 | while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) {
648 | $maps[] = $matchmaps[0];
649 | $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1);
650 | }
651 |
652 | if ($i++ >= 10) break;
653 |
654 | } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false);
655 |
656 | $explode = explode(', ',$inline);
657 | $stringi = 0; $i = 0;
658 |
659 | while (1) {
660 |
661 | // Re-add the sequences
662 | if (!empty($seqs)) {
663 | foreach ($explode as $key => $value) {
664 | if (strpos($value,'YAMLSeq') !== false) {
665 | foreach ($seqs as $seqk => $seq) {
666 | $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value);
667 | $value = $explode[$key];
668 | }
669 | }
670 | }
671 | }
672 |
673 | // Re-add the mappings
674 | if (!empty($maps)) {
675 | foreach ($explode as $key => $value) {
676 | if (strpos($value,'YAMLMap') !== false) {
677 | foreach ($maps as $mapk => $map) {
678 | $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value);
679 | $value = $explode[$key];
680 | }
681 | }
682 | }
683 | }
684 |
685 |
686 | // Re-add the strings
687 | if (!empty($saved_strings)) {
688 | foreach ($explode as $key => $value) {
689 | while (strpos($value,'YAMLString') !== false) {
690 | $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1);
691 | unset($saved_strings[$stringi]);
692 | ++$stringi;
693 | $value = $explode[$key];
694 | }
695 | }
696 | }
697 |
698 | $finished = true;
699 | foreach ($explode as $key => $value) {
700 | if (strpos($value,'YAMLSeq') !== false) {
701 | $finished = false; break;
702 | }
703 | if (strpos($value,'YAMLMap') !== false) {
704 | $finished = false; break;
705 | }
706 | if (strpos($value,'YAMLString') !== false) {
707 | $finished = false; break;
708 | }
709 | }
710 | if ($finished) break;
711 |
712 | $i++;
713 | if ($i > 10)
714 | break; // Prevent infinite loops.
715 | }
716 |
717 | return $explode;
718 | }
719 |
720 | private function literalBlockContinues ($line, $lineIndent) {
721 | if (!trim($line)) return true;
722 | if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true;
723 | return false;
724 | }
725 |
726 | private function referenceContentsByAlias ($alias) {
727 | do {
728 | if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; }
729 | $groupPath = $this->SavedGroups[$alias];
730 | $value = $this->result;
731 | foreach ($groupPath as $k) {
732 | $value = $value[$k];
733 | }
734 | } while (false);
735 | return $value;
736 | }
737 |
738 | private function addArrayInline ($array, $indent) {
739 | $CommonGroupPath = $this->path;
740 | if (empty ($array)) return false;
741 |
742 | foreach ($array as $k => $_) {
743 | $this->addArray(array($k => $_), $indent);
744 | $this->path = $CommonGroupPath;
745 | }
746 | return true;
747 | }
748 |
749 | private function addArray ($incoming_data, $incoming_indent) {
750 |
751 | // print_r ($incoming_data);
752 |
753 | if (count ($incoming_data) > 1)
754 | return $this->addArrayInline ($incoming_data, $incoming_indent);
755 |
756 | $key = key ($incoming_data);
757 | $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null;
758 | if ($key === '__!YAMLZero') $key = '0';
759 |
760 | if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values.
761 | if ($key || $key === '' || $key === '0') {
762 | $this->result[$key] = $value;
763 | } else {
764 | $this->result[] = $value; end ($this->result); $key = key ($this->result);
765 | }
766 | $this->path[$incoming_indent] = $key;
767 | return;
768 | }
769 |
770 |
771 |
772 | $history = array();
773 | // Unfolding inner array tree.
774 | $history[] = $_arr = $this->result;
775 | foreach ($this->path as $k) {
776 | $history[] = $_arr = $_arr[$k];
777 | }
778 |
779 | if ($this->_containsGroupAlias) {
780 | $value = $this->referenceContentsByAlias($this->_containsGroupAlias);
781 | $this->_containsGroupAlias = false;
782 | }
783 |
784 |
785 | // Adding string or numeric key to the innermost level or $this->arr.
786 | if (is_string($key) && $key == '<<') {
787 | if (!is_array ($_arr)) { $_arr = array (); }
788 |
789 | $_arr = array_merge ($_arr, $value);
790 | } else if ($key || $key === '' || $key === '0') {
791 | if (!is_array ($_arr))
792 | $_arr = array ($key=>$value);
793 | else
794 | $_arr[$key] = $value;
795 | } else {
796 | if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; }
797 | else { $_arr[] = $value; end ($_arr); $key = key ($_arr); }
798 | }
799 |
800 | $reverse_path = array_reverse($this->path);
801 | $reverse_history = array_reverse ($history);
802 | $reverse_history[0] = $_arr;
803 | $cnt = count($reverse_history) - 1;
804 | for ($i = 0; $i < $cnt; $i++) {
805 | $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i];
806 | }
807 | $this->result = $reverse_history[$cnt];
808 |
809 | $this->path[$incoming_indent] = $key;
810 |
811 | if ($this->_containsGroupAnchor) {
812 | $this->SavedGroups[$this->_containsGroupAnchor] = $this->path;
813 | if (is_array ($value)) {
814 | $k = key ($value);
815 | if (!is_int ($k)) {
816 | $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k;
817 | }
818 | }
819 | $this->_containsGroupAnchor = false;
820 | }
821 |
822 | }
823 |
824 | private static function startsLiteralBlock ($line) {
825 | $lastChar = substr (trim($line), -1);
826 | if ($lastChar != '>' && $lastChar != '|') return false;
827 | if ($lastChar == '|') return $lastChar;
828 | // HTML tags should not be counted as literal blocks.
829 | if (preg_match ('#<.*?>$#', $line)) return false;
830 | return $lastChar;
831 | }
832 |
833 | private static function greedilyNeedNextLine($line) {
834 | $line = trim ($line);
835 | if (!strlen($line)) return false;
836 | if (substr ($line, -1, 1) == ']') return false;
837 | if ($line[0] == '[') return true;
838 | if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true;
839 | return false;
840 | }
841 |
842 | private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) {
843 | $line = self::stripIndent($line, $indent);
844 | if ($literalBlockStyle !== '|') {
845 | $line = self::stripIndent($line);
846 | }
847 | $line = rtrim ($line, "\r\n\t ") . "\n";
848 | if ($literalBlockStyle == '|') {
849 | return $literalBlock . $line;
850 | }
851 | if (strlen($line) == 0)
852 | return rtrim($literalBlock, ' ') . "\n";
853 | if ($line == "\n" && $literalBlockStyle == '>') {
854 | return rtrim ($literalBlock, " \t") . "\n";
855 | }
856 | if ($line != "\n")
857 | $line = trim ($line, "\r\n ") . " ";
858 | return $literalBlock . $line;
859 | }
860 |
861 | function revertLiteralPlaceHolder ($lineArray, $literalBlock) {
862 | foreach ($lineArray as $k => $_) {
863 | if (is_array($_))
864 | $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock);
865 | else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder)
866 | $lineArray[$k] = rtrim ($literalBlock, " \r\n");
867 | }
868 | return $lineArray;
869 | }
870 |
871 | private static function stripIndent ($line, $indent = -1) {
872 | if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line));
873 | return substr ($line, $indent);
874 | }
875 |
876 | private function getParentPathByIndent ($indent) {
877 | if ($indent == 0) return array();
878 | $linePath = $this->path;
879 | do {
880 | end($linePath); $lastIndentInParentPath = key($linePath);
881 | if ($indent <= $lastIndentInParentPath) array_pop ($linePath);
882 | } while ($indent <= $lastIndentInParentPath);
883 | return $linePath;
884 | }
885 |
886 |
887 | private function clearBiggerPathValues ($indent) {
888 |
889 |
890 | if ($indent == 0) $this->path = array();
891 | if (empty ($this->path)) return true;
892 |
893 | foreach ($this->path as $k => $_) {
894 | if ($k > $indent) unset ($this->path[$k]);
895 | }
896 |
897 | return true;
898 | }
899 |
900 |
901 | private static function isComment ($line) {
902 | if (!$line) return false;
903 | if ($line[0] == '#') return true;
904 | if (trim($line, " \r\n\t") == '---') return true;
905 | return false;
906 | }
907 |
908 | private static function isEmpty ($line) {
909 | return (trim ($line) === '');
910 | }
911 |
912 |
913 | private function isArrayElement ($line) {
914 | if (!$line) return false;
915 | if ($line[0] != '-') return false;
916 | if (strlen ($line) > 3)
917 | if (substr($line,0,3) == '---') return false;
918 |
919 | return true;
920 | }
921 |
922 | private function isHashElement ($line) {
923 | return strpos($line, ':');
924 | }
925 |
926 | private function isLiteral ($line) {
927 | if ($this->isArrayElement($line)) return false;
928 | if ($this->isHashElement($line)) return false;
929 | return true;
930 | }
931 |
932 |
933 | private static function unquote ($value) {
934 | if (!$value) return $value;
935 | if (!is_string($value)) return $value;
936 | if ($value[0] == '\'') return trim ($value, '\'');
937 | if ($value[0] == '"') return trim ($value, '"');
938 | return $value;
939 | }
940 |
941 | private function startsMappedSequence ($line) {
942 | return ($line[0] == '-' && substr ($line, -1, 1) == ':');
943 | }
944 |
945 | private function returnMappedSequence ($line) {
946 | $array = array();
947 | $key = self::unquote(trim(substr($line,1,-1)));
948 | $array[$key] = array();
949 | $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key);
950 | return array($array);
951 | }
952 |
953 | private function returnMappedValue ($line) {
954 | $array = array();
955 | $key = self::unquote (trim(substr($line,0,-1)));
956 | $array[$key] = '';
957 | return $array;
958 | }
959 |
960 | private function startsMappedValue ($line) {
961 | return (substr ($line, -1, 1) == ':');
962 | }
963 |
964 | private function isPlainArray ($line) {
965 | return ($line[0] == '[' && substr ($line, -1, 1) == ']');
966 | }
967 |
968 | private function returnPlainArray ($line) {
969 | return $this->_toType($line);
970 | }
971 |
972 | private function returnKeyValuePair ($line) {
973 | $array = array();
974 | $key = '';
975 | if (strpos ($line, ':')) {
976 | // It's a key/value pair most likely
977 | // If the key is in double quotes pull it out
978 | if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
979 | $value = trim(str_replace($matches[1],'',$line));
980 | $key = $matches[2];
981 | } else {
982 | // Do some guesswork as to the key and the value
983 | $explode = explode(':',$line);
984 | $key = trim($explode[0]);
985 | array_shift($explode);
986 | $value = trim(implode(':',$explode));
987 | }
988 | // Set the type of the value. Int, string, etc
989 | $value = $this->_toType($value);
990 | if ($key === '0') $key = '__!YAMLZero';
991 | $array[$key] = $value;
992 | } else {
993 | $array = array ($line);
994 | }
995 | return $array;
996 |
997 | }
998 |
999 |
1000 | private function returnArrayElement ($line) {
1001 | if (strlen($line) <= 1) return array(array()); // Weird %)
1002 | $array = array();
1003 | $value = trim(substr($line,1));
1004 | $value = $this->_toType($value);
1005 | $array[] = $value;
1006 | return $array;
1007 | }
1008 |
1009 |
1010 | private function nodeContainsGroup ($line) {
1011 | $symbolsForReference = 'A-z0-9_\-';
1012 | if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
1013 | if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
1014 | if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
1015 | if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1];
1016 | if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1];
1017 | if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1];
1018 | return false;
1019 |
1020 | }
1021 |
1022 | private function addGroup ($line, $group) {
1023 | if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1);
1024 | if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1);
1025 | //print_r ($this->path);
1026 | }
1027 |
1028 | private function stripGroup ($line, $group) {
1029 | $line = trim(str_replace($group, '', $line));
1030 | return $line;
1031 | }
1032 | }
1033 |
1034 | // Enable use of Spyc from command line
1035 | // The syntax is the following: php spyc.php spyc.yaml
1036 |
1037 | define ('SPYC_FROM_COMMAND_LINE', false);
1038 |
1039 | do {
1040 | if (!SPYC_FROM_COMMAND_LINE) break;
1041 | if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break;
1042 | if (empty ($_SERVER['PHP_SELF']) || $_SERVER['PHP_SELF'] != 'spyc.php') break;
1043 | $file = $argv[1];
1044 | printf ("Spyc loading file: %s\n", $file);
1045 | print_r (spyc_load_file ($file));
1046 | } while (0);
--------------------------------------------------------------------------------
/models/Admin.php:
--------------------------------------------------------------------------------
1 |