| 1 | ;; ***** BEGIN LICENSE BLOCK ***** |
|---|
| 2 | ;; Roadsend PHP Compiler Runtime Libraries |
|---|
| 3 | ;; Copyright (C) 2007 Roadsend, Inc. |
|---|
| 4 | ;; |
|---|
| 5 | ;; This program is free software; you can redistribute it and/or |
|---|
| 6 | ;; modify it under the terms of the GNU Lesser General Public License |
|---|
| 7 | ;; as published by the Free Software Foundation; either version 2.1 |
|---|
| 8 | ;; of the License, or (at your option) any later version. |
|---|
| 9 | ;; |
|---|
| 10 | ;; This program is distributed in the hope that it will be useful, |
|---|
| 11 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | ;; GNU Lesser General Public License for more details. |
|---|
| 14 | ;; |
|---|
| 15 | ;; You should have received a copy of the GNU Lesser General Public License |
|---|
| 16 | ;; along with this program; if not, write to the Free Software |
|---|
| 17 | ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|---|
| 18 | ;; ***** END LICENSE BLOCK ***** |
|---|
| 19 | (module php-ini |
|---|
| 20 | (import |
|---|
| 21 | (utils "utils.scm") |
|---|
| 22 | (php-runtime "php-runtime.scm") |
|---|
| 23 | (php-hash "php-hash.scm") |
|---|
| 24 | (php-errors "php-errors.scm")) |
|---|
| 25 | (export |
|---|
| 26 | (set-ini-entry name value) |
|---|
| 27 | (get-ini-entry name) |
|---|
| 28 | (default-ini-entry name value) |
|---|
| 29 | (config-ini-entry name value) |
|---|
| 30 | (reset-ini!) |
|---|
| 31 | (generate-config-ini-entries) |
|---|
| 32 | (ini-file-parse fname::bstring parse-sections?::bool))) |
|---|
| 33 | |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | ;;;;ini file |
|---|
| 37 | (define *ini-table* (make-hashtable)) |
|---|
| 38 | (define *default-ini-table* (make-hashtable)) |
|---|
| 39 | (define *config-ini-table* (make-hashtable)) |
|---|
| 40 | |
|---|
| 41 | (define (reset-ini!) |
|---|
| 42 | ;; reset ini settings to config file state |
|---|
| 43 | (unless (or (=fx (hashtable-size *ini-table*) 0) |
|---|
| 44 | (=fx (hashtable-size *ini-table*) (hashtable-size *config-ini-table*))) |
|---|
| 45 | (set! *ini-table* (make-hashtable)) |
|---|
| 46 | (hashtable-for-each *config-ini-table* |
|---|
| 47 | (lambda (k v) |
|---|
| 48 | (hashtable-put! *ini-table* k v))))) |
|---|
| 49 | |
|---|
| 50 | ; return current value, attemping a default if current doesn't exist |
|---|
| 51 | (define (get-ini-entry name) |
|---|
| 52 | (let ((ival (hashtable-get *ini-table* (mkstr name)))) |
|---|
| 53 | (debug-trace 9 (format "(runtime) getting ~a which is ~a" name ival)) |
|---|
| 54 | (if ival |
|---|
| 55 | ival |
|---|
| 56 | (hashtable-get *default-ini-table* (mkstr name))))) |
|---|
| 57 | |
|---|
| 58 | ; used by php land code and .htaccess to override |
|---|
| 59 | (define (set-ini-entry name value) |
|---|
| 60 | (debug-trace 9 (format "(runtime) setting ~a to ~a" name value)) |
|---|
| 61 | (hashtable-put! *ini-table* (mkstr name) value) |
|---|
| 62 | ; precision? |
|---|
| 63 | (when (string=? (mkstr name) "precision") |
|---|
| 64 | (set! *float-precision* (mkfixnum value)))) |
|---|
| 65 | |
|---|
| 66 | ; used only by config file reader |
|---|
| 67 | ; ini table will be reset to this after every page load |
|---|
| 68 | (define (config-ini-entry name value) |
|---|
| 69 | (debug-trace 9 (format "(runtime) config setting ~a to ~a" name value)) |
|---|
| 70 | (hashtable-put! *config-ini-table* (mkstr name) value) |
|---|
| 71 | ; initially we also setup the main ini |
|---|
| 72 | ; it will be reset every page load |
|---|
| 73 | (set-ini-entry name value)) |
|---|
| 74 | |
|---|
| 75 | ;; generate code to re-create ini entries from the config file |
|---|
| 76 | (define (generate-config-ini-entries) |
|---|
| 77 | (let ((code '())) |
|---|
| 78 | (hashtable-for-each *config-ini-table* |
|---|
| 79 | (lambda (k v) |
|---|
| 80 | (set! code (cons `(config-ini-entry ,k ,v) code)))) |
|---|
| 81 | `(begin ,@(reverse code)))) |
|---|
| 82 | |
|---|
| 83 | ; used by extensions to set base values |
|---|
| 84 | ; these will be used if no other is available |
|---|
| 85 | (define (default-ini-entry name value) |
|---|
| 86 | (hashtable-put! *default-ini-table* (mkstr name) value)) |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | ; |
|---|
| 91 | ; This module implements reading an INI file |
|---|
| 92 | ; into a php hash. it is used in the builtin functions |
|---|
| 93 | ; in stdlib (parse_ini_file) and also by the compiler |
|---|
| 94 | ; to process project files from the IDE |
|---|
| 95 | ; |
|---|
| 96 | |
|---|
| 97 | ; |
|---|
| 98 | ; this still needs more work to be compatible with php: |
|---|
| 99 | ; 1) it will replace constants with their values |
|---|
| 100 | ; 2) bitewise operations |
|---|
| 101 | |
|---|
| 102 | (define *current-lineno* 1) |
|---|
| 103 | |
|---|
| 104 | (define *first-eof-p* #t) |
|---|
| 105 | |
|---|
| 106 | (define *ini-surface* |
|---|
| 107 | (regular-grammar |
|---|
| 108 | ((crlf (: (* "\r") #\newline ))) |
|---|
| 109 | ; yadda |
|---|
| 110 | ("[" 'lbrak) |
|---|
| 111 | ("]" 'rbrak) |
|---|
| 112 | ("=" 'assign) |
|---|
| 113 | ; space, newlines |
|---|
| 114 | ((+ (in space #\Tab)) (ignore)) |
|---|
| 115 | ; |
|---|
| 116 | (crlf (begin |
|---|
| 117 | (set! *current-lineno* (+ *current-lineno* 1)) |
|---|
| 118 | 'nl)) |
|---|
| 119 | ; comment |
|---|
| 120 | ((: (in #\; #\#) (* all) crlf) |
|---|
| 121 | (begin |
|---|
| 122 | (set! *current-lineno* (+ *current-lineno* 1)) |
|---|
| 123 | 'nl)) |
|---|
| 124 | ; value (quoted string) |
|---|
| 125 | ((: #\" (* (or (out #\\ #\") (: #\\ (or all crlf)))) #\") |
|---|
| 126 | ; XXX if the string was multiline, our current-lineno isn't advanced. does this happen? |
|---|
| 127 | (cons 'string (the-substring 1 (-fx (the-length) 1)))) |
|---|
| 128 | ; value (symbol) |
|---|
| 129 | ((+ (out space #\= #\newline #\tab "\r" #\[ #\] #\" #\; #\#)) |
|---|
| 130 | (cons 'symbol (the-string))) |
|---|
| 131 | (else |
|---|
| 132 | ;; this trick is so that the first time we see the eof, it will |
|---|
| 133 | ;; be returned as a newline, and the second time the actual eof |
|---|
| 134 | ;; will be returned. It allows us to read ini files that don't |
|---|
| 135 | ;; end in a newline. |
|---|
| 136 | (cond |
|---|
| 137 | ((and *first-eof-p* |
|---|
| 138 | (eof-object? (the-failure))) |
|---|
| 139 | (set! *first-eof-p* #f) |
|---|
| 140 | 'nl) |
|---|
| 141 | (else |
|---|
| 142 | ;; reset *first-eof-p* |
|---|
| 143 | (set! *first-eof-p* #t) |
|---|
| 144 | (the-failure)))))) |
|---|
| 145 | |
|---|
| 146 | |
|---|
| 147 | (define *ini-grammar* |
|---|
| 148 | (lalr-grammar |
|---|
| 149 | ; terminals |
|---|
| 150 | (assign lbrak rbrak string symbol nl) |
|---|
| 151 | |
|---|
| 152 | (inifile |
|---|
| 153 | ((line inifile) (cons line inifile)) |
|---|
| 154 | (() '())) |
|---|
| 155 | |
|---|
| 156 | (line |
|---|
| 157 | ; section header |
|---|
| 158 | ; XXX symbol-list here because headers can contain spaces |
|---|
| 159 | ((lbrak symbol-list rbrak nl) (cons 'section symbol-list)) |
|---|
| 160 | |
|---|
| 161 | ; XXX this symbol-list gets us around not supporting bitwise |
|---|
| 162 | ; operations on constants (e.g. error_reporting). we just concat the symbols together |
|---|
| 163 | ((symbol@key assign symbol-list nl) (cons* 'value key symbol-list)) |
|---|
| 164 | |
|---|
| 165 | ; value assign, quoted string |
|---|
| 166 | ((symbol@key assign string@val nl) (cons* 'value key val)) |
|---|
| 167 | |
|---|
| 168 | ; value assign, blank string |
|---|
| 169 | ((symbol assign nl) (cons* 'value symbol "")) |
|---|
| 170 | |
|---|
| 171 | ; blank line |
|---|
| 172 | ((nl) '())) |
|---|
| 173 | |
|---|
| 174 | (symbol-list |
|---|
| 175 | ((symbol symbol-list) (string-append symbol symbol-list)) |
|---|
| 176 | ((symbol) symbol)) |
|---|
| 177 | |
|---|
| 178 | )) |
|---|
| 179 | |
|---|
| 180 | |
|---|
| 181 | (define (ini-file-parse fname::bstring parse-sections?::bool) |
|---|
| 182 | (bind-exit (exit) |
|---|
| 183 | (if (file-exists? fname) |
|---|
| 184 | (let ((rhash (make-php-hash)) |
|---|
| 185 | (current-section "") |
|---|
| 186 | (ini-toks '())) |
|---|
| 187 | ; XXX grammer debug |
|---|
| 188 | ; (set! *current-lineno* 1) |
|---|
| 189 | ; (with-input-from-file fname |
|---|
| 190 | ; (lambda () |
|---|
| 191 | ; (pp (get-tokens *ini-surface* (current-input-port))))) |
|---|
| 192 | (set! *current-lineno* 1) |
|---|
| 193 | (try |
|---|
| 194 | (set! ini-toks (with-input-from-file fname |
|---|
| 195 | (lambda () |
|---|
| 196 | (read/lalrp *ini-grammar* *ini-surface* (current-input-port))))) |
|---|
| 197 | (lambda (e p m o) |
|---|
| 198 | (php-warning (format "On line ~a of ~a: ~a" *current-lineno* fname m)) |
|---|
| 199 | (exit #f))) |
|---|
| 200 | ; go through tokens and build php hash |
|---|
| 201 | (for-each (lambda (a) |
|---|
| 202 | (unless (null? a) |
|---|
| 203 | (let ((tok (car a))) |
|---|
| 204 | (cond |
|---|
| 205 | ; |
|---|
| 206 | ; NOTE: assumes parser has already handler conversion to string |
|---|
| 207 | ; |
|---|
| 208 | ((eqv? tok 'section) (set! current-section (cdr a))) |
|---|
| 209 | ((eqv? tok 'value) (let* ((key (cadr a)) |
|---|
| 210 | (val (cddr a)) |
|---|
| 211 | (down-val (string-downcase val))) |
|---|
| 212 | (when (or (string=? down-val "on") |
|---|
| 213 | (string=? down-val "true")) |
|---|
| 214 | (set! val "1")) |
|---|
| 215 | (when (or (string=? down-val "off") |
|---|
| 216 | (string=? down-val "null") |
|---|
| 217 | (string=? down-val "false")) |
|---|
| 218 | (set! val "")) |
|---|
| 219 | (if (and parse-sections? |
|---|
| 220 | (> (string-length current-section) 0)) |
|---|
| 221 | ; use section |
|---|
| 222 | (let ((shash (php-hash-lookup rhash current-section))) |
|---|
| 223 | (if (php-hash? shash) |
|---|
| 224 | ; already have the section |
|---|
| 225 | (php-hash-insert! shash key val) |
|---|
| 226 | ; make a new section hash |
|---|
| 227 | (begin |
|---|
| 228 | (set! shash (make-php-hash)) |
|---|
| 229 | (php-hash-insert! shash key val) |
|---|
| 230 | (php-hash-insert! rhash current-section shash)))) |
|---|
| 231 | ; no sections or none current |
|---|
| 232 | (php-hash-insert! rhash key val)))))))) |
|---|
| 233 | ini-toks) |
|---|
| 234 | ; make hash |
|---|
| 235 | rhash) |
|---|
| 236 | ; bad file |
|---|
| 237 | #f))) |
|---|
| 238 | |
|---|
| 239 | |
|---|
| 240 | ;;;;;;;;; |
|---|
| 241 | ; |
|---|
| 242 | ; defaults |
|---|
| 243 | ; |
|---|
| 244 | |
|---|
| 245 | ; url rewriter tag defaults |
|---|
| 246 | (default-ini-entry "url_rewriter.tags" "a=href,area=href,frame=src,input=src,form=fakeentry") |
|---|
| 247 | (default-ini-entry "arg_separator.input" "&") |
|---|
| 248 | (default-ini-entry "precision" "12") |
|---|
| 249 | (default-ini-entry "register_globals" #f) |
|---|