cwresdev 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cwresdev",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -13,6 +13,7 @@
13
13
  "bin",
14
14
  "src",
15
15
  "vendor/php/windows",
16
+ "stubs",
16
17
  "README.md",
17
18
  "LICENSE",
18
19
  "THIRD_PARTY_NOTICES.md"
@@ -0,0 +1,146 @@
1
+ <?php
2
+ /**
3
+ * Mock OAuth library for local development (cwrespro).
4
+ * Stubs out OAuth classes used by LTI so courses run without Canvas.
5
+ * All classes guarded with class_exists() to avoid redeclaration errors.
6
+ */
7
+
8
+ // Inject LTI launch params so is_lti_request() returns true and BLTI validates
9
+ if (empty($_REQUEST['lti_message_type'])) {
10
+ $ltiParams = array(
11
+ 'lti_message_type' => 'basic-lti-launch-request',
12
+ 'lti_version' => 'LTI-1p0',
13
+ 'resource_link_id' => 'dev_resource_001',
14
+ 'oauth_consumer_key' => 'dev_consumer_key',
15
+ 'user_id' => 'dev_user_001',
16
+ 'lis_person_name_given' => 'Dev',
17
+ 'lis_person_name_family' => 'User',
18
+ 'lis_person_name_full' => 'Dev User',
19
+ 'lis_person_contact_email_primary' => 'dev@localhost',
20
+ 'lis_result_sourcedid' => '',
21
+ 'lis_outcome_service_url' => '',
22
+ 'roles' => 'Instructor',
23
+ 'context_id' => 'dev_context_001',
24
+ 'context_title' => 'Local Development',
25
+ );
26
+ foreach ($ltiParams as $k => $v) {
27
+ if (!isset($_REQUEST[$k])) $_REQUEST[$k] = $v;
28
+ if (!isset($_POST[$k])) $_POST[$k] = $v;
29
+ }
30
+ }
31
+
32
+ if (!class_exists('OAuthException')) {
33
+ class OAuthException extends Exception {}
34
+ }
35
+
36
+ if (!class_exists('OAuthConsumer')) {
37
+ class OAuthConsumer {
38
+ public $key;
39
+ public $secret;
40
+ public $callback_url;
41
+
42
+ function __construct($key, $secret, $callback_url = NULL) {
43
+ $this->key = $key;
44
+ $this->secret = $secret;
45
+ $this->callback_url = $callback_url;
46
+ }
47
+ }
48
+ }
49
+
50
+ if (!class_exists('OAuthToken')) {
51
+ class OAuthToken {
52
+ public $key;
53
+ public $secret;
54
+
55
+ function __construct($key, $secret) {
56
+ $this->key = $key;
57
+ $this->secret = $secret;
58
+ }
59
+ }
60
+ }
61
+
62
+ if (!class_exists('OAuthSignatureMethod')) {
63
+ class OAuthSignatureMethod {
64
+ public function check_signature($request, $consumer, $token, $signature) {
65
+ return true;
66
+ }
67
+ }
68
+ }
69
+
70
+ if (!class_exists('OAuthSignatureMethod_HMAC_SHA1')) {
71
+ class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {
72
+ function get_name() {
73
+ return "HMAC-SHA1";
74
+ }
75
+
76
+ public function check_signature($request, $consumer, $token, $signature) {
77
+ return true;
78
+ }
79
+
80
+ public function build_signature($request, $consumer, $token) {
81
+ return "mock_signature";
82
+ }
83
+ }
84
+ }
85
+
86
+ if (!class_exists('OAuthRequest')) {
87
+ class OAuthRequest {
88
+ private $parameters;
89
+ private $http_method;
90
+ private $http_url;
91
+
92
+ function __construct($http_method, $http_url, $parameters = NULL) {
93
+ $this->parameters = $parameters ?? array();
94
+ $this->http_method = $http_method;
95
+ $this->http_url = $http_url;
96
+ }
97
+
98
+ public static function from_request($http_method = NULL, $http_url = NULL, $parameters = NULL) {
99
+ $http_method = $http_method ?? $_SERVER['REQUEST_METHOD'];
100
+ $http_url = $http_url ?? ('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
101
+ $params = $parameters ?? array_merge($_GET, $_POST);
102
+ return new OAuthRequest($http_method, $http_url, $params);
103
+ }
104
+
105
+ public function get_parameter($name) {
106
+ return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
107
+ }
108
+
109
+ public function get_parameters() {
110
+ return $this->parameters;
111
+ }
112
+
113
+ public function get_signature_base_string() {
114
+ return "mock_base_string";
115
+ }
116
+ }
117
+ }
118
+
119
+ if (!class_exists('OAuthServer')) {
120
+ class OAuthServer {
121
+ private $data_store;
122
+ private $signature_methods = array();
123
+
124
+ function __construct($data_store) {
125
+ $this->data_store = $data_store;
126
+ }
127
+
128
+ public function add_signature_method($signature_method) {
129
+ $this->signature_methods[$signature_method->get_name()] = $signature_method;
130
+ }
131
+
132
+ public function verify_request($request) {
133
+ return true;
134
+ }
135
+ }
136
+ }
137
+
138
+ if (!class_exists('OAuthDataStore')) {
139
+ class OAuthDataStore {
140
+ function lookup_consumer($consumer_key) { return NULL; }
141
+ function lookup_token($consumer, $token_type, $token) { return NULL; }
142
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) { return NULL; }
143
+ function new_request_token($consumer) { return NULL; }
144
+ function new_access_token($token, $consumer) { return NULL; }
145
+ }
146
+ }
@@ -0,0 +1,67 @@
1
+ <?php
2
+ /**
3
+ * cwrespro dev prepend: mocks LTI context for local development.
4
+ * Auto-prepended via PHP -d auto_prepend_file.
5
+ * No source files under virtual_env are modified.
6
+ */
7
+
8
+ // Polyfill functions removed in PHP 8.0+ that legacy courses still use
9
+ if (!function_exists('get_magic_quotes_gpc')) {
10
+ function get_magic_quotes_gpc() { return false; }
11
+ }
12
+ if (!function_exists('get_magic_quotes_runtime')) {
13
+ function get_magic_quotes_runtime() { return false; }
14
+ }
15
+
16
+ // Add stubs directory to include_path so OAuth.php is found by lti_util.php
17
+ $stubsDir = __DIR__;
18
+ set_include_path(get_include_path() . PATH_SEPARATOR . $stubsDir);
19
+
20
+ // Start session, seed LTI vars, then close so the course can call session_start() without notice
21
+ if (session_status() === PHP_SESSION_NONE) {
22
+ session_start();
23
+ }
24
+
25
+ // Mock LTI session context if not already set (simulates a valid LTI launch)
26
+ if (!isset($_SESSION['_lti_context'])) {
27
+ $_SESSION['_lti_context'] = array(
28
+ 'lis_person_name_given' => 'Dev',
29
+ 'lis_person_name_family' => 'User',
30
+ 'lis_person_name_full' => 'Dev User',
31
+ 'lis_person_contact_email_primary' => 'dev@localhost',
32
+ 'user_id' => 'dev_user_001',
33
+ 'roles' => 'Instructor',
34
+ 'resource_link_id' => 'dev_resource_001',
35
+ 'context_id' => 'dev_context_001',
36
+ 'context_title' => 'Local Development',
37
+ 'oauth_consumer_key' => 'dev_consumer_key',
38
+ );
39
+ $_SESSION['_lti_row'] = null;
40
+ $_SESSION['_lti_context_id'] = 'dev_context_001';
41
+ }
42
+
43
+ // Close session so course code can call session_start() without "already active" notice
44
+ session_write_close();
45
+
46
+ // Fake LTI launch request params for courses that check $_REQUEST directly
47
+ // (e.g. BLTI constructor with $usesession=false)
48
+ if (empty($_REQUEST['lti_message_type'])) {
49
+ $ltiParams = array(
50
+ 'lti_message_type' => 'basic-lti-launch-request',
51
+ 'lti_version' => 'LTI-1p0',
52
+ 'resource_link_id' => 'dev_resource_001',
53
+ 'oauth_consumer_key' => 'dev_consumer_key',
54
+ 'user_id' => 'dev_user_001',
55
+ 'lis_person_name_given' => 'Dev',
56
+ 'lis_person_name_family' => 'User',
57
+ 'lis_person_name_full' => 'Dev User',
58
+ 'lis_person_contact_email_primary' => 'dev@localhost',
59
+ 'roles' => 'Instructor',
60
+ 'context_id' => 'dev_context_001',
61
+ 'context_title' => 'Local Development',
62
+ );
63
+ foreach ($ltiParams as $k => $v) {
64
+ $_REQUEST[$k] = $v;
65
+ $_POST[$k] = $v;
66
+ }
67
+ }
@@ -0,0 +1,61 @@
1
+ <?php
2
+ /**
3
+ * cwrespro PHP router script.
4
+ * Runs before every request on PHP's built-in server.
5
+ * For PHP files: injects LTI mocks then includes the file in the same context.
6
+ * For static files: returns false to let PHP serve them normally.
7
+ */
8
+
9
+ $requestUri = $_SERVER['REQUEST_URI'];
10
+ $path = parse_url($requestUri, PHP_URL_PATH);
11
+ $docRoot = $_SERVER['DOCUMENT_ROOT'];
12
+ $file = realpath($docRoot . $path);
13
+
14
+ // Security: ensure file is within doc root
15
+ if ($file && strpos($file, realpath($docRoot)) !== 0) {
16
+ http_response_code(403);
17
+ echo "Forbidden";
18
+ return true;
19
+ }
20
+
21
+ // For non-PHP files (CSS, JS, images, etc.) let the built-in server handle them
22
+ if (!$file || !preg_match('/\.php$/i', $file)) {
23
+ return false;
24
+ }
25
+
26
+ // --- PHP file: set up dev environment then include it ---
27
+
28
+ // Add stubs directory to include_path so OAuth.php mock is found
29
+ $stubsDir = __DIR__;
30
+ set_include_path(get_include_path() . PATH_SEPARATOR . $stubsDir);
31
+
32
+ // Inject LTI launch params so is_lti_request() returns true and BLTI validates
33
+ if (empty($_REQUEST['lti_message_type'])) {
34
+ $ltiParams = array(
35
+ 'lti_message_type' => 'basic-lti-launch-request',
36
+ 'lti_version' => 'LTI-1p0',
37
+ 'resource_link_id' => 'dev_resource_001',
38
+ 'oauth_consumer_key' => 'dev_consumer_key',
39
+ 'user_id' => 'dev_user_001',
40
+ 'lis_person_name_given' => 'Dev',
41
+ 'lis_person_name_family' => 'User',
42
+ 'lis_person_name_full' => 'Dev User',
43
+ 'lis_person_contact_email_primary' => 'dev@localhost',
44
+ 'lis_result_sourcedid' => '',
45
+ 'lis_outcome_service_url' => '',
46
+ 'roles' => 'Instructor',
47
+ 'context_id' => 'dev_context_001',
48
+ 'context_title' => 'Local Development',
49
+ );
50
+ foreach ($ltiParams as $k => $v) {
51
+ if (!isset($_REQUEST[$k])) $_REQUEST[$k] = $v;
52
+ if (!isset($_POST[$k])) $_POST[$k] = $v;
53
+ }
54
+ }
55
+
56
+ // Change to the directory of the requested file so relative paths work
57
+ chdir(dirname($file));
58
+
59
+ // Include the PHP file in this context (where $_REQUEST is modified)
60
+ include $file;
61
+ return true;