Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

main/exercise/hotpotatoes.lib.php (1 issue)

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Code library for HotPotatoes integration.
6
 *
7
 * @package chamilo.exercise
8
 *
9
 * @author Istvan Mandak (original author)
10
 */
11
12
/* TODO: This is a global variable with too simple name, conflicts are possible.
13
Better eliminate it. Correct the test unit too. */
14
$dbTable = Database::get_course_table(TABLE_DOCUMENT);
15
16
/**
17
 * Creates a hotpotato directory.
18
 *
19
 * If a directory of that name already exists, don't create any.
20
 * If a file of that name exists, remove it and create a directory.
21
 *
22
 * @param string $base_work_dir Wanted path
23
 *
24
 * @return bool Always true so far
25
 */
26
function hotpotatoes_init($base_work_dir)
27
{
28
    //global $_course, $_user;
29
    $document_path = $base_work_dir.'/';
30
    if (!is_dir($document_path)) {
31
        if (is_file($document_path)) {
32
            @unlink($document_path);
33
        }
34
        @mkdir($document_path, api_get_permissions_for_new_directories());
35
36
        return true;
37
    } else {
38
        return false;
39
    }
40
    //why create a .htaccess here?
41
    //if (!is_file($document_path.".htacces"))
42
    //{
43
    //        if (!($fp = fopen($document_path.".htaccess", "w"))) {
44
    //    }
45
    //    $str = "order deny,allow\nallow from all";
46
    //    if (!fwrite($fp,$str)) { }
47
    //}
48
}
49
50
/**
51
 * Gets the title of the quiz file given as parameter.
52
 *
53
 * @param string $fname File name
54
 * @param string $fpath File path
55
 *
56
 * @return string The exercise title
57
 */
58
function GetQuizName($fname, $fpath)
59
{
60
    $title = GetComment($fname);
61
    if (trim($title) == '') {
62
        if (file_exists($fpath.$fname)) {
63
            if (!($fp = @fopen($fpath.$fname, 'r'))) {
64
                //die('Could not open Quiz input.');
65
                return basename($fname);
66
            }
67
68
            $contents = @fread($fp, filesize($fpath.$fname));
69
            @fclose($fp);
70
71
            $title = api_get_title_html($contents);
72
        }
73
    }
74
    if ($title == '') {
75
        $title = basename($fname);
76
    }
77
78
    return (string) $title;
79
}
80
81
/**
82
 * Gets the comment about a file from the corresponding database record.
83
 *
84
 * @param string $path       File path
85
 * @param string $courseCode (if not given, the course will be taken from the context)
86
 *
87
 * @return string comment from the database record
88
 *                Added conditional to the table if is empty
89
 */
90
function GetComment($path, $courseCode = '')
91
{
92
    $dbTable = Database::get_course_table(TABLE_DOCUMENT);
93
    $course_info = api_get_course_info($courseCode);
94
    $path = Database::escape_string($path);
95
    if (!empty($course_info) && !empty($path)) {
96
        $query = "SELECT comment FROM $dbTable WHERE c_id = {$course_info['real_id']}";
97
        $result = Database::query($query);
98
        while ($row = Database::fetch_array($result)) {
99
            return $row[0];
100
        }
101
    }
102
103
    return null;
104
}
105
106
/**
107
 * Sets the comment in the database for a particular path.
108
 *
109
 * @param string $path    File path
110
 * @param string $comment Comment to set
111
 *
112
 * @return Doctrine\DBAL\Driver\Statement|null
113
 *                                             Result of the database operation
114
 *                                             (Database::query will output some message directly on error anyway)
115
 */
116
function SetComment($path, $comment)
117
{
118
    $dbTable = Database::get_course_table(TABLE_DOCUMENT);
119
    $path = Database::escape_string($path);
120
    $comment = Database::escape_string($comment);
121
    $course_id = api_get_course_int_id();
122
    $query = "UPDATE $dbTable SET comment = '$comment'
123
              WHERE $course_id AND path = '$path'";
124
    $result = Database::query($query);
125
126
    return $result;
127
}
128
129
/**
130
 * Reads the file contents into a string.
131
 *
132
 * @param string $full_file_path Urlencoded path
133
 *
134
 * @return string The file contents or false on security error
135
 */
136
function ReadFileCont($full_file_path)
137
{
138
    if (empty($full_file_path)) {
139
        return false;
140
    }
141
    if (Security::check_abs_path(dirname($full_file_path).'/', api_get_path(SYS_COURSE_PATH))) {
142
        if (is_file($full_file_path)) {
143
            if (!($fp = fopen(urldecode($full_file_path), 'r'))) {
144
                return '';
145
            }
146
            $contents = fread($fp, filesize($full_file_path));
147
            fclose($fp);
148
149
            return $contents;
150
        }
151
    }
152
153
    return false;
154
}
155
156
/**
157
 * Writes the file contents into the given file path.
158
 *
159
 * @param string $full_file_path Urlencoded path
160
 * @param string $content        The file contents
161
 *
162
 * @return bool True on success, false on security error
163
 */
164
function WriteFileCont($full_file_path, $content)
165
{
166
    // Check if this is not an attack, trying to get into other directories or something like that.
167
    $_course = api_get_course_info();
168
    if (Security::check_abs_path(
169
        dirname($full_file_path).'/',
170
        api_get_path(SYS_COURSE_PATH).$_course['path'].'/'
171
    )) {
172
        // Check if this is not an attack, trying to upload a php file or something like that.
173
        if (basename($full_file_path) != Security::filter_filename(basename($full_file_path))) {
174
            return false;
175
        }
176
        //if (!($fp = fopen(urldecode($full_file_path), 'w'))) {
177
        //die('Could not open Quiz input.');
178
        //}
179
        $fp = fopen(urldecode($full_file_path), 'w');
180
        if ($fp !== false) {
181
            fwrite($fp, $content);
182
            fclose($fp);
183
184
            return true;
185
        }
186
    }
187
188
    return false;
189
}
190
191
/**
192
 * Gets the name of an img whose path is given (without directories or extensions).
193
 *
194
 * @param string $imageTag An image tag (<img src="...." ...>)
195
 *
196
 * @return string The image file name or an empty string
197
 */
198
function GetImgName($imageTag)
199
{
200
    // Select src tag from img tag.
201
    $match = [];
202
    //preg_match('/(src=(["\'])1.*(["\'])1)/i', $imageTag, $match);            //src
203
    preg_match('/src(\s)*=(\s)*[\'"]([^\'"]*)[\'"]/i', $imageTag, $match); //get the img src as contained between " or '
204
    //list($key, $srctag) = each($match);
205
    $src = $match[3];
206
    //$src = substr($srctag, 5, (strlen($srctag) - 7));
207
    if (stristr($src, 'http') === false) {
208
        // Valid or invalid image name.
209
        if ($src == '') {
210
            return '';
211
        } else {
212
            $tmp_src = basename($src);
213
            if ($tmp_src == '') {
214
                return $src;
215
            } else {
216
                return $tmp_src;
217
            }
218
        }
219
    } else {
220
        // The img tag contained "http", which means it is probably external. Ignore it.
221
        return '';
222
    }
223
}
224
225
/**
226
 * Gets the source path of an image tag.
227
 *
228
 * @param string $imageTag An image tag
229
 *
230
 * @return string The image source or ""
231
 */
232
function GetSrcName($imageTag)
233
{
234
    // Select src tag from img tag.
235
    $match = [];
236
    preg_match("|(src=\".*\" )|U", $imageTag, $match); //src
237
    $srctag = reset($match);
238
    $src = substr($srctag, 5, (strlen($srctag) - 7));
239
    if (stristr($src, 'http') === false) {
240
        // valid or invalid image name
241
        return $src;
242
    } else {
243
        return '';
244
    }
245
}
246
247
/**
248
 * Gets the image parameters from an image path.
249
 *
250
 * @param string $fname     File name
251
 * @param string $fpath     File path
252
 * @param array  $imgparams Reference to a list of image parameters (emptied, then used to return results)
253
 * @param int    $imgcount  Reference to a counter of images (emptied, then used to return results)
254
 */
255
function GetImgParams($fname, $fpath, &$imgparams, &$imgcount)
256
{
257
    // Select img tags from context.
258
    $imgparams = [];
259
    //phpinfo();
260
    $contents = ReadFileCont("$fpath"."$fname");
261
    $matches = [];
262
    preg_match_all('(<img .*>)', $contents, $matches);
263
    $imgcount = 0;
264
    foreach ($matches as $match) {
265
        // Each match consists of a key and a value.
266
        foreach ($match as $imageTag) {
267
            $imgname = GetImgName($imageTag);
268
            if ($imgname != '' && !in_array($imgname, $imgparams)) {
269
                array_push($imgparams, $imgname); // name (+ type) of the images in the html test
270
                $imgcount = $imgcount + 1; // number of images in the html test
271
            }
272
        }
273
    }
274
}
275
276
/**
277
 * Generates a list of hidden fields with the image params given as parameter to this function.
278
 *
279
 * @param array $imgparams List of image parameters
280
 *
281
 * @return string String containing the hidden parameters built from the list given
282
 */
283
function GenerateHiddenList($imgparams)
284
{
285
    $list = '';
286
    if (is_array($imgparams)) {
287
        foreach ($imgparams as $string) {
288
            $list .= "<input type=\"hidden\" name=\"imgparams[]\" value=\"$string\" />\n";
289
        }
290
    }
291
292
    return $list;
293
}
294
295
/**
296
 * Searches for a node in the given array.
297
 *
298
 * @param array  $array Reference to the array to search
299
 * @param string $node  Node we are looking for in the array
300
 *
301
 * @return mixed Node name or false if not found
302
 */
303
function myarraysearch(&$array, $node)
304
{
305
    $match = false;
306
    $tmp_array = [];
307
    for ($i = 0; $i < count($array); $i++) {
308
        if (!strcmp($array[$i], $node)) {
309
            $match = $node;
310
        } else {
311
            array_push($tmp_array, $array[$i]);
312
        }
313
    }
314
    $array = $tmp_array;
315
316
    return $match;
317
}
318
319
/**
320
 * Searches an image name into an array.
321
 *
322
 * @param array  $imgparams Reference to an array to search
323
 * @param string $string    String to look for
324
 *
325
 * @return mixed String given if found, false otherwise
326
 *
327
 * @uses     \myarraysearch    This function is just an additional layer on the myarraysearch() function
328
 */
329
function CheckImageName(&$imgparams, $string)
330
{
331
    $checked = myarraysearch($imgparams, $string);
332
333
    return $checked;
334
}
335
336
/**
337
 * Replaces an image tag by ???
338
 *
339
 * @param string $content The content to replace
340
 *
341
 * @return string The modified content
342
 */
343
function ReplaceImgTag($content)
344
{
345
    $newcontent = $content;
346
    $matches = [];
347
    preg_match_all('(<img .*>)', $content, $matches);
348
    foreach ($matches as $match) {
349
        foreach ($match as $imageTag) {
350
            $imgname = GetSrcName($imageTag);
351
            if ($imgname != '') {
352
                $prehref = $imgname;
353
                $posthref = basename($imgname);
354
                $newcontent = str_replace($prehref, $posthref, $newcontent);
355
            }
356
        }
357
    }
358
359
    return $newcontent;
360
}
361
362
/**
363
 * Fills the folder name up to a certain length with "0".
364
 *
365
 * @param string $name  Original folder name
366
 * @param int    $nsize Length to reach
367
 *
368
 * @return string Modified folder name
369
 */
370
function FillFolderName($name, $nsize)
371
{
372
    $str = '';
373
    for ($i = 0; $i < $nsize - strlen($name); $i++) {
374
        $str .= '0';
375
    }
376
    $str .= $name;
377
378
    return $str;
379
}
380
381
/**
382
 * Generates the HotPotato folder tree.
383
 *
384
 * @param string $folder Folder path
385
 *
386
 * @return string Folder name (modified)
387
 */
388
function GenerateHpFolder($folder)
389
{
390
    $filelist = [];
391
    if ($dir = @opendir($folder)) {
392
        while (($file = readdir($dir)) !== false) {
393
            if ($file != '.') {
394
                if ($file != '..') {
395
                    $full_name = $folder.'/'.$file;
396
                    if (is_dir($full_name)) {
397
                        $filelist[] = $file;
398
                    }
399
                }
400
            }
401
        }
402
    }
403
    $name = '';
404
    $w = true;
405
    while ($w == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
406
        $name = FillFolderName(mt_rand(1, 99999), 6);
407
        $checked = myarraysearch($filelist, $name);
408
        // As long as we find the name in the array, continue looping. As soon as we have a new element, quit.
409
        if (!$checked) {
410
            $w = false;
411
        }
412
    }
413
414
    return $name;
415
}
416
417
/**
418
 * Gets the folder name (strips down path).
419
 *
420
 * @param string $fname Path
421
 *
422
 * @return string Folder name stripped down
423
 */
424
function GetFolderName($fname)
425
{
426
    $name = explode('/', $fname);
427
    $name = $name[count($name) - 2];
428
429
    return $name;
430
}
431
432
/**
433
 * Gets the folder path (with out the name of the folder itself) ?
434
 *
435
 * @param string $fname Path
436
 *
437
 * @return string Path stripped down
438
 */
439
function GetFolderPath($fname)
440
{
441
    $str = '';
442
    $name = explode('/', $fname);
443
    for ($i = 0; $i < sizeof($name) - 1; $i++) {
444
        $str = $str.$name[$i].'/';
445
    }
446
447
    return $str;
448
}
449
450
/**
451
 * Checks if there are subfolders.
452
 *
453
 * @param string $path Path
454
 *
455
 * @return int 1 if a subfolder was found, 0 otherwise
456
 */
457
function CheckSubFolder($path)
458
{
459
    $folder = GetFolderPath($path);
460
    $dflag = 0;
461
    if ($dir = @opendir($folder)) {
462
        while (($file = readdir($dir)) !== false) {
463
            if ($file != '.') {
464
                if ($file != '..') {
465
                    $full_name = $folder.'/'.$file;
466
                    if (is_dir($full_name)) {
467
                        $dflag = 1; // first directory
468
                    }
469
                }
470
            }
471
        }
472
    }
473
474
    return $dflag;
475
}
476
477
/**
478
 * Hotpotato Garbage Collector.
479
 *
480
 * @param string $folder  Path
481
 * @param int    $flag    Flag
482
 * @param int    $user_id User id
483
 */
484
function HotPotGCt($folder, $flag, $user_id)
485
{
486
    // Garbage Collector
487
    $filelist = [];
488
    if ($dir = @opendir($folder)) {
489
        while (($file = readdir($dir)) !== false) {
490
            if ($file != '.') {
491
                if ($file != '..') {
492
                    $full_name = $folder.'/'.$file;
493
                    if (is_dir($full_name)) {
494
                        HotPotGCt($folder.'/'.$file, $flag, $user_id);
495
                    } else {
496
                        $filelist[] = $file;
497
                    }
498
                }
499
            }
500
        }
501
        closedir($dir);
502
    }
503
504
    foreach ($filelist as $val) {
505
        if (stristr($val, $user_id.'.t.html')) {
506
            if ($flag == 1) {
507
                my_delete($folder.'/'.$val);
508
            } else {
509
                echo $folder.'/'.$val.'<br />';
510
            }
511
        }
512
    }
513
}
514
515
/**
516
 * Deletes an attempt from TABLE_STATISTIC_TRACK_E_HOTPOTATOES.
517
 *
518
 * @param int $id
519
 */
520
function deleteAttempt($id)
521
{
522
    $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
523
    $id = intval($id);
524
    $sql = "DELETE FROM $table WHERE id = $id";
525
    Database::query($sql);
526
}
527