Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Configurable Reports
19
 * A Moodle block for creating customizable reports
20
 * @package blocks
21
 * @author: Juan leyva <http://www.twitter.com/jleyvadelgado>
22
 * @date: 2009
23
 */
24
 
25
// Based on Custom SQL Reports Plugin
26
// See http://moodle.org/mod/data/view.php?d=13&rid=2884.
27
 
28
if (!defined('MOODLE_INTERNAL')) {
29
    //  It must be included from a Moodle page.
30
    die('Direct access to this script is forbidden.');
31
}
32
 
33
require_once($CFG->libdir.'/formslib.php');
34
 
35
class customsql_form extends moodleform {
36
 
37
    public function definition() {
38
        global $DB, $CFG, $COURSE;
39
 
40
        $mform =& $this->_form;
41
 
42
        $mform->addElement('textarea', 'querysql', get_string('querysql', 'block_configurable_reports'), 'rows="35" cols="80"');
43
        $mform->addRule('querysql', get_string('required'), 'required', null, 'client');
44
        $mform->setType('querysql', PARAM_RAW);
45
 
46
        $mform->addElement('hidden', 'courseid', $COURSE->id);
47
        $mform->setType('courseid', PARAM_INT);
48
 
49
        $this->add_action_buttons();
50
 
51
        $mform->addElement('static', 'note', '', get_string('listofsqlreports', 'block_configurable_reports'));
52
 
53
        if ($userandrepo = get_config('block_configurable_reports', 'sharedsqlrepository')) {
54
 
55
            $github = new \block_configurable_reports\github;
56
            $github->set_repo($userandrepo);
57
            $res = $github->get('/contents');
58
            $res = json_decode($res);
59
 
60
            if (is_array($res)) {
61
                $reportcategories = array(get_string('choose'));
62
                foreach ($res as $item) {
63
                    if ($item->type == 'dir') {
64
                        $reportcategories[$item->path] = $item->path;
65
                    }
66
                }
67
 
68
                $reportcatstr = get_string('reportcategories', 'block_configurable_reports');
69
                $reportcatattrs = ['onchange' => 'M.block_configurable_reports.onchange_reportcategories(this,"'.sesskey().'")'];
70
                $mform->addElement('select', 'reportcategories', $reportcatstr, $reportcategories, $reportcatattrs);
71
 
72
                $reportsincatstr = get_string('reportsincategory', 'block_configurable_reports');
73
                $reportsincatattrs = ['onchange' => 'M.block_configurable_reports.onchange_reportsincategory(this,"'.sesskey().'")'];
74
                $mform->addElement('select', 'reportsincategory', $reportsincatstr, $reportcategories, $reportsincatattrs);
75
 
76
                $mform->addElement('textarea', 'remotequerysql', get_string('remotequerysql', 'block_configurable_reports'),
77
                    'rows="15" cols="90"');
78
            }
79
        }
80
    }
81
 
82
    public function validation($data, $files) {
83
        if (get_config('block_configurable_reports', 'sqlsecurity')) {
84
            return $this->validation_high_security($data, $files);
85
        } else {
86
            return $this->validation_low_security($data, $files);
87
        }
88
    }
89
 
90
    public function validation_high_security($data, $files) {
91
        global $DB, $CFG, $db, $USER;
92
 
93
        $errors = parent::validation($data, $files);
94
 
95
        $sql = $data['querysql'];
96
        $sql = trim($sql);
97
 
98
        // Simple test to avoid evil stuff in the SQL.
99
        $regex = '/\b(ALTER|CREATE|DELETE|DROP|GRANT|INSERT|INTO|TRUNCATE|UPDATE|SET|VACUUM|REINDEX|DISCARD|LOCK)\b/i';
100
        if (preg_match($regex, $sql)) {
101
            $errors['querysql'] = get_string('notallowedwords', 'block_configurable_reports');
102
 
103
        } else if (strpos($sql, ';') !== false) {
104
            // Do not allow any semicolons.
105
            $errors['querysql'] = get_string('nosemicolon', 'report_customsql');
106
 
107
        } else if ($CFG->prefix != '' && preg_match('/\b' . $CFG->prefix . '\w+/i', $sql)) {
108
            // Make sure prefix is prefix_, not explicit.
109
            $errors['querysql'] = get_string('noexplicitprefix', 'block_configurable_reports');
110
 
111
        } else {
112
            // Now try running the SQL, and ensure it runs without errors.
113
 
114
            $sql = $this->_customdata['reportclass']->prepare_sql($sql);
115
            $rs = null;
116
            try {
117
                $rs = $this->_customdata['reportclass']->execute_query($sql, 2);
118
            } catch (dml_read_exception $e) {
119
                $errors['querysql'] = get_string('queryfailed', 'block_configurable_reports', $e->error );
120
            }
121
            if ($rs && !empty($data['singlerow'])) {
122
                if (rs_EOF($rs)) {
123
                    $errors['querysql'] = get_string('norowsreturned', 'block_configurable_reports');
124
                }
125
            }
126
 
127
            if ($rs) {
128
                $rs->close();
129
            }
130
        }
131
 
132
        return $errors;
133
    }
134
 
135
    public function validation_low_security($data, $files) {
136
        global $DB, $CFG, $db, $USER;
137
 
138
        $errors = parent::validation($data, $files);
139
 
140
        $sql = $data['querysql'];
141
        $sql = trim($sql);
142
 
143
        if (preg_match('/\b(ALTER|DELETE|DROP|GRANT|TRUNCATE|UPDATE|SET|VACUUM|REINDEX|DISCARD|LOCK)\b/i', $sql)) {
144
            // Only allow INSERT|INTO|CREATE in low security.
145
            $errors['querysql'] = get_string('notallowedwords', 'block_configurable_reports');
146
 
147
        } else if (preg_match('/\b(INSERT|INTO|CREATE)\b/i', $sql) && empty($CFG->block_configurable_reports_enable_sql_execution)) {
148
            // Only allow INSERT|INTO|CREATE in low security when SQL execution is enabled in the server.
149
            $errors['querysql'] = get_string('notallowedwords', 'block_configurable_reports');
150
        } else {
151
            // Now try running the SQL, and ensure it runs without errors.
152
            $sql = $this->_customdata['reportclass']->prepare_sql($sql);
153
            $rs = $this->_customdata['reportclass']->execute_query($sql, 2);
154
            if (!$rs) {
155
                $errors['querysql'] = get_string('queryfailed', 'block_configurable_reports', $db->ErrorMsg());
156
            } else if (!empty($data['singlerow'])) {
157
                if (rs_EOF($rs)) {
158
                    $errors['querysql'] = get_string('norowsreturned', 'block_configurable_reports');
159
                }
160
            }
161
 
162
            if ($rs) {
163
                $rs->close();
164
            }
165
        }
166
 
167
        return $errors;
168
    }
169
}