aboutsummaryrefslogtreecommitdiff
path: root/endpoints/rest.php
blob: 6f9efc1e8d3952638f33640a8f4f540e920591fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<?php
	/**
	 * Rest endpoint.
	 * The API REST endpoint.
	 * 
	 * @package Elgg
	 * @subpackage API
	 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
	 * @author Marcus Povey <marcus@dushka.co.uk>
	 * @copyright Curverider Ltd 2008
	 * @link http://elgg.org/
	 */

	
	
	
	
	/*

	 Elgg API system
A brief specification: internal only

NB: this is a loose specification, and as such some holes or shortcomings may become evident in
implementation.  Therefore, feel free to adjust as necessary, bearing in mind the goals, which 
are unmovable ...

Goals:  an extensible, two-way API that can be used to easily code secure client applications 
on a variety of networked systems, whether web or application-based.  The results should be available, 
at the very least, in JSON, serialised PHP, XML and CSV, but the output formats should also be 
extensible by plugins in a documented way.  Similarly, plugins must be able to add new function calls, 
in a similar way to how they register events or enable actions.






On release, we will need to provide simple client libraries for PHP, .NET, C, Java and (although this 
can hopefully be outsourced to Kevin or similar) Ruby on Rails.  Additionally, Django, vanilla Python 
and Perl libraries would be a bonus, although not required.

Brief implementation requirements:   A set of procedural functions.  If possible, the output should 
use the existing views system, creating a new base view set for xml, json, csv and php.  That way other 
output formats can be specified simply by changing the &view URL parameter, and added / extended by plugins.  
(It would also allow RSS output pretty much for free for certain types of data.)  On failure, a friendly 
message should be returned in a way that can be read by the client software.

These functions should be made available in a simple api.php module within engine/lib.php, without the use of
any external libraries.  If an external library really must be used, ensure that it has a compatible license 
and can be used on all systems where Elgg can be installed, including Apache for Windows and Apache-compatible 
web servers.

When a plugin or core software module registers an API call, it should reference a function name, the 
parameters it requires, and an English description of the call.  A special API call – and internal function - 
should return a list of enabled calls, for the use of client applications and internal help pages respectively.

As one application of the API is as a back-end for AJAX applications, the API endpoint should check $_SESSION 
for logged in user information before checking for any other kind of login data.  This way the browser can 
simply make an asynchronous callback request, allowing for many very interesting Javascript applications.
In an ideal world, client applications should not need a special API key.  This is because an application would 
have to install a new key for each installed Elgg site, which is not preferable, as it has a serious user 
experience hit (before the user can use a new client software on a particular install, they have to go to 
their account settings and obtain something that to them looks like a string of gobbledygook).  If possible, 
all the client application should need is a valid username and password.

Using a $CONFIG configuration option, site admins should be able to shut down the entire API system if 
required, or disallow the $_SESSION authentication method.

	 */
	
	
	// Include required files
	require_once('../engine/start.php');
	global $CONFIG;

	// Register the error handler
	error_reporting(E_ALL); 
	set_error_handler('__php_api_error_handler');
	
	// Register a default exception handler
	set_exception_handler('__php_api_exception_handler'); 
	
	// Check to see if the api is available
	if ((isset($CONFIG->disable_api)) && ($CONFIG->disable_api == true))
		throw new ConfigurationException("Sorry, API access has been disabled by the administrator.");
	
	
	
	
	// Get parameter variables
	$format = get_input('format', 'php');
	$method = get_input('method');
	$result = null;
	
	// See if we have a session
	/**
	 * If we have a session then we can assume that this is being called by AJAX from 
	 * within an already logged on browser.
	 * 
	 * NB. This may be a gaping security hole, but hey ho. 
	 */
	if (!isloggedin())
	{
		//$CONFIG->api_header = get_and_validate_api_headers(); // Get api header
		//$CONFIG->api_user = get_api_user($CONFIG->api_header->api_key); // Pull API user details
	
	
		
		
		
		
		
		
		
		
	
	}
	else
	{
		// User is logged in, just execute 
		
		
		
		
	}
	
	// Finally output
	if (!($result instanceof GenericResult))
		throw new APIException("API Result is of an unknown type, this should never happen.");

	// Output the result
	echo output_result($result, $format);

	
	
	
	
	
	
	
	
	
	
	

	
	
	
	
	
	
	
	
	
	
	// See if we have a session
	/**
	 * If we have a session then we can assume that this is being called by AJAX from 
	 * within an already logged on browser.
	 * 
	 * NB. This may be a gaping security hole, but hey ho. 
	 */
//	if (!isloggedin())
//	{
/*		// Get api header
		$api_header = get_and_validate_api_headers();
		$ApiEnvironment->api_header = $api_header;
		
		// Pull API user details
		$ApiEnvironment->api_user = get_api_user($api_header->api_key);
		
		// Get site
		$ApiEnvironment->site_id = $ApiEnvironment->api_user->side_id;	
		
		if ($ApiEnvironment->api_user)
		{
			// Get the secret key
			$secret_key = $ApiEnvironment->api_user->secret;
				
			// Validate HMAC
			$hmac = calculate_hmac($api_header->hmac_algo, 
					$api_header->time, 
					$api_header->api_key, 
					$secret_key, 
					$api_header->get_variables, 
					$api_header->method == 'POST' ? $api_header->posthash : "");
				
			if (strcmp(
				$api_header->hmac,
				$hmac	
			)==0)
			{
				// Now make sure this is not a replay
				if (!cache_hmac_check_replay($hmac)) 
				{
					$postdata = "";
					$token = "";
					$params = $_REQUEST;
					
					// Validate post data
					if ($api_header->method=="POST")
					{
						$postdata = get_post_data();
						$calculated_posthash = calculate_posthash($postdata, $api_header->posthash_algo);

						if (strcmp($api_header->posthash, $calculated_posthash)!=0)
							throw new SecurityException("POST data hash is invalid - Expected $calculated_posthash but got {$api_header->posthash}.");
					}
					
					// Execute 
					if (isset($params['auth_token'])) 
					$result = execute_method($method, $params, $token);
				}
				else
					throw new SecurityException("Packet signature already seen.");
			}
			else 
				throw new SecurityException("HMAC is invalid.  {$api_header->hmac} != [calc]$hmac = {$api_header->hmac_algo}(**SECRET KEY**, time:{$api_header->time}, apikey:{$api_header->api_key}, get_vars:{$api_header->get_variables}" . ($api_header->method=="POST"? "posthash:$api_header->posthash}" : ")"));
		}
		else
			throw new SecurityException("Invalid or missing API Key.",ErrorResult::$RESULT_FAIL_APIKEY_INVALID);
	}*/
//	else
//	{
//		// Set site environment
//		$ApiEnvironment->site_id = $CONFIG->site_id;
//		
//		// User is logged in, just execute 
//		if (isset($params['auth_token'])) $token = $params['auth_token'];
//		$result = execute_method($method, $params, $token);	
//	}


	
		
?>