1<?php 2/** 3 * pfcglobalconfig.class.php 4 * 5 * Copyright © 2006 Stephane Gully <stephane.gully@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the 19 * Free Software Foundation, 51 Franklin St, Fifth Floor, 20 * Boston, MA 02110-1301 USA 21 */ 22 23require_once dirname(__FILE__)."/pfctools.php"; 24require_once dirname(__FILE__)."/pfci18n.class.php"; 25require_once dirname(__FILE__).'/pfccontainer.class.php'; 26 27/** 28 * pfcGlobalConfig stock configuration data into sessions and initialize some stuff 29 * 30 * @author Stephane Gully <stephane.gully@gmail.com> 31 */ 32class pfcGlobalConfig 33{ 34 // ------------------ 35 // public parameters 36 // ------------------ 37 38 /** 39 * <p>This is the only mandatory parameter used to identify the chat server. 40 * You can compare it to the server ip/host like on an IRC server. 41 * If you don't know what to write, just try : <code>$params["serverid"] = md5(__FILE__);</code></p> 42 */ 43 var $serverid = ''; 44 45 /** 46 * <p>Used to translate the chat text and messages. Accepted values are the <code>i18n/</code> sub directories names. 47 * (By default, this is the local server language.)</p> 48 */ 49 var $language = ''; 50 51 /** 52 * <p>Set a sepcific encoding for chat labels. 53 * This is really useful when the Web page embedding the chat is not UTF-8 encoded. 54 * This parameter should be the same as the chat web page. 55 * Could be ISO-8859-1 or anything else but it must be supported by iconv php module. 56 * (Default value: UTF-8)</p> 57 */ 58 var $output_encoding = 'UTF-8'; 59 60 /** 61 * <p>If you have already identified the user (forum, portal...) you can force the user's nickname with this parameter. 62 * Defining a nick will skip the "Please enter your nickname" popup.</p> 63 * <p>Warning : Nicknames must be encoded in UTF-8. 64 * For example, if you get nicks from a databases where they are ISO-8859-1 encoded, 65 * you must convert it: <code>$params["nick"] = iconv("ISO-8859-1", "UTF-8", $bdd_nickname);</code> 66 * (Of course, change the <code>$bdd_nickname</code> parameter for your needs.)</p> 67 * <p>(Default value: "" - means users must choose a nickname when s/he connects.)</p> 68 */ 69 var $nick = ""; 70 71 /** 72 * <p>This is the maximum nickname length, a longer nickname is forbidden. 73 * (Default value: 15)</p> 74 */ 75 var $max_nick_len = 15; 76 77 /** 78 * <p>Setting this to true will forbid the user to change his/her nickname later. 79 * (Default value: false)</p> 80 */ 81 var $frozen_nick = false; 82 83 /** 84 * <p>Contains some extra data (metadata) about the user that can be used to customize the display. 85 * For example: the user's gender, age, real name, etc. can be setup in order to display it in the user's info box. 86 * A example for gender is : <code>$params["nickmeta"] = array('gender'=>'f');</code> 87 * (Default value: empty array)</p> 88 */ 89 var $nickmeta = array(); 90 91 /** 92 * <p>Can be used to set user metadata that is only visible to admins. 93 * (Default value: <code>array('ip')</code> - means that the user's IP address is shown to admins only)</p> 94 */ 95 var $nickmeta_private = array('ip'); 96 97 /** 98 * <p>Can be used to hide keys in the final displayed whoisbox. 99 * (Default value: <code>array()</code> - means that nothing is hidden)</p> 100 */ 101 var $nickmeta_key_to_hide = array(); 102 103 /** 104 * <p>Set this parameter to true if you want to give admin rights to the connected user. 105 * Attention : if you don't use any external registration system, all your users will be admins. 106 * You have to test current user rights before setting this parameter to true. 107 * (Default value: false)</p> 108 */ 109 var $isadmin = false; 110 111 /** 112 * <p>This parameter contains a list of key/value that identify admin access. 113 * The keys are the nicknames and the values are the corresponding passwords. 114 * Note: The "isadmin" parameter does not depend on this variable. 115 * (Default value: nick 'admin' with no password is available. Don't forget to change it.)</p> 116 */ 117 var $admins = array("admin" => ""); 118 119 /** 120 * <p>When this parameter is true, it gives admin rights to the first connected user on the server. 121 * (Default value: false)</p> 122 */ 123 var $firstisadmin = false; 124 125 /** 126 * <p>Used to change the chat title that is visible just above the messages list. 127 * (Default value: "My Chat")</p> 128 */ 129 var $title = ''; 130 131 /** 132 * <p>Used to create default rooms (auto-joined at startup). It contains an array of rooms names. 133 * (Default value: one room is created named "My room")</p> 134 */ 135 var $channels = array(); 136 137 /** 138 * <p>This parameter can be used to restrict channels to users. 139 * If the array is empty, it allows users to create their own channels. 140 * (Default value: empty array)</p> 141 */ 142 var $frozen_channels = array(); 143 144 /** 145 * <p>The maximum number of allowed channels for each user. 146 * (Default value: 10)</p> 147 */ 148 var $max_channels = 10; 149 150 /** 151 * <p>This array contains the nicknames list you want to initiate a private message at chat loading. 152 * Of course, the listed nicknames should be online or it will just be ignored. 153 * (Default value: empty array)</p> 154 */ 155 var $privmsg = array(); 156 157 /** 158 * <p>This is the maximum number of private message allowed at the same time for one user. 159 * (Default value: 5)</p> 160 */ 161 var $max_privmsg = 5; 162 163 /** 164 * <p>This is the time to wait between two refreshes. 165 * A refresh is an HTTP request which asks the server if there are new messages to display. 166 * If there are no new messages, then an empty HTTP response is returned. 167 * This parameter will be dynamically changed depending on the chat activity, see refresh_delay_steps 168 * parameter for more information. 169 * (Default value: 2000 it means 2000 ms or 2 seconds)</p> 170 */ 171 var $refresh_delay = 2000; 172 173 /** 174 * <p>This parameter is used to control the refresh_delay value dynamically. 175 * More the chat is active, more the refresh_delay is low, that means more the chat is responsive. 176 * The first parameter is a refresh delay value, the second is a time inactivity boundary etc ... 177 * (Default value: array(2000,20000,3000,60000 ... that means: start with 2s delay after 20s of inactivity, 178 * 3s delay after 60s of inactivity ...)</p> 179 */ 180 var $refresh_delay_steps = array(2000,20000,3000,30000,5000,60000,8000,300000,15000,600000,30000); 181 182 /** 183 * <p>This is the time of inactivity to wait before considering a user is disconnected (in milliseconds). 184 * A user is inactive only if s/he closed his/her chat window. A user with an open chat window 185 * is not inactive because s/he sends each <code>refresh_delay</code> an HTTP request. 186 * (Default value: 35000 it means 35000 ms or 35 seconds)</p> 187 */ 188 var $timeout = 35000; 189 190 /** 191 * When this parameter is true, all the chatters will be redirected 192 * to the url indicated by the <code>lockurl</code> parameter. 193 * (Default value: false)</p> 194 */ 195 var $islocked = false; 196 197 /** 198 * This url is used when <code>islocked</code> parameter is true. 199 * The users will be redirected (http redirect) to this url. 200 * (Default value: http://www.phpfreechat.net) 201 */ 202 var $lockurl = 'http://www.phpfreechat.net'; 203 204 /** 205 * <p>Contains the list of proxies to ingore. 206 * For example: append 'censor' to the list to disable words censoring. 207 * The list of system proxies can be found in src/proxies/. 208 * Attention: 'checktimeout' and 'checknickchange' proxies should not be disabled or the chat will not work anymore. 209 * (Default value: empty array - no proxies will be skipped)</p> 210 */ 211 var $skip_proxies = array(); 212 213 /** 214 * <p>This array contains the proxies that will be handled just before to process a command 215 * and just after the system proxies. 216 * You can use this array to execute your own proxy. 217 * (Default value: empty array)</p> 218 */ 219 var $post_proxies = array(); 220 221 /** 222 * <p>This array ocntains the proxies that will be handled just before system proxies. 223 * You can use this array to execute your own proxy. 224 * (Default value: empty array)</p> 225 */ 226 var $pre_proxies = array(); 227 228 /** 229 * <p>Contains the proxies configuration. 230 * TODO: explain the possible values for each proxies.</p> 231 */ 232 var $proxies_cfg = array("auth" => array(), 233 "noflood" => array("charlimit" => 450, 234 "msglimit" => 10, 235 "delay" => 5), 236 "censor" => array("words" => array("fuck","sex","bitch"), 237 "replaceby" => "*", 238 "regex" => false), 239 "log" => array("path" => "")); 240 241 /** 242 * <p>A custom proxies path. Used to easily plugin your own proxy to the chat without modifying the code. 243 * (Default value: empty path)</p> 244 */ 245 var $proxies_path = ''; 246 247 /** 248 * <p>Contains the default proxies location. 249 * Do not change this parameter if you don't know what you are doing. 250 * If you try to add your own proxy, check the <code>proxies_path</code> parameter. 251 * (Default value: <code>dirname(__FILE__).'/proxies'</code>)</p> 252 */ 253 var $proxies_path_default = ''; 254 255 /** 256 * <p>This parameter indicates your own commands directory location. 257 * The chat uses commands to communicate between client and server. 258 * As an example, when a message is sent, the <code>/send your message</code> command is used, 259 * when a nickname is changed, the <code>/nick newnickname</code> command is used. 260 * To create a new command, you have to write it and indicate in this parameter where it is located. 261 * (Default value: empty string - means no custom command path is used)</p> 262 */ 263 var $cmd_path = ''; 264 265 /** 266 * <p>Contains the default command path used by the system. 267 * Do not change this parameter if you don't know what you are doing. 268 * If you try to add your own command, check the <code>cmd_path</code> parameter. 269 * (Default value: <code>dirname(__FILE__).'/commands'</code>)</p> 270 */ 271 var $cmd_path_default = ''; 272 273 /** 274 * <p>This is the maximum message length in characters. A longer message is forbidden. 275 * (Default value: 400)</p> 276 */ 277 var $max_text_len = 400; 278 279 /** 280 * <p>This is the number of messages kept in the history. 281 * This is what you see when you reload the chat. 282 * The number of messages s/he can see is defined by this parameter. 283 * (Default value: 20</p> 284 */ 285 var $max_msg = 20; 286 287 /** 288 * <p>The maximum number of lines displayed in the window. 289 * Old lines will be deleted to save browser's memory on clients. 290 * Default value: 150)</p> 291 */ 292 var $max_displayed_lines = 150; 293 294 /** 295 * <p>Setting this to true will send a <code>/quit</code> command when the user closes his/her window. 296 * (NOTE: Doesn't work on Firefox). 297 * This parameter isn't true by default because on IE and Konqueror/Safari, 298 * reloading the window (F5) will generate the same event as closing the window which can be annoying. 299 * (Default value: false)</p> 300 */ 301 var $quit_on_closedwindow = true; 302 303 /** 304 * <p>Setting this to true will give the focus to the input text box when connecting to the chat. 305 * It can be useful not to touch the focus when integrating the chat into an existing website 306 * because when the focus is changed, the viewport follows the focus location. 307 * (Default value: true)</p> 308 */ 309 var $focus_on_connect = true; 310 311 /** 312 * <p>Setting this to false will oblige user to click on the connect button if s/he wants to chat. 313 * (Default value: true - a connection to the chat is automaticaly performed)</p> 314 */ 315 var $connect_at_startup = true; 316 317 /** 318 * <p>Setting it to true will start the chat minimized. 319 * (Default value: false)</p> 320 */ 321 var $start_minimized = false; 322 323 /** 324 * <p>Height of the chat area. 325 * (Default value: "440px")</p> 326 */ 327 var $height = "440px"; 328 329 /** 330 * <p><ul><li>Setting this to 0 will show nothing.</li> 331 * <li>Setting it to 1 will show nicknames changes.</li> 332 * <li>Setting it to 2 will show connect/disconnect notifications.</li> 333 * <li>Setting it to 4 will show kick/ban notifications.</li> 334 * <li>Setting it to 7 (1+2+4) will show all the notifications.</li></ul> 335 * (Default value: 7)</p> 336 */ 337 var $shownotice = 7; 338 339 /** 340 * <p>Setting it to false will disable nickname colorization. 341 * (Default value: true)</p> 342 **/ 343 var $nickmarker = true; 344 345 /** 346 * <p>Setting it to false will hide the date/hour column. 347 * (Default value: true)</p> 348 */ 349 var $clock = true; 350 351 /** 352 * <p>Setting it to false will start the chat without sound notifications. 353 * (Default value: true)</p> 354 */ 355 var $startwithsound = true; 356 357 /** 358 * <p>Setting it to true will open all links in a new window. 359 * (Default value: true)</p> 360 */ 361 var $openlinknewwindow = true; 362 363 /** 364 * <p>Setting it to false will disable the window title notification. 365 * When a message is received and this parameter is true, the window title is modified with <code>[n]</code> 366 * (n is the number of new posted messages). 367 * (Default value: true)</p> 368 */ 369 var $notify_window = true; 370 371 /** 372 * <p>Setting it to true will shorten long URLs entered by users in the chat area. 373 * (Default value: true)</p> 374 */ 375 var $short_url = true; 376 377 /** 378 * <p>Final width of the shortened URL in characters. (This includes the elipsis on shortened URLs.) 379 * This parameter is taken into account only when <code>short_url</code> is true. 380 * (Default value: 40)</p> 381 */ 382 var $short_url_width = 40; 383 384 /** 385 * <p>Used to show/hide the ping information near the phpfreechat linkback logo. 386 * The ping is the time between a client request and a server response. 387 * More the ping is low, faster the chat is responding. 388 * (Default value: true)</p> 389 */ 390 var $display_ping = true; 391 392 /** 393 * <p>Used to hide the phpfreechat linkback logo. 394 * Be sure that you are conform to the <a href="http://www.phpfreechat.net/license.en.html">license page</a> 395 * before setting this to false! 396 * (Default value: true)</p> 397 */ 398 var $display_pfc_logo = true; 399 400 /** 401 * <p>Used to show/hide the images in the channels and pv tabs. 402 * (Default value: true)</p> 403 */ 404 var $displaytabimage = true; 405 406 /** 407 * <p>Used to show/hide the close button in the channels tabs. 408 * (Default value: true)</p> 409 */ 410 var $displaytabclosebutton = true; 411 412 /** 413 * <p>Used to show/hide online users list at startup. 414 * (Default value: true)</p> 415 */ 416 var $showwhosonline = true; 417 418 /** 419 * <p>Used to show/hide the smiley selector at startup. 420 * (Default value: true)</p> 421 */ 422 var $showsmileys = true; 423 424 /** 425 * <p>Used to show/hide the showwhosonline button. 426 * (Default value: true)</p> 427 */ 428 var $btn_sh_whosonline = true; 429 430 /** 431 * <p>Used to show/hide the showsmileys button. 432 * (Default value: true)</p> 433 */ 434 var $btn_sh_smileys = true; 435 436 /** 437 * <p>This is the list of colors that will appears into the bbcode palette. 438 * (Default value: contains an array of basic colors: '#FFFFFF', '#000000', ...)</p> 439 */ 440 var $bbcode_colorlist = array('#FFFFFF', 441 '#000000', 442 '#000055', 443 '#008000', 444 '#FF0000', 445 '#800000', 446 '#800080', 447 '#FF5500', 448 '#FFFF00', 449 '#00FF00', 450 '#008080', 451 '#00FFFF', 452 '#0000FF', 453 '#FF00FF', 454 '#7F7F7F', 455 '#D2D2D2'); 456 457 /** 458 * <p>This is the list of colors that will be used to automaticaly and randomly colorize the nicknames in the chat. 459 * (Default value: contains an array of basic colors: '#CCCCCC','#000000')</p> 460 */ 461 var $nickname_colorlist = array('#CCCCCC', 462 '#000000', 463 '#3636B2', 464 '#2A8C2A', 465 '#C33B3B', 466 '#C73232', 467 '#80267F', 468 '#66361F', 469 '#D9A641', 470 '#3DCC3D', 471 '#1A5555', 472 '#2F8C74', 473 '#4545E6', 474 '#B037B0', 475 '#4C4C4C', 476 '#959595'); 477 478 /** 479 * <p>This parameter specifies which theme the chat will use. 480 * A theme is a package that makes it possible to completly change the chat appearance (CSS) and the chat dynamics (JS) 481 * You can find official themes in the <code>themes/</code> directory on your local phpfreechat distribution. 482 * (Default value: 'default')</p> 483 */ 484 var $theme = 'default'; 485 486 /** 487 * <p>Indicates where the themes are located. 488 * Use this parameter if you want to store your own theme in a special location. 489 * (by default the same as <code>theme_default_path</code>)</p> 490 */ 491 var $theme_path = ''; 492 493 /** 494 * <p>This url indicates the <code>theme_path</code> location. 495 * It will be used by the browser to load theme resources : images, css, js. 496 * If this parameter is not indicated, the themes will be copied to <code>data_public_path/themes</code> 497 * and this parameter value will be set to <code>data_public_url/theme</code>. 498 * (Default value: '')</p> 499 */ 500 var $theme_url = ''; 501 502 /** 503 * <p>Indicate where the official pfc default theme is located. 504 * Do not change this parameter if you don't know what you are doing. 505 * If you try to add your own theme, check the <code>theme_path</code> parameter. 506 * (Default value: '' - empty string means <code>dirname(__FILE__).'/../themes'</code> is used automatically)</p> 507 */ 508 var $theme_default_path = ''; 509 510 /** 511 * <p>This url indicates the <code>theme_default_path</code> location. 512 * Do not change this parameter if you don't know what you are doing. 513 * If you try to add your own theme, check the <code>theme_path</code> parameter. 514 * (Default value: the theme is copied into <code>data_public_path/themes</code> 515 * and this parameter will be set to <code>data_public_url/theme</code>)</p> 516 */ 517 var $theme_default_url = ''; 518 519 /** 520 * <p>Used to specify the chat container (chat database). 521 * Accepted containers are : File and Mysql (maybe others in the future). 522 * (Default value: 'File')</p> 523 */ 524 var $container_type = 'File'; 525 526 /** 527 * <p>Used to specify the script that will handle asynchronous requests. 528 * Very useful when the chat (client) script is resource consuming (ex: forum or portal chat integration). 529 * (Default value: '' - means this parameter is automatically calculated)</p> 530 */ 531 var $server_script_path = ''; 532 533 /** 534 * <p>This url indicates the <code>server_script_path</code>. 535 * It will be used to do AJAX requests from the browser. Therefore, this URL should be a browsable public url. 536 * This parameter is useful when using URL rewriting because basic auto-calculation will fail. 537 * (Default value: '' - means this parameter is automatically calculated)</p> 538 */ 539 var $server_script_url = ''; 540 541 /** 542 * <p>Used to specify the script path which first displays the chat. 543 * This path will be used to calculate relatives paths for resources: javascript lib and images. 544 * Useful when the php configuration is uncommon. This option can be used to force the automatic detection process. 545 * (Default value: '' - means this parameter is automatically calculated)</p> 546 */ 547 var $client_script_path = ''; 548 549 /** 550 * <p>Used to store private data like cache, logs and chat history. 551 * Tip: you can optimize your chat performances, 552 * see <a href="http://www.phpfreechat.net/faq.en.html#tmpfs">this FAQ entry</a>. 553 * (Default value: '' - means <code>dirname(__FILE__)."/../data/private"</code> is used automatically)</p> 554 */ 555 var $data_private_path = ''; 556 557 /** 558 * This path must be reachable by your web server. 559 * Javascript and every resources (theme) files will be stored here. 560 * (Default value: '' - means dirname(__FILE__)."/../data/public" is used automatically) 561 */ 562 var $data_public_path = ''; 563 564 /** 565 * This URL should link to the <code>data_private_path</code> directory so that 566 * the clients' browsers will be able to load needed javascript files and theme resources. 567 * It can be useful when url rewriting is done on the server. 568 * (Default value: '' - means this parameter is automatically calculated from <code>data_private_path</code>) 569 */ 570 var $data_public_url = ''; 571 572 /** 573 * <p>This is the prototype javascript library URL. 574 * Use this parameter to use your external library. 575 * (Default value: '' - means <code>data/js/prototype.js</code> is used automatically)</p> 576 */ 577 var $prototypejs_url = ''; 578 579 /** 580 * <p>When debug is true, some traces will be shown on the chat clients 581 * (Default value: false)</p> 582 */ 583 var $debug = false; 584 585 /** 586 * <p>Can be used to setup the chat time zone. 587 * It is the difference in seconds between chat clock and server clock. 588 * (Default value: 0)</p> 589 */ 590 var $time_offset = 0; 591 592 /** 593 * <p>How to display the dates in the chat. 594 * (Default value: <code>'d/m/Y'</code>)</p> 595 */ 596 var $date_format = 'd/m/Y'; 597 598 /** 599 * <p>How to display the time in the chat 600 * (Default value: <code>'H:i:s'</code>)</p> 601 */ 602 var $time_format = 'H:i:s'; 603 604 /** 605 * <p>This parameter is useful when your chat server is behind a reverse proxy that 606 * forwards client ip address in HTTP_X_FORWARDED_FOR http header. 607 * Some discutions about this parameter are available 608 * on <a href="http://www.phpfreechat.net/forum/viewtopic.php?id=1344">the forum</a>. 609 * (Default value: false)</p> 610 */ 611 var $get_ip_from_xforwardedfor = false; 612 613 /** 614 * <p>Most of the chat parameters are stored in a internal cache for performances issues. 615 * It means that for all the clients the chat will have the same parameters. However sometime you need 616 * to customize some parameters for each clients. 617 * For example: the 'language' parameter could depends on the chatter profil so it could interesting to 618 * ignore the cache for this parameter. 619 * The 'dyn_params' contains the parameters that need to be dynamic (not stored in the cache). 620 * (Default value: array())</p> 621 */ 622 var $dyn_params = array(); 623 624 // ------------------ 625 // private parameters 626 // ------------------ 627 /** 628 * Contains proxies to execute on each commands. 629 * Filled in the init step, this parameter cannot be overridden. 630 */ 631 var $proxies = array(); 632 633 var $smileys = array(); 634 var $errors = array(); 635 var $is_init = false; // used internaly to know if the chat config is initialized 636 var $version = ''; // the phpfreechat version: taken from the 'version' file content 637 638 var $_sys_proxies = array("lock", "checktimeout", "checknickchange", "auth", "noflood", "censor", "log"); 639 var $_dyn_params = array("nick","isadmin","islocked","admins","frozen_channels", "channels", "privmsg", "nickmeta","time_offset","date_format","time_format"); 640 var $_params_type = array(); 641 var $_query_string = ''; 642 643 function pfcGlobalConfig( $params = array() ) 644 { 645 // @todo find a cleaner way to forward serverid to i18n functions 646 $GLOBALS['serverid'] = isset($params['serverid']) ? $params['serverid'] : '_serverid_'; 647 // setup the locales for the translated messages 648 pfcI18N::Init(isset($params['language']) ? $params['language'] : ''); 649 650 // check the serverid is really defined 651 if (!isset($params["serverid"])) 652 $this->errors[] = _pfc("'%s' parameter is mandatory by default use '%s' value", "serverid", "md5(__FILE__)"); 653 $this->serverid = $params["serverid"]; 654 655 // setup data_private_path because _GetCacheFile needs it 656 if (!isset($params["data_private_path"])) 657 $this->data_private_path = dirname(__FILE__)."/../data/private"; 658 else 659 $this->data_private_path = $params["data_private_path"]; 660 661 // check if a cached configuration already exists 662 // don't load parameters if the cache exists 663 $cachefile = $this->_GetCacheFile(); 664 if (!file_exists($cachefile)) 665 { 666 // first of all, save our current state in order to be able to check for variable types later 667 $this->_saveParamsTypes(); 668 669 if (!isset($params["data_public_path"])) 670 $this->data_public_path = dirname(__FILE__)."/../data/public"; 671 else 672 $this->data_public_path = $params["data_public_path"]; 673 674 // if the user didn't specify the server_script_url, then remember it and 675 // append QUERY_STRING to it 676 if (!isset($params['server_script_url'])) 677 $this->_query_string = isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '' ? 678 '?'.$_SERVER['QUERY_STRING'] : 679 ''; 680 681 // load users container or keep default one 682 if (isset($params["container_type"])) 683 $this->container_type = $params["container_type"]; 684 685 // load default container's config 686 $ct =& pfcContainer::Instance($this->container_type, true); 687 $ct_cfg = $ct->getDefaultConfig(); 688 foreach( $ct_cfg as $k => $v ) 689 { 690 $attr = "container_cfg_".$k; 691 if (!isset($this->$attr)) 692 $this->$attr = $v; 693 } 694 695 // load all user's parameters which will override default ones 696 foreach ( $params as $k => $v ) 697 { 698 if (!isset($this->$k)) 699 $this->errors[] = _pfc("Error: undefined or obsolete parameter '%s', please correct or remove this parameter", $k); 700 if (preg_match('/^_/',$k)) 701 $this->errors[] = _pfc("Error: '%s' is a private parameter, you are not allowed to change it", $k); 702 703 if ($k == "proxies_cfg") 704 { 705 // don't replace all the proxy_cfg parameters, just replace the specified ones 706 foreach ( $params["proxies_cfg"] as $k2 => $v2 ) 707 { 708 if (is_array($v2)) 709 foreach( $v2 as $k3 => $v3) 710 $this->proxies_cfg[$k2][$k3] = $v3; 711 else 712 $this->proxies_cfg[$k2] = $v2; 713 } 714 } 715 else 716 $this->$k = $v; 717 } 718 } 719 720 // load dynamic parameter even if the config exists in the cache 721 if (isset($params['dyn_params']) && is_array($params['dyn_params'])) 722 $this->_dyn_params = array_merge($this->_dyn_params,$params['dyn_params']); 723 foreach ( $this->_dyn_params as $dp ) 724 if (isset($params[$dp])) 725 $this->$dp = $params[$dp]; 726 727 // 'channels' is now a dynamic parameter, just check if I need to initialize it or not 728 if (is_array($this->channels) && 729 count($this->channels) == 0 && 730 !isset($params['channels'])) 731 $this->channels = array(_pfc("My room")); 732 733 // now load or save the configuration in the cache 734 $this->synchronizeWithCache(); 735 736 // to be sure the container instance is initialized 737 $ct =& pfcContainer::Instance($this->container_type, true); 738 739 // This is a dirty workaround which fix a infinite loop when: 740 // 'frozen_nick' is true 741 // 'nick' length is > 'max_nick_len' 742 $this->nick = $this->filterNickname($this->nick); 743 } 744 745 function &Instance( $params = array(), $destroy_instance = false ) 746 { 747 static $i; 748 if ($destroy_instance) 749 $i = NULL; 750 else 751 if (!isset($i)) 752 $i = new pfcGlobalConfig( $params ); 753 return $i; 754 } 755 756 /** 757 * This function saves all the parameters types in order to check later if the types are ok 758 */ 759 function _saveParamsTypes() 760 { 761 $vars = get_object_vars($this); 762 foreach($vars as $k => $v) 763 { 764 if (is_string($v)) $this->_params_type["string"][] = $k; 765 else if (is_bool($v)) $this->_params_type["bool"][] = $k; 766 else if (is_array($v)) $this->_params_type["array"][] = $k; 767 else if (is_int($v) && $v>0) $this->_params_type["positivenumeric"][] = $k; 768 else $this->_params_type["misc"][] = $k; 769 } 770 } 771 772 /** 773 * Initialize the phpfreechat configuration 774 * this initialisation is done once at startup then it is stored into a session cache 775 */ 776 function init() 777 { 778 $ok = true; 779 780 // check the parameters types 781 $array_params = $this->_params_type["array"]; 782 foreach( $array_params as $ap ) 783 { 784 if (!is_array($this->$ap)) 785 $this->errors[] = _pfc("'%s' parameter must be an array", $ap); 786 } 787 $numerical_positive_params = $this->_params_type["positivenumeric"]; 788 foreach( $numerical_positive_params as $npp ) 789 { 790 if (!is_int($this->$npp) || $this->$npp < 0) 791 $this->errors[] = _pfc("'%s' parameter must be a positive number", $npp); 792 } 793 $boolean_params = $this->_params_type["bool"]; 794 foreach( $boolean_params as $bp ) 795 { 796 if (!is_bool($this->$bp)) 797 $this->errors[] = _pfc("'%s' parameter must be a boolean", $bp); 798 } 799 $string_params = $this->_params_type["string"]; 800 foreach( $string_params as $sp ) 801 { 802 if (!is_string($this->$sp)) 803 $this->errors[] = _pfc("'%s' parameter must be a charatere string", $sp); 804 } 805 806 if ($this->title == "") $this->title = _pfc("My Chat"); 807 808 // first of all, check the used functions 809 $f_list["file_get_contents"] = _pfc("You need %s", "PHP 4 >= 4.3.0 or PHP 5"); 810 $err_session_x = "You need PHP 4 or PHP 5"; 811 $f_list["session_start"] = $err_session_x; 812 $f_list["session_destroy"] = $err_session_x; 813 $f_list["session_id"] = $err_session_x; 814 $f_list["session_name"] = $err_session_x; 815 $err_preg_x = _pfc("You need %s", "PHP 3 >= 3.0.9 or PHP 4 or PHP 5"); 816 $f_list["preg_match"] = $err_preg_x; 817 $f_list["preg_replace"] = $err_preg_x; 818 $f_list["preg_split"] = $err_preg_x; 819 $err_ob_x = _pfc("You need %s", "PHP 4 or PHP 5"); 820 $f_list["ob_start"] = $err_ob_x; 821 $f_list["ob_get_contents"] = $err_ob_x; 822 $f_list["ob_end_clean"] = $err_ob_x; 823 $f_list["get_object_vars"] = _pfc("You need %s", "PHP 4 or PHP 5"); 824 $this->errors = array_merge($this->errors, check_functions_exist($f_list)); 825 826 // $this->errors = array_merge($this->errors, @test_writable_dir($this->data_public_path, "data_public_path")); 827 $this->errors = array_merge($this->errors, @test_writable_dir($this->data_private_path, "data_private_path")); 828 $this->errors = array_merge($this->errors, @test_writable_dir($this->data_private_path."/cache", "data_private_path/cache")); 829 830 831 // install the public directory content 832 $dir = dirname(__FILE__)."/../data/public/js"; 833 $dh = opendir($dir); 834 while (false !== ($file = readdir($dh))) 835 { 836 $f_src = $dir.'/'.$file; 837 $f_dst = $this->data_public_path.'/js/'.$file; 838 if ($file == "." || $file == ".." || !is_file($f_src)) continue; // skip . and .. generic files 839 // install js files only if the destination doesn't exists or if the destination timestamp is older than the source timestamp 840 if (!file_exists($f_dst) || filemtime($f_dst) < filemtime($f_src) ) 841 { 842 mkdir_r($this->data_public_path.'/js/'); 843 copy( $f_src, $f_dst ); 844 } 845 if (!file_exists($f_dst)) $this->errors[] = _pfc("%s doesn't exist, data_public_path cannot be installed", $f_dst); 846 } 847 closedir($dh); 848 849 850 // --- 851 // test client script 852 // try to find the path into server configuration 853 if ($this->client_script_path == '') 854 $this->client_script_path = pfc_GetScriptFilename(); 855 856 if ($this->server_script_url == '' && $this->server_script_path == '') 857 { 858 $filetotest = $this->client_script_path; 859 // do not take into account the url parameters 860 if (preg_match("/(.*)\?(.*)/", $filetotest, $res)) 861 $filetotest = $res[1]; 862 if ( !file_exists($filetotest) ) 863 $this->errors[] = _pfc("%s doesn't exist", $filetotest); 864 $this->server_script_url = './'.basename($filetotest).$this->_query_string; 865 } 866 867 // calculate datapublic url 868 if ($this->data_public_url == "") 869 $this->data_public_url = pfc_RelativePath($this->client_script_path, $this->data_public_path); 870 871 if ($this->server_script_path == '') 872 $this->server_script_path = $this->client_script_path; 873 874 // --- 875 // test server script 876 if ($this->server_script_url == '') 877 { 878 $filetotest = $this->server_script_path; 879 // do not take into account the url parameters 880 if (preg_match("/(.*)\?(.*)/",$this->server_script_path, $res)) 881 $filetotest = $res[1]; 882 if ( !file_exists($filetotest) ) 883 $this->errors[] = _pfc("%s doesn't exist", $filetotest); 884 $this->server_script_url = pfc_RelativePath($this->client_script_path, $this->server_script_path).'/'.basename($filetotest).$this->_query_string; 885 } 886 887 // check if the theme_path parameter are correctly setup 888 if ($this->theme_default_path == '' || !is_dir($this->theme_default_path)) 889 $this->theme_default_path = dirname(__FILE__).'/../themes'; 890 if ($this->theme_path == '' || !is_dir($this->theme_path)) 891 $this->theme_path = $this->theme_default_path; 892 893 // If the user didn't give any theme_default_url value, 894 // copy the default theme resources in a public directory 895 if ($this->theme_default_url == '') 896 { 897 mkdir_r($this->data_public_path.'/themes/default'); 898 if (!is_dir($this->data_public_path.'/themes/default')) 899 $this->errors[] = _pfc("cannot create %s", $this->data_public_path.'/themes/default'); 900 else 901 { 902 $ret = copy_r( dirname(__FILE__).'/../themes/default', 903 $this->data_public_path.'/themes/default' ); 904 if (!$ret) 905 $this->errors[] = _pfc("cannot copy %s in %s", 906 dirname(__FILE__).'/../themes/default', 907 $this->data_public_path.'/themes/default'); 908 } 909 $this->theme_default_url = $this->data_public_url.'/themes'; 910 } 911 if ($this->theme_url == '') 912 { 913 mkdir_r($this->data_public_path.'/themes/'.$this->theme); 914 if (!is_dir($this->data_public_path.'/themes/'.$this->theme)) 915 $this->errors[] = _pfc("cannot create %s", $this->data_public_path.'/themes/'.$this->theme); 916 else 917 { 918 $ret = copy_r( $this->theme_path.'/'.$this->theme, 919 $this->data_public_path.'/themes/'.$this->theme ); 920 if (!$ret) 921 $this->errors[] = _pfc("cannot copy %s in %s", 922 $this->theme_path.'/'.$this->theme, 923 $this->data_public_path.'/themes/'.$this->theme); 924 } 925 $this->theme_url = $this->data_public_url.'/themes'; 926 } 927 928 // if the user do not have an existing prototype.js library, we use the embeded one 929 if ($this->prototypejs_url == '') $this->prototypejs_url = $this->data_public_url.'/js/prototype.js'; 930 931 // --- 932 // run specific container initialisation 933 $ct =& pfcContainer::Instance(); 934 $ct_errors = $ct->init($this); 935 $this->errors = array_merge($this->errors, $ct_errors); 936 937 // check if the wanted language is known 938 $lg_list = pfcI18N::GetAcceptedLanguage(); 939 if ( $this->language != "" && !in_array($this->language, $lg_list) ) 940 $this->errors[] = _pfc("'%s' parameter is not valid. Available values are : '%s'", "language", implode(", ", $lg_list)); 941 942 // calculate the proxies chaine 943 $this->proxies = array(); 944 foreach($this->pre_proxies as $px) 945 { 946 if (!in_array($px,$this->skip_proxies) && !in_array($px,$this->proxies)) 947 $this->proxies[] = $px; 948 949 } 950 foreach($this->_sys_proxies as $px) 951 { 952 if (!in_array($px,$this->skip_proxies) && !in_array($px,$this->proxies)) 953 $this->proxies[] = $px; 954 955 } 956 foreach($this->post_proxies as $px) 957 { 958 if (!in_array($px,$this->skip_proxies) && !in_array($px,$this->proxies)) 959 $this->proxies[] = $px; 960 961 } 962 963 if (in_array('log',$this->proxies)) { 964 // test the LOCK_EX feature because the log proxy needs to write in a file 965 $filename = $this->data_private_path.'/filemtime2.test'; 966 if (is_writable(dirname($filename))) 967 { 968 $data1 = time(); 969 file_put_contents($filename, $data1, LOCK_EX); 970 $data2 = file_get_contents($filename); 971 if ($data1 != $data2) { 972 unset($this->proxies[array_search('log',$this->proxies)]); 973 } 974 } 975 } 976 977 // save the proxies path 978 $this->proxies_path_default = dirname(__FILE__).'/proxies'; 979 // check the customized proxies path 980 if ($this->proxies_path != '' && !is_dir($this->proxies_path)) 981 $this->errors[] = _pfc("'%s' directory doesn't exist", $this->proxies_path); 982 if ($this->proxies_path == '') $this->proxies_path = $this->proxies_path_default; 983 984 // save the commands path 985 $this->cmd_path_default = dirname(__FILE__).'/commands'; 986 if ($this->cmd_path == '') $this->cmd_path = $this->cmd_path_default; 987 988 // load smileys from file 989 $this->loadSmileyTheme(); 990 991 // load version number from file 992 $this->version = trim(file_get_contents(dirname(__FILE__)."/../version.txt")); 993 994 $this->is_init = (count($this->errors) == 0); 995 } 996 997 function isInit() 998 { 999 return $this->is_init; 1000 } 1001 1002 function &getErrors() 1003 { 1004 return $this->errors; 1005 } 1006 1007 function loadSmileyTheme() 1008 { 1009 $theme = file($this->getFilePathFromTheme("smileys/theme.txt")); 1010 $result = array(); 1011 foreach($theme as $line) 1012 { 1013 $line = trim($line); 1014 if (preg_match("/^#.*/",$line)) 1015 continue; 1016 else if (preg_match("/([a-z_\-0-9\.]+)(.*)$/i",$line,$res)) 1017 { 1018 $smiley_file = 'smileys/'.$res[1]; 1019 $smiley_str = trim($res[2])."\n"; 1020 $smiley_str = str_replace("\n", "", $smiley_str); 1021 $smiley_str = str_replace("\t", " ", $smiley_str); 1022 $smiley_str_tab = explode(" ", $smiley_str); 1023 foreach($smiley_str_tab as $str) 1024 $result[$smiley_file][] = htmlspecialchars(addslashes($str)); 1025 } 1026 } 1027 $this->smileys =& $result; 1028 } 1029 1030 function getId() 1031 { 1032 return $this->serverid; 1033 } 1034 1035 function _GetCacheFile($serverid = "", $data_private_path = "") 1036 { 1037 if ($serverid == '') $serverid = $this->getId(); 1038 if ($data_private_path == '') $data_private_path = $this->data_private_path; 1039 return $data_private_path.'/cache/'.$serverid.'.php'; 1040 } 1041 1042 function destroyCache() 1043 { 1044 $cachefile = $this->_GetCacheFile(); 1045 if (!file_exists($cachefile)) 1046 return false; 1047 $this->is_init = false; 1048 // destroy the cache lock file 1049 $cachefile_lock = $cachefile."_lock"; 1050 if (file_exists($cachefile_lock)) @unlink($cachefile_lock); 1051 // destroy the cache file 1052 return @unlink($cachefile); 1053 } 1054 1055 /** 1056 * Save the pfcConfig object into cache if it doesn't exists yet 1057 * else restore the old pfcConfig object 1058 */ 1059 function synchronizeWithCache() 1060 { 1061 $cachefile = $this->_GetCacheFile(); 1062 $cachefile_lock = $cachefile."_lock"; 1063 1064 if (file_exists($cachefile)) 1065 { 1066 // if a cache file exists, remove the lock file because config has been succesfully stored 1067 if (file_exists($cachefile_lock)) @unlink($cachefile_lock); 1068 1069 include $cachefile; 1070 foreach($pfc_conf as $key => $val) 1071 // the dynamics parameters must not be cached 1072 if (!in_array($key,$this->_dyn_params)) 1073 $this->$key = $val; 1074 1075 return true; // synchronized 1076 } 1077 else 1078 { 1079 if (file_exists($cachefile_lock)) 1080 { 1081 // delete too old lockfiles (more than 15 seconds) 1082 $locktime = filemtime($cachefile_lock); 1083 if ($locktime+15 < time()) 1084 unlink($cachefile_lock); 1085 else 1086 return false; // do nothing if the lock file exists 1087 } 1088 else 1089 @touch($cachefile_lock); // create the lockfile 1090 1091 if (!$this->isInit()) 1092 $this->init(); 1093 $errors =& $this->getErrors(); 1094 if (count($errors) == 0) 1095 { 1096 // save the validated config in cache 1097 $this->saveInCache(); 1098 } 1099 else 1100 @unlink($cachefile_lock); // destroy the lock file for the next attempt 1101 return false; // new cache created 1102 } 1103 } 1104 function saveInCache() 1105 { 1106 $cachefile = $this->_GetCacheFile(); 1107 $data = '<?php '; 1108 1109 $conf = get_object_vars($this); 1110 $keys = array_keys($conf); 1111 foreach($keys as $k) 1112 if (preg_match('/^_.*/',$k)) 1113 unset($conf[$k]); 1114 1115 // remove dynamic parameters 1116 foreach($this->_dyn_params as $k) 1117 unset($conf[$k]); 1118 1119 $data .= '$pfc_conf = '.var_export($conf,true).";\n"; 1120 $data .= '?>'; 1121 1122 file_put_contents($cachefile, $data/*serialize(get_object_vars($this))*/); 1123 } 1124 1125 function isDefaultFile($file) 1126 { 1127 $fexists1 = file_exists($this->theme_path."/default/".$file); 1128 $fexists2 = file_exists($this->theme_path."/".$this->theme."/".$file); 1129 return ($this->theme == "default" ? $fexists1 : !$fexists2); 1130 } 1131 1132 function getFilePathFromTheme($file) 1133 { 1134 if (file_exists($this->theme_path."/".$this->theme."/".$file)) 1135 return $this->theme_path."/".$this->theme."/".$file; 1136 else 1137 if (file_exists($this->theme_default_path."/default/".$file)) 1138 return $this->theme_default_path."/default/".$file; 1139 else 1140 { 1141 $this->destroyCache(); 1142 die(_pfc("Error: '%s' could not be found, please check your themepath '%s' and your theme '%s' are correct", $file, $this->theme_path, $this->theme)); 1143 } 1144 } 1145 1146 function getFileUrlFromTheme($file) 1147 { 1148 if (file_exists($this->theme_path.'/'.$this->theme.'/'.$file)) 1149 return $this->theme_url.'/'.$this->theme.'/'.$file; 1150 else 1151 if (file_exists($this->theme_default_path.'/default/'.$file)) 1152 return $this->theme_default_url.'/default/'.$file; 1153 else 1154 return 'notfound'; 1155 } 1156 1157 1158 function filterNickname($nickname) 1159 { 1160 $nickname = trim($nickname); 1161 require_once dirname(__FILE__)."/../lib/utf8/utf8_substr.php"; 1162 $nickname = (string)utf8_substr($nickname, 0, $this->max_nick_len); 1163 return $nickname; 1164 } 1165} 1166 1167?> 1168