diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..b89efd77 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,22 @@ +FROM mcr.microsoft.com/devcontainers/php:0-8.0 + +# Install MariaDB client +RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ + && apt-get install -y mariadb-client \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* + +# Install php-mysql driver +RUN docker-php-ext-install mysqli pdo pdo_mysql + +RUN [ ! -d /var/www/html/ona ] && ln -fs /workspace/ona/www /var/www/html/ona +RUN apache2ctl start + +# run php install/installcli.php and set 127.0.0.1 + +# [Optional] Uncomment this section to install additional OS packages. +# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ +# && apt-get -y install --no-install-recommends + +# [Optional] Uncomment this line to install global node packages. +# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 + diff --git a/.devcontainer/README b/.devcontainer/README new file mode 100644 index 00000000..e040247f --- /dev/null +++ b/.devcontainer/README @@ -0,0 +1,2 @@ +I'm not sure that I will continue with the .devcontainer testing. I will +leave it here for the time being. diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..2a373497 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,29 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/php-mariadb +{ + "name": "PHP & MariaDB", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // For use with PHP or Apache (e.g.php -S localhost:8080 or apache2ctl start) + "forwardPorts": [ + 8080, + 3306 + ], + "features": { + "ghcr.io/devcontainers-contrib/features/neofetch:1": {} + } + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "sudo chmod a+x \"$(pwd)\" && sudo rm -rf /var/www/html && sudo ln -s \"$(pwd)\" /var/www/html" + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..51df1442 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,36 @@ +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + + volumes: + - ../..:/workspaces:cached + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db + + # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + + db: + image: mariadb:10.4 + restart: unless-stopped + volumes: + - mariadb-data:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: mariadb + MYSQL_DATABASE: mariadb + MYSQL_USER: mariadb + MYSQL_PASSWORD: mariadb + + # Add "forwardPorts": ["3306"] to **devcontainer.json** to forward MariaDB locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + +volumes: + mariadb-data: diff --git a/.gitignore b/.gitignore index 6df4251e..dfecb448 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,13 @@ www/*.htm cfg_archive_local spool + +*.log + +.vagrant +.DS_Store + +# ignore vim swap files +*.swp + +.gitignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..dfed58cb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,59 @@ +# This Dockerfile is intended for development and testing purposes only. Not +# recommended for production use. +# +# First: Build an image with a specific version of Ubuntu and tag it as such. +# docker build --build-arg UBUNTU_VERSION=23.04 -t ona-dev:23.04 . +# +# Second: Start the container for general use. Point your browser to http://localhost/ona +# docker run -p 80:80 -it ona-dev:23.04 +# +# OR +# +# Start the container for development. Mount the current directory as a volume +# This will allow you to edit the files on your host and have them be hosted +# in the container +# docker run -p 80:80 -it -v $(pwd):/opt/ona ona-dev:23.04 +# +# This assumes you are in the directory you cloned the ONA repo into. +# Also, if you have already installed this prior, you may need to remove +# www/local/config/database_settings.conf.php to get the install to run again. + +ARG UBUNTU_VERSION=latest +FROM ubuntu:${UBUNTU_VERSION} + +LABEL description="OpenNetAdmin development and testing docker image" +LABEL Author="Matt Pascoe " + +ENV TZ=UTC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt-get update +RUN apt-get -y install git mariadb-server apache2 php-yaml php-gmp php-mysql libapache2-mod-php php-mbstring php-xml unzip vim sendemail jq curl && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN git -C /opt clone https://github.com/opennetadmin/ona.git -b develop + +ENV APACHE_RUN_USER www-data +ENV APACHE_RUN_GROUP www-data +ENV APACHE_LOG_DIR /var/log/apache2 + +RUN ln -sf /opt/ona/www /var/www/html/ona +RUN rm -f /var/www/html/index.html + +RUN touch /var/log/ona.log +RUN chmod 666 /var/log/ona.log + +RUN chown www-data /opt/ona/www/local/config + +# Start as mariadb or mysql depending on version of Ubuntu. +RUN service mariadb start || service mysql start + +RUN echo '/opt/ona' > /etc/onabase +RUN echo "\n\n\n"|php /opt/ona/install/installcli.php +RUN echo "ServerName ona-dev.localhost" > /etc/apache2/conf-enabled/servername.conf + +EXPOSE 80 + +# Since we are running mysql and apache, start them both. Also runs initial install. +CMD bash -c 'service mariadb start || service mysql start && echo "\n\n\n"|php /opt/ona/install/installcli.php && /usr/sbin/apache2ctl -D FOREGROUND' diff --git a/README.md b/README.md index a9114ac4..d2be22d5 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,10 @@ Thanks for your interest in OpenNetAdmin! --- Each host or subnet can be tracked via a centralized AJAX enabled web interface -that can help reduce errors. A full [CLI interface](https://github.com/opennetadmin/dcm) is available -as well to use for scripting and bulk work. We hope to provide a useful -Network Management application for managing your IP subnets and hosts. -Stop using spreadsheets to manage your network! Start doing proper IP +that can help reduce errors. A full [CLI interface](https://github.com/opennetadmin/dcm) is available +as well to use for scripting and bulk work. We hope to provide a useful +Network Management application for managing your IP subnets and hosts. +Stop using spreadsheets to manage your network! Start doing proper IP address management! ![desktop image](https://github.com/opennetadmin/ona/wiki/images/desktop.png) @@ -32,6 +32,55 @@ your web server to serve out `/opt/ona/www`. Open it in your web browser and ru Please refer to the [install page on the Github Wiki for more detail](https://github.com/opennetadmin/ona/wiki/Install) +DEVELOPMENT +----------- +You can interact with either Docker or Vagrant. Docker is is the preferred +method at this time. + +## Docker + +Once you have cloned the repo you can issue +The Dockerfile is intended for development and testing purposes only. It is not recommended for production use. + +First: Build an image with a specific version of Ubuntu and tag it as such. +``` +docker build --build-arg UBUNTU_VERSION=23.04 -t ona-dev:23.04 . +``` + +Second: Start the container for general use. Point your browser to http://localhost/ona +``` +docker run -p 80:80 -it ona-dev:23.04 +``` + +OR + +Start the container for development. Mount the current directory as a volume. This will allow you to edit the files on your host and have them be hosted in the container +``` +docker run -p 80:80 -it -v $(pwd):/opt/ona ona-dev:23.04 +``` + +This assumes you are in the directory you cloned the ONA repo into. +Also, if you have already installed this prior, you may need to remove `www/local/config/database_settings.conf.php` to get the install to run again. + + +## Vagrant + +Simply clone this repo and issue a vagrant up to get a basic working system to develop with. +You will need to have git and [vagrant](https://vagrantup.com) installed on your system + + git clone https://github.com/opennetadmin/ona.git + cd ona + vagrant up + +## Postman + +There is a postman collection in the `docs` directory that can be used to interact with the API. An environment file is also provided that can be used. Simply import the collection and environment into postman or use Newman to run the collection from the command line. + +A simple usage would be: +``` +cd /opt/ona +newman run docs/ONA-dcm.postman_collection.json -e docs/ONA-dcm-dev.postman_environment.json +``` CONTACT ------- diff --git a/VERSION b/VERSION index 7acc4058..e741d6db 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v18.1.1 +v19.0.0 diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 00000000..aac03996 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,84 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Allow user to pass in a different web port forward value. +# Use when you are running multiple vms on one system +PORTNUM = ENV["PORTNUM"] || "10000" + +Vagrant.configure("2") do |config| + config.vm.box = "ubuntu/jammy64" + + # Assign this VM to a bridged network, allowing you to connect directly to a + # network using the host's network device. This makes the VM appear as another + # physical device on your network. + # Uncomment the following if you want this VM to have its own IP + #config.vm.network :bridged + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:10000" will access port 80 on the guest machine. + # NOTE: This will enable public access to the opened port + config.vm.network "forwarded_port", guest: 80, host: PORTNUM , auto_correct: false + + # Set up our repo as a synced folder + config.vm.synced_folder ".", "/opt/ona" + + # The basic install script + $script = <<-SCRIPT +#------- Start provision -------- +PORTNUM=$1 + +# Tell apt to quit its whining +export DEBIAN_FRONTEND=noninteractive + +apt-get update +apt-get install -y \ + curl \ + apache2 \ + mariadb-server \ + php \ + php-mysql \ + php-mbstring \ + php-gmp \ + php-pear \ + libapache2-mod-php \ + libyaml-dev \ + libio-socket-ssl-perl + +# Link in our ona code +[ ! -d /var/www/html/ona ] && ln -fs /opt/ona/www /var/www/html/ona + +# Allow others to see apache logs (and probably other stuff) +#usermod -a -G adm www-data +#usermod -a -G adm vagrant + +# Set up application log file +if [ ! -f /var/log/ona.log ] +then + touch /var/log/ona.log + chmod 666 /var/log/ona.log +fi + +# restart apache so it picks up changes +systemctl restart apache2.service + +# Clean out any old configs +# Re-running the provisioner will wipe out any previous configs +rm -f /opt/ona/www/local/config/database_settings.inc.php + +# Run the CLI installer with all default options +echo "\n\n\n"|php /opt/ona/install/installcli.php + +echo " + + +Please point your browser to: http://localhost:${PORTNUM}/ona + +" +#------- End provision -------- + SCRIPT + + # Run our shell provisioner + config.vm.provision "shell", inline: $script, :args => [ PORTNUM ] + +end diff --git a/LICENSE b/docs/LICENSE similarity index 100% rename from LICENSE rename to docs/LICENSE diff --git a/docs/ONA-dcm-dev.postman_environment.json b/docs/ONA-dcm-dev.postman_environment.json new file mode 100644 index 00000000..6adae80e --- /dev/null +++ b/docs/ONA-dcm-dev.postman_environment.json @@ -0,0 +1,68 @@ +{ + "id": "1c834988-d66c-2969-ffb4-33ccbb1b32cb", + "name": "Dev", + "values": [ + { + "key": "URL", + "value": "http://127.0.0.1", + "type": "text", + "enabled": true + }, + { + "key": "DCM_URL", + "value": "{{URL}}/ona/dcm.php", + "type": "default", + "enabled": true + }, + { + "key": "format", + "value": "json", + "enabled": true + }, + { + "key": "username", + "value": "admin", + "type": "text", + "enabled": true + }, + { + "key": "password", + "value": "admin", + "type": "text", + "enabled": true + }, + { + "key": "netname", + "value": "LAN-EXAMPLE", + "type": "text", + "enabled": true + }, + { + "key": "netip", + "value": "1.1.1.0", + "type": "default", + "enabled": true + }, + { + "key": "netmask", + "value": "/24", + "type": "default", + "enabled": true + }, + { + "key": "domainname", + "value": "example.com", + "type": "text", + "enabled": true + }, + { + "key": "host", + "value": "host.{{domainname}}", + "type": "text", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2023-05-27T05:16:49.996Z", + "_postman_exported_using": "Postman/10.14.4" +} \ No newline at end of file diff --git a/docs/ONA-dcm.postman_collection.json b/docs/ONA-dcm.postman_collection.json new file mode 100644 index 00000000..023fe86a --- /dev/null +++ b/docs/ONA-dcm.postman_collection.json @@ -0,0 +1,1687 @@ +{ + "info": { + "_postman_id": "0b9185a6-168b-4130-afd7-16464ef4f42f", + "name": "ONA-dcm", + "description": "Attempt at some sort of testing in the current dcm.php based endpoints. This endpoint is NOT a REST endpoint. It behaves in poor ways but should be testable and consistent in its behavior.\n\nEven though these requests are represented as GET,POST,DEL type requests, those types do not actualy mean anything to the DCM.php endpoint. They are done this way more for clarity in the task than actual proper usage.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "2080494" + }, + "item": [ + { + "name": "Domains", + "item": [ + { + "name": "Add Domain", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Domain ADDED: newdomain.com\\n\";", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=domain_add&name=newdomain.com&refresh=1&retry=2&expiry=3&minimum=4&ttl=5&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "domain_add" + }, + { + "key": "name", + "value": "newdomain.com" + }, + { + "key": "refresh", + "value": "1" + }, + { + "key": "retry", + "value": "2" + }, + { + "key": "expiry", + "value": "3" + }, + { + "key": "minimum", + "value": "4" + }, + { + "key": "ttl", + "value": "5" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Modify Domain", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Domain UPDATED:.*: newdomain.com/.test(jsonData.module_exit_message);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=domain_modify&domain=newdomain.com&set_refresh=10&set_retry=20&set_expiry=30&set_minimum=40&set_ttl=50&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "domain_modify" + }, + { + "key": "domain", + "value": "newdomain.com" + }, + { + "key": "set_refresh", + "value": "10" + }, + { + "key": "set_retry", + "value": "20" + }, + { + "key": "set_expiry", + "value": "30" + }, + { + "key": "set_minimum", + "value": "40" + }, + { + "key": "set_ttl", + "value": "50" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Display Domain", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "if (responseCode.code === 200) {", + " var jsonData = JSON.parse(responseBody);", + " tests[\"ONA Status Code\"] = jsonData.module_exit_status === 0;", + "", + " tests[\"Found Name\"] = jsonData.name === \"newdomain.com\";", + " tests[\"Found refresh\"] = jsonData.refresh === \"10\";", + " tests[\"Found retry\"] = jsonData.retry === \"20\";", + " tests[\"Found expiry\"] = jsonData.expiry === \"30\";", + " tests[\"Found minimum\"] = jsonData.minimum === \"40\";", + " tests[\"Found ttl\"] = jsonData.default_ttl === \"50\";", + "", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "", + "type": "string" + }, + { + "key": "username", + "value": "", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{DCM_URL}}?module=domain_display&domain=newdomain.com&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "domain_display" + }, + { + "key": "domain", + "value": "newdomain.com" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Domain", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Domain DELETED: newdomain.com\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=domain_del&domain=newdomain.com&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "domain_del" + }, + { + "key": "domain", + "value": "newdomain.com" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Domain 1.in-addr.arpa", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Domain ADDED: 1.in-addr.arpa\\n\";", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=domain_add&name=1.in-addr.arpa&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "domain_add" + }, + { + "key": "name", + "value": "1.in-addr.arpa" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Locations", + "item": [ + { + "name": "Add Location for delete", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Location ADDED: DEL: deleteme\\n\";", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=location_add&reference=del&name=deleteme&format={{format}}&address=123 Main&city=Boise&state=ID&zip_code=90210", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "location_add" + }, + { + "key": "reference", + "value": "del" + }, + { + "key": "name", + "value": "deleteme" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "address", + "value": "123 Main" + }, + { + "key": "city", + "value": "Boise" + }, + { + "key": "state", + "value": "ID" + }, + { + "key": "zip_code", + "value": "90210" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Location", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Location DELETED: DEL (deleteme)\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=location_del&reference=DEL&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "location_del" + }, + { + "key": "reference", + "value": "DEL" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Location", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Location ADDED: BOI-CHANGE: Corporate Off\\n\";", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=location_add&reference=boi-change&name=Corporate Off&format={{format}}&address=123 Main&city=Boisee&state=IL&zip_code=90210", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "location_add" + }, + { + "key": "reference", + "value": "boi-change" + }, + { + "key": "name", + "value": "Corporate Off" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "address", + "value": "123 Main" + }, + { + "key": "city", + "value": "Boisee" + }, + { + "key": "state", + "value": "IL" + }, + { + "key": "zip_code", + "value": "90210" + } + ] + } + }, + "response": [] + }, + { + "name": "Modify Location", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Location UPDATED.*BOI-CHANGE/.test(jsonData.module_exit_message);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=location_modify&reference=BOI-CHANGE&set_reference=BOI&set_address=1234 Main St&format={{format}}&set_city=Boise&set_state=ID&set_zip_code=83706&set_name=Corporate Office", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "location_modify" + }, + { + "key": "reference", + "value": "BOI-CHANGE" + }, + { + "key": "set_reference", + "value": "BOI" + }, + { + "key": "set_address", + "value": "1234 Main St" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "set_city", + "value": "Boise" + }, + { + "key": "set_state", + "value": "ID" + }, + { + "key": "set_zip_code", + "value": "83706" + }, + { + "key": "set_name", + "value": "Corporate Office" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Subnets", + "item": [ + { + "name": "Add Subnet for delete", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Subnet ADDED: 3.3.3.0/24\\n\";", + "", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=subnet_add&name={{netname}} del&ip=3.3.3.0&netmask={{netmask}}&type=LAN&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "subnet_add" + }, + { + "key": "name", + "value": "{{netname}} del" + }, + { + "key": "ip", + "value": "3.3.3.0" + }, + { + "key": "netmask", + "value": "{{netmask}}" + }, + { + "key": "type", + "value": "LAN" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete single subnet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Subnet DELETED: LAN-EXAMPLE-DEL IP: 3.3.3.0/24\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=subnet_del&subnet=3.3.3.0&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "subnet_del" + }, + { + "key": "subnet", + "value": "3.3.3.0" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Subnet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Subnet ADDED: 2.2.2.0/24\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=subnet_add&name={{netname}}_CHANGE&ip=2.2.2.0&netmask={{netmask}}&type=LAN&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "subnet_add" + }, + { + "key": "name", + "value": "{{netname}}_CHANGE" + }, + { + "key": "ip", + "value": "2.2.2.0" + }, + { + "key": "netmask", + "value": "{{netmask}}" + }, + { + "key": "type", + "value": "LAN" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Modify Subnet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Subnet UPDATED:/.test(jsonData.module_exit_message);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=subnet_modify&set_name={{netname}}&set_ip={{netip}}&set_type=VLAN&format={{format}}&subnet={{netname}}_CHANGE", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "subnet_modify" + }, + { + "key": "set_name", + "value": "{{netname}}" + }, + { + "key": "set_ip", + "value": "{{netip}}" + }, + { + "key": "set_type", + "value": "VLAN" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "subnet", + "value": "{{netname}}_CHANGE" + } + ] + } + }, + "response": [] + }, + { + "name": "Display Subnet", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "if (responseCode.code === 200) {", + " var jsonData = JSON.parse(responseBody);", + " tests[\"ONA Status Code\"] = jsonData.module_exit_status === 0;", + "", + " tests[\"Found Name\"] = jsonData.name === \"LAN-EXAMPLE\";", + " tests[\"Found IP\"] = jsonData.ip_addr === \"16843008\";", + " tests[\"Found Type\"] = jsonData.subnet_type_name === \"VLAN\";", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "", + "type": "string" + }, + { + "key": "username", + "value": "", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{DCM_URL}}?module=subnet_display&subnet={{netname}}&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "subnet_display" + }, + { + "key": "subnet", + "value": "{{netname}}" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Hosts", + "item": [ + { + "name": "Add Host for delete", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Host ADDED: delete.example.com/.test(jsonData.module_exit_message);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=host_add&host=delete.{{domainname}}&ip=1.1.1.100&type=1&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "host_add" + }, + { + "key": "host", + "value": "delete.{{domainname}}" + }, + { + "key": "ip", + "value": "1.1.1.100" + }, + { + "key": "type", + "value": "1" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete host", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Host DELETED: delete.example.com/.test(jsonData.module_exit_message);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=host_del&host=delete.{{domainname}}&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "host_del" + }, + { + "key": "host", + "value": "delete.{{domainname}}" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + }, + { + "name": "Add Host", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Host ADDED:/.test(jsonData.module_exit_message);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=host_add&host={{host}}&ip=1.1.1.1&type=1&format={{format}}&location=BOI", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "host_add" + }, + { + "key": "host", + "value": "{{host}}" + }, + { + "key": "ip", + "value": "1.1.1.1" + }, + { + "key": "type", + "value": "1" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "location", + "value": "BOI" + } + ] + } + }, + "response": [] + }, + { + "name": "Modify Host", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Host UPDATED:/.test(jsonData.module_exit_message);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=host_modify&set_notes=updated notes&set_type=2&format={{format}}&host={{host}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "host_modify" + }, + { + "key": "set_notes", + "value": "updated notes" + }, + { + "key": "set_type", + "value": "2" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "host", + "value": "{{host}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Display Host", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "if (responseCode.code === 200) {", + " var jsonData = JSON.parse(responseBody);", + " tests[\"ONA Status Code\"] = jsonData.module_exit_status === 0;", + "", + " tests[\"Found Name\"] = jsonData.name === \"host\";", + " tests[\"Found FQDN\"] = jsonData.fqdn === \"host.example.com\";", + " tests[\"Found Notes\"] = jsonData.notes === \"updated notes\";", + " tests[\"Found IP\"] = jsonData.interfaces[1].ip_addr_text === \"1.1.1.1\";", + " tests[\"Found Location\"] = jsonData.location.reference === \"BOI\";", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "", + "type": "string" + }, + { + "key": "username", + "value": "", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{DCM_URL}}?module=host_display&host={{host}}&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "host_display" + }, + { + "key": "host", + "value": "{{host}}" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Interfaces", + "item": [ + { + "name": "Add Interface", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Interface ADDED: 1.1.1.100\\n\";", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=interface_add&host={{host}}&format={{format}}&ip=1.1.1.100&name=eth1&laa=true", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "interface_add" + }, + { + "key": "host", + "value": "{{host}}" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "ip", + "value": "1.1.1.100" + }, + { + "key": "name", + "value": "eth1" + }, + { + "key": "laa", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "Modify Interface", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "", + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Interface UPDATED:.*: 1.1.1.200/.test(jsonData.module_exit_message);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "url": { + "raw": "{{DCM_URL}}?module=interface_modify&interface=1.1.1.100&set_ip=1.1.1.200&set_name=eth2&set_description=int description&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "interface_modify" + }, + { + "key": "interface", + "value": "1.1.1.100" + }, + { + "key": "set_ip", + "value": "1.1.1.200" + }, + { + "key": "set_name", + "value": "eth2" + }, + { + "key": "set_description", + "value": "int description" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Display Interface", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "if (responseCode.code === 200) {", + " var jsonData = JSON.parse(responseBody);", + " tests[\"ONA Status Code\"] = jsonData.module_exit_status === 0;", + "", + " tests[\"Found Name\"] = jsonData.name === \"eth2\";", + " tests[\"Found IP\"] = jsonData.ip_addr_text === \"1.1.1.200\";", + " tests[\"Found Desc\"] = jsonData.description === \"int description\";", + "", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "", + "type": "string" + }, + { + "key": "username", + "value": "", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{DCM_URL}}?module=interface_display&interface=1.1.1.200&format={{format}}", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "interface_display" + }, + { + "key": "interface", + "value": "1.1.1.200" + }, + { + "key": "format", + "value": "{{format}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Interface", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = /Interface DELETED: 1.1.1.200/.test(jsonData.module_exit_message);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=interface_del&interface=1.1.1.200&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "interface_del" + }, + { + "key": "interface", + "value": "1.1.1.200" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Final cleanup", + "item": [ + { + "name": "Delete Subnet LAN-EXAMPLE", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Subnet DELETED: LAN-EXAMPLE IP: 1.1.1.0/24\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=subnet_del&subnet={{netname}}&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "subnet_del" + }, + { + "key": "subnet", + "value": "{{netname}}" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Location BOI", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Location DELETED: BOI (Corporate Office)\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=location_del&reference=BOI&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "location_del" + }, + { + "key": "reference", + "value": "BOI" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Domain 1.in-addr.arpa", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"ONA return code\"] = jsonData.module_exit_status === 0;", + "tests[\"Status mesage output\"] = jsonData.module_exit_message === \"INFO => Domain DELETED: 1.in-addr.arpa\\n\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{DCM_URL}}?module=domain_del&domain=1.in-addr.arpa&format={{format}}&commit=yes", + "host": [ + "{{DCM_URL}}" + ], + "query": [ + { + "key": "module", + "value": "domain_del" + }, + { + "key": "domain", + "value": "1.in-addr.arpa" + }, + { + "key": "format", + "value": "{{format}}" + }, + { + "key": "commit", + "value": "yes" + } + ] + } + }, + "response": [] + } + ] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "{{password}}", + "type": "string" + }, + { + "key": "username", + "value": "{{username}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] +} \ No newline at end of file diff --git a/install/13-to-14.xml b/install/13-to-14.xml new file mode 100644 index 00000000..d30f7f59 --- /dev/null +++ b/install/13-to-14.xml @@ -0,0 +1,9 @@ + + + + INSERT INTO dcm_module_list (name,description,file) VALUES ('config_del', 'Delete a configuration text from the database', 'ona/configuration.inc.php') on duplicate key update name='config_del' + INSERT INTO dcm_module_list (name,description,file) VALUES ('config_del_all', 'Delete all configurations from a host', 'ona/configuration.inc.php') on duplicate key update name='config_del_all' + + + + diff --git a/install/14-to-15.xml b/install/14-to-15.xml new file mode 100644 index 00000000..0d510ebd --- /dev/null +++ b/install/14-to-15.xml @@ -0,0 +1,9 @@ + + + + INSERT INTO `auth_groups` VALUES (17,'Default','Default user group',1) on duplicate key update name='Default' + INSERT INTO `auth_groups` VALUES (18,'Admin','Admin group',99) on duplicate key update name='Admin' + + + + diff --git a/install/PRE-v08.02.18-to-08.02.18.sql b/install/PRE-v08.02.18-to-08.02.18.sql deleted file mode 100644 index 9605e334..00000000 --- a/install/PRE-v08.02.18-to-08.02.18.sql +++ /dev/null @@ -1,67 +0,0 @@ --- Use this file to upgrade from older versions --- It has not been fully tested and will probably break! - --- --- Table structure for table `sys_config` --- - -CREATE TABLE `sys_config` ( - `name` varchar(128) NOT NULL, - `value` varchar(256) NOT NULL, - `description` varchar(512) NOT NULL, - PRIMARY KEY (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - --- --- Table structure for table `custom_attribute_types` --- - -CREATE TABLE `custom_attribute_types` ( - `id` int(10) unsigned NOT NULL, - `name` varchar(63) NOT NULL, - `notes` varchar(127) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT=''; - --- --- Table structure for table `custom_attributes` --- - -CREATE TABLE `custom_attributes` ( - `id` int(10) unsigned NOT NULL auto_increment, - `table_name_ref` varchar(40) NOT NULL COMMENT 'the name of the table conaining the associated record', - `table_id_ref` int(10) unsigned NOT NULL default '0' COMMENT 'the id within the table_name_ref table to associate with', - `custom_attribute_type_id` int(10) NOT NULL, - `attribute` longtext NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT=''; - - --- --- Dumping data for table `sys_config` --- - -INSERT INTO `sys_config` (`name`, `value`, `description`) VALUES -('cookie_life', '172800', 'Sets the length of the session cookie. It is in seconds'), -('date_format', 'M jS, g:ia', 'PHP text format for date values'), -('db', '1', 'Log to a sql log (not sure if this is working)'), -('debug', '0', 'Debug output level, the higher the number the more it logs'), -('dns_admin_email', 'hostmaster', 'per RFC 2412, defaults to hostmaster within the domain origin'), -('dns_defaultdomain', 'example.com', 'Default DNS domain name'), -('dns_default_ttl', '86400', 'this is the value of $TTL for the zone, used as the default value'), -('dns_expiry', '3600', 'DNS expire time used in SOA'), -('dns_minimum', '3600', 'DNS minimum TTL time, used as the negative caching value per RFC 2308'), -('dns_primary_master', '', 'The fqdn of your default primary master DNS server, leave blank if not required'), -('dns_refresh', '86400', 'DNS refresh time used in SOA'), -('dns_retry', '3600', 'DNS retry time used in SOA'), -('logfile', '/var/log/ona.log', 'Local filesystem path to log messages'), -('search_results_per_page', '10', 'Sets the amount of rows per page in list items'), -('stdout', '0', 'Flag to allow logging via STDOUT.. This is extreme debugging, not recomended.'), -('suggest_max_results', '10', 'Limits the amount of rows returned by queries. (test impact of changing this first)'), -('syslog', '0', 'Log via syslog, only works if debug is set to 0'), -('version', '', 'Tracks current installed version, used to detect when upgrades should be done.'), -('upgrade_index', '1', 'Tracks current upgrade index, used to process database upgrades in order.'); - - -INSERT INTO `dcm_module_list` VALUES (53, 'dhcp_failover_group_add', 'Add servers to a DHCP failover group', 'ona/dhcp_failover.inc.php'),(54, 'dhcp_failover_group_modify', 'Modify a DHCP failover group', 'ona/dhcp_failover.inc.php'),(55, 'dhcp_failover_group_display', 'Display a DHCP failover group', 'ona/dhcp_failover.inc.php'); - diff --git a/install/README b/install/README index 3b00434c..28320e79 100644 --- a/install/README +++ b/install/README @@ -1,8 +1,9 @@ This directory contains the information needed to perform an initial setup of the system. README: This text -ona-data.sql: Initial data required for the system -ona-tables.sql: Initial database tables -install.php: The installation script ran at first startup -x-to-x.sql: Various SQL upgrade scripts -x-to-x.php: Various PHP upgrade scripts +ona-example-data.sql: Example set of data used for demo site +ona-data.sql: Initial data required for the system +ona-tables.sql: Initial database tables +install.php: The installation script ran at first startup +x-to-x.sql: Various SQL upgrade scripts +x-to-x.php: Various PHP upgrade scripts diff --git a/install/install.php b/install/install.php index 7bf5649b..07e7745b 100644 --- a/install/install.php +++ b/install/install.php @@ -14,13 +14,15 @@ $runinstall = $onabase.'/www/local/config/run_install'; $xmlfile_tables = $base.'/ona-table_schema.xml'; $xmlfile_data = $base.'/ona-data.xml'; -$license_text = file_get_contents($base.'/../LICENSE'); +$license_text = file_get_contents($base.'/../docs/LICENSE'); $new_ver = trim(file_get_contents($onabase.'/VERSION')); $curr_ver = ''; // Get some pre-requisite information -$phpversion = phpversion() > '5.0' ? 'Yes' : 'No'; +$phpversion = phpversion() > '7.0' ? 'Yes' : 'No'; $hasgmp = function_exists( 'gmp_init' ) ? 'Yes' : 'No'; +$hasxml = function_exists( 'xml_parse' ) ? 'Yes' : 'No'; +$hasjson = function_exists( 'json_decode' ) ? 'Yes' : 'No'; $hasmysql = function_exists( 'mysqli_connect' ) ? 'Yes' : 'Recommended'; $hasmbstring = function_exists( 'mb_internal_encoding' ) ? 'Yes' : 'Recommended'; $dbconfwrite = @is_writable($onabase.'/www/local/config/') ? 'Yes' : 'No'; @@ -44,17 +46,22 @@
- + + +
Prerequisite checks
PHP version > 5.0:{$phpversion}
PHP version > 7.0:{$phpversion}
PHP mysqli support:{$hasmysql}
Has GMP support:{$hasgmp}
Has mbstring support:{$hasmbstring}
Has XML support:{$hasxml}
Has JSON support:{$hasjson}
{$onabase}/www/local/config dir writable by '{$_ENV['APACHE_RUN_USER']}':{$dbconfwrite}
EOL; // Initial text for the greeting div -$greet_txt = "It looks as though this is your first time running OpenNetAdmin. Please answer a few questions and we'll initialize the system for you. We've pre-populated some of the fields with suggested values. If the database you specify below already exists, it will be overwritten entirely."; +$greet_txt = "It looks as though this is your first time running OpenNetAdmin. Please answer a few questions and we'll initialize the system for you. We've pre-populated some of the fields with suggested values. If the database you specify below already exists, it will be overwritten entirely. +

+If the web based install fails to connect as the Database Admin user, you may need to execute the command line installer using 'php {$base}/installcli.php' as the root user. +"; $upgrademain = ''; @@ -246,8 +253,8 @@ $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($xmlfile_tables); - // Execute the SQL on the database - //$text .= "
".$schema->PrintSQL('TEXT')."
"; + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-upgrade-tables.sql', $schema->PrintSQL('TEXT')); if ($schema->ExecuteSchema( $sql ) == 2) { $text .= " [{$cname}/{$cdbs['db_host']}] Upgrading tables within database '{$cdbs['db_database']}'.
"; printmsg("INFO => [{$cname}/{$cdbs['db_host']}] Upgrading tables within database: {$cdbs['db_database']}",0); @@ -286,6 +293,8 @@ $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($upgrade_xmlfile); + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-upgrade-data.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= " [{$cname}/{$cdbs['db_host']}] Processed XML update file.
"; @@ -453,6 +462,8 @@ $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($xmlfile_tables); + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-newinstall-tables.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= " Creating and updating tables within database '{$database_name}'.
"; @@ -468,7 +479,8 @@ $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($xmlfile_data); - //$text .= "
".$schema->PrintSQL('TEXT')."
"; + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-newinstall-data.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= " Loaded tables with default data.
"; @@ -484,10 +496,10 @@ // Run the query if ($status == 0) { - // it is likely that this method here is mysql only? - if(@$db->Execute("GRANT ALL ON {$database_name}.* TO '{$sys_login}'@'localhost' IDENTIFIED BY '{$sys_passwd}'")) { - @$db->Execute("GRANT ALL ON {$database_name}.* TO '{$sys_login}'@'%' IDENTIFIED BY '{$sys_passwd}'"); - @$db->Execute("GRANT ALL ON {$database_name}.* TO '{$sys_login}'@'{$database_host}' IDENTIFIED BY '{$sys_passwd}'"); + if( $db->Execute("CREATE USER '{$sys_login}'@'localhost' IDENTIFIED BY '{$sys_passwd}'")) { + $db->Execute("CREATE USER '{$sys_login}'@'{$database_host}' IDENTIFIED BY '{$sys_passwd}'"); + $db->Execute("GRANT ALL privileges ON {$database_name}.* TO '{$sys_login}'@'localhost' "); + $db->Execute("GRANT ALL privileges ON {$database_name}.* TO '{$sys_login}'@'{$database_host}' "); @$db->Execute("FLUSH PRIVILEGES"); $text .= " Created system user '{$sys_login}'.
"; printmsg("INFO => Created new DB user: {$sys_login}",0); @@ -654,11 +666,27 @@ text-align: left; width:500px; } + #alert-banner { + background-color: #FFDBFF; + padding: 5px; + border: 1px solid; + text-align: left; + width:500px; + } +
OpenNetAdmin Install
+ +
+
+
ALERT
+It is advised to run the install process from the CLI at this time due to changes in database security models. Use this web installer at your own risk.
+
+Please execute "php /opt/ona/install/installcli.php" as root.
+
EOL; diff --git a/install/installcli.php b/install/installcli.php index 292a74e1..984649ed 100644 --- a/install/installcli.php +++ b/install/installcli.php @@ -26,6 +26,9 @@ /* Defaults for some user definable options normally in sys_config table */ "debug" => "2", "logfile" => "/var/log/ona.log", + "syslog" => "0", + "stdout" => "0", + "log_to_db" => "0", ); @@ -33,9 +36,6 @@ // any $conf settings used in this "require" should not be user adjusted in the sys_config table require_once("{$include}/functions_general.inc.php"); -// Include the basic database functions -#require_once("{$include}/functions_db.inc.php"); - // Include the localized Database settings $dbconffile = "{$onabase}/www/local/config/database_settings.inc.php"; if (file_exists($dbconffile)) { @@ -50,15 +50,6 @@ # exit; } -#// If it does, run the install process. -#if (file_exists($base.'/local/config/run_install') or @$runinstaller or @$install_submit == 'Y') { -# // Process the install script -# require_once($base.'/../install/install.php'); -# exit; -#} - - - @@ -92,7 +83,7 @@ echo "ONA is licensed under GPL v2.0.\n"; $showlicense = promptUser("Would you like to view license? [y/N] ", 'n'); if ($showlicense == 'y') { - system("more -80 {$base}/../LICENSE"); + system("more -80 {$base}/../docs/LICENSE"); promptUser("[Press Enter To Continue]"); } @@ -105,6 +96,10 @@ new_install(); } + // Print out the text to the end user + echo "\n"; + echo $text; + exit; } @@ -120,11 +115,12 @@ function check_requirements() { system('clear'); // Get some pre-requisite information - $phpversion = phpversion() > '5.0' ? 'PASS' : 'FAIL'; + $phpversion = phpversion() > '7.0' ? 'PASS' : 'FAIL'; $hasgmp = function_exists( 'gmp_init' ) ? 'PASS' : 'FAIL'; //echo function_exists( 'gmp_init' ) ? '' : 'PHP GMP module is missing.'; $hasmysql = function_exists( 'mysqli_connect' ) ? 'PASS' : 'FAIL'; $hasxml = function_exists( 'xml_parser_create' ) ? 'PASS' : 'FAIL'; + $hasjson = function_exists( 'json_decode' ) ? 'PASS' : 'FAIL'; $hasmbstring = function_exists( 'mb_internal_encoding' ) ? 'PASS' : 'FAIL'; $dbconfwrite = @is_writable($onabase.'/www/local/config/') ? 'PASS' : 'FAIL'; $logfilewrite = @is_writable($conf['logfile']) ? 'PASS' : 'FAIL'; @@ -133,13 +129,14 @@ function check_requirements() { CHECKING PREREQUISITES... - PHP version greater than 5.0: $phpversion + PHP version greater than 7.0: $phpversion PHP GMP module: $hasgmp PHP XML module: $hasxml + PHP JSON module: $hasjson PHP mysqli function: $hasmysql PHP mbstring function: $hasmbstring $onabase/www/local/config dir writable: $dbconfwrite - {$conf['logfile']} writable: $logfilewrite + {$conf['logfile']} writable: $logfilewrite EOL; } @@ -150,7 +147,9 @@ function check_requirements() { function upgrade() { echo "\n\n"; - global $new_ver,$text,$xmlfile_data,$xmlfile_tables,$dbconffile; + global $new_ver,$text,$xmlfile_data,$xmlfile_tables,$dbconffile,$base,$status; + $upgrade = 'N'; + $levelinfo = ''; // If they already have a dbconffile, assume that we are doing and upgrade if (@file_exists($dbconffile)) { @@ -197,7 +196,7 @@ function upgrade() { @$db->Close(); - $text .= "{$cname} {$cdbs['db_type']} {$cdbs['db_host']} {$cdbs['db_database']} {$curr_ver} {$levelinfo}\n"; + $text .= "{$cname} {$cdbs['db_type']} {$cdbs['db_host']} {$cdbs['db_database']} {$curr_ver} {$levelinfo}\n"; } } @@ -209,7 +208,7 @@ function upgrade() { $text = ''; } else { $text .= <<ErrorMsg()."\n"; } else { $db->Close(); - if ($db->NConnect( $database_host, $cdbs['db_login'], $cdbs['db_passwd'], $cdbs['db_database'])) { + if ($db->NConnect( $cdbs['db_host'], $cdbs['db_login'], $cdbs['db_passwd'], $cdbs['db_database'])) { // Get the current upgrade index if there is one. @@ -252,8 +251,8 @@ function upgrade() { $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($xmlfile_tables); - // Uncomment the following to display the raw SQL - #$text .= "----------\n".$schema->PrintSQL('TEXT')."\n---------\n"; + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-upgrade-tables.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= "[{$cname}/{$cdbs['db_host']}] Upgrading tables within database '{$cdbs['db_database']}'.\n"; @@ -293,6 +292,8 @@ function upgrade() { $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($upgrade_xmlfile); + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-upgrade-data.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= "[{$cname}/{$cdbs['db_host']}] Processed XML update file.\n"; @@ -345,25 +346,6 @@ function upgrade() { } - // If we still have the old reference to db_context in our config, upgrade it - if (is_array($db_context)) { - // set default db name to uppercase - $ona_contexts['DEFAULT'] = $ona_contexts['default'];unset($ona_contexts['default']); - - // Open the database config and write the contents to it. - if (!$fh = @fopen($dbconffile, 'w')) { - $status++; - $text .= " Failed to open config file for writing: '{$dbconffile}'.
"; - printmsg("ERROR => Failed to open config file for writing: '{$dbconffile}'.",0); - } - else { - fwrite($fh, ""); - fclose($fh); - $text .= "Upgraded database connection config file to new format.\n"; - } - } - - if($status == 0) { $text .= $script_text; $text .= "Upgrade complete, you may start using OpenNetAdmin! Enjoy!\n"; @@ -377,8 +359,6 @@ function upgrade() { } else { $text .= "There was a fatal error. Upgrade may be incomplete. Fix the issue and try again\n"; } - - echo $text."\n"; } @@ -392,7 +372,7 @@ function upgrade() { function new_install() { echo "\n\n"; - global $new_ver,$text,$xmlfile_data,$xmlfile_tables,$dbconffile; + global $new_ver,$text,$xmlfile_data,$xmlfile_tables,$dbconffile,$status; // Gather info $adotype = 'mysqli'; @@ -470,6 +450,8 @@ function new_install() { $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($xmlfile_tables); + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-newinstall-tables.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= "Creating and updating tables within database '{$database_name}'.\n"; @@ -485,8 +467,8 @@ function new_install() { $schema = new adoSchema( $db ); // Build the SQL array from the schema XML file $sql = $schema->ParseSchema($xmlfile_data); - // Uncomment the following to display the raw SQL - #$text .= "----------\n".$schema->PrintSQL('TEXT')."\n---------\n"; + // Save a copy of current sqlstatement + file_put_contents('/tmp/ona-newinstall-data.sql', $schema->PrintSQL('TEXT')); // Execute the SQL on the database if ($schema->ExecuteSchema( $sql ) == 2) { $text .= "Loaded tables with default data.\n"; @@ -498,14 +480,13 @@ function new_install() { } } - // Add the system user to the database - // Run the query + // Add the system user to the database + // Run the query if ($status == 0) { - - // it is likely that this method here is mysql only? - if($db->Execute("GRANT ALL ON {$database_name}.* TO '{$sys_login}'@'localhost' IDENTIFIED BY '{$sys_passwd}'")) { - $db->Execute("GRANT ALL ON {$database_name}.* TO '{$sys_login}'@'%' IDENTIFIED BY '{$sys_passwd}'"); - $db->Execute("GRANT ALL ON {$database_name}.* TO '{$sys_login}'@'{$database_host}' IDENTIFIED BY '{$sys_passwd}'"); + if( $db->Execute("CREATE USER '{$sys_login}'@'localhost' IDENTIFIED BY '{$sys_passwd}'")) { + $db->Execute("CREATE USER '{$sys_login}'@'{$database_host}' IDENTIFIED BY '{$sys_passwd}'"); + $db->Execute("GRANT ALL privileges ON {$database_name}.* TO '{$sys_login}'@'localhost' "); + $db->Execute("GRANT ALL privileges ON {$database_name}.* TO '{$sys_login}'@'{$database_host}' "); $db->Execute("FLUSH PRIVILEGES"); $text .= "Created system user '{$sys_login}'.\n"; printmsg("INFO => Created new DB user: {$sys_login}",0); @@ -519,11 +500,12 @@ function new_install() { // add the default domain to the system // This is a manual add with hard coded values for timers. + $ctime=date('Y-m-j G:i:s',time()); $xmldefdomain = << - INSERT INTO domains (id,name,admin_email,default_ttl,refresh,retry,expiry,minimum,parent_id,serial,primary_master) VALUES (1,'{$default_domain}','hostmaster', 86400, 86400, 3600, 3600, 3600,0,0,0) + INSERT INTO domains (id,name,admin_email,default_ttl,refresh,retry,expiry,minimum,parent_id,serial,primary_master,ctime) VALUES (1,'{$default_domain}','hostmaster', 86400, 86400, 3600, 3600, 3600,0,0,0,'{$ctime}') UPDATE sys_config SET value='{$default_domain}' WHERE name like 'dns_defaultdomain' @@ -581,7 +563,7 @@ function new_install() { $text .= "Please remove '{$runinstall}' manually.\n"; } } - $text .= "You can now go the following URL in your browser: ".parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH)."' using OpenNetAdmin!\nYou can log in as 'admin' with a password of 'admin'\nEnjoy!"; + $text .= "You can now go the URL in your browser for this server.\nYou can log in as 'admin' with a password of 'admin'\nEnjoy!\n"; } // Close the database connection @@ -593,9 +575,6 @@ function new_install() { -// Print out the text to the end user -echo $text; - if ($upgrademain != '') { @@ -616,7 +595,7 @@ function new_install() { //# Or if return pressed returns a default if used e.g usage //# $name = promptUser("Enter your name"); //# $serverName = promptUser("Enter your server name", "localhost"); -//# Note: Returned value requires validation +//# Note: Returned value requires validation // from http://wiki.uniformserver.com/index.php/PHP_CLI:_User_Input //#....................................................................... function promptUser($promptStr,$defaultVal=false){; @@ -626,7 +605,7 @@ function promptUser($promptStr,$defaultVal=false){; } else { // No default set echo $promptStr. ": "; // print prompt only - } + } $name = chop(fgets(STDIN)); // Read input. Remove CR if(empty($name)) { // No value. Enter was pressed return $defaultVal; // return default diff --git a/install/ona-data.xml b/install/ona-data.xml index c7b5eac6..2afd2041 100644 --- a/install/ona-data.xml +++ b/install/ona-data.xml @@ -44,6 +44,8 @@ ('block_del','Delete an ip block','ona/block.inc.php'), ('block_modify','Modify ip blocks','ona/block.inc.php'), ('config_add','Adds a configuration to the database','ona/configuration.inc.php'), +('config_del','Delete a configuration text from the database','ona/configuration.inc.php'), +('config_del_all','Delete all configurations from a host ','ona/configuration.inc.php'), ('config_chksum','Displays the chksum of a config record from the database','ona/configuration.inc.php'), ('config_display','Displays a config record from the database','ona/configuration.inc.php'), ('dhcp_server_add','Add a DHCP server to subnet relationship','ona/dhcp_server.inc.php'), @@ -106,7 +108,7 @@ INSERT INTO `subnet_types` VALUES (1,'loopback','Loopback','Loopback Interfaces (mostly for routers)'),(2,'','WAN',''),(7,'','VLAN',''),(10,'p2p','Point-to-Point',''),(11,'','VPN',''),(12,'','Wireless LAN',''),(13,'lan','LAN','Simple LAN'); -INSERT INTO `groups` VALUES (17,'Default','Default user group',1),(18,'Admin','Admin group',99); +INSERT INTO `auth_groups` VALUES (17,'Default','Default user group',1),(18,'Admin','Admin group',99); INSERT INTO `group_assignments` VALUES (1,17,1),(2,18,2); @@ -134,7 +136,7 @@ ('suggest_max_results', '10', 'Limits the amount of rows returned by queries. (test impact of changing this first)', '', '', 1, 0), ('syslog', '0', 'Log via syslog, only works if debug is set to 0', '', '', 0, 0), ('version', 'not-set', 'Tracks current installed version, used to detect when upgrades should be done.', '', '', 0, 0), -('upgrade_index', '13', 'Tracks current upgrade index, used to perform database upgrades.', '', '', 0, 0); +('upgrade_index', '15', 'Tracks current upgrade index, used to perform database upgrades.', '', '', 0, 0); INSERT INTO `users` VALUES (1,'guest','098f6bcd4621d373cade4e832627b4f6',0,'2007-10-30 02:55:37','2007-12-02 23:44:21'),(2,'admin','21232f297a57a5a743894a0e4a801fc3',0,'2007-10-30 03:00:17','2007-12-02 22:10:26'); diff --git a/install/ona-example-data.sql b/install/ona-example-data.sql new file mode 100644 index 00000000..c8430143 --- /dev/null +++ b/install/ona-example-data.sql @@ -0,0 +1,412 @@ +-- MySQL dump 10.13 Distrib 5.7.20, for Linux (x86_64) +-- +-- Host: localhost Database: ona_default +-- ------------------------------------------------------ +-- Server version 5.7.20-0ubuntu0.16.04.1 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Dumping data for table `blocks` +-- + +LOCK TABLES `blocks` WRITE; +/*!40000 ALTER TABLE `blocks` DISABLE KEYS */; +INSERT INTO `blocks` (`id`, `ip_addr_start`, `ip_addr_end`, `name`, `notes`) VALUES (4,3232235520,3233480703,'ALL-CORP-LANS','Class B for Corp'),(5,3232235796,3232235806,'SERVER-RANGE','Put servers here'),(6,3232235781,3232235785,'LAN-EXAMPLE-RESERVED','example reserved space'); +/*!40000 ALTER TABLE `blocks` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `configuration_types` +-- + +LOCK TABLES `configuration_types` WRITE; +/*!40000 ALTER TABLE `configuration_types` DISABLE KEYS */; +INSERT INTO `configuration_types` (`id`, `name`) VALUES (1,'IOS_CONFIG'),(2,'IOS_VERSION'),(3,'NS_CONFIG'),(4,'NS_VERSION'),(5,'UCS_CONFIG'),(6,'UCS_VERSION'); +/*!40000 ALTER TABLE `configuration_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `configurations` +-- + +LOCK TABLES `configurations` WRITE; +/*!40000 ALTER TABLE `configurations` DISABLE KEYS */; +INSERT INTO `configurations` (`id`, `configuration_type_id`, `host_id`, `md5_checksum`, `config_body`, `ctime`) VALUES (1,1,22,'0c01d6431707f18fa514786ee66c6ca1','service timestamps debug uptime\nservice timestamps log uptime\nno service password-encryption\n!\nhostname router\n!\n!\nip subnet-zero\nip cef\n!\n!\n!\nip ssh time-out 120\nip ssh authentication-retries 3\n!\n!\ninterface Ethernet0/0\n description LAN-EXAMPLE\n ip address 192.168.1.1 255.255.255.0\n!\ninterface Ethernet0/1\n description CORP-DMZ\n ip address 192.168.2.1 255.255.255.0\n!\ninterface Ethernet1/0\n no ip address\n shutdown\n!\ninterface Ethernet1/1\n no ip address\n shutdown\n!\ninterface Ethernet1/2\n no ip address\n shutdown\n!\nrouter eigrp 60\n network 192.168.0.0 0.0.255.255\n auto-summary\n no eigrp log-neighbor-changes\n!\nip classless\nip route 0.0.0.0 0.0.0.0 14.38.1.1\nip http server\n!\n!\nline con 0\n exec-timeout 0 0\nline aux 0\nline vty 0 4\n!\nend\n','2018-01-06 22:02:13'),(2,1,22,'71f65ba78cd70e6c46e04112f6acc584','service timestamps debug uptime\nservice timestamps log uptime\nno service password-encryption\n!\nhostname router\n!\n!\nip subnet-zero\nip cef\n!\n!\n!\nip ssh time-out 120\nip ssh authentication-retries 3\n!\n!\ninterface Ethernet0/0\n description LAN-EXAMPLE\n ip address 192.168.1.1 255.255.255.0\n!\ninterface Ethernet0/1\n description CORP-DMZ\n ip address 192.168.2.1 255.255.255.0\n!\ninterface Ethernet1/0\n no ip address\n shutdown\n!\ninterface Ethernet1/1\n no ip address\n!\ninterface Ethernet1/2\n description A-NEW-DESCRIPTION\n no ip address\n shutdown\n!\nrouter eigrp 60\n network 192.168.0.0 0.0.255.255\n auto-summary\n no eigrp log-neighbor-changes\n!\nip classless\nip route 0.0.0.0 0.0.0.0 14.38.1.1\nip http server\n!\n!\nline con 0\n exec-timeout 0 22\nline aux 0\nline vty 0 4\n!\nend\n','2018-01-06 22:03:55'); +/*!40000 ALTER TABLE `configurations` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `custom_attribute_types` +-- + +LOCK TABLES `custom_attribute_types` WRITE; +/*!40000 ALTER TABLE `custom_attribute_types` DISABLE KEYS */; +INSERT INTO `custom_attribute_types` (`id`, `name`, `notes`, `field_validation_rule`, `failed_rule_text`) VALUES (1,'nmap_scan','Used to determine if this subnet should be scanned by Nmap based tools.','/^[Y|N]$/','Must be either Y or N'),(3,'Asset Tag','Asset tracking tag of physical device','',''); +/*!40000 ALTER TABLE `custom_attribute_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `custom_attributes` +-- + +LOCK TABLES `custom_attributes` WRITE; +/*!40000 ALTER TABLE `custom_attributes` DISABLE KEYS */; +INSERT INTO `custom_attributes` (`id`, `table_name_ref`, `table_id_ref`, `custom_attribute_type_id`, `value`) VALUES (1,'hosts',23,3,'QKRNS731'); +/*!40000 ALTER TABLE `custom_attributes` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dcm_module_list` +-- + +LOCK TABLES `dcm_module_list` WRITE; +/*!40000 ALTER TABLE `dcm_module_list` DISABLE KEYS */; +INSERT INTO `dcm_module_list` (`name`, `description`, `file`) VALUES ('add_module','Register a new DCM module','get_module_list.inc.php'),('add_permission','Add new security permission','permissions.inc.php'),('block_add','Add an ip block range','ona/block.inc.php'),('block_del','Delete an ip block','ona/block.inc.php'),('block_modify','Modify ip blocks','ona/block.inc.php'),('config_add','Adds a configuration to the database','ona/configuration.inc.php'),('config_chksum','Displays the chksum of a config record from the database','ona/configuration.inc.php'),('config_diff','Display unix diff of configs','ona/configuration.inc.php'),('config_display','Displays a config record from the database','ona/configuration.inc.php'),('custom_attribute_add','Add a custom attribute','ona/custom_attribute.inc.php'),('custom_attribute_del','Delete a custom attribute','ona/custom_attribute.inc.php'),('custom_attribute_display','Display a custom attribute','ona/custom_attribute.inc.php'),('custom_attribute_modify','Modify a custom attribute','ona/custom_attribute.inc.php'),('custom_attribute_type_display','Display a custom attribute type','ona/custom_attribute.inc.php'),('dhcp_entry_add','Add a DHCP option entry','ona/dhcp_entry.inc.php'),('dhcp_entry_del','Delete a DHCP option entry','ona/dhcp_entry.inc.php'),('dhcp_entry_modify','Modify DHCP option entry','ona/dhcp_entry.inc.php'),('dhcp_failover_group_add','Add servers to a DHCP failover group','ona/dhcp_failover.inc.php'),('dhcp_failover_group_del','Delete a DHCP failover group','ona/dhcp_failover.inc.php'),('dhcp_failover_group_display','Display a DHCP failover group','ona/dhcp_failover.inc.php'),('dhcp_failover_group_modify','Modify a DHCP failover group','ona/dhcp_failover.inc.php'),('dhcp_pool_add','Add DHCP pools','ona/dhcp_pool.inc.php'),('dhcp_pool_del','Delete a DHCP pool','ona/dhcp_pool.inc.php'),('dhcp_pool_modify','Modify DHCP pools','ona/dhcp_pool.inc.php'),('dhcp_server_add','Add a DHCP server to subnet relationship','ona/dhcp_server.inc.php'),('dhcp_server_del','Delete a DHCP server to subnet relationship','ona/dhcp_server.inc.php'),('dns_record_add','Add a DNS record','ona/dns_record.inc.php'),('dns_record_del','Delete a DNS record','ona/dns_record.inc.php'),('dns_record_display','Display info about a DNS record','ona/dns_record.inc.php'),('dns_record_modify','Modify a DNS record','ona/dns_record.inc.php'),('domain_add','Adds a domain entry into the IP database','ona/domain.inc.php'),('domain_del','Deletes a domain from the IP database','ona/domain.inc.php'),('domain_display','Displays an existing domain','ona/domain.inc.php'),('domain_modify','Updates an domain record in the IP database','ona/domain.inc.php'),('domain_server_add','Add a DNS domain to a server','ona/domain_server.inc.php'),('domain_server_del','Delete a DNS domain from a server','ona/domain_server.inc.php'),('get_module_list','Returns the list of available modules','get_module_list.inc.php'),('host_add','Add a new host','ona/host.inc.php'),('host_del','Delete an existing host','ona/host.inc.php'),('host_display','Display an existing host','ona/host.inc.php'),('host_modify','Modify an existing host','ona/host.inc.php'),('interface_add','Add an interface to an existing host','ona/interface.inc.php'),('interface_del','Delete an existing interface','ona/interface.inc.php'),('interface_display','Displays details of an existing interface','ona/interface.inc.php'),('interface_modify','Modify an existing interface','ona/interface.inc.php'),('interface_move','Move an interface from one subnet to another','ona/interface.inc.php'),('interface_move_host','Moves an interface from one host to another','ona/interface.inc.php'),('interface_share','Share an existing interface with another host','ona/interface.inc.php'),('interface_share_del','Delete an interface share entry','ona/interface.inc.php'),('location_add','Add a location record','ona/location.inc.php'),('location_del','Delete a location','ona/location.inc.php'),('location_modify','Modify a location record','ona/location.inc.php'),('mangle_ip','Converts between various IP address representations','mangle.inc.php'),('message_add','Add a message to a subnet or host that will show on a display page','ona/message.inc.php'),('mysql_purge_logs','Purges unused replication logs on MySQL masters','mysql_purge_logs.inc.php'),('nat_add','Add external NAT IP to existing internal IP','ona/interface.inc.php'),('nat_del','Delete external NAT IP from existing internal IP','ona/interface.inc.php'),('ona_sql','Perform basic SQL operations on the database','sql.inc.php'),('report_run','Run a report','report_run.inc.php'),('subnet_add','Add a new subnet','ona/subnet.inc.php'),('subnet_del','Delete an existing subnet','ona/subnet.inc.php'),('subnet_display','Display an existing subnet','ona/subnet.inc.php'),('subnet_modify','Modify an existing subnet','ona/subnet.inc.php'),('subnet_nextip','Return the next available IP address on a subnet','ona/subnet.inc.php'),('tag_add','Add a tag to an object','ona/tag.inc.php'),('tag_del','Delete a tag from an object','ona/tag.inc.php'),('vlan_add','Add a VLAN','ona/vlan.inc.php'),('vlan_campus_add','Add a VLAN campus (VTP Domain)','ona/vlan_campus.inc.php'),('vlan_campus_del','Delete a VLAN campus','ona/vlan_campus.inc.php'),('vlan_campus_display','Display a VLAN campus record','ona/vlan_campus.inc.php'),('vlan_campus_modify','Modify a VLAN campus record','ona/vlan_campus.inc.php'),('vlan_del','Delete a VLAN','ona/vlan.inc.php'),('vlan_modify','Modify a VLAN','ona/vlan.inc.php'); +/*!40000 ALTER TABLE `dcm_module_list` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `device_types` +-- + +LOCK TABLES `device_types` WRITE; +/*!40000 ALTER TABLE `device_types` DISABLE KEYS */; +INSERT INTO `device_types` (`id`, `model_id`, `role_id`) VALUES (1,1,1),(2,9,11),(3,2,13),(4,4,2),(5,5,3),(6,9,12),(7,11,4),(8,12,13); +/*!40000 ALTER TABLE `device_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `devices` +-- + +LOCK TABLES `devices` WRITE; +/*!40000 ALTER TABLE `devices` DISABLE KEYS */; +INSERT INTO `devices` (`id`, `device_type_id`, `location_id`, `primary_host_id`, `asset_tag`, `serial_number`) VALUES (14,1,1,22,NULL,NULL),(15,8,1,23,NULL,NULL),(16,7,1,24,NULL,NULL); +/*!40000 ALTER TABLE `devices` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dhcp_failover_groups` +-- + +LOCK TABLES `dhcp_failover_groups` WRITE; +/*!40000 ALTER TABLE `dhcp_failover_groups` DISABLE KEYS */; +/*!40000 ALTER TABLE `dhcp_failover_groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dhcp_option_entries` +-- + +LOCK TABLES `dhcp_option_entries` WRITE; +/*!40000 ALTER TABLE `dhcp_option_entries` DISABLE KEYS */; +INSERT INTO `dhcp_option_entries` (`id`, `subnet_id`, `host_id`, `server_id`, `dhcp_option_id`, `value`) VALUES (13,22,0,0,2,'192.168.1.1'); +/*!40000 ALTER TABLE `dhcp_option_entries` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dhcp_options` +-- + +LOCK TABLES `dhcp_options` WRITE; +/*!40000 ALTER TABLE `dhcp_options` DISABLE KEYS */; +INSERT INTO `dhcp_options` (`id`, `name`, `number`, `type`, `display_name`, `sys_default`) VALUES (1,'subnet-mask',1,'I','Subnet Mask',1),(2,'routers',3,'L','Default Gateway',1),(3,'domain-name-servers',6,'L','DNS Name Servers',1),(4,'domain-name',15,'S','Default domain',1),(5,'host-name',12,'S','Host Name',1),(6,'vendor-encapsulated-options',43,'S','Vendor Ecapsulated Options',1),(7,'netbios-name-servers',44,'L','Netbios Name Servers',1),(8,'netbios-node-type',46,'N','Netbios Node Type',1),(9,'netbios-scope',47,'S','Netbios Scope',1),(10,'vendor-class-identifier',60,'S','Vendor Class Identifier',1),(11,'tftp-server-name',66,'S','TFTP Server Name',1),(12,'bootfile-name',67,'S','Bootfile Name',1); +/*!40000 ALTER TABLE `dhcp_options` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dhcp_pools` +-- + +LOCK TABLES `dhcp_pools` WRITE; +/*!40000 ALTER TABLE `dhcp_pools` DISABLE KEYS */; +INSERT INTO `dhcp_pools` (`id`, `subnet_id`, `dhcp_failover_group_id`, `ip_addr_start`, `ip_addr_end`, `lease_length`, `lease_grace_period`, `lease_renewal_time`, `lease_rebind_time`, `allow_bootp_clients`) VALUES (3,22,0,3232235876,3232236030,604800,0,0,0,0); +/*!40000 ALTER TABLE `dhcp_pools` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dhcp_server_subnets` +-- + +LOCK TABLES `dhcp_server_subnets` WRITE; +/*!40000 ALTER TABLE `dhcp_server_subnets` DISABLE KEYS */; +INSERT INTO `dhcp_server_subnets` (`id`, `host_id`, `subnet_id`) VALUES (6,24,22); +/*!40000 ALTER TABLE `dhcp_server_subnets` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dns` +-- + +LOCK TABLES `dns` WRITE; +/*!40000 ALTER TABLE `dns` DISABLE KEYS */; +INSERT INTO `dns` (`id`, `domain_id`, `interface_id`, `dns_id`, `type`, `ttl`, `name`, `ebegin`, `notes`, `mx_preference`, `txt`, `srv_pri`, `srv_weight`, `srv_port`, `dns_view_id`) VALUES (62,1,28,0,'A',0,'router','2018-01-05 05:24:37','',0,'',0,0,0,0),(63,5,28,62,'PTR',0,'','2018-01-05 05:24:37','',0,'',0,0,0,0),(64,1,29,0,'A',0,'laptop01','2018-01-05 05:27:16','',0,'',0,0,0,0),(65,5,29,64,'PTR',0,'','2018-01-05 05:27:16','',0,'',0,0,0,0),(66,1,30,0,'A',0,'server','2018-01-06 22:06:57','Primary name for this server used for searching in ONA',0,'',0,0,0,0),(67,5,30,66,'PTR',0,'','2018-01-05 05:34:23','',0,'',0,0,0,0),(68,1,30,66,'NS',0,'','2018-01-06 22:06:27','NS record since this is a DNS server',0,'',0,0,0,0),(69,5,31,62,'PTR',0,'','2018-01-05 05:48:31','',0,'',0,0,0,0),(70,5,32,66,'PTR',0,'','2018-01-05 05:49:14','',0,'',0,0,0,0),(71,6,33,66,'PTR',0,'','2018-01-05 06:10:59','',0,'',0,0,0,0),(72,1,32,0,'A',0,'www','2018-01-05 06:13:29','internal dns record for the website',0,'',0,0,0,0),(73,1,30,66,'MX',0,'mail','2018-01-05 06:14:43','MX record for mail services',10,'',0,0,0,0); +/*!40000 ALTER TABLE `dns` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dns_server_domains` +-- + +LOCK TABLES `dns_server_domains` WRITE; +/*!40000 ALTER TABLE `dns_server_domains` DISABLE KEYS */; +INSERT INTO `dns_server_domains` (`id`, `host_id`, `domain_id`, `role`, `rebuild_flag`) VALUES (8,24,1,'master',1); +/*!40000 ALTER TABLE `dns_server_domains` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `dns_views` +-- + +LOCK TABLES `dns_views` WRITE; +/*!40000 ALTER TABLE `dns_views` DISABLE KEYS */; +INSERT INTO `dns_views` (`id`, `name`, `description`) VALUES (0,'DEFAULT','Default view for dns records'); +/*!40000 ALTER TABLE `dns_views` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `domains` +-- + +LOCK TABLES `domains` WRITE; +/*!40000 ALTER TABLE `domains` DISABLE KEYS */; +INSERT INTO `domains` (`id`, `parent_id`, `ctime`, `serial`, `refresh`, `retry`, `expiry`, `minimum`, `default_ttl`, `primary_master`, `admin_email`, `name`) VALUES (1,0,'2018-01-07 02:10:17',0,86400,3600,3600,3600,86400,'server.example.com','hostmaster','example.com'),(5,0,'2018-01-05 05:24:35',15052435,86400,3600,3600,3600,86400,'','hostmaster','192.in-addr.arpa'),(6,0,'2018-01-05 06:10:49',15061049,86400,3600,3600,3600,86400,'','hostmaster','250.in-addr.arpa'); +/*!40000 ALTER TABLE `domains` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `group_assignments` +-- + +LOCK TABLES `group_assignments` WRITE; +/*!40000 ALTER TABLE `group_assignments` DISABLE KEYS */; +INSERT INTO `group_assignments` (`id`, `group_id`, `user_id`) VALUES (1,17,1),(2,18,2); +/*!40000 ALTER TABLE `group_assignments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `groups` +-- + +LOCK TABLES `auth_groups` WRITE; +/*!40000 ALTER TABLE `auth_groups` DISABLE KEYS */; +INSERT INTO `auth_groups` (`id`, `name`, `description`, `level`) VALUES (17,'Default','Default user group',1),(18,'Admin','Admin group',99); +/*!40000 ALTER TABLE `auth_groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `host_roles` +-- + +LOCK TABLES `host_roles` WRITE; +/*!40000 ALTER TABLE `host_roles` DISABLE KEYS */; +/*!40000 ALTER TABLE `host_roles` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `hosts` +-- + +LOCK TABLES `hosts` WRITE; +/*!40000 ALTER TABLE `hosts` DISABLE KEYS */; +INSERT INTO `hosts` (`id`, `parent_id`, `primary_dns_id`, `device_id`, `notes`) VALUES (22,0,62,14,'This is the router for the office'),(23,0,64,15,'Example desktop/laptop device'),(24,0,66,16,'Example DNS and DHCP server'); +/*!40000 ALTER TABLE `hosts` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `interface_clusters` +-- + +LOCK TABLES `interface_clusters` WRITE; +/*!40000 ALTER TABLE `interface_clusters` DISABLE KEYS */; +/*!40000 ALTER TABLE `interface_clusters` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `interfaces` +-- + +LOCK TABLES `interfaces` WRITE; +/*!40000 ALTER TABLE `interfaces` DISABLE KEYS */; +INSERT INTO `interfaces` (`id`, `subnet_id`, `host_id`, `nat_interface_id`, `ip_addr`, `mac_addr`, `name`, `description`, `last_response`) VALUES (28,22,22,0,3232235777,'','Ethernet0/0','',NULL),(29,22,23,0,3232235786,'784F43679B70','','Static MAC based IP address, Assigned by DHCP',NULL),(30,22,24,0,3232235796,'','eth0','Interface for DNS and DHCP services',NULL),(31,24,22,0,3232236033,'','Ethernet0/1','',NULL),(32,24,24,33,3232236042,'','eth0:websvc','Interface for public web site, with NAT',NULL),(33,23,24,0,4194370123,'','','EXT NAT',NULL); +/*!40000 ALTER TABLE `interfaces` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `locations` +-- + +LOCK TABLES `locations` WRITE; +/*!40000 ALTER TABLE `locations` DISABLE KEYS */; +INSERT INTO `locations` (`id`, `reference`, `name`, `address`, `city`, `state`, `zip_code`, `latitude`, `longitude`, `misc`) VALUES (1,'CORP','Primary Office','123 Main St','Boise','ID',83706,'','','Main Phone: 208-123-4456\nContact: John Doe'); +/*!40000 ALTER TABLE `locations` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `manufacturers` +-- + +LOCK TABLES `manufacturers` WRITE; +/*!40000 ALTER TABLE `manufacturers` DISABLE KEYS */; +INSERT INTO `manufacturers` (`id`, `name`) VALUES (7,'Adtran'),(8,'Allied Telesyn'),(48,'Apple'),(9,'Cabletron'),(1,'Cisco'),(5,'Dell'),(10,'Extreme Networks'),(4,'Hewlett Packard'),(6,'IBM'),(2,'Juniper'),(3,'Unknown'),(47,'VMware'); +/*!40000 ALTER TABLE `manufacturers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `messages` +-- + +LOCK TABLES `messages` WRITE; +/*!40000 ALTER TABLE `messages` DISABLE KEYS */; +/*!40000 ALTER TABLE `messages` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `models` +-- + +LOCK TABLES `models` WRITE; +/*!40000 ALTER TABLE `models` DISABLE KEYS */; +INSERT INTO `models` (`id`, `manufacturer_id`, `name`, `snmp_sysobjectid`) VALUES (1,1,'2821',''),(2,4,'dv9000t',''),(3,4,'4000m',''),(4,4,'8000m',''),(5,4,'LJ5000',''),(6,1,'2948G-L3',''),(7,5,'Optiplex GS560',''),(8,9,'24TXM-GLS',''),(9,3,'Unknown',''),(10,6,'Netfinity 2232',''),(11,47,'Virtual',''),(12,48,'MacBook Pro',''); +/*!40000 ALTER TABLE `models` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `ona_logs` +-- + +LOCK TABLES `ona_logs` WRITE; +/*!40000 ALTER TABLE `ona_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `ona_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `permission_assignments` +-- + +LOCK TABLES `permission_assignments` WRITE; +/*!40000 ALTER TABLE `permission_assignments` DISABLE KEYS */; +INSERT INTO `permission_assignments` (`id`, `perm_id`, `user_id`, `group_id`) VALUES (1,1,2,18),(2,2,2,18),(3,3,2,18),(4,4,2,18),(5,5,2,18),(6,6,2,18),(7,7,2,18),(8,8,2,18),(9,9,2,18),(10,10,2,18),(11,11,2,18),(12,12,2,18),(13,13,2,18),(14,14,2,18),(15,15,2,18),(16,16,2,18),(17,17,2,18),(18,18,2,18),(100001,100019,2,18),(100002,100020,2,18),(100003,100021,2,18),(100004,100022,2,18),(100005,100023,2,18),(100006,100024,2,18); +/*!40000 ALTER TABLE `permission_assignments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `permissions` +-- + +LOCK TABLES `permissions` WRITE; +/*!40000 ALTER TABLE `permissions` DISABLE KEYS */; +INSERT INTO `permissions` (`id`, `name`, `description`) VALUES (1,'dns_record_add','Add a DNS record'),(2,'dns_record_modify','Modify a DNS record'),(3,'dns_record_del','Delete a DNS record'),(4,'host_add','Add hosts and interfaces'),(5,'host_modify','Modify hosts'),(6,'host_del','Delete hosts'),(7,'user_admin','User Administrator'),(8,'subnet_add','Add subnets'),(9,'subnet_modify','Modify subnets'),(10,'subnet_del','Delete subnets'),(11,'interface_modify','Modify interface records'),(12,'interface_del','Delete interface records'),(13,'advanced','Advanced Maintenance'),(14,'host_config_admin','Host config archive admin'),(15,'template_admin','Template system admin'),(16,'vlan_add','Add VLANs and VLAN Campuses'),(17,'vlan_del','Delete VLANs and VLAN Campuses'),(18,'vlan_modify','Modify VLANs and VLAN Campuses'),(100019,'location_del','Delete a location'),(100020,'location_add','Add a location'),(100021,'ona_sql','Perform SQL operations on the ONA tables'),(100022,'custom_attribute_add','Add custom attribute'),(100023,'custom_attribute_del','Delete custom attribute'),(100024,'custom_attribute_modify','Modify custom attribute'); +/*!40000 ALTER TABLE `permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `roles` +-- + +LOCK TABLES `roles` WRITE; +/*!40000 ALTER TABLE `roles` DISABLE KEYS */; +INSERT INTO `roles` (`id`, `name`) VALUES (12,'Bulk loaded'),(13,'laptop'),(11,'Manually loaded'),(3,'printer'),(1,'router'),(4,'server'),(2,'switch'),(7,'wireless access point'),(5,'workstation'); +/*!40000 ALTER TABLE `roles` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `sequences` +-- + +LOCK TABLES `sequences` WRITE; +/*!40000 ALTER TABLE `sequences` DISABLE KEYS */; +INSERT INTO `sequences` (`name`, `seq`) VALUES ('blocks',7),('configurations',3),('configuration_types',5),('custom_attribute_types',4),('devices',17),('device_types',9),('dhcp_options',14),('dhcp_option_entries',14),('dhcp_pools',4),('dhcp_server_subnets',7),('dns',74),('dns_server_domains',9),('domains',7),('hosts',25),('interfaces',34),('locations',2),('manufacturers',49),('models',13),('permissions',100),('roles',14),('subnets',25),('subnet_types',15),('tags',3),('vlans',2),('vlan_campuses',6); +/*!40000 ALTER TABLE `sequences` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `subnet_types` +-- + +LOCK TABLES `subnet_types` WRITE; +/*!40000 ALTER TABLE `subnet_types` DISABLE KEYS */; +INSERT INTO `subnet_types` (`id`, `short_name`, `display_name`, `notes`) VALUES (1,'loopback','Loopback','Loopback Interfaces (mostly for routers)'),(2,'','WAN',''),(7,'','VLAN',''),(10,'p2p','Point-to-Point',''),(11,'','VPN',''),(12,'','Wireless LAN',''),(13,'lan','LAN','Simple LAN'),(14,'nat','NAT','Subnet used for NAT translation mapping'); +/*!40000 ALTER TABLE `subnet_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `subnets` +-- + +LOCK TABLES `subnets` WRITE; +/*!40000 ALTER TABLE `subnets` DISABLE KEYS */; +INSERT INTO `subnets` (`id`, `subnet_type_id`, `vlan_id`, `ip_addr`, `ip_mask`, `name`) VALUES (22,7,1,3232235776,4294967040,'LAN-EXAMPLE'),(23,14,0,4194370048,4294967040,'PUBLIC-NAT'),(24,7,0,3232236032,4294967040,'CORP-DMZ'); +/*!40000 ALTER TABLE `subnets` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `sys_config` +-- + +LOCK TABLES `sys_config` WRITE; +/*!40000 ALTER TABLE `sys_config` DISABLE KEYS */; +INSERT INTO `sys_config` (`name`, `value`, `description`, `field_validation_rule`, `editable`, `deleteable`, `failed_rule_text`) VALUES ('authtype','local','Define standard authentication module to use','',1,0,''),('build_dhcp_type','isc','DHCP build type',NULL,1,1,NULL),('build_dns_type','bind','DNS build type',NULL,1,1,NULL),('cookie_life','172800','Sets the length of the session cookie. It is in seconds','',1,0,''),('date_format','M jS, g:ia','PHP text format for date values','',1,0,''),('debug','0','Debug output level, the higher the number the more it logs','',1,0,''),('disable_guest','0','Disable the autologin of the guest user.','',1,0,''),('dns_admin_email','hostmaster','per RFC 2412, defaults to hostmaster within the domain origin','',1,0,''),('dns_defaultdomain','example.com','Default DNS domain name','',1,0,''),('dns_default_ttl','86400','this is the value of $TTL for the zone, used as the default value','',1,0,''),('dns_expiry','3600','DNS expire time used in SOA','',1,0,''),('dns_minimum','3600','DNS minimum TTL time, used as the negative caching value per RFC 2308','',1,0,''),('dns_primary_master','server.example.com','The fqdn of your default primary master DNS server, leave blank if not required','',1,0,''),('dns_refresh','86400','DNS refresh time used in SOA','',1,0,''),('dns_retry','3600','DNS retry time used in SOA','',1,0,''),('dns_views','0','Enable support for DNS views.','',0,0,''),('logfile','/var/log/ona.log','Local filesystem path to log messages','',1,0,''),('log_to_db','0','Log only level 0 messages to the database.','',1,0,''),('search_results_per_page','10','Sets the amount of rows per page in list items','',1,0,''),('stdout','0','Flag to allow logging via STDOUT.. This is extreme debugging, not recomended.','',0,0,''),('suggest_max_results','10','Limits the amount of rows returned by queries. (test impact of changing this first)','',1,0,''),('syslog','0','Log via syslog, only works if debug is set to 0','',0,0,''),('upgrade_index','13','Tracks current upgrade index, used to perform database upgrades.','',0,0,''),('version','v18.1.1','Tracks current installed version, used to detect when upgrades should be done.','',0,0,''); +/*!40000 ALTER TABLE `sys_config` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `tags` +-- + +LOCK TABLES `tags` WRITE; +/*!40000 ALTER TABLE `tags` DISABLE KEYS */; +INSERT INTO `tags` (`id`, `name`, `type`, `reference`) VALUES (1,'Webserver','host',24),(2,'Prod','host',24); +/*!40000 ALTER TABLE `tags` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `users` +-- + +LOCK TABLES `users` WRITE; +/*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` (`id`, `username`, `password`, `level`, `ctime`, `atime`) VALUES (1,'guest','098f6bcd4621d373cade4e832627b4f6',0,'2018-01-06 04:50:42','2018-01-06 04:50:42'),(2,'admin','21232f297a57a5a743894a0e4a801fc3',0,'2018-01-05 06:10:17','2018-01-05 06:10:17'); +/*!40000 ALTER TABLE `users` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `vlan_campuses` +-- + +LOCK TABLES `vlan_campuses` WRITE; +/*!40000 ALTER TABLE `vlan_campuses` DISABLE KEYS */; +INSERT INTO `vlan_campuses` (`id`, `name`) VALUES (5,'CORPORATE'); +/*!40000 ALTER TABLE `vlan_campuses` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping data for table `vlans` +-- + +LOCK TABLES `vlans` WRITE; +/*!40000 ALTER TABLE `vlans` DISABLE KEYS */; +INSERT INTO `vlans` (`id`, `vlan_campus_id`, `name`, `number`) VALUES (1,5,'EXAMPLE-VLAN',23); +/*!40000 ALTER TABLE `vlans` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2018-01-07 2:19:49 diff --git a/install/ona-table_schema.xml b/install/ona-table_schema.xml index 9d6a4337..c10afe05 100644 --- a/install/ona-table_schema.xml +++ b/install/ona-table_schema.xml @@ -6,7 +6,7 @@ - ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -29,7 +29,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -41,7 +41,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -64,11 +64,14 @@ + + host_id +
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -89,7 +92,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -113,7 +116,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -131,7 +134,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -145,7 +148,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -164,7 +167,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -209,7 +212,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -237,7 +240,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -263,7 +266,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -307,7 +310,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -324,7 +327,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -389,7 +392,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -411,7 +414,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -438,9 +441,6 @@ - - - @@ -478,7 +478,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -497,8 +497,8 @@
- - ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci +
+ ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -522,7 +522,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -539,7 +539,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -563,7 +563,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -579,7 +579,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -613,7 +613,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -650,7 +650,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -687,10 +687,12 @@ - + + + @@ -705,7 +707,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -724,7 +726,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -750,7 +752,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -775,7 +777,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -795,7 +797,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -823,7 +825,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -838,7 +840,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -856,7 +858,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -884,7 +886,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -909,7 +911,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -949,6 +951,7 @@ + @@ -958,7 +961,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -970,7 +973,7 @@
- ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci + ENGINE=INNODB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci @@ -989,34 +992,6 @@
- - - - - - ALTER TABLE `configurations` CHANGE `ctime` `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP - ALTER TABLE `dns` CHANGE `ebegin` `ebegin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP - ALTER TABLE `ona_logs` CHANGE `timestamp` `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP - ALTER TABLE `users` CHANGE `ctime` `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP - - - - -CREATE TABLE domains ( -id INTEGER NOT NULL, -host_id INTEGER NOT NULL, -domain_id INTEGER NOT NULL, -role VARCHAR(10) NOT NULL, -type VARCHAR(10) NOT NULL, -rebuild_flag INTEGER NOT NULL, - PRIMARY KEY (id) -); - - - - - - @@ -1027,5 +1002,8 @@ rebuild_flag INTEGER NOT NULL, + + update dns set ebegin = '2000-01-01' where CAST(ebegin AS CHAR(20)) = '0000-00-00 00:00:00' + diff --git a/install/v08.02.18-to-v08.04.15.sql b/install/v08.02.18-to-v08.04.15.sql deleted file mode 100644 index fabf8afa..00000000 --- a/install/v08.02.18-to-v08.04.15.sql +++ /dev/null @@ -1,8 +0,0 @@ -INSERT INTO `sys_config` (`name`, `value`, `description`) VALUES -('version', 'v08.04.15', 'Tracks current installed version, used to detect when upgrades should be done.'), -('upgrade_index', '1', 'Tracks current upgrade index, used to process database upgrades in order.'); - -INSERT INTO `permissions` (`id`, `name`, `description`) VALUES -(16, 'vlan_add', 'Add VLANs and VLAN Campuses'), -(17, 'vlan_del', 'Delete VLANs and VLAN Campuses'), -(18, 'vlan_modify', 'Modify VLANs and VLAN Campuses'); diff --git a/www/config/config.inc.php b/www/config/config.inc.php index 2a532b03..ea5571bc 100644 --- a/www/config/config.inc.php +++ b/www/config/config.inc.php @@ -30,9 +30,9 @@ // Get any query info -parse_str($_SERVER['QUERY_STRING']); - +parse_str($_SERVER['QUERY_STRING'],$output); +$year = date('Y'); // Many of these settings serve as defaults. They can be overridden by the settings in // the table "sys_config" @@ -70,6 +70,7 @@ /* Defaults for some user definable options normally in sys_config table */ "debug" => "2", + "force_https" => "0", // TODO: check what the best default is here.. something wrong with port level redirects too "syslog" => "0", "stdout" => "0", "log_to_db" => "0", diff --git a/www/dcm.php b/www/dcm.php index 080efc48..d2f18f49 100644 --- a/www/dcm.php +++ b/www/dcm.php @@ -9,7 +9,7 @@ // MP: Since we know ONA will generate a ton of notice level errors, lets turn them off here // I dont believe this will be impactful to anyone. keep an eye out for it however. -error_reporting (E_ALL ^ E_NOTICE); +error_reporting (E_ALL ^ E_WARNING ^ E_NOTICE); // These store the output to be displayed $status = 1; @@ -64,6 +64,19 @@ // Display the current debug level if it's above 1 printmsg("DEBUG => debug level: {$conf['debug']}", 1); +// If we do not have an options element, lets fake one by passing all _REQUEST variables to the options string +if (!isset($_REQUEST['options'])) { + foreach ($_REQUEST as $key => $value) { + if ($key != 'module') { + if ($value == '') { + $options .= "&${key}=Y"; + } else { + $options .= "&${key}=${value}"; + } + } + } + $_REQUEST['options'] = $options; +} /* ----------- RUN A MODULE IF NEEDED ------------ */ if (isset($_REQUEST['module'])) { @@ -73,8 +86,10 @@ // process various types of output formats if (strstr($_REQUEST['options'], "format=json")) { + header('Content-Type: application/json'); output_formatter('json','json_encode'); } elseif (strstr($_REQUEST['options'], "format=yaml")) { + header('Content-Type: application/yaml'); output_formatter('yaml','yaml_emit'); } else { // Assume default text format @@ -101,6 +116,7 @@ function output_formatter($format='',$function='') { // Output needs to be an array if (is_array($output)) { $output['module_exit_status'] = $status; + ksort($output); eval('print '.$function.'($output);'); } else { $out['module_exit_status'] = $status; diff --git a/www/images/favicon.ico b/www/images/favicon.ico new file mode 100644 index 00000000..c32d25c1 Binary files /dev/null and b/www/images/favicon.ico differ diff --git a/www/include/adodb b/www/include/adodb deleted file mode 120000 index 5d7bbfd0..00000000 --- a/www/include/adodb +++ /dev/null @@ -1 +0,0 @@ -adodb5 \ No newline at end of file diff --git a/www/include/adodb5/LICENSE.md b/www/include/adodb/LICENSE.md similarity index 98% rename from www/include/adodb5/LICENSE.md rename to www/include/adodb/LICENSE.md index b8191587..d00e2b1f 100644 --- a/www/include/adodb5/LICENSE.md +++ b/www/include/adodb/LICENSE.md @@ -1,19 +1,22 @@ ADOdb License ============= -ADOdb is dual licensed under BSD and LGPL. +The ADOdb Library is dual-licensed, released under both the +[BSD 3-clause](#bsd-3-clause-license) and the +[GNU Lesser General Public License (LGPL) v2.1](#gnu-lesser-general-public-license) +or, at your option, any later version. In plain English, you do not need to distribute your application in source code form, nor do you need to distribute ADOdb source code, provided you follow the rest of terms of the BSD license. -For more info about ADOdb, visit http://adodb.sourceforge.net/ +For more information about ADOdb, visit https://adodb.org/ BSD 3-Clause License -------------------- -(c) 2000-2013 John Lim (jlim@natsoft.com) -(c) 2014 Damien Regad, Mark Newnham and the ADOdb community +(c) 2000-2013 John Lim (jlim@natsoft.com) +(c) 2014 Damien Regad, Mark Newnham and the ADOdb community All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/www/include/adodb/README.md b/www/include/adodb/README.md new file mode 100644 index 00000000..96ac67b2 --- /dev/null +++ b/www/include/adodb/README.md @@ -0,0 +1,103 @@ +ADOdb Library for PHP +====================== + +[![Join chat on Gitter](https://img.shields.io/gitter/room/adodb/adodb?logo=gitter)](https://gitter.im/adodb/adodb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![SourceForge Downloads Shield](https://img.shields.io/sourceforge/dm/adodb?label=SourceForge&logo=sourceforge&color=informational)](https://sourceforge.net/projects/adodb/files/latest/download) +[![Packagist Downloads Shield](https://img.shields.io/packagist/dm/ADOdb/ADOdb-php?label=Packagist&logo=packagist&logoColor=white&color=informational)](https://packagist.org/packages/adodb/adodb-php) + +(c) 2000-2013 John Lim (jlim@natsoft.com) +(c) 2014 Damien Regad, Mark Newnham and the + [ADOdb community](https://github.com/ADOdb/ADOdb/graphs/contributors) + +The ADOdb Library is dual-licensed, released under both the +[BSD 3-Clause](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md#bsd-3-clause-license) +and the +[GNU Lesser General Public Licence (LGPL) v2.1](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md#gnu-lesser-general-public-license) +or, at your option, any later version. +This means you can use it in proprietary products; +see [License](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md) for details. + +Home page: https://adodb.org/ + + +Introduction +============ + +PHP's database access functions are not standardized. This creates a +need for a database class library to hide the differences between the +different databases (encapsulate the differences) so we can easily +switch databases. + +The library currently supports MySQL, Firebird & Interbase, PostgreSQL, SQLite3, Oracle, +Microsoft SQL Server, Foxpro ODBC, Access ODBC, Informix, DB2, Sybase, +Sybase SQL Anywhere, generic ODBC and Microsoft's ADO. + +We hope more people will contribute drivers to support other databases. + + +Installation +============ + +Unpack all the files into a directory accessible by your web server. + +To test, try modifying some of the tutorial examples. +Make sure you customize the connection settings correctly. + +You can debug using: + +``` php +debug = true; +$db->connect($server, $user, $password, $database); +$rs = $db->execute('select * from some_small_table'); +print "
";
+print_r($rs->getRows());
+print "
"; +``` + + +Documentation and Examples +========================== + +Refer to the [ADOdb website](https://adodb.org/) for library documentation and examples. The documentation can also be [downloaded for offline viewing](https://sourceforge.net/projects/adodb/files/Documentation/). + +- [Main documentation](https://adodb.org/dokuwiki/doku.php?id=v5:userguide:userguide_index): Query, update and insert records using a portable API. +- [Data dictionary](https://adodb.org/dokuwiki/doku.php?id=v5:dictionary:dictionary_index) describes how to create database tables and indexes in a portable manner. +- [Database performance monitoring](https://adodb.org/dokuwiki/doku.php?id=v5:performance:performance_index) allows you to perform health checks, tune and monitor your database. +- [Database-backed sessions](https://adodb.org/dokuwiki/doku.php?id=v5:session:session_index). + +There is also a [tutorial](https://adodb.org/dokuwiki/doku.php?id=v5:userguide:mysql_tutorial) that contrasts ADOdb code with PHP native MySQL code. + + +Files +===== + +- `adodb.inc.php` is the library's main file. You only need to include this file. +- `adodb-*.inc.php` are the database specific driver code. +- `adodb-session.php` is the PHP4 session handling code. +- `test.php` contains a list of test commands to exercise the class library. +- `testdatabases.inc.php` contains the list of databases to apply the tests on. +- `Benchmark.php` is a simple benchmark to test the throughput of a SELECT +statement for databases described in testdatabases.inc.php. The benchmark +tables are created in test.php. + + +Support +======= + +To discuss with the ADOdb development team and users, connect to our +[Gitter chatroom](https://gitter.im/adodb/adodb) using your Github credentials. + +Please report bugs, issues and feature requests on Github: + +https://github.com/ADOdb/ADOdb/issues + +You may also find legacy issues in + +- the [SourceForge tickets section](http://sourceforge.net/p/adodb/_list/tickets) + +However, please note that they are not actively monitored and should +only be used as reference. diff --git a/www/include/adodb/SECURITY.md b/www/include/adodb/SECURITY.md new file mode 100644 index 00000000..00670f24 --- /dev/null +++ b/www/include/adodb/SECURITY.md @@ -0,0 +1,45 @@ +# ADOdb Security Policy + +## Supported Versions + +The following releases of the library are currently being supported with +security updates. Please refer to the [project's home page](https://adodb.org) +for actual version numbers. + +- Stable +- Legacy +- Development (Git *master* branch) + +Older releases are no longer supported. + + +## Reporting a Vulnerability + +If you discover a vulnerability in ADOdb, please contact +the [project's maintainer](https://github.com/dregad) + +- by e-mail (look for it in the Git history) +- via private chat on [Gitter](https://gitter.im/dregad) + +Kindly provide the following information in your report: + +- Affected ADOdb version(s) or Git revision +- A clear and detailed description of the issue, including if possible a code + snippet to demonstrate or reproduce the vulnerability +- A patch for the issue if you have one, preferably in *Git diff* format + +### CVE handling + +To ensure a comprehensive and detailed declaration of the issue, we generally +prefer requesting CVE IDs ourselves, which usually happens after our analysis +confirms the vulnerability. + +In case you have already obtained a CVE ID, do not forget to reference it in +your report. + +### Credits + +Let us know if and how you wish to be credited for the finding. + +Your name, e-mail, company, etc. will be included as specified in the CVE +report, as well as in the Git commit message patching the issue. diff --git a/www/include/adodb5/adodb-active-record.inc.php b/www/include/adodb/adodb-active-record.inc.php similarity index 85% rename from www/include/adodb5/adodb-active-record.inc.php rename to www/include/adodb/adodb-active-record.inc.php index a7f0adf7..ad40640a 100644 --- a/www/include/adodb5/adodb-active-record.inc.php +++ b/www/include/adodb/adodb-active-record.inc.php @@ -1,23 +1,25 @@ $d) { - if (PHP_VERSION >= 5) { - if ($d->db === $db) { - return $k; - } - } else { - if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) { - return $k; - } - } + foreach($_ADODB_ACTIVE_DBS as $k => $d) { + if($d->db === $db) { + return $k; } + } - $obj = new ADODB_Active_DB(); - $obj->db = $db; - $obj->tables = array(); + $obj = new ADODB_Active_DB(); + $obj->db = $db; + $obj->tables = array(); - if ($index == false) { - $index = sizeof($_ADODB_ACTIVE_DBS); - } + if ($index == false) { + $index = sizeof($_ADODB_ACTIVE_DBS); + } - $_ADODB_ACTIVE_DBS[$index] = $obj; + $_ADODB_ACTIVE_DBS[$index] = $obj; - return sizeof($_ADODB_ACTIVE_DBS)-1; + return sizeof($_ADODB_ACTIVE_DBS)-1; } class ADODB_Active_Record { static $_changeNames = true; // dynamically pluralize table names - static $_quoteNames = false; + + /** @var bool|string Allows override of global $ADODB_QUOTE_FIELDNAMES */ + public $_quoteNames; static $_foreignSuffix = '_id'; // var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat] @@ -120,7 +118,12 @@ public function __set($name, $value) // php5 constructor function __construct($table = false, $pkeyarr=false, $db=false) { - global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS; + global $_ADODB_ACTIVE_DBS, $ADODB_QUOTE_FIELDNAMES; + + // Set the local override for field quoting, only if not defined yet + if (!isset($this->_quoteNames)) { + $this->_quoteNames = $ADODB_QUOTE_FIELDNAMES; + } if ($db == false && is_object($pkeyarr)) { $db = $pkeyarr; @@ -278,7 +281,7 @@ static function ClassBelongsTo($class, $foreignRef, $foreignKey=false, $parentKe static function TableBelongsTo($table, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record') { - $ar = new ADOdb_Active_Record($table); + $ar = new ADODB_Active_Record($table); $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass); } @@ -287,7 +290,7 @@ static function TableKeyBelongsTo($table, $tablePKey, $foreignRef, $foreignKey=f if (!is_array($tablePKey)) { $tablePKey = array($tablePKey); } - $ar = new ADOdb_Active_Record($table, $tablePKey); + $ar = new ADODB_Active_Record($table, $tablePKey); $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass); } @@ -374,7 +377,7 @@ function LoadRelations($name, $whereOrderBy='', $offset=-1,$limit=-1) // update metadata function UpdateActiveTable($pkeys=false,$forceUpdate=false) { - global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS; + global $_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS; global $ADODB_ACTIVE_DEFVALS,$ADODB_FETCH_MODE; $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; @@ -463,8 +466,8 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) $attr = array(); $keys = array(); - switch($ADODB_ASSOC_CASE) { - case 0: + switch (ADODB_ASSOC_CASE) { + case ADODB_ASSOC_CASE_LOWER: foreach($cols as $name => $fldobj) { $name = strtolower($name); if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) { @@ -480,7 +483,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) } break; - case 1: + case ADODB_ASSOC_CASE_UPPER: foreach($cols as $name => $fldobj) { $name = strtoupper($name); @@ -499,7 +502,6 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) break; default: foreach($cols as $name => $fldobj) { - $name = ($fldobj->name); if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) { $this->$name = $fldobj->default_value; @@ -510,7 +512,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) $attr[$name] = $fldobj; } foreach($pkeys as $k => $name) { - $keys[$name] = $cols[$name]->name; + $keys[$name] = $cols[strtoupper($name)]->name; } break; } @@ -522,7 +524,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) $activetab->_created = time(); $s = serialize($activetab); if (!function_exists('adodb_write_file')) { - include(ADODB_DIR.'/adodb-csvlib.inc.php'); + include_once(ADODB_DIR.'/adodb-csvlib.inc.php'); } adodb_write_file($fname,$s); } @@ -700,9 +702,14 @@ function LastInsertID(&$db,$fieldname) $val = false; } - if (is_null($val) || $val === false) { + if (is_null($val) || $val === false) + { + $SQL = sprintf("SELECT MAX(%s) FROM %s", + $this->nameQuoter($db,$fieldname), + $this->nameQuoter($db,$this->_table) + ); // this might not work reliably in multi-user environment - return $db->GetOne("select max(".$fieldname.") from ".$this->_table); + return $db->GetOne($SQL); } return $val; } @@ -749,10 +756,11 @@ function GenWhere(&$db, &$table) foreach($keys as $k) { $f = $table->flds[$k]; if ($f) { - $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type)); + $columnName = $this->nameQuoter($db,$k); + $parr[] = $columnName.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type)); } } - return implode(' and ', $parr); + return implode(' AND ', $parr); } @@ -774,7 +782,7 @@ function _QName($n,$db=false) function Load($where=null,$bindarr=false, $lock = false) { - global $ADODB_FETCH_MODE; + global $ADODB_FETCH_MODE; $db = $this->DB(); if (!$db) { @@ -788,7 +796,9 @@ function Load($where=null,$bindarr=false, $lock = false) $savem = $db->SetFetchMode(false); } - $qry = "select * from ".$this->_table; + $qry = sprintf("SELECT * FROM %s", + $this->nameQuoter($db,$this->_table) + ); if($where) { $qry .= ' WHERE '.$where; @@ -813,7 +823,7 @@ function LoadLocked($where=null, $bindarr=false) } # useful for multiple record inserts - # see http://phplens.com/lens/lensforum/msgs.php?id=17795 + # see PHPLens Issue No: 17795 function Reset() { $this->_where=null; @@ -862,7 +872,7 @@ function Insert() $val = $this->$name; if(!is_array($val) || !is_null($val) || !array_key_exists($name, $table->keys)) { $valarr[] = $val; - $names[] = $this->_QName($name,$db); + $names[] = $this->nameQuoter($db,$name); $valstr[] = $db->Param($cnt); $cnt += 1; } @@ -871,12 +881,18 @@ function Insert() if (empty($names)){ foreach($table->flds as $name=>$fld) { $valarr[] = null; - $names[] = $name; + $names[] = $this->nameQuoter($db,$name); $valstr[] = $db->Param($cnt); $cnt += 1; } } - $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')'; + + $tableName = $this->nameQuoter($db,$this->_table); + $sql = sprintf('INSERT INTO %s (%s) VALUES (%s)', + $tableName, + implode(',',$names), + implode(',',$valstr) + ); $ok = $db->Execute($sql,$valarr); if ($ok) { @@ -907,7 +923,14 @@ function Delete() $table = $this->TableInfo(); $where = $this->GenWhere($db,$table); - $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where; + + $tableName = $this->nameQuoter($db,$this->_table); + + $sql = sprintf('DELETE FROM %s WHERE %s', + $tableName, + $where + ); + $ok = $db->Execute($sql); return $ok ? true : false; @@ -927,8 +950,6 @@ function Find($whereOrderBy,$bindarr=false,$pkeysArr=false,$extra=array()) // returns 0 on error, 1 on update, 2 on insert function Replace() { - global $ADODB_ASSOC_CASE; - $db = $this->DB(); if (!$db) { return false; @@ -968,17 +989,32 @@ function Replace() $pkey = array($pkey); } - if ($ADODB_ASSOC_CASE == 0) { - foreach($pkey as $k => $v) - $pkey[$k] = strtolower($v); - } - elseif ($ADODB_ASSOC_CASE == 1) { - foreach($pkey as $k => $v) { - $pkey[$k] = strtoupper($v); - } + switch (ADODB_ASSOC_CASE) { + case ADODB_ASSOC_CASE_LOWER: + foreach ($pkey as $k => $v) { + $pkey[$k] = strtolower($v); + } + break; + case ADODB_ASSOC_CASE_UPPER: + foreach ($pkey as $k => $v) { + $pkey[$k] = strtoupper($v); + } + break; } - $ok = $db->Replace($this->_table,$arr,$pkey); + $newArr = array(); + foreach($arr as $k=>$v) + $newArr[$this->nameQuoter($db,$k)] = $v; + $arr = $newArr; + + $newPkey = array(); + foreach($pkey as $k=>$v) + $newPkey[$k] = $this->nameQuoter($db,$v); + $pkey = $newPkey; + + $tableName = $this->nameQuoter($db,$this->_table); + + $ok = $db->Replace($tableName,$arr,$pkey); if ($ok) { $this->_saved = true; // 1= update 2=insert if ($ok == 2) { @@ -1050,7 +1086,7 @@ function Update() } $valarr[] = $val; - $pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt); + $pairs[] = $this->nameQuoter($db,$name).'='.$db->Param($cnt); $cnt += 1; } @@ -1059,7 +1095,13 @@ function Update() return -1; } - $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where; + $tableName = $this->nameQuoter($db,$this->_table); + + $sql = sprintf('UPDATE %s SET %s WHERE %s', + $tableName, + implode(',',$pairs), + $where); + $ok = $db->Execute($sql,$valarr); if ($ok) { $this->_original = $neworig; @@ -1077,6 +1119,31 @@ function GetAttributeNames() return array_keys($table->flds); } + /** + * Quotes the table, column and field names. + * + * This honours the internal {@see $_quoteNames} property, which overrides + * the global $ADODB_QUOTE_FIELDNAMES directive. + * + * @param ADOConnection $db The database connection + * @param string $name The table or column name to quote + * + * @return string The quoted name + */ + private function nameQuoter($db, $name) + { + global $ADODB_QUOTE_FIELDNAMES; + + $save = $ADODB_QUOTE_FIELDNAMES; + $ADODB_QUOTE_FIELDNAMES = $this->_quoteNames; + + $string = _adodb_quote_fieldname($db, $name); + + $ADODB_QUOTE_FIELDNAMES = $save; + + return $string; + } + }; function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr, $primkeyArr, @@ -1086,6 +1153,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr $save = $db->SetFetchMode(ADODB_FETCH_NUM); + $qry = "select * from ".$table; if (!empty($whereOrderBy)) { @@ -1124,7 +1192,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr // arrRef will be the structure that knows about our objects. // It is an associative array. // We will, however, return arr, preserving regular 0.. order so that - // obj[0] can be used by app developpers. + // obj[0] can be used by app developers. $arrRef = array(); $bTos = array(); // Will store belongTo's indices if any foreach($rows as $row) { diff --git a/www/include/adodb5/adodb-active-recordx.inc.php b/www/include/adodb/adodb-active-recordx.inc.php similarity index 95% rename from www/include/adodb5/adodb-active-recordx.inc.php rename to www/include/adodb/adodb-active-recordx.inc.php index 7f553f1e..5de5b130 100644 --- a/www/include/adodb5/adodb-active-recordx.inc.php +++ b/www/include/adodb/adodb-active-recordx.inc.php @@ -1,27 +1,27 @@ $d) { - if (PHP_VERSION >= 5) { - if ($d->db === $db) { - return $k; - } - } else { - if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) { - return $k; - } - } + foreach($_ADODB_ACTIVE_DBS as $k => $d) { + if ($d->db === $db) { + return $k; } + } - $obj = new ADODB_Active_DB(); - $obj->db = $db; - $obj->tables = array(); + $obj = new ADODB_Active_DB(); + $obj->db = $db; + $obj->tables = array(); - $_ADODB_ACTIVE_DBS[] = $obj; + $_ADODB_ACTIVE_DBS[] = $obj; - return sizeof($_ADODB_ACTIVE_DBS)-1; + return sizeof($_ADODB_ACTIVE_DBS)-1; } @@ -137,7 +131,7 @@ public function __set($name, $value) // if $options['new'] is true, we forget all relations function __construct($table = false, $pkeyarr=false, $db=false, $options=array()) { - global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS; + global $_ADODB_ACTIVE_DBS; if ($db == false && is_object($pkeyarr)) { $db = $pkeyarr; @@ -410,7 +404,7 @@ function LoadRelations($name, $whereOrderBy, $offset=-1, $limit=-1) // update metadata function UpdateActiveTable($pkeys=false,$forceUpdate=false) { - global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS; + global $_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS; global $ADODB_ACTIVE_DEFVALS, $ADODB_FETCH_MODE; $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat]; @@ -491,8 +485,8 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) $attr = array(); $keys = array(); - switch($ADODB_ASSOC_CASE) { - case 0: + switch (ADODB_ASSOC_CASE) { + case ADODB_ASSOC_CASE_LOWER: foreach($cols as $name => $fldobj) { $name = strtolower($name); if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) { @@ -508,7 +502,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) } break; - case 1: + case ADODB_ASSOC_CASE_UPPER: foreach($cols as $name => $fldobj) { $name = strtoupper($name); @@ -551,7 +545,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false) $activetab->_created = time(); $s = serialize($activetab); if (!function_exists('adodb_write_file')) { - include(ADODB_DIR.'/adodb-csvlib.inc.php'); + include_once(ADODB_DIR.'/adodb-csvlib.inc.php'); } adodb_write_file($fname,$s); } @@ -1060,8 +1054,6 @@ function packageFind($whereOrderBy,$bindarr=false,$pkeysArr=false,$extra=array() // returns 0 on error, 1 on update, 2 on insert function Replace() { - global $ADODB_ASSOC_CASE; - $db = $this->DB(); if (!$db) { return false; @@ -1097,7 +1089,7 @@ function Replace() } - switch ($ADODB_ASSOC_CASE == 0) { + switch (ADODB_ASSOC_CASE) { case ADODB_ASSOC_CASE_LOWER: foreach($pkey as $k => $v) { $pkey[$k] = strtolower($v); @@ -1300,7 +1292,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $tableObj,$whereOrderBy,$bind if (!isset($_ADODB_ACTIVE_DBS)) { - include(ADODB_DIR.'/adodb-active-record.inc.php'); + include_once(ADODB_DIR.'/adodb-active-record.inc.php'); } if (!class_exists($class)) { $db->outp_throw("Unknown class $class in GetActiveRecordsClass()",'GetActiveRecordsClass'); @@ -1311,7 +1303,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $tableObj,$whereOrderBy,$bind // arrRef will be the structure that knows about our objects. // It is an associative array. // We will, however, return arr, preserving regular 0.. order so that - // obj[0] can be used by app developpers. + // obj[0] can be used by app developers. $arrRef = array(); $bTos = array(); // Will store belongTo's indices if any foreach($rows as $row) { diff --git a/www/include/adodb5/adodb-csvlib.inc.php b/www/include/adodb/adodb-csvlib.inc.php similarity index 81% rename from www/include/adodb5/adodb-csvlib.inc.php rename to www/include/adodb/adodb-csvlib.inc.php index bfd8d9b8..77e63bfb 100644 --- a/www/include/adodb5/adodb-csvlib.inc.php +++ b/www/include/adodb/adodb-csvlib.inc.php @@ -1,4 +1,26 @@ adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode; $class = $rs->connection->arrayClass; - $rs2 = new $class(); + $rs2 = new $class(-1); // Dummy query Id $rs2->timeCreated = $rs->timeCreated; # memcache fix $rs2->sql = $rs->sql; $rs2->oldProvider = $rs->dataProvider; @@ -81,19 +85,19 @@ function _rs2serialize(&$rs,$conn=false,$sql='') return $line.serialize($rs2); } - -/** -* Open CSV file and convert it into Data. -* -* @param url file/ftp/http url -* @param err returns the error message -* @param timeout dispose if recordset has been alive for $timeout secs -* -* @return recordset, or false if error occured. If no -* error occurred in sql INSERT/UPDATE/DELETE, -* empty recordset is returned -*/ - function csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array') + /** + * Open CSV file and convert it into Data. + * + * @param string $url file/ftp/http url + * @param string &$err returns the error message + * @param int $timeout dispose if recordset has been alive for $timeout secs + * @param string $rsclass RecordSet class to return + * + * @return ADORecordSet|false recordset, or false if error occurred. + * If no error occurred in sql INSERT/UPDATE/DELETE, + * empty recordset is returned. + */ + function csv2rs($url, &$err, $timeout=0, $rsclass='ADORecordSet_array') { $false = false; $err = false; @@ -249,10 +253,8 @@ function csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array') fclose($fp); @$arr = unserialize($text); - //var_dump($arr); if (!is_array($arr)) { $err = "Recordset had unexpected EOF (in serialized recordset)"; - if (get_magic_quotes_runtime()) $err .= ". Magic Quotes Runtime should be disabled!"; return $false; } $rs = new $rsclass(); diff --git a/www/include/adodb5/adodb-datadict.inc.php b/www/include/adodb/adodb-datadict.inc.php similarity index 70% rename from www/include/adodb5/adodb-datadict.inc.php rename to www/include/adodb/adodb-datadict.inc.php index b15a80e6..9dfa07a6 100644 --- a/www/include/adodb5/adodb-datadict.inc.php +++ b/www/include/adodb/adodb-datadict.inc.php @@ -1,32 +1,35 @@ $str

"; -$a= Lens_ParseArgs($str); +$a= lens_ParseArgs($str); print "
";
 print_r($a);
 print "
"; @@ -53,7 +56,7 @@ function ctype_alnum($text) { @param tokenchars Include the following characters in tokens apart from A-Z and 0-9 @returns 2 dimensional array containing parsed tokens. */ -function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-') +function lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-') { $pos = 0; $intoken = false; @@ -164,6 +167,7 @@ function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-') class ADODB_DataDict { + /** @var ADOConnection */ var $connection; var $debug = false; var $dropTable = 'DROP TABLE %s'; @@ -179,45 +183,60 @@ class ADODB_DataDict { var $serverInfo = array(); var $autoIncrement = false; var $dataProvider; - var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql + var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changeTableSQL var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob - /// in other words, we use a text area for editting. + /// in other words, we use a text area for editing. + /** @var string Uppercase driver name */ + var $upperName; - function GetCommentSQL($table,$col) + /* + * Indicates whether a BLOB/CLOB field will allow a NOT NULL setting + * The type is whatever is matched to an X or X2 or B type. We must + * explicitly set the value in the driver to switch the behaviour on + */ + public $blobAllowsNotNull; + /* + * Indicates whether a BLOB/CLOB field will allow a DEFAULT set + * The type is whatever is matched to an X or X2 or B type. We must + * explicitly set the value in the driver to switch the behaviour on + */ + public $blobAllowsDefaultValue; + + function getCommentSQL($table,$col) { return false; } - function SetCommentSQL($table,$col,$cmt) + function setCommentSQL($table,$col,$cmt) { return false; } - function MetaTables() + function metaTables() { - if (!$this->connection->IsConnected()) return array(); - return $this->connection->MetaTables(); + if (!$this->connection->isConnected()) return array(); + return $this->connection->metaTables(); } - function MetaColumns($tab, $upper=true, $schema=false) + function metaColumns($tab, $upper=true, $schema=false) { - if (!$this->connection->IsConnected()) return array(); - return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema); + if (!$this->connection->isConnected()) return array(); + return $this->connection->metaColumns($this->tableName($tab), $upper, $schema); } - function MetaPrimaryKeys($tab,$owner=false,$intkey=false) + function metaPrimaryKeys($tab,$owner=false,$intkey=false) { - if (!$this->connection->IsConnected()) return array(); - return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey); + if (!$this->connection->isConnected()) return array(); + return $this->connection->metaPrimaryKeys($this->tableName($tab), $owner, $intkey); } - function MetaIndexes($table, $primary = false, $owner = false) + function metaIndexes($table, $primary = false, $owner = false) { - if (!$this->connection->IsConnected()) return array(); - return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner); + if (!$this->connection->isConnected()) return array(); + return $this->connection->metaIndexes($this->tableName($table), $primary, $owner); } - function MetaType($t,$len=-1,$fieldobj=false) + function metaType($t,$len=-1,$fieldobj=false) { static $typeMap = array( 'VARCHAR' => 'C', @@ -323,18 +342,18 @@ function MetaType($t,$len=-1,$fieldobj=false) "SQLBOOL" => 'L' ); - if (!$this->connection->IsConnected()) { + if (!$this->connection->isConnected()) { $t = strtoupper($t); if (isset($typeMap[$t])) return $typeMap[$t]; - return 'N'; + return ADODB_DEFAULT_METATYPE; } - return $this->connection->MetaType($t,$len,$fieldobj); + return $this->connection->metaType($t,$len,$fieldobj); } - function NameQuote($name = NULL,$allowBrackets=false) + function nameQuote($name = NULL,$allowBrackets=false) { if (!is_string($name)) { - return FALSE; + return false; } $name = trim($name); @@ -360,16 +379,16 @@ function NameQuote($name = NULL,$allowBrackets=false) return $name; } - function TableName($name) + function tableName($name) { if ( $this->schema ) { - return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name); + return $this->nameQuote($this->schema) .'.'. $this->nameQuote($name); } - return $this->NameQuote($name); + return $this->nameQuote($name); } - // Executes the sql array returned by GetTableSQL and GetIndexSQL - function ExecuteSQLArray($sql, $continueOnError = true) + // Executes the sql array returned by getTableSQL and getIndexSQL + function executeSQLArray($sql, $continueOnError = true) { $rez = 2; $conn = $this->connection; @@ -377,10 +396,10 @@ function ExecuteSQLArray($sql, $continueOnError = true) foreach($sql as $line) { if ($this->debug) $conn->debug = true; - $ok = $conn->Execute($line); + $ok = $conn->execute($line); $conn->debug = $saved; if (!$ok) { - if ($this->debug) ADOConnection::outp($conn->ErrorMsg()); + if ($this->debug) ADOConnection::outp($conn->errorMsg()); if (!$continueOnError) return 0; $rez = 1; } @@ -406,17 +425,26 @@ function ExecuteSQLArray($sql, $continueOnError = true) N: Numeric or decimal number */ - function ActualType($meta) + function actualType($meta) { + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + return $meta; } - function CreateDatabase($dbname,$options=false) + function createDatabase($dbname,$options=false) { - $options = $this->_Options($options); + $options = $this->_options($options); $sql = array(); - $s = 'CREATE DATABASE ' . $this->NameQuote($dbname); + $s = 'CREATE DATABASE ' . $this->nameQuote($dbname); if (isset($options[$this->upperName])) $s .= ' '.$options[$this->upperName]; @@ -427,7 +455,7 @@ function CreateDatabase($dbname,$options=false) /* Generates the SQL to create index. Returns an array of sql strings. */ - function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false) + function createIndexSQL($idxname, $tabname, $flds, $idxoptions = false) { if (!is_array($flds)) { $flds = explode(',',$flds); @@ -435,27 +463,27 @@ function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false) foreach($flds as $key => $fld) { # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32) - $flds[$key] = $this->NameQuote($fld,$allowBrackets=true); + $flds[$key] = $this->nameQuote($fld,$allowBrackets=true); } - return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions)); + return $this->_indexSQL($this->nameQuote($idxname), $this->tableName($tabname), $flds, $this->_options($idxoptions)); } - function DropIndexSQL ($idxname, $tabname = NULL) + function dropIndexSQL ($idxname, $tabname = NULL) { - return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname))); + return array(sprintf($this->dropIndex, $this->nameQuote($idxname), $this->tableName($tabname))); } - function SetSchema($schema) + function setSchema($schema) { $this->schema = $schema; } - function AddColumnSQL($tabname, $flds) + function addColumnSQL($tabname, $flds) { - $tabname = $this->TableName ($tabname); + $tabname = $this->tableName($tabname); $sql = array(); - list($lines,$pkey,$idxs) = $this->_GenFields($flds); + list($lines,$pkey,$idxs) = $this->_genFields($flds); // genfields can return FALSE at times if ($lines == null) $lines = array(); $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' '; @@ -464,7 +492,7 @@ function AddColumnSQL($tabname, $flds) } if (is_array($idxs)) { foreach($idxs as $idx => $idxdef) { - $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); + $sql_idxs = $this->createIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); $sql = array_merge($sql, $sql_idxs); } } @@ -474,19 +502,19 @@ function AddColumnSQL($tabname, $flds) /** * Change the definition of one column * - * As some DBM's can't do that on there own, you need to supply the complete defintion of the new table, - * to allow, recreating the table and copying the content over to the new table + * As some DBMs can't do that on their own, you need to supply the complete definition of the new table, + * to allow recreating the table and copying the content over to the new table * @param string $tabname table-name * @param string $flds column-name and type for the changed column - * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default '' - * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default '' + * @param string $tableflds='' complete definition of the new table, eg. for postgres, default '' + * @param array|string $tableoptions='' options for the new table see createTableSQL, default '' * @return array with SQL strings */ - function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') + function alterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') { - $tabname = $this->TableName ($tabname); + $tabname = $this->tableName($tabname); $sql = array(); - list($lines,$pkey,$idxs) = $this->_GenFields($flds); + list($lines,$pkey,$idxs) = $this->_genFields($flds); // genfields can return FALSE at times if ($lines == null) $lines = array(); $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' '; @@ -495,7 +523,7 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') } if (is_array($idxs)) { foreach($idxs as $idx => $idxdef) { - $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); + $sql_idxs = $this->createIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); $sql = array_merge($sql, $sql_idxs); } @@ -506,71 +534,71 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') /** * Rename one column * - * Some DBM's can only do this together with changeing the type of the column (even if that stays the same, eg. mysql) + * Some DBMs can only do this together with changeing the type of the column (even if that stays the same, eg. mysql) * @param string $tabname table-name * @param string $oldcolumn column-name to be renamed * @param string $newcolumn new column-name - * @param string $flds='' complete column-defintion-string like for AddColumnSQL, only used by mysql atm., default='' + * @param string $flds='' complete column-definition-string like for addColumnSQL, only used by mysql atm., default='' * @return array with SQL strings */ - function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='') + function renameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='') { - $tabname = $this->TableName ($tabname); + $tabname = $this->tableName($tabname); if ($flds) { - list($lines,$pkey,$idxs) = $this->_GenFields($flds); + list($lines,$pkey,$idxs) = $this->_genFields($flds); // genfields can return FALSE at times if ($lines == null) $lines = array(); - list(,$first) = each($lines); + $first = current($lines); list(,$column_def) = preg_split("/[\t ]+/",$first,2); } - return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def)); + return array(sprintf($this->renameColumn,$tabname,$this->nameQuote($oldcolumn),$this->nameQuote($newcolumn),$column_def)); } /** * Drop one column * - * Some DBM's can't do that on there own, you need to supply the complete defintion of the new table, + * Some DBM's can't do that on their own, you need to supply the complete definition of the new table, * to allow, recreating the table and copying the content over to the new table * @param string $tabname table-name * @param string $flds column-name and type for the changed column - * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default '' - * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default '' + * @param string $tableflds='' complete definition of the new table, eg. for postgres, default '' + * @param array|string $tableoptions='' options for the new table see createTableSQL, default '' * @return array with SQL strings */ - function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') + function dropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') { - $tabname = $this->TableName ($tabname); + $tabname = $this->tableName($tabname); if (!is_array($flds)) $flds = explode(',',$flds); $sql = array(); $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' '; foreach($flds as $v) { - $sql[] = $alter . $this->NameQuote($v); + $sql[] = $alter . $this->nameQuote($v); } return $sql; } - function DropTableSQL($tabname) + function dropTableSQL($tabname) { - return array (sprintf($this->dropTable, $this->TableName($tabname))); + return array (sprintf($this->dropTable, $this->tableName($tabname))); } - function RenameTableSQL($tabname,$newname) + function renameTableSQL($tabname,$newname) { - return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname))); + return array (sprintf($this->renameTable, $this->tableName($tabname),$this->tableName($newname))); } /** Generate the SQL to create table. Returns an array of sql strings. */ - function CreateTableSQL($tabname, $flds, $tableoptions=array()) + function createTableSQL($tabname, $flds, $tableoptions=array()) { - list($lines,$pkey,$idxs) = $this->_GenFields($flds, true); + list($lines,$pkey,$idxs) = $this->_genFields($flds, true); // genfields can return FALSE at times if ($lines == null) $lines = array(); - $taboptions = $this->_Options($tableoptions); - $tabname = $this->TableName ($tabname); - $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions); + $taboptions = $this->_options($tableoptions); + $tabname = $this->tableName($tabname); + $sql = $this->_tableSQL($tabname,$lines,$pkey,$taboptions); // ggiunta - 2006/10/12 - KLUDGE: // if we are on autoincrement, and table options includes REPLACE, the @@ -579,12 +607,12 @@ function CreateTableSQL($tabname, $flds, $tableoptions=array()) // creating sql that double-drops the sequence if ($this->autoIncrement && isset($taboptions['REPLACE'])) unset($taboptions['REPLACE']); - $tsql = $this->_Triggers($tabname,$taboptions); + $tsql = $this->_triggers($tabname,$taboptions); foreach($tsql as $s) $sql[] = $s; if (is_array($idxs)) { foreach($idxs as $idx => $idxdef) { - $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); + $sql_idxs = $this->createIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); $sql = array_merge($sql, $sql_idxs); } } @@ -594,13 +622,13 @@ function CreateTableSQL($tabname, $flds, $tableoptions=array()) - function _GenFields($flds,$widespacing=false) + function _genFields($flds,$widespacing=false) { if (is_string($flds)) { $padding = ' '; $txt = $flds.$padding; $flds = array(); - $flds0 = Lens_ParseArgs($txt,','); + $flds0 = lens_ParseArgs($txt,','); $hasparam = false; foreach($flds0 as $f0) { $f1 = array(); @@ -643,8 +671,8 @@ function _GenFields($flds,$widespacing=false) $pkey = array(); $idxs = array(); foreach($flds as $fld) { - $fld = _array_change_key_case($fld); - + if (is_array($fld)) + $fld = array_change_key_case($fld,CASE_UPPER); $fname = false; $fdefault = false; $fautoinc = false; @@ -660,27 +688,41 @@ function _GenFields($flds,$widespacing=false) $funsigned = false; $findex = ''; $funiqueindex = false; + $fOptions = array(); //----------------- // Parse attributes foreach($fld as $attr => $v) { - if ($attr == 2 && is_numeric($v)) $attr = 'SIZE'; - else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v); + if ($attr == 2 && is_numeric($v)) + $attr = 'SIZE'; + elseif ($attr == 2 && strtoupper($ftype) == 'ENUM') + $attr = 'ENUM'; + else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) + $attr = strtoupper($v); switch($attr) { case '0': case 'NAME': $fname = $v; break; case '1': - case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break; + case 'TYPE': + + $ty = $v; + $ftype = $this->actualType(strtoupper($v)); + break; case 'SIZE': - $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,','); - if ($dotat === false) $fsize = $v; - else { - $fsize = substr($v,0,$dotat); - $fprec = substr($v,$dotat+1); - } - break; + $dotat = strpos($v,'.'); + if ($dotat === false) + $dotat = strpos($v,','); + if ($dotat === false) + $fsize = $v; + else { + + $fsize = substr($v,0,$dotat); + $fprec = substr($v,$dotat+1); + + } + break; case 'UNSIGNED': $funsigned = true; break; case 'AUTOINCREMENT': case 'AUTO': $fautoinc = true; $fnotnull = true; break; @@ -697,6 +739,8 @@ function _GenFields($flds,$widespacing=false) // let INDEX keyword create a 'very standard' index on column case 'INDEX': $findex = $v; break; case 'UNIQUE': $funiqueindex = true; break; + case 'ENUM': + $fOptions['ENUM'] = $v; break; } //switch } // foreach $fld @@ -708,7 +752,7 @@ function _GenFields($flds,$widespacing=false) } $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname)); - $fname = $this->NameQuote($fname); + $fname = $this->nameQuote($fname); if (!strlen($ftype)) { if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'"); @@ -717,14 +761,24 @@ function _GenFields($flds,$widespacing=false) $ftype = strtoupper($ftype); } - $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec); + $ftype = $this->_getSize($ftype, $ty, $fsize, $fprec, $fOptions); - if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls + if (($ty == 'X' || $ty == 'X2' || $ty == 'XL' || $ty == 'B') && !$this->blobAllowsNotNull) + /* + * some blob types do not accept nulls, so we override the + * previously defined value + */ + $fnotnull = false; - if ($fprimary) $pkey[] = $fname; + if ($fprimary) + $pkey[] = $fname; - // some databases do not allow blobs to have defaults - if ($ty == 'X') $fdefault = false; + if (($ty == 'X' || $ty == 'X2' || $ty == 'XL' || $ty == 'B') && !$this->blobAllowsDefaultValue) + /* + * some databases do not allow blobs to have defaults, so we + * override the previously defined value + */ + $fdefault = false; // build list of indexes if ($findex != '') { @@ -769,11 +823,11 @@ function _GenFields($flds,$widespacing=false) // convert default date into database-aware code if ($ty == 'T') { - $fdefault = $this->connection->DBTimeStamp($fdefault); + $fdefault = $this->connection->dbTimeStamp($fdefault); } else { - $fdefault = $this->connection->DBDate($fdefault); + $fdefault = $this->connection->dbDate($fdefault); } } else @@ -783,7 +837,7 @@ function _GenFields($flds,$widespacing=false) $fdefault = $this->connection->qstr($fdefault); } } - $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned); + $suffix = $this->_createSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned); // add index creation if ($widespacing) $fname = str_pad($fname,24); @@ -806,19 +860,38 @@ function _GenFields($flds,$widespacing=false) $ftype is the actual type $ty is the type defined originally in the DDL */ - function _GetSize($ftype, $ty, $fsize, $fprec) + function _getSize($ftype, $ty, $fsize, $fprec, $options=false) { if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) { $ftype .= "(".$fsize; if (strlen($fprec)) $ftype .= ",".$fprec; $ftype .= ')'; } + + /* + * Handle additional options + */ + if (is_array($options)) + { + foreach($options as $type=>$value) + { + switch ($type) + { + case 'ENUM': + $ftype .= '(' . $value . ')'; + break; + + default: + } + } + } + return $ftype; } // return string must begin with space - function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) + function _createSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) { $suffix = ''; if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault"; @@ -827,7 +900,7 @@ function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint return $suffix; } - function _IndexSQL($idxname, $tabname, $flds, $idxoptions) + function _indexSQL($idxname, $tabname, $flds, $idxoptions) { $sql = array(); @@ -856,25 +929,26 @@ function _IndexSQL($idxname, $tabname, $flds, $idxoptions) return $sql; } - function _DropAutoIncrement($tabname) + function _dropAutoIncrement($tabname) { return false; } - function _TableSQL($tabname,$lines,$pkey,$tableoptions) + function _tableSQL($tabname,$lines,$pkey,$tableoptions) { $sql = array(); if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) { $sql[] = sprintf($this->dropTable,$tabname); if ($this->autoIncrement) { - $sInc = $this->_DropAutoIncrement($tabname); + $sInc = $this->_dropAutoIncrement($tabname); if ($sInc) $sql[] = $sInc; } if ( isset ($tableoptions['DROP']) ) { return $sql; } } + $s = "CREATE TABLE $tabname (\n"; $s .= implode(",\n", $lines); if (sizeof($pkey)>0) { @@ -898,7 +972,7 @@ function _TableSQL($tabname,$lines,$pkey,$tableoptions) GENERATE TRIGGERS IF NEEDED used when table has auto-incrementing field that is emulated using triggers */ - function _Triggers($tabname,$taboptions) + function _triggers($tabname,$taboptions) { return array(); } @@ -906,7 +980,7 @@ function _Triggers($tabname,$taboptions) /** Sanitize options, so that array elements with no keys are promoted to keys */ - function _Options($opts) + function _options($opts) { if (!is_array($opts)) return array(); $newopts = array(); @@ -938,25 +1012,25 @@ function _getSizePrec($size) This function changes/adds new fields to your table. You don't have to know if the col is new or not. It will check on its own. */ - function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false) + function changeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false) { global $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE; $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; - if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false); + if ($this->connection->fetchMode !== false) $savem = $this->connection->setFetchMode(false); // check table exists $save_handler = $this->connection->raiseErrorFn; $this->connection->raiseErrorFn = ''; - $cols = $this->MetaColumns($tablename); + $cols = $this->metaColumns($tablename); $this->connection->raiseErrorFn = $save_handler; - if (isset($savem)) $this->connection->SetFetchMode($savem); + if (isset($savem)) $this->connection->setFetchMode($savem); $ADODB_FETCH_MODE = $save; if ( empty($cols)) { - return $this->CreateTableSQL($tablename, $flds, $tableoptions); + return $this->createTableSQL($tablename, $flds, $tableoptions); } if (is_array($flds)) { @@ -976,7 +1050,7 @@ function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=f $c = $cols[$k]; $ml = $c->max_length; - $mt = $this->MetaType($c->type,$ml); + $mt = $this->metaType($c->type,$ml); if (isset($c->scale)) $sc = $c->scale; else $sc = 99; // always force change if scale not known. @@ -998,16 +1072,16 @@ function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=f // already exists, alter table instead - list($lines,$pkey,$idxs) = $this->_GenFields($flds); + list($lines,$pkey,$idxs) = $this->_genFields($flds); // genfields can return FALSE at times if ($lines == null) $lines = array(); - $alter = 'ALTER TABLE ' . $this->TableName($tablename); + $alter = 'ALTER TABLE ' . $this->tableName($tablename); $sql = array(); foreach ( $lines as $id => $v ) { if ( isset($cols[$id]) && is_object($cols[$id]) ) { - $flds = Lens_ParseArgs($v,','); + $flds = lens_ParseArgs($v,','); // We are trying to change the size of the field, if not allowed, simply ignore the request. // $flds[1] holds the type, $flds[2] holds the size -postnuke addition diff --git a/www/include/adodb5/adodb-error.inc.php b/www/include/adodb/adodb-error.inc.php similarity index 86% rename from www/include/adodb5/adodb-error.inc.php rename to www/include/adodb/adodb-error.inc.php index d42a06a8..517cf9b0 100644 --- a/www/include/adodb5/adodb-error.inc.php +++ b/www/include/adodb/adodb-error.inc.php @@ -1,19 +1,27 @@ DB_ERROR_SERIALIZATION_FAILURE ); reset($error_regexps); - while (list($regexp,$code) = each($error_regexps)) { + foreach ($error_regexps as $regexp => $code) { if (preg_match("/$regexp/mi", $errormsg)) { return $code; } @@ -245,9 +257,9 @@ function adodb_error_mysql() 1006 => DB_ERROR_CANNOT_CREATE, 1007 => DB_ERROR_ALREADY_EXISTS, 1008 => DB_ERROR_CANNOT_DROP, - 1045 => DB_ERROR_ACCESS_VIOLATION, + 1045 => DB_ERROR_ACCESS_VIOLATION, 1046 => DB_ERROR_NODBSELECTED, - 1049 => DB_ERROR_NOSUCHDB, + 1049 => DB_ERROR_NOSUCHDB, 1050 => DB_ERROR_ALREADY_EXISTS, 1051 => DB_ERROR_NOSUCHTABLE, 1054 => DB_ERROR_NOSUCHFIELD, @@ -257,8 +269,8 @@ function adodb_error_mysql() 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, 1146 => DB_ERROR_NOSUCHTABLE, 1048 => DB_ERROR_CONSTRAINT, - 2002 => DB_ERROR_CONNECT_FAILED, - 2005 => DB_ERROR_CONNECT_FAILED + 2002 => DB_ERROR_CONNECT_FAILED, + 2005 => DB_ERROR_CONNECT_FAILED ); return $MAP; diff --git a/www/include/adodb5/adodb-errorhandler.inc.php b/www/include/adodb/adodb-errorhandler.inc.php similarity index 76% rename from www/include/adodb5/adodb-errorhandler.inc.php rename to www/include/adodb/adodb-errorhandler.inc.php index 7f36ba1e..0cd3f218 100644 --- a/www/include/adodb5/adodb-errorhandler.inc.php +++ b/www/include/adodb/adodb-errorhandler.inc.php @@ -1,18 +1,23 @@ array_pop($tmp)]; + } if ($arr) if (strpos($arr[1], '(') !== false) { $at = strpos($sql, $arr[1]); @@ -39,6 +54,7 @@ function adodb_strip_order_by($sql) } else { $sql = str_replace($arr[1], '', $sql); } + return $sql; } @@ -118,272 +134,259 @@ function adodb_transpose(&$arr, &$newarr, &$hdr, &$fobjs) } } -// Force key to upper. -// See also http://www.php.net/manual/en/function.array-change-key-case.php -function _array_change_key_case($an_array) -{ - if (is_array($an_array)) { - $new_array = array(); - foreach($an_array as $key=>$value) - $new_array[strtoupper($key)] = $value; - - return $new_array; - } - - return $an_array; -} function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc) { - if (count($fieldArray) == 0) return 0; - $first = true; - $uSet = ''; - - if (!is_array($keyCol)) { - $keyCol = array($keyCol); - } - foreach($fieldArray as $k => $v) { - if ($v === null) { - $v = 'NULL'; - $fieldArray[$k] = $v; - } else if ($autoQuote && /*!is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ strcasecmp($v,$zthis->null2null)!=0) { - $v = $zthis->qstr($v); - $fieldArray[$k] = $v; - } - if (in_array($k,$keyCol)) continue; // skip UPDATE if is key + // Add Quote around table name to support use of spaces / reserved keywords + $table=sprintf('%s%s%s', $zthis->nameQuote,$table,$zthis->nameQuote); - if ($first) { - $first = false; - $uSet = "$k=$v"; - } else - $uSet .= ",$k=$v"; - } + if (count($fieldArray) == 0) return 0; - $where = false; - foreach ($keyCol as $v) { - if (isset($fieldArray[$v])) { - if ($where) $where .= ' and '.$v.'='.$fieldArray[$v]; - else $where = $v.'='.$fieldArray[$v]; - } + if (!is_array($keyCol)) { + $keyCol = array($keyCol); + } + $uSet = ''; + foreach($fieldArray as $k => $v) { + if ($v === null) { + $v = 'NULL'; + $fieldArray[$k] = $v; + } else if ($autoQuote && /*!is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ strcasecmp($v,$zthis->null2null)!=0) { + $v = $zthis->qstr($v); + $fieldArray[$k] = $v; } + if (in_array($k,$keyCol)) continue; // skip UPDATE if is key - if ($uSet && $where) { - $update = "UPDATE $table SET $uSet WHERE $where"; + // Add Quote around column name to support use of spaces / reserved keywords + $uSet .= sprintf(',%s%s%s=%s',$zthis->nameQuote,$k,$zthis->nameQuote,$v); + } + $uSet = ltrim($uSet, ','); - $rs = $zthis->Execute($update); + // Add Quote around column name in where clause + $where = ''; + foreach ($keyCol as $v) { + if (isset($fieldArray[$v])) { + $where .= sprintf(' and %s%s%s=%s ', $zthis->nameQuote,$v,$zthis->nameQuote,$fieldArray[$v]); + } + } + if ($where) { + $where = substr($where, 5); + } + if ($uSet && $where) { + $update = "UPDATE $table SET $uSet WHERE $where"; + $rs = $zthis->Execute($update); - if ($rs) { - if ($zthis->poorAffectedRows) { - /* - The Select count(*) wipes out any errors that the update would have returned. - http://phplens.com/lens/lensforum/msgs.php?id=5696 - */ - if ($zthis->ErrorNo()<>0) return 0; + if ($rs) { + if ($zthis->poorAffectedRows) { + // The Select count(*) wipes out any errors that the update would have returned. + // PHPLens Issue No: 5696 + if ($zthis->ErrorNo()<>0) return 0; - # affected_rows == 0 if update field values identical to old values - # for mysql - which is silly. + // affected_rows == 0 if update field values identical to old values + // for mysql - which is silly. + $cnt = $zthis->GetOne("select count(*) from $table where $where"); + if ($cnt > 0) return 1; // record already exists + } else { + if (($zthis->Affected_Rows()>0)) return 1; + } + } else + return 0; + } - $cnt = $zthis->GetOne("select count(*) from $table where $where"); - if ($cnt > 0) return 1; // record already exists - } else { - if (($zthis->Affected_Rows()>0)) return 1; - } - } else - return 0; - } + $iCols = $iVals = ''; + foreach($fieldArray as $k => $v) { + if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col - // print "

Error=".$this->ErrorNo().'

'; - $first = true; - foreach($fieldArray as $k => $v) { - if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col + // Add Quote around Column Name + $iCols .= sprintf(',%s%s%s',$zthis->nameQuote,$k,$zthis->nameQuote); + $iVals .= ",$v"; + } + $iCols = ltrim($iCols, ','); + $iVals = ltrim($iVals, ','); - if ($first) { - $first = false; - $iCols = "$k"; - $iVals = "$v"; - } else { - $iCols .= ",$k"; - $iVals .= ",$v"; - } - } - $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; - $rs = $zthis->Execute($insert); - return ($rs) ? 2 : 0; + $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; + $rs = $zthis->Execute($insert); + return ($rs) ? 2 : 0; } -// Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false, $size=0, $selectAttr='',$compareFields0=true) { - $hasvalue = false; - - if ($multiple or is_array($defstr)) { - if ($size==0) $size=5; - $attr = ' multiple size="'.$size.'"'; - if (!strpos($name,'[]')) $name .= '[]'; - } else if ($size) $attr = ' size="'.$size.'"'; - else $attr =''; + global $ADODB_FETCH_MODE; - $s = '\n"; } -// Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM function _adodb_getmenu_gp(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false, $size=0, $selectAttr='',$compareFields0=true) { - $hasvalue = false; - - if ($multiple or is_array($defstr)) { - if ($size==0) $size=5; - $attr = ' multiple size="'.$size.'"'; - if (!strpos($name,'[]')) $name .= '[]'; - } else if ($size) $attr = ' size="'.$size.'"'; - else $attr =''; + global $ADODB_FETCH_MODE; - $s = '\n"; } +/** + * Generate the opening SELECT tag for getmenu functions. + * + * ADOdb internal function, used by _adodb_getmenu() and _adodb_getmenu_gp(). + * + * @param string $name + * @param string $defstr + * @param bool $blank1stItem + * @param bool $multiple + * @param int $size + * @param string $selectAttr + * + * @return string HTML + */ +function _adodb_getmenu_select($name, $defstr = '', $blank1stItem = true, + $multiple = false, $size = 0, $selectAttr = '') +{ + if ($multiple || is_array($defstr)) { + if ($size == 0 ) { + $size = 5; + } + $attr = ' multiple size="' . $size . '"'; + if (!strpos($name,'[]')) { + $name .= '[]'; + } + } elseif ($size) { + $attr = ' size="' . $size . '"'; + } else { + $attr = ''; + } + + $html = '

", diff --git a/www/include/adodb5/adodb-pear.inc.php b/www/include/adodb/adodb-pear.inc.php similarity index 90% rename from www/include/adodb5/adodb-pear.inc.php rename to www/include/adodb/adodb-pear.inc.php index c8f09331..c48ef132 100644 --- a/www/include/adodb5/adodb-pear.inc.php +++ b/www/include/adodb/adodb-pear.inc.php @@ -1,18 +1,25 @@ + * and Tomas V.V.Cox . Portions (c)1997-2002 The PHP Group. * - * PEAR DB Emulation Layer for ADODB. + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. * - * The following code is modelled on PEAR DB code by Stig Bakken | - * and Tomas V.V.Cox . Portions (c)1997-2002 The PHP Group. + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community */ /* @@ -336,7 +343,7 @@ function parseDSN($dsn) $parsed['hostspec'] = urldecode($str); } - // Get dabase if any + // Get database if any // $dsn => database if (!empty($dsn)) { $parsed['database'] = $dsn; @@ -358,7 +365,7 @@ function parseDSN($dsn) */ function assertExtension($name) { - if (!extension_loaded($name)) { + if (function_exists('dl') && !extension_loaded($name)) { $dlext = (strncmp(PHP_OS,'WIN',3) === 0) ? '.dll' : '.so'; @dl($name . $dlext); } diff --git a/www/include/adodb5/adodb-perf.inc.php b/www/include/adodb/adodb-perf.inc.php similarity index 94% rename from www/include/adodb5/adodb-perf.inc.php rename to www/include/adodb/adodb-perf.inc.php index 69218c6e..d9d8a993 100644 --- a/www/include/adodb5/adodb-perf.inc.php +++ b/www/include/adodb/adodb-perf.inc.php @@ -1,22 +1,23 @@ dataProvider == 'oci8' && $dbT != 'oci8po') { $isql = "insert into $perf_table values($d,:b,:c,:d,:e,:f)"; - } else if ($dbT == 'odbc_mssql' || $dbT == 'informix' || strncmp($dbT,'odbtp',4)==0) { + } else if ($dbT == 'mssqlnative' || $dbT == 'odbc_mssql' || $dbT == 'informix' || strncmp($dbT,'odbtp',4)==0) { $timer = $arr['f']; if ($dbT == 'informix') $sql2 = substr($sql2,0,230); @@ -166,7 +167,13 @@ function adodb_log_sql(&$connx,$sql,$inputarr) global $ADODB_PERF_MIN; if ($errN != 0 || $time >= $ADODB_PERF_MIN) { + if($conn instanceof ADODB_mysqli && $conn->_queryID) { + mysqli_free_result($conn->_queryID); + } $ok = $conn->Execute($isql,$arr); + if($conn instanceof ADODB_mysqli && $conn->_queryID){ + mysqli_free_result($conn->_queryID); + } } else $ok = true; @@ -226,7 +233,7 @@ class adodb_perf { var $cliFormat = "%32s => %s \r\n"; var $sql1 = 'sql1'; // used for casting sql1 to text for mssql var $explain = true; - var $helpurl = 'LogSQL help'; + var $helpurl = 'LogSQL help'; var $createTableSQL = false; var $maxLength = 2000; @@ -260,12 +267,6 @@ function _CPULoad() // Algorithm is taken from // http://social.technet.microsoft.com/Forums/en-US/winservergen/thread/414b0e1b-499c-411e-8a02-6a12e339c0f1/ if (strncmp(PHP_OS,'WIN',3)==0) { - if (PHP_VERSION == '5.0.0') return false; - if (PHP_VERSION == '5.0.1') return false; - if (PHP_VERSION == '5.0.2') return false; - if (PHP_VERSION == '5.0.3') return false; - if (PHP_VERSION == '4.3.10') return false; # see http://bugs.php.net/bug.php?id=31737 - static $FAIL = false; if ($FAIL) return false; @@ -590,7 +591,7 @@ function DBParameter($param) } /* - Raw function returning array of poll paramters + Raw function returning array of poll parameters */ function PollParameters() { @@ -691,12 +692,6 @@ function UI($pollsecs=5) } $this->conn->LogSQL($savelog); - // magic quotes - - if (isset($_GET['sql']) && get_magic_quotes_gpc()) { - $_GET['sql'] = $_GET['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$_GET['sql']); - } - if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10; else $nsql = $_SESSION['ADODB_PERF_SQL']; @@ -721,7 +716,7 @@ function UI($pollsecs=5) if (empty($_GET['hidem'])) echo " @@ -113,19 +103,19 @@ function window_open($window_name, $window=array()) { } // Create a new div to display the content in - $response->addScript("removeElement('{$window_name}');"); - $response->addCreate("window_container", "div", $window_name); - $response->addScript( + $response->script("removeElement('{$window_name}');"); + $response->create("window_container", "div", $window_name); + $response->script( "initialize_window('{$window_name}');" . "el('$window_name').style.display = 'none';" . "el('$window_name').style.visibility = 'hidden';" . "el('$window_name').onclick = function(ev) { focus_window(this.id); };" ); - $response->addAssign($window_name, "innerHTML", $window['header'] . $window['html'] . $window['footer']); - $response->addScript("toggle_window('{$window_name}');" . $window['js']); + $response->assign($window_name, "innerHTML", $window['header'] . $window['html'] . $window['footer']); + $response->script("toggle_window('{$window_name}');" . $window['js']); // Send an XML response to the web browser - return($response->getXML()); + return $response; } @@ -157,7 +147,7 @@ function window_open($window_name, $window=array()) { function window_submit($window_name, $form='', $function='') { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$window_name or !$form) { return($response->getXML()); } + if (!$window_name or !$form) { return $response; } $js = ""; printmsg("DEBUG => webwin_submit() Window: {$window_name} Function: {$function} Form: {$form}", 1); @@ -175,14 +165,14 @@ function window_submit($window_name, $form='', $function='') { // Try looking for the same function in an include file $file = window_find_include($window_name); if ($file) { require_once($file); } - else { $response->addAssign("work_space_content", "innerHTML", "
Invalid window requested: {$window_name}
"); } + else { $response->assign("work_space_content", "innerHTML", "
Invalid window requested: {$window_name}
"); } // Now see if our function is available... if (function_exists($function)) { return($function($window_name, $form)); } // Ok, I couldn't find anything to do.. just return an empty XML response printmsg("NOTICE => webwin_submit() invalid function called! Window: {$window_name} Function: {$function}", 0); - return($response->getXML()); + return $response; } @@ -248,4 +238,4 @@ function window_find_include($window_name) { -?> \ No newline at end of file +?> diff --git a/www/include/xajax_webwin/webwin.js b/www/include/xajax_webwin/webwin.js index 0e5dcae8..b1828596 100644 --- a/www/include/xajax_webwin/webwin.js +++ b/www/include/xajax_webwin/webwin.js @@ -161,11 +161,13 @@ function focus_window(el_name) { // Basically we loop through every window. If we find any windows // that have a higher zIndex than the default we set it to the default. // When we find the window we're focusing we set it's zIndex to default + 1. - nodes = _parent.childNodes; - for (var i=0; i window_default_zindex) nodes[i].style.zIndex = window_default_zindex; + } } } diff --git a/www/index.php b/www/index.php index a6e1c638..597c4551 100644 --- a/www/index.php +++ b/www/index.php @@ -8,7 +8,9 @@ /* --------------------------------------------------------- */ // MP: Since we know ONA will generate a ton of notice level errors, lets turn them off here // I dont believe this will be impactful to anyone. keep an eye out for it however. -error_reporting (E_ALL ^ E_NOTICE); +// MP: Also turning of warnings. php8 whines about things I like to lazily do. its probably +// worth looking at warnings now and then to clean up mess. but there is a lot here +error_reporting (E_ALL ^ E_WARNING ^ E_NOTICE); // Start out the session as a guest with level 0 access. This is for view only mode. // You can enable or disable this by setting the "disable_guest" sysconfig option @@ -53,4 +55,4 @@ // Include "Desktop" Framework require_once($conf['html_desktop']); -?> \ No newline at end of file +?> diff --git a/www/logout.php b/www/logout.php index 0f9da170..b50d4aa6 100644 --- a/www/logout.php +++ b/www/logout.php @@ -16,7 +16,11 @@ printmsg("INFO => [Desktop] {$_SESSION['ona']['auth']['user']['username']} has logged out",0); // Unset session info relating to their account -$_SESSION['ona']['auth'] = array(); +if(isset($_SESSION['ona']['auth'])) { + $_SESSION = array(); +} + +session_destroy(); // Print javascript to redirect them to https so they can login again echo << EOL; -?> \ No newline at end of file +?> diff --git a/www/modules/ona/configuration.inc.php b/www/modules/ona/configuration.inc.php index 2edecfa9..8bac68d5 100644 --- a/www/modules/ona/configuration.inc.php +++ b/www/modules/ona/configuration.inc.php @@ -271,6 +271,254 @@ function config_chksum($options="") { +/////////////////////////////////////////////////////////////////////// +// Function: config_del (string $options='') +// +// Input Options: +// $options = key=value pairs of options for this function. +// multiple sets of key=value pairs should be separated +// by an "&" symbol. +// +// Output: +// Returns a two part list: +// 1. The exit status of the function (0 on success, non-zero on error) +// 2. A textual message displaying information on the selected unit +// record from the database. +// +// Example: list($status, $result) = config_chksum('config=12345'); +// +// Exit codes: +// 0 :: No error +// 1 :: Help text printed - Insufficient or invalid input received +// 2 :: Host specified doesn't exist +// 3 :: Invalid config type specified +// 4 :: The ona_get_next_id() call failed +// 5 :: SQL INSERT failed +/////////////////////////////////////////////////////////////////////// +function config_del($options="") { + + // The important globals + global $conf; + global $self; + global $onadb; + + // Version - UPDATE on every edit! + $version = '1.00'; + + // This debug is set very high as it can contain large configs and sensitive data, you gotta mean it! + printmsg('DEBUG => config_del('.$options.') called', 7); + + // Parse incoming options string to an array + $options = parse_options($options); + + // Return the usage summary if we need to + if ($options['help'] or ( (!$options['config']) and (!$options['host'] or !$options['type']) ) ) { + // NOTE: Help message lines should not exceed 80 characters for proper display on a console + return(array(1, +<< $config['id'])); + if ($status or !$rows) { + $self['error'] = "ERROR => config_del() SQL Query failed: " . $self['error']; + printmsg($self['error'], 0); + return(array(6, $self['error'] . "\n")); + } + + // Return the success notice + $self['error'] = "INFO => Configuration DELETED: {$config['md5_checksum']} ({$options['type']}) from host {$options['host']}"; + printmsg($self['error'],0); + return(array(0, $self['error'] . "\n")); + } + + + + // Maybe one day display the body below.. deminishing returns there + // Otherwise display the record that would have been deleted + $text = << config_del_all('.$options.') called', 7); + + // Parse incoming options string to an array + $options = parse_options($options); + + // Return the usage summary if we need to + if ($options['help'] or !$options['host'] ) { + // NOTE: Help message lines should not exceed 80 characters for proper display on a console + return(array(1, +<< $host['id']), '', 0); + + // Error if an error was returned + if ($count == 0) { + $text = ""; + if ($self['error']) { $text = $self['error'] . "\n"; } + $text .= "ERROR => No config text entries found!\n"; + return(array(2, $text)); + } + + // If "commit" is yes, delete the record + if ($options['commit'] == 'Y') { + + list($status, $rows) = db_delete_records($onadb, 'configurations', array('host_id' => $host['id'])); + if ($status or !$rows) { + $self['error'] = "ERROR => config_del_all() SQL Query failed: " . $self['error']; + printmsg($self['error'], 0); + return(array(6, $self['error'] . "\n")); + } + + // Return the success notice + $self['error'] = "INFO => {$rows} Configuration(s) DELETED from {$host['fqdn']}"; + printmsg($self['error'],0); + return(array(0, $self['error'] . "\n")); + } + + + + // Maybe one day display the body below.. deminishing returns there + // Otherwise display the record that would have been deleted + $text = << config_add('.$options.') called', 7); @@ -316,7 +564,7 @@ function config_add($options="") { // Return the usage summary if we need to if ($options['help'] or !($options['host'] and $options['type'] and $options['config']) ) { // NOTE: Help message lines should not exceed 80 characters for proper display on a console - return(array(1, + return(array(1, << config_diff('.$options.') called', 3); @@ -437,7 +686,7 @@ function config_diff($options="") { // Return the usage summary if we need to if ($options['help'] or ( !$options['host'] or !$options['type'] ) and ( !$options['ida'] or !$options['idb'] ) ) { // NOTE: Help message lines should not exceed 80 characters for proper display on a console - return(array(1, + return(array(1, << $config['host_id'],'configuration_type_id' => $config['configuration_type_id']), 'ctime DESC', '2', - '' + '0' ); } diff --git a/www/modules/ona/dns_record.inc.php b/www/modules/ona/dns_record.inc.php index 7812d15b..145ca73f 100644 --- a/www/modules/ona/dns_record.inc.php +++ b/www/modules/ona/dns_record.inc.php @@ -25,7 +25,8 @@ function dns_record_add($options="") { global $conf, $self, $onadb; // Version - UPDATE on every edit! - $version = '1.12'; + $version = '1.13'; + $debug_val = 3; printmsg("DEBUG => dns_record_add({$options}) called", 3); @@ -119,9 +120,10 @@ function dns_record_add($options="") { $options['view'] = trim($options['view']); // Check the date formatting etc + // Note, anything past 2038-01-10 will be considered disabled. Stupid mysql timestamp. if (isset($options['ebegin'])) { // format the time that was passed in for the database, leave it as 0 if they pass it as 0 - $options['ebegin']=($options['ebegin'] == '0' ? 0 : date('Y-m-j G:i:s',strtotime($options['ebegin'])) ); + $options['ebegin']=($options['ebegin'] == '0' ? '2038-01-19 00:00:00' : date('Y-m-j G:i:s',strtotime($options['ebegin'])) ); } else { // If I got no date, use right now as the date/time $options['ebegin'] = date('Y-m-j G:i:s'); @@ -749,7 +751,7 @@ function dns_record_add($options="") { //FIXME: MP, will this use its own dns_record_add permission? or use host_add? // Check permissions - if (!auth('host_add')) { + if (!auth('host_add',$debug_val)) { $self['error'] = "Permission denied!"; printmsg($self['error'], 0); return(array(10, $self['error'] . "\n")); @@ -859,7 +861,7 @@ function dns_record_modify($options="") { global $conf, $self, $onadb; // Version - UPDATE on every edit! - $version = '1.13'; + $version = '1.14'; printmsg("DEBUG => dns_record_modify({$options}) called", 3); @@ -871,6 +873,7 @@ function dns_record_modify($options="") { (!$options['set_name'] and !$options['set_ip'] and !$options['set_ttl'] and + !$options['set_ebegin'] and !$options['set_pointsto'] and !$options['set_srv_pri'] and !$options['set_srv_weight'] and @@ -926,7 +929,7 @@ function dns_record_modify($options="") { */ // Check permissions - if (!auth('host_modify')) { + if (!auth('host_modify',$debug_val)) { $self['error'] = "Permission denied!"; printmsg($self['error'], 0); return(array(10, $self['error'] . "\n")); @@ -1211,15 +1214,13 @@ function dns_record_modify($options="") { } // Check the date formatting etc - if (isset($options['set_ebegin']) and $options['set_ebegin'] != $dns['ebegin']) { - // format the time that was passed in for the database, leave it as 0 if they pass it as 0 - $options['set_ebegin'] = ($options['set_ebegin'] == '0' ? 0 : date('Y-m-j G:i:s',strtotime($options['set_ebegin'])) ); - // Force the SET variable if its ont 0 and the current record is not 0000:00:00 00:00 - if (!(($options['set_ebegin'] == '0') and ($dns['ebegin'] == '0000-00-00 00:00:00'))) - $SET['ebegin'] = $options['set_ebegin']; - } else { - // If I got no date, use right now as the date/time - $options['set_ebegin'] = date('Y-m-j G:i:s'); + // Note, anything past 2038-01-10 will be considered disabled. Stupid mysql timestamp. + if (array_key_exists('set_ebegin', $options) and $options['set_ebegin'] != $dns['ebegin']) { + // Format the time that was passed in for the database, if 0 set to our disabled timestamp + $options['set_ebegin'] = ($options['set_ebegin'] == '0' ? '2038-01-19 00:00:00' : date('Y-m-j G:i:s',strtotime($options['set_ebegin'])) ); + // Check that our new begin format still does not match the current setting, this accounts for our 0 method + if (!(($options['set_ebegin'] == '2038-01-19 00:00:00') and ($dns['ebegin'] == '2038-01-19 00:00:00'))) + $SET['ebegin'] = $options['set_ebegin']; } // Add the remaining items to the $SET variable @@ -1265,11 +1266,11 @@ function dns_record_modify($options="") { // Update the host record if necessary - //if(count($SET) > 0 and $options['set_ebegin'] != $dns['ebegin']) { if(count($SET) > 0) { - // Use the ebegin value set above - $SET['ebegin'] = $options['set_ebegin']; + // If we are changing records but do not have an ebegin defined, set it to current time + if (!array_key_exists('ebegin', $SET) and $SET['ebegin'] != $dns['ebegin']) + $SET['ebegin'] = date('Y-m-j G:i:s'); // If we are changing the interface id as determined above, check using that value if ($changingint) { @@ -1492,7 +1493,7 @@ function dns_record_del($options="") { // Check permissions - if (!auth('host_del') or !authlvl($host['LVL'])) { + if (!auth('host_del',$debug_val) or !authlvl($host['LVL'])) { $self['error'] = "Permission denied!"; printmsg($self['error'], 0); return(array(10, $self['error'] . "\n")); diff --git a/www/modules/ona/domain.inc.php b/www/modules/ona/domain.inc.php index 9e8ab250..68b974ce 100644 --- a/www/modules/ona/domain.inc.php +++ b/www/modules/ona/domain.inc.php @@ -42,7 +42,7 @@ function domain_add($options="") { printmsg("DEBUG => domain_add({$options}) called", 3); // Version - UPDATE on every edit! - $version = '1.07'; + $version = '1.08'; // Parse incoming options string to an array $options = parse_options($options); @@ -199,6 +199,7 @@ function domain_add($options="") { 'refresh' => $refresh, 'retry' => $retry, 'expiry' => $expiry, + 'ctime' => date('Y-m-j G:i:s',time()), 'minimum' => $minimum, 'default_ttl' => $ttl, 'parent_id' => $parent_domain['id'], @@ -419,7 +420,7 @@ function domain_modify($options="") { printmsg("DEBUG => domain_modify({$options}) called", 3); // Version - UPDATE on every edit! - $version = '1.05'; + $version = '1.06'; // Parse incoming options string to an array $options = parse_options($options); @@ -487,7 +488,7 @@ function domain_modify($options="") { // Test to see that we were able to find the specified record if (!$entry['id']) { - printmsg("DEBUG => Unable to find a domain record using ID {$options['domain']}!",3); + printmsg("ERROR => Unable to find a domain record using ID {$options['domain']}!",3); $self['error'] = "ERROR => Unable to find the domain record using {$options['domain']}!"; return(array(4, $self['error']. "\n")); } @@ -513,7 +514,7 @@ function domain_modify($options="") { list($status, $rows, $domain) = ona_get_domain_record($parentsearch); if (!$domain['id']) { - printmsg("DEBUG => The parent domain specified ({$options['set_parent']}) does not exist!",3); + printmsg("ERROR => The parent domain specified ({$options['set_parent']}) does not exist!",3); $self['error'] = "ERROR => The parent domain specified ({$options['set_parent']}) does not exist!"; return(array(2, $self['error'] . "\n")); } @@ -525,7 +526,7 @@ function domain_modify($options="") { // FIXME: currently renaming zones may not work when using // parent zones. https://github.com/opennetadmin/ona/issues/36 - if (is_string($options['set_name'])) { + if (is_string($options['set_name']) and $options['set_name'] != '') { // trim leading and trailing whitespace from 'value' if ($entry['name'] != trim($options['set_name'])) $SET['name'] = trim($options['set_name']); @@ -534,7 +535,7 @@ function domain_modify($options="") { // Test to see that the new entry isnt already used if ($domain['id'] and $domain['id'] != $entry['id']) { - printmsg("DEBUG => The domain specified ({$options['set_name']}) already exists!",3); + printmsg("ERROR => The domain specified ({$options['set_name']}) already exists!",3); $self['error'] = "ERROR => The domain specified ({$options['set_name']}) already exists!"; return(array(6, $self['error']. "\n")); } @@ -665,7 +666,7 @@ function domain_display($options="") { global $conf, $self, $oracle; // Version - UPDATE on every edit! - $version = '1.01'; + $version = '1.02'; printmsg("DEBUG => domain_display({$options}) called", 3); @@ -722,7 +723,8 @@ function domain_display($options="") { - + // Convert some data + $text_array = $domain; // Build text to return @@ -739,6 +741,13 @@ function domain_display($options="") { EOL; + // change the output format if other than default + if ($options['format'] == 'json') { + $text = $text_array; + } + if ($options['format'] == 'yaml') { + $text = $text_array; + } // Return the success notice return(array(0, $text)); diff --git a/www/modules/ona/host.inc.php b/www/modules/ona/host.inc.php index fe50b6d8..d8298aea 100644 --- a/www/modules/ona/host.inc.php +++ b/www/modules/ona/host.inc.php @@ -404,6 +404,7 @@ interface=[ID|IP|MAC] Select host by IP or MAC // This variable will contain the updated info we'll insert into the DB $SET = array(); + $SET_DEV = array(); // Set options['set_type']? if ($options['set_type']) { diff --git a/www/modules/ona/interface.inc.php b/www/modules/ona/interface.inc.php index 83b722a8..bab663fd 100644 --- a/www/modules/ona/interface.inc.php +++ b/www/modules/ona/interface.inc.php @@ -21,7 +21,7 @@ function interface_add($options="") { printmsg("DEBUG => interface_add({$options}) called", 3); // Version - UPDATE on every edit! - $version = '1.11'; + $version = '1.12'; // Parse incoming options string to an array $options = parse_options($options); @@ -48,6 +48,7 @@ interface_add-v{$version} description=TEXT brief description of the interface natip=ADDRESS IP of NAT address to add with this new interface addptr Auto add a PTR record for new IP + laa Auto gen a Locally Administerd Mac address in 0A range Notes: * DOMAIN will default to {$conf['dns_defaultdomain']} if not specified @@ -65,6 +66,8 @@ interface_add-v{$version} // Set options[addptr] and options[create_a] to Y if they're not set $options['addptr'] = sanitize_YN($options['addptr'], 'Y'); + $options['laa'] = sanitize_YN($options['laa'], 'N'); + // Warn about 'name' and 'description' fields exceeding max lengths if ($options['force'] == 'N') { if(strlen($options['name']) > 255) { @@ -138,6 +141,11 @@ interface_add-v{$version} } } + // If we want locally administered mac addresses + if ($options['laa'] == 'Y') { + $options['mac'] = '0a:'.implode(':', str_split(substr(md5(mt_rand()), 0, 10), 2)); + printmsg("INFO => Generating Locally Administered MAC Address.", 1); + } // Remove any MAC address formatting if ($options['mac']) { @@ -264,13 +272,14 @@ function interface_modify($options="") { printmsg("DEBUG => interface_modify({$options}) called", 3); // Version - UPDATE on every edit! - $version = '1.11'; + $version = '1.14'; // Parse incoming options string to an array $options = parse_options($options); // Set options[use_primary] to N if they're not set $options['use_primary'] = sanitize_YN($options['use_primary'], 'N'); + $options['set_laa'] = sanitize_YN($options['set_laa'], 'N'); // Set options[force] to N if it's not set $options['force'] = sanitize_YN($options['force'], 'N'); @@ -303,7 +312,8 @@ interface=ID or IP or MAC interface ID or IP address set_mac=ADDRESS change the mac address (most formats ok) set_name=NAME interface name (i.e. "FastEthernet0/1.100") set_description=TEXT description (i.e. "VPN link to building 3") - set_last_response=DATE date ip was last seen + set_last_response=DATE date ip was last seen. (set to NULL to remove date) + set_laa Auto gen a Locally Administerd Mac address in 0A range Optional: use_primary[=Y] use the host's primary interface (only applies @@ -481,6 +491,11 @@ interface=ID or IP or MAC interface ID or IP address $SET['ip_addr'] = $options['set_ip']; } + // If we want locally administered mac addresses + if ($options['set_laa'] == 'Y') { + $options['set_mac'] = '0a:'.implode(':', str_split(substr(md5(mt_rand()), 0, 10), 2)); + printmsg("INFO => Generating Locally Administered MAC Address.", 1); + } // Setting an MAC address? if (array_key_exists('set_mac', $options)) { @@ -508,14 +523,19 @@ interface=ID or IP or MAC interface ID or IP address } } } - if($interface['mac_addr'] != $options['set_mac']) + if(strcmp($interface['mac_addr'],$options['set_mac']) !== 0) { $SET['mac_addr'] = $options['set_mac']; + } } // Check the date formatting etc if (isset($options['set_last_response'])) { - // format the time that was passed in for the database - $SET['last_response']=date('Y-m-j G-i-s',strtotime($options['set_last_response'])); + // format the time that was passed in for the database unless its NULL + if ( "${options['set_last_response']}" == "NULL" ) { + $SET['last_response']=NULL; + } else { + $SET['last_response']=date('Y-m-j G-i-s',strtotime($options['set_last_response'])); + } } // Set options[set_name]? diff --git a/www/modules/ona/location.inc.php b/www/modules/ona/location.inc.php index 1cefc7d9..377bd86a 100644 --- a/www/modules/ona/location.inc.php +++ b/www/modules/ona/location.inc.php @@ -27,7 +27,7 @@ function location_add($options="") { global $conf, $self, $onadb; // Version - UPDATE on every edit! - $version = '1.02'; + $version = '1.03'; printmsg("DEBUG => location_add({$options}) called", 3); @@ -70,8 +70,14 @@ function location_add($options="") { $options['reference'] = strtoupper(trim($options['reference'])); if (!$options['zip_code']) { $options['zip_code'] = 0; } - - // check to see if the campus already exists + if (!$options['latitude']) { $options['latitude'] = ''; } + if (!$options['longitude']) { $options['longitude'] = ''; } + if (!$options['address']) { $options['address'] = ''; } + if (!$options['city']) { $options['city'] = ''; } + if (!$options['state']) { $options['state'] = ''; } + if (!$options['misc']) { $options['misc'] = ''; } + + // check to see if the location already exists list($status, $rows, $loc) = ona_get_location_record(array('reference' => $options['reference'])); if ($status or $rows) { @@ -290,7 +296,7 @@ function location_modify($options="") { global $conf, $self, $onadb; // Version - UPDATE on every edit! - $version = '1.01'; + $version = '1.02'; printmsg("DEBUG => location_modify({$options}) called", 3); @@ -345,48 +351,48 @@ function location_modify($options="") { // This variable will contain the updated info we'll insert into the DB $SET = array(); - if ($loc['reference'] != $options['set_reference']) { + if (isset($options['set_reference']) && $loc['reference'] != $options['set_reference']) { $SET['reference'] = $options['set_reference']; $msg .= "INFO => Location UPDATED reference: {$loc['reference']} => {$options['set_reference']}\n"; } // If they are specifying a new name, process it. - if ($loc['name'] != $options['set_name']) { + if (isset($options['set_name']) && $loc['name'] != $options['set_name']) { $SET['name'] = $options['set_name']; $msg .= "INFO => Location UPDATED name: {$loc['name']} => {$options['set_name']}\n"; } - if ($loc['address'] != $options['set_address']) { + if (isset($options['set_address']) && $loc['address'] != $options['set_address']) { $SET['address'] = $options['set_address']; $msg .= "INFO => Location UPDATED address: {$loc['address']} => {$options['set_address']}\n"; } - if ($loc['city'] != $options['set_city']) { + if (isset($options['set_city']) && $loc['city'] != $options['set_city']) { $SET['city'] = $options['set_city']; $msg .= "INFO => Location UPDATED city: {$loc['city']} => {$options['set_city']}\n"; } - if ($loc['state'] != $options['set_state']) { + if (isset($options['set_state']) && $loc['state'] != $options['set_state']) { $SET['state'] = $options['set_state']; $msg .= "INFO => Location UPDATED state: {$loc['state']} => {$options['set_state']}\n"; } - if ($loc['zip_code'] != $options['set_zip_code']) { + if (isset($options['set_zip_code']) && $loc['zip_code'] != $options['set_zip_code']) { $SET['zip_code'] = $options['set_zip_code']; $msg .= "INFO => Location UPDATED zip_code: {$loc['zip_code']} => {$options['set_zip_code']}\n"; } - if ($loc['latitude'] != $options['set_latitude']) { + if (isset($options['set_latitude']) && $loc['latitude'] != $options['set_latitude']) { $SET['latitude'] = $options['set_latitude']; $msg .= "INFO => Location UPDATED latitude: {$loc['latitude']} => {$options['set_latitude']}\n"; } - if ($loc['longitude'] != $options['set_longitude']) { + if (isset($options['set_logitude']) && $loc['longitude'] != $options['set_longitude']) { $SET['longitude'] = $options['set_longitude']; $msg .= "INFO => Location UPDATED longitude: {$loc['longitude']} => {$options['set_longitude']}\n"; } - if ($loc['misc'] != $options['set_misc']) { + if (isset($options['set_misc']) && $loc['misc'] != $options['set_misc']) { $SET['misc'] = $options['set_misc']; $msg .= "INFO => Location UPDATED misc: {$loc['misc']} => {$options['set_misc']}\n"; } diff --git a/www/modules/ona/subnet.inc.php b/www/modules/ona/subnet.inc.php index 8e72305f..20fbf895 100644 --- a/www/modules/ona/subnet.inc.php +++ b/www/modules/ona/subnet.inc.php @@ -247,7 +247,7 @@ function subnet_add($options="") { $fmt = 'ipv6gz'; $ip1 = ip_mangle($ourip, 'bin128'); $sub = gmp_sub("340282366920938463463374607431768211455", $options['netmask']); - $num_hosts = gmp_strval($sub); + $num_hosts = gmp_strval($sub); $last_host = gmp_strval(gmp_add($options['ip'],$num_hosts)); } @@ -271,7 +271,7 @@ function subnet_add($options="") { if ($rows != 0) { $self['error'] = "ERROR => Subnet address conflict! New subnet starts inside an existing subnet."; return(array(6, $self['error'] . "\n" . - "ERROR => Conflicting subnet record ID: {$subnet['id']}\n")); + "ERROR => Conflicting subnet record ID: {$subnet['id']}\n")); } @@ -283,7 +283,7 @@ function subnet_add($options="") { if ($rows != 0) { $self['error'] = "ERROR => Subnet address conflict! New subnet ends inside an existing subnet."; return(array(7, $self['error'] . "\n" . - "ERROR => Conflicting subnet record ID: {$subnet['id']}\n")); + "ERROR => Conflicting subnet record ID: {$subnet['id']}\n")); } @@ -298,7 +298,7 @@ function subnet_add($options="") { if ($rows != 0) { $self['error'] = "ERROR => Subnet address conflict! New subnet would encompass an existing subnet."; return(array(8, $self['error'] . "\n" . - "ERROR => Conflicting subnet record ID: {$subnet['id']}\n")); + "ERROR => Conflicting subnet record ID: {$subnet['id']}\n")); } // The IP/NETMASK look good, set them. @@ -772,7 +772,7 @@ function subnet_del($options="") { if ($options['commit'] == 'Y') { $text = ""; - // FIXME: (add all this) ... + // FIXME: (add all this) ... // SUMMARY: // Delete assignments to any DHCP servers // Delete any DHCP pools on the current subnet @@ -912,7 +912,7 @@ function subnet_del($options="") { // Display any DHCP parameters associated with this subnet // Display subnet Record // Display Host records (and all their sub-records) - // Display custom attributes + // Display custom attributes // Otherwise just display the host record for the host we would have deleted diff --git a/www/modules/sql.inc.php b/www/modules/sql.inc.php index 1b2585a4..6aa4ce4f 100644 --- a/www/modules/sql.inc.php +++ b/www/modules/sql.inc.php @@ -20,7 +20,7 @@ function ona_sql($options="") { global $conf, $onadb, $base; // Version - UPDATE on every edit! - $version = '1.05'; + $version = '1.06'; // TODO: Maybe make this into a sys_config option $srvdir = dirname($base)."/sql"; @@ -118,6 +118,7 @@ function ona_sql($options="") { $plugins = plugin_list(); $files = array(); $srvdirs = array(); + $sqlopts = array(); array_push($srvdirs, $srvdir); // add a local sql dir as well so they don't get overrriden by installs array_push($srvdirs, dirname($base).'/www/local/sql'); diff --git a/www/plugins/ona_nmap_scans/nmap_scan_cron b/www/plugins/ona_nmap_scans/nmap_scan_cron index 2ac58acf..d780268e 100755 --- a/www/plugins/ona_nmap_scans/nmap_scan_cron +++ b/www/plugins/ona_nmap_scans/nmap_scan_cron @@ -142,7 +142,7 @@ for NETENTRY in $NETLIST do NETCLEAN=`echo $NETENTRY|sed "s/\//-/"` echo "INFO => Running NMAP ping only scan on $NETENTRY..." - $NMAPCOMMAND --stylesheet nmap.xsl -sP -R -oX - $NETENTRY > $NMAP_OUTPUT_DIR/$NETCLEAN.xml + $NMAPCOMMAND --stylesheet nmap.xsl -v -PE -sn -R -oX - $NETENTRY > $NMAP_OUTPUT_DIR/$NETCLEAN.xml 2>/dev/null if [ -n "$UPDATE_LAST_RESPONSE" ] then diff --git a/www/plugins/ona_nmap_scans/report.inc.php b/www/plugins/ona_nmap_scans/report.inc.php index ec14d3de..f072dfb6 100644 --- a/www/plugins/ona_nmap_scans/report.inc.php +++ b/www/plugins/ona_nmap_scans/report.inc.php @@ -348,7 +348,7 @@ function rpt_output_html($form) { // Set a red background color $redcolor = "color: red;"; // Skip over hosts that are not in network or database - if ($record['dbip'] == "NOT FOUND") continue; + if (($record['dbip'] == "NOT FOUND") and ($record['netdnsname'] == '')) continue; // If it is only in the database then they should validate the ip or remove from database if (($record['netip'] == $record['dbip']) or ($record['netdnsname'] != $record['dbdnsname'])) { $action = "Ping to verify then delete as desired"; @@ -547,7 +547,7 @@ function rpt_output_text($form) { // Check devices that are down if ($record['netstatus'] == "down") { // Skip over hosts that are not in network or database - if ($record['dbip'] == "NOT FOUND") continue; + if (($record['dbip'] == "NOT FOUND") and ($record['netdnsname'] == '')) continue; // If it is only in the database then they should validate the ip or remove from database if (($record['netip'] == $record['dbip']) or ($record['netdnsname'] != $record['dbdnsname'])) { $action = "Ping to verify then delete as desired"; diff --git a/www/winc/app_advanced_search.inc.php b/www/winc/app_advanced_search.inc.php index 689d58df..ca3c17a6 100644 --- a/www/winc/app_advanced_search.inc.php +++ b/www/winc/app_advanced_search.inc.php @@ -91,7 +91,7 @@ function(ev) { -
+
- ADOdb Performance Monitor for $app
+ ADOdb Performance Monitor for $app
Performance Stats   View SQL   View Tables   Poll Stats", $allowsql ? '   Run SQL' : '', @@ -764,7 +759,6 @@ function UI($pollsecs=5) echo $this->Tables(); break; } global $ADODB_vers; - echo "

$ADODB_vers Sponsored by phpLens
"; } /* @@ -953,7 +947,7 @@ function DoSQLForm() undomq(trim($sql)); + $sql = trim($sql); if (substr($sql,strlen($sql)-1) === ';') { $print = true; $sqla = $this->SplitSQL($sql); @@ -997,18 +991,6 @@ function SplitSQL($sql) return $arr; } - function undomq($m) - { - if (get_magic_quotes_gpc()) { - // undo the damage - $m = str_replace('\\\\','\\',$m); - $m = str_replace('\"','"',$m); - $m = str_replace('\\\'','\'',$m); - } - return $m; -} - - /************************************************************************/ /** diff --git a/www/include/adodb5/adodb-time.inc.php b/www/include/adodb/adodb-time.inc.php similarity index 89% rename from www/include/adodb5/adodb-time.inc.php rename to www/include/adodb/adodb-time.inc.php index 4d2016c7..cfbdc6a5 100644 --- a/www/include/adodb5/adodb-time.inc.php +++ b/www/include/adodb/adodb-time.inc.php @@ -1,78 +1,67 @@ 4 digit year conversion. The maximum is billions of years in the -future, but this is a theoretical limit as the computation of that year -would take too long with the current implementation of adodb_mktime(). - -This library replaces native functions as follows: - -
-	getdate()  with  adodb_getdate()
-	date()     with  adodb_date()
-	gmdate()   with  adodb_gmdate()
-	mktime()   with  adodb_mktime()
-	gmmktime() with  adodb_gmmktime()
-	strftime() with  adodb_strftime()
-	strftime() with  adodb_gmstrftime()
-
- -The parameters are identical, except that adodb_date() accepts a subset -of date()'s field formats. Mktime() will convert from local time to GMT, -and date() will convert from GMT to local time, but daylight savings is -not handled currently. - -This library is independant of the rest of ADOdb, and can be used -as standalone code. - -PERFORMANCE - -For high speed, this library uses the native date functions where -possible, and only switches to PHP code when the dates fall outside -the 32-bit signed integer range. - -GREGORIAN CORRECTION - -Pope Gregory shortened October of A.D. 1582 by ten days. Thursday, -October 4, 1582 (Julian) was followed immediately by Friday, October 15, -1582 (Gregorian). - -Since 0.06, we handle this correctly, so: - -adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582) - == 24 * 3600 (1 day) - -============================================================================= - -COPYRIGHT - -(c) 2003-2014 John Lim and released under BSD-style license except for code by -jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year -and originally found at http://www.php.net/manual/en/function.mktime.php - -============================================================================= - -BUG REPORTS - -These should be posted to the ADOdb forums at - - http://phplens.com/lens/lensforum/topics.php?id=4 +/** + * ADOdb Date Library. + * + * PHP native date functions use integer timestamps for computations. + * Because of this, dates are restricted to the years 1901-2038 on Unix + * and 1970-2038 on Windows due to integer overflow for dates beyond + * those years. This library overcomes these limitations by replacing the + * native function's signed integers (normally 32-bits) with PHP floating + * point numbers (normally 64-bits). + * + * Dates from 100 A.D. to 3000 A.D. and later have been tested. + * The minimum is 100 A.D. as <100 will invoke the 2 => 4 digit year + * conversion. The maximum is billions of years in the future, but this + * is a theoretical limit as the computation of that year would take too + * long with the current implementation of adodb_mktime(). + * + * Replaces native functions as follows: + * - getdate() with adodb_getdate() + * - date() with adodb_date() + * - gmdate() with adodb_gmdate() + * - mktime() with adodb_mktime() + * - gmmktime() with adodb_gmmktime() + * - strftime() with adodb_strftime() + * - strftime() with adodb_gmstrftime() + * + * The parameters are identical, except that adodb_date() accepts a subset + * of date()'s field formats. Mktime() will convert from local time to GMT, + * and date() will convert from GMT to local time, but daylight savings is + * not handled currently. + * + * To improve performance, the native date functions are used whenever + * possible, the library only switches to PHP code when the dates fall outside + * of the 32-bit signed integer range. + * + * This library is independent of the rest of ADOdb, and can be used + * as standalone code. + * + * GREGORIAN CORRECTION + * + * Pope Gregory shortened October of A.D. 1582 by ten days. Thursday, + * October 4, 1582 (Julian) was followed immediately by Friday, October 15, + * 1582 (Gregorian). We handle this correctly, so: + * adodb_mktime(0, 0, 0, 10, 15, 1582) - adodb_mktime(0, 0, 0, 10, 4, 1582) + * == 24 * 3600 (1 day) + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2003-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ +/* ============================================================================= FUNCTION DESCRIPTIONS @@ -267,7 +256,7 @@ * Now adodb_mktime(0,0,0,24,1,2037) works correctly. - 15 July 2007 0.30 -Added PHP 5.2.0 compatability fixes. +Added PHP 5.2.0 compatibility fixes. * gmtime behaviour for 1970 has changed. We use the actual date if it is between 1970 to 2038 to get the * timezone, otherwise we use the current year as the baseline to retrieve the timezone. * Also the timezone's in php 5.2.* support historical data better, eg. if timezone today was +8, but @@ -347,7 +336,7 @@ function adodb_daylight_sv(&$arr, $is_gmt) - 9 Aug 2003 0.10 Fixed bug with dates after 2038. -See http://phplens.com/lens/lensforum/msgs.php?id=6980 +See PHPLens Issue No: 6980 - 1 July 2003 0.09 Added support for Q (Quarter). @@ -403,8 +392,6 @@ function adodb_daylight_sv(&$arr, $is_gmt) */ define('ADODB_DATE_VERSION',0.35); -$ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2); - /* This code was originally for windows. But apparently this problem happens also with Linux, RH 7.3 and later! @@ -420,6 +407,9 @@ function adodb_daylight_sv(&$arr, $is_gmt) if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1); +if (!DEFINED('ADODB_FUTURE_DATE_CUTOFF_YEARS')) + DEFINE('ADODB_FUTURE_DATE_CUTOFF_YEARS',200); + function adodb_date_test_date($y1,$m,$d=13) { $h = round(rand()% 24); @@ -528,8 +518,8 @@ function adodb_date_test() if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950
"; if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990
"; - // Test string formating - print "

Testing date formating

"; + // Test string formatting + print "

Testing date formatting

"; $fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C2822 r s t U w y Y z Z 2003'; $s1 = date($fmt,0); @@ -733,13 +723,12 @@ function adodb_get_gmt_diff_ts($ts) */ function adodb_get_gmt_diff($y,$m,$d) { -static $TZ,$tzo; -global $ADODB_DATETIME_CLASS; + static $TZ,$tzo; if (!defined('ADODB_TEST_DATES')) $y = false; else if ($y < 1970 || $y >= 2038) $y = false; - if ($ADODB_DATETIME_CLASS && $y !== false) { + if ($y !== false) { $dt = new DateTime(); $dt->setISODate($y,$m,$d); if (empty($tzo)) { @@ -816,7 +805,7 @@ function adodb_validdate($y,$m,$d) if ($marr[$m] < $d) return false; - if ($y < 1000 && $y > 3000) return false; + if ($y < 1000 || $y > 3000) return false; return true; } @@ -829,13 +818,23 @@ function adodb_validdate($y,$m,$d) function _adodb_getdate($origd=false,$fast=false,$is_gmt=false) { static $YRS; -global $_month_table_normal,$_month_table_leaf; +global $_month_table_normal,$_month_table_leaf, $_adodb_last_date_call_failed; + + $_adodb_last_date_call_failed = false; $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd)); $_day_power = 86400; $_hour_power = 3600; $_min_power = 60; + $cutoffDate = time() + (60 * 60 * 24 * 365 * ADODB_FUTURE_DATE_CUTOFF_YEARS); + + if ($d > $cutoffDate) + { + $d = $cutoffDate; + $_adodb_last_date_call_failed = true; + } + if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31); @@ -1021,20 +1020,20 @@ function _adodb_getdate($origd=false,$fast=false,$is_gmt=false) 0 => $origd ); } -/* - if ($isphp5) - $dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36); - else - $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); - break;*/ -function adodb_tz_offset($gmt,$isphp5) + +/** + * Compute timezone offset. + * + * @param int $gmt Time offset from GMT, in seconds + * @param bool $ignored Param leftover from removed PHP4-compatibility code + * kept to avoid altering function signature. + * @return string + */ +function adodb_tz_offset($gmt, $ignored=true) { - $zhrs = abs($gmt)/3600; + $zhrs = abs($gmt) / 3600; $hrs = floor($zhrs); - if ($isphp5) - return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); - else - return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); + return sprintf('%s%02d%02d', ($gmt <= 0) ? '+' : '-', $hrs, ($zhrs - $hrs) * 60); } @@ -1067,10 +1066,8 @@ function adodb_date2($fmt, $d=false, $is_gmt=false) */ function adodb_date($fmt,$d=false,$is_gmt=false) { -static $daylight; -global $ADODB_DATETIME_CLASS; -static $jan1_1971; - + static $daylight; + static $jan1_1971; if (!isset($daylight)) { $daylight = function_exists('adodb_daylight_sv'); @@ -1079,7 +1076,15 @@ function adodb_date($fmt,$d=false,$is_gmt=false) if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt); if (!defined('ADODB_TEST_DATES')) { - if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range + + /* + * Format 'Q' is an ADOdb custom format, not supported in PHP + * so if there is a 'Q' in the format, we force it to use our + * function. There is a trivial overhead in this + */ + + if ((abs($d) <= 0x7FFFFFFF) && strpos($fmt,'Q') === false) + { // check if number in 32-bit signed range if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= $jan1_1971) // if windows, must be +ve integer return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d); @@ -1102,8 +1107,6 @@ function adodb_date($fmt,$d=false,$is_gmt=false) $max = strlen($fmt); $dates = ''; - $isphp5 = PHP_VERSION >= 5; - /* at this point, we have the following integer vars to manipulate: $year, $month, $day, $hour, $min, $secs @@ -1114,12 +1117,9 @@ function adodb_date($fmt,$d=false,$is_gmt=false) $dates .= date('e'); break; case 'T': - if ($ADODB_DATETIME_CLASS) { - $dt = new DateTime(); - $dt->SetDate($year,$month,$day); - $dates .= $dt->Format('T'); - } else - $dates .= date('T'); + $dt = new DateTime(); + $dt->SetDate($year,$month,$day); + $dates .= $dt->Format('T'); break; // YEAR case 'L': $dates .= $arr['leap'] ? '1' : '0'; break; @@ -1138,14 +1138,16 @@ function adodb_date($fmt,$d=false,$is_gmt=false) $gmt = adodb_get_gmt_diff($year,$month,$day); - $dates .= ' '.adodb_tz_offset($gmt,$isphp5); + $dates .= ' '.adodb_tz_offset($gmt); break; case 'Y': $dates .= $year; break; case 'y': $dates .= substr($year,strlen($year)-2,2); break; // MONTH case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break; - case 'Q': $dates .= ($month+3)>>2; break; + case 'Q': + $dates .= ceil($month / 3); + break; case 'n': $dates .= $month; break; case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break; case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break; @@ -1153,6 +1155,9 @@ function adodb_date($fmt,$d=false,$is_gmt=false) case 't': $dates .= $arr['ndays']; break; case 'z': $dates .= $arr['yday']; break; case 'w': $dates .= adodb_dow($year,$month,$day); break; + case 'W': + $dates .= sprintf('%02d',ceil( $arr['yday'] / 7) - 1); + break; case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break; case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break; case 'j': $dates .= $day; break; @@ -1171,7 +1176,7 @@ function adodb_date($fmt,$d=false,$is_gmt=false) case 'O': $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day); - $dates .= adodb_tz_offset($gmt,$isphp5); + $dates .= adodb_tz_offset($gmt); break; case 'H': @@ -1375,7 +1380,7 @@ function adodb_strftime($fmt, $ts=false,$is_gmt=false) $sep = substr($tstr,2,1); $hasAM = strrpos($tstr,'M') !== false; */ - # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24 + # see PHPLens Issue No: 14865 for reasoning, and changelog for version 0.24 $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am $sep = substr($dstr,2,1); $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am @@ -1460,3 +1465,16 @@ function adodb_strftime($fmt, $ts=false,$is_gmt=false) $ret = adodb_date($fmtdate, $ts, $is_gmt); return $ret; } + +/** +* Returns the status of the last date calculation and whether it exceeds +* the limit of ADODB_FUTURE_DATE_CUTOFF_YEARS +* +* @return boolean +*/ +function adodb_last_date_status() +{ + global $_adodb_last_date_call_failed; + + return $_adodb_last_date_call_failed; +} diff --git a/www/include/adodb5/adodb-xmlschema.inc.php b/www/include/adodb/adodb-xmlschema.inc.php similarity index 60% rename from www/include/adodb5/adodb-xmlschema.inc.php rename to www/include/adodb/adodb-xmlschema.inc.php index ca5fa567..32b8afa1 100644 --- a/www/include/adodb5/adodb-xmlschema.inc.php +++ b/www/include/adodb/adodb-xmlschema.inc.php @@ -1,150 +1,144 @@ parent = $parent; } /** - * XML Callback to process start elements - * - * @access private - */ + * XML Callback to process start elements + * + * @access private + */ function _tag_open( &$parser, $tag, $attributes ) { } /** - * XML Callback to process CDATA elements - * - * @access private - */ + * XML Callback to process CDATA elements + * + * @access private + */ function _tag_cdata( &$parser, $cdata ) { } /** - * XML Callback to process end elements - * - * @access private - */ + * XML Callback to process end elements + * + * @access private + */ function _tag_close( &$parser, $tag ) { } @@ -154,110 +148,110 @@ function create(&$xmls) { } /** - * Destroys the object - */ + * Destroys the object + */ function destroy() { } /** - * Checks whether the specified RDBMS is supported by the current - * database object or its ranking ancestor. - * - * @param string $platform RDBMS platform name (from ADODB platform list). - * @return boolean TRUE if RDBMS is supported; otherwise returns FALSE. - */ + * Checks whether the specified RDBMS is supported by the current + * database object or its ranking ancestor. + * + * @param string $platform RDBMS platform name (from ADODB platform list). + * @return boolean TRUE if RDBMS is supported; otherwise returns FALSE. + */ function supportedPlatform( $platform = NULL ) { return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE; } /** - * Returns the prefix set by the ranking ancestor of the database object. - * - * @param string $name Prefix string. - * @return string Prefix. - */ + * Returns the prefix set by the ranking ancestor of the database object. + * + * @param string $name Prefix string. + * @return string Prefix. + */ function prefix( $name = '' ) { return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name; } /** - * Extracts a field ID from the specified field. - * - * @param string $field Field. - * @return string Field ID. - */ + * Extracts a field ID from the specified field. + * + * @param string $field Field. + * @return string Field ID. + */ function FieldID( $field ) { return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) ); } } /** -* Creates a table object in ADOdb's datadict format -* -* This class stores information about a database table. As charactaristics -* of the table are loaded from the external source, methods and properties -* of this class are used to build up the table description in ADOdb's -* datadict format. -* -* @package axmls -* @access private -*/ + * Creates a table object in ADOdb's datadict format + * + * This class stores information about a database table. As charactaristics + * of the table are loaded from the external source, methods and properties + * of this class are used to build up the table description in ADOdb's + * datadict format. + * + * @package axmls + * @access private + */ class dbTable extends dbObject { /** - * @var string Table name - */ + * @var string Table name + */ var $name; /** - * @var array Field specifier: Meta-information about each field - */ + * @var array Field specifier: Meta-information about each field + */ var $fields = array(); /** - * @var array List of table indexes. - */ + * @var array List of table indexes. + */ var $indexes = array(); /** - * @var array Table options: Table-level options - */ + * @var array Table options: Table-level options + */ var $opts = array(); /** - * @var string Field index: Keeps track of which field is currently being processed - */ + * @var string Field index: Keeps track of which field is currently being processed + */ var $current_field; /** - * @var boolean Mark table for destruction - * @access private - */ + * @var boolean Mark table for destruction + * @access private + */ var $drop_table; /** - * @var boolean Mark field for destruction (not yet implemented) - * @access private - */ + * @var boolean Mark field for destruction (not yet implemented) + * @access private + */ var $drop_field = array(); /** - * Iniitializes a new table object. - * - * @param string $prefix DB Object prefix - * @param array $attributes Array of table attributes. - */ - function __construct( &$parent, $attributes = NULL ) { + * Iniitializes a new table object. + * + * @param string $prefix DB Object prefix + * @param array $attributes Array of table attributes. + */ + function __construct( $parent, $attributes = NULL ) { $this->parent = $parent; $this->name = $this->prefix($attributes['NAME']); } /** - * XML Callback to process start elements. Elements currently - * processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT. - * - * @access private - */ + * XML Callback to process start elements. Elements currently + * processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT. + * + * @access private + */ function _tag_open( &$parser, $tag, $attributes ) { $this->currentElement = strtoupper( $tag ); @@ -313,10 +307,10 @@ function _tag_open( &$parser, $tag, $attributes ) { } /** - * XML Callback to process CDATA elements - * - * @access private - */ + * XML Callback to process CDATA elements + * + * @access private + */ function _tag_cdata( &$parser, $cdata ) { switch( $this->currentElement ) { // Table constraint @@ -337,10 +331,10 @@ function _tag_cdata( &$parser, $cdata ) { } /** - * XML Callback to process end elements - * - * @access private - */ + * XML Callback to process end elements + * + * @access private + */ function _tag_close( &$parser, $tag ) { $this->currentElement = ''; @@ -358,11 +352,11 @@ function _tag_close( &$parser, $tag ) { } /** - * Adds an index to a table object - * - * @param array $attributes Index attributes - * @return object dbIndex object - */ + * Adds an index to a table object + * + * @param array $attributes Index attributes + * @return object dbIndex object + */ function addIndex( $attributes ) { $name = strtoupper( $attributes['NAME'] ); $this->indexes[$name] = new dbIndex( $this, $attributes ); @@ -370,11 +364,11 @@ function addIndex( $attributes ) { } /** - * Adds data to a table object - * - * @param array $attributes Data attributes - * @return object dbData object - */ + * Adds data to a table object + * + * @param array $attributes Data attributes + * @return object dbData object + */ function addData( $attributes ) { if( !isset( $this->data ) ) { $this->data = new dbData( $this, $attributes ); @@ -383,34 +377,34 @@ function addData( $attributes ) { } /** - * Adds a field to a table object - * - * $name is the name of the table to which the field should be added. - * $type is an ADODB datadict field type. The following field types - * are supported as of ADODB 3.40: - * - C: varchar - * - X: CLOB (character large object) or largest varchar size - * if CLOB is not supported - * - C2: Multibyte varchar - * - X2: Multibyte CLOB - * - B: BLOB (binary large object) - * - D: Date (some databases do not support this, and we return a datetime type) - * - T: Datetime or Timestamp - * - L: Integer field suitable for storing booleans (0 or 1) - * - I: Integer (mapped to I4) - * - I1: 1-byte integer - * - I2: 2-byte integer - * - I4: 4-byte integer - * - I8: 8-byte integer - * - F: Floating point number - * - N: Numeric or decimal number - * - * @param string $name Name of the table to which the field will be added. - * @param string $type ADODB datadict field type. - * @param string $size Field size - * @param array $opts Field options array - * @return array Field specifier array - */ + * Adds a field to a table object + * + * $name is the name of the table to which the field should be added. + * $type is an ADODB datadict field type. The following field types + * are supported as of ADODB 3.40: + * - C: varchar + * - X: CLOB (character large object) or largest varchar size + * if CLOB is not supported + * - C2: Multibyte varchar + * - X2: Multibyte CLOB + * - B: BLOB (binary large object) + * - D: Date (some databases do not support this, and we return a datetime type) + * - T: Datetime or Timestamp + * - L: Integer field suitable for storing booleans (0 or 1) + * - I: Integer (mapped to I4) + * - I1: 1-byte integer + * - I2: 2-byte integer + * - I4: 4-byte integer + * - I8: 8-byte integer + * - F: Floating point number + * - N: Numeric or decimal number + * + * @param string $name Name of the table to which the field will be added. + * @param string $type ADODB datadict field type. + * @param string $size Field size + * @param array $opts Field options array + * @return array Field specifier array + */ function addField( $name, $type, $size = NULL, $opts = NULL ) { $field_id = $this->FieldID( $name ); @@ -435,16 +429,16 @@ function addField( $name, $type, $size = NULL, $opts = NULL ) { } /** - * Adds a field option to the current field specifier - * - * This method adds a field option allowed by the ADOdb datadict - * and appends it to the given field. - * - * @param string $field Field name - * @param string $opt ADOdb field option - * @param mixed $value Field option value - * @return array Field specifier array - */ + * Adds a field option to the current field specifier + * + * This method adds a field option allowed by the ADOdb datadict + * and appends it to the given field. + * + * @param string $field Field name + * @param string $opt ADOdb field option + * @param mixed $value Field option value + * @return array Field specifier array + */ function addFieldOpt( $field, $opt, $value = NULL ) { if( !isset( $value ) ) { $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt; @@ -455,14 +449,14 @@ function addFieldOpt( $field, $opt, $value = NULL ) { } /** - * Adds an option to the table - * - * This method takes a comma-separated list of table-level options - * and appends them to the table object. - * - * @param string $opt Table option - * @return array Options - */ + * Adds an option to the table + * + * This method takes a comma-separated list of table-level options + * and appends them to the table object. + * + * @param string $opt Table option + * @return array Options + */ function addTableOpt( $opt ) { if(isset($this->currentPlatform)) { $this->opts[$this->parent->db->databaseType] = $opt; @@ -472,11 +466,11 @@ function addTableOpt( $opt ) { /** - * Generates the SQL that will create the table in the database - * - * @param object $xmls adoSchema object - * @return array Array containing table creation SQL - */ + * Generates the SQL that will create the table in the database + * + * @param object $xmls adoSchema object + * @return array Array containing table creation SQL + */ function create( &$xmls ) { $sql = array(); @@ -584,8 +578,8 @@ function create( &$xmls ) { } /** - * Marks a field or table for destruction - */ + * Marks a field or table for destruction + */ function drop() { if( isset( $this->current_field ) ) { // Drop the current field @@ -602,61 +596,61 @@ function drop() { } /** -* Creates an index object in ADOdb's datadict format -* -* This class stores information about a database index. As charactaristics -* of the index are loaded from the external source, methods and properties -* of this class are used to build up the index description in ADOdb's -* datadict format. -* -* @package axmls -* @access private -*/ + * Creates an index object in ADOdb's datadict format + * + * This class stores information about a database index. As charactaristics + * of the index are loaded from the external source, methods and properties + * of this class are used to build up the index description in ADOdb's + * datadict format. + * + * @package axmls + * @access private + */ class dbIndex extends dbObject { /** - * @var string Index name - */ + * @var string Index name + */ var $name; /** - * @var array Index options: Index-level options - */ + * @var array Index options: Index-level options + */ var $opts = array(); /** - * @var array Indexed fields: Table columns included in this index - */ + * @var array Indexed fields: Table columns included in this index + */ var $columns = array(); /** - * @var boolean Mark index for destruction - * @access private - */ + * @var boolean Mark index for destruction + * @access private + */ var $drop = FALSE; /** - * Initializes the new dbIndex object. - * - * @param object $parent Parent object - * @param array $attributes Attributes - * - * @internal - */ - function __construct( &$parent, $attributes = NULL ) { + * Initializes the new dbIndex object. + * + * @param object $parent Parent object + * @param array $attributes Attributes + * + * @internal + */ + function __construct( $parent, $attributes = NULL ) { $this->parent = $parent; $this->name = $this->prefix ($attributes['NAME']); } /** - * XML Callback to process start elements - * - * Processes XML opening tags. - * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH. - * - * @access private - */ + * XML Callback to process start elements + * + * Processes XML opening tags. + * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH. + * + * @access private + */ function _tag_open( &$parser, $tag, $attributes ) { $this->currentElement = strtoupper( $tag ); @@ -678,12 +672,12 @@ function _tag_open( &$parser, $tag, $attributes ) { } /** - * XML Callback to process CDATA elements - * - * Processes XML cdata. - * - * @access private - */ + * XML Callback to process CDATA elements + * + * Processes XML cdata. + * + * @access private + */ function _tag_cdata( &$parser, $cdata ) { switch( $this->currentElement ) { // Index field name @@ -696,10 +690,10 @@ function _tag_cdata( &$parser, $cdata ) { } /** - * XML Callback to process end elements - * - * @access private - */ + * XML Callback to process end elements + * + * @access private + */ function _tag_close( &$parser, $tag ) { $this->currentElement = ''; @@ -711,11 +705,11 @@ function _tag_close( &$parser, $tag ) { } /** - * Adds a field to the index - * - * @param string $name Field name - * @return string Field list - */ + * Adds a field to the index + * + * @param string $name Field name + * @return string Field list + */ function addField( $name ) { $this->columns[$this->FieldID( $name )] = $name; @@ -724,11 +718,11 @@ function addField( $name ) { } /** - * Adds options to the index - * - * @param string $opt Comma-separated list of index options. - * @return string Option list - */ + * Adds options to the index + * + * @param string $opt Comma-separated list of index options. + * @return string Option list + */ function addIndexOpt( $opt ) { $this->opts[] = $opt; @@ -737,11 +731,11 @@ function addIndexOpt( $opt ) { } /** - * Generates the SQL that will create the index in the database - * - * @param object $xmls adoSchema object - * @return array Array containing index creation SQL - */ + * Generates the SQL that will create the index in the database + * + * @param object $xmls adoSchema object + * @return array Array containing index creation SQL + */ function create( &$xmls ) { if( $this->drop ) { return NULL; @@ -758,21 +752,21 @@ function create( &$xmls ) { } /** - * Marks an index for destruction - */ + * Marks an index for destruction + */ function drop() { $this->drop = TRUE; } } /** -* Creates a data object in ADOdb's datadict format -* -* This class stores information about table data. -* -* @package axmls -* @access private -*/ + * Creates a data object in ADOdb's datadict format + * + * This class stores information about table data. + * + * @package axmls + * @access private + */ class dbData extends dbObject { var $data = array(); @@ -780,25 +774,25 @@ class dbData extends dbObject { var $row; /** - * Initializes the new dbIndex object. - * - * @param object $parent Parent object - * @param array $attributes Attributes - * - * @internal - */ - function __construct( &$parent, $attributes = NULL ) { + * Initializes the new dbIndex object. + * + * @param object $parent Parent object + * @param array $attributes Attributes + * + * @internal + */ + function __construct( $parent, $attributes = NULL ) { $this->parent = $parent; } /** - * XML Callback to process start elements - * - * Processes XML opening tags. - * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH. - * - * @access private - */ + * XML Callback to process start elements + * + * Processes XML opening tags. + * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH. + * + * @access private + */ function _tag_open( &$parser, $tag, $attributes ) { $this->currentElement = strtoupper( $tag ); @@ -815,12 +809,12 @@ function _tag_open( &$parser, $tag, $attributes ) { } /** - * XML Callback to process CDATA elements - * - * Processes XML cdata. - * - * @access private - */ + * XML Callback to process CDATA elements + * + * Processes XML cdata. + * + * @access private + */ function _tag_cdata( &$parser, $cdata ) { switch( $this->currentElement ) { // Index field name @@ -833,10 +827,10 @@ function _tag_cdata( &$parser, $cdata ) { } /** - * XML Callback to process end elements - * - * @access private - */ + * XML Callback to process end elements + * + * @access private + */ function _tag_close( &$parser, $tag ) { $this->currentElement = ''; @@ -848,11 +842,11 @@ function _tag_close( &$parser, $tag ) { } /** - * Adds a field to the index - * - * @param string $name Field name - * @return string Field list - */ + * Adds a field to the index + * + * @param string $name Field name + * @return string Field list + */ function addField( $attributes ) { if( isset( $attributes['NAME'] ) ) { $name = $attributes['NAME']; @@ -865,11 +859,11 @@ function addField( $attributes ) { } /** - * Adds options to the index - * - * @param string $opt Comma-separated list of index options. - * @return string Option list - */ + * Adds options to the index + * + * @param string $opt Comma-separated list of index options. + * @return string Option list + */ function addData( $cdata ) { if( !isset( $this->data[$this->row] ) ) { $this->data[$this->row] = array(); @@ -883,11 +877,11 @@ function addData( $cdata ) { } /** - * Generates the SQL that will create the index in the database - * - * @param object $xmls adoSchema object - * @return array Array containing index creation SQL - */ + * Generates the SQL that will create the index in the database + * + * @param object $xmls adoSchema object + * @return array Array containing index creation SQL + */ function create( &$xmls ) { $table = $xmls->dict->TableName($this->parent->name); $table_field_count = count($this->parent->fields); @@ -901,7 +895,8 @@ function create( &$xmls ) { foreach( $row as $field_id => $field_data ) { if( !array_key_exists( $field_id, $table_fields ) ) { if( is_numeric( $field_id ) ) { - $field_id = reset( array_keys( $table_fields ) ); + $keys = array_keys($table_fields); + $field_id = reset($keys); } else { continue; } @@ -953,40 +948,40 @@ function create( &$xmls ) { } /** -* Creates the SQL to execute a list of provided SQL queries -* -* @package axmls -* @access private -*/ + * Creates the SQL to execute a list of provided SQL queries + * + * @package axmls + * @access private + */ class dbQuerySet extends dbObject { /** - * @var array List of SQL queries - */ + * @var array List of SQL queries + */ var $queries = array(); /** - * @var string String used to build of a query line by line - */ + * @var string String used to build of a query line by line + */ var $query; /** - * @var string Query prefix key - */ + * @var string Query prefix key + */ var $prefixKey = ''; /** - * @var boolean Auto prefix enable (TRUE) - */ + * @var boolean Auto prefix enable (TRUE) + */ var $prefixMethod = 'AUTO'; /** - * Initializes the query set. - * - * @param object $parent Parent object - * @param array $attributes Attributes - */ - function __construct( &$parent, $attributes = NULL ) { + * Initializes the query set. + * + * @param object $parent Parent object + * @param array $attributes Attributes + */ + function __construct( $parent, $attributes = NULL ) { $this->parent = $parent; // Overrides the manual prefix key @@ -1011,11 +1006,11 @@ function __construct( &$parent, $attributes = NULL ) { } /** - * XML Callback to process start elements. Elements currently - * processed are: QUERY. - * - * @access private - */ + * XML Callback to process start elements. Elements currently + * processed are: QUERY. + * + * @access private + */ function _tag_open( &$parser, $tag, $attributes ) { $this->currentElement = strtoupper( $tag ); @@ -1036,8 +1031,8 @@ function _tag_open( &$parser, $tag, $attributes ) { } /** - * XML Callback to process CDATA elements - */ + * XML Callback to process CDATA elements + */ function _tag_cdata( &$parser, $cdata ) { switch( $this->currentElement ) { // Line of queryset SQL data @@ -1050,10 +1045,10 @@ function _tag_cdata( &$parser, $cdata ) { } /** - * XML Callback to process end elements - * - * @access private - */ + * XML Callback to process end elements + * + * @access private + */ function _tag_close( &$parser, $tag ) { $this->currentElement = ''; @@ -1073,10 +1068,10 @@ function _tag_close( &$parser, $tag ) { } /** - * Re-initializes the query. - * - * @return boolean TRUE - */ + * Re-initializes the query. + * + * @return boolean TRUE + */ function newQuery() { $this->query = ''; @@ -1084,10 +1079,10 @@ function newQuery() { } /** - * Discards the existing query. - * - * @return boolean TRUE - */ + * Discards the existing query. + * + * @return boolean TRUE + */ function discardQuery() { unset( $this->query ); @@ -1095,11 +1090,11 @@ function discardQuery() { } /** - * Appends a line to a query that is being built line by line - * - * @param string $data Line of SQL data or NULL to initialize a new query - * @return string SQL query string. - */ + * Appends a line to a query that is being built line by line + * + * @param string $data Line of SQL data or NULL to initialize a new query + * @return string SQL query string. + */ function buildQuery( $sql = NULL ) { if( !isset( $this->query ) OR empty( $sql ) ) { return FALSE; @@ -1111,10 +1106,10 @@ function buildQuery( $sql = NULL ) { } /** - * Adds a completed query to the query list - * - * @return string SQL of added query - */ + * Adds a completed query to the query list + * + * @return string SQL of added query + */ function addQuery() { if( !isset( $this->query ) ) { return FALSE; @@ -1128,11 +1123,11 @@ function addQuery() { } /** - * Creates and returns the current query set - * - * @param object $xmls adoSchema object - * @return array Query set - */ + * Creates and returns the current query set + * + * @param object $xmls adoSchema object + * @return array Query set + */ function create( &$xmls ) { foreach( $this->queries as $id => $query ) { switch( $this->prefixMethod ) { @@ -1168,13 +1163,13 @@ function create( &$xmls ) { } /** - * Rebuilds the query with the prefix attached to any objects - * - * @param string $regex Regex used to add prefix - * @param string $query SQL query string - * @param string $prefix Prefix to be appended to tables, indices, etc. - * @return string Prefixed SQL query string. - */ + * Rebuilds the query with the prefix attached to any objects + * + * @param string $regex Regex used to add prefix + * @param string $query SQL query string + * @param string $prefix Prefix to be appended to tables, indices, etc. + * @return string Prefixed SQL query string. + */ function prefixQuery( $regex, $query, $prefix = NULL ) { if( !isset( $prefix ) ) { return $query; @@ -1204,113 +1199,102 @@ function prefixQuery( $regex, $query, $prefix = NULL ) { } /** -* Loads and parses an XML file, creating an array of "ready-to-run" SQL statements -* -* This class is used to load and parse the XML file, to create an array of SQL statements -* that can be used to build a database, and to build the database using the SQL array. -* -* @tutorial getting_started.pkg -* -* @author Richard Tango-Lowy & Dan Cech -* @version $Revision: 1.12 $ -* -* @package axmls -*/ + * Loads and parses an XML file, creating an array of "ready-to-run" SQL statements + * + * This class is used to load and parse the XML file, to create an array of SQL statements + * that can be used to build a database, and to build the database using the SQL array. + * + * @tutorial getting_started.pkg + * + * @author Richard Tango-Lowy & Dan Cech + * @version 1.12 + * + * @package axmls + */ class adoSchema { /** - * @var array Array containing SQL queries to generate all objects - * @access private - */ + * @var array Array containing SQL queries to generate all objects + * @access private + */ var $sqlArray; /** - * @var object ADOdb connection object - * @access private - */ + * @var object ADOdb connection object + * @access private + */ var $db; /** - * @var object ADOdb Data Dictionary - * @access private - */ + * @var object ADOdb Data Dictionary + * @access private + */ var $dict; /** - * @var string Current XML element - * @access private - */ + * @var string Current XML element + * @access private + */ var $currentElement = ''; /** - * @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database - * @access private - */ + * @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database + * @access private + */ var $upgrade = ''; /** - * @var string Optional object prefix - * @access private - */ + * @var string Optional object prefix + * @access private + */ var $objectPrefix = ''; /** - * @var long Original Magic Quotes Runtime value - * @access private - */ - var $mgq; - - /** - * @var long System debug - * @access private - */ + * @var long System debug + * @access private + */ var $debug; /** - * @var string Regular expression to find schema version - * @access private - */ + * @var string Regular expression to find schema version + * @access private + */ var $versionRegex = '//'; /** - * @var string Current schema version - * @access private - */ + * @var string Current schema version + * @access private + */ var $schemaVersion; /** - * @var int Success of last Schema execution - */ + * @var int Success of last Schema execution + */ var $success; /** - * @var bool Execute SQL inline as it is generated - */ + * @var bool Execute SQL inline as it is generated + */ var $executeInline; /** - * @var bool Continue SQL execution if errors occur - */ + * @var bool Continue SQL execution if errors occur + */ var $continueOnError; /** - * Creates an adoSchema object - * - * Creating an adoSchema object is the first step in processing an XML schema. - * The only parameter is an ADOdb database connection object, which must already - * have been created. - * - * @param object $db ADOdb database connection object. - */ + * Creates an adoSchema object + * + * Creating an adoSchema object is the first step in processing an XML schema. + * The only parameter is an ADOdb database connection object, which must already + * have been created. + * + * @param object $db ADOdb database connection object. + */ function __construct( $db ) { - // Initialize the environment - $this->mgq = get_magic_quotes_runtime(); - ini_set("magic_quotes_runtime", 0); - #set_magic_quotes_runtime(0); - $this->db = $db; $this->debug = $this->db->debug; - $this->dict = NewDataDictionary( $this->db ); + $this->dict = newDataDictionary( $this->db ); $this->sqlArray = array(); $this->schemaVersion = XMLS_SCHEMA_VERSION; $this->executeInline( XMLS_EXECUTE_INLINE ); @@ -1319,21 +1303,21 @@ function __construct( $db ) { } /** - * Sets the method to be used for upgrading an existing database - * - * Use this method to specify how existing database objects should be upgraded. - * The method option can be set to ALTER, REPLACE, BEST, or NONE. ALTER attempts to - * alter each database object directly, REPLACE attempts to rebuild each object - * from scratch, BEST attempts to determine the best upgrade method for each - * object, and NONE disables upgrading. - * - * This method is not yet used by AXMLS, but exists for backward compatibility. - * The ALTER method is automatically assumed when the adoSchema object is - * instantiated; other upgrade methods are not currently supported. - * - * @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE) - * @returns string Upgrade method used - */ + * Sets the method to be used for upgrading an existing database + * + * Use this method to specify how existing database objects should be upgraded. + * The method option can be set to ALTER, REPLACE, BEST, or NONE. ALTER attempts to + * alter each database object directly, REPLACE attempts to rebuild each object + * from scratch, BEST attempts to determine the best upgrade method for each + * object, and NONE disables upgrading. + * + * This method is not yet used by AXMLS, but exists for backward compatibility. + * The ALTER method is automatically assumed when the adoSchema object is + * instantiated; other upgrade methods are not currently supported. + * + * @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE) + * @returns string Upgrade method used + */ function SetUpgradeMethod( $method = '' ) { if( !is_string( $method ) ) { return FALSE; @@ -1364,18 +1348,19 @@ function SetUpgradeMethod( $method = '' ) { } /** - * Enables/disables inline SQL execution. - * - * Call this method to enable or disable inline execution of the schema. If the mode is set to TRUE (inline execution), - * AXMLS applies the SQL to the database immediately as each schema entity is parsed. If the mode - * is set to FALSE (post execution), AXMLS parses the entire schema and you will need to call adoSchema::ExecuteSchema() - * to apply the schema to the database. - * - * @param bool $mode execute - * @return bool current execution mode - * - * @see ParseSchema(), ExecuteSchema() - */ + * Enables/disables inline SQL execution. + * + * Call this method to enable or disable inline execution of the schema. If the mode is set to TRUE (inline execution), + * AXMLS applies the SQL to the database immediately as each schema entity is parsed. If the mode + * is set to FALSE (post execution), AXMLS parses the entire schema and you will need to call adoSchema::ExecuteSchema() + * to apply the schema to the database. + * + * @param bool $mode execute + * @return bool current execution mode + * + * @see ParseSchema() + * @see ExecuteSchema() + */ function ExecuteInline( $mode = NULL ) { if( is_bool( $mode ) ) { $this->executeInline = $mode; @@ -1385,18 +1370,19 @@ function ExecuteInline( $mode = NULL ) { } /** - * Enables/disables SQL continue on error. - * - * Call this method to enable or disable continuation of SQL execution if an error occurs. - * If the mode is set to TRUE (continue), AXMLS will continue to apply SQL to the database, even if an error occurs. - * If the mode is set to FALSE (halt), AXMLS will halt execution of generated sql if an error occurs, though parsing - * of the schema will continue. - * - * @param bool $mode execute - * @return bool current continueOnError mode - * - * @see addSQL(), ExecuteSchema() - */ + * Enables/disables SQL continue on error. + * + * Call this method to enable or disable continuation of SQL execution if an error occurs. + * If the mode is set to TRUE (continue), AXMLS will continue to apply SQL to the database, even if an error occurs. + * If the mode is set to FALSE (halt), AXMLS will halt execution of generated sql if an error occurs, though parsing + * of the schema will continue. + * + * @param bool $mode execute + * @return bool current continueOnError mode + * + * @see addSQL() + * @see ExecuteSchema() + */ function ContinueOnError( $mode = NULL ) { if( is_bool( $mode ) ) { $this->continueOnError = $mode; @@ -1406,33 +1392,34 @@ function ContinueOnError( $mode = NULL ) { } /** - * Loads an XML schema from a file and converts it to SQL. - * - * Call this method to load the specified schema (see the DTD for the proper format) from - * the filesystem and generate the SQL necessary to create the database described. - * @see ParseSchemaString() - * - * @param string $file Name of XML schema file. - * @param bool $returnSchema Return schema rather than parsing. - * @return array Array of SQL queries, ready to execute - */ + * Loads an XML schema from a file and converts it to SQL. + * + * Call this method to load the specified schema (see the DTD for the proper format) from + * the filesystem and generate the SQL necessary to create the database described. + * @see ParseSchemaString() + * + * @param string $file Name of XML schema file. + * @param bool $returnSchema Return schema rather than parsing. + * @return array Array of SQL queries, ready to execute + */ function ParseSchema( $filename, $returnSchema = FALSE ) { return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema ); } /** - * Loads an XML schema from a file and converts it to SQL. - * - * Call this method to load the specified schema from a file (see the DTD for the proper format) - * and generate the SQL necessary to create the database described by the schema. - * - * @param string $file Name of XML schema file. - * @param bool $returnSchema Return schema rather than parsing. - * @return array Array of SQL queries, ready to execute. - * - * @deprecated Replaced by adoSchema::ParseSchema() and adoSchema::ParseSchemaString() - * @see ParseSchema(), ParseSchemaString() - */ + * Loads an XML schema from a file and converts it to SQL. + * + * Call this method to load the specified schema from a file (see the DTD for the proper format) + * and generate the SQL necessary to create the database described by the schema. + * + * @param string $file Name of XML schema file. + * @param bool $returnSchema Return schema rather than parsing. + * @return array Array of SQL queries, ready to execute. + * + * @deprecated Replaced by adoSchema::ParseSchema() and adoSchema::ParseSchemaString() + * @see ParseSchema() + * @see ParseSchemaString() + */ function ParseSchemaFile( $filename, $returnSchema = FALSE ) { // Open the file if( !($fp = fopen( $filename, 'r' )) ) { @@ -1475,16 +1462,16 @@ function ParseSchemaFile( $filename, $returnSchema = FALSE ) { } /** - * Converts an XML schema string to SQL. - * - * Call this method to parse a string containing an XML schema (see the DTD for the proper format) - * and generate the SQL necessary to create the database described by the schema. - * @see ParseSchema() - * - * @param string $xmlstring XML schema string. - * @param bool $returnSchema Return schema rather than parsing. - * @return array Array of SQL queries, ready to execute. - */ + * Converts an XML schema string to SQL. + * + * Call this method to parse a string containing an XML schema (see the DTD for the proper format) + * and generate the SQL necessary to create the database described by the schema. + * @see ParseSchema() + * + * @param string $xmlstring XML schema string. + * @param bool $returnSchema Return schema rather than parsing. + * @return array Array of SQL queries, ready to execute. + */ function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) { if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) { return FALSE; @@ -1518,31 +1505,31 @@ function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) { } /** - * Loads an XML schema from a file and converts it to uninstallation SQL. - * - * Call this method to load the specified schema (see the DTD for the proper format) from - * the filesystem and generate the SQL necessary to remove the database described. - * @see RemoveSchemaString() - * - * @param string $file Name of XML schema file. - * @param bool $returnSchema Return schema rather than parsing. - * @return array Array of SQL queries, ready to execute - */ + * Loads an XML schema from a file and converts it to uninstallation SQL. + * + * Call this method to load the specified schema (see the DTD for the proper format) from + * the filesystem and generate the SQL necessary to remove the database described. + * @see RemoveSchemaString() + * + * @param string $file Name of XML schema file. + * @param bool $returnSchema Return schema rather than parsing. + * @return array Array of SQL queries, ready to execute + */ function RemoveSchema( $filename, $returnSchema = FALSE ) { return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema ); } /** - * Converts an XML schema string to uninstallation SQL. - * - * Call this method to parse a string containing an XML schema (see the DTD for the proper format) - * and generate the SQL necessary to uninstall the database described by the schema. - * @see RemoveSchema() - * - * @param string $schema XML schema string. - * @param bool $returnSchema Return schema rather than parsing. - * @return array Array of SQL queries, ready to execute. - */ + * Converts an XML schema string to uninstallation SQL. + * + * Call this method to parse a string containing an XML schema (see the DTD for the proper format) + * and generate the SQL necessary to uninstall the database described by the schema. + * @see RemoveSchema() + * + * @param string $schema XML schema string. + * @param bool $returnSchema Return schema rather than parsing. + * @return array Array of SQL queries, ready to execute. + */ function RemoveSchemaString( $schema, $returnSchema = FALSE ) { // grab current version @@ -1554,18 +1541,20 @@ function RemoveSchemaString( $schema, $returnSchema = FALSE ) { } /** - * Applies the current XML schema to the database (post execution). - * - * Call this method to apply the current schema (generally created by calling - * ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes, - * and executing other SQL specified in the schema) after parsing. - * @see ParseSchema(), ParseSchemaString(), ExecuteInline() - * - * @param array $sqlArray Array of SQL statements that will be applied rather than - * the current schema. - * @param boolean $continueOnErr Continue to apply the schema even if an error occurs. - * @returns integer 0 if failure, 1 if errors, 2 if successful. - */ + * Applies the current XML schema to the database (post execution). + * + * Call this method to apply the current schema (generally created by calling + * ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes, + * and executing other SQL specified in the schema) after parsing. + * @see ParseSchema() + * @see ParseSchemaString() + * @see ExecuteInline() + * + * @param array $sqlArray Array of SQL statements that will be applied rather than + * the current schema. + * @param boolean $continueOnErr Continue to apply the schema even if an error occurs. + * @returns integer 0 if failure, 1 if errors, 2 if successful. + */ function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) { if( !is_bool( $continueOnErr ) ) { $continueOnErr = $this->ContinueOnError(); @@ -1585,28 +1574,28 @@ function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) { } /** - * Returns the current SQL array. - * - * Call this method to fetch the array of SQL queries resulting from - * ParseSchema() or ParseSchemaString(). - * - * @param string $format Format: HTML, TEXT, or NONE (PHP array) - * @return array Array of SQL statements or FALSE if an error occurs - */ + * Returns the current SQL array. + * + * Call this method to fetch the array of SQL queries resulting from + * ParseSchema() or ParseSchemaString(). + * + * @param string $format Format: HTML, TEXT, or NONE (PHP array) + * @return array Array of SQL statements or FALSE if an error occurs + */ function PrintSQL( $format = 'NONE' ) { $sqlArray = null; return $this->getSQL( $format, $sqlArray ); } /** - * Saves the current SQL array to the local filesystem as a list of SQL queries. - * - * Call this method to save the array of SQL queries (generally resulting from a - * parsed XML schema) to the filesystem. - * - * @param string $filename Path and name where the file should be saved. - * @return boolean TRUE if save is successful, else FALSE. - */ + * Saves the current SQL array to the local filesystem as a list of SQL queries. + * + * Call this method to save the array of SQL queries (generally resulting from a + * parsed XML schema) to the filesystem. + * + * @param string $filename Path and name where the file should be saved. + * @return boolean TRUE if save is successful, else FALSE. + */ function SaveSQL( $filename = './schema.sql' ) { if( !isset( $sqlArray ) ) { @@ -1625,12 +1614,12 @@ function SaveSQL( $filename = './schema.sql' ) { } /** - * Create an xml parser - * - * @return object PHP XML parser object - * - * @access private - */ + * Create an xml parser + * + * @return object PHP XML parser object + * + * @access private + */ function create_parser() { // Create the parser $xmlParser = xml_parser_create(); @@ -1644,10 +1633,10 @@ function create_parser() { } /** - * XML Callback to process start elements - * - * @access private - */ + * XML Callback to process start elements + * + * @access private + */ function _tag_open( &$parser, $tag, $attributes ) { switch( strtoupper( $tag ) ) { case 'TABLE': @@ -1667,39 +1656,39 @@ function _tag_open( &$parser, $tag, $attributes ) { } /** - * XML Callback to process CDATA elements - * - * @access private - */ + * XML Callback to process CDATA elements + * + * @access private + */ function _tag_cdata( &$parser, $cdata ) { } /** - * XML Callback to process end elements - * - * @access private - * @internal - */ + * XML Callback to process end elements + * + * @access private + * @internal + */ function _tag_close( &$parser, $tag ) { } /** - * Converts an XML schema string to the specified DTD version. - * - * Call this method to convert a string containing an XML schema to a different AXMLS - * DTD version. For instance, to convert a schema created for an pre-1.0 version for - * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version - * parameter is specified, the schema will be converted to the current DTD version. - * If the newFile parameter is provided, the converted schema will be written to the specified - * file. - * @see ConvertSchemaFile() - * - * @param string $schema String containing XML schema that will be converted. - * @param string $newVersion DTD version to convert to. - * @param string $newFile File name of (converted) output file. - * @return string Converted XML schema or FALSE if an error occurs. - */ + * Converts an XML schema string to the specified DTD version. + * + * Call this method to convert a string containing an XML schema to a different AXMLS + * DTD version. For instance, to convert a schema created for an pre-1.0 version for + * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version + * parameter is specified, the schema will be converted to the current DTD version. + * If the newFile parameter is provided, the converted schema will be written to the specified + * file. + * @see ConvertSchemaFile() + * + * @param string $schema String containing XML schema that will be converted. + * @param string $newVersion DTD version to convert to. + * @param string $newFile File name of (converted) output file. + * @return string Converted XML schema or FALSE if an error occurs. + */ function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) { // grab current version @@ -1725,29 +1714,22 @@ function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) { return $result; } - // compat for pre-4.3 - jlim - function _file_get_contents($path) - { - if (function_exists('file_get_contents')) return file_get_contents($path); - return join('',file($path)); - } - - /** - * Converts an XML schema file to the specified DTD version. - * - * Call this method to convert the specified XML schema file to a different AXMLS - * DTD version. For instance, to convert a schema created for an pre-1.0 version for - * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version - * parameter is specified, the schema will be converted to the current DTD version. - * If the newFile parameter is provided, the converted schema will be written to the specified - * file. - * @see ConvertSchemaString() - * - * @param string $filename Name of XML schema file that will be converted. - * @param string $newVersion DTD version to convert to. - * @param string $newFile File name of (converted) output file. - * @return string Converted XML schema or FALSE if an error occurs. - */ + /** + * Converts an XML schema file to the specified DTD version. + * + * Call this method to convert the specified XML schema file to a different AXMLS + * DTD version. For instance, to convert a schema created for an pre-1.0 version for + * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version + * parameter is specified, the schema will be converted to the current DTD version. + * If the newFile parameter is provided, the converted schema will be written to the specified + * file. + * @see ConvertSchemaString() + * + * @param string $filename Name of XML schema file that will be converted. + * @param string $newVersion DTD version to convert to. + * @param string $newFile File name of (converted) output file. + * @return string Converted XML schema or FALSE if an error occurs. + */ function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) { // grab current version @@ -1760,7 +1742,7 @@ function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) { } if( $version == $newVersion ) { - $result = _file_get_contents( $filename ); + $result = file_get_contents( $filename ); // remove unicode BOM if present if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) { @@ -1799,7 +1781,7 @@ function TransformSchema( $schema, $xsl, $schematype='string' ) return FALSE; } - $schema = _file_get_contents( $schema ); + $schema = file_get_contents( $schema ); break; case 'string': default: @@ -1810,14 +1792,14 @@ function TransformSchema( $schema, $xsl, $schematype='string' ) $arguments = array ( '/_xml' => $schema, - '/_xsl' => _file_get_contents( $xsl_file ) + '/_xsl' => file_get_contents( $xsl_file ) ); // create an XSLT processor $xh = xslt_create (); // set error handler - xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler')); + xslt_set_error_handler ($xh, array ($this, 'xslt_error_handler')); // process the schema $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments); @@ -1828,15 +1810,15 @@ function TransformSchema( $schema, $xsl, $schematype='string' ) } /** - * Processes XSLT transformation errors - * - * @param object $parser XML parser object - * @param integer $errno Error number - * @param integer $level Error level - * @param array $fields Error information fields - * - * @access private - */ + * Processes XSLT transformation errors + * + * @param object $parser XML parser object + * @param integer $errno Error number + * @param integer $level Error level + * @param array $fields Error information fields + * + * @access private + */ function xslt_error_handler( $parser, $errno, $level, $fields ) { if( is_array( $fields ) ) { $msg = array( @@ -1881,14 +1863,14 @@ function xslt_error_handler( $parser, $errno, $level, $fields ) { } /** - * Returns the AXMLS Schema Version of the requested XML schema file. - * - * Call this method to obtain the AXMLS DTD version of the requested XML schema file. - * @see SchemaStringVersion() - * - * @param string $filename AXMLS schema file - * @return string Schema version number or FALSE on error - */ + * Returns the AXMLS Schema Version of the requested XML schema file. + * + * Call this method to obtain the AXMLS DTD version of the requested XML schema file. + * @see SchemaStringVersion() + * + * @param string $filename AXMLS schema file + * @return string Schema version number or FALSE on error + */ function SchemaFileVersion( $filename ) { // Open the file if( !($fp = fopen( $filename, 'r' )) ) { @@ -1907,14 +1889,14 @@ function SchemaFileVersion( $filename ) { } /** - * Returns the AXMLS Schema Version of the provided XML schema string. - * - * Call this method to obtain the AXMLS DTD version of the provided XML schema string. - * @see SchemaFileVersion() - * - * @param string $xmlstring XML schema string - * @return string Schema version number or FALSE on error - */ + * Returns the AXMLS Schema Version of the provided XML schema string. + * + * Call this method to obtain the AXMLS DTD version of the provided XML schema string. + * @see SchemaFileVersion() + * + * @param string $xmlstring XML schema string + * @return string Schema version number or FALSE on error + */ function SchemaStringVersion( $xmlstring ) { if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) { return FALSE; @@ -1928,15 +1910,15 @@ function SchemaStringVersion( $xmlstring ) { } /** - * Extracts an XML schema from an existing database. - * - * Call this method to create an XML schema string from an existing database. - * If the data parameter is set to TRUE, AXMLS will include the data from the database - * in the schema. - * - * @param boolean $data Include data in schema dump - * @return string Generated XML schema - */ + * Extracts an XML schema from an existing database. + * + * Call this method to create an XML schema string from an existing database. + * If the data parameter is set to TRUE, AXMLS will include the data from the database + * in the schema. + * + * @param boolean $data Include data in schema dump + * @return string Generated XML schema + */ function ExtractSchema( $data = FALSE ) { $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM ); @@ -2035,15 +2017,15 @@ function ExtractSchema( $data = FALSE ) { } /** - * Sets a prefix for database objects - * - * Call this method to set a standard prefix that will be prepended to all database tables - * and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix. - * - * @param string $prefix Prefix that will be prepended. - * @param boolean $underscore If TRUE, automatically append an underscore character to the prefix. - * @return boolean TRUE if successful, else FALSE - */ + * Sets a prefix for database objects + * + * Call this method to set a standard prefix that will be prepended to all database tables + * and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix. + * + * @param string $prefix Prefix that will be prepended. + * @param boolean $underscore If TRUE, automatically append an underscore character to the prefix. + * @return boolean TRUE if successful, else FALSE + */ function SetPrefix( $prefix = '', $underscore = TRUE ) { switch( TRUE ) { // clear prefix @@ -2070,13 +2052,13 @@ function SetPrefix( $prefix = '', $underscore = TRUE ) { } /** - * Returns an object name with the current prefix prepended. - * - * @param string $name Name - * @return string Prefixed name - * - * @access private - */ + * Returns an object name with the current prefix prepended. + * + * @param string $name Name + * @return string Prefixed name + * + * @access private + */ function prefix( $name = '' ) { // if prefix is set if( !empty( $this->objectPrefix ) ) { @@ -2090,13 +2072,13 @@ function prefix( $name = '' ) { } /** - * Checks if element references a specific platform - * - * @param string $platform Requested platform - * @returns boolean TRUE if platform check succeeds - * - * @access private - */ + * Checks if element references a specific platform + * + * @param string $platform Requested platform + * @returns boolean TRUE if platform check succeeds + * + * @access private + */ function supportedPlatform( $platform = NULL ) { $regex = '/^(\w*\|)*' . $this->db->databaseType . '(\|\w*)*$/'; @@ -2110,22 +2092,22 @@ function supportedPlatform( $platform = NULL ) { } /** - * Clears the array of generated SQL. - * - * @access private - */ + * Clears the array of generated SQL. + * + * @access private + */ function clearSQL() { $this->sqlArray = array(); } /** - * Adds SQL into the SQL array. - * - * @param mixed $sql SQL to Add - * @return boolean TRUE if successful, else FALSE. - * - * @access private - */ + * Adds SQL into the SQL array. + * + * @param mixed $sql SQL to Add + * @return boolean TRUE if successful, else FALSE. + * + * @access private + */ function addSQL( $sql = NULL ) { if( is_array( $sql ) ) { foreach( $sql as $line ) { @@ -2161,13 +2143,13 @@ function addSQL( $sql = NULL ) { } /** - * Gets the SQL array in the specified format. - * - * @param string $format Format - * @return mixed SQL - * - * @access private - */ + * Gets the SQL array in the specified format. + * + * @param string $format Format + * @return mixed SQL + * + * @access private + */ function getSQL( $format = NULL, $sqlArray = NULL ) { if( !is_array( $sqlArray ) ) { $sqlArray = $this->sqlArray; @@ -2189,22 +2171,19 @@ function getSQL( $format = NULL, $sqlArray = NULL ) { } /** - * Destroys an adoSchema object. - * - * Call this method to clean up after an adoSchema object that is no longer in use. - * @deprecated adoSchema now cleans up automatically. - */ - function Destroy() { - ini_set("magic_quotes_runtime", $this->mgq ); - #set_magic_quotes_runtime( $this->mgq ); - } + * Destroys an adoSchema object. + * + * Call this method to clean up after an adoSchema object that is no longer in use. + * @deprecated adoSchema now cleans up automatically. + */ + function Destroy() {} } /** -* Message logging function -* -* @access private -*/ + * Message logging function + * + * @access private + */ function logMsg( $msg, $title = NULL, $force = FALSE ) { if( XMLS_DEBUG or $force ) { echo '
';
diff --git a/www/include/adodb5/adodb-xmlschema03.inc.php b/www/include/adodb/adodb-xmlschema03.inc.php
similarity index 54%
rename from www/include/adodb5/adodb-xmlschema03.inc.php
rename to www/include/adodb/adodb-xmlschema03.inc.php
index c1ecb885..a03386b3 100644
--- a/www/include/adodb5/adodb-xmlschema03.inc.php
+++ b/www/include/adodb/adodb-xmlschema03.inc.php
@@ -1,91 +1,85 @@
 parent = $parent;
 	}
 
 	/**
-	* XML Callback to process start elements
-	*
-	* @access private
-	*/
-	function _tag_open( &$parser, $tag, $attributes ) {
+	 * XML Callback to process start elements
+	 *
+	 * @access private
+	 */
+	function _tag_open( $parser, $tag, $attributes ) {
 
 	}
 
 	/**
-	* XML Callback to process CDATA elements
-	*
-	* @access private
-	*/
-	function _tag_cdata( &$parser, $cdata ) {
+	 * XML Callback to process CDATA elements
+	 *
+	 * @access private
+	 */
+	function _tag_cdata( $parser, $cdata ) {
 
 	}
 
 	/**
-	* XML Callback to process end elements
-	*
-	* @access private
-	*/
-	function _tag_close( &$parser, $tag ) {
+	 * XML Callback to process end elements
+	 *
+	 * @access private
+	 */
+	function _tag_close( $parser, $tag ) {
 
 	}
 
@@ -172,118 +166,118 @@ function create(&$xmls) {
 	}
 
 	/**
-	* Destroys the object
-	*/
+	 * Destroys the object
+	 */
 	function destroy() {
 	}
 
 	/**
-	* Checks whether the specified RDBMS is supported by the current
-	* database object or its ranking ancestor.
-	*
-	* @param string $platform RDBMS platform name (from ADODB platform list).
-	* @return boolean TRUE if RDBMS is supported; otherwise returns FALSE.
-	*/
+	 * Checks whether the specified RDBMS is supported by the current
+	 * database object or its ranking ancestor.
+	 *
+	 * @param string $platform RDBMS platform name (from ADODB platform list).
+	 * @return boolean TRUE if RDBMS is supported; otherwise returns FALSE.
+	 */
 	function supportedPlatform( $platform = NULL ) {
 		return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
 	}
 
 	/**
-	* Returns the prefix set by the ranking ancestor of the database object.
-	*
-	* @param string $name Prefix string.
-	* @return string Prefix.
-	*/
+	 * Returns the prefix set by the ranking ancestor of the database object.
+	 *
+	 * @param string $name Prefix string.
+	 * @return string Prefix.
+	 */
 	function prefix( $name = '' ) {
 		return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
 	}
 
 	/**
-	* Extracts a field ID from the specified field.
-	*
-	* @param string $field Field.
-	* @return string Field ID.
-	*/
-	function FieldID( $field ) {
+	 * Extracts a field ID from the specified field.
+	 *
+	 * @param string $field Field.
+	 * @return string Field ID.
+	 */
+	function fieldID( $field ) {
 		return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
 	}
 }
 
 /**
-* Creates a table object in ADOdb's datadict format
-*
-* This class stores information about a database table. As charactaristics
-* of the table are loaded from the external source, methods and properties
-* of this class are used to build up the table description in ADOdb's
-* datadict format.
-*
-* @package axmls
-* @access private
-*/
+ * Creates a table object in ADOdb's datadict format
+ *
+ * This class stores information about a database table. As charactaristics
+ * of the table are loaded from the external source, methods and properties
+ * of this class are used to build up the table description in ADOdb's
+ * datadict format.
+ *
+ * @package axmls
+ * @access private
+ */
 class dbTable extends dbObject {
 
 	/**
-	* @var string Table name
-	*/
+	 * @var string Table name
+	 */
 	var $name;
 
 	/**
-	* @var array Field specifier: Meta-information about each field
-	*/
+	 * @var array Field specifier: Meta-information about each field
+	 */
 	var $fields = array();
 
 	/**
-	* @var array List of table indexes.
-	*/
+	 * @var array List of table indexes.
+	 */
 	var $indexes = array();
 
 	/**
-	* @var array Table options: Table-level options
-	*/
+	 * @var array Table options: Table-level options
+	 */
 	var $opts = array();
 
 	/**
-	* @var string Field index: Keeps track of which field is currently being processed
-	*/
+	 * @var string Field index: Keeps track of which field is currently being processed
+	 */
 	var $current_field;
 
 	/**
-	* @var boolean Mark table for destruction
-	* @access private
-	*/
+	 * @var boolean Mark table for destruction
+	 * @access private
+	 */
 	var $drop_table;
 
 	/**
-	* @var boolean Mark field for destruction (not yet implemented)
-	* @access private
-	*/
+	 * @var boolean Mark field for destruction (not yet implemented)
+	 * @access private
+	 */
 	var $drop_field = array();
 
 	/**
-	* @var array Platform-specific options
-	* @access private
-	*/
+	 * @var array Platform-specific options
+	 * @access private
+	 */
 	var $currentPlatform = true;
 
 
 	/**
-	* Iniitializes a new table object.
-	*
-	* @param string $prefix DB Object prefix
-	* @param array $attributes Array of table attributes.
-	*/
-	function __construct( &$parent, $attributes = NULL ) {
+	 * Iniitializes a new table object.
+	 *
+	 * @param string $prefix DB Object prefix
+	 * @param array $attributes Array of table attributes.
+	 */
+	function __construct( $parent, $attributes = NULL ) {
 		$this->parent = $parent;
 		$this->name = $this->prefix($attributes['NAME']);
 	}
 
 	/**
-	* XML Callback to process start elements. Elements currently
-	* processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT.
-	*
-	* @access private
-	*/
-	function _tag_open( &$parser, $tag, $attributes ) {
+	 * XML Callback to process start elements. Elements currently
+	 * processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT.
+	 *
+	 * @access private
+	 */
+	function _tag_open( $parser, $tag, $attributes ) {
 		$this->currentElement = strtoupper( $tag );
 
 		switch( $this->currentElement ) {
@@ -341,12 +335,20 @@ function _tag_open( &$parser, $tag, $attributes ) {
 	}
 
 	/**
-	* XML Callback to process CDATA elements
-	*
-	* @access private
-	*/
-	function _tag_cdata( &$parser, $cdata ) {
+	 * XML Callback to process CDATA elements
+	 *
+	 * @access private
+	 */
+	function _tag_cdata( $parser, $cdata ) {
 		switch( $this->currentElement ) {
+			// Table or field comment
+			case 'DESCR':
+				if( isset( $this->current_field ) ) {
+					$this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
+				} else {
+					$this->addTableComment( $cdata );
+				}
+				break;
 			// Table/field constraint
 			case 'CONSTRAINT':
 				if( isset( $this->current_field ) ) {
@@ -369,11 +371,11 @@ function _tag_cdata( &$parser, $cdata ) {
 	}
 
 	/**
-	* XML Callback to process end elements
-	*
-	* @access private
-	*/
-	function _tag_close( &$parser, $tag ) {
+	 * XML Callback to process end elements
+	 *
+	 * @access private
+	 */
+	function _tag_close( $parser, $tag ) {
 		$this->currentElement = '';
 
 		switch( strtoupper( $tag ) ) {
@@ -395,11 +397,11 @@ function _tag_close( &$parser, $tag ) {
 	}
 
 	/**
-	* Adds an index to a table object
-	*
-	* @param array $attributes Index attributes
-	* @return object dbIndex object
-	*/
+	 * Adds an index to a table object
+	 *
+	 * @param array $attributes Index attributes
+	 * @return object dbIndex object
+	 */
 	function addIndex( $attributes ) {
 		$name = strtoupper( $attributes['NAME'] );
 		$this->indexes[$name] = new dbIndex( $this, $attributes );
@@ -407,11 +409,11 @@ function addIndex( $attributes ) {
 	}
 
 	/**
-	* Adds data to a table object
-	*
-	* @param array $attributes Data attributes
-	* @return object dbData object
-	*/
+	 * Adds data to a table object
+	 *
+	 * @param array $attributes Data attributes
+	 * @return object dbData object
+	 */
 	function addData( $attributes ) {
 		if( !isset( $this->data ) ) {
 			$this->data = new dbData( $this, $attributes );
@@ -420,36 +422,36 @@ function addData( $attributes ) {
 	}
 
 	/**
-	* Adds a field to a table object
-	*
-	* $name is the name of the table to which the field should be added.
-	* $type is an ADODB datadict field type. The following field types
-	* are supported as of ADODB 3.40:
-	* 	- C:  varchar
-	*	- X:  CLOB (character large object) or largest varchar size
-	*	   if CLOB is not supported
-	*	- C2: Multibyte varchar
-	*	- X2: Multibyte CLOB
-	*	- B:  BLOB (binary large object)
-	*	- D:  Date (some databases do not support this, and we return a datetime type)
-	*	- T:  Datetime or Timestamp
-	*	- L:  Integer field suitable for storing booleans (0 or 1)
-	*	- I:  Integer (mapped to I4)
-	*	- I1: 1-byte integer
-	*	- I2: 2-byte integer
-	*	- I4: 4-byte integer
-	*	- I8: 8-byte integer
-	*	- F:  Floating point number
-	*	- N:  Numeric or decimal number
-	*
-	* @param string $name Name of the table to which the field will be added.
-	* @param string $type	ADODB datadict field type.
-	* @param string $size	Field size
-	* @param array $opts	Field options array
-	* @return array Field specifier array
-	*/
+	 * Adds a field to a table object
+	 *
+	 * $name is the name of the table to which the field should be added.
+	 * $type is an ADODB datadict field type. The following field types
+	 * are supported as of ADODB 3.40:
+	 * 	- C:  varchar
+	 *	- X:  CLOB (character large object) or largest varchar size
+	 *	   if CLOB is not supported
+	 *	- C2: Multibyte varchar
+	 *	- X2: Multibyte CLOB
+	 *	- B:  BLOB (binary large object)
+	 *	- D:  Date (some databases do not support this, and we return a datetime type)
+	 *	- T:  Datetime or Timestamp
+	 *	- L:  Integer field suitable for storing booleans (0 or 1)
+	 *	- I:  Integer (mapped to I4)
+	 *	- I1: 1-byte integer
+	 *	- I2: 2-byte integer
+	 *	- I4: 4-byte integer
+	 *	- I8: 8-byte integer
+	 *	- F:  Floating point number
+	 *	- N:  Numeric or decimal number
+	 *
+	 * @param string $name Name of the table to which the field will be added.
+	 * @param string $type	ADODB datadict field type.
+	 * @param string $size	Field size
+	 * @param array $opts	Field options array
+	 * @return array Field specifier array
+	 */
 	function addField( $name, $type, $size = NULL, $opts = NULL ) {
-		$field_id = $this->FieldID( $name );
+		$field_id = $this->fieldID( $name );
 
 		// Set the field index so we know where we are
 		$this->current_field = $field_id;
@@ -474,16 +476,16 @@ function addField( $name, $type, $size = NULL, $opts = NULL ) {
 	}
 
 	/**
-	* Adds a field option to the current field specifier
-	*
-	* This method adds a field option allowed by the ADOdb datadict
-	* and appends it to the given field.
-	*
-	* @param string $field	Field name
-	* @param string $opt ADOdb field option
-	* @param mixed $value Field option value
-	* @return array Field specifier array
-	*/
+	 * Adds a field option to the current field specifier
+	 *
+	 * This method adds a field option allowed by the ADOdb datadict
+	 * and appends it to the given field.
+	 *
+	 * @param string $field	Field name
+	 * @param string $opt ADOdb field option
+	 * @param mixed $value Field option value
+	 * @return array Field specifier array
+	 */
 	function addFieldOpt( $field, $opt, $value = NULL ) {
 		if( $this->currentPlatform ) {
 		if( !isset( $value ) ) {
@@ -496,35 +498,39 @@ function addFieldOpt( $field, $opt, $value = NULL ) {
 	}
 
 	/**
-	* Adds an option to the table
-	*
-	* This method takes a comma-separated list of table-level options
-	* and appends them to the table object.
-	*
-	* @param string $opt Table option
-	* @return array Options
-	*/
+	 * Adds an option to the table
+	 *
+	 * This method takes a comma-separated list of table-level options
+	 * and appends them to the table object.
+	 *
+	 * @param string $opt Table option
+	 * @return array Options
+	 */
 	function addTableOpt( $opt ) {
 		if(isset($this->currentPlatform)) {
-			$this->opts[$this->parent->db->databaseType] = $opt;
+			$this->opts[$this->parent->db->dataProvider] = $opt;
 		}
 		return $this->opts;
 	}
 
+	function addTableComment( $opt ) {
+		$this->opts['comment'] = $opt;
+		return $this->opts;
+	}
 
 	/**
-	* Generates the SQL that will create the table in the database
-	*
-	* @param object $xmls adoSchema object
-	* @return array Array containing table creation SQL
-	*/
+	 * Generates the SQL that will create the table in the database
+	 *
+	 * @param object $xmls adoSchema object
+	 * @return array Array containing table creation SQL
+	 */
 	function create( &$xmls ) {
 		$sql = array();
 
 		// drop any existing indexes
-		if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
+		if( is_array( $legacy_indexes = $xmls->dict->metaIndexes( $this->name ) ) ) {
 			foreach( $legacy_indexes as $index => $index_details ) {
-				$sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
+				$sql[] = $xmls->dict->dropIndexSQL( $index, $this->name );
 			}
 		}
 
@@ -534,10 +540,10 @@ function create( &$xmls ) {
 		}
 
 		// if table exists
-		if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
+		if( is_array( $legacy_fields = $xmls->dict->metaColumns( $this->name ) ) ) {
 			// drop table
 			if( $this->drop_table ) {
-				$sql[] = $xmls->dict->DropTableSQL( $this->name );
+				$sql[] = $xmls->dict->dropTableSQL( $this->name );
 
 				return $sql;
 			}
@@ -545,7 +551,7 @@ function create( &$xmls ) {
 			// drop any existing fields not in schema
 			foreach( $legacy_fields as $field_id => $field ) {
 				if( !isset( $this->fields[$field_id] ) ) {
-					$sql[] = $xmls->dict->DropColumnSQL( $this->name, $field->name );
+					$sql[] = $xmls->dict->dropColumnSQL( $this->name, $field->name );
 				}
 			}
 		// if table doesn't exist
@@ -579,8 +585,11 @@ function create( &$xmls ) {
 					// Option has an argument.
 					if( is_array( $opt ) ) {
 						$key = key( $opt );
-						$value = $opt[key( $opt )];
-						@$fldarray[$field_id][$key] .= $value;
+						$value = $opt[$key];
+						if(!isset($fldarray[$field_id][$key])) {
+							$fldarray[$field_id][$key] = "";
+						}
+						$fldarray[$field_id][$key] .= $value;
 					// Option doesn't have arguments
 					} else {
 						$fldarray[$field_id][$opt] = $opt;
@@ -591,21 +600,21 @@ function create( &$xmls ) {
 
 		if( empty( $legacy_fields ) ) {
 			// Create the new table
-			$sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
-			logMsg( end( $sql ), 'Generated CreateTableSQL' );
+			$sql[] = $xmls->dict->createTableSQL( $this->name, $fldarray, $this->opts );
+			logMsg( end( $sql ), 'Generated createTableSQL' );
 		} else {
 			// Upgrade an existing table
 			logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
 			switch( $xmls->upgrade ) {
 				// Use ChangeTableSQL
 				case 'ALTER':
-					logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
-					$sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
+					logMsg( 'Generated changeTableSQL (ALTERing table)' );
+					$sql[] = $xmls->dict->changeTableSQL( $this->name, $fldarray, $this->opts );
 					break;
 				case 'REPLACE':
 					logMsg( 'Doing upgrade REPLACE (testing)' );
-					$sql[] = $xmls->dict->DropTableSQL( $this->name );
-					$sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
+					$sql[] = $xmls->dict->dropTableSQL( $this->name );
+					$sql[] = $xmls->dict->createTableSQL( $this->name, $fldarray, $this->opts );
 					break;
 				// ignore table
 				default:
@@ -625,8 +634,8 @@ function create( &$xmls ) {
 	}
 
 	/**
-	* Marks a field or table for destruction
-	*/
+	 * Marks a field or table for destruction
+	 */
 	function drop() {
 		if( isset( $this->current_field ) ) {
 			// Drop the current field
@@ -643,62 +652,62 @@ function drop() {
 }
 
 /**
-* Creates an index object in ADOdb's datadict format
-*
-* This class stores information about a database index. As charactaristics
-* of the index are loaded from the external source, methods and properties
-* of this class are used to build up the index description in ADOdb's
-* datadict format.
-*
-* @package axmls
-* @access private
-*/
+ * Creates an index object in ADOdb's datadict format
+ *
+ * This class stores information about a database index. As charactaristics
+ * of the index are loaded from the external source, methods and properties
+ * of this class are used to build up the index description in ADOdb's
+ * datadict format.
+ *
+ * @package axmls
+ * @access private
+ */
 class dbIndex extends dbObject {
 
 	/**
-	* @var string	Index name
-	*/
+	 * @var string	Index name
+	 */
 	var $name;
 
 	/**
-	* @var array	Index options: Index-level options
-	*/
+	 * @var array	Index options: Index-level options
+	 */
 	var $opts = array();
 
 	/**
-	* @var array	Indexed fields: Table columns included in this index
-	*/
+	 * @var array	Indexed fields: Table columns included in this index
+	 */
 	var $columns = array();
 
 	/**
-	* @var boolean Mark index for destruction
-	* @access private
-	*/
+	 * @var boolean Mark index for destruction
+	 * @access private
+	 */
 	var $drop = FALSE;
 
 	/**
-	* Initializes the new dbIndex object.
-	*
-	* @param object $parent Parent object
-	* @param array $attributes Attributes
-	*
-	* @internal
-	*/
-	function __construct( &$parent, $attributes = NULL ) {
+	 * Initializes the new dbIndex object.
+	 *
+	 * @param object $parent Parent object
+	 * @param array $attributes Attributes
+	 *
+	 * @internal
+	 */
+	function __construct( $parent, $attributes = NULL ) {
 		$this->parent = $parent;
 
 		$this->name = $this->prefix ($attributes['NAME']);
 	}
 
 	/**
-	* XML Callback to process start elements
-	*
-	* Processes XML opening tags.
-	* Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH.
-	*
-	* @access private
-	*/
-	function _tag_open( &$parser, $tag, $attributes ) {
+	 * XML Callback to process start elements
+	 *
+	 * Processes XML opening tags.
+	 * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH.
+	 *
+	 * @access private
+	 */
+	function _tag_open( $parser, $tag, $attributes ) {
 		$this->currentElement = strtoupper( $tag );
 
 		switch( $this->currentElement ) {
@@ -719,13 +728,13 @@ function _tag_open( &$parser, $tag, $attributes ) {
 	}
 
 	/**
-	* XML Callback to process CDATA elements
-	*
-	* Processes XML cdata.
-	*
-	* @access private
-	*/
-	function _tag_cdata( &$parser, $cdata ) {
+	 * XML Callback to process CDATA elements
+	 *
+	 * Processes XML cdata.
+	 *
+	 * @access private
+	 */
+	function _tag_cdata( $parser, $cdata ) {
 		switch( $this->currentElement ) {
 			// Index field name
 			case 'COL':
@@ -737,11 +746,11 @@ function _tag_cdata( &$parser, $cdata ) {
 	}
 
 	/**
-	* XML Callback to process end elements
-	*
-	* @access private
-	*/
-	function _tag_close( &$parser, $tag ) {
+	 * XML Callback to process end elements
+	 *
+	 * @access private
+	 */
+	function _tag_close( $parser, $tag ) {
 		$this->currentElement = '';
 
 		switch( strtoupper( $tag ) ) {
@@ -752,24 +761,24 @@ function _tag_close( &$parser, $tag ) {
 	}
 
 	/**
-	* Adds a field to the index
-	*
-	* @param string $name Field name
-	* @return string Field list
-	*/
+	 * Adds a field to the index
+	 *
+	 * @param string $name Field name
+	 * @return string Field list
+	 */
 	function addField( $name ) {
-		$this->columns[$this->FieldID( $name )] = $name;
+		$this->columns[$this->fieldID( $name )] = $name;
 
 		// Return the field list
 		return $this->columns;
 	}
 
 	/**
-	* Adds options to the index
-	*
-	* @param string $opt Comma-separated list of index options.
-	* @return string Option list
-	*/
+	 * Adds options to the index
+	 *
+	 * @param string $opt Comma-separated list of index options.
+	 * @return string Option list
+	 */
 	function addIndexOpt( $opt ) {
 		$this->opts[] = $opt;
 
@@ -778,11 +787,11 @@ function addIndexOpt( $opt ) {
 	}
 
 	/**
-	* Generates the SQL that will create the index in the database
-	*
-	* @param object $xmls adoSchema object
-	* @return array Array containing index creation SQL
-	*/
+	 * Generates the SQL that will create the index in the database
+	 *
+	 * @param object $xmls adoSchema object
+	 * @return array Array containing index creation SQL
+	 */
 	function create( &$xmls ) {
 		if( $this->drop ) {
 			return NULL;
@@ -795,26 +804,26 @@ function create( &$xmls ) {
 			}
 		}
 
-		return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
+		return $xmls->dict->createIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
 	}
 
 	/**
-	* Marks an index for destruction
-	*/
+	 * Marks an index for destruction
+	 */
 	function drop() {
 		$this->drop = TRUE;
 	}
 }
 
 /**
-* Creates a data object in ADOdb's datadict format
-*
-* This class stores information about table data, and is called
-* when we need to load field data into a table.
-*
-* @package axmls
-* @access private
-*/
+ * Creates a data object in ADOdb's datadict format
+ *
+ * This class stores information about table data, and is called
+ * when we need to load field data into a table.
+ *
+ * @package axmls
+ * @access private
+ */
 class dbData extends dbObject {
 
 	var $data = array();
@@ -822,26 +831,26 @@ class dbData extends dbObject {
 	var $row;
 
 	/**
-	* Initializes the new dbData object.
-	*
-	* @param object $parent Parent object
-	* @param array $attributes Attributes
-	*
-	* @internal
-	*/
-	function __construct( &$parent, $attributes = NULL ) {
+	 * Initializes the new dbData object.
+	 *
+	 * @param object $parent Parent object
+	 * @param array $attributes Attributes
+	 *
+	 * @internal
+	 */
+	function __construct( $parent, $attributes = NULL ) {
 		$this->parent = $parent;
 	}
 
 	/**
-	* XML Callback to process start elements
-	*
-	* Processes XML opening tags.
-	* Elements currently processed are: ROW and F (field).
-	*
-	* @access private
-	*/
-	function _tag_open( &$parser, $tag, $attributes ) {
+	 * XML Callback to process start elements
+	 *
+	 * Processes XML opening tags.
+	 * Elements currently processed are: ROW and F (field).
+	 *
+	 * @access private
+	 */
+	function _tag_open( $parser, $tag, $attributes ) {
 		$this->currentElement = strtoupper( $tag );
 
 		switch( $this->currentElement ) {
@@ -857,13 +866,13 @@ function _tag_open( &$parser, $tag, $attributes ) {
 	}
 
 	/**
-	* XML Callback to process CDATA elements
-	*
-	* Processes XML cdata.
-	*
-	* @access private
-	*/
-	function _tag_cdata( &$parser, $cdata ) {
+	 * XML Callback to process CDATA elements
+	 *
+	 * Processes XML cdata.
+	 *
+	 * @access private
+	 */
+	function _tag_cdata( $parser, $cdata ) {
 		switch( $this->currentElement ) {
 			// Index field name
 			case 'F':
@@ -875,11 +884,11 @@ function _tag_cdata( &$parser, $cdata ) {
 	}
 
 	/**
-	* XML Callback to process end elements
-	*
-	* @access private
-	*/
-	function _tag_close( &$parser, $tag ) {
+	 * XML Callback to process end elements
+	 *
+	 * @access private
+	 */
+	function _tag_close( $parser, $tag ) {
 		$this->currentElement = '';
 
 		switch( strtoupper( $tag ) ) {
@@ -890,11 +899,11 @@ function _tag_close( &$parser, $tag ) {
 	}
 
 	/**
-	* Adds a field to the insert
-	*
-	* @param string $name Field name
-	* @return string Field list
-	*/
+	 * Adds a field to the insert
+	 *
+	 * @param string $name Field name
+	 * @return string Field list
+	 */
 	function addField( $attributes ) {
 		// check we're in a valid row
 		if( !isset( $this->row ) || !isset( $this->data[$this->row] ) ) {
@@ -903,7 +912,7 @@ function addField( $attributes ) {
 
 		// Set the field index so we know where we are
 		if( isset( $attributes['NAME'] ) ) {
-			$this->current_field = $this->FieldID( $attributes['NAME'] );
+			$this->current_field = $this->fieldID( $attributes['NAME'] );
 		} else {
 			$this->current_field = count( $this->data[$this->row] );
 		}
@@ -915,11 +924,11 @@ function addField( $attributes ) {
 	}
 
 	/**
-	* Adds options to the index
-	*
-	* @param string $opt Comma-separated list of index options.
-	* @return string Option list
-	*/
+	 * Adds options to the index
+	 *
+	 * @param string $opt Comma-separated list of index options.
+	 * @return string Option list
+	 */
 	function addData( $cdata ) {
 		// check we're in a valid field
 		if ( isset( $this->data[$this->row][$this->current_field] ) ) {
@@ -929,18 +938,18 @@ function addData( $cdata ) {
 	}
 
 	/**
-	* Generates the SQL that will add/update the data in the database
-	*
-	* @param object $xmls adoSchema object
-	* @return array Array containing index creation SQL
-	*/
+	 * Generates the SQL that will add/update the data in the database
+	 *
+	 * @param object $xmls adoSchema object
+	 * @return array Array containing index creation SQL
+	 */
 	function create( &$xmls ) {
-		$table = $xmls->dict->TableName($this->parent->name);
+		$table = $xmls->dict->tableName($this->parent->name);
 		$table_field_count = count($this->parent->fields);
-		$tables = $xmls->db->MetaTables();
+		$tables = $xmls->db->metaTables();
 		$sql = array();
 
-		$ukeys = $xmls->db->MetaPrimaryKeys( $table );
+		$ukeys = $xmls->db->metaPrimaryKeys( $table );
 		if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) {
 			foreach( $this->parent->indexes as $indexObj ) {
 				if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name;
@@ -956,7 +965,8 @@ function create( &$xmls ) {
 			foreach( $row as $field_id => $field_data ) {
 				if( !array_key_exists( $field_id, $table_fields ) ) {
 					if( is_numeric( $field_id ) ) {
-						$field_id = reset( array_keys( $table_fields ) );
+						$keys = array_keys($table_fields);
+						$field_id = reset($keys);
 					} else {
 						continue;
 					}
@@ -1027,19 +1037,19 @@ function create( &$xmls ) {
 					$where .= $key . ' = ' . $xmls->db->qstr( $mfields[$key] );
 				}
 			}
-			$records = $xmls->db->Execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
-			switch( $records->RecordCount() ) {
+			$records = $xmls->db->execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
+			switch( $records->recordCount() ) {
 				case 0:
 					// No matching record, so safe to insert.
 					logMsg( "No matching records. Inserting new row with unique data" );
-					$sql[] = $xmls->db->GetInsertSQL( $records, $mfields );
+					$sql[] = $xmls->db->getInsertSQL( $records, $mfields );
 					break;
 				case 1:
 					// Exactly one matching record, so we can update if the mode permits.
 					logMsg( "One matching record..." );
 					if( $mode == XMLS_MODE_UPDATE ) {
 						logMsg( "...Updating existing row from unique data" );
-						$sql[] = $xmls->db->GetUpdateSQL( $records, $mfields );
+						$sql[] = $xmls->db->getUpdateSQL( $records, $mfields );
 					}
 					break;
 				default:
@@ -1052,40 +1062,40 @@ function create( &$xmls ) {
 }
 
 /**
-* Creates the SQL to execute a list of provided SQL queries
-*
-* @package axmls
-* @access private
-*/
+ * Creates the SQL to execute a list of provided SQL queries
+ *
+ * @package axmls
+ * @access private
+ */
 class dbQuerySet extends dbObject {
 
 	/**
-	* @var array	List of SQL queries
-	*/
+	 * @var array	List of SQL queries
+	 */
 	var $queries = array();
 
 	/**
-	* @var string	String used to build of a query line by line
-	*/
+	 * @var string	String used to build of a query line by line
+	 */
 	var $query;
 
 	/**
-	* @var string	Query prefix key
-	*/
+	 * @var string	Query prefix key
+	 */
 	var $prefixKey = '';
 
 	/**
-	* @var boolean	Auto prefix enable (TRUE)
-	*/
+	 * @var boolean	Auto prefix enable (TRUE)
+	 */
 	var $prefixMethod = 'AUTO';
 
 	/**
-	* Initializes the query set.
-	*
-	* @param object $parent Parent object
-	* @param array $attributes Attributes
-	*/
-	function __construct( &$parent, $attributes = NULL ) {
+	 * Initializes the query set.
+	 *
+	 * @param object $parent Parent object
+	 * @param array $attributes Attributes
+	 */
+	function __construct( $parent, $attributes = NULL ) {
 		$this->parent = $parent;
 
 		// Overrides the manual prefix key
@@ -1110,12 +1120,12 @@ function __construct( &$parent, $attributes = NULL ) {
 	}
 
 	/**
-	* XML Callback to process start elements. Elements currently
-	* processed are: QUERY.
-	*
-	* @access private
-	*/
-	function _tag_open( &$parser, $tag, $attributes ) {
+	 * XML Callback to process start elements. Elements currently
+	 * processed are: QUERY.
+	 *
+	 * @access private
+	 */
+	function _tag_open( $parser, $tag, $attributes ) {
 		$this->currentElement = strtoupper( $tag );
 
 		switch( $this->currentElement ) {
@@ -1135,9 +1145,9 @@ function _tag_open( &$parser, $tag, $attributes ) {
 	}
 
 	/**
-	* XML Callback to process CDATA elements
-	*/
-	function _tag_cdata( &$parser, $cdata ) {
+	 * XML Callback to process CDATA elements
+	 */
+	function _tag_cdata( $parser, $cdata ) {
 		switch( $this->currentElement ) {
 			// Line of queryset SQL data
 			case 'QUERY':
@@ -1149,11 +1159,11 @@ function _tag_cdata( &$parser, $cdata ) {
 	}
 
 	/**
-	* XML Callback to process end elements
-	*
-	* @access private
-	*/
-	function _tag_close( &$parser, $tag ) {
+	 * XML Callback to process end elements
+	 *
+	 * @access private
+	 */
+	function _tag_close( $parser, $tag ) {
 		$this->currentElement = '';
 
 		switch( strtoupper( $tag ) ) {
@@ -1172,10 +1182,10 @@ function _tag_close( &$parser, $tag ) {
 	}
 
 	/**
-	* Re-initializes the query.
-	*
-	* @return boolean TRUE
-	*/
+	 * Re-initializes the query.
+	 *
+	 * @return boolean TRUE
+	 */
 	function newQuery() {
 		$this->query = '';
 
@@ -1183,10 +1193,10 @@ function newQuery() {
 	}
 
 	/**
-	* Discards the existing query.
-	*
-	* @return boolean TRUE
-	*/
+	 * Discards the existing query.
+	 *
+	 * @return boolean TRUE
+	 */
 	function discardQuery() {
 		unset( $this->query );
 
@@ -1194,11 +1204,11 @@ function discardQuery() {
 	}
 
 	/**
-	* Appends a line to a query that is being built line by line
-	*
-	* @param string $data Line of SQL data or NULL to initialize a new query
-	* @return string SQL query string.
-	*/
+	 * Appends a line to a query that is being built line by line
+	 *
+	 * @param string $data Line of SQL data or NULL to initialize a new query
+	 * @return string SQL query string.
+	 */
 	function buildQuery( $sql = NULL ) {
 		if( !isset( $this->query ) OR empty( $sql ) ) {
 			return FALSE;
@@ -1210,10 +1220,10 @@ function buildQuery( $sql = NULL ) {
 	}
 
 	/**
-	* Adds a completed query to the query list
-	*
-	* @return string	SQL of added query
-	*/
+	 * Adds a completed query to the query list
+	 *
+	 * @return string	SQL of added query
+	 */
 	function addQuery() {
 		if( !isset( $this->query ) ) {
 			return FALSE;
@@ -1227,11 +1237,11 @@ function addQuery() {
 	}
 
 	/**
-	* Creates and returns the current query set
-	*
-	* @param object $xmls adoSchema object
-	* @return array Query set
-	*/
+	 * Creates and returns the current query set
+	 *
+	 * @param object $xmls adoSchema object
+	 * @return array Query set
+	 */
 	function create( &$xmls ) {
 		foreach( $this->queries as $id => $query ) {
 			switch( $this->prefixMethod ) {
@@ -1267,13 +1277,13 @@ function create( &$xmls ) {
 	}
 
 	/**
-	* Rebuilds the query with the prefix attached to any objects
-	*
-	* @param string $regex Regex used to add prefix
-	* @param string $query SQL query string
-	* @param string $prefix Prefix to be appended to tables, indices, etc.
-	* @return string Prefixed SQL query string.
-	*/
+	 * Rebuilds the query with the prefix attached to any objects
+	 *
+	 * @param string $regex Regex used to add prefix
+	 * @param string $query SQL query string
+	 * @param string $prefix Prefix to be appended to tables, indices, etc.
+	 * @return string Prefixed SQL query string.
+	 */
 	function prefixQuery( $regex, $query, $prefix = NULL ) {
 		if( !isset( $prefix ) ) {
 			return $query;
@@ -1303,118 +1313,107 @@ function prefixQuery( $regex, $query, $prefix = NULL ) {
 }
 
 /**
-* Loads and parses an XML file, creating an array of "ready-to-run" SQL statements
-*
-* This class is used to load and parse the XML file, to create an array of SQL statements
-* that can be used to build a database, and to build the database using the SQL array.
-*
-* @tutorial getting_started.pkg
-*
-* @author Richard Tango-Lowy & Dan Cech
-* @version $Revision: 1.62 $
-*
-* @package axmls
-*/
+ * Loads and parses an XML file, creating an array of "ready-to-run" SQL statements
+ *
+ * This class is used to load and parse the XML file, to create an array of SQL statements
+ * that can be used to build a database, and to build the database using the SQL array.
+ *
+ * @tutorial getting_started.pkg
+ *
+ * @author Richard Tango-Lowy & Dan Cech
+ * @version 1.62
+ *
+ * @package axmls
+ */
 class adoSchema {
 
 	/**
-	* @var array	Array containing SQL queries to generate all objects
-	* @access private
-	*/
+	 * @var array	Array containing SQL queries to generate all objects
+	 * @access private
+	 */
 	var $sqlArray;
 
 	/**
-	* @var object	ADOdb connection object
-	* @access private
-	*/
+	 * @var object	ADOdb connection object
+	 * @access private
+	 */
 	var $db;
 
 	/**
-	* @var object	ADOdb Data Dictionary
-	* @access private
-	*/
+	 * @var object	ADOdb Data Dictionary
+	 * @access private
+	 */
 	var $dict;
 
 	/**
-	* @var string Current XML element
-	* @access private
-	*/
+	 * @var string Current XML element
+	 * @access private
+	 */
 	var $currentElement = '';
 
 	/**
-	* @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database
-	* @access private
-	*/
+	 * @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database
+	 * @access private
+	 */
 	var $upgrade = '';
 
 	/**
-	* @var string Optional object prefix
-	* @access private
-	*/
+	 * @var string Optional object prefix
+	 * @access private
+	 */
 	var $objectPrefix = '';
 
 	/**
-	* @var long	Original Magic Quotes Runtime value
-	* @access private
-	*/
-	var $mgq;
-
-	/**
-	* @var long	System debug
-	* @access private
-	*/
+	 * @var long	System debug
+	 * @access private
+	 */
 	var $debug;
 
 	/**
-	* @var string Regular expression to find schema version
-	* @access private
-	*/
+	 * @var string Regular expression to find schema version
+	 * @access private
+	 */
 	var $versionRegex = '//';
 
 	/**
-	* @var string Current schema version
-	* @access private
-	*/
+	 * @var string Current schema version
+	 * @access private
+	 */
 	var $schemaVersion;
 
 	/**
-	* @var int	Success of last Schema execution
-	*/
+	 * @var int	Success of last Schema execution
+	 */
 	var $success;
 
 	/**
-	* @var bool	Execute SQL inline as it is generated
-	*/
+	 * @var bool	Execute SQL inline as it is generated
+	 */
 	var $executeInline;
 
 	/**
-	* @var bool	Continue SQL execution if errors occur
-	*/
+	 * @var bool	Continue SQL execution if errors occur
+	 */
 	var $continueOnError;
 
 	/**
-	* @var int	How to handle existing data rows (insert, update, or ignore)
-	*/
+	 * @var int	How to handle existing data rows (insert, update, or ignore)
+	 */
 	var $existingData;
 
 	/**
-	* Creates an adoSchema object
-	*
-	* Creating an adoSchema object is the first step in processing an XML schema.
-	* The only parameter is an ADOdb database connection object, which must already
-	* have been created.
-	*
-	* @param object $db ADOdb database connection object.
-	*/
+	 * Creates an adoSchema object
+	 *
+	 * Creating an adoSchema object is the first step in processing an XML schema.
+	 * The only parameter is an ADOdb database connection object, which must already
+	 * have been created.
+	 *
+	 * @param object $db ADOdb database connection object.
+	 */
 	function __construct( $db ) {
-		// Initialize the environment
-		$this->mgq = get_magic_quotes_runtime();
-		#set_magic_quotes_runtime(0);
-		ini_set("magic_quotes_runtime", 0);
-
 		$this->db = $db;
 		$this->debug = $this->db->debug;
-		$this->dict = NewDataDictionary( $this->db );
+		$this->dict = newDataDictionary( $this->db );
 		$this->sqlArray = array();
 		$this->schemaVersion = XMLS_SCHEMA_VERSION;
 		$this->executeInline( XMLS_EXECUTE_INLINE );
@@ -1424,22 +1423,22 @@ function __construct( $db ) {
 	}
 
 	/**
-	* Sets the method to be used for upgrading an existing database
-	*
-	* Use this method to specify how existing database objects should be upgraded.
-	* The method option can be set to ALTER, REPLACE, BEST, or NONE. ALTER attempts to
-	* alter each database object directly, REPLACE attempts to rebuild each object
-	* from scratch, BEST attempts to determine the best upgrade method for each
-	* object, and NONE disables upgrading.
-	*
-	* This method is not yet used by AXMLS, but exists for backward compatibility.
-	* The ALTER method is automatically assumed when the adoSchema object is
-	* instantiated; other upgrade methods are not currently supported.
-	*
-	* @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE)
-	* @returns string Upgrade method used
-	*/
-	function SetUpgradeMethod( $method = '' ) {
+	 * Sets the method to be used for upgrading an existing database
+	 *
+	 * Use this method to specify how existing database objects should be upgraded.
+	 * The method option can be set to ALTER, REPLACE, BEST, or NONE. ALTER attempts to
+	 * alter each database object directly, REPLACE attempts to rebuild each object
+	 * from scratch, BEST attempts to determine the best upgrade method for each
+	 * object, and NONE disables upgrading.
+	 *
+	 * This method is not yet used by AXMLS, but exists for backward compatibility.
+	 * The ALTER method is automatically assumed when the adoSchema object is
+	 * instantiated; other upgrade methods are not currently supported.
+	 *
+	 * @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE)
+	 * @returns string Upgrade method used
+	 */
+	function setUpgradeMethod( $method = '' ) {
 		if( !is_string( $method ) ) {
 			return FALSE;
 		}
@@ -1469,25 +1468,25 @@ function SetUpgradeMethod( $method = '' ) {
 	}
 
 	/**
-	* Specifies how to handle existing data row when there is a unique key conflict.
-	*
-	* The existingData setting specifies how the parser should handle existing rows
-	* when a unique key violation occurs during the insert. This can happen when inserting
-	* data into an existing table with one or more primary keys or unique indexes.
-	* The existingData method takes one of three options: XMLS_MODE_INSERT attempts
-	* to always insert the data as a new row. In the event of a unique key violation,
-	* the database will generate an error.  XMLS_MODE_UPDATE attempts to update the
-	* any existing rows with the new data based upon primary or unique key fields in
-	* the schema. If the data row in the schema specifies no unique fields, the row
-	* data will be inserted as a new row. XMLS_MODE_IGNORE specifies that any data rows
-	* that would result in a unique key violation be ignored; no inserts or updates will
-	* take place. For backward compatibility, the default setting is XMLS_MODE_INSERT,
-	* but XMLS_MODE_UPDATE will generally be the most appropriate setting.
-	*
-	* @param int $mode XMLS_MODE_INSERT, XMLS_MODE_UPDATE, or XMLS_MODE_IGNORE
-	* @return int current mode
-	*/
-	function ExistingData( $mode = NULL ) {
+	 * Specifies how to handle existing data row when there is a unique key conflict.
+	 *
+	 * The existingData setting specifies how the parser should handle existing rows
+	 * when a unique key violation occurs during the insert. This can happen when inserting
+	 * data into an existing table with one or more primary keys or unique indexes.
+	 * The existingData method takes one of three options: XMLS_MODE_INSERT attempts
+	 * to always insert the data as a new row. In the event of a unique key violation,
+	 * the database will generate an error.  XMLS_MODE_UPDATE attempts to update the
+	 * any existing rows with the new data based upon primary or unique key fields in
+	 * the schema. If the data row in the schema specifies no unique fields, the row
+	 * data will be inserted as a new row. XMLS_MODE_IGNORE specifies that any data rows
+	 * that would result in a unique key violation be ignored; no inserts or updates will
+	 * take place. For backward compatibility, the default setting is XMLS_MODE_INSERT,
+	 * but XMLS_MODE_UPDATE will generally be the most appropriate setting.
+	 *
+	 * @param int $mode XMLS_MODE_INSERT, XMLS_MODE_UPDATE, or XMLS_MODE_IGNORE
+	 * @return int current mode
+	 */
+	function existingData( $mode = NULL ) {
 		if( is_int( $mode ) ) {
 			switch( $mode ) {
 				case XMLS_MODE_UPDATE:
@@ -1510,19 +1509,20 @@ function ExistingData( $mode = NULL ) {
 	}
 
 	/**
-	* Enables/disables inline SQL execution.
-	*
-	* Call this method to enable or disable inline execution of the schema. If the mode is set to TRUE (inline execution),
-	* AXMLS applies the SQL to the database immediately as each schema entity is parsed. If the mode
-	* is set to FALSE (post execution), AXMLS parses the entire schema and you will need to call adoSchema::ExecuteSchema()
-	* to apply the schema to the database.
-	*
-	* @param bool $mode execute
-	* @return bool current execution mode
-	*
-	* @see ParseSchema(), ExecuteSchema()
-	*/
-	function ExecuteInline( $mode = NULL ) {
+	 * Enables/disables inline SQL execution.
+	 *
+	 * Call this method to enable or disable inline execution of the schema. If the mode is set to TRUE (inline execution),
+	 * AXMLS applies the SQL to the database immediately as each schema entity is parsed. If the mode
+	 * is set to FALSE (post execution), AXMLS parses the entire schema and you will need to call adoSchema::ExecuteSchema()
+	 * to apply the schema to the database.
+	 *
+	 * @param bool $mode execute
+	 * @return bool current execution mode
+	 *
+	 * @see ParseSchema()
+	 * @see ExecuteSchema()
+	 */
+	function executeInline( $mode = NULL ) {
 		if( is_bool( $mode ) ) {
 			$this->executeInline = $mode;
 		}
@@ -1531,19 +1531,20 @@ function ExecuteInline( $mode = NULL ) {
 	}
 
 	/**
-	* Enables/disables SQL continue on error.
-	*
-	* Call this method to enable or disable continuation of SQL execution if an error occurs.
-	* If the mode is set to TRUE (continue), AXMLS will continue to apply SQL to the database, even if an error occurs.
-	* If the mode is set to FALSE (halt), AXMLS will halt execution of generated sql if an error occurs, though parsing
-	* of the schema will continue.
-	*
-	* @param bool $mode execute
-	* @return bool current continueOnError mode
-	*
-	* @see addSQL(), ExecuteSchema()
-	*/
-	function ContinueOnError( $mode = NULL ) {
+	 * Enables/disables SQL continue on error.
+	 *
+	 * Call this method to enable or disable continuation of SQL execution if an error occurs.
+	 * If the mode is set to TRUE (continue), AXMLS will continue to apply SQL to the database, even if an error occurs.
+	 * If the mode is set to FALSE (halt), AXMLS will halt execution of generated sql if an error occurs, though parsing
+	 * of the schema will continue.
+	 *
+	 * @param bool $mode execute
+	 * @return bool current continueOnError mode
+	 *
+	 * @see addSQL()
+	 * @see ExecuteSchema()
+	 */
+	function continueOnError( $mode = NULL ) {
 		if( is_bool( $mode ) ) {
 			$this->continueOnError = $mode;
 		}
@@ -1552,44 +1553,45 @@ function ContinueOnError( $mode = NULL ) {
 	}
 
 	/**
-	* Loads an XML schema from a file and converts it to SQL.
-	*
-	* Call this method to load the specified schema (see the DTD for the proper format) from
-	* the filesystem and generate the SQL necessary to create the database
-	* described. This method automatically converts the schema to the latest
-	* axmls schema version.
-	* @see ParseSchemaString()
-	*
-	* @param string $file Name of XML schema file.
-	* @param bool $returnSchema Return schema rather than parsing.
-	* @return array Array of SQL queries, ready to execute
-	*/
-	function ParseSchema( $filename, $returnSchema = FALSE ) {
-		return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
-	}
-
-	/**
-	* Loads an XML schema from a file and converts it to SQL.
-	*
-	* Call this method to load the specified schema directly from a file (see
-	* the DTD for the proper format) and generate the SQL necessary to create
-	* the database described by the schema. Use this method when you are dealing
-	* with large schema files. Otherwise, ParseSchema() is faster.
-	* This method does not automatically convert the schema to the latest axmls
-	* schema version. You must convert the schema manually using either the
-	* ConvertSchemaFile() or ConvertSchemaString() method.
-	* @see ParseSchema()
-	* @see ConvertSchemaFile()
-	* @see ConvertSchemaString()
-	*
-	* @param string $file Name of XML schema file.
-	* @param bool $returnSchema Return schema rather than parsing.
-	* @return array Array of SQL queries, ready to execute.
-	*
-	* @deprecated Replaced by adoSchema::ParseSchema() and adoSchema::ParseSchemaString()
-	* @see ParseSchema(), ParseSchemaString()
-	*/
-	function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
+	 * Loads an XML schema from a file and converts it to SQL.
+	 *
+	 * Call this method to load the specified schema (see the DTD for the proper format) from
+	 * the filesystem and generate the SQL necessary to create the database
+	 * described. This method automatically converts the schema to the latest
+	 * axmls schema version.
+	 * @see ParseSchemaString()
+	 *
+	 * @param string $file Name of XML schema file.
+	 * @param bool $returnSchema Return schema rather than parsing.
+	 * @return array Array of SQL queries, ready to execute
+	 */
+	function parseSchema( $filename, $returnSchema = FALSE ) {
+		return $this->parseSchemaString( $this->convertSchemaFile( $filename ), $returnSchema );
+	}
+
+	/**
+	 * Loads an XML schema from a file and converts it to SQL.
+	 *
+	 * Call this method to load the specified schema directly from a file (see
+	 * the DTD for the proper format) and generate the SQL necessary to create
+	 * the database described by the schema. Use this method when you are dealing
+	 * with large schema files. Otherwise, parseSchema() is faster.
+	 * This method does not automatically convert the schema to the latest axmls
+	 * schema version. You must convert the schema manually using either the
+	 * convertSchemaFile() or convertSchemaString() method.
+	 * @see parseSchema()
+	 * @see convertSchemaFile()
+	 * @see convertSchemaString()
+	 *
+	 * @param string $file Name of XML schema file.
+	 * @param bool $returnSchema Return schema rather than parsing.
+	 * @return array Array of SQL queries, ready to execute.
+	 *
+	 * @deprecated Replaced by adoSchema::parseSchema() and adoSchema::parseSchemaString()
+	 * @see parseSchema()
+	 * @see parseSchemaString()
+	 */
+	function parseSchemaFile( $filename, $returnSchema = FALSE ) {
 		// Open the file
 		if( !($fp = fopen( $filename, 'r' )) ) {
 			logMsg( 'Unable to open file' );
@@ -1597,7 +1599,7 @@ function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
 		}
 
 		// do version detection here
-		if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
+		if( $this->schemaFileVersion( $filename ) != $this->schemaVersion ) {
 			logMsg( 'Invalid Schema Version' );
 			return FALSE;
 		}
@@ -1631,17 +1633,17 @@ function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
 	}
 
 	/**
-	* Converts an XML schema string to SQL.
-	*
-	* Call this method to parse a string containing an XML schema (see the DTD for the proper format)
-	* and generate the SQL necessary to create the database described by the schema.
-	* @see ParseSchema()
-	*
-	* @param string $xmlstring XML schema string.
-	* @param bool $returnSchema Return schema rather than parsing.
-	* @return array Array of SQL queries, ready to execute.
-	*/
-	function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
+	 * Converts an XML schema string to SQL.
+	 *
+	 * Call this method to parse a string containing an XML schema (see the DTD for the proper format)
+	 * and generate the SQL necessary to create the database described by the schema.
+	 * @see parseSchema()
+	 *
+	 * @param string $xmlstring XML schema string.
+	 * @param bool $returnSchema Return schema rather than parsing.
+	 * @return array Array of SQL queries, ready to execute.
+	 */
+	function parseSchemaString( $xmlstring, $returnSchema = FALSE ) {
 		if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
 			logMsg( 'Empty or Invalid Schema' );
 			return FALSE;
@@ -1675,57 +1677,59 @@ function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
 	}
 
 	/**
-	* Loads an XML schema from a file and converts it to uninstallation SQL.
-	*
-	* Call this method to load the specified schema (see the DTD for the proper format) from
-	* the filesystem and generate the SQL necessary to remove the database described.
-	* @see RemoveSchemaString()
-	*
-	* @param string $file Name of XML schema file.
-	* @param bool $returnSchema Return schema rather than parsing.
-	* @return array Array of SQL queries, ready to execute
-	*/
-	function RemoveSchema( $filename, $returnSchema = FALSE ) {
-		return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
+	 * Loads an XML schema from a file and converts it to uninstallation SQL.
+	 *
+	 * Call this method to load the specified schema (see the DTD for the proper format) from
+	 * the filesystem and generate the SQL necessary to remove the database described.
+	 * @see RemoveSchemaString()
+	 *
+	 * @param string $file Name of XML schema file.
+	 * @param bool $returnSchema Return schema rather than parsing.
+	 * @return array Array of SQL queries, ready to execute
+	 */
+	function removeSchema( $filename, $returnSchema = FALSE ) {
+		return $this->removeSchemaString( $this->convertSchemaFile( $filename ), $returnSchema );
 	}
 
 	/**
-	* Converts an XML schema string to uninstallation SQL.
-	*
-	* Call this method to parse a string containing an XML schema (see the DTD for the proper format)
-	* and generate the SQL necessary to uninstall the database described by the schema.
-	* @see RemoveSchema()
-	*
-	* @param string $schema XML schema string.
-	* @param bool $returnSchema Return schema rather than parsing.
-	* @return array Array of SQL queries, ready to execute.
-	*/
-	function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
+	 * Converts an XML schema string to uninstallation SQL.
+	 *
+	 * Call this method to parse a string containing an XML schema (see the DTD for the proper format)
+	 * and generate the SQL necessary to uninstall the database described by the schema.
+	 * @see removeSchema()
+	 *
+	 * @param string $schema XML schema string.
+	 * @param bool $returnSchema Return schema rather than parsing.
+	 * @return array Array of SQL queries, ready to execute.
+	 */
+	function removeSchemaString( $schema, $returnSchema = FALSE ) {
 
 		// grab current version
-		if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
+		if( !( $version = $this->schemaStringVersion( $schema ) ) ) {
 			return FALSE;
 		}
 
-		return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
+		return $this->parseSchemaString( $this->transformSchema( $schema, 'remove-' . $version), $returnSchema );
 	}
 
 	/**
-	* Applies the current XML schema to the database (post execution).
-	*
-	* Call this method to apply the current schema (generally created by calling
-	* ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes,
-	* and executing other SQL specified in the schema) after parsing.
-	* @see ParseSchema(), ParseSchemaString(), ExecuteInline()
-	*
-	* @param array $sqlArray Array of SQL statements that will be applied rather than
-	*		the current schema.
-	* @param boolean $continueOnErr Continue to apply the schema even if an error occurs.
-	* @returns integer 0 if failure, 1 if errors, 2 if successful.
-	*/
-	function ExecuteSchema( $sqlArray = NULL, $continueOnErr =  NULL ) {
+	 * Applies the current XML schema to the database (post execution).
+	 *
+	 * Call this method to apply the current schema (generally created by calling
+	 * parseSchema() or parseSchemaString() ) to the database (creating the tables, indexes,
+	 * and executing other SQL specified in the schema) after parsing.
+	 * @see parseSchema()
+	 * @see parseSchemaString()
+	 * @see executeInline()
+	 *
+	 * @param array $sqlArray Array of SQL statements that will be applied rather than
+	 *		the current schema.
+	 * @param boolean $continueOnErr Continue to apply the schema even if an error occurs.
+	 * @returns integer 0 if failure, 1 if errors, 2 if successful.
+	 */
+	function executeSchema( $sqlArray = NULL, $continueOnErr =  NULL ) {
 		if( !is_bool( $continueOnErr ) ) {
-			$continueOnErr = $this->ContinueOnError();
+			$continueOnErr = $this->continueOnError();
 		}
 
 		if( !isset( $sqlArray ) ) {
@@ -1735,36 +1739,36 @@ function ExecuteSchema( $sqlArray = NULL, $continueOnErr =  NULL ) {
 		if( !is_array( $sqlArray ) ) {
 			$this->success = 0;
 		} else {
-			$this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
+			$this->success = $this->dict->executeSQLArray( $sqlArray, $continueOnErr );
 		}
 
 		return $this->success;
 	}
 
 	/**
-	* Returns the current SQL array.
-	*
-	* Call this method to fetch the array of SQL queries resulting from
-	* ParseSchema() or ParseSchemaString().
-	*
-	* @param string $format Format: HTML, TEXT, or NONE (PHP array)
-	* @return array Array of SQL statements or FALSE if an error occurs
-	*/
-	function PrintSQL( $format = 'NONE' ) {
+	 * Returns the current SQL array.
+	 *
+	 * Call this method to fetch the array of SQL queries resulting from
+	 * parseSchema() or parseSchemaString().
+	 *
+	 * @param string $format Format: HTML, TEXT, or NONE (PHP array)
+	 * @return array Array of SQL statements or FALSE if an error occurs
+	 */
+	function printSQL( $format = 'NONE' ) {
 		$sqlArray = null;
 		return $this->getSQL( $format, $sqlArray );
 	}
 
 	/**
-	* Saves the current SQL array to the local filesystem as a list of SQL queries.
-	*
-	* Call this method to save the array of SQL queries (generally resulting from a
-	* parsed XML schema) to the filesystem.
-	*
-	* @param string $filename Path and name where the file should be saved.
-	* @return boolean TRUE if save is successful, else FALSE.
-	*/
-	function SaveSQL( $filename = './schema.sql' ) {
+	 * Saves the current SQL array to the local filesystem as a list of SQL queries.
+	 *
+	 * Call this method to save the array of SQL queries (generally resulting from a
+	 * parsed XML schema) to the filesystem.
+	 *
+	 * @param string $filename Path and name where the file should be saved.
+	 * @return boolean TRUE if save is successful, else FALSE.
+	 */
+	function saveSQL( $filename = './schema.sql' ) {
 
 		if( !isset( $sqlArray ) ) {
 			$sqlArray = $this->sqlArray;
@@ -1782,12 +1786,12 @@ function SaveSQL( $filename = './schema.sql' ) {
 	}
 
 	/**
-	* Create an xml parser
-	*
-	* @return object PHP XML parser object
-	*
-	* @access private
-	*/
+	 * Create an xml parser
+	 *
+	 * @return object PHP XML parser object
+	 *
+	 * @access private
+	 */
 	function create_parser() {
 		// Create the parser
 		$xmlParser = xml_parser_create();
@@ -1801,11 +1805,11 @@ function create_parser() {
 	}
 
 	/**
-	* XML Callback to process start elements
-	*
-	* @access private
-	*/
-	function _tag_open( &$parser, $tag, $attributes ) {
+	 * XML Callback to process start elements
+	 *
+	 * @access private
+	 */
+	function _tag_open( $parser, $tag, $attributes ) {
 		switch( strtoupper( $tag ) ) {
 			case 'TABLE':
 				if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
@@ -1826,43 +1830,43 @@ function _tag_open( &$parser, $tag, $attributes ) {
 	}
 
 	/**
-	* XML Callback to process CDATA elements
-	*
-	* @access private
-	*/
-	function _tag_cdata( &$parser, $cdata ) {
+	 * XML Callback to process CDATA elements
+	 *
+	 * @access private
+	 */
+	function _tag_cdata( $parser, $cdata ) {
 	}
 
 	/**
-	* XML Callback to process end elements
-	*
-	* @access private
-	* @internal
-	*/
-	function _tag_close( &$parser, $tag ) {
+	 * XML Callback to process end elements
+	 *
+	 * @access private
+	 * @internal
+	 */
+	function _tag_close( $parser, $tag ) {
 
 	}
 
 	/**
-	* Converts an XML schema string to the specified DTD version.
-	*
-	* Call this method to convert a string containing an XML schema to a different AXMLS
-	* DTD version. For instance, to convert a schema created for an pre-1.0 version for
-	* AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
-	* parameter is specified, the schema will be converted to the current DTD version.
-	* If the newFile parameter is provided, the converted schema will be written to the specified
-	* file.
-	* @see ConvertSchemaFile()
-	*
-	* @param string $schema String containing XML schema that will be converted.
-	* @param string $newVersion DTD version to convert to.
-	* @param string $newFile File name of (converted) output file.
-	* @return string Converted XML schema or FALSE if an error occurs.
-	*/
-	function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
+	 * Converts an XML schema string to the specified DTD version.
+	 *
+	 * Call this method to convert a string containing an XML schema to a different AXMLS
+	 * DTD version. For instance, to convert a schema created for an pre-1.0 version for
+	 * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
+	 * parameter is specified, the schema will be converted to the current DTD version.
+	 * If the newFile parameter is provided, the converted schema will be written to the specified
+	 * file.
+	 * @see convertSchemaFile()
+	 *
+	 * @param string $schema String containing XML schema that will be converted.
+	 * @param string $newVersion DTD version to convert to.
+	 * @param string $newFile File name of (converted) output file.
+	 * @return string Converted XML schema or FALSE if an error occurs.
+	 */
+	function convertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
 
 		// grab current version
-		if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
+		if( !( $version = $this->schemaStringVersion( $schema ) ) ) {
 			return FALSE;
 		}
 
@@ -1873,7 +1877,7 @@ function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
 		if( $version == $newVersion ) {
 			$result = $schema;
 		} else {
-			$result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
+			$result = $this->transformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
 		}
 
 		if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
@@ -1884,34 +1888,26 @@ function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
 		return $result;
 	}
 
-	/*
-	// compat for pre-4.3 - jlim
-	function _file_get_contents($path)
-	{
-		if (function_exists('file_get_contents')) return file_get_contents($path);
-		return join('',file($path));
-	}*/
-
-	/**
-	* Converts an XML schema file to the specified DTD version.
-	*
-	* Call this method to convert the specified XML schema file to a different AXMLS
-	* DTD version. For instance, to convert a schema created for an pre-1.0 version for
-	* AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
-	* parameter is specified, the schema will be converted to the current DTD version.
-	* If the newFile parameter is provided, the converted schema will be written to the specified
-	* file.
-	* @see ConvertSchemaString()
-	*
-	* @param string $filename Name of XML schema file that will be converted.
-	* @param string $newVersion DTD version to convert to.
-	* @param string $newFile File name of (converted) output file.
-	* @return string Converted XML schema or FALSE if an error occurs.
-	*/
-	function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
+	/**
+	 * Converts an XML schema file to the specified DTD version.
+	 *
+	 * Call this method to convert the specified XML schema file to a different AXMLS
+	 * DTD version. For instance, to convert a schema created for an pre-1.0 version for
+	 * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
+	 * parameter is specified, the schema will be converted to the current DTD version.
+	 * If the newFile parameter is provided, the converted schema will be written to the specified
+	 * file.
+	 * @see convertSchemaString()
+	 *
+	 * @param string $filename Name of XML schema file that will be converted.
+	 * @param string $newVersion DTD version to convert to.
+	 * @param string $newFile File name of (converted) output file.
+	 * @return string Converted XML schema or FALSE if an error occurs.
+	 */
+	function convertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
 
 		// grab current version
-		if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
+		if( !( $version = $this->schemaFileVersion( $filename ) ) ) {
 			return FALSE;
 		}
 
@@ -1920,14 +1916,14 @@ function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
 		}
 
 		if( $version == $newVersion ) {
-			$result = _file_get_contents( $filename );
+			$result = file_get_contents( $filename );
 
 			// remove unicode BOM if present
 			if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
 				$result = substr( $result, 3 );
 			}
 		} else {
-			$result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
+			$result = $this->transformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
 		}
 
 		if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
@@ -1938,7 +1934,7 @@ function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
 		return $result;
 	}
 
-	function TransformSchema( $schema, $xsl, $schematype='string' )
+	function transformSchema( $schema, $xsl, $schematype='string' )
 	{
 		// Fail if XSLT extension is not available
 		if( ! function_exists( 'xslt_create' ) ) {
@@ -1959,7 +1955,7 @@ function TransformSchema( $schema, $xsl, $schematype='string' )
 					return FALSE;
 				}
 
-				$schema = _file_get_contents( $schema );
+				$schema = file_get_contents( $schema );
 				break;
 			case 'string':
 			default:
@@ -1970,14 +1966,14 @@ function TransformSchema( $schema, $xsl, $schematype='string' )
 
 		$arguments = array (
 			'/_xml' => $schema,
-			'/_xsl' => _file_get_contents( $xsl_file )
+			'/_xsl' => file_get_contents( $xsl_file )
 		);
 
 		// create an XSLT processor
 		$xh = xslt_create ();
 
 		// set error handler
-		xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
+		xslt_set_error_handler ($xh, array ($this, 'xslt_error_handler'));
 
 		// process the schema
 		$result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
@@ -1988,15 +1984,15 @@ function TransformSchema( $schema, $xsl, $schematype='string' )
 	}
 
 	/**
-	* Processes XSLT transformation errors
-	*
-	* @param object $parser XML parser object
-	* @param integer $errno Error number
-	* @param integer $level Error level
-	* @param array $fields Error information fields
-	*
-	* @access private
-	*/
+	 * Processes XSLT transformation errors
+	 *
+	 * @param object $parser XML parser object
+	 * @param integer $errno Error number
+	 * @param integer $level Error level
+	 * @param array $fields Error information fields
+	 *
+	 * @access private
+	 */
 	function xslt_error_handler( $parser, $errno, $level, $fields ) {
 		if( is_array( $fields ) ) {
 			$msg = array(
@@ -2041,15 +2037,15 @@ function xslt_error_handler( $parser, $errno, $level, $fields ) {
 	}
 
 	/**
-	* Returns the AXMLS Schema Version of the requested XML schema file.
-	*
-	* Call this method to obtain the AXMLS DTD version of the requested XML schema file.
-	* @see SchemaStringVersion()
-	*
-	* @param string $filename AXMLS schema file
-	* @return string Schema version number or FALSE on error
-	*/
-	function SchemaFileVersion( $filename ) {
+	 * Returns the AXMLS Schema Version of the requested XML schema file.
+	 *
+	 * Call this method to obtain the AXMLS DTD version of the requested XML schema file.
+	 * @see SchemaStringVersion()
+	 *
+	 * @param string $filename AXMLS schema file
+	 * @return string Schema version number or FALSE on error
+	 */
+	function schemaFileVersion( $filename ) {
 		// Open the file
 		if( !($fp = fopen( $filename, 'r' )) ) {
 			// die( 'Unable to open file' );
@@ -2067,15 +2063,15 @@ function SchemaFileVersion( $filename ) {
 	}
 
 	/**
-	* Returns the AXMLS Schema Version of the provided XML schema string.
-	*
-	* Call this method to obtain the AXMLS DTD version of the provided XML schema string.
-	* @see SchemaFileVersion()
-	*
-	* @param string $xmlstring XML schema string
-	* @return string Schema version number or FALSE on error
-	*/
-	function SchemaStringVersion( $xmlstring ) {
+	 * Returns the AXMLS Schema Version of the provided XML schema string.
+	 *
+	 * Call this method to obtain the AXMLS DTD version of the provided XML schema string.
+	 * @see SchemaFileVersion()
+	 *
+	 * @param string $xmlstring XML schema string
+	 * @return string Schema version number or FALSE on error
+	 */
+	function schemaStringVersion( $xmlstring ) {
 		if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
 			return FALSE;
 		}
@@ -2088,24 +2084,24 @@ function SchemaStringVersion( $xmlstring ) {
 	}
 
 	/**
-	* Extracts an XML schema from an existing database.
-	*
-	* Call this method to create an XML schema string from an existing database.
-	* If the data parameter is set to TRUE, AXMLS will include the data from the database
-	* in the schema.
-	*
-	* @param boolean $data Include data in schema dump
-	* @indent string indentation to use
-	* @prefix string extract only tables with given prefix
-	* @stripprefix strip prefix string when storing in XML schema
-	* @return string Generated XML schema
-	*/
-	function ExtractSchema( $data = FALSE, $indent = '  ', $prefix = '' , $stripprefix=false) {
-		$old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
+	 * Extracts an XML schema from an existing database.
+	 *
+	 * Call this method to create an XML schema string from an existing database.
+	 * If the data parameter is set to TRUE, AXMLS will include the data from the database
+	 * tables in the schema.
+	 *
+	 * @param boolean $data include data in schema dump
+	 * @param string $indent indentation to use
+	 * @param string $prefix extract only tables with given prefix
+	 * @param boolean $stripprefix strip prefix string when storing in XML schema
+	 * @return string Generated XML schema
+	 */
+	function extractSchema( $data = FALSE, $indent = '  ', $prefix = '' , $stripprefix=false) {
+		$old_mode = $this->db->setFetchMode( ADODB_FETCH_NUM );
 
 		$schema = '' . "\n"
 				. '' . "\n";
-		if( is_array( $tables = $this->db->MetaTables( 'TABLES' ,false ,($prefix) ? str_replace('_','\_',$prefix).'%' : '') ) ) {
+		if( is_array( $tables = $this->db->metaTables( 'TABLES' ,false ,($prefix) ? str_replace('_','\_',$prefix).'%' : '') ) ) {
 			foreach( $tables as $table ) {
 				$schema .= $indent
 					. '' . "\n";
 
 				// grab details from database
-				$rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' );
-				$fields = $this->db->MetaColumns( $table );
-				$indexes = $this->db->MetaIndexes( $table );
+				$rs = $this->db->execute('SELECT * FROM ' . $table . ' WHERE 0=1');
+				$fields = $this->db->metaColumns( $table );
+				$indexes = $this->db->metaIndexes( $table );
 
 				if( is_array( $fields ) ) {
 					foreach( $fields as $details ) {
@@ -2147,7 +2143,7 @@ function ExtractSchema( $data = FALSE, $indent = '  ', $prefix = '' , $strippref
 						// this stops the creation of 'R' columns,
 						// AUTOINCREMENT is used to create auto columns
 						$details->primary_key = 0;
-						$type = $rs->MetaType( $details );
+						$type = $rs->metaType( $details );
 
 						$schema .= str_repeat( $indent, 2 ) . 'db->Execute( 'SELECT * FROM ' . $table );
+					$rs = $this->db->execute( 'SELECT * FROM ' . $table );
 
 					if( is_object( $rs ) && !$rs->EOF ) {
 						$schema .= str_repeat( $indent, 2 ) . "\n";
 
-						while( $row = $rs->FetchRow() ) {
+						while( $row = $rs->fetchRow() ) {
 							foreach( $row as $key => $val ) {
 								if ( $val != htmlentities( $val ) ) {
 									$row[$key] = '';
@@ -2201,23 +2197,23 @@ function ExtractSchema( $data = FALSE, $indent = '  ', $prefix = '' , $strippref
 			}
 		}
 
-		$this->db->SetFetchMode( $old_mode );
+		$this->db->setFetchMode( $old_mode );
 
 		$schema .= '';
 		return $schema;
 	}
 
 	/**
-	* Sets a prefix for database objects
-	*
-	* Call this method to set a standard prefix that will be prepended to all database tables
-	* and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix.
-	*
-	* @param string $prefix Prefix that will be prepended.
-	* @param boolean $underscore If TRUE, automatically append an underscore character to the prefix.
-	* @return boolean TRUE if successful, else FALSE
-	*/
-	function SetPrefix( $prefix = '', $underscore = TRUE ) {
+	 * Sets a prefix for database objects
+	 *
+	 * Call this method to set a standard prefix that will be prepended to all database tables
+	 * and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix.
+	 *
+	 * @param string $prefix Prefix that will be prepended.
+	 * @param boolean $underscore If TRUE, automatically append an underscore character to the prefix.
+	 * @return boolean TRUE if successful, else FALSE
+	 */
+	function setPrefix( $prefix = '', $underscore = TRUE ) {
 		switch( TRUE ) {
 			// clear prefix
 			case empty( $prefix ):
@@ -2243,13 +2239,13 @@ function SetPrefix( $prefix = '', $underscore = TRUE ) {
 	}
 
 	/**
-	* Returns an object name with the current prefix prepended.
-	*
-	* @param string	$name Name
-	* @return string	Prefixed name
-	*
-	* @access private
-	*/
+	 * Returns an object name with the current prefix prepended.
+	 *
+	 * @param string	$name Name
+	 * @return string	Prefixed name
+	 *
+	 * @access private
+	 */
 	function prefix( $name = '' ) {
 		// if prefix is set
 		if( !empty( $this->objectPrefix ) ) {
@@ -2263,13 +2259,13 @@ function prefix( $name = '' ) {
 	}
 
 	/**
-	* Checks if element references a specific platform
-	*
-	* @param string $platform Requested platform
-	* @returns boolean TRUE if platform check succeeds
-	*
-	* @access private
-	*/
+	 * Checks if element references a specific platform
+	 *
+	 * @param string $platform Requested platform
+	 * @returns boolean TRUE if platform check succeeds
+	 *
+	 * @access private
+	 */
 	function supportedPlatform( $platform = NULL ) {
 		if( !empty( $platform ) ) {
 			$regex = '/(^|\|)' . $this->db->databaseType . '(\||$)/i';
@@ -2292,22 +2288,22 @@ function supportedPlatform( $platform = NULL ) {
 	}
 
 	/**
-	* Clears the array of generated SQL.
-	*
-	* @access private
-	*/
+	 * Clears the array of generated SQL.
+	 *
+	 * @access private
+	 */
 	function clearSQL() {
 		$this->sqlArray = array();
 	}
 
 	/**
-	* Adds SQL into the SQL array.
-	*
-	* @param mixed $sql SQL to Add
-	* @return boolean TRUE if successful, else FALSE.
-	*
-	* @access private
-	*/
+	 * Adds SQL into the SQL array.
+	 *
+	 * @param mixed $sql SQL to Add
+	 * @return boolean TRUE if successful, else FALSE.
+	 *
+	 * @access private
+	 */
 	function addSQL( $sql = NULL ) {
 		if( is_array( $sql ) ) {
 			foreach( $sql as $line ) {
@@ -2343,13 +2339,13 @@ function addSQL( $sql = NULL ) {
 	}
 
 	/**
-	* Gets the SQL array in the specified format.
-	*
-	* @param string $format Format
-	* @return mixed SQL
-	*
-	* @access private
-	*/
+	 * Gets the SQL array in the specified format.
+	 *
+	 * @param string $format Format
+	 * @return mixed SQL
+	 *
+	 * @access private
+	 */
 	function getSQL( $format = NULL, $sqlArray = NULL ) {
 		if( !is_array( $sqlArray ) ) {
 			$sqlArray = $this->sqlArray;
@@ -2371,22 +2367,20 @@ function getSQL( $format = NULL, $sqlArray = NULL ) {
 	}
 
 	/**
-	* Destroys an adoSchema object.
-	*
-	* Call this method to clean up after an adoSchema object that is no longer in use.
-	* @deprecated adoSchema now cleans up automatically.
-	*/
-	function Destroy() {
-		ini_set("magic_quotes_runtime", $this->mgq );
-		#set_magic_quotes_runtime( $this->mgq );
+	 * Destroys an adoSchema object.
+	 *
+	 * Call this method to clean up after an adoSchema object that is no longer in use.
+	 * @deprecated adoSchema now cleans up automatically.
+	 */
+	function destroy() {
 	}
 }
 
 /**
-* Message logging function
-*
-* @access private
-*/
+ * Message logging function
+ *
+ * @access private
+ */
 function logMsg( $msg, $title = NULL, $force = FALSE ) {
 	if( XMLS_DEBUG or $force ) {
 		echo '
';
diff --git a/www/include/adodb5/adodb.inc.php b/www/include/adodb/adodb.inc.php
similarity index 60%
rename from www/include/adodb5/adodb.inc.php
rename to www/include/adodb/adodb.inc.php
index 62607a25..7ed8242b 100644
--- a/www/include/adodb5/adodb.inc.php
+++ b/www/include/adodb/adodb.inc.php
@@ -1,37 +1,22 @@
 fields is available on EOF
 		$ADODB_FETCH_MODE,	// DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
 		$ADODB_GETONE_EOF,
@@ -85,35 +69,52 @@ class library to hide the differences between the different database API's (enca
 	// GLOBAL SETUP
 	//==============================================================================================
 
-	$ADODB_EXTENSION = defined('ADODB_EXTENSION');
-
-	// ********************************************************
-	// Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
-	// Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
-	//
-	// 0 = ignore empty fields. All empty fields in array are ignored.
-	// 1 = force null. All empty, php null and string 'null' fields are changed to sql NULL values.
-	// 2 = force empty. All empty, php null and string 'null' fields are changed to sql empty '' or 0 values.
-	// 3 = force value. Value is left as it is. Php null and string 'null' are set to sql NULL values and empty fields '' are set to empty '' sql values.
-
+	/*********************************************************
+	 * Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
+	 * Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:adodb_force_type
+	 *
+	 * 0 = ignore empty fields. All empty fields in array are ignored.
+	 * 1 = force null. All empty, php null and string 'null' fields are
+	 *     changed to sql NULL values.
+	 * 2 = force empty. All empty, php null and string 'null' fields are
+	 *     changed to sql empty '' or 0 values.
+	 * 3 = force value. Value is left as it is. Php null and string 'null'
+	 *     are set to sql NULL values and empty fields '' are set to empty '' sql values.
+	 * 4 = force value. Like 1 but numeric empty fields are set to zero.
+	 */
 		define('ADODB_FORCE_IGNORE',0);
 		define('ADODB_FORCE_NULL',1);
 		define('ADODB_FORCE_EMPTY',2);
 		define('ADODB_FORCE_VALUE',3);
+		define('ADODB_FORCE_NULL_AND_ZERO',4);
 	// ********************************************************
 
 
-	if (!$ADODB_EXTENSION || ADODB_EXTENSION < 4.0) {
+	/**
+	 * Constants for returned values from the charMax and textMax methods.
+	 * If not specifically defined in the driver, methods return the NOTSET value.
+	 */
+	define ('ADODB_STRINGMAX_NOTSET', -1);
+	define ('ADODB_STRINGMAX_NOLIMIT',-2);
+
+	/*
+	 * Defines the the default meta type returned
+	 * when ADOdb encounters a type that it is not
+	 * defined in the metaTypes.
+	 */
+	if (!defined('ADODB_DEFAULT_METATYPE'))
+		define ('ADODB_DEFAULT_METATYPE','N');
 
-		define('ADODB_BAD_RS','

Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;

'); + define('ADODB_BAD_RS','

Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;

'); // allow [ ] @ ` " and . in table names - define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)'); + define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)'); // prefetching used by oracle - if (!defined('ADODB_PREFETCH_ROWS')) { - define('ADODB_PREFETCH_ROWS',10); - } + if (!defined('ADODB_PREFETCH_ROWS')) { + define('ADODB_PREFETCH_ROWS',10); + } /** @@ -128,10 +129,10 @@ class library to hide the differences between the different database API's (enca * - BOTH: array(0 => 456, 'id' => 456, 1 => 'john', 'name' => 'john') * - DEFAULT: driver-dependent */ - define('ADODB_FETCH_DEFAULT', 0); - define('ADODB_FETCH_NUM', 1); - define('ADODB_FETCH_ASSOC', 2); - define('ADODB_FETCH_BOTH', 3); + define('ADODB_FETCH_DEFAULT', 0); + define('ADODB_FETCH_NUM', 1); + define('ADODB_FETCH_ASSOC', 2); + define('ADODB_FETCH_BOTH', 3); /** * Associative array case constants @@ -148,53 +149,23 @@ class library to hide the differences between the different database API's (enca * NOTE: This functionality is not implemented everywhere, it currently * works only with: mssql, odbc, oci8 and ibase derived drivers */ - define('ADODB_ASSOC_CASE_LOWER', 0); - define('ADODB_ASSOC_CASE_UPPER', 1); - define('ADODB_ASSOC_CASE_NATIVE', 2); - - - if (!defined('TIMESTAMP_FIRST_YEAR')) { - define('TIMESTAMP_FIRST_YEAR',100); - } + define('ADODB_ASSOC_CASE_LOWER', 0); + define('ADODB_ASSOC_CASE_UPPER', 1); + define('ADODB_ASSOC_CASE_NATIVE', 2); - /** - * AutoExecute constants - * (moved from adodb-pear.inc.php since they are only used in here) - */ - define('DB_AUTOQUERY_INSERT', 1); - define('DB_AUTOQUERY_UPDATE', 2); - - // PHP's version scheme makes converting to numbers difficult - workaround - $_adodb_ver = (float) PHP_VERSION; - if ($_adodb_ver >= 5.2) { - define('ADODB_PHPVER',0x5200); - } else if ($_adodb_ver >= 5.0) { - define('ADODB_PHPVER',0x5000); - } else { - die("PHP5 or later required. You are running ".PHP_VERSION); - } - unset($_adodb_ver); + if (!defined('TIMESTAMP_FIRST_YEAR')) { + define('TIMESTAMP_FIRST_YEAR',100); } - /** - Accepts $src and $dest arrays, replacing string $data - */ - function ADODB_str_replace($src, $dest, $data) { - if (ADODB_PHPVER >= 0x4050) { - return str_replace($src,$dest,$data); - } + * AutoExecute constants + * (moved from adodb-pear.inc.php since they are only used in here) + */ + define('DB_AUTOQUERY_INSERT', 1); + define('DB_AUTOQUERY_UPDATE', 2); + - $s = reset($src); - $d = reset($dest); - while ($s !== false) { - $data = str_replace($s,$d,$data); - $s = next($src); - $d = next($dest); - } - return $data; - } function ADODB_Setup() { GLOBAL @@ -224,15 +195,10 @@ function ADODB_Setup() { } } - - // Initialize random number generator for randomizing cache flushes - // -- note Since PHP 4.2.0, the seed becomes optional and defaults to a random value if omitted. - srand(((double)microtime())*1000000); - /** * ADODB version as a string. */ - $ADODB_vers = 'v5.20.9 21-Dec-2016'; + $ADODB_vers = 'v5.22.2 2022-05-08'; /** * Determines whether recordset->RecordCount() is used. @@ -274,12 +240,25 @@ class ADOFieldObject { } + /** + * Parse date string to prevent injection attack. + * + * @param string $s + * + * @return string + */ function _adodb_safedate($s) { return str_replace(array("'", '\\'), '', $s); } - // parse date string to prevent injection attack - // date string will have one quote at beginning e.g. '3434343' + /** + * Parse date string to prevent injection attack. + * Date string will have one quote at beginning e.g. '3434343' + * + * @param string $s + * + * @return string + */ function _adodb_safedateq($s) { $len = strlen($s); if ($s[0] !== "'") { @@ -303,20 +282,29 @@ function _adodb_safedateq($s) { return strlen($s2) == 0 ? 'null' : $s2; } - - // for transaction handling - + /** + * For transaction handling. + * + * @param $dbms + * @param $fn + * @param $errno + * @param $errmsg + * @param $p1 + * @param $p2 + * @param $thisConnection + */ function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection) { //print "Errorno ($fn errno=$errno m=$errmsg) "; $thisConnection->_transOK = false; if ($thisConnection->_oldRaiseFn) { - $fn = $thisConnection->_oldRaiseFn; - $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection); + $errfn = $thisConnection->_oldRaiseFn; + $errfn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection); } } - //------------------ - // class for caching + /** + * Class ADODB_Cache_File + */ class ADODB_Cache_File { var $createdir = true; // requires creation of temp dirs @@ -328,18 +316,42 @@ function __construct() { } } - // write serialised recordset to cache item/file - function writecache($filename, $contents, $debug, $secs2cache) { + /** + * Write serialised RecordSet to cache item/file. + * + * @param $filename + * @param $contents + * @param $debug + * @param $secs2cache + * + * @return bool|int + */ + function writecache($filename, $contents, $debug, $secs2cache) { return adodb_write_file($filename, $contents,$debug); } - // load serialised recordset and unserialise it + /** + * load serialised RecordSet and unserialise it + * + * @param $filename + * @param $err + * @param $secs2cache + * @param $rsClass + * + * @return ADORecordSet + */ function &readcache($filename, &$err, $secs2cache, $rsClass) { $rs = csv2rs($filename,$err,$secs2cache,$rsClass); return $rs; } - // flush all items in cache + /** + * Flush all items in cache. + * + * @param bool $debug + * + * @return bool|void + */ function flushall($debug=false) { global $ADODB_CACHE_DIR; @@ -354,7 +366,12 @@ function flushall($debug=false) { return $rez; } - // flush one file in cache + /** + * Flush one file in cache. + * + * @param string $f + * @param bool $debug + */ function flushcache($f, $debug=false) { if (!@unlink($f)) { if ($debug) { @@ -363,6 +380,11 @@ function flushcache($f, $debug=false) { } } + /** + * @param string $hash + * + * @return string + */ function getdirname($hash) { global $ADODB_CACHE_DIR; if (!isset($this->notSafeMode)) { @@ -371,7 +393,14 @@ function getdirname($hash) { return ($this->notSafeMode) ? $ADODB_CACHE_DIR.'/'.substr($hash,0,2) : $ADODB_CACHE_DIR; } - // create temp directories + /** + * Create temp directories. + * + * @param string $hash + * @param bool $debug + * + * @return string + */ function createdir($hash, $debug) { global $ADODB_CACHE_PERMS; @@ -430,7 +459,14 @@ abstract class ADOConnection { var $dataProvider = 'native'; var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql var $database = ''; /// Name of database to be used. + + /** + * @var string If the driver is PDO, then the dsnType is e.g. sqlsrv, otherwise empty + */ + public $dsnType = ''; + var $host = ''; /// The hostname of the database server + var $port = ''; /// The port of the database server var $user = ''; /// The username which is used to connect to the database server. var $password = ''; /// Password for the username. For security, we no longer store it. var $debug = false; /// if set to true will output sql statements @@ -446,6 +482,8 @@ abstract class ADOConnection { var $false = '0'; /// string that represents FALSE for a database var $replaceQuote = "\\'"; /// string to use to replace quotes var $nameQuote = '"'; /// string to use to quote identifiers and names + var $leftBracket = '['; /// left square bracked for t-sql styled column names + var $rightBracket = ']'; /// right square bracked for t-sql styled column names var $charSet=false; /// character set to use - only for interbase, postgres and oci8 var $metaDatabasesSQL = ''; var $metaTablesSQL = ''; @@ -464,15 +502,54 @@ abstract class ADOConnection { var $hasTransactions = true; /// has transactions //-- var $genID = 0; /// sequence id used by GenID(); - var $raiseErrorFn = false; /// error function to call + + /** @var bool|callable Error function to call */ + var $raiseErrorFn = false; + var $isoDates = false; /// accepts dates in ISO format var $cacheSecs = 3600; /// cache for 1 hour - // memcache - var $memCache = false; /// should we use memCache instead of caching in files - var $memCacheHost; /// memCache host - var $memCachePort = 11211; /// memCache port - var $memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) + /***************************************** + * memcached server options + ******************************************/ + + /** + * Use memCache library instead of caching in files. + * @var bool $memCache + */ + public $memCache = false; + + /** + * The memcache server(s) to connect to. Can be defined as: + * - a single host name/ip address + * - a list of hosts/ip addresses + * - an array of server connection data (weighted server groups). + * @link https://adodb.org/dokuwiki/doku.php?id=v5:userguide:memcached + * @var string|array $memCacheHost + */ + public $memCacheHost; + + /** + * Default port number. + * The default port can be overridden if memcache server connection data + * is provided as an array {@see $memCacheHost}. + * @var int $memCachePort + */ + public $memCachePort = 11211; + + /** + * Enable compression of stored items. + * @var bool $memCacheCompress + */ + public $memCacheCompress = false; + + /** + * An array of memcached options. + * Only used with memcached; memcache ignores this setting. + * @link https://www.php.net/manual/en/memcached.constants.php + * @var array $memCacheOptions + */ + public $memCacheOptions = array(); var $sysDate = false; /// name of function that returns the current date var $sysTimeStamp = false; /// name of function that returns the current timestamp @@ -490,8 +567,12 @@ abstract class ADOConnection { var $autoRollback = false; // autoRollback on PConnect(). var $poorAffectedRows = false; // affectedRows not working or unreliable + /** @var bool|callable Execute function to call */ var $fnExecute = false; + + /** @var bool|callable Cache execution function to call */ var $fnCacheExecute = false; + var $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char var $rsPrefix = "ADORecordSet_"; @@ -508,7 +589,8 @@ abstract class ADOConnection { // var $_oldRaiseFn = false; var $_transOK = null; - var $_connectionID = false; /// The returned link identifier whenever a successful database connection is made. + /** @var resource Identifier for the native database connection */ + var $_connectionID = false; var $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will /// then returned by the errorMsg() function var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8 @@ -521,32 +603,77 @@ abstract class ADOConnection { var $_logsql = false; var $_transmode = ''; // transaction mode - /* - * Additional parameters that may be passed to drivers in the connect string - * Driver must be coded to accept the parameters + /** + * Additional parameters that may be passed to drivers in the connect string. + * + * Data is stored as an array of arrays and not a simple associative array, + * because some drivers (e.g. mysql) allow multiple parameters with the same + * key to be set. + * @link https://github.com/ADOdb/ADOdb/issues/187 + * + * @see setConnectionParameter() + * + * @var array $connectionParameters Set of ParameterName => Value pairs */ protected $connectionParameters = array(); + /* + * A simple associative array of user-defined custom actual/meta types + */ + public $customActualTypes = array(); + + /* + * An array of user-defined custom meta/actual types. + * $this->customMetaTypes[$meta] = array( + * 'actual'=>'', + * 'dictionary'=>'', + * 'handler'=>'', + * 'callback'=>'' + * ); + */ + public $customMetaTypes = array(); + + /** - * Adds a parameter to the connection string. - * - * These parameters are added to the connection string when connecting, - * if the driver is coded to use it. - * - * @param string $parameter The name of the parameter to set - * @param string $value The value of the parameter - * - * @return null - * - * @example, for mssqlnative driver ('CharacterSet','UTF-8') - */ - final public function setConnectionParameter($parameter,$value) + * Default Constructor. + * We define it even though it does not actually do anything. This avoids + * getting a PHP Fatal error: Cannot call constructor if a subclass tries + * to call its parent constructor. + */ + public function __construct() { + } - $this->connectionParameters[$parameter] = $value; - + /** + * Adds a parameter to the connection string. + * + * Parameters must be added before the connection is established; + * they are then passed on to the connect statement, which will. + * process them if the driver supports this feature. + * + * Example usage: + * - mssqlnative: setConnectionParameter('CharacterSet','UTF-8'); + * - mysqli: setConnectionParameter(MYSQLI_SET_CHARSET_NAME,'utf8mb4'); + * + * If used in a portable environment, parameters set in this manner should + * be predicated on the database provider, as unexpected results may occur + * if applied to the wrong database. + * + * @param string $parameter The name of the parameter to set + * @param string $value The value of the parameter + * + * @return bool True if success, false otherwise (e.g. parameter is not valid) + */ + public function setConnectionParameter($parameter, $value) { + $this->connectionParameters[] = array($parameter=>$value); + return true; } + /** + * ADOdb version. + * + * @return string + */ static function Version() { global $ADODB_vers; @@ -568,19 +695,74 @@ static function Version() { } /** - Get server version info... + * Set a custom meta type with a corresponding actual + * + * @param string $metaType The Custom ADOdb metatype + * @param string $dictionaryType The database dictionary type + * @param string $actualType The database actual type + * @param bool $handleAsType handle like an existing Metatype + * @param mixed $callBack A pre-processing function + * + * @return bool success if the actual exists + */ + final public function setCustomMetaType( + $metaType, + $dictionaryType, + $actualType, + $handleAsType=false, + $callback=false){ + + $this->customMetaTypes[strtoupper($metaType)] = array( + 'actual'=>$actualType, + 'dictionary'=>strtoupper($dictionaryType), + 'handler'=>$handleAsType, + 'callback'=>$callback + ); + + /* + * Create a reverse lookup for the actualType + */ + $this->customActualTypes[$actualType] = $metaType; + + return true; + } + + /** + * Get a list of custom meta types. + * + * @return string[] + */ + final public function getCustomMetaTypes() + { + return $this->customMetaTypes; + } - @returns An array with 2 elements: $arr['string'] is the description string, - and $arr[version] is the version (also a string). - */ + + /** + * Get server version info. + * + * @return string[] Array with 2 string elements: version and description + */ function ServerInfo() { return array('description' => '', 'version' => ''); } + /** + * Return true if connected to the database. + * + * @return bool + */ function IsConnected() { return !empty($this->_connectionID); } + /** + * Find version string. + * + * @param string $str + * + * @return string + */ function _findvers($str) { if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) { return $arr[1]; @@ -590,9 +772,13 @@ function _findvers($str) { } /** - * All error messages go through this bottleneck function. - * You can define your own handler by defining the function name in ADODB_OUTP. - */ + * All error messages go through this bottleneck function. + * + * You can define your own handler by defining the function name in ADODB_OUTP. + * + * @param string $msg Message to print + * @param bool $newline True to add a newline after printing $msg + */ static function outp($msg,$newline=true) { global $ADODB_FLUSH,$ADODB_OUTP; @@ -601,8 +787,7 @@ static function outp($msg,$newline=true) { $fn($msg,$newline); return; } else if (isset($ADODB_OUTP)) { - $fn = $ADODB_OUTP; - $fn($msg,$newline); + call_user_func($ADODB_OUTP,$msg,$newline); return; } @@ -623,6 +808,10 @@ static function outp($msg,$newline=true) { } + /** + * Return the database server's current date and time. + * @return int|false + */ function Time() { $rs = $this->_Execute("select $this->sysTimeStamp"); if ($rs && !$rs->EOF) { @@ -633,23 +822,43 @@ function Time() { } /** - * Connect to database + * Parses the hostname to extract the port. + * Overwrites $this->host and $this->port, only if a port is specified. + * The Hostname can be fully or partially qualified, + * ie: "db.mydomain.com:5432" or "ldaps://ldap.mydomain.com:636" + * Any specified scheme such as ldap:// or ldaps:// is maintained. + */ + protected function parseHostNameAndPort() { + $parsed_url = parse_url($this->host); + if (is_array($parsed_url) && isset($parsed_url['host']) && isset($parsed_url['port'])) { + if ( isset($parsed_url['scheme']) ) { + // If scheme is specified (ie: ldap:// or ldaps://, make sure we retain that. + $this->host = $parsed_url['scheme'] . "://" . $parsed_url['host']; + } else { + $this->host = $parsed_url['host']; + } + $this->port = $parsed_url['port']; + } + } + + /** + * Connect to database. * - * @param [argHostname] Host to connect to - * @param [argUsername] Userid to login - * @param [argPassword] Associated password - * @param [argDatabaseName] database - * @param [forceNew] force new connection + * @param string $argHostname Host to connect to + * @param string $argUsername Userid to login + * @param string $argPassword Associated password + * @param string $argDatabaseName Database name + * @param bool $forceNew Force new connection * - * @return true or false + * @return bool */ function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false) { if ($argHostname != "") { $this->host = $argHostname; } - if ( strpos($this->host, ':') > 0 && isset($this->port) ) { - list($this->host, $this->port) = explode(":", $this->host, 2); - } + // Overwrites $this->host and $this->port if a port is specified. + $this->parseHostNameAndPort(); + if ($argUsername != "") { $this->user = $argUsername; } @@ -692,34 +901,45 @@ function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDa return false; } + /** + * Always force a new connection to database. + * + * @param string $argHostname Host to connect to + * @param string $argUsername Userid to login + * @param string $argPassword Associated password + * @param string $argDatabaseName Database name + * + * @return bool + */ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName) { return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName); } - /** - * Always force a new connection to database - currently only works with oracle + * Always force a new connection to database. * - * @param [argHostname] Host to connect to - * @param [argUsername] Userid to login - * @param [argPassword] Associated password - * @param [argDatabaseName] database + * Currently this only works with Oracle. * - * @return true or false + * @param string $argHostname Host to connect to + * @param string $argUsername Userid to login + * @param string $argPassword Associated password + * @param string $argDatabaseName Database name + * + * @return bool */ function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") { return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true); } /** - * Establish persistent connect to database + * Establish persistent connection to database. * - * @param [argHostname] Host to connect to - * @param [argUsername] Userid to login - * @param [argPassword] Associated password - * @param [argDatabaseName] database + * @param string $argHostname Host to connect to + * @param string $argUsername Userid to login + * @param string $argPassword Associated password + * @param string $argDatabaseName Database name * - * @return return true or false + * @return bool */ function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") { @@ -730,9 +950,9 @@ function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argD if ($argHostname != "") { $this->host = $argHostname; } - if ( strpos($this->host, ':') > 0 && isset($this->port) ) { - list($this->host, $this->port) = explode(":", $this->host, 2); - } + // Overwrites $this->host and $this->port if a port is specified. + $this->parseHostNameAndPort(); + if ($argUsername != "") { $this->user = $argUsername; } @@ -756,7 +976,7 @@ function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argD $ret = false; } else { $err = "Missing extension for ".$this->dataProvider; - $ret = 0; + $ret = false; } if ($fn = $this->raiseErrorFn) { $fn($this->databaseType,'PCONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this); @@ -769,7 +989,13 @@ function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argD return $ret; } - function outp_throw($msg,$src='WARN',$sql='') { + /** + * Throw an exception if the handler is defined or prints the message if not. + * @param string $msg Message + * @param string $src the name of the calling function (in uppercase) + * @param string $sql Optional offending SQL statement + */ + function outp_throw($msg, $src='WARN', $sql='') { if (defined('ADODB_ERROR_HANDLER') && ADODB_ERROR_HANDLER == 'adodb_throw') { adodb_throw($this->databaseType,$src,-9999,$msg,$sql,false,$this); return; @@ -777,7 +1003,11 @@ function outp_throw($msg,$src='WARN',$sql='') { ADOConnection::outp($msg); } - // create cache class. Code is backward compat with old memcache implementation + /** + * Create cache class. + * + * Code is backwards-compatible with old memcache implementation. + */ function _CreateCache() { global $ADODB_CACHE, $ADODB_CACHE_CLASS; @@ -793,8 +1023,18 @@ function _CreateCache() { } } - // Format date column in sql string given an input format that understands Y M D - function SQLDate($fmt, $col=false) { + /** + * Format date column in sql string. + * + * See https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:sqldate + * for documentation on supported formats. + * + * @param string $fmt Format string + * @param string $col Date column; use system date if not specified. + * + * @return string + */ + function SQLDate($fmt, $col = '') { if (!$col) { $col = $this->sysDate; } @@ -802,66 +1042,79 @@ function SQLDate($fmt, $col=false) { } /** - * Should prepare the sql statement and return the stmt resource. - * For databases that do not support this, we return the $sql. To ensure - * compatibility with databases that do not support prepare: + * Prepare an SQL statement and return the statement resource. * - * $stmt = $db->Prepare("insert into table (id, name) values (?,?)"); - * $db->Execute($stmt,array(1,'Jill')) or die('insert failed'); - * $db->Execute($stmt,array(2,'Joe')) or die('insert failed'); + * For databases that do not support prepared statements, we return the + * provided SQL statement as-is, to ensure compatibility: * - * @param sql SQL to send to database + * $stmt = $db->prepare("insert into table (id, name) values (?,?)"); + * $db->execute($stmt, array(1,'Jill')) or die('insert failed'); + * $db->execute($stmt, array(2,'Joe')) or die('insert failed'); * - * @return return FALSE, or the prepared statement, or the original sql if - * if the database does not support prepare. + * @param string $sql SQL to send to database * + * @return mixed|false The prepared statement, or the original sql if the + * database does not support prepare. */ function Prepare($sql) { return $sql; } /** + * Releases a previously prepared statement. + * + * @param mixed $stmt Statement resource, as returned by {@see prepare()} + * + * @return bool + */ + function releaseStatement(&$stmt) { + return true; + } + + /** + * Prepare a Stored Procedure and return the statement resource. + * * Some databases, eg. mssql require a different function for preparing * stored procedures. So we cannot use Prepare(). * - * Should prepare the stored procedure and return the stmt resource. - * For databases that do not support this, we return the $sql. To ensure - * compatibility with databases that do not support prepare: + * For databases that do not support this, we return the $sql. * - * @param sql SQL to send to database - * - * @return return FALSE, or the prepared statement, or the original sql if - * if the database does not support prepare. + * @param string $sql SQL to send to database + * @param bool $param * + * @return mixed|false The prepared statement, or the original sql if the + * database does not support prepare. */ function PrepareSP($sql,$param=true) { return $this->Prepare($sql,$param); } /** - * PEAR DB Compat - */ + * PEAR DB Compat - alias for qStr. + * @param $s + * @return string + */ function Quote($s) { - return $this->qstr($s,false); + return $this->qstr($s); } /** - * Requested by "Karsten Dambekalns" + * Quotes a string so that all strings are escaped. + * Wrapper for qstr with magic_quotes = false. + * + * @param string &$s */ - function QMagic($s) { - return $this->qstr($s,get_magic_quotes_gpc()); - } - function q(&$s) { //if (!empty($this->qNull && $s == 'null') { // return $s; //} - $s = $this->qstr($s,false); + $s = $this->qstr($s); } /** - * PEAR DB Compat - do not use internally. - */ + * PEAR DB Compat - do not use internally. + * @return int + */ function ErrorNative() { return $this->ErrorNo(); } @@ -869,39 +1122,54 @@ function ErrorNative() { /** * PEAR DB Compat - do not use internally. + * @param string $seq_name + * @return int */ function nextId($seq_name) { return $this->GenID($seq_name); } /** - * Lock a row, will escalate and lock the table if row locking not supported - * will normally free the lock at the end of the transaction + * Lock a row. + * Will escalate and lock the table if row locking is not supported. + * Will normally free the lock at the end of the transaction. + * + * @param string $table name of table to lock + * @param string $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock + * @param string $col * - * @param $table name of table to lock - * @param $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock + * @return bool */ function RowLock($table,$where,$col='1 as adodbignore') { return false; } + /** + * @param string $table + * @return true + */ function CommitLock($table) { return $this->CommitTrans(); } + /** + * @param string $table + * @return true + */ function RollbackLock($table) { return $this->RollbackTrans(); } /** - * PEAR DB Compat - do not use internally. - * - * The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical - * for easy porting :-) - * - * @param mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM - * @returns The previous fetch mode - */ + * PEAR DB Compat - do not use internally. + * + * The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical + * for easy porting :-) + * + * @param int $mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM + * + * @return int Previous fetch mode + */ function SetFetchMode($mode) { $old = $this->fetchMode; $this->fetchMode = $mode; @@ -913,10 +1181,14 @@ function SetFetchMode($mode) { return $old; } - /** - * PEAR DB Compat - do not use internally. - */ + * PEAR DB Compat - do not use internally. + * + * @param string $sql + * @param array|bool $inputarr + * + * @return ADORecordSet|bool + */ function Query($sql, $inputarr=false) { $rs = $this->Execute($sql, $inputarr); if (!$rs && defined('ADODB_PEAR')) { @@ -925,10 +1197,9 @@ function Query($sql, $inputarr=false) { return $rs; } - /** - * PEAR DB Compat - do not use internally - */ + * PEAR DB Compat - do not use internally + */ function LimitQuery($sql, $offset, $count, $params=false) { $rs = $this->SelectLimit($sql, $count, $offset, $params); if (!$rs && defined('ADODB_PEAR')) { @@ -939,22 +1210,26 @@ function LimitQuery($sql, $offset, $count, $params=false) { /** - * PEAR DB Compat - do not use internally - */ + * PEAR DB Compat - do not use internally + */ function Disconnect() { return $this->Close(); } /** - * Returns a placeholder for query parameters + * Returns a placeholder for query parameters. + * * e.g. $DB->Param('a') will return * - '?' for most databases * - ':a' for Oracle * - '$1', '$2', etc. for PostgreSQL - * @param string $name parameter's name, false to force a reset of the - * number to 1 (for databases that require positioned - * params such as PostgreSQL; note that ADOdb will - * automatically reset this when executing a query ) + * + * @param mixed $name parameter's name. + * For databases that require positioned params (e.g. PostgreSQL), + * a "falsy" value can be used to force resetting the placeholder + * count; using boolean 'false' will reset it without actually + * returning a placeholder. ADOdb will also automatically reset + * the count when executing a query. * @param string $type (unused) * @return string query parameter placeholder */ @@ -962,36 +1237,54 @@ function Param($name,$type='C') { return '?'; } - /* - InParameter and OutParameter are self-documenting versions of Parameter(). - */ - function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false) { + /** + * Self-documenting version of Parameter(). + * + * @param $stmt + * @param &$var + * @param $name + * @param int $maxLen + * @param bool $type + * + * @return bool + */ + function InParameter(&$stmt, &$var, $name, $maxLen=4000, $type=false) { return $this->Parameter($stmt,$var,$name,false,$maxLen,$type); } - /* - */ + /** + * Self-documenting version of Parameter(). + * + * @param $stmt + * @param $var + * @param $name + * @param int $maxLen + * @param bool $type + * + * @return bool + */ function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false) { return $this->Parameter($stmt,$var,$name,true,$maxLen,$type); } - - /* - Usage in oracle - $stmt = $db->Prepare('select * from table where id =:myid and group=:group'); - $db->Parameter($stmt,$id,'myid'); - $db->Parameter($stmt,$group,'group',64); - $db->Execute(); - - @param $stmt Statement returned by Prepare() or PrepareSP(). - @param $var PHP variable to bind to - @param $name Name of stored procedure variable name to bind to. - @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. - @param [$maxLen] Holds an maximum length of the variable. - @param [$type] The data type of $var. Legal values depend on driver. - - */ + /** + * + * Usage in oracle + * $stmt = $db->Prepare('select * from table where id =:myid and group=:group'); + * $db->Parameter($stmt,$id,'myid'); + * $db->Parameter($stmt,$group,'group',64); + * $db->Execute(); + * + * @param mixed &$stmt Statement returned by Prepare() or PrepareSP(). + * @param mixed &$var PHP variable to bind to + * @param string $name Name of stored procedure variable name to bind to. + * @param int|bool $isOutput Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. + * @param int $maxLen Holds an maximum length of the variable. + * @param mixed $type The data type of $var. Legal values depend on driver. + * + * @return bool + */ function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false) { return false; } @@ -1038,13 +1331,16 @@ function StartTrans($errfn = 'ADODB_TransMonitor') { /** - Used together with StartTrans() to end a transaction. Monitors connection - for sql errors, and will commit or rollback as appropriate. - - @autoComplete if true, monitor sql errors and commit and rollback as appropriate, - and if set to false force rollback even if no SQL error detected. - @returns true on commit, false on rollback. - */ + * Complete a transation. + * + * Used together with StartTrans() to end a transaction. Monitors connection + * for sql errors, and will commit or rollback as appropriate. + * + * @param bool autoComplete if true, monitor sql errors and commit and + * rollback as appropriate, and if set to false + * force rollback even if no SQL error detected. + * @returns true on commit, false on rollback. + */ function CompleteTrans($autoComplete = true) { if ($this->transOff > 1) { $this->transOff -= 1; @@ -1068,16 +1364,16 @@ function CompleteTrans($autoComplete = true) { $this->_transOK = false; $this->RollbackTrans(); if ($this->debug) { - ADOCOnnection::outp("Smart Rollback occurred"); + ADOConnection::outp("Smart Rollback occurred"); } } return $this->_transOK; } - /* - At the end of a StartTrans/CompleteTrans block, perform a rollback. - */ + /** + * At the end of a StartTrans/CompleteTrans block, perform a rollback. + */ function FailTrans() { if ($this->debug) if ($this->transOff == 0) { @@ -1090,8 +1386,8 @@ function FailTrans() { } /** - Check if transaction has failed, only for Smart Transactions. - */ + * Check if transaction has failed, only for Smart Transactions. + */ function HasFailedTrans() { if ($this->transOff > 0) { return $this->_transOK == false; @@ -1102,11 +1398,14 @@ function HasFailedTrans() { /** * Execute SQL * - * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text) - * @param [inputarr] holds the input data to bind to. Null elements will be set to null. - * @return RecordSet or false + * @param string $sql SQL statement to execute, or possibly an array + * holding prepared statement ($sql[0] will hold sql text) + * @param array|bool $inputarr holds the input data to bind to. + * Null elements will be set to null. + * + * @return ADORecordSet|bool */ - function Execute($sql,$inputarr=false) { + public function Execute($sql, $inputarr = false) { if ($this->fnExecute) { $fn = $this->fnExecute; $ret = $fn($this,$sql,$inputarr); @@ -1163,8 +1462,7 @@ function Execute($sql,$inputarr=false) { foreach($inputarr as $arr) { $sql = ''; $i = 0; - //Use each() instead of foreach to reduce memory usage -mikefedyk - while(list(, $v) = each($arr)) { + foreach ($arr as $v) { $sql .= $sqlarr[$i]; // from Ron Baldwin // Only quote string types @@ -1238,13 +1536,14 @@ function _Execute($sql,$inputarr=false) { if( is_string($sql) ) { // Strips keyword used to help generate SELECT COUNT(*) queries // from SQL if it exists. - $sql = ADODB_str_replace( '_ADODB_COUNT', '', $sql ); + // TODO: obsoleted by #715 - kept for backwards-compatibility + $sql = str_replace( '_ADODB_COUNT', '', $sql ); } if ($this->debug) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } $this->_queryID = _adodb_debug_execute($this, $sql,$inputarr); } else { @@ -1275,8 +1574,17 @@ function _Execute($sql,$inputarr=false) { return $rs; } + if ($this->dataProvider == 'pdo' && $this->databaseType != 'pdo') { + // PDO uses a slightly different naming convention for the + // recordset class if the database type is changed, so we must + // treat it specifically. The mysql driver leaves the + // databaseType as pdo + $rsclass = $this->rsPrefix . 'pdo_' . $this->databaseType; + } else { + $rsclass = $this->rsPrefix . $this->databaseType; + } + // return real recordset from select statement - $rsclass = $this->rsPrefix.$this->databaseType; $rs = new $rsclass($this->_queryID,$this->fetchMode); $rs->connection = $this; // Pablo suggestion $rs->Init(); @@ -1313,12 +1621,14 @@ function DropSequence($seqname='adodbseq') { } /** - * Generates a sequence id and stores it in $this->genID; + * Generates a sequence id and stores it in $this->genID. + * * GenID is only available if $this->hasGenID = true; * - * @param seqname name of sequence to use - * @param startID if sequence does not exist, start at this ID - * @return 0 if not supported, otherwise a sequence id + * @param string $seqname Name of sequence to use + * @param int $startID If sequence does not exist, start at this ID + * + * @return int Sequence id, 0 if not supported */ function GenID($seqname='adodbseq',$startID=1) { if (!$this->hasGenID) { @@ -1353,16 +1663,22 @@ function GenID($seqname='adodbseq',$startID=1) { } /** - * @param $table string name of the table, not needed by all databases (eg. mysql), default '' - * @param $column string name of the column, not needed by all databases (eg. mysql), default '' - * @return the last inserted ID. Not all databases support this. + * Returns the last inserted ID. + * + * Not all databases support this feature. Some do not require to specify + * table or column name (e.g. MySQL). + * + * @param string $table Table name, default '' + * @param string $column Column name, default '' + * + * @return int The last inserted ID. */ function Insert_ID($table='',$column='') { if ($this->_logsql && $this->lastInsID) { return $this->lastInsID; } if ($this->hasInsertID) { - return $this->_insertid($table,$column); + return $this->_insertID($table,$column); } if ($this->debug) { ADOConnection::outp( '

Insert_ID error

'); @@ -1371,12 +1687,37 @@ function Insert_ID($table='',$column='') { return false; } + /** + * Enable or disable the Last Insert Id functionality. + * + * If the Driver supports it, this function allows setting {@see $hasInsertID}. + * + * @param bool $enable False to disable + */ + public function enableLastInsertID($enable = true) {} + + /** + * Return the id of the last row that has been inserted in a table. + * + * @param string $table + * @param string $column + * + * @return int|false + */ + protected function _insertID($table = '', $column = '') + { + return false; + } /** * Portable Insert ID. Pablo Roca * - * @return the last inserted ID. All databases support this. But aware possible - * problems in multiuser environments. Heavy test this before deploying. + * @param string $table + * @param string $id + + * @return mixed The last inserted ID. All databases support this, but be + * aware of possible problems in multiuser environments. + * Heavily test this before deploying. */ function PO_Insert_ID($table="", $id="") { if ($this->hasInsertID){ @@ -1387,8 +1728,8 @@ function PO_Insert_ID($table="", $id="") { } /** - * @return # rows affected by UPDATE/DELETE - */ + * @return int|false Number of rows affected by UPDATE/DELETE + */ function Affected_Rows() { if ($this->hasAffectedRows) { if ($this->fnExecute === 'adodb_log_sql') { @@ -1408,7 +1749,7 @@ function Affected_Rows() { /** - * @return the last error message + * @return string the last error message */ function ErrorMsg() { if ($this->_errorMsg) { @@ -1420,7 +1761,7 @@ function ErrorMsg() { /** - * @return the last error number. Normally 0 means no error. + * @return int the last error number. Normally 0 means no error. */ function ErrorNo() { return ($this->_errorMsg) ? -1 : 0; @@ -1463,21 +1804,36 @@ function MetaPrimaryKeys($table, $owner=false) { } /** - * @returns assoc array where keys are tables, and values are foreign keys + * Returns a list of Foreign Keys associated with a specific table. + * + * If there are no foreign keys then the function returns false. + * + * @param string $table The name of the table to get the foreign keys for. + * @param string $owner Table owner/schema. + * @param bool $upper If true, only matches the table with the uppercase name. + * @param bool $associative Returns the result in associative mode; + * if ADODB_FETCH_MODE is already associative, then + * this parameter is discarded. + * + * @return string[]|false An array where keys are tables, and values are foreign keys; + * false if no foreign keys could be found. */ - function MetaForeignKeys($table, $owner=false, $upper=false) { + function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { return false; } + /** * Choose a database to connect to. Many databases do not support this. * - * @param dbName is the name of the database to select - * @return true or false + * @param string $dbName the name of the database to select + * @return bool */ function SelectDB($dbName) {return false;} /** + * Select a limited number of rows. + * * Will select, getting rows from $offset (1-based), for $nrows. * This simulates the MySQL "select * from table limit $offset,$nrows" , and * the PostgreSQL "select * from table limit $nrows offset $offset". Note that @@ -1489,14 +1845,18 @@ function SelectDB($dbName) {return false;} * Uses SELECT TOP for Microsoft databases (when $this->hasTop is set) * BUG: Currently SelectLimit fails with $sql with LIMIT or TOP clause already set * - * @param sql - * @param [offset] is the row to start calculations from (1-based) - * @param [nrows] is the number of rows to get - * @param [inputarr] array of bind variables - * @param [secs2cache] is a private parameter only used by jlim - * @return the recordset ($rs->databaseType == 'array') + * @param string $sql + * @param int $offset Row to start calculations from (1-based) + * @param int $nrows Number of rows to get + * @param array|bool $inputarr Array of bind variables + * @param int $secs2cache Private parameter only used by jlim + * + * @return ADORecordSet The recordset ($rs->databaseType == 'array') */ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { + $nrows = (int)$nrows; + $offset = (int)$offset; + if ($this->hasTop && $nrows > 0) { // suggested by Reinhard Balling. Access requires top after distinct // Informix requires first before distinct - F Riosa @@ -1508,32 +1868,47 @@ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { } if ($offset <= 0) { - // access includes ties in result - if ($isaccess) { - $sql = preg_replace( - '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql); + // access includes ties in result + if ($isaccess) { + $sql = preg_replace( + '/(^\s*select\s+(distinctrow|distinct)?)/i', + '\\1 '.$this->hasTop.' '.$nrows.' ', + $sql + ); - if ($secs2cache != 0) { - $ret = $this->CacheExecute($secs2cache, $sql,$inputarr); - } else { - $ret = $this->Execute($sql,$inputarr); - } - return $ret; // PHP5 fix - } else if ($ismssql){ - $sql = preg_replace( - '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql); + if ($secs2cache != 0) { + $ret = $this->CacheExecute($secs2cache, $sql,$inputarr); } else { - $sql = preg_replace( - '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql); + $ret = $this->Execute($sql,$inputarr); } + return $ret; // PHP5 fix + } else if ($ismssql){ + $sql = preg_replace( + '/(^\s*select\s+(distinctrow|distinct)?)/i', + '\\1 '.$this->hasTop.' '.$nrows.' ', + $sql + ); + } else { + $sql = preg_replace( + '/(^\s*select\s)/i', + '\\1 '.$this->hasTop.' '.$nrows.' ', + $sql + ); + } } else { $nn = $nrows + $offset; if ($isaccess || $ismssql) { $sql = preg_replace( - '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql); + '/(^\s*select\s+(distinctrow|distinct)?)/i', + '\\1 '.$this->hasTop.' '.$nn.' ', + $sql + ); } else { $sql = preg_replace( - '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql); + '/(^\s*select\s)/i', + '\\1 '.$this->hasTop.' '.$nn.' ', + $sql + ); } } } @@ -1542,17 +1917,19 @@ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { // 0 to offset-1 which will be discarded anyway. So we disable $ADODB_COUNTRECS. global $ADODB_COUNTRECS; - $savec = $ADODB_COUNTRECS; - $ADODB_COUNTRECS = false; + try { + $savec = $ADODB_COUNTRECS; + $ADODB_COUNTRECS = false; - - if ($secs2cache != 0) { - $rs = $this->CacheExecute($secs2cache,$sql,$inputarr); - } else { - $rs = $this->Execute($sql,$inputarr); + if ($secs2cache != 0) { + $rs = $this->CacheExecute($secs2cache, $sql, $inputarr); + } else { + $rs = $this->Execute($sql, $inputarr); + } + } finally { + $ADODB_COUNTRECS = $savec; } - $ADODB_COUNTRECS = $savec; if ($rs && !$rs->EOF) { $rs = $this->_rs2rs($rs,$nrows,$offset); } @@ -1561,10 +1938,12 @@ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { } /** - * Create serializable recordset. Breaks rs link to connection. - * - * @param rs the recordset to serialize - */ + * Create serializable recordset. Breaks rs link to connection. + * + * @param ADORecordSet $rs the recordset to serialize + * + * @return ADORecordSet_array|bool the new recordset + */ function SerializableRS(&$rs) { $rs2 = $this->_rs2rs($rs); $ignore = false; @@ -1574,18 +1953,21 @@ function SerializableRS(&$rs) { } /** - * Convert database recordset to an array recordset - * input recordset's cursor should be at beginning, and - * old $rs will be closed. - * - * @param rs the recordset to copy - * @param [nrows] number of rows to retrieve (optional) - * @param [offset] offset by number of rows (optional) - * @return the new recordset - */ + * Convert a database recordset to an array recordset. + * + * Input recordset's cursor should be at beginning, and old $rs will be closed. + * + * @param ADORecordSet $rs the recordset to copy + * @param int $nrows number of rows to retrieve (optional) + * @param int $offset offset by number of rows (optional) + * @param bool $close + * + * @return ADORecordSet_array|ADORecordSet|bool the new recordset + */ function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true) { if (! $rs) { - return false; + $ret = false; + return $ret; } $dbtype = $rs->databaseType; if (!$dbtype) { @@ -1610,7 +1992,7 @@ function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true) { $arrayClass = $this->arrayClass; - $rs2 = new $arrayClass(); + $rs2 = new $arrayClass($fakeQueryId=1); $rs2->connection = $this; $rs2->sql = $rs->sql; $rs2->dataProvider = $this->dataProvider; @@ -1619,24 +2001,59 @@ function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true) { return $rs2; } - /* - * Return all rows. Compat with PEAR DB - */ + /** + * Return all rows. + * + * Compat with PEAR DB. + * + * @param string $sql SQL statement + * @param array|bool $inputarr Input bind array + * + * @return array|false + */ function GetAll($sql, $inputarr=false) { - $arr = $this->GetArray($sql,$inputarr); - return $arr; + return $this->GetArray($sql,$inputarr); } - function GetAssoc($sql, $inputarr=false,$force_array = false, $first2cols = false) { + /** + * Execute statement and return rows in an array. + * + * The function executes a statement and returns all of the returned rows in + * an array, or false if the statement execution fails or if only 1 column + * is requested in the SQL statement. + * If no records match the provided SQL statement, an empty array is returned. + * + * @param string $sql SQL statement + * @param array|bool $inputarr input bind array + * @param bool $force_array + * @param bool $first2cols + * + * @return array|bool + */ + public function GetAssoc($sql, $inputarr = false, $force_array = false, $first2cols = false) { $rs = $this->Execute($sql, $inputarr); + if (!$rs) { + /* + * Execution failure + */ return false; } - $arr = $rs->GetAssoc($force_array,$first2cols); - return $arr; + return $rs->GetAssoc($force_array, $first2cols); } - function CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = false, $first2cols = false) { + /** + * Search for the results of an executed query in the cache. + * + * @param int $secs2cache + * @param string|bool $sql SQL statement + * @param array|bool $inputarr input bind array + * @param bool $force_array + * @param bool $first2cols + * + * @return false|array + */ + public function CacheGetAssoc($secs2cache, $sql = false, $inputarr = false,$force_array = false, $first2cols = false) { if (!is_numeric($secs2cache)) { $first2cols = $force_array; $force_array = $inputarr; @@ -1645,25 +2062,29 @@ function CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = f if (!$rs) { return false; } - $arr = $rs->GetAssoc($force_array,$first2cols); - return $arr; + return $rs->GetAssoc($force_array, $first2cols); } /** - * Return first element of first row of sql statement. Recordset is disposed - * for you. - * - * @param sql SQL statement - * @param [inputarr] input bind array - */ - function GetOne($sql,$inputarr=false) { + * Return first element of first row of sql statement. Recordset is disposed + * for you. + * + * @param string $sql SQL statement + * @param array|bool $inputarr input bind array + * @return mixed + */ + public function GetOne($sql, $inputarr=false) { global $ADODB_COUNTRECS,$ADODB_GETONE_EOF; - $crecs = $ADODB_COUNTRECS; - $ADODB_COUNTRECS = false; + try { + $crecs = $ADODB_COUNTRECS; + $ADODB_COUNTRECS = false; + $rs = $this->Execute($sql, $inputarr); + } finally { + $ADODB_COUNTRECS = $crecs; + } $ret = false; - $rs = $this->Execute($sql,$inputarr); if ($rs) { if ($rs->EOF) { $ret = $ADODB_GETONE_EOF; @@ -1673,7 +2094,6 @@ function GetOne($sql,$inputarr=false) { $rs->Close(); } - $ADODB_COUNTRECS = $crecs; return $ret; } @@ -1710,6 +2130,17 @@ function CacheGetOne($secs2cache,$sql=false,$inputarr=false) { return $ret; } + /** + * Executes a statement and returns each row's first column in an array. + * + * @param string $sql SQL statement + * @param array|bool $inputarr input bind array + * @param bool $trim enables space trimming of the returned value. + * This is only relevant if the returned string + * is coming from a CHAR type field. + * + * @return array|bool 1D array containning the first row of the query + */ function GetCol($sql, $inputarr = false, $trim = false) { $rs = $this->Execute($sql, $inputarr); @@ -1755,23 +2186,17 @@ function CacheGetCol($secs, $sql = false, $inputarr = false,$trim=false) { return $rv; } - function Transpose(&$rs,$addfieldnames=true) { - $rs2 = $this->_rs2rs($rs); - if (!$rs2) { - return false; - } - - $rs2->_transpose($addfieldnames); - return $rs2; - } - - /* - Calculate the offset of a date for a particular database and generate - appropriate SQL. Useful for calculating future/past dates and storing - in a database. - - If dayFraction=1.5 means 1.5 days from now, 1.0/24 for 1 hour. - */ + /** + * Calculate the offset of a date for a particular database + * and generate appropriate SQL. + * + * Useful for calculating future/past dates and storing in a database. + * + * @param double $dayFraction 1.5 means 1.5 days from now, 1.0/24 for 1 hour + * @param string|false $date Reference date, false for system time + * + * @return string + */ function OffsetDate($dayFraction,$date=false) { if (!$date) { $date = $this->sysDate; @@ -1781,21 +2206,27 @@ function OffsetDate($dayFraction,$date=false) { /** - * - * @param sql SQL statement - * @param [inputarr] input bind array - */ + * Executes a statement and returns a the entire recordset in an array. + * + * @param string $sql SQL statement + * @param array|bool $inputarr input bind array + * + * @return array|false + */ function GetArray($sql,$inputarr=false) { global $ADODB_COUNTRECS; - $savec = $ADODB_COUNTRECS; - $ADODB_COUNTRECS = false; - $rs = $this->Execute($sql,$inputarr); - $ADODB_COUNTRECS = $savec; + try { + $savec = $ADODB_COUNTRECS; + $ADODB_COUNTRECS = false; + $rs = $this->Execute($sql, $inputarr); + } finally { + $ADODB_COUNTRECS = $savec; + } + if (!$rs) if (defined('ADODB_PEAR')) { - $cls = ADODB_PEAR_Error(); - return $cls; + return ADODB_PEAR_Error(); } else { return false; } @@ -1805,22 +2236,23 @@ function GetArray($sql,$inputarr=false) { } function CacheGetAll($secs2cache,$sql=false,$inputarr=false) { - $arr = $this->CacheGetArray($secs2cache,$sql,$inputarr); - return $arr; + return $this->CacheGetArray($secs2cache,$sql,$inputarr); } function CacheGetArray($secs2cache,$sql=false,$inputarr=false) { global $ADODB_COUNTRECS; - $savec = $ADODB_COUNTRECS; - $ADODB_COUNTRECS = false; - $rs = $this->CacheExecute($secs2cache,$sql,$inputarr); - $ADODB_COUNTRECS = $savec; + try { + $savec = $ADODB_COUNTRECS; + $ADODB_COUNTRECS = false; + $rs = $this->CacheExecute($secs2cache, $sql, $inputarr); + } finally { + $ADODB_COUNTRECS = $savec; + } if (!$rs) if (defined('ADODB_PEAR')) { - $cls = ADODB_PEAR_Error(); - return $cls; + return ADODB_PEAR_Error(); } else { return false; } @@ -1836,21 +2268,25 @@ function GetRandRow($sql, $arr= false) { } /** - * Return one row of sql statement. Recordset is disposed for you. - * Note that SelectLimit should not be called. - * - * @param sql SQL statement - * @param [inputarr] input bind array - */ + * Return one row of sql statement. Recordset is disposed for you. + * Note that SelectLimit should not be called. + * + * @param string $sql SQL statement + * @param array|bool $inputarr input bind array + * + * @return array|false Array containing the first row of the query + */ function GetRow($sql,$inputarr=false) { global $ADODB_COUNTRECS; - $crecs = $ADODB_COUNTRECS; - $ADODB_COUNTRECS = false; - - $rs = $this->Execute($sql,$inputarr); + try { + $crecs = $ADODB_COUNTRECS; + $ADODB_COUNTRECS = false; + $rs = $this->Execute($sql, $inputarr); + } finally { + $ADODB_COUNTRECS = $crecs; + } - $ADODB_COUNTRECS = $crecs; if ($rs) { if (!$rs->EOF) { $arr = $rs->fields; @@ -1864,6 +2300,12 @@ function GetRow($sql,$inputarr=false) { return false; } + /** + * @param int $secs2cache + * @param string|false $sql + * @param mixed[]|bool $inputarr + * @return mixed[]|bool + */ function CacheGetRow($secs2cache,$sql=false,$inputarr=false) { $rs = $this->CacheExecute($secs2cache,$sql,$inputarr); if ($rs) { @@ -1880,29 +2322,29 @@ function CacheGetRow($secs2cache,$sql=false,$inputarr=false) { } /** - * Insert or replace a single record. Note: this is not the same as MySQL's replace. - * ADOdb's Replace() uses update-insert semantics, not insert-delete-duplicates of MySQL. - * Also note that no table locking is done currently, so it is possible that the - * record be inserted twice by two programs... - * - * $this->Replace('products', array('prodname' =>"'Nails'","price" => 3.99), 'prodname'); - * - * $table table name - * $fieldArray associative array of data (you must quote strings yourself). - * $keyCol the primary key field name or if compound key, array of field names - * autoQuote set to true to use a hueristic to quote strings. Works with nulls and numbers - * but does not work with dates nor SQL functions. - * has_autoinc the primary key is an auto-inc field, so skip in insert. - * - * Currently blob replace not supported - * - * returns 0 = fail, 1 = update, 2 = insert - */ + * Insert or replace a single record. Note: this is not the same as MySQL's replace. + * ADOdb's Replace() uses update-insert semantics, not insert-delete-duplicates of MySQL. + * Also note that no table locking is done currently, so it is possible that the + * record be inserted twice by two programs... + * + * $this->Replace('products', array('prodname' =>"'Nails'","price" => 3.99), 'prodname'); + * + * $table table name + * $fieldArray associative array of data (you must quote strings yourself). + * $keyCol the primary key field name or if compound key, array of field names + * autoQuote set to true to use a heuristic to quote strings. Works with nulls and numbers + * but does not work with dates nor SQL functions. + * has_autoinc the primary key is an auto-inc field, so skip in insert. + * + * Currently blob replace not supported + * + * returns 0 = fail, 1 = update, 2 = insert + */ function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } return _adodb_replace($this, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc); @@ -1920,12 +2362,13 @@ function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=fa * * BUG: Currently CacheSelectLimit fails with $sql with LIMIT or TOP clause already set * - * @param [secs2cache] seconds to cache data, set to 0 to force query. This is optional - * @param sql - * @param [offset] is the row to start calculations from (1-based) - * @param [nrows] is the number of rows to get - * @param [inputarr] array of bind variables - * @return the recordset ($rs->databaseType == 'array') + * @param int $secs2cache Seconds to cache data, set to 0 to force query. This is optional + * @param string $sql + * @param int $offset Row to start calculations from (1-based) + * @param int $nrows Number of rows to get + * @param array $inputarr Array of bind variables + * + * @return ADORecordSet The recordset ($rs->databaseType == 'array') */ function CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false) { if (!is_numeric($secs2cache)) { @@ -2008,11 +2451,12 @@ function _gencachename($sql,$createdir) { /** * Execute SQL, caching recordsets. * - * @param [secs2cache] seconds to cache data, set to 0 to force query. - * This is an optional parameter. - * @param sql SQL statement to execute - * @param [inputarr] holds the input data to bind to - * @return RecordSet or false + * @param int $secs2cache Seconds to cache data, set to 0 to force query. + * This is an optional parameter. + * @param string|bool $sql SQL statement to execute + * @param array|bool $inputarr Holds the input data to bind + * + * @return ADORecordSet RecordSet or false */ function CacheExecute($secs2cache,$sql=false,$inputarr=false) { global $ADODB_CACHE; @@ -2047,11 +2491,8 @@ function CacheExecute($secs2cache,$sql=false,$inputarr=false) { } if (!$rs) { - // no cached rs found + // no cached rs found if ($this->debug) { - if (get_magic_quotes_runtime() && !$this->memCache) { - ADOConnection::outp("Please disable magic_quotes_runtime - it corrupts cache files :("); - } if ($this->debug !== -1) { ADOConnection::outp( " $md5file cache failure: $err (this is a notice and not an error)"); } @@ -2122,13 +2563,32 @@ function CacheExecute($secs2cache,$sql=false,$inputarr=false) { /* - Similar to PEAR DB's autoExecute(), except that - $mode can be 'INSERT' or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE - If $mode == 'UPDATE', then $where is compulsory as a safety measure. - $forceUpdate means that even if the data has not changed, perform update. + + $forceUpdate . */ - function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $forceUpdate = true, $magicq = false) { + /** + * Similar to PEAR DB's autoExecute(), except that $mode can be 'INSERT' + * or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE. + * If $mode == 'UPDATE', then $where is compulsory as a safety measure. + * + * @param $table + * @param $fields_values + * @param string $mode + * @param false $where + * @param bool $forceUpdate If true, perform update even if the data has not changed. + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * + * @return bool + * + * @noinspection PhpUnusedParameterInspection + */ + function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $forceUpdate = true, $magic_quotes = false) { + if (empty($fields_values)) { + $this->outp_throw('AutoExecute: Empty fields array', 'AutoExecute'); + return false; + } if ($where === false && ($mode == 'UPDATE' || $mode == 2 /* DB_AUTOQUERY_UPDATE */) ) { $this->outp_throw('AutoExecute: Illegal mode=UPDATE with empty WHERE clause', 'AutoExecute'); return false; @@ -2149,11 +2609,11 @@ function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $ switch($mode) { case 'UPDATE': case DB_AUTOQUERY_UPDATE: - $sql = $this->GetUpdateSQL($rs, $fields_values, $forceUpdate, $magicq); + $sql = $this->GetUpdateSQL($rs, $fields_values, $forceUpdate); break; case 'INSERT': case DB_AUTOQUERY_INSERT: - $sql = $this->GetInsertSQL($rs, $fields_values, $magicq); + $sql = $this->GetInsertSQL($rs, $fields_values); break; default: $this->outp_throw("AutoExecute: Unknown mode=$mode", 'AutoExecute'); @@ -2165,16 +2625,27 @@ function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $ /** * Generates an Update Query based on an existing recordset. + * * $arrFields is an associative array of fields with the value * that should be assigned. * * Note: This function should only be used on a recordset - * that is run against a single table and sql should only - * be a simple select stmt with no groupby/orderby/limit + * that is run against a single table and sql should only + * be a simple select stmt with no groupby/orderby/limit + * @author "Jonathan Younger" * - * "Jonathan Younger" + * @param $rs + * @param $arrFields + * @param bool $forceUpdate + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * @param null $force + * + * @return false|string + * + * @noinspection PhpUnusedParameterInspection */ - function GetUpdateSQL(&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=null) { + function GetUpdateSQL(&$rs, $arrFields, $forceUpdate=false, $magic_quotes=false, $force=null) { global $ADODB_INCLUDED_LIB; // ******************************************************** @@ -2187,64 +2658,85 @@ function GetUpdateSQL(&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=n // ******************************************************** if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } - return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpdate,$magicq,$force); + return _adodb_getupdatesql($this, $rs, $arrFields, $forceUpdate, $force); } /** * Generates an Insert Query based on an existing recordset. + * * $arrFields is an associative array of fields with the value * that should be assigned. * * Note: This function should only be used on a recordset * that is run against a single table. + * + * @param $rs + * @param $arrFields + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * @param null $force + * + * @return false|string + * + * @noinspection PhpUnusedParameterInspection */ - function GetInsertSQL(&$rs, $arrFields,$magicq=false,$force=null) { + function GetInsertSQL(&$rs, $arrFields, $magic_quotes=false, $force=null) { global $ADODB_INCLUDED_LIB; if (!isset($force)) { global $ADODB_FORCE_TYPE; $force = $ADODB_FORCE_TYPE; } if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); - } - return _adodb_getinsertsql($this,$rs,$arrFields,$magicq,$force); - } - - - /** - * Update a blob column, given a where clause. There are more sophisticated - * blob handling functions that we could have implemented, but all require - * a very complex API. Instead we have chosen something that is extremely - * simple to understand and use. - * - * Note: $blobtype supports 'BLOB' and 'CLOB', default is BLOB of course. - * - * Usage to update a $blobvalue which has a primary key blob_id=1 into a - * field blobtable.blobcolumn: - * - * UpdateBlob('blobtable', 'blobcolumn', $blobvalue, 'blob_id=1'); - * - * Insert example: - * - * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); - * $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); - */ - function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') { + include_once(ADODB_DIR.'/adodb-lib.inc.php'); + } + return _adodb_getinsertsql($this, $rs, $arrFields, $force); + } + + + /** + * Update a BLOB column, given a where clause. + * + * There are more sophisticated blob handling functions that we could have + * implemented, but all require a very complex API. Instead we have chosen + * something that is extremely simple to understand and use. + * + * Sample usage: + * - update a BLOB in field table.blob_col with value $blobValue, for a + * record having primary key id=1 + * $conn->updateBlob('table', 'blob_col', $blobValue, 'id=1'); + * - insert example: + * $conn->execute('INSERT INTO table (id, blob_col) VALUES (1, null)'); + * $conn->updateBlob('table', 'blob_col', $blobValue, 'id=1'); + * + * @param string $table + * @param string $column + * @param string $val Filename containing blob data + * @param mixed $where {@see updateBlob()} + * @param string $blobtype supports 'BLOB' (default) and 'CLOB' + * + * @return bool success + */ + function updateBlob($table, $column, $val, $where, $blobtype='BLOB') { return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false; } /** - * Usage: - * UpdateBlob('TABLE', 'COLUMN', '/path/to/file', 'ID=1'); - * - * $blobtype supports 'BLOB' and 'CLOB' - * - * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); - * $conn->UpdateBlob('blobtable','blobcol',$blobpath,'id=1'); - */ - function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB') { + * Update a BLOB from a file. + * + * Usage example: + * $conn->updateBlobFile('table', 'blob_col', '/path/to/file', 'id=1'); + * + * @param string $table + * @param string $column + * @param string $path Filename containing blob data + * @param mixed $where {@see updateBlob()} + * @param string $blobtype supports 'BLOB' and 'CLOB' + * + * @return bool success + */ + function updateBlobFile($table, $column, $path, $where, $blobtype='BLOB') { $fd = fopen($path,'rb'); if ($fd === false) { return false; @@ -2262,11 +2754,26 @@ function BlobEncode($blob) { return $blob; } - function GetCharSet() { + /** + * Retrieve the client connection's current character set. + * + * @return string|false The character set, or false if it can't be determined. + */ + function getCharSet() { return $this->charSet; } - function SetCharSet($charset) { + /** + * Sets the client-side character set. + * + * This is only supported for some databases. + * @see https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:setcharset + * + * @param string $charset The character set to switch to. + * + * @return bool True if the character set was changed successfully, false otherwise. + */ + function setCharSet($charset) { $this->charSet = $charset; return true; } @@ -2293,12 +2800,12 @@ function LogSQL($enable=true) { } /** - * Usage: - * UpdateClob('TABLE', 'COLUMN', $var, 'ID=1', 'CLOB'); - * - * $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)'); - * $conn->UpdateClob('clobtable','clobcol',$clob,'id=1'); - */ + * Usage: + * UpdateClob('TABLE', 'COLUMN', $var, 'ID=1', 'CLOB'); + * + * $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)'); + * $conn->UpdateClob('clobtable','clobcol',$clob,'id=1'); + */ function UpdateClob($table,$column,$val,$where) { return $this->UpdateBlob($table,$column,$val,$where,'CLOB'); } @@ -2317,9 +2824,9 @@ function MetaType($t,$len=-1,$fieldobj=false) { /** - * Change the SQL connection locale to a specified locale. - * This is used to get the date formats written depending on the client locale. - */ + * Change the SQL connection locale to a specified locale. + * This is used to get the date formats written depending on the client locale. + */ function SetDateLocale($locale = 'En') { $this->locale = $locale; switch (strtoupper($locale)) @@ -2392,14 +2899,17 @@ function GetActiveRecords($table,$where=false,$bindarr=false,$primkeyArr=false) */ function Close() { $rez = $this->_close(); + $this->_queryID = false; $this->_connectionID = false; return $rez; } /** - * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans(). + * Begin a Transaction. * - * @return true if succeeded or false if database does not support transactions + * Must be followed by CommitTrans() or RollbackTrans(). + * + * @return bool true if succeeded or false if database does not support transactions */ function BeginTrans() { if ($this->debug) { @@ -2459,11 +2969,14 @@ function MetaTransaction($mode,$db) { } /** - * If database does not support transactions, always return true as data always commited + * Commits a transaction. + * + * If database does not support transactions, return true as data is + * always committed. * - * @param $ok set to false to rollback transaction, true to commit + * @param bool $ok True to commit, false to rollback the transaction. * - * @return true/false. + * @return bool true if successful */ function CommitTrans($ok=true) { return true; @@ -2471,9 +2984,12 @@ function CommitTrans($ok=true) { /** - * If database does not support transactions, rollbacks always fail, so return false + * Rolls back a transaction. * - * @return true/false. + * If database does not support transactions, return false as rollbacks + * always fail. + * + * @return bool true if successful */ function RollbackTrans() { return false; @@ -2484,7 +3000,7 @@ function RollbackTrans() { * return the databases that the driver can connect to. * Some databases will return an empty array. * - * @return an array of database names. + * @return array|bool an array of database names. */ function MetaDatabases() { global $ADODB_FETCH_MODE; @@ -2708,14 +3224,16 @@ function MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for } /** + * Concatenate strings. + * * Different SQL databases used different methods to combine strings together. * This function provides a wrapper. * - * param s variable number of string parameters - * * Usage: $db->Concat($str1,$str2); * - * @return concatenated string + * @param string $s Variable number of string parameters + * + * @return string concatenated string */ function Concat() { $arr = func_get_args(); @@ -2726,9 +3244,9 @@ function Concat() { /** * Converts a date "d" to a string that the database can understand. * - * @param d a date in Unix date time format. + * @param mixed $d a date in Unix date time format. * - * @return date string in database date format + * @return string date string in database date format */ function DBDate($d, $isfld=false) { if (empty($d) && $d !== 0) { @@ -2780,9 +3298,9 @@ function BindTimeStamp($d) { /** * Converts a timestamp "ts" to a string that the database can understand. * - * @param ts a timestamp in Unix date time format. + * @param int|object $ts A timestamp in Unix date time format. * - * @return timestamp string in database timestamp format + * @return string $timestamp string in database timestamp format */ function DBTimeStamp($ts,$isfld=false) { if (empty($ts) && $ts !== 0) { @@ -2813,9 +3331,9 @@ function DBTimeStamp($ts,$isfld=false) { /** * Also in ADORecordSet. - * @param $v is a date string in YYYY-MM-DD format + * @param mixed $v is a date string in YYYY-MM-DD format * - * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format + * @return int|false Date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format */ static function UnixDate($v) { if (is_object($v)) { @@ -2842,9 +3360,9 @@ static function UnixDate($v) { /** * Also in ADORecordSet. - * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format + * @param string|object $v is a timestamp string in YYYY-MM-DD HH-NN-SS format * - * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format + * @return int|false Date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format */ static function UnixTimeStamp($v) { if (is_object($v)) { @@ -2869,14 +3387,15 @@ static function UnixTimeStamp($v) { } /** - * Also in ADORecordSet. - * * Format database date based on user defined format. * - * @param v is the character date in YYYY-MM-DD format, returned by database - * @param fmt is the format to apply to it, using date() + * Also in ADORecordSet. + * + * @param mixed $v Date in YYYY-MM-DD format, returned by database + * @param string $fmt Format to apply, using date() + * @param bool $gmt * - * @return a date formated as user desires + * @return string Formatted date */ function UserDate($v,$fmt='Y-m-d',$gmt=false) { $tt = $this->UnixDate($v); @@ -2895,11 +3414,13 @@ function UserDate($v,$fmt='Y-m-d',$gmt=false) { } /** + * Format timestamp based on user defined format. * - * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format - * @param fmt is the format to apply to it, using date() + * @param mixed $v Date in YYYY-MM-DD hh:mm:ss format + * @param string $fmt Format to apply, using date() + * @param bool $gmt * - * @return a timestamp formated as user desires + * @return string Formatted timestamp */ function UserTimeStamp($v,$fmt='Y-m-d H:i:s',$gmt=false) { if (!isset($v)) { @@ -2920,123 +3441,237 @@ function UserTimeStamp($v,$fmt='Y-m-d H:i:s',$gmt=false) { return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt); } + /** + * Alias for addQ() + * @param string $s + * @param bool [$magic_quotes] + * @return mixed + * + * @deprecated 5.21.0 + * @noinspection PhpUnusedParameterInspection + */ function escape($s,$magic_quotes=false) { - return $this->addq($s,$magic_quotes); + return $this->addQ($s); } /** - * Quotes a string, without prefixing nor appending quotes. - */ - function addq($s,$magic_quotes=false) { - if (!$magic_quotes) { - if ($this->replaceQuote[0] == '\\') { - // only since php 4.0.5 - $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); - //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s)); - } - return str_replace("'",$this->replaceQuote,$s); - } - - // undo magic quotes for " - $s = str_replace('\\"','"',$s); - - if ($this->replaceQuote == "\\'" || ini_get('magic_quotes_sybase')) { - // ' already quoted, no need to change anything - return $s; - } else { - // change \' to '' for sybase/mssql - $s = str_replace('\\\\','\\',$s); - return str_replace("\\'",$this->replaceQuote,$s); + * Quotes a string, without prefixing nor appending quotes. + * + * @param string $s The string to quote + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * + * @return string Quoted string + * + * @noinspection PhpUnusedParameterInspection + */ + function addQ($s, $magic_quotes=false) { + if ($this->replaceQuote[0] == '\\') { + $s = str_replace( + array('\\', "\0"), + array('\\\\', "\\\0"), + $s + ); } + return str_replace("'", $this->replaceQuote, $s); } /** - * Correctly quotes a string so that all strings are escaped. We prefix and append - * to the string single-quotes. - * An example is $db->qstr("Don't bother",magic_quotes_runtime()); + * Correctly quotes a string so that all strings are escaped. + * We prefix and append to the string single-quotes. + * An example is $db->qstr("Don't bother"); + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr + * + * @param string $s The string to quote + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. * - * @param s the string to quote - * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). - * This undoes the stupidity of magic quotes for GPC. + * @return string Quoted string to be sent back to database * - * @return quoted string to be sent back to database + * @noinspection PhpUnusedParameterInspection */ - function qstr($s,$magic_quotes=false) { - if (!$magic_quotes) { - if ($this->replaceQuote[0] == '\\'){ - // only since php 4.0.5 - $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); - //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s)); - } - return "'".str_replace("'",$this->replaceQuote,$s)."'"; - } + function qStr($s, $magic_quotes=false) { + return "'" . $this->addQ($s) . "'"; + } - // undo magic quotes for " - $s = str_replace('\\"','"',$s); - if ($this->replaceQuote == "\\'" || ini_get('magic_quotes_sybase')) { - // ' already quoted, no need to change anything - return "'$s'"; - } else { - // change \' to '' for sybase/mssql - $s = str_replace('\\\\','\\',$s); - return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; - } - } - - - /** - * Will select the supplied $page number from a recordset, given that it is paginated in pages of - * $nrows rows per page. It also saves two boolean values saying if the given page is the first - * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination. - * - * See docs-adodb.htm#ex8 for an example of usage. - * - * @param sql - * @param nrows is the number of rows per page to get - * @param page is the page number to get (1-based) - * @param [inputarr] array of bind variables - * @param [secs2cache] is a private parameter only used by jlim - * @return the recordset ($rs->databaseType == 'array') - * - * NOTE: phpLens uses a different algorithm and does not use PageExecute(). - * - */ + /** + * Will select the supplied $page number from a recordset, given that it is paginated in pages of + * $nrows rows per page. It also saves two boolean values saying if the given page is the first + * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination. + * + * See docs-adodb.htm#ex8 for an example of usage. + * NOTE: phpLens uses a different algorithm and does not use PageExecute(). + * + * @param string $sql + * @param int $nrows Number of rows per page to get + * @param int $page Page number to get (1-based) + * @param mixed[]|bool $inputarr Array of bind variables + * @param int $secs2cache Private parameter only used by jlim + * + * @return mixed the recordset ($rs->databaseType == 'array') + */ function PageExecute($sql, $nrows, $page, $inputarr=false, $secs2cache=0) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } if ($this->pageExecuteCountRows) { $rs = _adodb_pageexecute_all_rows($this, $sql, $nrows, $page, $inputarr, $secs2cache); } else { $rs = _adodb_pageexecute_no_last_page($this, $sql, $nrows, $page, $inputarr, $secs2cache); } - return $rs; - } + return $rs; + } + + + /** + * Will select the supplied $page number from a recordset, given that it is paginated in pages of + * $nrows rows per page. It also saves two boolean values saying if the given page is the first + * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination. + * + * @param int $secs2cache seconds to cache data, set to 0 to force query + * @param string $sql + * @param int $nrows is the number of rows per page to get + * @param int $page is the page number to get (1-based) + * @param mixed[]|bool $inputarr array of bind variables + * @return mixed the recordset ($rs->databaseType == 'array') + */ + function CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false) { + /*switch($this->dataProvider) { + case 'postgres': + case 'mysql': + break; + default: $secs2cache = 0; break; + }*/ + return $this->PageExecute($sql,$nrows,$page,$inputarr,$secs2cache); + } + + /** + * Returns the maximum size of a MetaType C field. If the method + * is not defined in the driver returns ADODB_STRINGMAX_NOTSET + * + * @return int + */ + function charMax() { + return ADODB_STRINGMAX_NOTSET; + } + + /** + * Returns the maximum size of a MetaType X field. If the method + * is not defined in the driver returns ADODB_STRINGMAX_NOTSET + * + * @return int + */ + function textMax() { + return ADODB_STRINGMAX_NOTSET; + } + + /** + * Returns a substring of a varchar type field + * + * Some databases have variations of the parameters, which is why + * we have an ADOdb function for it + * + * @param string $fld The field to sub-string + * @param int $start The start point + * @param int $length An optional length + * + * @return string The SQL text + */ + function substr($fld,$start,$length=0) { + $text = "{$this->substr}($fld,$start"; + if ($length > 0) + $text .= ",$length"; + $text .= ')'; + return $text; + } + + /* + * Formats the date into Month only format MM with leading zeroes + * + * @param string $fld The name of the date to format + * + * @return string The SQL text + */ + function month($fld) { + return $this->sqlDate('m',$fld); + } + + /* + * Formats the date into Day only format DD with leading zeroes + * + * @param string $fld The name of the date to format + * @return string The SQL text + */ + function day($fld) { + return $this->sqlDate('d',$fld); + } + + /* + * Formats the date into year only format YYYY + * + * @param string $fld The name of the date to format + * + * @return string The SQL text + */ + function year($fld) { + return $this->sqlDate('Y',$fld); + } + + /** + * Get the last error recorded by PHP and clear the message. + * + * By clearing the message, it becomes possible to detect whether a new error + * has occurred, even when it is the same error as before being repeated. + * + * @return mixed[]|null Array if an error has previously occurred. Null otherwise. + */ + protected function resetLastError() { + $error = error_get_last(); + + if (is_array($error)) { + $error['message'] = ''; + } + + return $error; + } + + /** + * Compare a previously stored error message with the last error recorded by PHP + * to determine whether a new error has occurred. + * + * @param mixed[]|null $old Optional. Previously stored return value of error_get_last(). + * + * @return string The error message if a new error has occurred + * or an empty string if no (new) errors have occurred.. + */ + protected function getChangedErrorMsg($old = null) { + $new = error_get_last(); + + if (is_null($new)) { + // No error has occurred yet at all. + return ''; + } + + if (is_null($old)) { + // First error recorded. + return $new['message']; + } + $changed = false; + foreach($new as $key => $value) { + if ($new[$key] !== $old[$key]) { + $changed = true; + break; + } + } - /** - * Will select the supplied $page number from a recordset, given that it is paginated in pages of - * $nrows rows per page. It also saves two boolean values saying if the given page is the first - * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination. - * - * @param secs2cache seconds to cache data, set to 0 to force query - * @param sql - * @param nrows is the number of rows per page to get - * @param page is the page number to get (1-based) - * @param [inputarr] array of bind variables - * @return the recordset ($rs->databaseType == 'array') - */ - function CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false) { - /*switch($this->dataProvider) { - case 'postgres': - case 'mysql': - break; - default: $secs2cache = 0; break; - }*/ - $rs = $this->PageExecute($sql,$nrows,$page,$inputarr,$secs2cache); - return $rs; + if ($changed === true) { + return $new['message']; + } + + return ''; } } // end class ADOConnection @@ -3048,15 +3683,14 @@ function CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false) { //============================================================================================== /** - * Internal placeholder for record objects. Used by ADORecordSet->FetchObj(). - */ + * Internal placeholder for record objects. Used by ADORecordSet->FetchObj(). + */ class ADOFetchObj { }; - //============================================================================================== - // CLASS ADORecordSet_empty - //============================================================================================== - + /** + * Class ADODB_Iterator_empty + */ class ADODB_Iterator_empty implements Iterator { private $rs; @@ -3065,26 +3699,32 @@ function __construct($rs) { $this->rs = $rs; } + #[\ReturnTypeWillChange] function rewind() {} + #[\ReturnTypeWillChange] function valid() { return !$this->rs->EOF; } + #[\ReturnTypeWillChange] function key() { return false; } + #[\ReturnTypeWillChange] function current() { return false; } + #[\ReturnTypeWillChange] function next() {} function __call($func, $params) { return call_user_func_array(array($this->rs, $func), $params); } + #[\ReturnTypeWillChange] function hasMore() { return false; } @@ -3093,14 +3733,15 @@ function hasMore() { /** - * Lightweight recordset when there are no records to be returned - */ + * Lightweight recordset when there are no records to be returned + */ class ADORecordSet_empty implements IteratorAggregate { var $dataProvider = 'empty'; var $databaseType = false; var $EOF = true; var $_numOfRows = 0; + /** @var bool|array */ var $fields = false; var $connection = false; @@ -3130,6 +3771,7 @@ function FieldCount() { function Init() {} + #[\ReturnTypeWillChange] function getIterator() { return new ADODB_Iterator_empty($this); } @@ -3175,13 +3817,12 @@ function NumCols() { // DATE AND TIME FUNCTIONS //============================================================================================== if (!defined('ADODB_DATE_VERSION')) { - include(ADODB_DIR.'/adodb-time.inc.php'); + include_once(ADODB_DIR.'/adodb-time.inc.php'); } - //============================================================================================== - // CLASS ADORecordSet - //============================================================================================== - + /** + * Class ADODB_Iterator + */ class ADODB_Iterator implements Iterator { private $rs; @@ -3190,22 +3831,27 @@ function __construct($rs) { $this->rs = $rs; } + #[\ReturnTypeWillChange] function rewind() { $this->rs->MoveFirst(); } + #[\ReturnTypeWillChange] function valid() { return !$this->rs->EOF; } + #[\ReturnTypeWillChange] function key() { return $this->rs->_currentRow; } + #[\ReturnTypeWillChange] function current() { return $this->rs->fields; } + #[\ReturnTypeWillChange] function next() { $this->rs->MoveNext(); } @@ -3221,18 +3867,20 @@ function hasMore() { } - /** - * RecordSet class that represents the dataset returned by the database. - * To keep memory overhead low, this class holds only the current row in memory. - * No prefetching of data is done, so the RecordCount() can return -1 ( which - * means recordcount not known). - */ - class ADORecordSet implements IteratorAggregate { +/** + * RecordSet class that represents the dataset returned by the database. + * + * To keep memory overhead low, this class holds only the current row in memory. + * No prefetching of data is done, so the RecordCount() can return -1 (which + * means recordcount not known). + */ +class ADORecordSet implements IteratorAggregate { /** * public variables */ var $dataProvider = "native"; + /** @var bool|array */ var $fields = false; /// holds the current row data var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob /// in other words, we use a text area for editing. @@ -3247,14 +3895,15 @@ class ADORecordSet implements IteratorAggregate { var $bind = false; /// used by Fields() to hold array - should be private? var $fetchMode; /// default fetch mode - var $connection = false; /// the parent connection - + /** @var ADOConnection The parent connection */ + var $connection = false; /** * private variables */ var $_numOfRows = -1; /** number of rows, or -1 */ var $_numOfFields = -1; /** number of fields in recordset */ - var $_queryID = -1; /** This variable keeps the result link identifier. */ + /** @var resource result link identifier */ + var $_queryID = -1; var $_currentRow = -1; /** This variable keeps the current row in the Recordset. */ var $_closed = false; /** has recordset been closed */ var $_inited = false; /** Init() should only be called once */ @@ -3268,13 +3917,23 @@ class ADORecordSet implements IteratorAggregate { var $_maxRecordCount = 0; var $datetime = false; + public $customActualTypes; + public $customMetaTypes; + + + /** + * @var ADOFieldObject[] Field metadata cache + * @see fieldTypesArray() + */ + protected $fieldObjectsCache; + /** * Constructor * - * @param queryID this is the queryID returned by ADOConnection->_query() - * + * @param resource|int $queryID Query ID returned by ADOConnection->_query() + * @param int|bool $mode The ADODB_FETCH_MODE value */ - function __construct($queryID) { + function __construct($queryID,$mode=false) { $this->_queryID = $queryID; } @@ -3282,6 +3941,7 @@ function __destruct() { $this->Close(); } + #[\ReturnTypeWillChange] function getIterator() { return new ADODB_Iterator($this); } @@ -3298,7 +3958,7 @@ function Init() { } $this->_inited = true; if ($this->_queryID) { - @$this->_initrs(); + @$this->_initRS(); } else { $this->_numOfRows = 0; $this->_numOfFields = 0; @@ -3313,78 +3973,140 @@ function Init() { } } + /** + * Recordset initialization stub + */ + protected function _initRS() {} + + /** + * Row fetch stub + * @return bool + */ + protected function _fetch() {} /** - * Generate a SELECT tag string from a recordset, and return the string. - * If the recordset has 2 cols, we treat the 1st col as the containing - * the text to display to the user, and 2nd col as the return value. Default - * strings are compared with the FIRST column. + * Generate a SELECT tag from a recordset, and return the HTML markup. * - * @param name name of SELECT tag - * @param [defstr] the value to hilite. Use an array for multiple hilites for listbox. - * @param [blank1stItem] true to leave the 1st item in list empty - * @param [multiple] true for listbox, false for popup - * @param [size] #rows to show for listbox. not used by popup - * @param [selectAttr] additional attributes to defined for SELECT tag. - * useful for holding javascript onChange='...' handlers. - & @param [compareFields0] when we have 2 cols in recordset, we compare the defstr with - * column 0 (1st col) if this is true. This is not documented. + * If the recordset has 2 columns, we treat the first one as the text to + * display to the user, and the second as the return value. Extra columns + * are discarded. * - * @return HTML + * @param string $name Name of SELECT tag + * @param string|array $defstr The value to highlight. Use an array for multiple highlight values. + * @param bool|string $blank1stItem True to create an empty item (default), False not to add one; + * 'string' to set its label and 'value:string' to assign a value to it. + * @param bool $multiple True for multi-select list + * @param int $size Number of rows to show (applies to multi-select box only) + * @param string $selectAttr Additional attributes to defined for SELECT tag, + * useful for holding javascript onChange='...' handlers, CSS class, etc. + * @param bool $compareFirstCol When true (default), $defstr is compared against the value (column 2), + * while false will compare against the description (column 1). * - * changes by glen.davies@cce.ac.nz to support multiple hilited items + * @return string HTML */ - function GetMenu($name,$defstr='',$blank1stItem=true,$multiple=false, - $size=0, $selectAttr='',$compareFields0=true) + function getMenu($name, $defstr = '', $blank1stItem = true, $multiple = false, + $size = 0, $selectAttr = '', $compareFirstCol = true) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } - return _adodb_getmenu($this, $name,$defstr,$blank1stItem,$multiple, - $size, $selectAttr,$compareFields0); + return _adodb_getmenu($this, $name, $defstr, $blank1stItem, $multiple, + $size, $selectAttr, $compareFirstCol); } - - /** - * Generate a SELECT tag string from a recordset, and return the string. - * If the recordset has 2 cols, we treat the 1st col as the containing - * the text to display to the user, and 2nd col as the return value. Default - * strings are compared with the SECOND column. + * Generate a SELECT tag with groups from a recordset, and return the HTML markup. + * + * The recordset must have 3 columns and be ordered by the 3rd column. The + * first column contains the text to display to the user, the second is the + * return value and the third is the option group. Extra columns are discarded. + * Default strings are compared with the SECOND column. * + * @param string $name Name of SELECT tag + * @param string|array $defstr The value to highlight. Use an array for multiple highlight values. + * @param bool|string $blank1stItem True to create an empty item (default), False not to add one; + * 'string' to set its label and 'value:string' to assign a value to it. + * @param bool $multiple True for multi-select list + * @param int $size Number of rows to show (applies to multi-select box only) + * @param string $selectAttr Additional attributes to defined for SELECT tag, + * useful for holding javascript onChange='...' handlers, CSS class, etc. + * @param bool $compareFirstCol When true (default), $defstr is compared against the value (column 2), + * while false will compare against the description (column 1). + * + * @return string HTML */ - function GetMenu2($name,$defstr='',$blank1stItem=true,$multiple=false,$size=0, $selectAttr='') { - return $this->GetMenu($name,$defstr,$blank1stItem,$multiple, - $size, $selectAttr,false); - } - - /* - Grouped Menu - */ - function GetMenu3($name,$defstr='',$blank1stItem=true,$multiple=false, - $size=0, $selectAttr='') + function getMenuGrouped($name, $defstr = '', $blank1stItem = true, $multiple = false, + $size = 0, $selectAttr = '', $compareFirstCol = true) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } - return _adodb_getmenu_gp($this, $name,$defstr,$blank1stItem,$multiple, + return _adodb_getmenu_gp($this, $name, $defstr, $blank1stItem, $multiple, + $size, $selectAttr, $compareFirstCol); + } + + /** + * Generate a SELECT tag from a recordset, and return the HTML markup. + * + * Same as GetMenu(), except that default strings are compared with the + * FIRST column (the description). + * + * @param string $name Name of SELECT tag + * @param string|array $defstr The value to highlight. Use an array for multiple highlight values. + * @param bool|string $blank1stItem True to create an empty item (default), False not to add one; + * 'string' to set its label and 'value:string' to assign a value to it. + * @param bool $multiple True for multi-select list + * @param int $size Number of rows to show (applies to multi-select box only) + * @param string $selectAttr Additional attributes to defined for SELECT tag, + * useful for holding javascript onChange='...' handlers, CSS class, etc. + * + * @return string HTML + * + * @deprecated 5.21.0 Use getMenu() with $compareFirstCol = false instead. + */ + function getMenu2($name, $defstr = '', $blank1stItem = true, $multiple = false, + $size = 0, $selectAttr = '') + { + return $this->getMenu($name, $defstr, $blank1stItem, $multiple, $size, $selectAttr,false); } + /** + * Generate a SELECT tag with groups from a recordset, and return the HTML markup. + * + * Same as GetMenuGrouped(), except that default strings are compared with the + * FIRST column (the description). + * + * @param string $name Name of SELECT tag + * @param string|array $defstr The value to highlight. Use an array for multiple highlight values. + * @param bool|string $blank1stItem True to create an empty item (default), False not to add one; + * 'string' to set its label and 'value:string' to assign a value to it. + * @param bool $multiple True for multi-select list + * @param int $size Number of rows to show (applies to multi-select box only) + * @param string $selectAttr Additional attributes to defined for SELECT tag, + * useful for holding javascript onChange='...' handlers, CSS class, etc. + * + * @return string HTML + * + * @deprecated 5.21.0 Use getMenuGrouped() with $compareFirstCol = false instead. + */ + function getMenu3($name, $defstr = '', $blank1stItem = true, $multiple = false, + $size = 0, $selectAttr = '') + { + return $this->getMenuGrouped($name, $defstr, $blank1stItem, $multiple, + $size, $selectAttr, false); + } + /** * return recordset as a 2-dimensional array. * - * @param [nRows] is the number of rows to return. -1 means every row. + * @param int $nRows Number of rows to return. -1 means every row. * - * @return an array indexed by the rows (0-based) from the recordset + * @return array indexed by the rows (0-based) from the recordset */ function GetArray($nRows = -1) { - global $ADODB_EXTENSION; if ($ADODB_EXTENSION) { - $results = adodb_getall($this,$nRows); - return $results; - } $results = array(); $cnt = 0; while (!$this->EOF && $nRows != $cnt) { @@ -3396,31 +4118,33 @@ function GetArray($nRows = -1) { } function GetAll($nRows = -1) { - $arr = $this->GetArray($nRows); - return $arr; + return $this->GetArray($nRows); } - /* - * Some databases allow multiple recordsets to be returned. This function - * will return true if there is a next recordset, or false if no more. - */ + /** + * Checks if there is another available recordset. + * + * Some databases allow multiple recordsets to be returned. + * + * @return boolean true if there is a next recordset, or false if no more + */ function NextRecordSet() { return false; } /** - * return recordset as a 2-dimensional array. + * Return recordset as a 2-dimensional array. + * * Helper function for ADOConnection->SelectLimit() * - * @param offset is the row to start calculations from (1-based) - * @param [nrows] is the number of rows to return + * @param int $nrows Number of rows to return + * @param int $offset Starting row (1-based) * - * @return an array indexed by the rows (0-based) from the recordset + * @return array an array indexed by the rows (0-based) from the recordset */ - function GetArrayLimit($nrows,$offset=-1) { + function getArrayLimit($nrows, $offset=-1) { if ($offset <= 0) { - $arr = $this->GetArray($nrows); - return $arr; + return $this->GetArray($nrows); } $this->Move($offset); @@ -3439,139 +4163,165 @@ function GetArrayLimit($nrows,$offset=-1) { /** * Synonym for GetArray() for compatibility with ADO. * - * @param [nRows] is the number of rows to return. -1 means every row. + * @param int $nRows Number of rows to return. -1 means every row. * - * @return an array indexed by the rows (0-based) from the recordset + * @return array an array indexed by the rows (0-based) from the recordset */ - function GetRows($nRows = -1) { - $arr = $this->GetArray($nRows); - return $arr; + function getRows($nRows = -1) { + return $this->GetArray($nRows); } /** - * return whole recordset as a 2-dimensional associative array if there are more than 2 columns. - * The first column is treated as the key and is not included in the array. - * If there is only 2 columns, it will return a 1 dimensional array of key-value pairs unless - * $force_array == true. + * return whole recordset as a 2-dimensional associative array if + * there are more than 2 columns. The first column is treated as the + * key and is not included in the array. If there is only 2 columns, + * it will return a 1 dimensional array of key-value pairs unless + * $force_array == true. This recordset method is currently part of + * the API, but may not be in later versions of ADOdb. By preference, use + * ADOconnnection::getAssoc() + * + * @param bool $force_array (optional) Has only meaning if we have 2 data + * columns. If false, a 1 dimensional + * array is returned, otherwise a 2 dimensional + * array is returned. If this sounds confusing, + * read the source. * - * @param [force_array] has only meaning if we have 2 data columns. If false, a 1 dimensional - * array is returned, otherwise a 2 dimensional array is returned. If this sounds confusing, - * read the source. + * @param bool $first2cols (optional) Means if there are more than + * 2 cols, ignore the remaining cols and + * instead of returning + * array[col0] => array(remaining cols), + * return array[col0] => col1 * - * @param [first2cols] means if there are more than 2 cols, ignore the remaining cols and - * instead of returning array[col0] => array(remaining cols), return array[col0] => col1 + * @return mixed[]|false * - * @return an associative array indexed by the first column of the array, - * or false if the data has less than 2 cols. */ - function GetAssoc($force_array = false, $first2cols = false) { - global $ADODB_EXTENSION; - - $cols = $this->_numOfFields; - if ($cols < 2) { - return false; - } + function getAssoc($force_array = false, $first2cols = false) + { + /* + * Insufficient rows to show data + */ + if ($this->_numOfFields < 2) + return; - // Empty recordset + /* + * Empty recordset + */ if (!$this->fields) { return array(); } - // Determine whether the array is associative or 0-based numeric - $numIndex = array_keys($this->fields) == range(0, count($this->fields) - 1); + /* + * The number of fields is half the actual returned in BOTH mode + */ + $numberOfFields = $this->_numOfFields; - $results = array(); + /* + * Get the fetch mode when the call was executed, this may be + * different than ADODB_FETCH_MODE + */ + $fetchMode = $this->connection->fetchMode; + if ($fetchMode == ADODB_FETCH_BOTH) { + /* + * If we are using BOTH, we present the data as if it + * was in ASSOC mode. This could be enhanced by adding + * a BOTH_ASSOC_MODE class property + * We build a template of numeric keys. you could improve the + * speed by caching this, indexed by number of keys + */ + $testKeys = array_fill(0,$numberOfFields,0); + } - if (!$first2cols && ($cols > 2 || $force_array)) { - if ($ADODB_EXTENSION) { - if ($numIndex) { - while (!$this->EOF) { - $results[trim($this->fields[0])] = array_slice($this->fields, 1); - adodb_movenext($this); - } - } else { - while (!$this->EOF) { - // Fix for array_slice re-numbering numeric associative keys - $keys = array_slice(array_keys($this->fields), 1); - $sliced_array = array(); + $showArrayMethod = 0; - foreach($keys as $key) { - $sliced_array[$key] = $this->fields[$key]; - } + if ($numberOfFields == 2) + /* + * Key is always value of first element + * Value is always value of second element + */ + $showArrayMethod = 1; - $results[trim(reset($this->fields))] = $sliced_array; - adodb_movenext($this); - } - } - } else { - if ($numIndex) { - while (!$this->EOF) { - $results[trim($this->fields[0])] = array_slice($this->fields, 1); - $this->MoveNext(); - } - } else { - while (!$this->EOF) { - // Fix for array_slice re-numbering numeric associative keys - $keys = array_slice(array_keys($this->fields), 1); - $sliced_array = array(); + if ($force_array) + $showArrayMethod = 0; - foreach($keys as $key) { - $sliced_array[$key] = $this->fields[$key]; - } + if ($first2cols) + $showArrayMethod = 1; - $results[trim(reset($this->fields))] = $sliced_array; - $this->MoveNext(); - } - } + $results = array(); + + while (!$this->EOF){ + + $myFields = $this->fields; + + if ($fetchMode == ADODB_FETCH_BOTH) { + /* + * extract the associative keys + */ + $myFields = array_diff_key($myFields,$testKeys); } - } else { - if ($ADODB_EXTENSION) { - // return scalar values - if ($numIndex) { - while (!$this->EOF) { - // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string - $results[trim(($this->fields[0]))] = $this->fields[1]; - adodb_movenext($this); - } - } else { - while (!$this->EOF) { - // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string - $v1 = trim(reset($this->fields)); - $v2 = ''.next($this->fields); - $results[$v1] = $v2; - adodb_movenext($this); - } - } - } else { - if ($numIndex) { - while (!$this->EOF) { - // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string - $results[trim(($this->fields[0]))] = $this->fields[1]; - $this->MoveNext(); - } - } else { - while (!$this->EOF) { - // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string - $v1 = trim(reset($this->fields)); - $v2 = ''.next($this->fields); - $results[$v1] = $v2; - $this->MoveNext(); - } + + /* + * key is value of first element, rest is data, + * The key is not case processed + */ + $key = array_shift($myFields); + + switch ($showArrayMethod) { + case 0: + + if ($fetchMode == ADODB_FETCH_ASSOC + || $fetchMode == ADODB_FETCH_BOTH) + { + /* + * The driver should have already handled the key + * casing, but in case it did not. We will check and force + * this in later versions of ADOdb + */ + if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_UPPER) + $myFields = array_change_key_case($myFields,CASE_UPPER); + + elseif (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) + $myFields = array_change_key_case($myFields,CASE_LOWER); + + /* + * We have already shifted the key off + * the front, so the rest is the value + */ + $results[$key] = $myFields; + } + else + /* + * I want the values in a numeric array, + * nicely re-indexed from zero + */ + $results[$key] = array_values($myFields); + break; + + case 1: + + /* + * Don't care how long the array is, + * I just want value of second column, and it doesn't + * matter whether the array is associative or numeric + */ + $results[$key] = array_shift($myFields); + break; } - } - $ref = $results; # workaround accelerator incompat with PHP 4.4 :( - return $ref; + $this->MoveNext(); + } + /* + * Done + */ + return $results; } - /** * - * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format - * @param fmt is the format to apply to it, using date() + * @param mixed $v is the character timestamp in YYYY-MM-DD hh:mm:ss format + * @param string [$fmt] is the format to apply to it, using date() * - * @return a timestamp formated as user desires + * @return string a timestamp formated as user desires */ function UserTimeStamp($v,$fmt='Y-m-d H:i:s') { if (is_numeric($v) && strlen($v)<14) { @@ -3590,10 +4340,10 @@ function UserTimeStamp($v,$fmt='Y-m-d H:i:s') { /** - * @param v is the character date in YYYY-MM-DD format, returned by database - * @param fmt is the format to apply to it, using date() + * @param mixed $v is the character date in YYYY-MM-DD format, returned by database + * @param string $fmt is the format to apply to it, using date() * - * @return a date formated as user desires + * @return string a date formatted as user desires */ function UserDate($v,$fmt='Y-m-d') { $tt = $this->UnixDate($v); @@ -3610,9 +4360,9 @@ function UserDate($v,$fmt='Y-m-d') { /** - * @param $v is a date string in YYYY-MM-DD format + * @param mixed $v is a date string in YYYY-MM-DD format * - * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format + * @return string date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format */ static function UnixDate($v) { return ADOConnection::UnixDate($v); @@ -3620,9 +4370,9 @@ static function UnixDate($v) { /** - * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format + * @param string|object $v is a timestamp string in YYYY-MM-DD HH-NN-SS format * - * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format + * @return mixed date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format */ static function UnixTimeStamp($v) { return ADOConnection::UnixTimeStamp($v); @@ -3630,34 +4380,38 @@ static function UnixTimeStamp($v) { /** - * PEAR DB Compat - do not use internally - */ + * PEAR DB Compat - do not use internally + */ function Free() { return $this->Close(); } /** - * PEAR DB compat, number of rows - */ + * PEAR DB compat, number of rows + * + * @return int + */ function NumRows() { return $this->_numOfRows; } /** - * PEAR DB compat, number of cols - */ + * PEAR DB compat, number of cols + * + * @return int + */ function NumCols() { return $this->_numOfFields; } /** - * Fetch a row, returning false if no more rows. - * This is PEAR DB compat mode. - * - * @return false or array containing the current record - */ + * Fetch a row, returning false if no more rows. + * This is PEAR DB compat mode. + * + * @return mixed[]|false false or array containing the current record + */ function FetchRow() { if ($this->EOF) { return false; @@ -3672,11 +4426,13 @@ function FetchRow() { /** - * Fetch a row, returning PEAR_Error if no more rows. - * This is PEAR DB compat mode. - * - * @return DB_OK or error object - */ + * Fetch a row, returning PEAR_Error if no more rows. + * This is PEAR DB compat mode. + * + * @param mixed[]|false $arr + * + * @return mixed DB_OK or error object + */ function FetchInto(&$arr) { if ($this->EOF) { return (defined('PEAR_ERROR_RETURN')) ? new PEAR_Error('EOF',-1): false; @@ -3690,7 +4446,7 @@ function FetchInto(&$arr) { /** * Move to the first row in the recordset. Many databases do NOT support this. * - * @return true or false + * @return bool true or false */ function MoveFirst() { if ($this->_currentRow == 0) { @@ -3703,7 +4459,7 @@ function MoveFirst() { /** * Move to the last row in the recordset. * - * @return true or false + * @return bool true or false */ function MoveLast() { if ($this->_numOfRows >= 0) { @@ -3725,7 +4481,7 @@ function MoveLast() { /** * Move to next record in the recordset. * - * @return true if there still rows available, or false if there are no more rows (EOF). + * @return bool true if there still rows available, or false if there are no more rows (EOF). */ function MoveNext() { if (!$this->EOF) { @@ -3750,9 +4506,9 @@ function MoveNext() { * Random access to a specific row in the recordset. Some databases do not support * access to previous rows in the databases (no scrolling backwards). * - * @param rowNumber is the row to move to (0-based) + * @param int $rowNumber is the row to move to (0-based) * - * @return true if there still rows available, or false if there are no more rows (EOF). + * @return bool true if there still rows available, or false if there are no more rows (EOF). */ function Move($rowNumber = 0) { $this->EOF = false; @@ -3784,18 +4540,11 @@ function Move($rowNumber = 0) { if ($rowNumber < $this->_currentRow) { return false; } - global $ADODB_EXTENSION; - if ($ADODB_EXTENSION) { - while (!$this->EOF && $this->_currentRow < $rowNumber) { - adodb_movenext($this); - } - } else { - while (! $this->EOF && $this->_currentRow < $rowNumber) { - $this->_currentRow++; + while (! $this->EOF && $this->_currentRow < $rowNumber) { + $this->_currentRow++; - if (!$this->_fetch()) { - $this->EOF = true; - } + if (!$this->_fetch()) { + $this->EOF = true; } } return !($this->EOF); @@ -3806,14 +4555,22 @@ function Move($rowNumber = 0) { return false; } + /** + * Adjusts the result pointer to an arbitrary row in the result. + * + * @param int $row The row to seek to. + * + * @return bool False if the recordset contains no rows, otherwise true. + */ + function _seek($row) {} /** * Get the value of a field in the current row by column name. * Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM. * - * @param colname is the field to access + * @param string $colname is the field to access * - * @return the value of $colname column + * @return mixed the value of $colname column */ function Fields($colname) { return $this->fields[$colname]; @@ -3822,6 +4579,9 @@ function Fields($colname) { /** * Defines the function to use for table fields case conversion * depending on ADODB_ASSOC_CASE + * + * @param int [$case] + * * @return string strtolower/strtoupper or false if no conversion needed */ protected function AssocCaseConvertFunction($case = ADODB_ASSOC_CASE) { @@ -3839,7 +4599,7 @@ protected function AssocCaseConvertFunction($case = ADODB_ASSOC_CASE) { /** * Builds the bind array associating keys to recordset fields * - * @param int $upper Case for the array keys, defaults to uppercase + * @param int [$upper] Case for the array keys, defaults to uppercase * (see ADODB_ASSOC_CASE_xxx constants) */ function GetAssocKeys($upper = ADODB_ASSOC_CASE) { @@ -3878,6 +4638,7 @@ function GetAssocKeys($upper = ADODB_ASSOC_CASE) { * * @param int $upper Case for the array keys, defaults to uppercase * (see ADODB_ASSOC_CASE_xxx constants) + * @return array */ function GetRowAssoc($upper = ADODB_ASSOC_CASE) { $record = array(); @@ -3899,7 +4660,7 @@ function GetRowAssoc($upper = ADODB_ASSOC_CASE) { /** * Clean up recordset * - * @return true or false + * @return bool */ function Close() { // free connection object - this seems to globally free the object @@ -3913,40 +4674,47 @@ function Close() { } /** - * synonyms RecordCount and RowCount + * Number of rows in recordset. * - * @return the number of rows or -1 if this is not supported + * @return int Number of rows or -1 if this is not supported */ - function RecordCount() { + function recordCount() { return $this->_numOfRows; } - - /* - * If we are using PageExecute(), this will return the maximum possible rows - * that can be returned when paging a recordset. - */ + /** + * If we are using PageExecute(), this will return the maximum possible rows + * that can be returned when paging a recordset. + * + * @return int + */ function MaxRecordCount() { - return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->RecordCount(); + return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->recordCount(); } /** - * synonyms RecordCount and RowCount + * Number of rows in recordset. + * Alias for {@see recordCount()} * - * @return the number of rows or -1 if this is not supported + * @return int Number of rows or -1 if this is not supported */ - function RowCount() { - return $this->_numOfRows; + function rowCount() { + return $this->recordCount(); } - - /** - * Portable RecordCount. Pablo Roca + /** + * Portable RecordCount. + * + * Be aware of possible problems in multiuser environments. + * For better speed the table must be indexed by the condition. + * Heavy test this before deploying. + * + * @param string $table + * @param string $condition * - * @return the number of records from a previous SELECT. All databases support this. + * @return int Number of records from a previous SELECT. All databases support this. * - * But aware possible problems in multiuser environments. For better speed the table - * must be indexed by the condition. Heavy test this before deploying. + * @author Pablo Roca */ function PO_RecordCount($table="", $condition="") { @@ -3991,51 +4759,53 @@ function FieldCount() { return $this->_numOfFields; } - /** - * Get the ADOFieldObject of a specific column. + * Get a Field's metadata from database. + * + * Must be defined by child class. * - * @param fieldoffset is the column position to access(0-based). + * @param int $fieldOffset * - * @return the ADOFieldObject for that column, or false. + * @return ADOFieldObject|false */ - function FetchField($fieldoffset = -1) { - // must be defined by child class - + function fetchField($fieldOffset) + { return false; } /** - * Get the ADOFieldObjects of all columns in an array. + * Get Field metadata for all the recordset's columns in an array. * + * @return ADOFieldObject[] */ - function FieldTypesArray() { - $arr = array(); - for ($i=0, $max=$this->_numOfFields; $i < $max; $i++) - $arr[] = $this->FetchField($i); - return $arr; + function fieldTypesArray() { + if (empty($this->fieldObjectsCache)) { + for ($i = 0; $i < $this->_numOfFields; $i++) { + $this->fieldObjectsCache[] = $this->fetchField($i); + } + } + return $this->fieldObjectsCache; } /** - * Return the fields array of the current row as an object for convenience. - * The default case is lowercase field names. - * - * @return the object with the properties set to the fields of the current row - */ + * Return the fields array of the current row as an object for convenience. + * The default case is lowercase field names. + * + * @return the object with the properties set to the fields of the current row + */ function FetchObj() { - $o = $this->FetchObject(false); - return $o; + return $this->FetchObject(false); } /** - * Return the fields array of the current row as an object for convenience. - * The default case is uppercase. - * - * @param $isupper to set the object property names to uppercase - * - * @return the object with the properties set to the fields of the current row - */ - function FetchObject($isupper=true) { + * Return the fields array of the current row as an object for convenience. + * The default case is uppercase. + * + * @param bool $isUpper to set the object property names to uppercase + * + * @return ADOFetchObj The object with properties set to the fields of the current row + */ + function FetchObject($isUpper=true) { if (empty($this->_obj)) { $this->_obj = new ADOFetchObj(); $this->_names = array(); @@ -4044,16 +4814,11 @@ function FetchObject($isupper=true) { $this->_names[] = $f->name; } } - $i = 0; - if (PHP_VERSION >= 5) { - $o = clone($this->_obj); - } else { - $o = $this->_obj; - } + $o = clone($this->_obj); for ($i=0; $i <$this->_numOfFields; $i++) { $name = $this->_names[$i]; - if ($isupper) { + if ($isUpper) { $n = strtoupper($name); } else { $n = $name; @@ -4065,35 +4830,34 @@ function FetchObject($isupper=true) { } /** - * Return the fields array of the current row as an object for convenience. - * The default is lower-case field names. - * - * @return the object with the properties set to the fields of the current row, - * or false if EOF - * - * Fixed bug reported by tim@orotech.net - */ + * Return the fields array of the current row as an object for convenience. + * The default is lower-case field names. + * + * @return ADOFetchObj|false The object with properties set to the fields of the current row + * or false if EOF. + * + * Fixed bug reported by tim@orotech.net + */ function FetchNextObj() { - $o = $this->FetchNextObject(false); - return $o; + return $this->FetchNextObject(false); } /** - * Return the fields array of the current row as an object for convenience. - * The default is upper case field names. - * - * @param $isupper to set the object property names to uppercase - * - * @return the object with the properties set to the fields of the current row, - * or false if EOF - * - * Fixed bug reported by tim@orotech.net - */ - function FetchNextObject($isupper=true) { + * Return the fields array of the current row as an object for convenience. + * The default is upper case field names. + * + * @param bool $isUpper to set the object property names to uppercase + * + * @return ADOFetchObj|false The object with properties set to the fields of the current row + * or false if EOF. + * + * Fixed bug reported by tim@orotech.net + */ + function FetchNextObject($isUpper=true) { $o = false; if ($this->_numOfRows != 0 && !$this->EOF) { - $o = $this->FetchObject($isupper); + $o = $this->FetchObject($isUpper); $this->_currentRow++; if ($this->_fetch()) { return $o; @@ -4104,34 +4868,27 @@ function FetchNextObject($isupper=true) { } /** - * Get the metatype of the column. This is used for formatting. This is because - * many databases use different names for the same type, so we transform the original - * type to our standardised version which uses 1 character codes: + * Get the ADOdb metatype. * - * @param t is the type passed in. Normally is ADOFieldObject->type. - * @param len is the maximum length of that field. This is because we treat character - * fields bigger than a certain size as a 'B' (blob). - * @param fieldobj is the field object returned by the database driver. Can hold - * additional info (eg. primary_key for mysql). + * Many databases use different names for the same type, so we transform + * the native type to our standardised one, which uses 1 character codes. + * @see https://adodb.org/dokuwiki/doku.php?id=v5:dictionary:dictionary_index#portable_data_types * - * @return the general type of the data: - * C for character < 250 chars - * X for teXt (>= 250 chars) - * B for Binary - * N for numeric or floating point - * D for date - * T for timestamp - * L for logical/Boolean - * I for integer - * R for autoincrement counter/integer + * @param string|ADOFieldObject $t Native type (usually ADOFieldObject->type) + * It is also possible to provide an + * ADOFieldObject here. + * @param int $len The field's maximum length. This is because we treat + * character fields bigger than a certain size as a 'B' (blob). + * @param ADOFieldObject $fieldObj Field object returned by the database driver; + * can hold additional info (eg. primary_key for mysql). * - * - */ - function MetaType($t,$len=-1,$fieldobj=false) { - if (is_object($t)) { - $fieldobj = $t; - $t = $fieldobj->type; - $len = $fieldobj->max_length; + * @return string The ADOdb Standard type + */ + function metaType($t, $len = -1, $fieldObj = false) { + if ($t instanceof ADOFieldObject) { + $fieldObj = $t; + $t = $fieldObj->type; + $len = $fieldObj->max_length; } // changed in 2.32 to hashing instead of switch stmt for speed... @@ -4240,9 +4997,8 @@ function MetaType($t,$len=-1,$fieldobj=false) { "SQLBOOL" => 'L' ); - $tmap = false; $t = strtoupper($t); - $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N'; + $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : ADODB_DEFAULT_METATYPE; switch ($tmap) { case 'C': // is the char field is too long, return as text field... @@ -4256,7 +5012,7 @@ function MetaType($t,$len=-1,$fieldobj=false) { return 'C'; case 'I': - if (!empty($fieldobj->primary_key)) { + if (!empty($fieldObj->primary_key)) { return 'R'; } return 'I'; @@ -4265,8 +5021,8 @@ function MetaType($t,$len=-1,$fieldobj=false) { return 'N'; case 'B': - if (isset($fieldobj->binary)) { - return ($fieldobj->binary) ? 'B' : 'X'; + if (isset($fieldObj->binary)) { + return ($fieldObj->binary) ? 'B' : 'X'; } return 'B'; @@ -4317,8 +5073,10 @@ function _close() {} /** * set/returns the current recordset page when paginating + * @param int $page + * @return int */ - function AbsolutePage($page=-1) { + function absolutePage($page=-1) { if ($page != -1) { $this->_currentPage = $page; } @@ -4327,6 +5085,8 @@ function AbsolutePage($page=-1) { /** * set/returns the status of the atFirstPage flag when paginating + * @param bool $status + * @return bool */ function AtFirstPage($status=false) { if ($status != false) { @@ -4335,6 +5095,10 @@ function AtFirstPage($status=false) { return $this->_atFirstPage; } + /** + * @param bool $page + * @return bool + */ function LastPageNo($page = false) { if ($page != false) { $this->_lastPageNo = $page; @@ -4344,6 +5108,8 @@ function LastPageNo($page = false) { /** * set/returns the status of the atLastPage flag when paginating + * @param bool $status + * @return bool */ function AtLastPage($status=false) { if ($status != false) { @@ -4381,58 +5147,32 @@ class ADORecordSet_array extends ADORecordSet /** * Constructor + * + * The parameters passed to this recordset are always fake because + * this class does not use the queryID + * + * @param resource|int $queryID Ignored + * @param int|bool $mode The ADODB_FETCH_MODE value */ - function __construct($fakeid=1) { + function __construct($queryID, $mode=false) { global $ADODB_FETCH_MODE,$ADODB_COMPAT_FETCH; // fetch() on EOF does not delete $this->fields $this->compat = !empty($ADODB_COMPAT_FETCH); - parent::__construct($fakeid); // fake queryID + parent::__construct($queryID); // fake queryID $this->fetchMode = $ADODB_FETCH_MODE; } - function _transpose($addfieldnames=true) { - global $ADODB_INCLUDED_LIB; - - if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); - } - $hdr = true; - - $fobjs = $addfieldnames ? $this->_fieldobjects : false; - adodb_transpose($this->_array, $newarr, $hdr, $fobjs); - //adodb_pr($newarr); - - $this->_skiprow1 = false; - $this->_array = $newarr; - $this->_colnames = $hdr; - - adodb_probetypes($newarr,$this->_types); - - $this->_fieldobjects = array(); - - foreach($hdr as $k => $name) { - $f = new ADOFieldObject(); - $f->name = $name; - $f->type = $this->_types[$k]; - $f->max_length = -1; - $this->_fieldobjects[] = $f; - } - $this->fields = reset($this->_array); - - $this->_initrs(); - - } /** * Setup the array. * * @param array is a 2-dimensional array holding the data. * The first row should hold the column names - * unless paramter $colnames is used. + * unless parameter $colnames is used. * @param typearr holds an array of types. These are the same types * used in MetaTypes (C,B,L,I,N). - * @param [colnames] array of column names. If set, then the first row of + * @param string[]|false [$colnames] array of column names. If set, then the first row of * $array should not hold the column names. */ function InitArray($array,$typearr,$colnames=false) { @@ -4450,10 +5190,10 @@ function InitArray($array,$typearr,$colnames=false) { /** * Setup the Array and datatype file objects * - * @param array is a 2-dimensional array holding the data. + * @param array $array 2-dimensional array holding the data * The first row should hold the column names - * unless paramter $colnames is used. - * @param fieldarr holds an array of ADOFieldObject's. + * unless parameter $colnames is used. + * @param array $fieldarr Array of ADOFieldObject's. */ function InitArrayFields(&$array,&$fieldarr) { $this->_array = $array; @@ -4464,12 +5204,15 @@ function InitArrayFields(&$array,&$fieldarr) { $this->Init(); } + /** + * @param int [$nRows] + * @return array + */ function GetArray($nRows=-1) { if ($nRows == -1 && $this->_currentRow <= 0 && !$this->_skiprow1) { return $this->_array; } else { - $arr = ADORecordSet::GetArray($nRows); - return $arr; + return ADORecordSet::GetArray($nRows); } } @@ -4484,7 +5227,12 @@ function _initrs() { : sizeof($this->_types); } - /* Use associative array to get fields array */ + /** + * Use associative array to get fields array + * + * @param string $colname + * @return mixed + */ function Fields($colname) { $mode = isset($this->adodbFetchMode) ? $this->adodbFetchMode : $this->fetchMode; @@ -4504,6 +5252,11 @@ function Fields($colname) { return $this->fields[$this->bind[strtoupper($colname)]]; } + /** + * @param int [$fieldOffset] + * + * @return \ADOFieldObject + */ function FetchField($fieldOffset = -1) { if (isset($this->_fieldobjects)) { return $this->_fieldobjects[$fieldOffset]; @@ -4516,6 +5269,10 @@ function FetchField($fieldOffset = -1) { return $o; } + /** + * @param int $row + * @return bool + */ function _seek($row) { if (sizeof($this->_array) && 0 <= $row && $row < $this->_numOfRows) { $this->_currentRow = $row; @@ -4528,6 +5285,9 @@ function _seek($row) { return false; } + /** + * @return bool + */ function MoveNext() { if (!$this->EOF) { $this->_currentRow++; @@ -4551,6 +5311,9 @@ function MoveNext() { return false; } + /** + * @return bool + */ function _fetch() { $pos = $this->_currentRow; @@ -4598,9 +5361,7 @@ function ADOLoadCode($dbType) { $db = strtolower($dbType); switch ($db) { case 'ado': - if (PHP_VERSION >= 5) { - $db = 'ado5'; - } + $db = 'ado5'; $class = 'ado'; break; @@ -4611,15 +5372,26 @@ function ADOLoadCode($dbType) { case 'pgsql': case 'postgres': - $class = $db = 'postgres8'; + $class = $db = 'postgres9'; + break; + + case 'mysql': + // mysql extension removed in PHP 7.0 - automatically switch to mysqli + $class = $db = 'mysqli'; break; default: - $class = $db; break; + if (substr($db, 0, 4) === 'pdo_') { + ADOConnection::outp("Invalid database type: $db"); + return false; + } + + $class = $db; + break; } - $file = ADODB_DIR."/drivers/adodb-".$db.".inc.php"; - @include_once($file); + $file = "drivers/adodb-$db.inc.php"; + @include_once(ADODB_DIR . '/' . $file); $ADODB_LASTDB = $class; if (class_exists("ADODB_" . $class)) { return $class; @@ -4635,20 +5407,24 @@ function ADOLoadCode($dbType) { } /** - * synonym for ADONewConnection for people like me who cannot remember the correct name + * Synonym for ADONewConnection for people like me who cannot remember the correct name + * + * @param string [$db] + * + * @return ADOConnection|false */ function NewADOConnection($db='') { - $tmp = ADONewConnection($db); - return $tmp; + return ADONewConnection($db); } /** * Instantiate a new Connection class for a specific database driver. * - * @param [db] is the database Connection object to create. If undefined, + * @param string $db Database Connection object to create. If undefined, * use the last database driver that was loaded by ADOLoadCode(). * - * @return the freshly created instance of the Connection class. + * @return ADOConnection|false The freshly created instance of the Connection class + * or false in case of error. */ function ADONewConnection($db='') { global $ADODB_NEWCONNECTION, $ADODB_LASTDB; @@ -4656,6 +5432,13 @@ function ADONewConnection($db='') { if (!defined('ADODB_ASSOC_CASE')) { define('ADODB_ASSOC_CASE', ADODB_ASSOC_CASE_NATIVE); } + + /* + * Are there special characters in the dsn password + * that disrupt parse_url + */ + $needsSpecialCharacterHandling = false; + $errorfn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER : false; if (($at = strpos($db,'://')) !== FALSE) { $origdsn = $db; @@ -4677,8 +5460,27 @@ function ADONewConnection($db='') { $path = substr($path,0,$qmark); } $dsna['path'] = '/' . urlencode($path); - } else - $dsna = @parse_url($fakedsn); + } else { + /* + * Stop # character breaking parse_url + */ + $cFakedsn = str_replace('#','\035',$fakedsn); + if (strcmp($fakedsn,$cFakedsn) != 0) + { + /* + * There is a # in the string + */ + $needsSpecialCharacterHandling = true; + + /* + * This allows us to successfully parse the url + */ + $fakedsn = $cFakedsn; + + } + + $dsna = parse_url($fakedsn); + } if (!$dsna) { return false; @@ -4705,11 +5507,20 @@ function ADONewConnection($db='') { if (!$db) { return false; } + $dsna['host'] = isset($dsna['host']) ? rawurldecode($dsna['host']) : ''; $dsna['user'] = isset($dsna['user']) ? rawurldecode($dsna['user']) : ''; $dsna['pass'] = isset($dsna['pass']) ? rawurldecode($dsna['pass']) : ''; $dsna['path'] = isset($dsna['path']) ? rawurldecode(substr($dsna['path'],1)) : ''; # strip off initial / + if ($needsSpecialCharacterHandling) + { + /* + * Revert back to the original string + */ + $dsna = str_replace('\035','#',$dsna); + } + if (isset($dsna['query'])) { $opt1 = explode('&',$dsna['query']); foreach($opt1 as $k => $v) { @@ -4719,6 +5530,7 @@ function ADONewConnection($db='') { } else { $opt = array(); } + } /* * phptype: Database backend used in PHP (mysql, odbc etc.) @@ -4903,12 +5715,19 @@ function NewPerfMonitor(&$conn) { if (!class_exists($class)) { return false; } - $perf = new $class($conn); - return $perf; + return new $class($conn); } - function NewDataDictionary(&$conn,$drivername=false) { + /** + * Get a new Data Dictionary object for the connection. + * + * @param ADOConnection $conn + * @param string $drivername + * + * @return ADODB_DataDict|false + */ + function newDataDictionary(&$conn, $drivername='') { if (!$drivername) { $drivername = _adodb_getdriver($conn->dataProvider,$conn->databaseType); } @@ -4935,11 +5754,9 @@ function NewDataDictionary(&$conn,$drivername=false) { return $dict; } - - - /* - Perform a print_r, with pre tags for better formatting. - */ + /** + * Perform a print_r, with pre tags for better formatting. + */ function adodb_pr($var,$as_string=false) { if ($as_string) { ob_start(); @@ -4958,16 +5775,19 @@ function adodb_pr($var,$as_string=false) { } } - /* - Perform a stack-crawl and pretty print it. - - @param printOrArr Pass in a boolean to indicate print, or an $exception->trace array (assumes that print is true then). - @param levels Number of levels to display - */ + /** + * Perform a stack-crawl and pretty print it. + * + * @param bool $printOrArr Pass in a boolean to indicate print, or an $exception->trace array (assumes that print is true then). + * @param int $levels Number of levels to display + * @param mixed $ishtml + * + * @return string + */ function adodb_backtrace($printOrArr=true,$levels=9999,$ishtml=null) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) { - include(ADODB_DIR.'/adodb-lib.inc.php'); + include_once(ADODB_DIR.'/adodb-lib.inc.php'); } return _adodb_backtrace($printOrArr,$levels,0,$ishtml); } diff --git a/www/include/adodb5/composer.json b/www/include/adodb/composer.json similarity index 78% rename from www/include/adodb5/composer.json rename to www/include/adodb/composer.json index 21bd25f9..cd97e9d7 100644 --- a/www/include/adodb5/composer.json +++ b/www/include/adodb/composer.json @@ -1,7 +1,7 @@ { "name" : "adodb/adodb-php", "description" : "ADOdb is a PHP database abstraction layer library", - "license" : [ "BSD-3-Clause", "LGPL-2.1" ], + "license" : [ "BSD-3-Clause", "LGPL-2.1-or-later" ], "authors" : [ { "name": "John Lim", @@ -20,14 +20,18 @@ "keywords" : [ "database", "abstraction", "layer", "library", "php" ], - "homepage": "http://adodb.org/", + "homepage": "https://adodb.org/", "support" : { "issues" : "https://github.com/ADOdb/ADOdb/issues", "source" : "https://github.com/ADOdb/ADOdb" }, "require" : { - "php" : ">=5.3.2" + "php" : "^7.0 || ^8.0" + }, + + "require-dev" : { + "phpunit/phpunit": "^8.5" }, "autoload" : { diff --git a/www/include/adodb5/datadict/datadict-access.inc.php b/www/include/adodb/datadict/datadict-access.inc.php similarity index 58% rename from www/include/adodb5/datadict/datadict-access.inc.php rename to www/include/adodb/datadict/datadict-access.inc.php index c1459154..b3f9fad0 100644 --- a/www/include/adodb5/datadict/datadict-access.inc.php +++ b/www/include/adodb/datadict/datadict-access.inc.php @@ -1,16 +1,23 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'TEXT'; case 'XL': @@ -34,18 +50,19 @@ function ActualType($meta) case 'B': return 'BINARY'; case 'TS': - case 'D': return 'DATETIME'; + case 'D': + return 'DATETIME'; case 'T': return 'DATETIME'; - case 'L': return 'BYTE'; - case 'I': return 'INTEGER'; + case 'L': return 'BYTE'; + case 'I': return 'INTEGER'; case 'I1': return 'BYTE'; case 'I2': return 'SMALLINT'; case 'I4': return 'INTEGER'; case 'I8': return 'INTEGER'; - case 'F': return 'DOUBLE'; - case 'N': return 'NUMERIC'; + case 'F': return 'DOUBLE'; + case 'N': return 'NUMERIC'; default: return $meta; } diff --git a/www/include/adodb5/datadict/datadict-db2.inc.php b/www/include/adodb/datadict/datadict-db2.inc.php similarity index 51% rename from www/include/adodb5/datadict/datadict-db2.inc.php rename to www/include/adodb/datadict/datadict-db2.inc.php index 7d201ff1..9ac106bb 100644 --- a/www/include/adodb5/datadict/datadict-db2.inc.php +++ b/www/include/adodb/datadict/datadict-db2.inc.php @@ -1,16 +1,24 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'VARCHAR'; case 'XL': return 'CLOB'; @@ -60,21 +82,66 @@ function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint return $suffix; } - function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') + function alterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') { - if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported"); - return array(); + $tabname = $this->TableName ($tabname); + $sql = array(); + list($lines,$pkey,$idxs) = $this->_GenFields($flds); + // genfields can return FALSE at times + if ($lines == null) $lines = array(); + $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' '; + + $dataTypeWords = array('SET','DATA','TYPE'); + + foreach($lines as $v) + { + /* + * We must now post-process the line to insert the 'SET DATA TYPE' + * text into the alter statement + */ + $e = explode(' ',$v); + + array_splice($e,1,0,$dataTypeWords); + + $v = implode(' ',$e); + + $sql[] = $alter . $v; + } + if (is_array($idxs)) + { + foreach($idxs as $idx => $idxdef) { + $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); + $sql = array_merge($sql, $sql_idxs); + } + + } + return $sql; } - function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') + + function dropColumnSql($tabname, $flds, $tableflds='',$tableoptions='') { - if ($this->debug) ADOConnection::outp("DropColumnSQL not supported"); - return array(); - } + + + $tabname = $this->connection->getMetaCasedValue($tabname); + $flds = $this->connection->getMetaCasedValue($flds); + + if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_NATIVE ) + { + /* + * METACASE_NATIVE + */ + $tabname = $this->connection->nameQuote . $tabname . $this->connection->nameQuote; + $flds = $this->connection->nameQuote . $flds . $this->connection->nameQuote; + } + $sql = sprintf($this->dropCol,$tabname,$flds); + return (array)$sql; + } + - function ChangeTableSQL($tablename, $flds, $tableoptions = false) + function changeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFields=false) { /** @@ -86,17 +153,25 @@ function ChangeTableSQL($tablename, $flds, $tableoptions = false) $validTypes = array("CHAR","VARC"); $invalidTypes = array("BIGI","BLOB","CLOB","DATE", "DECI","DOUB", "INTE", "REAL","SMAL", "TIME"); // check table exists - $cols = $this->MetaColumns($tablename); + + + $cols = $this->metaColumns($tablename); if ( empty($cols)) { - return $this->CreateTableSQL($tablename, $flds, $tableoptions); + return $this->createTableSQL($tablename, $flds, $tableoptions); } // already exists, alter table instead list($lines,$pkey) = $this->_GenFields($flds); - $alter = 'ALTER TABLE ' . $this->TableName($tablename); + $alter = 'ALTER TABLE ' . $this->tableName($tablename); $sql = array(); foreach ( $lines as $id => $v ) { + /* + * If the metaCasing was NATIVE the col returned with nameQuotes + * around the field. We need to remove this for the metaColumn + * match + */ + $id = str_replace($this->connection->nameQuote,'',$id); if ( isset($cols[$id]) && is_object($cols[$id]) ) { /** If the first field of $v is the fieldname, and diff --git a/www/include/adodb/datadict/datadict-firebird.inc.php b/www/include/adodb/datadict/datadict-firebird.inc.php new file mode 100644 index 00000000..79d0a8f5 --- /dev/null +++ b/www/include/adodb/datadict/datadict-firebird.inc.php @@ -0,0 +1,283 @@ +connection->customMetaTypes[$meta])) { + return $this->connection->customMetaTypes[$meta]['actual']; + } + + switch($meta) { + case 'C': + return 'VARCHAR'; + case 'XL': + return 'BLOB SUB_TYPE BINARY'; + case 'X': + return 'BLOB SUB_TYPE TEXT'; + + case 'C2': + return 'VARCHAR(32765)'; // up to 32K + case 'X2': + return 'VARCHAR(4096)'; + + case 'V': + return 'CHAR'; + case 'C1': + return 'CHAR(1)'; + + case 'B': + return 'BLOB'; + + case 'D': + return 'DATE'; + case 'TS': + case 'T': + return 'TIMESTAMP'; + + case 'L': + case 'I1': + case 'I2': + return 'SMALLINT'; + case 'I': + case 'I4': + return 'INTEGER'; + case 'I8': + return 'BIGINT'; + + case 'F': + return 'DOUBLE PRECISION'; + case 'N': + return 'DECIMAL'; + default: + return $meta; + } + } + + function nameQuote($name = null, $allowBrackets = false) + { + if (!is_string($name)) { + return false; + } + + $name = trim($name); + + if (!is_object($this->connection)) { + return $name; + } + + $quote = $this->connection->nameQuote; + + // if name is of the form `name`, quote it + if (preg_match('/^`(.+)`$/', $name, $matches)) { + return $quote . $matches[1] . $quote; + } + + // if name contains special characters, quote it + if (!preg_match('/^[' . $this->nameRegex . ']+$/', $name)) { + return $quote . $name . $quote; + } + + return $quote . $name . $quote; + } + + function createDatabase($dbname, $options = false) + { + $sql = array(); + + $sql[] = "DECLARE EXTERNAL FUNCTION LOWER CSTRING(80) RETURNS CSTRING(80) FREE_IT ENTRY_POINT 'IB_UDF_lower' MODULE_NAME 'ib_udf'"; + + return $sql; + } + + function _dropAutoIncrement($tabname) + { + if (strpos($tabname, '.') !== false) { + $tarr = explode('.', $tabname); + return 'DROP SEQUENCE ' . $tarr[0] . '."s_' . $tarr[1] . '"'; + } + return 'DROP SEQUENCE s_' . $tabname; + } + + + function _createSuffix($fname, &$ftype, $fnotnull, $fdefault, $fautoinc, $fconstraint, $funsigned) + { + $suffix = ''; + + if (strlen($fdefault)) { + $suffix .= " DEFAULT $fdefault"; + } + if ($fnotnull) { + $suffix .= ' NOT NULL'; + } + if ($fautoinc) { + $this->seqField = $fname; + } + $fconstraint = preg_replace("/``/", "\"", $fconstraint); + if ($fconstraint) { + $suffix .= ' ' . $fconstraint; + } + + return $suffix; + } + + /** + * Generate the SQL to create table. Returns an array of sql strings. + */ + function createTableSQL($tabname, $flds, $tableoptions = array()) + { + list($lines, $pkey, $idxs) = $this->_GenFields($flds, true); + // genfields can return FALSE at times + if ($lines == null) { + $lines = array(); + } + + $taboptions = $this->_Options($tableoptions); + $tabname = $this->TableName($tabname); + $sql = $this->_TableSQL($tabname, $lines, $pkey, $taboptions); + + if ($this->autoIncrement && !isset($taboptions['DROP'])) { + $tsql = $this->_Triggers($tabname, $taboptions); + foreach ($tsql as $s) { + $sql[] = $s; + } + } + + if (is_array($idxs)) { + foreach ($idxs as $idx => $idxdef) { + $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); + $sql = array_merge($sql, $sql_idxs); + } + } + + return $sql; + } + + + /* + CREATE or replace TRIGGER jaddress_insert + before insert on jaddress + for each row + begin + IF ( NEW."seqField" IS NULL OR NEW."seqField" = 0 ) THEN + NEW."seqField" = GEN_ID("GEN_tabname", 1); + end; + */ + function _triggers($tabname, $taboptions) + { + if (!$this->seqField) { + return array(); + } + + $tab1 = preg_replace('/"/', '', $tabname); + if ($this->schema) { + $t = strpos($tab1, '.'); + if ($t !== false) { + $tab = substr($tab1, $t + 1); + } else { + $tab = $tab1; + } + $seqField = $this->seqField; + $seqname = $this->schema . '.' . $this->seqPrefix . $tab; + $trigname = $this->schema . '.t_' . $this->seqPrefix . $tab; + } else { + $seqField = $this->seqField; + $seqname = $this->seqPrefix . $tab1; + $trigname = 't_' . $seqname; + } + + if (isset($taboptions['DROP'])) { + $sql[] = "DROP SEQUENCE $seqname"; + } elseif (isset($taboptions['REPLACE'])) { + $sql[] = "DROP SEQUENCE \"$seqname\""; + $sql[] = "CREATE SEQUENCE \"$seqname\""; + $sql[] = "ALTER TRIGGER \"$trigname\" BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END"; + } else { + $sql[] = "CREATE SEQUENCE $seqname"; + $sql[] = "CREATE TRIGGER $trigname FOR $tabname BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID($seqname, 1); END"; + } + + $this->seqField = false; + return $sql; + } + + /** + * Change the definition of one column + * + * @param string $tabname table-name + * @param string $flds column-name and type for the changed column + * @param string $tableflds Unused + * @param array|string $tableoptions Unused + * + * @return array with SQL strings + */ + public function alterColumnSQL($tabname, $flds, $tableflds = '', $tableoptions = '') + { + $tabname = $this->TableName($tabname); + $sql = array(); + list($lines, , $idxs) = $this->_GenFields($flds); + // genfields can return FALSE at times + + if ($lines == null) { + $lines = array(); + } + + $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' '; + + foreach ($lines as $v) { + /* + * The type must be preceded by the keyword 'TYPE' + */ + $vExplode = explode(' ', $v); + $vExplode = array_filter($vExplode); + array_splice($vExplode, 1, 0, array('TYPE')); + $v = implode(' ', $vExplode); + $sql[] = $alter . $v; + } + + if (is_array($idxs)) { + foreach ($idxs as $idx => $idxdef) { + $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); + $sql = array_merge($sql, $sql_idxs); + } + + } + return $sql; + } + +} diff --git a/www/include/adodb5/datadict/datadict-generic.inc.php b/www/include/adodb/datadict/datadict-generic.inc.php similarity index 69% rename from www/include/adodb5/datadict/datadict-generic.inc.php rename to www/include/adodb/datadict/datadict-generic.inc.php index e2e6909e..1a60dbc2 100644 --- a/www/include/adodb5/datadict/datadict-generic.inc.php +++ b/www/include/adodb/datadict/datadict-generic.inc.php @@ -1,16 +1,23 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'VARCHAR'; case 'XL': diff --git a/www/include/adodb5/datadict/datadict-ibase.inc.php b/www/include/adodb/datadict/datadict-ibase.inc.php similarity index 52% rename from www/include/adodb5/datadict/datadict-ibase.inc.php rename to www/include/adodb/datadict/datadict-ibase.inc.php index 495a722d..4310ded4 100644 --- a/www/include/adodb5/datadict/datadict-ibase.inc.php +++ b/www/include/adodb/datadict/datadict-ibase.inc.php @@ -1,16 +1,23 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'VARCHAR'; case 'XL': diff --git a/www/include/adodb5/datadict/datadict-informix.inc.php b/www/include/adodb/datadict/datadict-informix.inc.php similarity index 59% rename from www/include/adodb5/datadict/datadict-informix.inc.php rename to www/include/adodb/datadict/datadict-informix.inc.php index 25726f49..9e151633 100644 --- a/www/include/adodb5/datadict/datadict-informix.inc.php +++ b/www/include/adodb/datadict/datadict-informix.inc.php @@ -1,16 +1,23 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'VARCHAR';// 255 case 'XL': diff --git a/www/include/adodb5/datadict/datadict-mssql.inc.php b/www/include/adodb/datadict/datadict-mssql.inc.php similarity index 84% rename from www/include/adodb5/datadict/datadict-mssql.inc.php rename to www/include/adodb/datadict/datadict-mssql.inc.php index 2c496dea..17df9e39 100644 --- a/www/include/adodb5/datadict/datadict-mssql.inc.php +++ b/www/include/adodb/datadict/datadict-mssql.inc.php @@ -1,16 +1,23 @@ type; $len = $fieldobj->max_length; } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; $len = -1; // mysql max_length is not accurate - switch (strtoupper($t)) { + switch ($t) { case 'R': case 'INT': case 'INTEGER': return 'I'; @@ -80,6 +92,16 @@ function MetaType($t,$len=-1,$fieldobj=false) function ActualType($meta) { + + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch(strtoupper($meta)) { case 'C': return 'VARCHAR'; @@ -269,7 +291,7 @@ function _IndexSQL($idxname, $tabname, $flds, $idxoptions) } - function _GetSize($ftype, $ty, $fsize, $fprec) + function _GetSize($ftype, $ty, $fsize, $fprec, $options=false) { switch ($ftype) { case 'INT': @@ -279,7 +301,7 @@ function _GetSize($ftype, $ty, $fsize, $fprec) return $ftype; } if ($ty == 'T') return $ftype; - return parent::_GetSize($ftype, $ty, $fsize, $fprec); + return parent::_GetSize($ftype, $ty, $fsize, $fprec, $options); } } diff --git a/www/include/adodb5/datadict/datadict-mssqlnative.inc.php b/www/include/adodb/datadict/datadict-mssqlnative.inc.php similarity index 63% rename from www/include/adodb5/datadict/datadict-mssqlnative.inc.php rename to www/include/adodb/datadict/datadict-mssqlnative.inc.php index 36d5fcad..59228cbe 100644 --- a/www/include/adodb5/datadict/datadict-mssqlnative.inc.php +++ b/www/include/adodb/datadict/datadict-mssqlnative.inc.php @@ -1,16 +1,25 @@ type; - $len = $fieldobj->max_length; } - + + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + $_typeConversion = array( -155 => 'D', 93 => 'D', @@ -94,14 +111,25 @@ function MetaType($t,$len=-1,$fieldobj=false) -3 => 'X' ); - return $_typeConversion($t); + if (isset($_typeConversion[$t])) { + return $_typeConversion[$t]; + } + return ADODB_DEFAULT_METATYPE; } function ActualType($meta) { $DATE_TYPE = 'DATETIME'; - + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch(strtoupper($meta)) { case 'C': return 'VARCHAR'; @@ -126,7 +154,6 @@ function ActualType($meta) case 'F': return 'REAL'; case 'N': return 'NUMERIC'; default: - print "RETURN $meta"; return $meta; } } @@ -136,7 +163,7 @@ function AddColumnSQL($tabname, $flds) { $tabname = $this->TableName ($tabname); $f = array(); - list($lines,$pkey) = $this->_GenFields($flds); + list($lines,) = $this->_GenFields($flds); $s = "ALTER TABLE $tabname $this->addCol"; foreach($lines as $v) { $f[] = "\n $v"; @@ -146,30 +173,29 @@ function AddColumnSQL($tabname, $flds) return $sql; } - function DefaultConstraintname($tabname, $colname) + /** + * Get a column's default constraint. + * + * @param string $tabname + * @param string $colname + * @return string|null The Constraint's name, or null if there is none. + */ + function defaultConstraintName($tabname, $colname) { - $constraintname = false; - $rs = $this->connection->Execute( - "SELECT name FROM sys.default_constraints - WHERE object_name(parent_object_id) = '$tabname' - AND col_name(parent_object_id, parent_column_id) = '$colname'" - ); - if ( is_object($rs) ) { - $row = $rs->FetchRow(); - $constraintname = $row['name']; - } - return $constraintname; + $sql = "SELECT name FROM sys.default_constraints + WHERE object_name(parent_object_id) = ? + AND col_name(parent_object_id, parent_column_id) = ?"; + return $this->connection->getOne($sql, [$tabname, $colname]); } - + function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') { $tabname = $this->TableName ($tabname); $sql = array(); - list($lines,$pkey,$idxs) = $this->_GenFields($flds); + list($lines,,$idxs) = $this->_GenFields($flds); $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' '; foreach($lines as $v) { - $not_null = false; if ($not_null = preg_match('/NOT NULL/i',$v)) { $v = preg_replace('/NOT NULL/i','',$v); } @@ -177,7 +203,7 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') list(,$colname,$default) = $matches; $v = preg_replace('/^' . preg_quote($colname) . '\s/', '', $v); $t = trim(str_replace('DEFAULT '.$default,'',$v)); - if ( $constraintname = $this->DefaultConstraintname($tabname,$colname) ) { + if ( $constraintname = $this->defaultConstraintName($tabname,$colname) ) { $sql[] = 'ALTER TABLE '.$tabname.' DROP CONSTRAINT '. $constraintname; } if ($not_null) { @@ -190,7 +216,7 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') . ' DEFAULT ' . $default . ' FOR ' . $colname; } else { $colname = strtok($v," "); - if ( $constraintname = $this->DefaultConstraintname($tabname,$colname) ) { + if ( $constraintname = $this->defaultConstraintName($tabname,$colname) ) { $sql[] = 'ALTER TABLE '.$tabname.' DROP CONSTRAINT '. $constraintname; } if ($not_null) { @@ -218,17 +244,19 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') * @param string $tableflds Throwaway value to make the function match the parent * @param string $tableoptions Throway value to make the function match the parent * - * @return string The SQL necessary to drop the column + * @return string[] The SQL necessary to drop the column */ function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') { $tabname = $this->TableName ($tabname); - if (!is_array($flds)) - $flds = explode(',',$flds); + if (!is_array($flds)) { + /** @noinspection PhpParamsInspection */ + $flds = explode(',', $flds); + } $f = array(); $s = 'ALTER TABLE ' . $tabname; foreach($flds as $v) { - if ( $constraintname = $this->DefaultConstraintname($tabname,$v) ) { + if ( $constraintname = $this->defaultConstraintName($tabname,$v) ) { $sql[] = 'ALTER TABLE ' . $tabname . ' DROP CONSTRAINT ' . $constraintname; } $f[] = ' DROP COLUMN ' . $this->NameQuote($v); @@ -239,6 +267,8 @@ function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') } // return string must begin with space + + /** @noinspection DuplicatedCode */ function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) { $suffix = ''; @@ -250,78 +280,7 @@ function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint return $suffix; } - /* -CREATE TABLE - [ database_name.[ owner ] . | owner. ] table_name - ( { < column_definition > - | column_name AS computed_column_expression - | < table_constraint > ::= [ CONSTRAINT constraint_name ] } - - | [ { PRIMARY KEY | UNIQUE } [ ,...n ] - ) - -[ ON { filegroup | DEFAULT } ] -[ TEXTIMAGE_ON { filegroup | DEFAULT } ] - -< column_definition > ::= { column_name data_type } - [ COLLATE < collation_name > ] - [ [ DEFAULT constant_expression ] - | [ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ] - ] - [ ROWGUIDCOL] - [ < column_constraint > ] [ ...n ] - -< column_constraint > ::= [ CONSTRAINT constraint_name ] - { [ NULL | NOT NULL ] - | [ { PRIMARY KEY | UNIQUE } - [ CLUSTERED | NONCLUSTERED ] - [ WITH FILLFACTOR = fillfactor ] - [ON {filegroup | DEFAULT} ] ] - ] - | [ [ FOREIGN KEY ] - REFERENCES ref_table [ ( ref_column ) ] - [ ON DELETE { CASCADE | NO ACTION } ] - [ ON UPDATE { CASCADE | NO ACTION } ] - [ NOT FOR REPLICATION ] - ] - | CHECK [ NOT FOR REPLICATION ] - ( logical_expression ) - } - -< table_constraint > ::= [ CONSTRAINT constraint_name ] - { [ { PRIMARY KEY | UNIQUE } - [ CLUSTERED | NONCLUSTERED ] - { ( column [ ASC | DESC ] [ ,...n ] ) } - [ WITH FILLFACTOR = fillfactor ] - [ ON { filegroup | DEFAULT } ] - ] - | FOREIGN KEY - [ ( column [ ,...n ] ) ] - REFERENCES ref_table [ ( ref_column [ ,...n ] ) ] - [ ON DELETE { CASCADE | NO ACTION } ] - [ ON UPDATE { CASCADE | NO ACTION } ] - [ NOT FOR REPLICATION ] - | CHECK [ NOT FOR REPLICATION ] - ( search_conditions ) - } - - - */ - - /* - CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name - ON { table | view } ( column [ ASC | DESC ] [ ,...n ] ) - [ WITH < index_option > [ ,...n] ] - [ ON filegroup ] - < index_option > :: = - { PAD_INDEX | - FILLFACTOR = fillfactor | - IGNORE_DUP_KEY | - DROP_EXISTING | - STATISTICS_NORECOMPUTE | - SORT_IN_TEMPDB - } -*/ + /** @noinspection DuplicatedCode */ function _IndexSQL($idxname, $tabname, $flds, $idxoptions) { $sql = array(); @@ -353,17 +312,18 @@ function _IndexSQL($idxname, $tabname, $flds, $idxoptions) } - function _GetSize($ftype, $ty, $fsize, $fprec) + function _GetSize($ftype, $ty, $fsize, $fprec, $options=false) { switch ($ftype) { - case 'INT': - case 'SMALLINT': - case 'TINYINT': - case 'BIGINT': + case 'INT': + case 'SMALLINT': + case 'TINYINT': + case 'BIGINT': + return $ftype; + } + if ($ty == 'T') { return $ftype; } - if ($ty == 'T') return $ftype; - return parent::_GetSize($ftype, $ty, $fsize, $fprec); - + return parent::_GetSize($ftype, $ty, $fsize, $fprec, $options); } } diff --git a/www/include/adodb5/datadict/datadict-mysql.inc.php b/www/include/adodb/datadict/datadict-mysql.inc.php similarity index 75% rename from www/include/adodb5/datadict/datadict-mysql.inc.php rename to www/include/adodb/datadict/datadict-mysql.inc.php index 00a43a2a..9efbba1f 100644 --- a/www/include/adodb5/datadict/datadict-mysql.inc.php +++ b/www/include/adodb/datadict/datadict-mysql.inc.php @@ -1,16 +1,23 @@ type; @@ -34,7 +44,14 @@ function MetaType($t,$len=-1,$fieldobj=false) $is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->auto_increment; $len = -1; // mysql max_length is not accurate - switch (strtoupper($t)) { + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + + switch ($t) { + case 'STRING': case 'CHAR': case 'VARCHAR': @@ -74,13 +91,27 @@ function MetaType($t,$len=-1,$fieldobj=false) case 'SMALLINT': return $is_serial ? 'R' : 'I2'; case 'MEDIUMINT': return $is_serial ? 'R' : 'I4'; case 'BIGINT': return $is_serial ? 'R' : 'I8'; - default: return 'N'; + default: + + return ADODB_DEFAULT_METATYPE; } } function ActualType($meta) { - switch(strtoupper($meta)) { + + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + + switch($meta) + { + case 'C': return 'VARCHAR'; case 'XL':return 'LONGTEXT'; case 'X': return 'TEXT'; @@ -104,7 +135,9 @@ function ActualType($meta) case 'F': return 'DOUBLE'; case 'N': return 'NUMERIC'; + default: + return $meta; } } diff --git a/www/include/adodb5/datadict/datadict-oci8.inc.php b/www/include/adodb/datadict/datadict-oci8.inc.php similarity index 72% rename from www/include/adodb5/datadict/datadict-oci8.inc.php rename to www/include/adodb/datadict/datadict-oci8.inc.php index 57cf0af5..6d2cd244 100644 --- a/www/include/adodb5/datadict/datadict-oci8.inc.php +++ b/www/include/adodb/datadict/datadict-oci8.inc.php @@ -1,16 +1,23 @@ type; $len = $fieldobj->max_length; } - switch (strtoupper($t)) { + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + + switch ($t) { case 'VARCHAR': case 'VARCHAR2': case 'CHAR': @@ -69,12 +92,21 @@ function MetaType($t, $len=-1, $fieldobj=false) return 'I'; default: - return 'N'; + return ADODB_DEFAULT_METATYPE; } } function ActualType($meta) { + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'VARCHAR'; case 'X': return $this->typeX; @@ -185,32 +217,52 @@ function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint return $suffix; } -/* -CREATE or replace TRIGGER jaddress_insert -before insert on jaddress -for each row -begin -select seqaddress.nextval into :new.A_ID from dual; -end; -*/ + /** + * Creates an insert trigger to emulate an auto-increment column + * in a table + * + * @param string $tabname The name of the table + * @param string[] $tableoptions Optional configuration items + * + * @return string[] The SQL statements to create the trigger + */ function _Triggers($tabname,$tableoptions) { + if (!$this->seqField) return array(); - if ($this->schema) { + if ($this->schema) + { $t = strpos($tabname,'.'); - if ($t !== false) $tab = substr($tabname,$t+1); - else $tab = $tabname; + if ($t !== false) + $tab = substr($tabname,$t+1); + else + $tab = $tabname; + + if ($this->connection->useCompactAutoIncrements) + $id = sprintf('%u',crc32(strtolower($tab))); + else + $id = $tab; + $seqname = $this->schema.'.'.$this->seqPrefix.$tab; $trigname = $this->schema.'.'.$this->trigPrefix.$this->seqPrefix.$tab; - } else { - $seqname = $this->seqPrefix.$tabname; - $trigname = $this->trigPrefix.$seqname; + + } + else + { + if ($this->connection->useCompactAutoIncrements) + $id = sprintf('%u',crc32(strtolower($tabname))); + else + $id = $tabname; + + $seqname = $this->seqPrefix.$id; + $trigname = $this->trigPrefix.$id; } if (strlen($seqname) > 30) { $seqname = $this->seqPrefix.uniqid(''); } // end if + if (strlen($trigname) > 30) { $trigname = $this->trigPrefix.uniqid(''); } // end if @@ -221,8 +273,8 @@ function _Triggers($tabname,$tableoptions) $seqIncr = ''; if (isset($tableoptions['SEQUENCE_INCREMENT'])){$seqIncr = ' INCREMENT BY '.$tableoptions['SEQUENCE_INCREMENT'];} $seqStart = ''; - if (isset($tableoptions['SEQUENCE_START'])){$seqIncr = ' START WITH '.$tableoptions['SEQUENCE_START'];} - $sql[] = "CREATE SEQUENCE $seqname $seqStart $seqIncr $seqCache"; + if (isset($tableoptions['SEQUENCE_START'])){$seqStart = ' START WITH '.$tableoptions['SEQUENCE_START'];} + $sql[] = "CREATE SEQUENCE $seqname MINVALUE 1 $seqStart $seqIncr $seqCache"; $sql[] = "CREATE OR REPLACE TRIGGER $trigname BEFORE insert ON $tabname FOR EACH ROW WHEN (NEW.$this->seqField IS NULL OR NEW.$this->seqField = 0) BEGIN select $seqname.nextval into :new.$this->seqField from dual; END;"; $this->seqField = false; diff --git a/www/include/adodb5/datadict/datadict-postgres.inc.php b/www/include/adodb/datadict/datadict-postgres.inc.php similarity index 55% rename from www/include/adodb5/datadict/datadict-postgres.inc.php rename to www/include/adodb/datadict/datadict-postgres.inc.php index 99a56413..d403cee3 100644 --- a/www/include/adodb5/datadict/datadict-postgres.inc.php +++ b/www/include/adodb/datadict/datadict-postgres.inc.php @@ -1,22 +1,29 @@ type; $len = $fieldobj->max_length; } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + $is_serial = is_object($fieldobj) && !empty($fieldobj->primary_key) && !empty($fieldobj->unique) && !empty($fieldobj->has_default) && substr($fieldobj->default_value,0,8) == 'nextval('; - switch (strtoupper($t)) { + switch ($t) { + case 'INTERVAL': case 'CHAR': case 'CHARACTER': case 'VARCHAR': case 'NAME': - case 'BPCHAR': + case 'BPCHAR': if ($len <= $this->blobSize) return 'C'; case 'TEXT': @@ -84,14 +101,23 @@ function MetaType($t,$len=-1,$fieldobj=false) case 'REAL': return 'F'; - default: - return 'N'; + default: + return ADODB_DEFAULT_METATYPE; } } - function ActualType($meta) + function actualType($meta) { - switch($meta) { + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + + switch ($meta) { case 'C': return 'VARCHAR'; case 'XL': case 'X': return 'TEXT'; @@ -128,12 +154,12 @@ function ActualType($meta) * @param string $flds column-names and types for the changed columns * @return array with SQL strings */ - function AddColumnSQL($tabname, $flds) + function addColumnSQL($tabname, $flds) { - $tabname = $this->TableName ($tabname); + $tabname = $this->tableName($tabname); $sql = array(); $not_null = false; - list($lines,$pkey) = $this->_GenFields($flds); + list($lines,$pkey) = $this->_genFields($flds); $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' '; foreach($lines as $v) { if (($not_null = preg_match('/NOT NULL/i',$v))) { @@ -142,7 +168,7 @@ function AddColumnSQL($tabname, $flds) if (preg_match('/^([^ ]+) .*DEFAULT (\'[^\']+\'|\"[^\"]+\"|[^ ]+)/',$v,$matches)) { list(,$colname,$default) = $matches; $sql[] = $alter . str_replace('DEFAULT '.$default,'',$v); - $sql[] = 'UPDATE '.$tabname.' SET '.$colname.'='.$default; + $sql[] = 'UPDATE '.$tabname.' SET '.$colname.'='.$default.' WHERE '.$colname.' IS NULL '; $sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET DEFAULT ' . $default; } else { $sql[] = $alter . $v; @@ -156,51 +182,44 @@ function AddColumnSQL($tabname, $flds) } - function DropIndexSQL ($idxname, $tabname = NULL) + function dropIndexSQL($idxname, $tabname = NULL) { - return array(sprintf($this->dropIndex, $this->TableName($idxname), $this->TableName($tabname))); + return array(sprintf($this->dropIndex, $this->tableName($idxname), $this->tableName($tabname))); } /** * Change the definition of one column * - * Postgres can't do that on it's own, you need to supply the complete defintion of the new table, - * to allow, recreating the table and copying the content over to the new table - * @param string $tabname table-name - * @param string $flds column-name and type for the changed column - * @param string $tableflds complete defintion of the new table, eg. for postgres, default '' - * @param array/ $tableoptions options for the new table see CreateTableSQL, default '' + * Postgres can't do that on its own, you need to supply the complete + * definition of the new table, to allow recreating the table and copying + * the content over to the new table. + * + * @param string $tabname table-name + * @param string $flds column-name and type for the changed column + * @param string $tableflds complete definition of the new table, e.g. for postgres, default '' + * @param array $tableoptions options for the new table {@see CreateTableSQL()}, default '' + * * @return array with SQL strings */ - /* - function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') - { - if (!$tableflds) { - if ($this->debug) ADOConnection::outp("AlterColumnSQL needs a complete table-definiton for PostgreSQL"); - return array(); - } - return $this->_recreate_copy_table($tabname,False,$tableflds,$tableoptions); - }*/ - - function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') + function alterColumnSQL($tabname, $flds, $tableflds='', $tableoptions='') { // Check if alter single column datatype available - works with 8.0+ $has_alter_column = 8.0 <= (float) @$this->serverInfo['version']; if ($has_alter_column) { - $tabname = $this->TableName($tabname); + $tabname = $this->tableName($tabname); $sql = array(); - list($lines,$pkey) = $this->_GenFields($flds); + list($lines,$pkey) = $this->_genFields($flds); $set_null = false; foreach($lines as $v) { $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' '; if ($not_null = preg_match('/NOT NULL/i',$v)) { $v = preg_replace('/NOT NULL/i','',$v); } - // this next block doesn't work - there is no way that I can see to - // explicitly ask a column to be null using $flds - else if ($set_null = preg_match('/NULL/i',$v)) { - // if they didn't specify not null, see if they explicitely asked for null + // this next block doesn't work - there is no way that I can see to + // explicitly ask a column to be null using $flds + elseif ($set_null = preg_match('/NULL/i',$v)) { + // if they didn't specify not null, see if they explicitly asked for null // Lookbehind pattern covers the case 'fieldname NULL datatype DEFAULT NULL' // only the first NULL should be removed, not the one specifying // the default value @@ -208,13 +227,12 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') } if (preg_match('/^([^ ]+) .*DEFAULT (\'[^\']+\'|\"[^\"]+\"|[^ ]+)/',$v,$matches)) { - $existing = $this->MetaColumns($tabname); + $existing = $this->metaColumns($tabname); list(,$colname,$default) = $matches; $alter .= $colname; if ($this->connection) { - $old_coltype = $this->connection->MetaType($existing[strtoupper($colname)]); - } - else { + $old_coltype = $this->connection->metaType($existing[strtoupper($colname)]); + } else { $old_coltype = $t; } $v = preg_replace('/^' . preg_quote($colname) . '\s/', '', $v); @@ -250,7 +268,7 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') $sql[] = $alter . ' TYPE ' . $rest; } -# list($colname) = explode(' ',$v); + #list($colname) = explode(' ',$v); if ($not_null) { // this does not error out if the column is already not null $sql[] = $alter . ' SET NOT NULL'; @@ -268,31 +286,33 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') if ($this->debug) ADOConnection::outp("AlterColumnSQL needs a complete table-definiton for PostgreSQL"); return array(); } - return $this->_recreate_copy_table($tabname,False,$tableflds,$tableoptions); + return $this->_recreate_copy_table($tabname, false, $tableflds,$tableoptions); } /** * Drop one column * - * Postgres < 7.3 can't do that on it's own, you need to supply the complete defintion of the new table, + * Postgres < 7.3 can't do that on it's own, you need to supply the complete definition of the new table, * to allow, recreating the table and copying the content over to the new table * @param string $tabname table-name * @param string $flds column-name and type for the changed column - * @param string $tableflds complete defintion of the new table, eg. for postgres, default '' - * @param array/ $tableoptions options for the new table see CreateTableSQL, default '' + * @param string $tableflds complete definition of the new table, eg. for postgres, default '' + * @param array $tableoptions options for the new table {@see CreateTableSQL}, default [] * @return array with SQL strings */ - function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') + function dropColumnSQL($tabname, $flds, $tableflds='', $tableoptions='') { $has_drop_column = 7.3 <= (float) @$this->serverInfo['version']; if (!$has_drop_column && !$tableflds) { - if ($this->debug) ADOConnection::outp("DropColumnSQL needs complete table-definiton for PostgreSQL < 7.3"); - return array(); - } + if ($this->debug) { + ADOConnection::outp("dropColumnSQL needs complete table-definiton for PostgreSQL < 7.3"); + } + return array(); + } if ($has_drop_column) { - return ADODB_DataDict::DropColumnSQL($tabname, $flds); + return ADODB_DataDict::dropColumnSQL($tabname, $flds); } - return $this->_recreate_copy_table($tabname,$flds,$tableflds,$tableoptions); + return $this->_recreate_copy_table($tabname, $flds, $tableflds, $tableoptions); } /** @@ -303,68 +323,82 @@ function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') * @internal * @param string $tabname table-name * @param string $dropflds column-names to drop - * @param string $tableflds complete defintion of the new table, eg. for postgres - * @param array/string $tableoptions options for the new table see CreateTableSQL, default '' + * @param string $tableflds complete definition of the new table, eg. for postgres + * @param array|string $tableoptions options for the new table see CreateTableSQL, default '' * @return array with SQL strings */ - function _recreate_copy_table($tabname,$dropflds,$tableflds,$tableoptions='') + function _recreate_copy_table($tabname, $dropflds, $tableflds, $tableoptions='') { if ($dropflds && !is_array($dropflds)) $dropflds = explode(',',$dropflds); $copyflds = array(); - foreach($this->MetaColumns($tabname) as $fld) { - if (!$dropflds || !in_array($fld->name,$dropflds)) { - // we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one - if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) && - in_array($fld->type,array('varchar','char','text','bytea'))) { + foreach($this->metaColumns($tabname) as $fld) { + if (preg_match('/'.$fld->name.' (\w+)/i', $tableflds, $matches)) { + $new_type = strtoupper($matches[1]); + // AlterColumn of a char column to a nummeric one needs an explicit conversation + if (in_array($new_type, array('I', 'I2', 'I4', 'I8', 'N', 'F')) && + in_array($fld->type, array('varchar','char','text','bytea')) + ) { $copyflds[] = "to_number($fld->name,'S9999999999999D99')"; } else { - $copyflds[] = $fld->name; - } - // identify the sequence name and the fld its on - if ($fld->primary_key && $fld->has_default && - preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) { - $seq_name = $matches[1]; - $seq_fld = $fld->name; + // other column-type changes needs explicit decode, encode for bytea or cast otherwise + $new_actual_type = $this->actualType($new_type); + if (strtoupper($fld->type) != $new_actual_type) { + if ($new_actual_type == 'BYTEA' && $fld->type == 'text') { + $copyflds[] = "DECODE($fld->name, 'escape')"; + } elseif ($fld->type == 'bytea' && $new_actual_type == 'TEXT') { + $copyflds[] = "ENCODE($fld->name, 'escape')"; + } else { + $copyflds[] = "CAST($fld->name AS $new_actual_type)"; + } + } } + } else { + $copyflds[] = $fld->name; + } + // identify the sequence name and the fld its on + if ($fld->primary_key && $fld->has_default && + preg_match("/nextval\('([^']+)'::(text|regclass)\)/", $fld->default_value, $matches)) { + $seq_name = $matches[1]; + $seq_fld = $fld->name; } } - $copyflds = implode(', ',$copyflds); + $copyflds = implode(', ', $copyflds); $tempname = $tabname.'_tmp'; $aSql[] = 'BEGIN'; // we use a transaction, to make sure not to loose the content of the table $aSql[] = "SELECT * INTO TEMPORARY TABLE $tempname FROM $tabname"; - $aSql = array_merge($aSql,$this->DropTableSQL($tabname)); - $aSql = array_merge($aSql,$this->CreateTableSQL($tabname,$tableflds,$tableoptions)); + $aSql = array_merge($aSql,$this->dropTableSQL($tabname)); + $aSql = array_merge($aSql,$this->createTableSQL($tabname, $tableflds, $tableoptions)); $aSql[] = "INSERT INTO $tabname SELECT $copyflds FROM $tempname"; if ($seq_name && $seq_fld) { // if we have a sequence we need to set it again $seq_name = $tabname.'_'.$seq_fld.'_seq'; // has to be the name of the new implicit sequence - $aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname"; + $aSql[] = "SELECT setval('$seq_name', MAX($seq_fld)) FROM $tabname"; } $aSql[] = "DROP TABLE $tempname"; - // recreate the indexes, if they not contain one of the droped columns - foreach($this->MetaIndexes($tabname) as $idx_name => $idx_data) - { + // recreate the indexes, if they not contain one of the dropped columns + foreach($this->metaIndexes($tabname) as $idx_name => $idx_data) { if (substr($idx_name,-5) != '_pkey' && (!$dropflds || !count(array_intersect($dropflds,$idx_data['columns'])))) { - $aSql = array_merge($aSql,$this->CreateIndexSQL($idx_name,$tabname,$idx_data['columns'], - $idx_data['unique'] ? array('UNIQUE') : False)); + $aSql = array_merge($aSql,$this->createIndexSQL($idx_name, $tabname, $idx_data['columns'], + $idx_data['unique'] ? array('UNIQUE') : false)); } } $aSql[] = 'COMMIT'; return $aSql; } - function DropTableSQL($tabname) + function dropTableSQL($tabname) { - $sql = ADODB_DataDict::DropTableSQL($tabname); - - $drop_seq = $this->_DropAutoIncrement($tabname); - if ($drop_seq) $sql[] = $drop_seq; + $sql = ADODB_DataDict::dropTableSQL($tabname); + $drop_seq = $this->_dropAutoIncrement($tabname); + if ($drop_seq) { + $sql[] = $drop_seq; + } return $sql; } // return string must begin with space - function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) + function _createSuffix($fname, &$ftype, $fnotnull, $fdefault, $fautoinc, $fconstraint, $funsigned) { if ($fautoinc) { $ftype = 'SERIAL'; @@ -377,34 +411,34 @@ function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstrai return $suffix; } - // search for a sequece for the given table (asumes the seqence-name contains the table-name!) + // search for a sequence for the given table (asumes the seqence-name contains the table-name!) // if yes return sql to drop it // this is still necessary if postgres < 7.3 or the SERIAL was created on an earlier version!!! - function _DropAutoIncrement($tabname) + function _dropAutoIncrement($tabname) { $tabname = $this->connection->quote('%'.$tabname.'%'); - $seq = $this->connection->GetOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'"); + $seq = $this->connection->getOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'"); - // check if a tables depends on the sequenz and it therefor cant and dont need to be droped separatly - if (!$seq || $this->connection->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) { - return False; + // check if a tables depends on the sequence and it therefore can't and don't need to be dropped separately + if (!$seq || $this->connection->getOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) { + return false; } return "DROP SEQUENCE ".$seq; } - function RenameTableSQL($tabname,$newname) + function renameTableSQL($tabname, $newname) { if (!empty($this->schema)) { - $rename_from = $this->TableName($tabname); + $rename_from = $this->tableName($tabname); $schema_save = $this->schema; $this->schema = false; - $rename_to = $this->TableName($newname); + $rename_to = $this->tableName($newname); $this->schema = $schema_save; return array (sprintf($this->renameTable, $rename_from, $rename_to)); } - return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname))); + return array (sprintf($this->renameTable, $this->tableName($tabname), $this->tableName($newname))); } /* @@ -440,17 +474,18 @@ function RenameTableSQL($tabname,$newname) [ USING acc_method ] ( func_name( column [, ... ]) [ ops_name ] ) [ WHERE predicate ] */ - function _IndexSQL($idxname, $tabname, $flds, $idxoptions) + function _indexSQL($idxname, $tabname, $flds, $idxoptions) { $sql = array(); if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) { $sql[] = sprintf ($this->dropIndex, $idxname, $tabname); - if ( isset($idxoptions['DROP']) ) + if ( isset($idxoptions['DROP']) ) { return $sql; + } } - if ( empty ($flds) ) { + if (empty($flds)) { return $sql; } @@ -458,27 +493,92 @@ function _IndexSQL($idxname, $tabname, $flds, $idxoptions) $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' '; - if (isset($idxoptions['HASH'])) + if (isset($idxoptions['HASH'])) { $s .= 'USING HASH '; + } - if ( isset($idxoptions[$this->upperName]) ) + if (isset($idxoptions[$this->upperName])) { $s .= $idxoptions[$this->upperName]; + } - if ( is_array($flds) ) - $flds = implode(', ',$flds); + if (is_array($flds)) { + $flds = implode(', ', $flds); + } $s .= '(' . $flds . ')'; $sql[] = $s; return $sql; } - function _GetSize($ftype, $ty, $fsize, $fprec) + function _getSize($ftype, $ty, $fsize, $fprec, $options=false) { if (strlen($fsize) && $ty != 'X' && $ty != 'B' && $ty != 'I' && strpos($ftype,'(') === false) { $ftype .= "(".$fsize; if (strlen($fprec)) $ftype .= ",".$fprec; $ftype .= ')'; } + + /* + * Handle additional options + */ + if (is_array($options)) { + foreach($options as $type=>$value) { + switch ($type) { + case 'ENUM': + $ftype .= '(' . $value . ')'; + break; + default: + } + } + } return $ftype; } -} + + function changeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false) + { + global $ADODB_FETCH_MODE; + parent::changeTableSQL($tablename, $flds); + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; + if ($this->connection->fetchMode !== false) { + $savem = $this->connection->setFetchMode(false); + } + + // check table exists + $save_handler = $this->connection->raiseErrorFn; + $this->connection->raiseErrorFn = ''; + $cols = $this->metaColumns($tablename); + $this->connection->raiseErrorFn = $save_handler; + + if (isset($savem)) { + $this->connection->setFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + + $sqlResult=array(); + if ( empty($cols)) { + $sqlResult=$this->createTableSQL($tablename, $flds, $tableoptions); + } else { + $sqlResultAdd = $this->addColumnSQL($tablename, $flds); + $sqlResultAlter = $this->alterColumnSQL($tablename, $flds, '', $tableoptions); + $sqlResult = array_merge((array)$sqlResultAdd, (array)$sqlResultAlter); + + if ($dropOldFlds) { + // already exists, alter table instead + list($lines,$pkey,$idxs) = $this->_genFields($flds); + // genfields can return FALSE at times + if ($lines == null) { + $lines = array(); + } + $alter = 'ALTER TABLE ' . $this->tableName($tablename); + foreach ( $cols as $id => $v ) { + if ( !isset($lines[$id]) ) { + $sqlResult[] = $alter . $this->dropCol . ' ' . $v->name; + } + } + } + + } + return $sqlResult; + } +} // end class diff --git a/www/include/adodb5/datadict/datadict-sapdb.inc.php b/www/include/adodb/datadict/datadict-sapdb.inc.php similarity index 70% rename from www/include/adodb5/datadict/datadict-sapdb.inc.php rename to www/include/adodb/datadict/datadict-sapdb.inc.php index fbf931c7..c469800f 100644 --- a/www/include/adodb5/datadict/datadict-sapdb.inc.php +++ b/www/include/adodb/datadict/datadict-sapdb.inc.php @@ -1,17 +1,23 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch($meta) { case 'C': return 'VARCHAR'; case 'XL': @@ -59,6 +74,12 @@ function MetaType($t,$len=-1,$fieldobj=false) $t = $fieldobj->type; $len = $fieldobj->max_length; } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + static $maxdb_type2adodb = array( 'VARCHAR' => 'C', 'CHARACTER' => 'C', @@ -71,7 +92,7 @@ function MetaType($t,$len=-1,$fieldobj=false) 'FLOAT' => 'F', 'FIXED' => 'N', ); - $type = isset($maxdb_type2adodb[$t]) ? $maxdb_type2adodb[$t] : 'C'; + $type = isset($maxdb_type2adodb[$t]) ? $maxdb_type2adodb[$t] : ADODB_DEFAULT_METATYPE; // convert integer-types simulated with fixed back to integer if ($t == 'FIXED' && !$fieldobj->scale && ($len == 20 || $len == 3)) { diff --git a/www/include/adodb5/datadict/datadict-sqlite.inc.php b/www/include/adodb/datadict/datadict-sqlite.inc.php similarity index 65% rename from www/include/adodb5/datadict/datadict-sqlite.inc.php rename to www/include/adodb/datadict/datadict-sqlite.inc.php index 86b1b047..d565f887 100644 --- a/www/include/adodb5/datadict/datadict-sqlite.inc.php +++ b/www/include/adodb/datadict/datadict-sqlite.inc.php @@ -1,18 +1,23 @@ connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch(strtoupper($meta)) { case 'C': return 'VARCHAR'; // TEXT , TEXT affinity case 'XL':return 'LONGTEXT'; // TEXT , TEXT affinity @@ -58,7 +74,7 @@ function ActualType($meta) } // return string must begin with space - function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) + function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) { $suffix = ''; if ($funsigned) $suffix .= ' UNSIGNED'; diff --git a/www/include/adodb5/datadict/datadict-sybase.inc.php b/www/include/adodb/datadict/datadict-sybase.inc.php similarity index 82% rename from www/include/adodb5/datadict/datadict-sybase.inc.php rename to www/include/adodb/datadict/datadict-sybase.inc.php index d4e5f053..d6573dfa 100644 --- a/www/include/adodb5/datadict/datadict-sybase.inc.php +++ b/www/include/adodb/datadict/datadict-sybase.inc.php @@ -1,16 +1,23 @@ max_length; } + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + $len = -1; // mysql max_length is not accurate - switch (strtoupper($t)) { + + switch ($t) { + case 'INT': case 'INTEGER': return 'I'; @@ -46,6 +60,15 @@ function MetaType($t,$len=-1,$fieldobj=false) function ActualType($meta) { + $meta = strtoupper($meta); + + /* + * Add support for custom meta types. We do this + * first, that allows us to override existing types + */ + if (isset($this->connection->customMetaTypes[$meta])) + return $this->connection->customMetaTypes[$meta]['actual']; + switch(strtoupper($meta)) { case 'C': return 'VARCHAR'; case 'XL': diff --git a/www/include/adodb/docs/README.md b/www/include/adodb/docs/README.md new file mode 100644 index 00000000..aefdc884 --- /dev/null +++ b/www/include/adodb/docs/README.md @@ -0,0 +1,17 @@ +# ADOdb Documentation + +ADOdb documentation is available in the following locations: + +- [Online](https://adodb.org/) +- [Download](https://sourceforge.net/projects/adodb/files/Documentation/) for offline use + +## Legacy documentation + +The old HTML files are available in +[GitHub](https://github.com/ADOdb/ADOdb/tree/8b8133771ecbe9c95e57abbe5dc3757f0226bfcd/docs), +or in the release zip/tarballs for version 5.20 and before on +[Sourceforge](https://sourceforge.net/projects/adodb/files/adodb-php5-only/). + +## Changelog + +The full historical [Changelog](changelog.md) is available on GitHub. diff --git a/www/include/adodb/docs/adodb.gif b/www/include/adodb/docs/adodb.gif new file mode 100644 index 00000000..c5e8dfc6 Binary files /dev/null and b/www/include/adodb/docs/adodb.gif differ diff --git a/www/include/adodb/docs/adodb2.gif b/www/include/adodb/docs/adodb2.gif new file mode 100644 index 00000000..f12ae203 Binary files /dev/null and b/www/include/adodb/docs/adodb2.gif differ diff --git a/www/include/adodb/docs/changelog.md b/www/include/adodb/docs/changelog.md new file mode 100644 index 00000000..8c2adfa5 --- /dev/null +++ b/www/include/adodb/docs/changelog.md @@ -0,0 +1,1315 @@ +# ADOdb Changelog - v5.x + +All notable changes to this project will be documented in this file. +As of version 5.20.1, its format is based on +[Keep a Changelog](https://keepachangelog.com/). + +This project adheres to the [Semantic Versioning](https://semver.org/) +specification, since version 5.20.0. + +Older changelogs: +[v4.x](changelog_v4.x.md), +[v3.x](changelog_v3.x.md), +[v2.x](changelog_v2.x.md). + +-------------------------------------------------------------------------------- + +## [5.22.2] - 2022-05-08 + +### Fixed + +- mssql: Automatic conversion of false to array is deprecated in PHP 8.1 + [#829](https://github.com/ADOdb/ADOdb/issues/829) +- mysql: Affected_Rows() not returning correct value + [#820](https://github.com/ADOdb/ADOdb/issues/820) +- mysql: uncaught ValueError exception calling execute() with an empty array + [#832](https://github.com/ADOdb/ADOdb/issues/832) +- pgsql: Affected_Rows() always returns false on PHP 8.1 + [#833](https://github.com/ADOdb/ADOdb/issues/833) + + +## [5.22.1] - 2022-03-30 + +### Removed + +- Legacy mysql, mysqlpo and mysqlt drivers + [#804](https://github.com/ADOdb/ADOdb/issues/804) + +### Fixed + +- firebird: undefined offset PHP notice in _fetchField() + [#808](https://github.com/ADOdb/ADOdb/issues/808) +- firebird: PHP deprecation warning in _blobDecode() + [#811](https://github.com/ADOdb/ADOdb/issues/811) +- firebird: PHP notice when executing query with empty array + [#812](https://github.com/ADOdb/ADOdb/issues/812) +- firebird: undefined array key with uppercase columns + [#813](https://github.com/ADOdb/ADOdb/issues/813) +- mysql: regression on setConnectionParameter() + [#803](https://github.com/ADOdb/ADOdb/issues/803) +- mysql: regression on bulk binding + [#806](https://github.com/ADOdb/ADOdb/issues/806) +- oci8: fix PHP 8.1 array deprecation warning + [#817](https://github.com/ADOdb/ADOdb/issues/817) +- memcache: weighted servers not connecting + [#807](https://github.com/ADOdb/ADOdb/issues/807) +- memcache: $memCacheCompress option ignored by memcached + [#823](https://github.com/ADOdb/ADOdb/issues/823) +- memcache: use default port in server controller template + [#824](https://github.com/ADOdb/ADOdb/issues/824) +- xml PHP Notice in dbData::create() + [#822](https://github.com/ADOdb/ADOdb/issues/822) + + +## [5.22.0] - 2022-02-08 + +### Added + +- Support for custom MetaTypes, e.g. JSON or GEOMETRY + [#602](https://github.com/ADOdb/ADOdb/issues/602) + [#626](https://github.com/ADOdb/ADOdb/issues/626) + [#649](https://github.com/ADOdb/ADOdb/issues/649) +- Use of weighted server groups with Memcached + [#676](https://github.com/ADOdb/ADOdb/issues/676) +- mssql: implement offsetDate() method + [#698](https://github.com/ADOdb/ADOdb/issues/698) +- oci8: new ADOConnection::releaseStatement() method + [#770](https://github.com/ADOdb/ADOdb/issues/770) +- sqlite3 performance monitor stub + [#661](https://github.com/ADOdb/ADOdb/issues/661) +- sqlite: support blob handling + [#702](https://github.com/ADOdb/ADOdb/issues/702) + +### Changed + +- firebird: complete overhaul to support latest PHP drivers + [#710](https://github.com/ADOdb/ADOdb/issues/710) +- mssql: Refactor _fetchField() method + [#725](https://github.com/ADOdb/ADOdb/issues/725) +- mysql: Support bound variable statements + [#655](https://github.com/ADOdb/ADOdb/issues/655) +- pgsql: missing standard datatypes + [#782](https://github.com/ADOdb/ADOdb/issues/782) +- xml: add field comments + [#732](https://github.com/ADOdb/ADOdb/issues/732) +- loadbalancer: support calling a function upon connection + [#784](https://github.com/ADOdb/ADOdb/issues/784) +- Code cleanup: PHPDoc, code style, whitespace, PHPStan errors, etc. + [#774](https://github.com/ADOdb/ADOdb/issues/774) + +### Deprecated + +- Compatibility with PHP < 7.2 + [#797](https://github.com/ADOdb/ADOdb/issues/797) +- Database Replication add-on + [#780](https://github.com/ADOdb/ADOdb/issues/780) + +### Removed + +- Compatibility with PHP 5.x + [#797](https://github.com/ADOdb/ADOdb/issues/797) +- Transpose() function and assorted sub-functions + [#586](https://github.com/ADOdb/ADOdb/issues/586) +- "proxy" server and client scripts + [#680](https://github.com/ADOdb/ADOdb/issues/680) + +### Fixed + +- metaIndexes does not return primary key correctly + [#656](https://github.com/ADOdb/ADOdb/issues/656) +- Uniformize ADOrecordSet::__construct() parameters + [#772](https://github.com/ADOdb/ADOdb/issues/772) +- Prevent PHP warning when throwing exception with P1 or P2 parameter as array + [#783](https://github.com/ADOdb/ADOdb/issues/783) +- $dsnType property not defined before use + [#789](https://github.com/ADOdb/ADOdb/issues/789) +- mysql: Update socket and client flags for ssl + [#622](https://github.com/ADOdb/ADOdb/issues/622) +- mysql: Handle tables that are reserved words +- [#759](https://github.com/ADOdb/ADOdb/issues/759) +- pgsql: prevent AddColumnSQL() from updating existing values when default is changed + [#635](https://github.com/ADOdb/ADOdb/issues/635) +- pgsql: Refactored _fixblobs() and replaced it with new _prepFields() method + [#767](https://github.com/ADOdb/ADOdb/issues/767) +- pgsql: Incorrect pg_execute() api calls + [#768](https://github.com/ADOdb/ADOdb/issues/768) +- pgsql: blobDelete() could silently fail with multiple connections + [#769](https://github.com/ADOdb/ADOdb/issues/769) +- pdo: ensure bound statements are correctly formatted + [#695](https://github.com/ADOdb/ADOdb/issues/695) +- perf: fix invalid SQL + [#753](https://github.com/ADOdb/ADOdb/issues/753) +- sqlite: driver returns incorrect time when using $sysTimeStamp + [#697](https://github.com/ADOdb/ADOdb/issues/697) +- sqlite: undeclared connection property + [#713](https://github.com/ADOdb/ADOdb/issues/713) +- xml: Undefined array key error + [#775](https://github.com/ADOdb/ADOdb/issues/775) +- memcache: library does not initialize correctly + [#788](https://github.com/ADOdb/ADOdb/issues/788) + + +## [5.21.4] and [5.20.21] - 2022-01-22 + +### Fixed + +- Methods return E_DEPRECATED with PHP8.1 + [#771](https://github.com/ADOdb/ADOdb/issues/771) + +### Security + +- pgsql: authentication bypass in connect functions (CVE-2021-3850) + [#793](https://github.com/ADOdb/ADOdb/issues/793) + + +## [5.21.3] - 2021-10-31 + +### Fixed + +- core: Ensure temp $ADODB_COUNTRECS changes really are temporary + [#761](https://github.com/ADOdb/ADOdb/issues/761) +- mysqli: force error reporting mode to OFF (PHP 8.1 compatibility) + [#755](https://github.com/ADOdb/ADOdb/issues/755) +- pdo: fix metaIndexes declaration to match parent + [#717](https://github.com/ADOdb/ADOdb/issues/717) + + +## [5.21.2] - 2021-08-22 + +### Fixed + +- Fix syntax error in toexport.inc.php + [#749](https://github.com/ADOdb/ADOdb/issues/749) +- pgsql: fix fetchField() parameter naming + [#752](https://github.com/ADOdb/ADOdb/issues/752) + + +## [5.21.1] - 2021-08-15 + +### Changed + +- Standardized source code file headers + [#728](https://github.com/ADOdb/ADOdb/issues/728) +- Code cleanup: PHPDoc, code style, whitespace, etc. + [#691](https://github.com/ADOdb/ADOdb/issues/691) + (and others) + +### Fixed + +- Caching in FieldTypesArray() causes problems + [#687](https://github.com/ADOdb/ADOdb/issues/687) +- setConnectionParameter() method should not be final + [#694](https://github.com/ADOdb/ADOdb/issues/694) +- Final private methods throw warning (PHP 8) + [#711](https://github.com/ADOdb/ADOdb/issues/711) +- Fix record count when executing SQL with subqueries + [#715](https://github.com/ADOdb/ADOdb/issues/715) +- Incorrect handling of $ADODB_QUOTE_FIELDNAMES = true + [#721](https://github.com/ADOdb/ADOdb/issues/721) +- array to string conversion in adodb_debug_execute() + [#737](https://github.com/ADOdb/ADOdb/issues/737) +- db2: fix columns always returned in lowercase + [#719](https://github.com/ADOdb/ADOdb/issues/719) +- PDO: Bind parameters fail if sent in associative array + [#705](https://github.com/ADOdb/ADOdb/issues/705) +- mssql: _insertid() doesn't work anymore + [#692](https://github.com/ADOdb/ADOdb/issues/692) +- mssql: PHP warnings in dropColumnSQL() + [#696](https://github.com/ADOdb/ADOdb/issues/696) +- mssql: duplicate key in SQLDate convert formats + [#748](https://github.com/ADOdb/ADOdb/issues/748) +- mysql: affected_rows() returns number instead of false + [#604](https://github.com/ADOdb/ADOdb/issues/604) +- mysql: TypeError when calling get/setChangeSet on unset connection (PHP 8) + [#686](https://github.com/ADOdb/ADOdb/issues/686) +- mysql: TypeError when calling setConnectionParameter() with non-numeric value (PHP 8) + [#693](https://github.com/ADOdb/ADOdb/issues/693) +- pdo: Affected_Rows() throws Notice and returns 0 when rows affected + [#733](https://github.com/ADOdb/ADOdb/issues/733) +- pgsql: sub-selects require aliasing + [#736](https://github.com/ADOdb/ADOdb/issues/736) +- xml: Invalid SQL in extractSchema() + [#707](https://github.com/ADOdb/ADOdb/issues/707) + +### Removed + +- Use of _ADODB_COUNT as workaround for counting in complex queries + (introduced in [#88](https://github.com/ADOdb/ADOdb/issues/88)) + [#715](https://github.com/ADOdb/ADOdb/issues/715) + + + +## [5.21.0] - 2021-02-27 + +### Fixed + +- pgsql: param(0) returns invalid `$0` placeholder + [#682](https://github.com/ADOdb/ADOdb/issues/682) + + +## [5.21.0-rc.1] - 2021-02-02 + +Includes all fixes from 5.20.20. + +### Added + +- Explicit support for PHP 8 with Composer + +### Fixed + +- Replace adodb_str_replace() calls with str_replace() + [#646](https://github.com/ADOdb/ADOdb/issues/646) +- pgsql: override ADODB_DataDict::ChangeTableSQL() + [#634](https://github.com/ADOdb/ADOdb/issues/634) +- sqlite: fix metaIndexes does not return primary key correctly + [#656](https://github.com/ADOdb/ADOdb/issues/656) +- xmlschema: PHP8 compatibility + [#658](https://github.com/ADOdb/ADOdb/issues/658) + +### Removed + +- Support for PHP < 5.5.9 + [#654](https://github.com/ADOdb/ADOdb/issues/654) +- XML-RPC Interface + [#671](https://github.com/ADOdb/ADOdb/issues/671) +- Magic quotes related code + [#674](https://github.com/ADOdb/ADOdb/issues/674) + + +## [5.20.20] - 2021-01-31 + +### Fixed + +- Fix usage of get_magic_* functions + [#619](https://github.com/ADOdb/ADOdb/issues/619) + [#657](https://github.com/ADOdb/ADOdb/issues/657) +- Fix PHP warning in _rs2rs() function + [#679](https://github.com/ADOdb/ADOdb/issues/679) +- pdo: Fix Fatal error in _query() + [#666](https://github.com/ADOdb/ADOdb/issues/666) +- pdo: Fix undefined variable + [#678](https://github.com/ADOdb/ADOdb/issues/678) +- pgsql: Fix Fatal error in _close() method (PHP8) + [#666](https://github.com/ADOdb/ADOdb/issues/666) +- pgsql: fix deprecated function aliases (PHP8) + [#667](https://github.com/ADOdb/ADOdb/issues/667) +- text: fix Cannot pass parameter by reference + [#668](https://github.com/ADOdb/ADOdb/issues/668) + + +## [5.21.0-beta.1] - 2020-12-20 + +Includes all fixes from 5.20.19. + +### Added + +- adodb: New helper methods: day(), month(), year() + [#225](https://github.com/ADOdb/ADOdb/issues/225) +- adodb: add Occitan ([#285](https://github.com/ADOdb/ADOdb/issues/285)) + and Indonesian ([#293](https://github.com/ADOdb/ADOdb/issues/293)) translations. +- adodb: add control over BLOB data dictionary feature (NOT NULL, DEFAULT) + [#292](https://github.com/ADOdb/ADOdb/issues/292) + [#478](https://github.com/ADOdb/ADOdb/issues/478) +- mssql: support Windows authentication + [#353](https://github.com/ADOdb/ADOdb/issues/353) +- mysqli: support SSL connections + [#415](https://github.com/ADOdb/ADOdb/issues/415) +- pdo/dblib: new driver + [#496](https://github.com/ADOdb/ADOdb/issues/496) +- pdo/firebird: new driver + [#378](https://github.com/ADOdb/ADOdb/issues/378) +- loadbalancer: read/write splitting and load balancing across multiple connections, thanks to Mike Benoit + [#111](https://github.com/ADOdb/ADOdb/issues/111) + +### Changed + +- adodb: addColumnSQL datadict function now supports ENUM data types + [#26](https://github.com/ADOdb/ADOdb/issues/26) +- adodb: introduce user-defined default Metatype + [#165](https://github.com/ADOdb/ADOdb/issues/165) +- adodb: AutoExecute validates empty fields array + [#154](https://github.com/ADOdb/ADOdb/issues/154) +- adodb: Add new value defaulting mode for getInsertSQL() + [#214](https://github.com/ADOdb/ADOdb/issues/214) +- adodb: Added portable substring method + [#219](https://github.com/ADOdb/ADOdb/issues/219) +- adodb: Optimize FieldTypesArray with static variable + [#367](https://github.com/ADOdb/ADOdb/issues/367) +- adodb: Allow output handler to be callable + [#312](https://github.com/ADOdb/ADOdb/issues/312) +- adodb-time: Add 'W' (week of year) format support in adodb_date() + [#223](https://github.com/ADOdb/ADOdb/issues/223) +- db2: full driver rewrite + [#442](https://github.com/ADOdb/ADOdb/issues/442) +- firebird: updated driver, thanks to Lester Caine + [#201](https://github.com/ADOdb/ADOdb/issues/201) +- mssql: Add Convert on SQLDate Method + [#304](https://github.com/ADOdb/ADOdb/issues/304) +- mssql: support alternative port in connect + [#314](https://github.com/ADOdb/ADOdb/issues/314) +- mssql: MetaForeignKeys() not returning all FKs + [#486](https://github.com/ADOdb/ADOdb/issues/486) +- mssql: support for T-SQL-style square brackets + [#246](https://github.com/ADOdb/ADOdb/issues/246) +- mssqlnative: add support for 'l' (day of week) format in sqlDate() + [#232](https://github.com/ADOdb/ADOdb/issues/232) +- mssqlnative: support metaProcedures() method + [#578](https://github.com/ADOdb/ADOdb/issues/578) +- setConnectionParameter() now allows multiple parameters with the same key value + [#187](https://github.com/ADOdb/ADOdb/issues/187) +- mysqli: Insert_ID() did not return correct value after executing stored procedure + [#166](https://github.com/ADOdb/ADOdb/issues/166) +- mysqli: method failed if $associative set true + [#181](https://github.com/ADOdb/ADOdb/issues/181) +- oci8: provide option to create compact trigger/sequence names + [#565](https://github.com/ADOdb/ADOdb/issues/565) +- odbc/mssql: fix null strings concatenation issue with SQL server 2012 + [#148](https://github.com/ADOdb/ADOdb/issues/148) +- odbc/mssql: add missing Concat() method + [#402](https://github.com/ADOdb/ADOdb/issues/402) +- pdo: add setConnectionParameter support + [#247](https://github.com/ADOdb/ADOdb/issues/247) +- pdo: add meta extension points + [#475](https://github.com/ADOdb/ADOdb/issues/475) +- pdo/mysql: add genID() and createSequence() support + [#465](https://github.com/ADOdb/ADOdb/issues/465) +- pdo/pgsql: Add support for transactions + [#363](https://github.com/ADOdb/ADOdb/issues/363) +- pdo/sqlsrv: add SetTransactionMode() method + [#362](https://github.com/ADOdb/ADOdb/issues/362) +- pgsql: optimize version check + [#334](https://github.com/ADOdb/ADOdb/issues/334) +- pgsql: use postgres9 driver by default + [#474](https://github.com/ADOdb/ADOdb/issues/474) +- sqlite: Fix Metataypes mapping + [#177](https://github.com/ADOdb/ADOdb/issues/177) +- sqlite: driver did not support metaForeignKeys + [#179](https://github.com/ADOdb/ADOdb/issues/179) +- memcache: add support for memcached PECL library + [#322](https://github.com/ADOdb/ADOdb/issues/322) +- xml: support table 'opt' attribute with mysqli + [#267](https://github.com/ADOdb/ADOdb/issues/267) +- xml: add support for 'DESCR' tags for tables/fields + [#265](https://github.com/ADOdb/ADOdb/issues/265) + +### Deprecated + +- mysqli: Deprecate $optionFlags property in favor of standard setConnectionParameter() method + [#188](https://github.com/ADOdb/ADOdb/issues/188) +- proxy: the client driver and server.php script are deprecated + [#444](https://github.com/ADOdb/ADOdb/issues/444) + +### Removed + +- adodb: Remove references to obsolete ADOdb Extension + [#270](https://github.com/ADOdb/ADOdb/issues/270) +- adodb: Remove unneeded ADODB_str_replace function + [#582](https://github.com/ADOdb/ADOdb/issues/582) +- adodb: Remove useless PHP 4 and 5 version checks + [#583](https://github.com/ADOdb/ADOdb/issues/583) + [#584](https://github.com/ADOdb/ADOdb/issues/584) +- adodb: replace _array_change_key_case() by internal PHP function + [#587](https://github.com/ADOdb/ADOdb/issues/587) + +### Fixed + +- adodb: Remove useless constructors + [#171](https://github.com/ADOdb/ADOdb/issues/171) +- adodb: Define default constructor in ADOConnection base class + [#172](https://github.com/ADOdb/ADOdb/issues/172) +- adodb: Reimplement base methods charMax() and textMax() + [#183](https://github.com/ADOdb/ADOdb/issues/183) + [#220](https://github.com/ADOdb/ADOdb/issues/220) +- adodb: fix getAssoc() + [#189](https://github.com/ADOdb/ADOdb/issues/189) + [#198](https://github.com/ADOdb/ADOdb/issues/198) + [#204](https://github.com/ADOdb/ADOdb/issues/204) +- adodb: Improve array identification in ADOrecordset::getAssoc() + [#101](https://github.com/ADOdb/ADOdb/issues/101) +- adodb: MetaColumns() consistently returns Actual Type by default in all drivers + [#184](https://github.com/ADOdb/ADOdb/issues/184) + [#133](https://github.com/ADOdb/ADOdb/issues/133) +- adodb: getAssoc() should not change case of result set's outermost key + [#335](https://github.com/ADOdb/ADOdb/issues/335) +- adodb: getAssoc() fix fetch mode + [#350](https://github.com/ADOdb/ADOdb/issues/350) +- adodb: Replace each() with foreach (PHP 7.2 compatibility) + [#373](https://github.com/ADOdb/ADOdb/issues/373) +- adodb: fix ADORecordSet constructor signature + [#278](https://github.com/ADOdb/ADOdb/issues/278) +- adodb: support use of spaces and reserved keywords in replace function + [#390](https://github.com/ADOdb/ADOdb/issues/390) +- adodb: fix adodb_strip_order_by() to only remove the last order by statement + [#549](https://github.com/ADOdb/ADOdb/issues/549) +- adodb: fix field names quoting when setting value to null + [#572](https://github.com/ADOdb/ADOdb/issues/572) +- adodb: fix getAssoc returning key as value column with ADODB_FETCH_BOTH mode + [#600](https://github.com/ADOdb/ADOdb/issues/600) +- adodb-time: Fix 'Q' (quarter of year) format in adodb_date() + [#222](https://github.com/ADOdb/ADOdb/issues/222) +- active record: honor column and table name quoting + [#309](https://github.com/ADOdb/ADOdb/issues/309) +- db2: fix ChangeTableSQL() signature + [#338](https://github.com/ADOdb/ADOdb/issues/338) +- mssqlnative: Query not returning id + [#185](https://github.com/ADOdb/ADOdb/issues/185) +- mssqlnative: fix invalid return value for ErrorNo() + [#298](https://github.com/ADOdb/ADOdb/issues/298) +- mssqlnative: ensure that the bind array is numeric + [#336](https://github.com/ADOdb/ADOdb/issues/336) +- mssqlnative: fix crash with driver version 5.6 on queries returning no data + [#492](https://github.com/ADOdb/ADOdb/issues/492) +- mysql: prevent use of driver with PHP >= 7.0 + [#310](https://github.com/ADOdb/ADOdb/issues/310) +- mysqli: return fields as ADOFieldObject objects + [#175](https://github.com/ADOdb/ADOdb/issues/175) +- mysqli (perf): tables() method definition inconsistent with parent + [#435](https://github.com/ADOdb/ADOdb/issues/435) +- mysql: genId() not returning next sequence value + [#493](https://github.com/ADOdb/ADOdb/issues/493) +- oci8: fix syntax error preventing sequence creation + [#540](https://github.com/ADOdb/ADOdb/issues/540) +- oci8: remove use of curly braces in string offsets (deprecated in PHP 7.4) + [#570](https://github.com/ADOdb/ADOdb/issues/570) +- odbc: MetaColumns() can optionally be set to return MetaType for backwards compatibility + [#184](https://github.com/ADOdb/ADOdb/issues/184) +- pdo: allow loading of subclassed recordset + [#245](https://github.com/ADOdb/ADOdb/issues/245) +- pdo: fix PHP notice + [#248](https://github.com/ADOdb/ADOdb/issues/248) +- pdo: fix ADORecordSet class loading + [#250](https://github.com/ADOdb/ADOdb/issues/250) +- pdo/sqlsrv: fix fetchField() method + [#251](https://github.com/ADOdb/ADOdb/issues/251) + [#234](https://github.com/ADOdb/ADOdb/issues/234) +- pgsql: add CIDR data type to MetaType() + [#281](https://github.com/ADOdb/ADOdb/issues/281) +- pgsql: fix param number reset with param(false) + [#380](https://github.com/ADOdb/ADOdb/issues/380) +- pgsql: specialized casts for _recreate_copy_table() + [#207](https://github.com/ADOdb/ADOdb/issues/207) +- sqlite: _createSuffix is now compatible with parent + [#178](https://github.com/ADOdb/ADOdb/issues/178) +- sqlite: metaIndexes could not locate indexes on uppercase table name + [#176](https://github.com/ADOdb/ADOdb/issues/176) +- sqlite: metaIndexes() returns column as array instead of CSV + [#567](https://github.com/ADOdb/ADOdb/issues/567) +- session: string parameters for `assert` are deprecated in PHP 7.2 + [#438](https://github.com/ADOdb/ADOdb/issues/438) +- xml: fix invalid xmlschema03.dtd and descr tag in session schema XML + [#595](https://github.com/ADOdb/ADOdb/issues/595) + +### Security + +- adodb: prevent SQL injection in SelectLimit() + [#311](https://github.com/ADOdb/ADOdb/issues/311) +- session: add 'httponly' flag to cookie + [#190](https://github.com/ADOdb/ADOdb/issues/190) + + +## [5.20.19] - 2020-12-13 + +### Changed + +- PDO: support persistent connections + [#650](https://github.com/ADOdb/ADOdb/issues/650) +- mssql: connect to SQL Server database on a specified port + [#624](https://github.com/ADOdb/ADOdb/issues/624) + +### Fixed + +- DSN database connection with password containing a `#` fails + [#651](https://github.com/ADOdb/ADOdb/issues/651) +- Metacolumns returns wrong type for integer fields in MySQL 8 + [#642](https://github.com/ADOdb/ADOdb/issues/642) +- Uninitialized Variable access in mssqlnative ErrorNo() method + [#637](https://github.com/ADOdb/ADOdb/issues/637) + + +## [5.20.18] - 2020-06-28 + +### Fixed + +- mssql: Retrieve error messages early before connection closed + [#614](https://github.com/ADOdb/ADOdb/issues/614) + + +## [5.20.17] - 2020-03-31 + +### Fixed + +- core: fix PHP notice in ADOdb_Exception constructor when using transactions + [#601](https://github.com/ADOdb/ADOdb/issues/601) +- mssql: fix PHP notice due to uninitialized array with PHP 7.4 + [#608](https://github.com/ADOdb/ADOdb/issues/608) +- active record: Fix UpdateActiveTable failing with mixed case column names + [#610](https://github.com/ADOdb/ADOdb/issues/610) + + +## [5.20.16] - 2020-01-12 + +-### Fixed + + mssql: queries are not correctly closed + [#590](https://github.com/ADOdb/ADOdb/issues/590) + + +## [5.20.15] - 2019-11-24 + +### Fixed + +- core: remove unnecessary srand() calls + [#532](https://github.com/ADOdb/ADOdb/issues/532) +- core: Fix getMenu with ADODB_FETCH_BOTH + [#482](https://github.com/ADOdb/ADOdb/issues/482) +- core: code cleanup for getMenu and related functions + [#563](https://github.com/ADOdb/ADOdb/issues/563) +- pgsql: stop using obsolete pg_attrdef.adsrc column + [#562](https://github.com/ADOdb/ADOdb/issues/562) +- pdo/mysql: remove extraneous comma in $fmtTimeStamp + [#531](https://github.com/ADOdb/ADOdb/issues/531) +- active record: Use ADODB_ASSOC_CASE constant + [#536](https://github.com/ADOdb/ADOdb/issues/536) +- session: Remove session_module_name('user') calls (PHP 7.2 compatibility) + [#449](https://github.com/ADOdb/ADOdb/issues/449) +- PHP 7.4 compatibility: fix deprecated usage of join() + [#547](https://github.com/ADOdb/ADOdb/issues/547) + + +## [5.20.14] - 2019-01-06 + +### Fixed + +- core: Fix support for getMenu with ADODB_FETCH_ASSOC + [#460](https://github.com/ADOdb/ADOdb/issues/460) +- perf/mysql: fix tables() function incompatible with parent + [#435](https://github.com/ADOdb/ADOdb/issues/435) +- perf/mysql: fix error when logging slow queries + [#463](https://github.com/ADOdb/ADOdb/issues/463) + +### Security + +- security: Denial of service in adodb_date() + [#467](https://github.com/ADOdb/ADOdb/issues/467) + + +## [5.20.13] - 2018-08-06 + +### Fixed + +- core: Fix query execution failures with mismatched quotes + [#420](https://github.com/ADOdb/ADOdb/issues/420) +- ldap: Fix connections using URIs + [#340](https://github.com/ADOdb/ADOdb/issues/340) +- mssql: Fix Time field format, allowing autoExecute() to inserting time + [#432](https://github.com/ADOdb/ADOdb/issues/432) +- mssql: Fix Insert_ID returning null with table name in brackets + [#313](https://github.com/ADOdb/ADOdb/issues/313) +- mssql: Fix count wrapper + [#423](https://github.com/ADOdb/ADOdb/issues/423) +- oci8: Fix prepared statements failure + [#318](https://github.com/ADOdb/ADOdb/issues/318) +- oci8po: Fix incorrect query parameter replacements + [#370](https://github.com/ADOdb/ADOdb/issues/370) +- pdo: fix PHP notice due to uninitialized variable + [#437](https://github.com/ADOdb/ADOdb/issues/437) + + +## [5.20.12] - 2018-03-30 + +### Fixed + +- adodb: PHP 7.2 compatibility + - Replace each() with foreach + [#373](https://github.com/ADOdb/ADOdb/issues/373) + - Replace deprecated create_function() calls + [#404](https://github.com/ADOdb/ADOdb/issues/404) + - Replace $php_errormsg with error_get_last() + [#405](https://github.com/ADOdb/ADOdb/issues/405) +- adodb: Don't call `dl()` when the function is disabled + [#406](https://github.com/ADOdb/ADOdb/issues/406) +- adodb: Don't bother with magic quotes when not available + [#407](https://github.com/ADOdb/ADOdb/issues/407) +- adodb: fix potential SQL injection vector in SelectLimit() + [#190](https://github.com/ADOdb/ADOdb/issues/190) + [#311](https://github.com/ADOdb/ADOdb/issues/311) + [#401](https://github.com/ADOdb/ADOdb/issues/401) + + +## [5.20.11] - Withdrawn + +This release has been withdrawn as it introduced a regression on PHP 5.x. +Please use version 5.20.12 or later. + + +## [5.20.10] - 2018-03-08 + +### Fixed + +- Fix year validation in adodb_validdate() + [#375](https://github.com/ADOdb/ADOdb/issues/375) +- Release db resource when closing connection + [#379](https://github.com/ADOdb/ADOdb/issues/379) +- Avoid full file path disclosure in ADOLoadCode() + [#389](https://github.com/ADOdb/ADOdb/issues/389) +- mssql: fix PHP warning in _adodb_getcount() + [#359](https://github.com/ADOdb/ADOdb/issues/359) +- mssql: string keys are not allowed in parameters arrays + [#316](https://github.com/ADOdb/ADOdb/issues/316) +- mysqli: fix PHP warning on DB connect + [#348](https://github.com/ADOdb/ADOdb/issues/348) +- pdo: fix auto-commit error in sqlsrv + [#347](https://github.com/ADOdb/ADOdb/issues/347) +- sybase: fix PHP Warning in _connect()/_pconnect + [#371](https://github.com/ADOdb/ADOdb/issues/371) + + +## [5.20.9] - 2016-12-21 + +### Fixed + +- mssql: fix syntax error in version matching regex + [#305](https://github.com/ADOdb/ADOdb/issues/305) + + +## [5.20.8] - 2016-12-17 + +### Fixed + +- mssql: support MSSQL Server 2016 and later + [#294](https://github.com/ADOdb/ADOdb/issues/294) +- mssql: fix Find() returning no results + [#298](https://github.com/ADOdb/ADOdb/issues/298) +- mssql: fix Sequence name forced to 'adodbseq' + [#295](https://github.com/ADOdb/ADOdb/issues/295), + [#300](https://github.com/ADOdb/ADOdb/issues/300) +- mssql: fix GenId() not returning next sequence value with SQL Server 2005/2008 + [#302](https://github.com/ADOdb/ADOdb/issues/302) +- mssql: fix drop/alter column with existing default constraint + [#290](https://github.com/ADOdb/ADOdb/issues/290) +- mssql: fix PHP notice in MetaColumns() + [#289](https://github.com/ADOdb/ADOdb/issues/289) +- oci8po: fix inconsistent variable binding in SelectLimit() + [#288](https://github.com/ADOdb/ADOdb/issues/288) +- oci8po: fix SelectLimit() with prepared statements + [#282](https://github.com/ADOdb/ADOdb/issues/282) + + +## [5.20.7] - 2016-09-20 + +### Fixed + +- oci8po: prevent segfault on PHP 7 + [#259](https://github.com/ADOdb/ADOdb/issues/259) +- pdo/mysql: Fix MetaTables() method + [#275](https://github.com/ADOdb/ADOdb/issues/275) + +### Security + +- security: Fix SQL injection in PDO drivers qstr() method (CVE-2016-7405) + [#226](https://github.com/ADOdb/ADOdb/issues/226) + + +## [5.20.6] - 2016-08-31 + +### Fixed + +- adodb: Exit with error/exception when the ADOdb Extension is loaded + [#269](https://github.com/ADOdb/ADOdb/issues/269) +- adodb: Fix truncated exception messages + [#273](https://github.com/ADOdb/ADOdb/issues/273) + +### Security + +- security: Fix XSS vulnerability in old test script (CVE-2016-4855) + [#274](https://github.com/ADOdb/ADOdb/issues/274) + +## [5.20.5] - 2016-08-10 + +### Fixed + +- adodb: Fix fatal error when connecting with missing extension + [#254](https://github.com/ADOdb/ADOdb/issues/254) +- adodb: Fix _adodb_getcount() + [#236](https://github.com/ADOdb/ADOdb/issues/236) +- mssql: Destructor fails if recordset already closed + [#268](https://github.com/ADOdb/ADOdb/issues/268) +- mssql: Use SQL server native data types if available + [#234](https://github.com/ADOdb/ADOdb/issues/234) +- mysqli: Fix PHP notice in _close() method + [#240](https://github.com/ADOdb/ADOdb/issues/240) +- pdo: Let driver handle SelectDB() and SQLDate() calls + [#242](https://github.com/ADOdb/ADOdb/issues/242) +- xml: Fix PHP strict warning + [#260](https://github.com/ADOdb/ADOdb/issues/260) +- xml: remove calls to 'unset($this)' (PHP 7.1 compatibility) + [#257](https://github.com/ADOdb/ADOdb/issues/257) + + +## [5.20.4] - 2016-03-31 + +### Fixed + +- adodb: Fix BulkBind() param count validation + [#199](https://github.com/ADOdb/ADOdb/issues/199) +- mysqli: fix PHP warning in recordset destructor + [#217](https://github.com/ADOdb/ADOdb/issues/217) +- mysqli: cast port number to int when connecting (PHP7 compatibility) + [#218](https://github.com/ADOdb/ADOdb/issues/218) + + +## [5.20.3] - 2016-01-01 + +### Fixed + +- mssql: PHP warning when closing recordset from destructor not fixed in v5.20.2 + [#180](https://github.com/ADOdb/ADOdb/issues/180) + + +## [5.20.2] - 2015-12-27 + +### Fixed + +- adodb: Remove a couple leftover PHP 4.x constructors (PHP7 compatibility) + [#139](https://github.com/ADOdb/ADOdb/issues/139) +- db2ora: Remove deprecated preg_replace '/e' flag (PHP7 compatibility) + [#168](https://github.com/ADOdb/ADOdb/issues/168) +- mysql: MoveNext() now respects ADODB_ASSOC_CASE + [#167](https://github.com/ADOdb/ADOdb/issues/167) +- mssql, mysql, informix: Avoid PHP warning when closing recordset from destructor + [#170](https://github.com/ADOdb/ADOdb/issues/170) + + +## [5.20.1] - 2015-12-06 + +### Fixed + +- adodb: Fix regression introduced in 5.20.0, causing a PHP Warning when + calling GetAssoc() on an empty recordset + [#162](https://github.com/ADOdb/ADOdb/issues/162) +- ADOConnection::Version() now handles SemVer + [#164](https://github.com/ADOdb/ADOdb/issues/164) + + +## [5.20.0] - 2015-11-28 + +### Added + +- adodb: new setConnectionParameter() method, + previously implemented in mssqlnative driver only + [#158](https://github.com/ADOdb/ADOdb/issues/158). +- pdo: new sqlsrv driver, thanks to MarcelTO + [#81](https://github.com/ADOdb/ADOdb/issues/81) +- adodb: support for pagination with complex queries, thanks to Mike Benoit + [#88](https://github.com/ADOdb/ADOdb/issues/88) +- pdo/mysql: New methods to make the driver behave more like mysql/mysqli, thanks to Andy Theuninck + [#40](https://github.com/ADOdb/ADOdb/issues/40) + +### Changed + +- adodb: Define DB_AUTOQUERY_* constants in main include file + [#49](https://github.com/ADOdb/ADOdb/issues/49) +- adodb: Add mssql's DATETIME2 type to ADOConnection::MetaType(), thanks to MarcelTO + [#80](https://github.com/ADOdb/ADOdb/issues/80) +- adodb: Initialize charset in ADOConnection::SetCharSet + [#39](https://github.com/ADOdb/ADOdb/issues/39) +- adodb: Parse port out of hostname if specified in connection parameters, thanks to Andy Theuninck + [#63](https://github.com/ADOdb/ADOdb/issues/63) +- adodb: Improve compatibility of ADORecordSet_empty, thanks to Sjan Evardsson + [#43](https://github.com/ADOdb/ADOdb/issues/43) +- mssqlnative: Use ADOConnection::outp instead of error_log + [#12](https://github.com/ADOdb/ADOdb/issues/12) + +### Fixed + +- adodb: Fix regression introduced in v5.19, causing queries to return empty rows + [#20](https://github.com/ADOdb/ADOdb/issues/20) + [#93](https://github.com/ADOdb/ADOdb/issues/93) + [#95](https://github.com/ADOdb/ADOdb/issues/95) +- adodb: Fix regression introduced in v5.19 in GetAssoc() with ADODB_FETCH_ASSOC mode and '0' as data + [#102](https://github.com/ADOdb/ADOdb/issues/102) +- adodb: AutoExecute correctly handles empty result set in case of updates + [#13](https://github.com/ADOdb/ADOdb/issues/13) +- adodb: Fix regex in Version() + [#16](https://github.com/ADOdb/ADOdb/issues/16) +- adodb: Align method signatures to definition in parent class ADODB_DataDict + [#31](https://github.com/ADOdb/ADOdb/issues/31) +- adodb: fix ADODB_Session::open() failing after successful ADONewConnection() call, thanks to Sjan Evardsson + [#44](https://github.com/ADOdb/ADOdb/issues/44) +- adodb: Only include memcache library once for PHPUnit 4.x, thanks to Alan Farquharson + [#74](https://github.com/ADOdb/ADOdb/issues/74) +- adodb: Move() returns false when given row is < 0, thanks to Mike Benoit. +- adodb: Fix inability to set values from 0 to null (and vice versa) with Active Record, thanks to Louis Johnson + [#71](https://github.com/ADOdb/ADOdb/issues/71) +- adodb: Fix PHP strict warning in ADODB_Active_Record::Reload(), thanks to Boštjan Žokš + [#75](https://github.com/ADOdb/ADOdb/issues/75) +- adodb: When flushing cache, initialize it if it is not set, thanks to Paul Haggart + [#57](https://github.com/ADOdb/ADOdb/issues/57) +- adodb: Improve documentation of fetch mode and assoc case +- adodb: Improve logic to build the assoc case bind array +- adodb: Strict-standards compliance for function names + [#18](https://github.com/ADOdb/ADOdb/issues/18) + [#142](https://github.com/ADOdb/ADOdb/issues/142) +- adodb: Remove old PHP 4.x constructors for compatibility with PHP 7 + [#139](https://github.com/ADOdb/ADOdb/issues/139) +- adodb: Fix incorrect handling of input array in Execute() + [#146](https://github.com/ADOdb/ADOdb/issues/146) +- adodb: Release Recordset when raising exception + [#143](https://github.com/ADOdb/ADOdb/issues/143) +- adodb-lib: Optimize query pagination, thanks to Mike Benoit + [#110](https://github.com/ADOdb/ADOdb/issues/110) +- memcache: use include_once() to avoid issues with PHPUnit. See PHPLens Issue No: 19489 +- mssql_n: Allow use of prepared statements with driver + [#22](https://github.com/ADOdb/ADOdb/issues/22) +- mssqlnative: fix failure on Insert_ID() if the insert statement contains a semicolon in a value string, thanks to sketule + [#96](https://github.com/ADOdb/ADOdb/issues/96) +- mssqlnative: Fix "invalid parameter was passed to sqlsrv_configure" error, thanks to Ray Morris + [#103](https://github.com/ADOdb/ADOdb/issues/103) +- mssqlnative: Fix insert_ID() failing if server returns more than 1 row, thanks to gitjti + [#41](https://github.com/ADOdb/ADOdb/issues/41) +- mysql: prevent race conditions when creating/dropping sequences, thanks to MikeB + [#28](https://github.com/ADOdb/ADOdb/issues/28) +- mysql: Fix adodb_strip_order_by() bug causing SQL error for subqueries with order/limit clause, thanks to MikeB. +- mysql: workaround for HHVM behavior, thanks to Mike Benoit. +- mysqli: Fix qstr() when called without an active connection + [#11](https://github.com/ADOdb/ADOdb/issues/11) +- oci8: Fix broken quoting of table name in AddColumnSQL and AlterColumnSQL, thanks to Andreas Fernandez + [#67](https://github.com/ADOdb/ADOdb/issues/67) +- oci8: Allow oci8 driver to use lowercase field names in assoc mode + [#21](https://github.com/ADOdb/ADOdb/issues/21) +- oci8po: Prevent replacement of '?' within strings, thanks to Mark Newnham + [#132](https://github.com/ADOdb/ADOdb/issues/132) +- pdo: Added missing property (fixes PHP notices) + [#56](https://github.com/ADOdb/ADOdb/issues/56) +- pdo: Align method signatures with parent class, thanks to Andy Theuninck + [#62](https://github.com/ADOdb/ADOdb/issues/62) +- postgres: Stop using legacy function aliases +- postgres: Fix AlterColumnSQL when updating multiple columns, thanks to Jouni Ahto + [#72](https://github.com/ADOdb/ADOdb/issues/72) +- postgres: Fix support for HHVM 3.6, thanks to Mike Benoit + [#87](https://github.com/ADOdb/ADOdb/issues/87) +- postgres: Noblob optimization, thanks to Mike Benoit + [#112](https://github.com/ADOdb/ADOdb/issues/112) +- postgres7: fix system warning in MetaColumns() with schema. See PHPLens Issue No: 19481 +- sqlite3: ServerInfo() now returns driver's version +- sqlite3: Fix wrong connection parameter in _connect(), thanks to diogotoscano + [#51](https://github.com/ADOdb/ADOdb/issues/51) +- sqlite3: Fix FetchField, thanks to diogotoscano + [#53](https://github.com/ADOdb/ADOdb/issues/53) +- sqlite3: Fix result-less SQL statements executed twice + [#99](https://github.com/ADOdb/ADOdb/issues/99) +- sqlite3: use -1 for _numOfRows + [#151](https://github.com/ADOdb/ADOdb/issues/151) +- xmlschema: Fix ExtractSchema() when given $prefix and $stripprefix parameters, thanks to peterdd + [#92](https://github.com/ADOdb/ADOdb/issues/92) +- Convert languages files to UTF-8, thanks to Marc-Etienne Vargenau + [#32](https://github.com/ADOdb/ADOdb/issues/32) + + +## 5.19 - 2014-04-23 + +**NOTE:** +This release suffers from a [known issue with Associative Fetch Mode](https://github.com/ADOdb/ADOdb/issues/20) +(i.e. when $ADODB_FETCH_MODE is set to ADODB_FETCH_ASSOC). +It causes recordsets to return empty strings (no data) when using some database drivers. +The problem has been reported on MSSQL, Interbase and Foxpro, but possibly affects +other database types as well; all drivers derived from the above are also impacted. + +- adodb: GetRowAssoc will return null as required. See PHPLens Issue No: 19289 +- adodb: Fix GetRowAssoc bug introduced in 5.17, causing function to return data from previous fetch for NULL fields. See PHPLens Issue No: 17539 +- adodb: GetAssoc will return a zero-based array when 2nd column is null. See https://sourceforge.net/p/adodb/bugs/130/ +- adodb: Execute no longer ignores single parameters evaluating to false. See https://sourceforge.net/p/adodb/patches/32/ +- adodb: Fix LIMIT 1 clause in subquery gets stripped off. See PHPLens Issue No: 17813 +- adodb-lib: Fix columns quoting bug. See https://sourceforge.net/p/adodb/bugs/127/ +- Added new ADODB_ASSOC_CASE_* constants. Thx to Damien Regad. +- sessions: changed lob handling to detect all variations of oci8 driver. +- ads: clear fields before fetching. See PHPLens Issue No: 17539 +- mssqlnative: fixed many FetchField compat issues. See PHPLens Issue No: 18464. Also date format changed to remove timezone. +- mssqlnative: Numerous fixes and improvements by Mark Newnham + - Driver supports SQL Server 2005, 2008 and 2012 + - Bigint data types mapped to I8 instead of I + - Reintroduced MetaColumns function + - On SQL Server 2012, makes use of new CREATE SEQUENCE statement + - FetchField caches metadata at initialization to improve performance + - etc. +- mssqlnative: Fix Insert ID on prepared statement, thanks to Mike Parks. See PHPLens Issue No: 19079 +- mssql: timestamp format changed to `Y-m-d\TH:i:s` (ISO 8601) to make them independent from DATEFORMAT setting, as recommended on + [Microsoft TechNet](http://technet.microsoft.com/en-us/library/ms180878%28v=sql.105%29.aspx#StringLiteralDateandTimeFormats). +- mysql/mysqli: Fix ability for MetaTables to filter by table name, broken since 5.15. See PHPLens Issue No: 19359 +- odbc: Fixed MetaTables and MetaPrimaryKeys definitions in odbc driver to match adoconnection class. +- odbc: clear fields before fetching. See PHPLens Issue No: 17539 +- oci8: GetRowAssoc now works in ADODB_FETCH_ASSOC fetch mode +- oci8: MetaType and MetaForeignKeys argument count are now strict-standards compliant +- oci8: Added trailing `;` on trigger creation for sequence fields, prevents occurence of ORA-24344 +- oci8quercus: new oci8 driver with support for quercus jdbc data types. +- pdo: Fixed concat recursion bug in 5.3. See PHPLens Issue No: 19285 +- pgsql: Default driver (postgres/pgsql) is now postgres8 +- pgsql: Fix output of BLOB (bytea) columns with PostgreSQL >= 9.0 +- pgsql: Fix handling of DEFAULT NULL columns in AlterColumnSQL +- pgsql: Fix mapping of error message to ADOdb error codes +- pgsql: Reset parameter number in Param() method when $name == false +- postgres8: New class/type with correct behavior for _insertid() + [#8](https://github.com/ADOdb/ADOdb/issues/8) +- postgres9: Fixed assoc problem. See PHPLens Issue No: 19296 +- sybase: Removed redundant sybase_connect() call in _connect() + [#3](https://github.com/ADOdb/ADOdb/issues/3) +- sybase: Allow connection on custom port + [#9](https://github.com/ADOdb/ADOdb/issues/9) +- sybase: Fix null values returned with ASSOC fetch mode + [#10](https://github.com/ADOdb/ADOdb/issues/10) +- Added Composer support + [#7](https://github.com/ADOdb/ADOdb/issues/7) + +## 5.18 - 2012-09-03 + +- datadict-postgres: Fixes bug in ALTER COL. See PHPLens Issue No: 19202. +- datadict-postgres: fixed bugs in MetaType() checking $fieldobj properties. +- GetRowAssoc did not work with null values. Bug in 5.17. +- postgres9: New driver to better support PostgreSQL 9. Thx Glenn Herteg and Cacti team. +- sqlite3: Modified to support php 5.4. Thx Günter Weber [built.development#googlemail.com] +- adodb: When fetch mode is ADODB_FETCH_ASSOC, and we execute `$db->GetAssoc("select 'a','0'");` we get an error. Fixed. See PHPLens Issue No: 19190 +- adodb: Caching directory permissions now configurable using global variable $ADODB_CACHE_PERMS. Default value is 0771. +- mysqli: SetCharSet() did not return true (success) or false (fail) correctly. Fixed. +- mysqli: changed dataProvider to 'mysql' so that MetaError and other shared functions will work. +- mssqlnative: Prepare() did not work previously. Now calling Prepare() will work but the sql is not actually compiled. Unfortunately bind params are passed to sqlsrv_prepare and not to sqlsrv_execute. make Prepare() and empty function, and we still execute the unprepared stmt. +- mysql: FetchField(-1), turns it is is not possible to retrieve the max_length. Set to -1. +- mysql-perf: Fixed "SHOW INNODB STATUS". Change to "SHOW ENGINE INNODB STATUS" + +## 5.17 - 2012-05-18 + +- Active Record: Removed trailing whitespace from adodb-active-record.inc.php. +- odbc: Added support for $database parameter in odbc Connect() function. E.g. $DB->Connect($dsn_without_db, $user, $pwd, $database). + Previously $database had to be left blank and the $dsn was used to pass in this parameter. +- oci8: Added better empty($rs) error handling to metaindexes(). +- oci8: Changed to use newer oci API to support PHP 5.4. +- adodb.inc.php: Changed GetRowAssoc to more generic code that will work in all scenarios. + +## 5.16 - 2012-03-26 + +- mysqli: extra mysqli_next_result() in close() removed. See PHPLens Issue No: 19100 +- datadict-oci8: minor typo in create sequence trigger fixed. See PHPLens Issue No: 18879. +- security: safe date parsing changes. Does not impact security, these are code optimisations. Thx Saithis. +- postgres, oci8, oci8po, db2oci: Param() function parameters inconsistent with base class. $type='C' missing. Fixed. +- active-record: locked bug fixed. PHPLens Issue:19073 +- mysql, mysqli and informix: added MetaProcedures. Metaprocedures allows to retrieve an array list of all procedures in database. PHPLens Issue No: 18414 +- Postgres7: added support for serial data type in MetaColumns(). + +## 5.15 - 2012-01-19 + +- pdo: fix ErrorMsg() to detect errors correctly. Thx Jens. +- mssqlnative: added another check for $this->fields array exists. +- mssqlnative: bugs in FetchField() fixed. See PHPLens Issue No: 19024 +- DBDate and DBTimeStamp had sql injection bug. Fixed. Thx Saithis +- mysql and mysqli: MetaTables() now identifies views and tables correctly. +- Added function adodb_time() to adodb-time.inc.php. Generates current time in unsigned integer format. + +## 5.14 - 2011-09-08 + +- mysqli: fix php compilation bug. +- postgres: bind variables did not work properly. Fixed. +- postgres: blob handling bug in _decode. Fixed. +- ActiveRecord: if a null field was never updated, activerecord would still update the record. Fixed. +- ActiveRecord: 1 char length string never quoted. Fixed. +- LDAP: Connection string ldap:// and ldaps:// did not work. Fixed. + +## 5.13 - 2011-08-15 + +- Postgres: Fix in 5.12 was wrong. Uses pg_unescape_bytea() correctly now in _decode. +- GetInsertSQL/GetUpdateSQL: Now $ADODB_QUOTE_FIELDNAMES allows you to define 'NATIVE', 'UPPER', 'LOWER'. If set to true, will default to 'UPPER'. +- mysqli: added support for persistent connections 'p:'. +- mssqlnative: ADODB_FETCH_BOTH did not work properly. Fixed. +- mssqlnative: return values for stored procedures where not returned! Fixed. See PHPLens Issue No: 18919 +- mssqlnative: timestamp and fetchfield bugs fixed. PHPLens Issue: 18453 + +## 5.12 - 2011-06-30 + +- Postgres: Added information_schema support for postgresql. +- Postgres: Use pg_unescape_bytea() in _decode. +- Fix bulk binding with oci8. PHPLens Issue No: 18786 +- oci8 perf: added wait evt monitoring. Also db cache advice now handles multiple buffer pools properly. +- sessions2: Fixed setFetchMode problem. +- sqlite: Some DSN connection settings were not parsed correctly. +- mysqli: now GetOne obeys $ADODB_GETONE_EOF; +- memcache: compress option did not work. Fixed. See PHPLens Issue No: 18899 + +## 5.11 - 2010-05-05 + +- mysql: Fixed GetOne() to return null if no records returned. +- oci8 perf: added stats on sga, rman, memory usage, and flash in performance tab. +- odbtp: Now you can define password in $password field of Connect()/PConnect(), and it will add it to DSN. +- Datadict: altering columns did not consider the scale of the column. Now it does. +- mssql: Fixed problem with ADODB_CASE_ASSOC causing multiple versions of column name appearing in recordset fields. +- oci8: Added missing & to refLob. +- oci8: Added obj->scale to FetchField(). +- oci8: Now you can get column info of a table in a different schema, e.g. MetaColumns("schema.table") is supported. +- odbc_mssql: Fixed missing $metaDatabasesSQL. +- xmlschema: Changed declaration of create() to create($xmls) to fix compat problems. Also changed constructor adoSchema() to pass in variable instead of variable reference. +- ado5: Fixed ado5 exceptions to only display errors when $this->debug=true; +- Added DSN support to sessions2.inc.php. +- adodb-lib.inc.php. Fixed issue with _adodb_getcount() not using $secs2cache parameter. +- adodb active record. Fixed caching bug. See PHPLens Issue No: 18288. +- db2: fixed ServerInfo(). +- adodb_date: Added support for format 'e' for TZ as in adodb_date('e') +- Active Record: If you have a field which is a string field (with numbers in) and you add preceding 0's to it the adodb library does not pick up the fact that the field has changed because of the way php's == works (dodgily). The end result is that it never gets updated into the database - fix by Matthew Forrester (MediaEquals). [matthew.forrester#mediaequals.com] +- Fixes RowLock() and MetaIndexes() inconsistencies. See PHPLens Issue No: 18236 +- Active record support for postgrseql boolean. See PHPLens Issue No: 18246 +- By default, Execute 2D array is disabled for security reasons. Set $conn->bulkBind = true to enable. See PHPLens Issue No: 18270. Note this breaks backward compat. +- MSSQL: fixes for 5.2 compat. PHPLens Issue No: 18325 +- Changed Version() to return a string instead of a float so it correctly returns 5.10 instead of 5.1. + +## 5.10 - 2009-11-10 + +- Fixed memcache to properly support $rs->timeCreated. +- adodb-ado.inc.php: Added BigInt support for PHP5. Will return float instead to support large numbers. Thx nasb#mail.goo.ne.jp. +- adodb-mysqli.inc.php: mysqli_multi_query is now turned off by default. To turn it on, use $conn->multiQuery = true; This is because of the risks of sql injection. See PHPLens Issue No: 18144 +- New db2oci driver for db2 9.7 when using PL/SQL mode. Allows oracle style :0, :1, :2 bind parameters which are remapped to ? ? ?. +- adodb-db2.inc.php: fixed bugs in MetaTables. SYS owner field not checked properly. Also in $conn->Connect($dsn, null, null, $schema) and PConnect($dsn, null, null, $schema), we do a SET SCHEMA=$schema if successful connection. +- adodb-mysqli.inc.php: Now $rs->Close() closes all pending next resultsets. Thx Clifton mesmackgod#gmail.com +- Moved _CreateCache() from PConnect()/Connect() to CacheExecute(). Suggested by Dumka. +- Many bug fixes to adodb-pdo_sqlite.inc.php and new datadict-sqlite.inc.php. Thx Andrei B. [andreutz#mymail.ro] +- Removed usage of split (deprecated in php 5.3). Thx david#horizon-nigh.org. +- Fixed RowLock() parameters to comply with PHP5 strict mode in multiple drivers. + +## 5.09 - 2009-06-25 + +- Active Record: You can force column names to be quoted in INSERT and UPDATE statements, typically because you are using reserved words as column names by setting ADODB_Active_Record::$_quoteNames = true; +- Added memcache and cachesecs to DSN. e.g. + + ``` php + # we have a memcache servers mem1,mem2 on port 8888, compression=off and cachesecs=120 + $dsn = 'mysql://user:pwd@localhost/mydb?memcache=mem1,mem2:8888:0&cachesecs=120'; + ``` + +- Fixed up MetaColumns and MetaPrimaryIndexes() for php 5.3 compat. Thx http://adodb.pastebin.com/m52082b16 +- The postgresql driver's OffsetDate() apparently does not work with postgres 8.3. Fixed. +- Added support for magic_quotes_sybase in qstr() and addq(). Thanks Eloy and Sam Moffat. +- The oci8 driver did not handle LOBs properly when binding. Fixed. See PHPLens Issue No: 17991. +- Datadict: In order to support TIMESTAMP with subsecond accuracy, added to datadict the new TS type. Supported by mssql, postgresql and oci8 (oracle). Also changed oci8 $conn->sysTimeStamp to use 'SYSTIMESTAMP' instead of 'SYSDATE'. Should be backwards compat. +- Added support for PHP 5.1+ DateTime objects in DBDate and DBTimeStamp. This means that dates and timestamps will be managed by DateTime objects if you are running PHP 5.1+. +- Added new property to postgres64 driver to support returning I if type is unique int called $db->uniqueIisR, defaulting to true. See PHPLens Issue No: 17963 +- Added support for bindarray in adodb_GetActiveRecordsClass with SelectLimit in adodb-active-record.inc.php. +- Transactions now allowed in ado_access driver. Thx to petar.petrov.georgiev#gmail.com. +- Sessions2 garbage collection is now much more robust. We perform ORDER BY to prevent deadlock in adodb-sessions2.inc.php. +- Fixed typo in pdo_sqlite driver. + +## 5.08a - 2009-04-17 + +- Fixes wrong version number string. +- Incorrect + in adodb-datadict.inc.php removed. +- Fixes missing OffsetDate() function in pdo. Thx paul#mantisforge.org. + +## 5.08 - 2009-04-17 + +- adodb-sybase.inc.php driver. Added $conn->charSet support. Thx Luis Henrique Mulinari (luis.mulinari#gmail.com) +- adodb-ado5.inc.php. Fixed some bind param issues. Thx Jirka Novak. +- adodb-ado5.inc.php. Now has improved error handling. +- Fixed typo in adodb-xmlschema03.inc.php. See XMLS_EXISTING_DATA, line 1501. Thx james johnson. +- Made $inputarr optional for _query() in all drivers. +- Fixed spelling mistake in flushall() in adodb.inc.ophp. +- Fixed handling of quotes in adodb_active_record::doquote. Thx Jonathan Hohle (jhohle#godaddy.com). +- Added new index parameter to adodb_active_record::setdatabaseadaptor. Thx Jonathan Hohle +- Fixed & readcache() reference compat problem with php 5.3 in adodb.Thx Jonathan Hohle. +- Some minor $ADODB_CACHE_CLASS definition issues in adodb.inc.php. +- Added Reset() function to adodb_active_record. Thx marcus. +- Minor dsn fix for pdo_sqlite in adodb.inc.php. Thx Sergey Chvalyuk. +- Fixed adodb-datadict _CreateSuffix() inconsistencies. Thx Chris Miller. +- Option to delete old fields $dropOldFlds in datadict ChangeTableSQL($table, $flds, $tableOptions, $dropOldFlds=false) added. Thx Philipp Niethammer. +- Memcache caching did not expire properly. Fixed. +- MetaForeignKeys for postgres7 driver changed from adodb_movenext to $rs->MoveNext (also in 4.99) +- Added support for ldap and ldaps url format in ldap driver. E.g. ldap://host:port/dn?attributes?scope?filter?extensions + +## 5.07 - 2008-12-26 + +- BeginTrans/CommitTrans/RollbackTrans return true/false correctly on success/failure now for mssql, odbc, oci8, mysqlt, mysqli, postgres, pdo. +- Replace() now quotes all non-null values including numeric ones. +- Postgresql qstr() now returns booleans as *true* and *false* without quotes. +- MetaForeignKeys in mysql and mysqli drivers had this problem: A table can have two foreign keys pointing to the same column in the same table. The original code will incorrectly report only the last column. Fixed. https://sourceforge.net/p/adodb/bugs/100/ +- Passing in full ado connection string in $argHostname with ado drivers was failing in adodb5 due to bug. Fixed. +- Fixed memcachelib flushcache and flushall bugs. Also fixed possible timeCreated = 0 problem in readcache. (Also in adodb 4.992). Thanks AlexB_UK (alexbarnes#hotmail.com). +- Fixed a notice in adodb-sessions2.inc.php, in _conn(). Thx bober m.derlukiewicz#rocktech.remove_me.pl; +- ADOdb Active Record: Fixed some issues with incompatible fetch modes (ADODB_FETCH_ASSOC) causing problems in UpdateActiveTable(). +- ADOdb Active Record: Added support for functions that support predefining one-to-many relationships: + _ClassHasMany ClassBelongsTo TableHasMany TableBelongsTo TableKeyHasMany TableKeyBelongsTo_. +- You can also define your child/parent class in these functions, instead of the default ADODB_Active_Record. Thx Arialdo Martini & Chris R for idea. +- ADOdb Active Record: HasMany hardcoded primary key to "id". Fixed. +- Many pdo and pdo-sqlite fixes from Sid Dunayer [sdunayer#interserv.com]. +- CacheSelectLimit not working for mssql. Fixed. Thx AlexB. +- The rs2html function did not display hours in timestamps correctly. Now 24hr clock used. +- Changed ereg* functions to use preg* functions as ereg* is deprecated in PHP 5.3. Modified sybase and postgresql drivers. + +## 5.06 - 2008-10-16 + +- Added driver adodb-pdo_sqlite.inc.php. Thanks Diogo Toscano (diogo#scriptcase.net) for the code. +- Added support for [one-to-many relationships](https://adodb.org/dokuwiki/doku.php?id=v5:userguide:active_record#one_to_many_relations) with BelongsTo() and HasMany() in adodb_active_record. +- Added BINARY type to mysql.inc.php (also in 4.991). +- Added support for SelectLimit($sql,-1,100) in oci8. (also in 4.991). +- New $conn->GetMedian($table, $field, $where='') to get median account no. (also in 4.991) +- The rs2html() function in tohtml.inc.php did not handle dates with ':' in it properly. Fixed. (also in 4.991) +- Added support for connecting to oci8 using `$DB->Connect($ip, $user, $pwd, "SID=$sid");` (also in 4.991) +- Added mysql type 'VAR_STRING' to MetaType(). (also in 4.991) +- The session and session2 code supports setfetchmode assoc properly now (also in 4.991). +- Added concat support to pdo. Thx Andrea Baron. +- Changed db2 driver to use format `Y-m-d H-i-s` for datetime instead of `Y-m-d-H-i-s` which was legacy from odbc_db2 conversion. +- Removed vestigal break on adodb_tz_offset in adodb-time.inc.php. +- MetaForeignKeys did not work for views in MySQL 5. Fixed. +- Changed error handling in GetActiveRecordsClass. +- Added better support for using existing driver when $ADODB_NEWCONNECTION function returns false. +- In _CreateSuffix in adodb-datadict.inc.php, adding unsigned variable for mysql. +- In adodb-xmlschema03.inc.php, changed addTableOpt to include db name. +- If bytea blob in postgresql is null, empty string was formerly returned. Now null is returned. +- Changed db2 driver CreateSequence to support $start parameter. +- rs2html() now does not add nbsp to end if length of string > 0 +- The oci8po FetchField() now only lowercases field names if ADODB_ASSOC_CASE is set to 0. +- New mssqlnative drivers for php. TQ Garrett Serack of M'soft. [Download](http://www.microsoft.com/downloads/details.aspx?FamilyId=61BF87E0-D031-466B-B09A-6597C21A2E2A&displaylang=en) mssqlnative extension. Note that this is still in beta. +- Fixed bugs in memcache support. +- You can now change the return value of GetOne if no records are found using the global variable $ADODB_GETONE_EOF. The default is null. To change it back to the pre-4.99/5.00 behaviour of false, set $ADODB_GETONE_EOF = false; +- In Postgresql 8.2/8.3 MetaForeignkeys did not work. Fixed William Kolodny William.Kolodny#gt-t.net + +## 5.05 - 2008-07-11 + +Released together with [v4.990](changelog_v4.x.md#4990---11-jul-2008) + +- Added support for multiple recordsets in mysqli , thanks to Geisel Sierote geisel#4up.com.br. See PHPLens Issue No: 15917 +- Malcolm Cook added new Reload() function to Active Record. See PHPLens Issue No: 17474 +- Thanks Zoltan Monori (monzol#fotoprizma.hu) for bug fixes in iterator, SelectLimit, GetRandRow, etc. +- Under heavy loads, the performance monitor for oci8 disables Ixora views. +- Fixed sybase driver SQLDate to use str_replace(). Also for adodb5, changed sybase driver UnixDate and UnixTimeStamp calls to static. +- Changed oci8 lob handler to use & reference `$this->_refLOBs[$numlob]['VAR'] = &$var`. +- We now strtolower the get_class() function in PEAR::isError() for php5 compat. +- CacheExecute did not retrieve cache recordsets properly for 5.04 (worked in 4.98). Fixed. +- New ADODB_Cache_File class for file caching defined in adodb.inc.php. +- Farsi language file contribution by Peyman Hooshmandi Raad (phooshmand#gmail.com) +- New API for creating your custom caching class which is stored in $ADODB_CACHE: + + ``` php + include "/path/to/adodb.inc.php"; + $ADODB_CACHE_CLASS = 'MyCacheClass'; + class MyCacheClass extends ADODB_Cache_File + { + function writecache($filename, $contents,$debug=false) {...} + function &readcache($filename, &$err, $secs2cache, $rsClass) { ...} + : + } + $DB = NewADOConnection($driver); + $DB->Connect(...); ## MyCacheClass created here and stored in $ADODB_CACHE global variable. + $data = $rs->CacheGetOne($sql); ## MyCacheClass is used here for caching... + ``` + +- Memcache supports multiple pooled hosts now. Only if none of the pooled servers + can be contacted will a connect error be generated. Usage example below: + + ``` php + $db = NewADOConnection($driver); + $db->memCache = true; /// should we use memCache instead of caching in files + $db->memCacheHost = array($ip1, $ip2, $ip3); /// $db->memCacheHost = $ip1; still works + $db->memCachePort = 11211; /// this is default memCache port + $db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) + $db->Connect(...); + $db->CacheExecute($sql); + ``` + +## 5.04 - 2008-02-13 + +Released together with [v4.98](changelog_v4.x.md#498---13-feb-2008) + +- Fixed adodb_mktime problem which causes a performance bottleneck in $hrs. +- Added mysqli support to adodb_getcount(). +- Removed MYSQLI_TYPE_CHAR from MetaType(). + +## 5.03 - 2008-01-22 + +Released together with [v4.97](changelog_v4.x.md#497---22-jan-2008) + +- Active Record: $ADODB_ASSOC_CASE=1 did not work properly. Fixed. +- Modified Fields() in recordset class to support display null fields in FetchNextObject(). +- In ADOdb5, active record implementation, we now support column names with spaces in them - we autoconvert the spaces to _ using __set(). Thx Daniel Cook. PHPLens Issue No: 17200 +- Removed $arg3 from mysqli SelectLimit. See PHPLens Issue No: 16243. Thx Zsolt Szeberenyi. +- Changed oci8 FetchField, which returns the max_length of BLOB/CLOB/NCLOB as 4000 (incorrectly) to -1. +- CacheExecute would sometimes return an error on Windows if it was unable to lock the cache file. This is harmless and has been changed to a warning that can be ignored. Also adodb_write_file() code revised. +- ADOdb perf code changed to only log sql if execution time >= 0.05 seconds. New $ADODB_PERF_MIN variable holds min sql timing. Any SQL with timing value below this and is not causing an error is not logged. +- Also adodb_backtrace() now traces 1 level deeper as sometimes actual culprit function is not displayed. +- Fixed a group by problem with adodb_getcount() for db's which are not postgres/oci8 based. +- Changed mssql driver Parameter() from SQLCHAR to SQLVARCHAR: case 'string': $type = SQLVARCHAR; break. +- Problem with mssql driver in php5 (for adodb 5.03) because some functions are not static. Fixed. + +## 5.02 - 2007-09-24 + +Released together with [v4.96](changelog_v4.x.md#496---24-sept-2007) + +- ADOdb perf for oci8 now has non-table-locking code when clearing the sql. Slower but better transparency. Added in 4.96a and 5.02a. +- Fix adodb count optimisation. Preg_match did not work properly. Also rewrote the ORDER BY stripping code in _adodb_getcount(), adodb-lib.inc.php. +- SelectLimit for oci8 not optimal for large recordsets when offset=0. Changed $nrows check. +- Active record optimizations. Added support for assoc arrays in Set(). +- Now GetOne returns null if EOF (no records found), and false if error occurs. Use ErrorMsg()/ErrorNo() to get the error. +- Also CacheGetRow and CacheGetCol will return false if error occurs, or empty array() if EOF, just like GetRow and GetCol. +- Datadict now allows changing of types which are not resizable, eg. VARCHAR to TEXT in ChangeTableSQL. -- Mateo Tibaquirá +- Added BIT data type support to adodb-ado.inc.php and adodb-ado5.inc.php. +- Ldap driver did not return actual ldap error messages. Fixed. +- Implemented GetRandRow($sql, $inputarr). Optimized for Oci8. +- Changed adodb5 active record to use static SetDatabaseAdapter() and removed php4 constructor. Bas van Beek bas.vanbeek#gmail.com. +- Also in adodb5, changed adodb-session2 to use static function declarations in class. Thx Daniel Berlin. +- Added "Clear SQL Log" to bottom of Performance screen. +- Sessions2 code echo'ed directly to the screen in debug mode. Now uses ADOConnection::outp(). +- In mysql/mysqli, qstr(null) will return the string `null` instead of empty quoted string `''`. +- postgresql optimizeTable in perf-postgres.inc.php added by Daniel Berlin (mail#daniel-berlin.de) +- Added 5.2.1 compat code for oci8. +- Changed @@identity to SCOPE_IDENTITY() for multiple mssql drivers. Thx Stefano Nari. +- Code sanitization introduced in 4.95 caused problems in European locales (as float 3.2 was typecast to 3,2). Now we only sanitize if is_numeric fails. +- Added support for customizing ADORecordset_empty using $this->rsPrefix.'empty'. By Josh Truwin. +- Added proper support for ALterColumnSQL for Postgresql in datadict code. Thx. Josh Truwin. +- Added better support for MetaType() in mysqli when using an array recordset. +- Changed parser for pgsql error messages in adodb-error.inc.php to case-insensitive regex. + +## 5.01 - 2007-05-17 + +Released together with [v4.95](changelog_v4.x.md#495---17-may-2007) + +- CacheFlush debug outp() passed in invalid parameters. Fixed. +- Added Thai language file for adodb. Thx Trirat Petchsingh rosskouk#gmail.com and Marcos Pont +- Added zerofill checking support to MetaColumns for mysql and mysqli. +- CacheFlush no longer deletes all files/directories. Only *.cache files deleted. +- DB2 timestamp format changed to `var $fmtTimeStamp = "'Y-m-d-H:i:s'";` +- Added some code sanitization to AutoExecute in adodb-lib.inc.php. +- Due to typo, all connections in adodb-oracle.inc.php would become persistent, even non-persistent ones. Fixed. +- Oci8 DBTimeStamp uses 24 hour time for input now, so you can perform string comparisons between 2 DBTimeStamp values. +- Some PHP4.4 compat issues fixed in adodb-session2.inc.php +- For ADOdb 5.01, fixed some adodb-datadict.inc.php MetaType compat issues with PHP5. +- The $argHostname was wiped out in adodb-ado5.inc.php. Fixed. +- Adodb5 version, added iterator support for adodb_recordset_empty. +- Adodb5 version,more error checking code now will use exceptions if available. + + +[5.22.2]: https://github.com/adodb/adodb/compare/v5.22.1...v5.22.2 +[5.22.1]: https://github.com/adodb/adodb/compare/v5.22.0...v5.22.1 +[5.22.0]: https://github.com/adodb/adodb/compare/v5.21.4...v5.22.0 + +[5.21.4]: https://github.com/adodb/adodb/compare/v5.21.3...v5.21.4 +[5.21.3]: https://github.com/adodb/adodb/compare/v5.21.2...v5.21.3 +[5.21.2]: https://github.com/adodb/adodb/compare/v5.21.1...v5.21.2 +[5.21.1]: https://github.com/adodb/adodb/compare/v5.21.0...v5.21.1 +[5.21.0]: https://github.com/adodb/adodb/compare/v5.21.0-rc.1...v5.21.0 +[5.21.0-rc.1]: https://github.com/adodb/adodb/compare/v5.21.0-beta.1...v5.21.0-rc.1 +[5.21.0-beta.1]: https://github.com/adodb/adodb/compare/v5.20.20...v5.21.0-beta.1 + +[5.20.21]: https://github.com/adodb/adodb/compare/v5.20.20...v5.20.21 +[5.20.20]: https://github.com/adodb/adodb/compare/v5.20.19...v5.20.20 +[5.20.19]: https://github.com/adodb/adodb/compare/v5.20.18...v5.20.19 +[5.20.18]: https://github.com/adodb/adodb/compare/v5.20.17...v5.20.18 +[5.20.17]: https://github.com/adodb/adodb/compare/v5.20.16...v5.20.17 +[5.20.16]: https://github.com/adodb/adodb/compare/v5.20.15...v5.20.16 +[5.20.15]: https://github.com/adodb/adodb/compare/v5.20.14...v5.20.15 +[5.20.14]: https://github.com/adodb/adodb/compare/v5.20.13...v5.20.14 +[5.20.13]: https://github.com/adodb/adodb/compare/v5.20.12...v5.20.13 +[5.20.12]: https://github.com/adodb/adodb/compare/v5.20.11...v5.20.12 +[5.20.11]: https://github.com/adodb/adodb/compare/v5.20.10...v5.20.11 +[5.20.10]: https://github.com/adodb/adodb/compare/v5.20.9...v5.20.10 +[5.20.9]: https://github.com/adodb/adodb/compare/v5.20.8...v5.20.9 +[5.20.8]: https://github.com/adodb/adodb/compare/v5.20.7...v5.20.8 +[5.20.7]: https://github.com/adodb/adodb/compare/v5.20.6...v5.20.7 +[5.20.6]: https://github.com/adodb/adodb/compare/v5.20.5...v5.20.6 +[5.20.5]: https://github.com/adodb/adodb/compare/v5.20.4...v5.20.5 +[5.20.4]: https://github.com/adodb/adodb/compare/v5.20.3...v5.20.4 +[5.20.3]: https://github.com/adodb/adodb/compare/v5.20.2...v5.20.3 +[5.20.2]: https://github.com/adodb/adodb/compare/v5.20.1...v5.20.2 +[5.20.1]: https://github.com/adodb/adodb/compare/v5.20.0...v5.20.1 +[5.20.0]: https://github.com/adodb/adodb/compare/v5.19...v5.20.0 diff --git a/www/include/adodb/docs/changelog_v2.x.md b/www/include/adodb/docs/changelog_v2.x.md new file mode 100644 index 00000000..af718b73 --- /dev/null +++ b/www/include/adodb/docs/changelog_v2.x.md @@ -0,0 +1,531 @@ +# ADOdb old Changelog - v2.x and older + +See the [Current Changelog](changelog.md). + + +## 2.91 - 3 Jan 2003 + +- Revised PHP version checking to use $ADODB_PHPVER with legal values 0x4000, 0x4050, 0x4200, 0x4300. +- Added support for bytea fields and oid blobs in postgres by allowing BlobDecode() to detect and convert non-oid fields. Also added BlobEncode to postgres when you want to encode oid blobs. +- Added blobEncodeType property for connections to inform phpLens what encoding method to use for blobs. +- Added BlobDecode() and BlobEncode() to base ADOConnection class. +- Added umask() to _gencachename() when creating directories. +- Added charPage for ado drivers, so you can set the code page. + ``` +$conn->charPage = CP_UTF8; +$conn->Connect($dsn); + ``` +- Modified _seek in mysql to check for num rows=0. +- Added to metatypes new informix types for IDS 9.30\. Thx Fernando Ortiz. +- _maxrecordcount returned in CachePageExecute $rsreturn +- Fixed sybase cacheselectlimit( ) problems +- MetaColumns() max_length should use precision for types X and C for ms access. Fixed. +- Speedup of odbc non-SELECT sql statements. +- Added support in MetaColumns for Wide Char types for ODBC. We halve max_length if unicode/wide char. +- Added 'B' to types handled by GetUpdateSQL/GetInsertSQL. +- Fixed warning message in oci8 driver with $persist variable when using PConnect. + +## 2.90 - 11 Dec 2002 + +- Mssql and mssqlpo and oci8po now support ADODB_ASSOC_CASE. +- Now MetaType() can accept a field object as the first parameter. +- New $arr = $db->ServerInfo( ) function. Returns $arr['description'] which is the string description, and $arr['version']. +- PostgreSQL and MSSQL speedups for insert/updates. +- Implemented new SetFetchMode() that removes the need to use $ADODB_FETCH_MODE. Each connection has independent fetchMode. +- ADODB_ASSOC_CASE now defaults to 2, use native defaults. This is because we would break backward compat for too many applications otherwise. +- Patched encrypted sessions to use replace() +- The qstr function supports quoting of nulls when escape character is \ +- Rewrote bits and pieces of session code to check for time synch and improve reliability. +- Added property ADOConnection::hasTransactions = true/false; +- Added CreateSequence and DropSequence functions +- Found misplaced MoveNext() in adodb-postgres.inc.php. Fixed. +- Sybase SelectLimit not reliable because 'set rowcount' not cached - fixed. +- Moved ADOConnection to adodb-connection.inc.php and ADORecordSet to adodb-recordset.inc.php. This allows us to use doxygen to generate documentation. Doxygen doesn't like the classes in the main adodb.inc.php file for some mysterious reason. + +## 2.50 - 14 Nov 2002 + +- Added transOff and transCnt properties for disabling (transOff = true) and tracking transaction status (transCnt>0). +- Added inputarray handling into _adodb_pageexecute_all_rows - "Ross Smith" RossSmith#bnw.com. +- Fixed postgresql inconsistencies in date handling. +- Added support for mssql_fetch_assoc. +- Fixed $ADODB_FETCH_MODE bug in odbc MetaTables() and MetaPrimaryKeys(). +- Accidentally declared UnixDate() twice, making adodb incompatible with php 4.3.0\. Fixed. +- Fixed pager problems with some databases that returned -1 for _currentRow on MoveLast() by switching to MoveNext() in adodb-lib.inc.php. +- Also fixed uninited $discard in adodb-lib.inc.php. + +## 2.43 - 25 Oct 2002 + +- Added ADODB_ASSOC_CASE constant to better support ibase and odbc field names. +- Added support for NConnect() for oracle OCINLogin. +- Fixed NumCols() bug. +- Changed session handler to use Replace() on write. +- Fixed oci8 SelectLimit aggregate function bug again. +- Rewrote pivoting code. + +## 2.42 - 4 Oct 2002 + +- Fixed ibase_fetch() problem with nulls. Also interbase now does automatic blob decoding, and is backward compatible. Suggested by Heinz Hombergs heinz#hhombergs.de. +- Fixed postgresql MoveNext() problems when called repeatedly after EOF. Also suggested by Heinz Hombergs. +- PageExecute() does not rewrite queries if SELECT DISTINCT is used. Requested by hans#velum.net +- Added additional fixes to oci8 SelectLimit handling with aggregate functions - thx to Christian Bugge for reporting the problem. + +## 2.41 - 2 Oct 2002 + +- Fixed ADODB_COUNTRECS bug in odbc. Thx to Joshua Zoshi jzoshi#hotmail.com. +- Increased buffers for adodb-csvlib.inc.php for extremely long sql from 8192 to 32000. +- Revised pivottable.inc.php code. Added better support for aggregate fields. +- Fixed mysql text/blob types problem in MetaTypes base class - thx to horacio degiorgi. +- Added SQLDate($fmt,$date) function, which allows an sql date format string to be generated - useful for group by's. +- Fixed bug in oci8 SelectLimit when offset>100. + +## 2.40 - 4 Sept 2002 + +- Added new NLS_DATE_FORMAT property to oci8\. Suggested by Laurent NAVARRO ln#altidev.com +- Now use bind parameters in oci8 selectlimit for better performance. +- Fixed interbase replaceQuote for dialect != 1\. Thx to "BEGUIN Pierre-Henri - INFOCOB" phb#infocob.com. +- Added white-space check to QA. +- Changed unixtimestamp to support fractional seconds (we always round down/floor the seconds). Thanks to beezly#beezly.org.uk. +- Now you can set the trigger_error type your own user-defined type in adodb-errorhandler.inc.php. Suggested by Claudio Bustos clbustos#entelchile.net. +- Added recordset filters with rsfilter.inc.php. + $conn->_rs2rs does not create a new recordset when it detects it is of type array. Some trickery there as there seems to be a bug in Zend Engine +- Added render_pagelinks to adodb-pager.inc.php. Code by "Pablo Costa" pablo#cbsp.com.br. +- MetaType() speedup in adodb.inc.php by using hashing instead of switch. Best performance if constant arrays are supported, as they are in PHP5. +- adodb-session.php now updates only the expiry date if the crc32 check indicates that the data has not been modified. + +## 2.31 - 20 Aug 2002 + +- Made changes to pivottable.inc.php due to daniel lucuzaeu's suggestions (we sum the pivottable column if desired). +- Fixed ErrorNo() in postgres so it does not depend on _errorMsg property. +- Robert Tuttle added support for oracle cursors. See ExecuteCursor(). +- Fixed Replace() so it works with mysql when updating record where data has not changed. Reported by Cal Evans (cal#calevans.com). + +## 2.30 - 1 Aug 2002 + +- Added pivottable.inc.php. Thanks to daniel.lucazeau#ajornet.com for the original concept. +- Added ADOConnection::outp($msg,$newline) to output error and debugging messages. Now you can override this using the ADODB_OUTP constant and use your own output handler. +- Changed == to === for 'null' comparison. Reported by ericquil#yahoo.com +- Fixed mssql SelectLimit( ) bug when distinct used. + +## 2.30 - 1 Aug 2002 + +- New GetCol() and CacheGetCol() from ross#bnw.com that returns the first field as a 1 dim array. +- We have an empty recordset, but RecordCount() could return -1\. Fixed. Reported by "Jonathan Polansky" jonathan#polansky.com. +- We now check for session variable changes using strlen($sessval).crc32($sessval). Formerly we only used crc32(). +- Informix SelectLimit() problem with $ADODB_COUNTRECS fixed. +- Fixed informix SELECT FIRST x DISTINCT, and not SELECT DISTINCT FIRST x - reported by F Riosa +- Now default adodb error handlers ignores error if @ used. +- If you set $conn->autoRollback=true, we auto-rollback persistent connections for odbc, mysql, oci8, mssql. Default for autoRollback is false. No need to do so for postgres. As interbase requires a transaction id (what a flawed api), we don't do it for interbase. +- Changed PageExecute() to use non-greedy preg_match when searching for "FROM" keyword. + +## 2.20 - 9 July 2002 + +- Added CacheGetOne($secs2cache,$sql), CacheGetRow($secs2cache,$sql), CacheGetAll($secs2cache,$sql). +- Added $conn->OffsetDate($dayFraction,$date=false) to generate sql that calcs date offsets. Useful for scheduling appointments. +- Added connection properties: leftOuter, rightOuter that hold left and right outer join operators. +- Added connection property: ansiOuter to indicate whether ansi outer joins supported. +- New driver _mssqlpo_, the portable mssql driver, which converts string concat operator from || to +. +- Fixed ms access bug - SelectLimit() did not support ties - fixed. +- Karsten Kraus (Karsten.Kraus#web.de), contributed error-handling code to ADONewConnection. Unfortunately due to backward compat problems, had to rollback most of the changes. +- Added new parameter to GetAssoc() to allow returning an array of key-value pairs, ignoring any additional columns in the recordset. Off by default. +- Corrected mssql $conn->sysDate to return only date using convert(). +- CacheExecute() improved debugging output. +- Changed rs2html() so newlines are converted to BR tags. Also optimized rs2html() based on feedback by "Jerry Workman" jerry#mtncad.com. +- Added support for Replace() with Interbase, using DELETE and INSERT. +- Some minor optimizations (mostly removing & references when passing arrays). +- Changed GenID() to allows id's larger than the size of an integer. +- Added force_session property to oci8 for better updateblob() support. +- Fixed PageExecute() which did not work properly with sql containing GROUP BY. + +## 2.12 - 12 June 2002 + +- Added toexport.inc.php to export recordsets in CSV and tab-delimited format. +- CachePageExecute() does not work - fixed - thx John Huong. +- Interbase aliases not set properly in FetchField() - fixed. Thx Stefan Goethals. +- Added cache property to adodb pager class. The number of secs to cache recordsets. +- SQL rewriting bug in pageexecute() due to skipping of newlines due to missing /s modifier. Fixed. +- Max size of cached recordset due to a bug was 256000 bytes. Fixed. +- Speedup of 1st invocation of CacheExecute() by tuning code. +- We compare $rewritesql with $sql in pageexecute code in case of rewrite failure. + +## 2.11 - 7 June 2002 + +- Fixed PageExecute() rewrite sql problem - COUNT(*) and ORDER BY don't go together with mssql, access and postgres. Thx to Alexander Zhukov alex#unipack.ru +- DB2 support for CHARACTER type added - thx John Huong huongch#bigfoot.com +- For ado, $argProvider not properly checked. Fixed - kalimero#ngi.it +- Added $conn->Replace() function for update with automatic insert if the record does not exist. Supported by all databases except interbase. + +## 2.10 - 4 June 2002 + +- Added uniqueSort property to indicate mssql ORDER BY cols must be unique. +- Optimized session handler by crc32 the data. We only write if session data has changed. +- adodb_sess_read in adodb-session.php now returns ''correctly - thanks to Jorma Tuomainen, webmaster#wizactive.com +- Mssql driver did not throw EXECUTE errors correctly because ErrorMsg() and ErrorNo() called in wrong order. Pointed out by Alexios Fakos. Fixed. +- Changed ado to use client cursors. This fixes BeginTran() problems with ado. +- Added handling of timestamp type in ado. +- Added to ado_mssql support for insert_id() and affected_rows(). +- Added support for mssql.datetimeconvert=0, available since php 4.2.0. +- Made UnixDate() less strict, so that the time is ignored if present. +- Changed quote() so that it checks for magic_quotes_gpc. +- Changed maxblobsize for odbc to default to 64000. + +## 2.00 - 13 May 2002 + +- Added drivers _informix72_ for pre-7.3 versions, and _oci805_ for oracle 8.0.5, and postgres64 for postgresql 6.4 and earlier. The postgres and postgres7 drivers are now identical. +- Interbase now partially supports ADODB_FETCH_BOTH, by defaulting to ASSOC mode. +- Proper support for blobs in mssql. Also revised blob support code is base class. Now UpdateBlobFile() calls UpdateBlob() for consistency. +- Added support for changed odbc_fetch_into api in php 4.2.0 with $conn->_has_stupid_odbc_fetch_api_change. +- Fixed spelling of tablock locking hint in GenID( ) for mssql. +- Added RowLock( ) to several databases, including oci8, informix, sybase, etc. Fixed where error in mssql RowLock(). +- Added sysDate and sysTimeStamp properties to most database drivers. These are the sql functions/constants for that database that return the current date and current timestamp, and are useful for portable inserts and updates. +- Support for RecordCount() caused date handling in sybase and mssql to break. Fixed, thanks to Toni Tunkkari, by creating derived classes for ADORecordSet_array for both databases. Generalized using arrayClass property. Also to support RecordCount(), changed metatype handling for ado drivers. Now the type returned in FetchField is no longer a number, but the 1-char data type returned by MetaType. At the same time, fixed a lot of date handling. Now mssql support dmy and mdy date formats. Also speedups in sybase and mssql with preg_match and ^ in date/timestamp handling. Added support in sybase and mssql for 24 hour clock in timestamps (no AM/PM). +- Extensive revisions to informix driver - thanks to Samuel CARRIERE samuel_carriere#hotmail.com +- Added $ok parameter to CommitTrans($ok) for easy rollbacks. +- Fixed odbc MetaColumns and MetaTables to save and restore $ADODB_FETCH_MODE. +- Some odbc drivers did not call the base connection class constructor. Fixed. +- Fixed regex for GetUpdateSQL() and GetInsertSQL() to support more legal character combinations. + +## 1.99 - 21 April 2002 + +- Added emulated RecordCount() to all database drivers if $ADODB_COUNTRECS = true (which it is by default). Inspired by Cristiano Duarte (cunha17#uol.com.br). +- Unified stored procedure support for mssql and oci8\. Parameter() and PrepareSP() functions implemented. +- Added support for SELECT FIRST in informix, modified hasTop property to support this. +- Changed csv driver to handle updates/deletes/inserts properly (when Execute() returns true). Bind params also work now, and raiseErrorFn with csv driver. Added csv driver to QA process. +- Better error checking in oci8 UpdateBlob() and UpdateBlobFile(). +- Added TIME type to MySQL - patch by Manfred h9125297#zechine.wu-wien.ac.at +- Prepare/Execute implemented for Interbase/Firebird +- Changed some regular expressions to be anchored by /^ $/ for speed. +- Added UnixTimeStamp() and UnixDate() to ADOConnection(). Now these functions are in both ADOConnection and ADORecordSet classes. +- Empty recordsets were not cached - fixed. +- Thanks to Gaetano Giunta (g.giunta#libero.it) for the oci8 code review. We didn't agree on everything, but i hoped we agreed to disagree! + +## 1.90 - 6 April 2002 + +- Now all database drivers support fetch modes ADODB_FETCH_NUM and ADODB_FETCH_ASSOC, though still not fully tested. Eg. Frontbase, Sybase, Informix. +- NextRecordSet() support for mssql. Contributed by "Sven Axelsson" sven.axelsson#bokochwebb.se +- Added blob support for SQL Anywhere. Contributed by Wade Johnson wade#wadejohnson.de +- Fixed some security loopholes in server.php. Server.php also supports fetch mode. +- Generalized GenID() to support odbc and mssql drivers. Mssql no longer generates GUID's. +- Experimental RowLock($table,$where) for mssql. +- Properly implemented Prepare() in oci8 and ODBC. +- Added Bind() support to oci8 to support Prepare(). +- Improved error handler. Catches CacheExecute() and GenID() errors now. +- Now if you are running php from the command line, debugging messages do not output html formatting. Not 100% complete, but getting there. + +## 1.81 - 22 March 2002 + +- Restored default $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT for backward compatibility. +- SelectLimit for oci8 improved - Our FIRST_ROWS optimization now does not overwrite existing hint. +- New Sybase SQL Anywhere driver. Contributed by Wade Johnson wade#wadejohnson.de + +## 1.80 - 15 March 2002 + +- Redesigned directory structure of ADOdb files. Added new driver directory where all database drivers reside. +- Changed caching algorithm to create subdirectories. Now we scale better. +- Informix driver now supports insert_id(). Contribution by "Andrea Pinnisi" pinnisi#sysnet.it +- Added experimental ISO date and FetchField support for informix. +- Fixed a quoting bug in Execute() with bind parameters, causing problems with blobs. +- Mssql driver speedup by 10-15%. +- Now in CacheExecute($secs2cache,$sql,...), $secs2cache is optional. If missing, it will take the value defined in $connection->cacheSecs (default is 3600 seconds). Note that CacheSelectLimit(), the secs2cache is still compulsory - sigh. +- Sybase SQL Anywhere driver (using ODBC) contributed by Wade Johnson wade#wadejohnson.de + +## 1.72 - 8 March 2002 + +- Added @ when returning Fields() to prevent spurious error - "Michael William Miller" mille562#pilot.msu.edu +- MetaDatabases() for postgres contributed by Phil pamelant#nerim.net +- Mitchell T. Young (mitch#youngfamily.org) contributed informix driver. +- Fixed rs2html() problem. I cannot reproduce, so probably a problem with pre PHP 4.1.0 versions, when supporting new ADODB_FETCH_MODEs. +- Mattia Rossi (mattia#technologist.com) contributed BlobDecode() and UpdateBlobFile() for postgresql using the postgres specific pg_lo_import()/pg_lo_open() - i don't use them but hopefully others will find this useful. See [this posting](PHPLens Issue No: 1262) for an example of usage. +- Added UpdateBlobFile() for uploading files to a database. +- Made UpdateBlob() compatible with oci8po driver. +- Added noNullStrings support to oci8 driver. Oracle changes all ' ' strings to nulls, so you need to set strings to ' ' to prevent the nullifying of strings. $conn->noNullStrings = true; will do this for you automatically. This is useful when you define a char column as NOT NULL. +- Fixed UnixTimeStamp() bug - wasn't setting minutes and seconds properly. Patch from Agusti Fita i Borrell agusti#anglatecnic.com. +- Toni Tunkkari added patch for sybase dates. Problem with spaces in day part of date fixed. + +## 1.71 - 18 Jan 2002 + +- Sequence start id support. Now $conn->Gen_ID('seqname', 50) to start sequence from 50. +- CSV driver fix for selectlimit, from Andreas - akaiser#vocote.de. +- Gam3r spotted that a global variable was undefined in the session handler. +- Mssql date regex had error. Fixed - reported by Minh Hoang vb_user#yahoo.com. +- DBTimeStamp() and DBDate() now accept iso dates and unix timestamps. This means that the PostgreSQL handling of dates in GetInsertSQL() and GetUpdateSQL() can be removed. Also if these functions are passed '' or null or false, we return a SQL null. +- GetInsertSQL() and GetUpdateSQL() now accept a new parameter, $magicq to indicate whether quotes should be inserted based on magic quote settings - suggested by dj#4ict.com. +- Reformated docs slightly based on suggestions by Chris Small. + +## 1.65 - 28 Dec 2001 + +- Fixed borland_ibase class naming bug. +- Now instead of using $rs->fields[0] internally, we use reset($rs->fields) so that we are compatible with ADODB_FETCH_ASSOC mode. Reported by Nico S. +- Changed recordset constructor and _initrs() for oci8 so that it returns the field definitions even if no rows in the recordset. Reported by Rick Hickerson (rhickers#mv.mv.com). +- Improved support for postgresql in GetInsertSQL and GetUpdateSQL by "mike" mike#partner2partner.com and "Ryan Bailey" rebel#windriders.com + +## 1.64 - 20 Dec 2001 + +- Danny Milosavljevic added some patches for MySQL error handling and displaying default values. +- Fixed some ADODB_FETCH_BOTH inconsistencies in odbc and interbase. +- Added more tests to test suite to cover ADODB_FETCH_* and ADODB_ERROR_HANDLER. +- Added firebird (ibase) driver +- Added borland_ibase driver for interbase 6.5 + +## 1.63 - 13 Dec 2001 + +- Absolute to the adodb-lib.inc.php file not set properly. Fixed. + +## 1.62 - 11 Dec 2001 + +- Major speedup of ADOdb for low-end web sites by reducing the php code loading and compiling cycle. We conditionally compile not so common functions. Moved csv code to adodb-csvlib.inc.php to reduce adodb.inc.php parsing. This file is loaded only when the csv/proxy driver is used, or CacheExecute() is run. Also moved PageExecute(), GetSelectSQL() and GetUpdateSQL() core code to adodb-lib.inc.php. This reduced the 70K main adodb.inc.php file to 55K, and since at least 20K of the file is comments, we have reduced 50K of code in adodb.inc.php to 35K. There should be 35% reduction in memory and thus 35% speedup in compiling the php code for the main adodb.inc.php file. +- Highly tuned SelectLimit() for oci8 for massive speed improvements on large files. Selecting 20 rows starting from the 20,000th row of a table is now 7 times faster. Thx to Tomas V V Cox. +- Allow . and # in table definitions in GetInsertSQL and GetUpdateSQL. See ADODB_TABLE_REGEX constant. Thx to Ari Kuorikoski. +- Added ADODB_PREFETCH_ROWS constant, defaulting to 10\. This determines the number of records to prefetch in a SELECT statement. Only used by oci8. +- Added high portability Oracle class called oci8po. This uses ? for bind variables, and lower cases column names. +- Now all database drivers support $ADODB_FETCH_MODE, including interbase, ado, and odbc: ADODB_FETCH_NUM and ADODB_FETCH_ASSOC. ADODB_FETCH_BOTH is not fully implemented for all database drivers. + +## 1.61 - Nov 2001 +- Added PO_RecordCount() and PO_Insert_ID(). PO stands for portable. Pablo Roca [pabloroca#mvps.org] +- GenID now returns 0 if not available. Safer is that you should check $conn->hasGenID for availability. +- M'soft ADO we now correctly close recordset in _close() peterd#telephonetics.co.uk +- MSSQL now supports GenID(). It generates a 16-byte GUID from mssql newid() function. +- Changed ereg_replace to preg_replace in SelectLimit. This is a fix for mssql. Ereg doesn't support t or n! Reported by marino Carlos xaplo#postnuke-espanol.org +- Added $recordset->connection. This is the ADOConnection object for the recordset. Works with cached and normal recordsets. Surprisingly, this had no affect on performance! + +## 1.54 - 15 Nov 2001 + +- Fixed some more bugs in PageExecute(). I am getting sick of bug in this and will have to reconsider my QA here. The main issue is that I don't use PageExecute() and to check whether it is working requires a visual inspection of the html generated currently. It is possible to write a test script but it would be quite complicated :( +- More speedups of SelectLimit() for DB2, Oci8, access, vfp, mssql. + +## 1.53 - 7 Nov 2001 + +- Added support for ADODB_FETCH_ASSOC for ado and odbc drivers. +- Tuned GetRowAssoc(false) in postgresql and mysql. +- Stephen Van Dyke contributed ADOdb icon, accepted with some minor mods. +- Enabled Affected_Rows() for postgresql +- Speedup for Concat() using implode() - Benjamin Curtis ben_curtis#yahoo.com +- Fixed some more bugs in PageExecute() to prevent infinite loops + +## 1.52 - 5 Nov 2001 + +- Spelling error in CacheExecute() caused it to fail. $ql should be $sql in line 625! +- Added fixes for parsing [ and ] in GetUpdateSQL(). + +## 1.51 - 5 Nov 2001 + +- Oci8 SelectLimit() speedup by using OCIFetch(). +- Oci8 was mistakenly reporting errors when $db->debug = true. +- If a connection failed with ODBC, it was not correctly reported - fixed. +- _connectionID was inited to -1, changed to false. +- Added $rs->FetchRow(), to simplify API, ala PEAR DB +- Added PEAR DB compat mode, which is still faster than PEAR! See adodb-pear.inc.php. +- Removed postgres pconnect debugging statement. + +## 1.50 - 31 Oct 2001 + +- ADOdbConnection renamed to ADOConnection, and ADOdbFieldObject to ADOFieldObject. +- PageExecute() now checks for empty $rs correctly, and the errors in the docs on this subject have been fixed. +- odbc_error() does not return 6 digit error correctly at times. Implemented workaround. +- Added ADORecordSet_empty class. This will speedup INSERTS/DELETES/UPDATES because the return object created is much smaller. +- Added Prepare() to odbc, and oci8 (but doesn't work properly for oci8 still). +- Made pgsql a synonym for postgre7, and changed SELECT LIMIT to use OFFSET for compat with postgres 7.2. +- Revised adodb-cryptsession.php thanks to Ari. +- Set resources to false on _close, to force freeing of resources. +- Added adodb-errorhandler.inc.php, adodb-errorpear.inc.php and raiseErrorFn on Freek's urging. +- GetRowAssoc($toUpper=true): $toUpper added as default. +- Errors when connecting to a database were not captured formerly. Now we do it correctly. + +## 1.40 - 19 September 2001 + +- PageExecute() to implement page scrolling added. Code and idea by Iván Oliva. +- Some minor postgresql fixes. +- Added sequence support using GenID() for postgresql, oci8, mysql, interbase. +- Added UpdateBlob support for interbase (untested). +- Added encrypted sessions (see adodb-cryptsession.php). By Ari Kuorikoski + +## 1.31 - 21 August 2001 + +- Many bug fixes thanks to "GaM3R (Cameron)" . Some session changes due to Gam3r. +- Fixed qstr() to quote also. +- rs2html() now pretty printed. +- Jonathan Younger contributed the great idea GetUpdateSQL() and GetInsertSQL() which generates SQL to update and insert into a table from a recordset. Modify the recordset fields array, then can this function to generate the SQL (the SQL is not executed). +- Nicola Fankhauser found some bugs in date handling for mssql. +- Added minimal Oracle support for LOBs. Still under development. +- Added $ADODB_FETCH_MODE so you can control whether recordsets return arrays which are numeric, associative or both. This is a global variable you set. Currently only MySQL, Oci8, Postgres drivers support this. +- PostgreSQL properly closes recordsets now. Reported by several people. +- Added UpdateBlob() for Oracle. A hack to make it easier to save blobs. +- Oracle timestamps did not display properly. Fixed. + +## 1.20 - 6 June 2001 + +- Now Oracle can connect using tnsnames.ora or server and service name +- Extensive Oci8 speed optimizations. Oci8 code revised to support variable binding, and /*+ FIRST_ROWS */ hint. +- Worked around some 4.0.6 bugs in odbc_fetch_into(). +- Paolo S. Asioli paolo.asioli#libero.it suggested GetRowAssoc(). +- Escape quotes for oracle wrongly set to '. Now '' is used. +- Variable binding now works in ODBC also. +- Jumped to version 1.20 because I don't like 13 :-) + +## 1.12 - 6 June 2001 + +- Changed $ADODB_DIR to ADODB_DIR constant to plug a security loophole. +- Changed _close() to close persistent connections also. Prevents connection leaks. +- Major revision of oracle and oci8 drivers. Added OCI_RETURN_NULLS and OCI_RETURN_LOBS to OCIFetchInto(). BLOB, CLOB and VARCHAR2 recognition in MetaType() improved. MetaColumns() returns columns in correct sort order. +- Interbase timestamp input format was wrong. Fixed. + +## 1.11 - 20 May 2001 + +- Improved file locking for Windows. +- Probabilistic flushing of cache to avoid avalanche updates when cache timeouts. +- Cached recordset timestamp not saved in some scenarios. Fixed. + +## 1.10 - 19 May 2001 + +- Added caching. CacheExecute() and CacheSelectLimit(). +- Added csv driver. +- Fixed SelectLimit(), SELECT TOP not working under certain circumstances. +- Added better Frontbase support of MetaTypes() by Frank M. Kromann. + +## 1.01 - 24 April 2001 + +- Fixed SelectLimit bug. not quoted properly. +- SelectLimit: SELECT TOP -1 * FROM TABLE not support by Microsoft. Fixed. +- GetMenu improved by glen.davies#cce.ac.nz to support multiple hilited items +- FetchNextObject() did not work with only 1 record returned. Fixed bug reported by $tim#orotech.net +- Fixed mysql field max_length problem. Fix suggested by Jim Nicholson (jnich#att.com) + +## 1.00 - 16 April 2001 + +- Given some brilliant suggestions on how to simplify ADOdb by akul. You no longer need to setup $ADODB_DIR yourself, and ADOLoadCode() is automatically called by ADONewConnection(), simplifying the startup code. +- FetchNextObject() added. Suggested by Jakub Marecek. This makes FetchObject() obsolete, as this is more flexible and powerful. +- Misc fixes to SelectLimit() to support Access (top must follow distinct) and Fields() in the array recordset. From Reinhard Balling. + +## 0.96 - 27 Mar 2001 + +- ADOConnection Close() did not return a value correctly. Thanks to akul#otamedia.com. +- When the horrible magic_quotes is enabled, back-slash () is changed to double-backslash (\). This doesn't make sense for Microsoft/Sybase databases. We fix this in qstr(). +- Fixed Sybase date problem in UnixDate() thanks to Toni Tunkkari. Also fixed MSSQL problem in UnixDate() - thanks to milhouse31#hotmail.com. +- MoveNext() moved to leaf classes for speed in MySQL/PostgreSQL. 10-15% speedup. +- Added null handling in bindInputArray in Execute() -- Ron Baldwin suggestion. +- Fixed some option tags. Thanks to john#jrmstudios.com. + +## 0.95 - 13 Mar 2001 + +- Added postgres7 database driver which supports LIMIT and other version 7 stuff in the future. +- Added SelectLimit to ADOConnection to simulate PostgreSQL's "select * from table limit 10 offset 3". Added helper function GetArrayLimit() to ADORecordSet. +- Fixed mysql metacolumns bug. Thanks to Freek Dijkstra (phpeverywhere#macfreek.com). +- Also many PostgreSQL changes by Freek. He almost rewrote the whole PostgreSQL driver! +- Added fix to input parameters in Execute for non-strings by Ron Baldwin. +- Added new metatype, X for TeXt. Formerly, metatype B for Blob also included text fields. Now 'B' is for binary/image data. 'X' for textual data. +- Fixed $this->GetArray() in GetRows(). +- Oracle and OCI8: 1st parameter is always blank -- now warns if it is filled. +- Now _hasLimit_ and _hasTop_ added to indicate whether SELECT * FROM TABLE LIMIT 10 or SELECT TOP 10 * FROM TABLE are supported. + +## 0.94 - 04 Feb 2001 + +- Added ADORecordSet::GetRows() for compatibility with Microsoft ADO. Synonym for GetArray(). +- Added new metatype 'R' to represent autoincrement numbers. +- Added ADORecordSet.FetchObject() to return a row as an object. +- Finally got a Linux box to test PostgreSql. Many fixes. +- Fixed copyright misspellings in 0.93. +- Fixed mssql MetaColumns type bug. +- Worked around odbc bug in PHP4 for sessions. +- Fixed many documentation bugs (affected_rows, metadatabases, qstr). +- Fixed MySQL timestamp format (removed comma). +- Interbase driver did not call ibase_pconnect(). Fixed. + +## 0.93 - 18 Jan 2002 + +- Fixed GetMenu bug. +- Simplified Interbase commit and rollback. +- Default behaviour on closing a connection is now to rollback all active transactions. +- Added field object handling for array recordset for future XML compatibility. +- Added arr2html() to convert array to html table. + +## 0.92 - 2 Jan 2002 + +- Interbase Commit and Rollback should be working again. +- Changed initialisation of ADORecordSet. This is internal and should not affect users. We are doing this to support cached recordsets in the future. +- Implemented ADORecordSet_array class. This allows you to simulate a database recordset with an array. +- Added UnixDate() and UnixTimeStamp() to ADORecordSet. + +## 0.91 - 21 Dec 2000 + +- Fixed ODBC so ErrorMsg() is working. +- Worked around ADO unrecognised null (0x1) value problem in COM. +- Added Sybase support for FetchField() type +- Removed debugging code and unneeded html from various files +- Changed to javadoc style comments to adodb.inc.php. +- Added maxsql as synonym for mysqlt +- Now ODBC downloads first 8K of blob by default + +## 0.90 - 15 Nov 2000 + +- Lots of testing of Microsoft ADO. Should be more stable now. +- Added $ADODB_COUNTREC. Set to false for high speed selects. +- Added Sybase support. Contributed by Toni Tunkkari (toni.tunkkari#finebyte.com). Bug in Sybase API: GetFields is unable to determine date types. +- Changed behaviour of RecordSet.GetMenu() to support size parameter (listbox) properly. +- Added emptyDate and emptyTimeStamp to RecordSet class that defines how to represent empty dates. +- Added MetaColumns($table) that returns an array of ADOFieldObject's listing the columns of a table. +- Added transaction support for PostgresSQL -- thanks to "Eric G. Werk" egw#netguide.dk. +- Added adodb-session.php for session support. + +## 0.80 - 30 Nov 2000 + +- Added support for charSet for interbase. Implemented MetaTables for most databases. PostgreSQL more extensively tested. + +## 0.71 - 22 Nov 2000 + +- Switched from using require_once to include/include_once for backward compatibility with PHP 4.02 and earlier. + +## 0.70 - 15 Nov 2000 + +- Calls by reference have been removed (call_time_pass_reference=Off) to ensure compatibility with future versions of PHP, except in Oracle 7 driver due to a bug in php_oracle.dll. +- PostgreSQL database driver contributed by Alberto Cerezal (acerezalp#dbnet.es). +- Oci8 driver for Oracle 8 contributed by George Fourlanos (fou#infomap.gr). +- Added _mysqlt_ database driver to support MySQL 3.23 which has transaction support. +- Oracle default date format (DD-MON-YY) did not match ADOdb default date format (which is YYYY-MM-DD). Use ALTER SESSION to force the default date. +- Error message checking is now included in test suite. +- MoveNext() did not check EOF properly -- fixed. + +## 0.60 - 8 Nov 2000 + +- Fixed some constructor bugs in ODBC and ADO. Added ErrorNo function to ADOConnection class. + +## 0.51 - 18 Oct 2000 + +- Fixed some interbase bugs. + +## 0.50 - 16 Oct 2000 + +- Interbase commit/rollback changed to be compatible with PHP 4.03\. +- CommitTrans( ) will now return true if transactions not supported. +- Conversely RollbackTrans( ) will return false if transactions not supported. + +## 0.46 - 12 Oct 2000 + +- Many Oracle compatibility issues fixed. + +## 0.40 - 26 Sept 2000 + +- Many bug fixes +- Now Code for BeginTrans, CommitTrans and RollbackTrans is working. So is the Affected_Rows and Insert_ID. Added above functions to test.php. +- ADO type handling was busted in 0.30\. Fixed. +- Generalised Move( ) so it works will all databases, including ODBC. + +## 0.30 - 18 Sept 2000 + +- Renamed ADOLoadDB to ADOLoadCode. This is clearer. +- Added BeginTrans, CommitTrans and RollbackTrans functions. +- Added Affected_Rows() and Insert_ID(), _affectedrows() and _insertID(), ListTables(), ListDatabases(), ListColumns(). +- Need to add New_ID() and hasInsertID and hasAffectedRows, autoCommit + +## 0.20 - 12 Sept 2000 + +- Added support for Microsoft's ADO. +- Added new field to ADORecordSet -- canSeek +- Added new parameter to _fetch($ignore_fields = false). Setting to true will not update fields array for faster performance. +- Added new field to ADORecordSet/ADOConnection -- dataProvider to indicate whether a class is derived from odbc or ado. +- Changed class ODBCFieldObject to ADOFieldObject -- not documented currently. +- Added benchmark.php and testdatabases.inc.php to the test suite. +- Added to ADORecordSet FastForward( ) for future high speed scrolling. Not documented. +- Realised that ADO's Move( ) uses relative positioning. ADOdb uses absolute. + +## 0.10 - 9 Sept 2000 + +- First release diff --git a/www/include/adodb/docs/changelog_v3.x.md b/www/include/adodb/docs/changelog_v3.x.md new file mode 100644 index 00000000..500c8669 --- /dev/null +++ b/www/include/adodb/docs/changelog_v3.x.md @@ -0,0 +1,242 @@ +# ADOdb old Changelog - v3.x + +See the [Current Changelog](changelog.md). +Older changelogs: +[v2.x](changelog_v2.x.md). + + +## 3.94 - 11 Oct 2003 + +- Create trigger in datadict-oci8.inc.php did not work, because all cr/lf's must be removed. +- ErrorMsg()/ErrorNo() did not work for many databases when logging enabled. Fixed. +- Removed global variable $ADODB_LOGSQL as it does not work properly with multiple connections. +- Added SQLDate support for sybase. Thx to Chris Phillipson +- Postgresql checking of pgsql resultset resource was incorrect. Fix by Bharat Mediratta bharat#menalto.com. Same patch applied to _insertid and _affectedrows for adodb-postgres64.inc.php. +- Added support for NConnect for postgresql. +- Added Sybase data dict support. Thx to Chris Phillipson +- Extensive improvements in $perf->UI(), eg. Explain now opens in new window, we show scripts which call sql, etc. +- Perf Monitor UI works with magic quotes enabled. +- rsPrefix was declared twice. Removed. +- Oci8 stored procedure support, eg. "begin func(); end;" was incorrect in _query. Fixed. +- Tiraboschi Massimiliano contributed italian language file. +- Fernando Ortiz, fortiz#lacorona.com.mx, contributed informix performance monitor. +- Added _varchar (varchar arrays) support for postgresql. Reported by PREVOT Stéphane. + + +## 3.92 - 22 Sept 2003 + +- Added GetAssoc and CacheGetAssoc to connection object. +- Removed TextMax and CharMax functions from adodb.inc.php. +- HasFailedTrans() returned false when trans failed. Fixed. +- Moved perf driver classes into adodb/perf/*.php. +- Misc improvements to performance monitoring, including UI(). +- RETVAL in mssql Parameter(), we do not append @ now. +- Added Param($name) to connection class, returns '?' or ":$name", for defining bind parameters portably. +- LogSQL traps affected_rows() and saves its value properly now. Also fixed oci8 _stmt and _affectedrows() bugs. +- Session code timestamp check for oci8 works now. Formerly default NLS_DATE_FORMAT stripped off time portion. Thx to Tony Blair (tonanbarbarian#hotmail.com). Also added new $conn->datetime field to oci8, controls whether MetaType() returns 'D' ($this->datetime==false) or 'T' ($this->datetime == true) for DATE type. +- Fixed bugs in adodb-cryptsession.inc.php and adodb-session-clob.inc.php. +- Fixed misc bugs in adodb_key_exists, GetInsertSQL() and GetUpdateSQL(). +- Tuned include_once handling to reduce file-system checking overhead. + +## 3.91 - 9 Sept 2003 + +- Only released to InterAkt +- Added LogSQL() for sql logging and $ADODB_NEWCONNECTION to override factory for driver instantiation. +- Added IfNull($field,$ifNull) function, thx to johnwilk#juno.com +- Added portable substr support. +- Now rs2html() has new parameter, $echo. Set to false to return $html instead of echoing it. + +## 3.90 - 5 Sept 2003 + +- First beta of performance monitoring released. +- MySQL supports MetaTable() masking. +- Fixed key_exists() bug in adodb-lib.inc.php +- Added sp_executesql Prepare() support to mssql. +- Added bind support to db2. +- Added swedish language file - Christian Tiberg" christian#commsoft.nu +- Bug in drop index for mssql data dict fixed. Thx to Gert-Rainer Bitterlich. +- Left join setting for oci8 was wrong. Thx to johnwilk#juno.com + +## 3.80 - 27 Aug 2003 + +- Patch for PHP 4.3.3 cached recordset csv2rs() fread loop incompatibility. +- Added matching mask for MetaTables. Only for oci8, mssql and postgres currently. +- Rewrite of "oracle" driver connection code, merging with "oci8", by Gaetano. +- Added better debugging for Smart Transactions. +- Postgres DBTimeStamp() was wrongly using TO_DATE. Changed to TO_TIMESTAMP. +- ADODB_FETCH_CASE check pushed to ADONewConnection to allow people to define it after including adodb.inc.php. +- Added portuguese (brazilian) to languages. Thx to "Levi Fukumori". +- Removed arg3 parameter from Execute/SelectLimit/Cache* functions. +- Execute() now accepts 2-d array as $inputarray. Also changed docs of fnExecute() to note change in sql query counting with 2-d arrays. +- Added MONEY to MetaType in PostgreSQL. +- Added more debugging output to CacheFlush(). + +## 3.72 - 9 Aug 2003 + +- Added qmagic($str), which is a qstr($str) that auto-checks for magic quotes and does the right thing... +- Fixed CacheFlush() bug - Thx to martin#gmx.de +- Walt Boring contributed MetaForeignKeys for postgres7. +- _fetch() called _BlobDecode() wrongly in interbase. Fixed. +- adodb_time bug fixed with dates after 2038 fixed by Jason Pell. PHPLens Issue No: 6980 + +## 3.71 - 4 Aug 2003 + +- The oci8 driver, MetaPrimaryKeys() did not check the owner correctly when $owner == false. +- Russian language file contributed by "Cyrill Malevanov" cyrill#malevanov.spb.ru. +- Spanish language file contributed by "Horacio Degiorgi" horaciod#codigophp.com. +- Error handling in oci8 bugfix - if there was an error in Execute(), then when calling ErrorNo() and/or ErrorMsg(), the 1st call would return the error, but the 2nd call would return no error. +- Error handling in odbc bugfix. ODBC would always return the last error, even if it happened 5 queries ago. Now we reset the errormsg to '' and errorno to 0 every time before CacheExecute() and Execute(). + +## 3.70 - 29 July 2003 + +- Added new SQLite driver. Tested on PHP 4.3 and PHP 5. +- Added limited "sapdb" driver support - mainly date support. +- The oci8 driver did not identify NUMBER with no defined precision correctly. +- Added ADODB_FORCE_NULLS, if set, then PHP nulls are converted to SQL nulls in GetInsertSQL/GetUpdateSQL. +- DBDate() and DBTimeStamp() format for postgresql had problems. Fixed. +- Added tableoptions to ChangeTableSQL(). Thx to Mike Benoit. +- Added charset support to postgresql. Thx to Julian Tarkhanov. +- Changed OS check for MS-Windows to prevent confusion with darWIN (MacOS) +- Timestamp format for db2 was wrong. Changed to yyyy-mm-dd-hh.mm.ss.nnnnnn. +- adodb-cryptsession.php includes wrong. Fixed. +- Added MetaForeignKeys(). Supported by mssql, odbc_mssql and oci8. +- Fixed some oci8 MetaColumns/MetaPrimaryKeys bugs. Thx to Walt Boring. +- adodb_getcount() did not init qryRecs to 0\. Missing "WHERE" clause checking in GetUpdateSQL fixed. Thx to Sebastiaan van Stijn. +- Added support for only 'VIEWS' and "TABLES" in MetaTables. From Walt Boring. +- Upgraded to adodb-xmlschema.inc.php 0.0.2. +- NConnect for mysql now returns value. Thx to Dennis Verspuij. +- ADODB_FETCH_BOTH support added to interbase/firebird. +- Czech language file contributed by Kamil Jakubovic jake#host.sk. +- PostgreSQL BlobDecode did not use _connectionID properly. Thx to Juraj Chlebec. +- Added some new initialization stuff for Informix. Thx to "Andrea Pinnisi" pinnisi#sysnet.it +- ADODB_ASSOC_CASE constant wrong in sybase _fetch(). Fixed. + +## 3.60 - 16 June 2003 + +- We now SET CONCAT_NULL_YIELDS_NULL OFF for odbc_mssql driver to be compat with mssql driver. +- The property $emptyDate missing from connection class. Also changed 1903 to constant (TIMESTAMP_FIRST_YEAR=100). Thx to Sebastiaan van Stijn. +- ADOdb speedup optimization - we now return all arrays by reference. +- Now DBDate() and DBTimeStamp() now accepts the string 'null' as a parameter. Suggested by vincent. +- Added GetArray() to connection class. +- Added not_null check in informix metacolumns(). +- Connection parameters for postgresql did not work correctly when port was defined. +- DB2 is now a tested driver, making adodb 100% compatible. Extensive changes to odbc driver for DB2, including implementing serverinfo() and SQLDate(), switching to SQL_CUR_USE_ODBC as the cursor mode, and lastAffectedRows and SelectLimit() fixes. +- The odbc driver's FetchField() field names did not obey ADODB_ASSOC_CASE. Fixed. +- Some bugs in adodb_backtrace() fixed. +- Added "INT IDENTITY" type to adorecordset::MetaType() to support odbc_mssql properly. +- MetaColumns() for oci8, mssql, odbc revised to support scale. Also minor revisions to odbc MetaColumns() for vfp and db2 compat. +- Added unsigned support to mysql datadict class. Thx to iamsure. +- Infinite loop in mssql MoveNext() fixed when ADODB_FETCH_ASSOC used. Thx to Josh R, Night_Wulfe#hotmail.com. +- ChangeTableSQL contributed by Florian Buzin. +- The odbc_mssql driver now sets CONCAT_NULL_YIELDS_NULL OFF for compat with mssql driver. + +## 3.50 - 19 May 2003 + +- Fixed mssql compat with FreeTDS. FreeTDS does not implement mssql_fetch_assoc(). +- Merged back connection and recordset code into adodb.inc.php. +- ADOdb sessions using oracle clobs contributed by achim.gosse#ddd.de. See adodb-session-clob.php. +- Added /s modifier to preg_match everywhere, which ensures that regex does not stop at /n. Thx Pao-Hsi Huang. +- Fixed error in metacolumns() for mssql. +- Added time format support for SQLDate. +- Image => B added to metatype. +- MetaType now checks empty($this->blobSize) instead of empty($this). +- Datadict has beta support for informix, sybase (mapped to mssql), db2 and generic (which is a fudge). +- BlobEncode for postgresql uses pg_escape_bytea, if available. Needed for compat with 7.3. +- Added $ADODB_LANG, to support multiple languages in MetaErrorMsg(). +- Datadict can now parse table definition as declarative text. +- For DataDict, oci8 autoincrement trigger missing semi-colon. Fixed. +- For DataDict, when REPLACE flag enabled, drop sequence in datadict for autoincrement field in postgres and oci8.s +- Postgresql defaults to template1 database if no database defined in connect/pconnect. +- We now clear _resultid in postgresql if query fails. + +## 3.40 - 19 May 2003 + +- Added insert_id for odbc_mssql. +- Modified postgresql UpdateBlobFile() because it did not work in safe mode. +- Now connection object is passed to raiseErrorFn as last parameter. Needed by StartTrans(). +- Added StartTrans() and CompleteTrans(). It is recommended that you do not modify transOff, but use the above functions. +- oci8po now obeys ADODB_ASSOC_CASE settings. +- Added virtualized error codes, using PEAR DB equivalents. Requires you to manually include adodb-error.inc.php yourself, with MetaError() and MetaErrorMsg($errno). +- GetRowAssoc for mysql and pgsql were flawed. Fix by Ross Smith. +- Added to datadict types I1, I2, I4 and I8\. Changed datadict type 'T' to map to timestamp instead of datetime for postgresql. +- Error handling in ExecuteSQLArray(), adodb-datadict.inc.php did not work. +- We now auto-quote postgresql connection parameters when building connection string. +- Added session expiry notification. +- We now test with odbc mysql - made some changes to odbc recordset constructor. +- MetaColumns now special cases access and other databases for odbc. + +## 3.31 - 17 March 2003 + +- Added row checking for _fetch in postgres. +- Added Interval type to MetaType for postgres. +- Remapped postgres driver to call postgres7 driver internally. +- Adorecordset_array::getarray() did not return array when nRows >= 0. +- Postgresql: at times, no error message returned by pg_result_error() but error message returned in pg_last_error(). Recoded again. +- Interbase blob's now use chunking for updateblob. +- Move() did not set EOF correctly. Reported by Jorma T. +- We properly support mysql timestamp fields when we are creating mysql tables using the data-dict interface. +- Table regex includes backticks character now. + +## 3.30 - 3 March 2003 + +- Added $ADODB_EXTENSION and $ADODB_COMPAT_FETCH constant. +- Made blank1stItem configurable using syntax "value:text" in GetMenu/GetMenu2. Thx to Gabriel Birke. +- Previously ADOdb differed from the Microsoft standard because it did not define what to set $this->fields when EOF was reached. Now at EOF, ADOdb sets $this->fields to false for all databases, which is consist with Microsoft's implementation. Postgresql and mysql have always worked this way (in 3.11 and earlier). If you are experiencing compatibility problems (and you are not using postgresql nor mysql) on upgrading to 3.30, try setting the global variables $ADODB_COUNTRECS = true (which is the default) and $ADODB_FETCH_COMPAT = true (this is a new global variable). +- We now check both pg_result_error and pg_last_error as sometimes pg_result_error does not display anything. Iman Mayes +- We no longer check for magic quotes gpc in Quote(). +- Misc fixes for table creation in adodb-datadict.inc.php. Thx to iamsure. +- Time calculations use adodb_time library for all negative timestamps due to problems in Red Hat 7.3 or later. Formerly, only did this for Windows. +- In mssqlpo, we now check if $sql in _query is a string before we change || to +. This is to support prepared stmts. +- Move() and MoveLast() internals changed to support to support EOF and $this->fields change. +- Added ADODB_FETCH_BOTH support to mssql. Thx to Angel Fradejas afradejas#mediafusion.es +- We now check if link resource exists before we run mysql_escape_string in qstr(). +- Before we flock in csv code, we check that it is not a http url. + +## 3.20 - 17 Feb 2003 + +- Added new Data Dictionary classes for creating tables and indexes. Warning - this is very much alpha quality code. The API can still change. See adodb/tests/test-datadict.php for more info. +- We now ignore $ADODB_COUNTRECS for mysql, because PHP truncates incomplete recordsets when mysql_unbuffered_query() is called a second time. +- Now postgresql works correctly when $ADODB_COUNTRECS = false. +- Changed _adodb_getcount to properly support SELECT DISTINCT. +- Discovered that $ADODB_COUNTRECS=true has some problems with prepared queries - suspect PHP bug. +- Now GetOne and GetRow run in $ADODB_COUNTRECS=false mode for better performance. +- Added support for mysql_real_escape_string() and pg_escape_string() in qstr(). +- Added an intermediate variable for mysql _fetch() and MoveNext() to store fields, to prevent overwriting field array with boolean when mysql_fetch_array() returns false. +- Made arrays for getinsertsql and getupdatesql case-insensitive. Suggested by Tim Uckun" tim#diligence.com + +## 3.11 - 11 Feb 2003 + +- Added check for ADODB_NEVER_PERSIST constant in PConnect(). If defined, then PConnect() will actually call non-persistent Connect(). +- Modified interbase to properly work with Prepare(). +- Added $this->ibase_timefmt to allow you to change the date and time format. +- Added support for $input_array parameter in CacheFlush(). +- Added experimental support for dbx, which was then removed when i found that it was slower than using native calls. +- Added MetaPrimaryKeys for mssql and ibase/firebird. +- Added new $trim parameter to GetCol and CacheGetCol +- Uses updated adodb-time.inc.php 0.06. + +## 3.10 - 27 Jan 2003 + +- Added adodb_date(), adodb_getdate(), adodb_mktime() and adodb-time.inc.php. +- For interbase, added code to handle unlimited number of bind parameters. From Daniel Hasan daniel#hasan.cl. +- Added BlobDecode and UpdateBlob for informix. Thx to Fernando Ortiz. +- Added constant ADODB_WINDOWS. If defined, means that running on Windows. +- Added constant ADODB_PHPVER which stores php version as a hex num. Removed $ADODB_PHPVER variable. +- Felho Bacsi reported a minor white-space regular expression problem in GetInsertSQL. +- Modified ADO to use variant to store _affectedRows +- Changed ibase to use base class Replace(). Modified base class Replace() to support ibase. +- Changed odbc to auto-detect when 0 records returned is wrong due to bad odbc drivers. +- Changed mssql to use datetimeconvert ini setting only when 4.30 or later (does not work in 4.23). +- ExecuteCursor($stmt, $cursorname, $params) now accepts a new $params array of additional bind parameters -- William Lovaton walovaton#yahoo.com.mx. +- Added support for sybase_unbuffered_query if ADODB_COUNTRECS == false. Thx to chuck may. +- Fixed FetchNextObj() bug. Thx to Jorma Tuomainen. +- We now use SCOPE_IDENTITY() instead of @@IDENTITY for mssql - thx to marchesini#eside.it +- Changed postgresql movenext logic to prevent illegal row number from being passed to pg_fetch_array(). +- Postgresql initrs bug found by "Bogdan RIPA" bripa#interakt.ro $f1 accidentally named $f + +## 3.00 - 6 Jan 2003 + +- Fixed adodb-pear.inc.php syntax error. +- Improved _adodb_getcount() to use SELECT COUNT(*) FROM ($sql) for languages that accept it. +- Fixed _adodb_getcount() caching error. +- Added sql to retrieve table and column info for odbc_mssql. diff --git a/www/include/adodb/docs/changelog_v4+5.md b/www/include/adodb/docs/changelog_v4+5.md new file mode 100644 index 00000000..c102ac6a --- /dev/null +++ b/www/include/adodb/docs/changelog_v4+5.md @@ -0,0 +1,109 @@ +## 4.990/5.05 - 11 Jul 2008 + +- Added support for multiple recordsets in mysqli Geisel Sierote . See PHPLens Issue No: 15917 +- Malcolm Cook added new Reload() function to Active Record. See PHPLens Issue No: 17474 +- Thanks Zoltan Monori [monzol#fotoprizma.hu] for bug fixes in iterator, SelectLimit, GetRandRow, etc. +- Under heavy loads, the performance monitor for oci8 disables Ixora views. +- Fixed sybase driver SQLDate to use str_replace(). Also for adodb5, changed sybase driver UnixDate and UnixTimeStamp calls to static. +- Changed oci8 lob handler to use & reference $this->_refLOBs[$numlob]['VAR'] = &$var. +- We now strtolower the get_class() function in PEAR::isError() for php5 compat. +- CacheExecute did not retrieve cache recordsets properly for 5.04 (worked in 4.98). Fixed. +- New ADODB_Cache_File class for file caching defined in adodb.inc.php. +- Farsi language file contribution by Peyman Hooshmandi Raad (phooshmand#gmail.com) +- New API for creating your custom caching class which is stored in $ADODB_CACHE: + ``` +include "/path/to/adodb.inc.php"; +$ADODB_CACHE_CLASS = 'MyCacheClass'; + +class MyCacheClass extends ADODB_Cache_File +{ + function writecache($filename, $contents,$debug=false){...} + function &readcache($filename, &$err, $secs2cache, $rsClass){ ...} + : +} + +$DB = NewADOConnection($driver); +$DB->Connect(...); ## MyCacheClass created here and stored in $ADODB_CACHE global variable. + +$data = $rs->CacheGetOne($sql); ## MyCacheClass is used here for caching... + ``` +- Memcache supports multiple pooled hosts now. Only if none of the pooled servers can be contacted will a connect error be generated. Usage example below: + ``` +$db = NewADOConnection($driver); +$db->memCache = true; /// should we use memCache instead of caching in files +$db->memCacheHost = array($ip1, $ip2, $ip3); /// $db->memCacheHost = $ip1; still works +$db->memCachePort = 11211; /// this is default memCache port +$db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) + +$db->Connect(...); +$db->CacheExecute($sql); + ``` + +## 4.98/5.04 - 13 Feb 2008 + +- Fixed adodb_mktime problem which causes a performance bottleneck in $hrs. +- Added mysqli support to adodb_getcount(). +- Removed MYSQLI_TYPE_CHAR from MetaType(). + +## 4.97/5.03 - 22 Jan 2008 + +- Active Record: $ADODB_ASSOC_CASE=1 did not work properly. Fixed. +- Modified Fields() in recordset class to support display null fields in FetchNextObject(). +- In ADOdb5, active record implementation, we now support column names with spaces in them - we autoconvert the spaces to _ using __set(). Thx Daniel Cook. PHPLens Issue No: 17200 +- Removed $arg3 from mysqli SelectLimit. See PHPLens Issue No: 16243. Thx Zsolt Szeberenyi. +- Changed oci8 FetchField, which returns the max_length of BLOB/CLOB/NCLOB as 4000 (incorrectly) to -1. +- CacheExecute would sometimes return an error on Windows if it was unable to lock the cache file. This is harmless and has been changed to a warning that can be ignored. Also adodb_write_file() code revised. +- ADOdb perf code changed to only log sql if execution time >= 0.05 seconds. New $ADODB_PERF_MIN variable holds min sql timing. Any SQL with timing value below this and is not causing an error is not logged. +- Also adodb_backtrace() now traces 1 level deeper as sometimes actual culprit function is not displayed. +- Fixed a group by problem with adodb_getcount() for db's which are not postgres/oci8 based. +- Changed mssql driver Parameter() from SQLCHAR to SQLVARCHAR: case 'string': $type = SQLVARCHAR; break. +- Problem with mssql driver in php5 (for adodb 5.03) because some functions are not static. Fixed. + +## 4.96/5.02 - 24 Sept 2007 + +ADOdb perf for oci8 now has non-table-locking code when clearing the sql. Slower but better transparency. Added in 4.96a and 5.02a. +Fix adodb count optimisation. Preg_match did not work properly. Also rewrote the ORDER BY stripping code in _adodb_getcount(), adodb-lib.inc.php. +SelectLimit for oci8 not optimal for large recordsets when offset=0. Changed $nrows check. +Active record optimizations. Added support for assoc arrays in Set(). +Now GetOne returns null if EOF (no records found), and false if error occurs. Use ErrorMsg()/ErrorNo() to get the error. +Also CacheGetRow and CacheGetCol will return false if error occurs, or empty array() if EOF, just like GetRow and GetCol. +Datadict now allows changing of types which are not resizable, eg. VARCHAR to TEXT in ChangeTableSQL. -- Mateo Tibaquirá +Added BIT data type support to adodb-ado.inc.php and adodb-ado5.inc.php. +Ldap driver did not return actual ldap error messages. Fixed. +Implemented GetRandRow($sql, $inputarr). Optimized for Oci8. +Changed adodb5 active record to use static SetDatabaseAdapter() and removed php4 constructor. Bas van Beek bas.vanbeek#gmail.com. +Also in adodb5, changed adodb-session2 to use static function declarations in class. Thx Daniel Berlin. +Added "Clear SQL Log" to bottom of Performance screen. +Sessions2 code echo'ed directly to the screen in debug mode. Now uses ADOConnection::outp(). +In mysql/mysqli, qstr(null) will return the string "null" instead of empty quoted string "''". +postgresql optimizeTable in perf-postgres.inc.php added by Daniel Berlin (mail#daniel-berlin.de) +Added 5.2.1 compat code for oci8. +Changed @@identity to SCOPE_IDENTITY() for multiple mssql drivers. Thx Stefano Nari. +Code sanitization introduced in 4.95 caused problems in European locales (as float 3.2 was typecast to 3,2). Now we only sanitize if is_numeric fails. +Added support for customizing ADORecordset_empty using $this->rsPrefix.'empty'. By Josh Truwin. +Added proper support for ALterColumnSQL for Postgresql in datadict code. Thx. Josh Truwin. +Added better support for MetaType() in mysqli when using an array recordset. +Changed parser for pgsql error messages in adodb-error.inc.php to case-insensitive regex. + +## 4.95/5.01 - 17 May 2007 + +CacheFlush debug outp() passed in invalid parameters. Fixed. +Added Thai language file for adodb. Thx Trirat Petchsingh rosskouk#gmail.com +and Marcos Pont +Added zerofill checking support to MetaColumns for mysql and mysqli. +CacheFlush no longer deletes all files/directories. Only *.cache files +deleted. +DB2 timestamp format changed to var $fmtTimeStamp = +"'Y-m-d-H:i:s'"; +Added some code sanitization to AutoExecute in adodb-lib.inc.php. +Due to typo, all connections in adodb-oracle.inc.php would become +persistent, even non-persistent ones. Fixed. +Oci8 DBTimeStamp uses 24 hour time for input now, so you can perform string +comparisons between 2 DBTimeStamp values. +Some PHP4.4 compat issues fixed in adodb-session2.inc.php +For ADOdb 5.01, fixed some adodb-datadict.inc.php MetaType compat issues +with PHP5. +The $argHostname was wiped out in adodb-ado5.inc.php. Fixed. +Adodb5 version, added iterator support for adodb_recordset_empty. +Adodb5 version,more error checking code now will use exceptions if +available. diff --git a/www/include/adodb/docs/changelog_v4.x.md b/www/include/adodb/docs/changelog_v4.x.md new file mode 100644 index 00000000..8b064440 --- /dev/null +++ b/www/include/adodb/docs/changelog_v4.x.md @@ -0,0 +1,717 @@ +# ADOdb old Changelog - v4.x + +See the [Current Changelog](changelog.md). +Older changelogs: +[v3.x](changelog_v3.x.md), +[v2.x](changelog_v2.x.md). + + +## 4.990 - 11 Jul 2008 + +- Added support for multiple recordsets in mysqli Geisel Sierote . See PHPLens Issue No: 15917 +- Malcolm Cook added new Reload() function to Active Record. See PHPLens Issue No: 17474 +- Thanks Zoltan Monori [monzol#fotoprizma.hu] for bug fixes in iterator, SelectLimit, GetRandRow, etc. +- Under heavy loads, the performance monitor for oci8 disables Ixora views. +- Fixed sybase driver SQLDate to use str_replace(). Also for adodb5, changed sybase driver UnixDate and UnixTimeStamp calls to static. +- Changed oci8 lob handler to use & reference $this->_refLOBs[$numlob]['VAR'] = &$var. +- We now strtolower the get_class() function in PEAR::isError() for php5 compat. +- CacheExecute did not retrieve cache recordsets properly for 5.04 (worked in 4.98). Fixed. +- New ADODB_Cache_File class for file caching defined in adodb.inc.php. +- Farsi language file contribution by Peyman Hooshmandi Raad (phooshmand#gmail.com) +- New API for creating your custom caching class which is stored in $ADODB_CACHE: + ``` + include "/path/to/adodb.inc.php"; + $ADODB_CACHE_CLASS = 'MyCacheClass'; + + class MyCacheClass extends ADODB_Cache_File + { + function writecache($filename, $contents,$debug=false){...} + function &readcache($filename, &$err, $secs2cache, $rsClass){ ...} + : + } + + $DB = NewADOConnection($driver); + $DB->Connect(...); ## MyCacheClass created here and stored in $ADODB_CACHE global variable. + + $data = $rs->CacheGetOne($sql); ## MyCacheClass is used here for caching... + ``` +- Memcache supports multiple pooled hosts now. Only if none of the pooled servers can be contacted will a connect error be generated. Usage example below: + ``` + $db = NewADOConnection($driver); + $db->memCache = true; /// should we use memCache instead of caching in files + $db->memCacheHost = array($ip1, $ip2, $ip3); /// $db->memCacheHost = $ip1; still works + $db->memCachePort = 11211; /// this is default memCache port + $db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) + + $db->Connect(...); + $db->CacheExecute($sql); + ``` + +## 4.98 - 13 Feb 2008 + +- Fixed adodb_mktime problem which causes a performance bottleneck in $hrs. +- Added mysqli support to adodb_getcount(). +- Removed MYSQLI_TYPE_CHAR from MetaType(). + +## 4.97 - 22 Jan 2008 + +- Active Record: $ADODB_ASSOC_CASE=1 did not work properly. Fixed. +- Modified Fields() in recordset class to support display null fields in FetchNextObject(). +- In ADOdb5, active record implementation, we now support column names with spaces in them - we autoconvert the spaces to `_` using `__set()`. Thx Daniel Cook. PHPLens Issue No: 17200 +- Removed $arg3 from mysqli SelectLimit. See PHPLens Issue No: 16243. Thx Zsolt Szeberenyi. +- Changed oci8 FetchField, which returns the max_length of BLOB/CLOB/NCLOB as 4000 (incorrectly) to -1. +- CacheExecute would sometimes return an error on Windows if it was unable to lock the cache file. This is harmless and has been changed to a warning that can be ignored. Also adodb_write_file() code revised. +- ADOdb perf code changed to only log sql if execution time >= 0.05 seconds. New $ADODB_PERF_MIN variable holds min sql timing. Any SQL with timing value below this and is not causing an error is not logged. +- Also adodb_backtrace() now traces 1 level deeper as sometimes actual culprit function is not displayed. +- Fixed a group by problem with adodb_getcount() for db's which are not postgres/oci8 based. +- Changed mssql driver Parameter() from SQLCHAR to SQLVARCHAR: case 'string': $type = SQLVARCHAR; break. +- Problem with mssql driver in php5 (for adodb 5.03) because some functions are not static. Fixed. + +## 4.96 - 24 Sept 2007 + +- ADOdb perf for oci8 now has non-table-locking code when clearing the sql. Slower but better transparency. Added in 4.96a and 5.02a. +- Fix adodb count optimisation. Preg_match did not work properly. Also rewrote the ORDER BY stripping code in _adodb_getcount(), adodb-lib.inc.php. +- SelectLimit for oci8 not optimal for large recordsets when offset=0. Changed $nrows check. +- Active record optimizations. Added support for assoc arrays in Set(). +- Now GetOne returns null if EOF (no records found), and false if error occurs. Use ErrorMsg()/ErrorNo() to get the error. +- Also CacheGetRow and CacheGetCol will return false if error occurs, or empty array() if EOF, just like GetRow and GetCol. +- Datadict now allows changing of types which are not resizable, eg. VARCHAR to TEXT in ChangeTableSQL. -- Mateo Tibaquirá +- Added BIT data type support to adodb-ado.inc.php and adodb-ado5.inc.php. +- Ldap driver did not return actual ldap error messages. Fixed. +- Implemented GetRandRow($sql, $inputarr). Optimized for Oci8. +- Changed adodb5 active record to use static SetDatabaseAdapter() and removed php4 constructor. Bas van Beek bas.vanbeek#gmail.com. +- Also in adodb5, changed adodb-session2 to use static function declarations in class. Thx Daniel Berlin. +- Added "Clear SQL Log" to bottom of Performance screen. +- Sessions2 code echo'ed directly to the screen in debug mode. Now uses ADOConnection::outp(). +- In mysql/mysqli, qstr(null) will return the string "null" instead of empty quoted string "''". +- postgresql optimizeTable in perf-postgres.inc.php added by Daniel Berlin (mail#daniel-berlin.de) +- Added 5.2.1 compat code for oci8. +- Changed @@identity to SCOPE_IDENTITY() for multiple mssql drivers. Thx Stefano Nari. +- Code sanitization introduced in 4.95 caused problems in European locales (as float 3.2 was typecast to 3,2). Now we only sanitize if is_numeric fails. +- Added support for customizing ADORecordset_empty using $this->rsPrefix.'empty'. By Josh Truwin. +- Added proper support for ALterColumnSQL for Postgresql in datadict code. Thx. Josh Truwin. +- Added better support for MetaType() in mysqli when using an array recordset. +- Changed parser for pgsql error messages in adodb-error.inc.php to case-insensitive regex. + +## 4.95 - 17 May 2007 + +- CacheFlush debug outp() passed in invalid parameters. Fixed. +- Added Thai language file for adodb. Thx Trirat Petchsingh rosskouk#gmail.com and Marcos Pont +- Added zerofill checking support to MetaColumns for mysql and mysqli. +- CacheFlush no longer deletes all files directories. Only `*.cache` files deleted. +- DB2 timestamp format changed to var $fmtTimeStamp = 'Y-m-d-H:i:s'; +- Added some code sanitization to AutoExecute in adodb-lib.inc.php. +- Due to typo, all connections in adodb-oracle.inc.php would become persistent, even non-persistent ones. Fixed. +- Oci8 DBTimeStamp uses 24 hour time for input now, so you can perform string comparisons between 2 DBTimeStamp values. +- Some PHP4.4 compat issues fixed in adodb-session2.inc.php +- For ADOdb 5.01, fixed some adodb-datadict.inc.php MetaType compat issues with PHP5. +- The $argHostname was wiped out in adodb-ado5.inc.php. Fixed. +- Adodb5 version, added iterator support for adodb_recordset_empty. +- Adodb5 version,more error checking code now will use exceptions if available. + +## 4.94 - 23 Jan 2007 + +- Active Record: $ADODB_ASSOC_CASE=2 did not work properly. Fixed. Thx gmane#auxbuss.com. +- mysqli had bugs in BeginTrans() and EndTrans(). Fixed. +- Improved error handling when no database is connected for oci8. Thx Andy Hassall. +- Names longer than 30 chars in oci8 datadict will be changed to random name. Thx Eugenio. PHPLens Issue No: 16182 +- Added var $upperCase = 'ucase' to access and ado_access drivers. Thx Renato De Giovanni renato#cria.org.br +- Postgres64 driver, if preparing plan failed in _query, did not handle error properly. Fixed. See PHPLens Issue No: 16131. +- Fixed GetActiveRecordsClass() reference bug. See PHPLens Issue No: 16120 +- Added handling of nulls in adodb-ado_mssql.inc.php for qstr(). Thx to Felix Rabinovich. +- Adodb-dict contributions by Gaetano + - Support for INDEX in data-dict. Example: idx_ev1. The ability to define indexes using the INDEX keyword was added in ADOdb 4.94. The following example features multiple indexes, including a compound index idx_ev1. + + ``` + event_id I(11) NOTNULL AUTOINCREMENT PRIMARY, + event_type I(4) NOTNULL + event_start_date T DEFAULT NULL **INDEX id_esd**, + event_end_date T DEFAULT '0000-00-00 00:00:00' **INDEX id_eted**, + event_parent I(11) UNSIGNED NOTNULL DEFAULT 0 **INDEX id_evp**, + event_owner I(11) DEFAULT 0 **INDEX idx_ev1**, + event_project I(11) DEFAULT 0 **INDEX idx_ev1**, + event_times_recuring I(11) UNSIGNED NOTNULL DEFAULT 0, + event_icon C(20) DEFAULT 'obj/event', + event_description X + ``` + + - Prevents the generated SQL from including double drop-sequence statements for REPLACE case of tables with autoincrement columns (on those dbs that emulate it via sequences) + - makes any date defined as DEFAULT value for D and T columns work cross-database, not just the "sysdate" value (as long as it is specified using adodb standard format). See above example. +- Fixed pdo's GetInsertID() support. Thx Ricky Su. +- oci8 Prepare() now sets error messages if an error occurs. +- Added 'PT_BR' to SetDateLocale() -- brazilian portuguese. +- charset in oci8 was not set correctly on `*Connect()` +- ADOConnection::Transpose() now appends as first column the field names. +- Added $ADODB_QUOTE_FIELDNAMES. If set to true, will autoquote field names in AutoExecute(),GetInsertSQL(), GetUpdateSQL(). +- Transpose now adds the field names as the first column after transposition. +- Added === check in ADODB_SetDatabaseAdapter for $db, adodb-active-record.inc.php. Thx Christian Affolter. +- Added ErrorNo() to adodb-active-record.inc.php. Thx ante#novisplet.com. + +## 4.93 - 10 Oct 2006 + +- Added support for multiple database connections in performance monitoring code (adodb-perf.inc.php). Now all sql in multiple database connections can be saved into one database ($ADODB_LOG_CONN). +- Added MetaIndexes() to odbc_mssql. +- Added connection property $db->null2null = 'null'. In autoexecute/getinsertsql/getupdatesql, this value will be converted to a null. Set this to a funny invalid value if you do not want null conversion. See PHPLens Issue No: 15902. +- Path disclosure problem in mysqli fixed. Thx Andy. +- Fixed typo in session_schema2.xml. +- Changed INT in oci8 to return correct precision in $fld->max_length, MetaColumns(). Thx Eloy Lafuente Plaza. +- Patched postgres64 _connect to handle serverinfo(). see PHPLens Issue No: 15887. +- Added pdo fix for null columns. See PHPLens Issue No: 15889 +- For stored procedures, missing connection id now passed into mssql_query(). Thx Ecsy (ecsy#freemail.hu). + +## 4.92a - 30 Aug 2006 + +- Syntax error in postgres7 driver. Thx Eloy Lafuente Plaza. +- Minor bug fixes - adodb informix 10 types added to adodb.inc.php. Thx Fernando Ortiz. + +## 4.92 - 29 Aug 2006 + +- Better odbtp date support. +- Added IgnoreErrors() to bypass default error handling. +- The _adodb_getcount() function in adodb-lib.inc.php, some ORDER BY bug fixes. +- For ibase and firebird, set $sysTimeStamp = "CURRENT_TIMESTAMP". +- Fixed postgres connection bug: PHPLens Issue No: 11057. +- Changed CacheSelectLimit() to flush cache when $secs2cache==-1 due to complaints from other users. +- Added support for using memcached with CacheExecute/CacheSelectLimit. Requires memcache module PECL extension. Usage: + ``` + $db = NewADOConnection($driver); + $db->memCache = true; /// should we use memCache instead of caching in files + $db->memCacheHost = "126.0.1.1"; /// memCache host + $db->memCachePort = 11211; /// this is default memCache port + $db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) + $db->Connect(...); + $db->CacheExecute($sql); + ``` + +- Implemented Transpose() for recordsets. Recordset must be retrieved using ADODB_FETCH_NUM. First column becomes the column name. + ``` + $db = NewADOConnection('mysql'); + $db->Connect(...); + $db->SetFetchMode(ADODB_FETCH_NUM); + $rs = $db->Execute('select productname,productid,unitprice from products limit 10'); + $rs2 = $db->Transpose($rs); + rs2html($rs2); + ``` + +## 4.91 - 2 Aug 2006 + +- Major session code rewrite... See session docs. +- PDO bindinputarray() was not set properly for MySQL (changed from true to false). +- Changed CacheSelectLimit() to re-cache when $secs2cache==0. This is one way to flush the cache when SelectLimit is called. +- Added to quotes to mysql and mysqli: "SHOW COLUMNS FROM \`%s\`"; +- Removed accidental optgroup handling in GetMenu(). Fixed ibase _BlobDecode for php5 compat, and also mem alloc issues for small blobs, thx salvatori#interia.pl +- Mysql driver OffsetDate() speedup, useful for adodb-sessions. +- Fix for GetAssoc() PHP5 compat. See PHPLens Issue No: 15425 +- Active Record - If inserting a record and the value of a primary key field is null, then we do not insert that field in as we assume it is an auto-increment field. Needed by mssql. +- Changed postgres7 MetaForeignKeys() see PHPLens Issue No: 15531 +- DB2 will now return db2_conn_errormsg() when it is a connection error. + +## 4.90 - 8 June 2006 + +- Changed adodb_countrec() in adodb-lib.inc.php to allow LIMIT to be used as a speedup to reduce no of records counted. +- Added support for transaction modes for postgres and oci8 with SetTransactionMode(). These transaction modes affect all subsequent transactions of that connection. +- Thanks to Halmai Csongor for suggestion. +- Removed `$off = $fieldOffset - 1` line in db2 driver, FetchField(). Tx Larry Menard. +- Added support for PHP5 objects as Execute() bind parameters using `__toString` (eg. Simple-XML). Thx Carl-Christian Salvesen. +- Rounding in tohtml.inc.php did not work properly. Fixed. +- MetaIndexes in postgres fails when fields are deleted then added in again because the attnum has gaps in it. See https://sourceforge.net/p/adodb/bugs/45/. Fixed. +- MetaForeignkeys in mysql and mysqli did not work when fetchMode==ADODB_FETCH_ASSOC used. Fixed. +- Reference error in AutoExecute() fixed. +- Added macaddr postgres type to MetaType. Maps to 'C'. +- Added to `_connect()` in adodb-ado5.inc.php support for $database and $dataProvider parameters. Thx Larry Menard. +- Added support for sequences in adodb-ado_mssql.inc.php. Thx Larry Menard. +- Added ADODB_SESSION_READONLY. +- Added session expiryref support to crc32 mode, and in LOB code. +- Clear `_errorMsg` in postgres7 driver, so that ErrorMsg() displays properly when no error occurs. +- Added BindDate and BindTimeStamp + +## 4.81 - 3 May 2006 + +- Fixed variable ref errors in adodb-ado5.inc.php in _query(). +- Mysqli setcharset fix using method_exists(). +- The adodb-perf.inc.php CreateLogTable() code now works for user-defined table names. +- Error in ibase_blob_open() fixed. See PHPLens Issue No: 14997 + +## 4.80 - 8 Mar 2006 + +- Added activerecord support. +- Added mysql `$conn->compat323 = true` if you want MySQL 3.23 compat enabled. Fixes GetOne() Select-Limit problems. +- Added adodb-xmlschema03.inc.php to support XML Schema version 3 and updated adodb-datadict.htm docs. +- Better memory management in Execute. Thx Mike Fedyk. + +## 4.72 - 21 Feb 2006 + +- Added 'new' DSN parameter for NConnect(). +- Pager now sanitizes $PHP_SELF to protect against XSS. Thx to James Bercegay and others. +- ADOConnection::MetaType changed to setup $rs->connection correctly. +- New native DB2 driver contributed by Larry Menard, Dan Scott, Andy Staudacher, Bharat Mediratta. +- The mssql CreateSequence() did not BEGIN TRANSACTION correctly. Fixed. Thx Sean Lee. +- The _adodb_countrecs() function in adodb-lib.inc.php has been revised to handle more ORDER BY variations. + +## 4.71 - 24 Jan 2006 + +- Fixes postgresql security issue related to binary strings. Thx to Andy Staudacher. +- Several DSN bugs found: + 1. Fix bugs in DSN connections introduced in 4.70 when underscores are found in the DSN. + 2. DSN with _ did not work properly in PHP5 (fine in PHP4). Fixed. + 3. Added support for PDO DSN connections in NewADOConnection(), and database parameter in PDO::Connect(). +- The oci8 datetime flag not correctly implemented in ADORecordSet_array. Fixed. +- Added BlobDelete() to postgres, as a counterpoint to UpdateBlobFile(). +- Fixed GetInsertSQL() to support oci8po. +- Fixed qstr() issue with postgresql with \0 in strings. +- Fixed some datadict driver loading issues in _adodb_getdriver(). +- Added register shutdown function session_write_close in adodb-session.inc.php for PHP 5 compat. See PHPLens Issue No: 14200. + +## 4.70 - 6 Jan 2006 + +- Many fixes from Danila Ulyanov to ibase, oci8, postgres, mssql, odbc_oracle, odbtp, etc drivers. +- Changed usage of binary hint in adodb-session.inc.php for mysql. See PHPLens Issue No: 14160 +- Fixed invalid variable reference problem in undomq(), adodb-perf.inc.php. +- Fixed PHPLens Issue No: 14254 in adodb-perf.inc.php, `_DBParameter()` settings of fetchmode was wrong. +- Fixed security issues in server.php and tmssql.php discussed by Andreas Sandblad in a Secunia security advisory. Added `$ACCEPTIP = 127.0.0.1` and changed suggested root password to something more secure. +- Changed pager to close recordset after RenderLayout(). + +## 4.68 - 25 Nov 2005 + +- PHP 5 compat for mysqli. MetaForeignKeys repeated twice and MYSQLI_BINARY_FLAG missing. +- PHP 5.1 support for postgresql bind parameters using ? did not work if >= 10 parameters. Fixed. Thx to Stanislav Shramko. +- Lots of PDO improvements. +- Spelling error fixed in mysql MetaForeignKeys, $associative parameter. + +## 4.67 - 16 Nov 2005 + +- Postgresql not_null flag not set to false correctly. Thx Cristian MARIN. +- We now check in Replace() if key is in fieldArray. Thx Sébastien Vanvelthem. +- `_file_get_contents()` function was missing in xmlschema. fixed. +- Added week in year support to SQLDate(), using 'W' flag. Thx Spider. +- In sqlite metacolumns was repeated twice, causing PHP 5 problems. Fixed. +- Made debug output XHTML compliant. + +## 4.66 - 28 Sept 2005 + +- ExecuteCursor() in oci8 did not clean up properly on failure. Fixed. +- Updated xmlschema.dtd, by "Alec Smecher" asmecher#smecher.bc.ca +- Hardened SelectLimit, typecasting nrows and offset to integer. +- Fixed misc bugs in AutoExecute() and GetInsertSQL(). +- Added $conn->database as the property holding the database name. The older $conn->databaseName is retained for backward compat. +- Changed _adodb_backtrace() compat check to use function_exists(). +- Bug in postgresql MetaIndexes fixed. Thx Kevin Jamieson. +- Improved OffsetDate for MySQL, reducing rounding error. +- Metacolumns added to sqlite. Thx Mark Newnham. +- PHP 4.4 compat fixes for GetAssoc(). +- Added postgresql bind support for php 5.1. Thx Cristiano da Cunha Duarte +- OffsetDate() fixes for postgresql, typecasting strings to date or timestamp. +- DBTimeStamp formats for mssql, odbc_mssql and postgresql made to conform with other db's. +- Changed PDO constants from PDO_ to PDO:: to support latest spec. + +## 4.65 - 22 July 2005 + +- Reverted 'X' in mssql datadict to 'TEXT' to be compat with mssql driver. However now you can set $datadict->typeX = 'varchar(4000)' or 'TEXT' or 'CLOB' for mssql and oci8 drivers. +- Added charset support when using DSN for Oracle. +- _adodb_getmenu did not use fieldcount() to get number of fields. Fixed. +- MetaForeignKeys() for mysql/mysqli contributed by Juan Carlos Gonzalez. +- MetaDatabases() now correctly returns an array for mysqli driver. Thx Cristian MARIN. +- CompleteTrans(false) did not return false. Fixed. Thx to JMF. +- AutoExecute() did not work with Oracle. Fixed. Thx José Moreira. +- MetaType() added to connection object. +- More PHP 4.4 reference return fixes. Thx Ryan C Bonham and others. + +## 4.64 - 20 June 2005 + +- In datadict, if the default field value is set to '', then it is not applied when the field is created. Fixed by Eugenio. +- MetaPrimaryKeys for postgres did not work because of true/false change in 4.63. Fixed. +- Tested ocifetchstatement in oci8. Rejected at the end. +- Added port to dsn handling. Supported in postgres, mysql, mysqli,ldap. +- Added 'w' and 'l' to mysqli SQLDate(). +- Fixed error handling in ldap _connect() to be more consistent. Also added ErrorMsg() handling to ldap. +- Added support for union in _adodb_getcount, adodb-lib.inc.php for postgres and oci8. +- rs2html() did not work with null dates properly. +- PHP 4.4 reference return fixes. + +## 4.63 - 18 May 2005 + +- Added $nrows<0 check to mysqli's SelectLimit(). +- Added OptimizeTable() and OptimizeTables() in adodb-perf.inc.php. By Markus Staab. +- PostgreSQL inconsistencies fixed. true and false set to TRUE and FALSE, and boolean type in datadict-postgres.inc.php set to 'L' => 'BOOLEAN'. Thx Kevin Jamieson. +- New adodb_session_create_table() function in adodb-session.inc.php. By Markus Staab. +- Added null check to UserTimeStamp(). +- Fixed typo in mysqlt driver in adorecordset. Thx to Andy Staudacher. +- GenID() had a bug in the raiseErrorFn handling. Fixed. Thx Marcos Pont. +- Datadict name quoting now handles ( ) in index fields correctly - they aren't part of the index field. +- Performance monitoring: + 1. oci8 Ixora checks moved down; + 2. expensive sql changed so that only those sql with count(*)>1 are shown; + 3. changed sql1 field to a length+crc32 checksum - this breaks backward compat. +- We remap firebird15 to firebird in data dictionary. + +## 4.62 - 2 Apr 2005 + +- Added 'w' (dow as 0-6 or 1-7) and 'l' (dow as string) for SQLDate for oci8, postgres and mysql. +- Rolled back MetaType() changes for mysqli done in prev version. +- Datadict change by chris, cblin#tennaxia.com data mappings from: + ``` + oci8: X->varchar(4000) XL->CLOB + mssql: X->XL->TEXT + mysql: X->XL->LONGTEXT + fbird: X->XL->varchar(4000) + ``` + to: + ``` + oci8: X->varchar(4000) XL->CLOB + mssql: X->VARCHAR(4000) XL->TEXT + mysql: X->TEXT XL->LONGTEXT + fbird: X->VARCHAR(4000) XL->VARCHAR(32000) + ``` +- Added $connection->disableBlobs to postgresql to improve performance when no bytea is used (2-5% improvement). +- Removed all HTTP_* vars. +- Added $rs->tableName to be set before calling AutoExecute(). +- Alex Rootoff rootoff#pisem.net contributed ukrainian language file. +- Added new mysql_option() support using $conn->optionFlags array. +- Added support for ldap_set_option() using the $LDAP_CONNECT_OPTIONS global variable. Contributed by Josh Eldridge. +- Added LDAP_* constant definitions to ldap. +- Added support for boolean bind variables. We use $conn->false and $conn->true to hold values to set false/true to. +- We now do not close the session connection in adodb-session.inc.php as other objects could be using this connection. +- We now strip off `\0` at end of Ixora SQL strings in $perf->tohtml() for oci8. + +## 4.61 - 23 Feb 2005 + +- MySQLi added support for mysqli_connect_errno() and mysqli_connect_error(). +- Massive improvements to alpha PDO driver. +- Quote string bind parameters logged by performance monitor for easy type checking. Thx Jason Judge. +- Added support for $role when connecting with Interbase/firebird. +- Added support for enum recognition in MetaColumns() mysql and mysqli. Thx Amedeo Petrella. +- The sybase_ase driver contributed by Interakt Online. Thx Cristian Marin cristic#interaktonline.com. +- Removed not_null, has_default, and default_value from ADOFieldObject. +- Sessions code, fixed quoting of keys when handling LOBs in session write() function. +- Sessions code, added adodb_session_regenerate_id(), to reduce risk of session hijacking by changing session cookie dynamically. Thx Joe Li. +- Perf monitor, polling for CPU did not work for PHP 4.3.10 and 5.0.0-5.0.3 due to PHP bugs, so we special case these versions. +- Postgresql, UpdateBlob() added code to handle type==CLOB. + +## 4.60 - 24 Jan 2005 + +- Implemented PEAR DB's autoExecute(). Simplified design because I don't like using constants when strings work fine. +- _rs2serialize will now update $rs->sql and $rs->oldProvider. +- Added autoExecute(). +- Added support for postgres8 driver. Currently just remapped to postgres7 driver. +- Changed oci8 _query(), so that OCIBindByName() sets the length to -1 if element size is > 4000. This provides better support for LONGs. +- Added SetDateLocale() support for netherlands (Nl). +- Spelling error in pivot code ($iff should be $iif). +- mysql insert_id() did not work with mysql 3.x. Fixed. +- `\r\n` not converted to spaces correctly in exporting data. Fixed. +- _nconnect() in mysqli did not return value correctly. Fixed. +- Arne Eckmann contributed danish language file. +- Added clone() support to FetchObject() for PHP5. +- Removed SQL_CUR_USE_ODBC from odbc_mssql. + +## 4.55 - 5 Jan 2005 + +- Found bug in Execute() with bind params for db's that do not support binding natively. +- DropSequence() now correctly uses default parameter. +- Now Execute() ignores locale for floats, so 1.23 is NEVER converted to 1,23. +- SetFetchMode() not properly saved in adodb-perf, suspicious sql and expensive sql. Fixed. +- Added INET to postgresql metatypes. Thx motzel. +- Allow oracle hints to work when counting with _adodb_getcount in adodb-lib.inc.php. Thx Chris Wrye. +- Changed mysql insert_id() to use SELECT LAST_INSERT_ID(). +- If alter col in datadict does not modify col type/size of actual col, then it is removed from alter col code. By Mark Newham. Not perfect as MetaType() !== ActualType(). +- Added handling of view fields in metacolumns() for postgresql. Thx Renato De Giovanni. +- Added to informix MetaPrimaryKeys and MetaColumns fixes for null bit. Thx to Cecilio Albero. +- Removed obsolete connection_timeout() from perf code. +- Added support for arrayClass in adodb-csv.inc.php. +- RSFilter now accepts methods of the form $array($obj, 'methodname'). Thx to blake#near-time.com. +- Changed CacheFlush to `$cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/[0-9a-f][0-9a-f]/';` +- For better cursor concurrency, added code to free ref cursors in oci8 when $rs->Close() is called. Note that CLose() is called internally by the Get* functions too. +- Added IIF support for access when pivoting. Thx Volodia Krupach. +- Added mssql datadict support for timestamp. Thx Alexios. +- Informix pager fix. By Mario Ramirez. +- ADODB_TABLE_REGEX now includes ':'. By Mario Ramirez. +- Mark Newnham contributed MetaIndexes for oci8 and db2. + +## 4.54 - 5 Nov 2004 + +- Now you can set $db->charSet = ?? before doing a Connect() in oci8. +- Added adodbFetchMode to sqlite. +- Perf code, added a string typecast to substr in adodb_log_sql(). +- Postgres: Changed BlobDecode() to use po_loread, added new $maxblobsize parameter, and now it returns the blob instead of sending it to stdout - make sure to mention that as a compat warning. Also added $db->IsOID($oid) function; uses a heuristic, not guaranteed to work 100%. +- Contributed arabic language file by "El-Shamaa, Khaled" k.el-shamaa#cgiar.org +- PHP5 exceptions did not handle @ protocol properly. Fixed. +- Added ifnull handling for postgresql (using coalesce). +- Added metatables() support for Postgresql 8.0 (no longer uses pg_% dictionary tables). +- Improved Sybase ErrorMsg() function. By Gaetano Giunta. +- Improved oci8 SelectLimit() to use Prepare(). By Cristiano Duarte. +- Type-cast $row parameter in ifx_fetch_row() to int. Thx stefan bodgan. +- Ralf becker contributed improvements in postgresql, sapdb, mysql data dictionary handling: + - MySql and Postgres MetaType was reporting every int column which was part of a primary key and unique as serial + - Postgres was not reporting the scale of decimal types + - MaxDB was padding the defaults of none-string types with spaces + - MySql now correctly converts enum columns to varchar +- Ralf also changed Postgresql datadict: + - you can't add NOT NULL columns in postgres in one go, they need to be added as NULL and then altered to NOT NULL + - AlterColumnSQL could not change a varchar column with numbers into an integer column, postgres need an explicit conversation + - a re-created sequence was not set to the correct value, if the name was the old name (no implicit sequence), now always the new name of the implicit sequence is used +- Sergio Strampelli added extra $intoken check to Lens_ParseArgs() in datadict code. + +## 4.53 - 28 Sept 2004 + +- FetchMode cached in recordset is sometimes mapped to native db fetchMode. Normally this does not matter, but when using cached recordsets, we need to switch back to using adodb fetchmode. So we cache this in $rs->adodbFetchMode if it differs from the db's fetchMode. +- For informix we now set canSeek = false driver because stefan bodgan tells me that seeking doesn't work. +- SetDateLocale() never worked till now ;-) Thx david#tomato.it +- Set $_bindInputArray = true in sapdb driver. Required for clob support. +- Fixed some PEAR::DB emulation issues with isError() and isWarning. Thx to Gert-Rainer Bitterlich. +- Empty() used in getupdatesql without strlen() check. Fixed. +- Added unsigned detection to mysql and mysqli drivers. Thx to dan cech. +- Added hungarian language file. Thx to Halászvári Gábor. +- Improved fieldname-type formatting of datadict SQL generated (adding $widespacing parameter to _GenField). +- Datadict oci8 DROP CONSTRAINTS misspelt. Fixed. Thx Mark Newnham. +- Changed odbtp to dynamically change databaseType based on connection, eg. from 'odbtp' to 'odbtp_mssql' when connecting to mssql database. +- In datadict, MySQL I4 was wrongly mapped to MEDIUMINT, which is actually I3. Fixed. +- Fixed mysqli MetaType() recognition. Mysqli returns numeric types unlike mysql extension. Thx Francesco Riosa. +- VFP odbc driver curmode set wrongly, causing problems with memo fields. Fixed. +- Odbc driver did not recognize odbc version 2 driver date types properly. Fixed. Thx Bostjan. +- ChangeTableSQL() fixes to datadict-db2.inc.php by Mark Newnham. +- Perf monitoring with odbc improved. Now we try in perf code to manually set the sysTimeStamp using date() if sysTimeStamp is empty. +- All ADO errors are thrown as exceptions in PHP5. So we added exception handling to ado in PHP5 by creating new adodb-ado5.inc.php driver. +- Added IsConnected(). Returns true if connection object connected. By Luca.Gioppo. +- "Ralf Becker" RalfBecker#digitalROCK.de contributed new sapdb data-dictionary driver and a large patch that implements field and table renaming for oracle, mssql, postgresql, mysql and sapdb. See the new RenameTableSQL() and RenameColumnSQL() functions. +- We now check ExecuteCursor to see if PrepareSP was initially called. +- Changed oci8 datadict to use MODIFY for $dd->alterCol. Thx Mark Newnham. + +## 4.52 - 10 Aug 2004 + +- Bug found in Replace() when performance logging enabled, introduced in ADOdb 4.50. Fixed. +- Replace() checks update stmt. If update stmt fails, we now return immediately. Thx to alex. +- Added support for $ADODB_FORCE_TYPE in GetUpdateSQL/GetInsertSQL. Thx to niko. +- Added ADODB_ASSOC_CASE support to postgres/postgres7 driver. +- Support for DECLARE stmt in oci8. Thx Lochbrunner. + +## 4.51 - 29 July 2004 + +- Added adodb-xmlschema 1.0.2. Thx dan and richard. +- Added new adorecordset_ext_* classes. If ADOdb extension installed for mysql, mysqlt and oci8 (but not oci8po), we use the superfast ADOdb extension code for movenext. +- Added schema support to mssql and odbc_mssql MetaPrimaryKeys(). +- Patched MSSQL driver to support PHP NULL and Boolean values while binding the input array parameters in the _query() function. By Stephen Farmer. +- Added support for clob's for mssql, UpdateBlob(). Thx to gfran#directa.com.br +- Added normalize support for postgresql (true=lowercase table name, or false=case-sensitive table names) to MetaColumns($table, $normalize=true). +- PHP5 variant dates in ADO not working. Fixed in adodb-ado.inc.php. +- Constant ADODB_FORCE_NULLS was not working properly for many releases (for GetUpdateSQL). Fixed. Also GetUpdateSQL strips off ORDER BY now - thx Elieser Leão. +- Perf Monitor for oci8 now dynamically highlights optimizer_* params if too high/low. +- Added dsn support to NewADOConnection/ADONewConnection. +- Fixed out of page bounds bug in _adodb_pageexecute_all_rows() Thx to "Sergio Strampelli" sergio#rir.it +- Speedup of movenext for mysql and oci8 drivers. +- Moved debugging code _adodb_debug_execute() to adodb-lib.inc.php. +- Fixed postgresql bytea detection bug. See PHPLens Issue No: 9849. +- Fixed ibase datetimestamp typo in PHP5. Thx stefan. +- Removed whitespace at end of odbtp drivers. +- Added db2 metaprimarykeys fix. +- Optimizations to MoveNext() for mysql and oci8. Misc speedups to Get* functions. + +## 4.50 - 6 July 2004 + +- Bumped it to 4.50 to avoid confusion with PHP 4.3.x series. +- Added db2 metatables and metacolumns extensions. +- Added alpha PDO driver. Very buggy, only works with odbc. +- Tested mysqli. Set poorAffectedRows = true. Cleaned up movenext() and _fetch(). +- PageExecute does not work properly with php5 (return val not a variable). Reported Dmytro Sychevsky sych#php.com.ua. Fixed. +- MetaTables() for mysql, $showschema parameter was not backward compatible with older versions of adodb. Fixed. +- Changed mysql GetOne() to work with mysql 3.23 when using with non-select stmts (e.g. SHOW TABLES). +- Changed TRIG_ prefix to a variable in datadict-oci8.inc.php. Thx to Luca.Gioppo#csi.it. +- New to adodb-time code. We allow you to define your own daylights savings function, adodb_daylight_sv for pre-1970 dates. If the function is defined (somewhere in an include), then you can correct for daylights savings. +- New sqlitepo driver. This is because assoc mode does not work like other drivers in sqlite. Namely, when selecting (joining) multiple tables, in assoc mode the table names are included in the assoc keys in the "sqlite" driver. In "sqlitepo" driver, the table names are stripped from the returned column names. When this results in a conflict, the first field get preference. Contributed by Herman Kuiper herman#ozuzo.net +- Added $forcenull parameter to GetInsertSQL/GetUpdateSQL. Idea by Marco Aurelio Silva. +- More XHTML changes for GetMenu. By Jeremy Evans. +- Fixes some ibase date issues. Thx to stefan bogdan. +- Improvements to mysqli driver to support $ADODB_COUNTRECS. +- Fixed adodb-csvlib.inc.php problem when reading stream from socket. We need to poll stream continuously. + +## 4.23 - 16 June 2004 + +- New interbase/firebird fixes thx to Lester Caine. Driver fixes a problem with getting field names in the result array, and corrects a couple of data conversions. Also we default to dialect3 for firebird. Also ibase sysDate property was wrong. Changed to cast as timestamp. +- The datadict driver is set up to give quoted tables and fields as this was the only way round reserved words being used as field names in TikiWiki. TikiPro is tidying that up, and I hope to be able to produce a build of THAT which uses what I consider proper UPPERCASE field and table names. The conversion of TikiWiki to ADOdb helped in that, but until the database is completely tidied up in TikiPro ... +- Modified _gencachename() to include fetchmode in name hash. This means you should clear your cache directory after installing this release as the cache name algorithm has changed. +- Now Cache* functions work in safe mode, because we do not create sub-directories in the $ADODB_CACHE_DIR in safe mode. In non-safe mode we still create sub-directories. Done by modifying _gencachename(). +- Added $gmt parameter (true/false) to UserDate and UserTimeStamp in connection class, to force conversion of input (in local time) to be converted to UTC/GMT. +- Mssql datadict did not support INT types properly (no size param allowed). Added _GetSize() to datadict-mssql.inc.php. +- For borland_ibase, BeginTrans(), changed: + ``` + $this->_transactionID = $this->_connectionID; + ``` + to + ``` + $this->_transactionID = ibase_trans($this->ibasetrans, $this->_connectionID); + ``` + +- Fixed typo in mysqi_field_seek(). Thx to Sh4dow (sh4dow#php.pl). +- LogSQL did not work with Firebird/Interbase. Fixed. +- Postgres: made errorno() handling more consistent. Thx to Michael Jahn, Michael.Jahn#mailbox.tu-dresden.de. +- Added informix patch to better support metatables, metacolumns by "Cecilio Albero" c-albero#eos-i.com +- Cyril Malevanov contributed patch to oci8 to support passing of LOB parameters: + ``` + $text = 'test test test'; + $sql = "declare rs clob; begin :rs := lobinout(:sa0); end;"; + $stmt = $conn -> PrepareSP($sql); + $conn -> InParameter($stmt,$text,'sa0', -1, OCI_B_CLOB); + $rs = ''; + $conn -> OutParameter($stmt,$rs,'rs', -1, OCI_B_CLOB); + $conn -> Execute($stmt); + echo "return = ".$rs."
";
+ ``` + + As he says, the LOBs limitations are: + - use OCINewDescriptor before binding + - if Param is IN, uses save() before each execute. This is done automatically for you. + - if Param is OUT, uses load() after each execute. This is done automatically for you. + - when we bind $var as LOB, we create new descriptor and return it as a Bind Result, so if we want to use OUT parameters, we have to store somewhere &$var to load() data from LOB to it. + - IN OUT params are not working now (should not be a big problem to fix it) + - now mass binding not working too (I've wrote about it before) +- Simplified Connect() and PConnect() error handling. +- When extension not loaded, Connect() and PConnect() will return null. On connect error, the fns will return false. +- CacheGetArray() added to code. +- Added Init() to adorecordset_empty(). +- Changed postgres64 driver, MetaColumns() to not strip off quotes in default value if :: detected (type-casting of default). +- Added test: if (!defined('ADODB_DIR')) die(). Useful to prevent hackers from detecting file paths. +- Changed metaTablesSQL to ignore Postgres 7.4 information schemas (sql_*). +- New polish language file by Grzegorz Pacan +- Added support for UNION in _adodb_getcount(). +- Added security check for ADODB_DIR to limit path disclosure issues. Requested by postnuke team. +- Added better error message support to oracle driver. Thx to Gaetano Giunta. +- Added showSchema support to mysql. +- Bind in oci8 did not handle $name=false properly. Fixed. +- If extension not loaded, Connect(), PConnect(), NConnect() will return null. + +## 4.22 - 15 Apr 2004 + +- Moved docs to own adodb/docs folder. +- Fixed session bug when quoting compressed/encrypted data in Replace(). +- Netezza Driver and LDAP drivers contributed by Josh Eldridge. +- GetMenu now uses rtrim() on values instead of trim(). +- Changed MetaColumnNames to return an associative array, keys being the field names in uppercase. +- Suggested fix to adodb-ado.inc.php affected_rows to support PHP5 variants. Thx to Alexios Fakos. +- Contributed bulgarian language file by Valentin Sheiretsky valio#valio.eu.org. +- Contributed romanian language file by stefan bogdan. +- GetInsertSQL now checks for table name (string) in $rs, and will create a recordset for that table automatically. Contributed by Walt Boring. Also added OCI_B_BLOB in bind on Walt's request - hope it doesn't break anything :-) +- Some minor postgres speedups in `_initrs()`. +- ChangeTableSQL checks now if MetaColumns returns empty. Thx Jason Judge. +- Added ADOConnection::Time(), returns current database time in unix timestamp format, or false. + +## 4.21 - 20 Mar 2004 + +- We no longer in SelectLimit for VFP driver add SELECT TOP X unless an ORDER BY exists. +- Pim Koeman contributed dutch language file adodb-nl.inc.php. +- Rick Hickerson added CLOB support to db2 datadict. +- Added odbtp driver. Thx to "stefan bogdan" sbogdan#rsb.ro. +- Changed PrepareSP() 2nd parameter, $cursor, to default to true (formerly false). Fixes oci8 backward compat problems with OUT params. +- Fixed month calculation error in adodb-time.inc.php. 2102-June-01 appeared as 2102-May-32. +- Updated PHP5 RC1 iterator support. API changed, hasMore() renamed to valid(). +- Changed internal format of serialized cache recordsets. As we store a version number, this should be backward compatible. +- Error handling when driver file not found was flawed in ADOLoadCode(). Fixed. + +## 4.20 - 27 Feb 2004 + +- Updated to AXMLS 1.01. +- MetaForeignKeys for postgres7 modified by Edward Jaramilla, works on pg 7.4. +- Now numbers accepts function calls or sequences for GetInsertSQL/GetUpdateSQL numeric fields. +- Changed quotes of 'delete from $perf_table' to "". Thx Kehui (webmaster#kehui.net) +- Added ServerInfo() for ifx, and putenv trim fix. Thx Fernando Ortiz. +- Added addq(), which is analogous to addslashes(). +- Tested with php5b4. Fix some php5 compat problems with exceptions and sybase. +- Carl-Christian Salvesen added patch to mssql _query to support binds greater than 4000 chars. +- Mike suggested patch to PHP5 exception handler. $errno must be numeric. +- Added double quotes (") to ADODB_TABLE_REGEX. +- For oci8, Prepare(...,$cursor), $cursor's meaning was accidentally inverted in 4.11. This causes problems with ExecuteCursor() too, which calls Prepare() internally. Thx to William Lovaton. +- Now dateHasTime property in connection object renamed to datetime for consistency. This could break bc. +- Csongor Halmai reports that db2 SelectLimit with input array is not working. Fixed.. + +## 4.11 - 27 Jan 2004 + +- Csongor Halmai reports db2 binding not working. Reverted back to emulated binding. +- Dan Cech modifies datadict code. Adds support for DropIndex. Minor cleanups. +- Table misspelt in perf-oci8.inc.php. Changed v$conn_cache_advice to v$db_cache_advice. Reported by Steve W. +- UserTimeStamp and DBTimeStamp did not handle YYYYMMDDHHMMSS format properly. Reported by Mike Muir. Fixed. +- Changed oci8 Prepare(). Does not auto-allocate OCINewCursor automatically, unless 2nd param is set to true. This will break backward compat, if Prepare/Execute is used instead of ExecuteCursor. Reported by Chris Jones. +- Added InParameter() and OutParameter(). Wrapper functions to Parameter(), but nicer because they are self-documenting. +- Added 'R' handling in ActualType() to datadict-mysql.inc.php +- Added ADOConnection::SerializableRS($rs). Returns a recordset that can be serialized in a session. +- Added "Run SQL" to performance UI(). +- Misc spelling corrections in adodb-mysqli.inc.php, adodb-oci8.inc.php and datadict-oci8.inc.php, from Heinz Hombergs. +- MetaIndexes() for ibase contributed by Heinz Hombergs. + +## 4.10 - 12 Jan 2004 + +- Dan Cech contributed extensive changes to data dictionary to support name quoting (with `\``), and drop table/index. +- Informix added cursorType property. Default remains IFX_SCROLL, but you can change to 0 (non-scrollable cursor) for performance. +- Added ADODB_View_PrimaryKeys() for returning view primary keys to MetaPrimaryKeys(). +- Simplified chinese file, adodb-cn.inc.php from cysoft. +- Added check for ctype_alnum in adodb-datadict.inc.php. Thx to Jason Judge. +- Added connection parameter to ibase Prepare(). Fix by Daniel Hassan. +- Added nameQuote for quoting identifiers and names to connection obj. Requested by Jason Judge. Also the data dictionary parser now detects `field name` and generates column names with spaces correctly. +- BOOL type not recognised correctly as L. Fixed. +- Fixed paths in ADODB_DIR for session files, and back-ported it to 4.05 (15 Dec 2003) +- Added Schema to postgresql MetaTables. Thx to col#gear.hu +- Empty postgresql recordsets that had blob fields did not set EOF properly. Fixed. +- CacheSelectLimit internal parameters to SelectLimit were wrong. Thx to Nio. +- Modified adodb_pr() and adodb_backtrace() to support command-line usage (eg. no html). +- Fixed some fr and it lang errors. Thx to Gaetano G. +- Added contrib directory, with adodb rs to xmlrpc converter by Gaetano G. +- Fixed array recordset bugs when `_skiprow1` is true. Thx to Gaetano G. +- Fixed pivot table code when count is false. + +## 4.05 - 13 Dec 2003 + +- Added MetaIndexes to data-dict code - thx to Dan Cech. +- Rewritten session code by Ross Smith. Moved code to adodb/session directory. +- Added function exists check on connecting to most drivers, so we don't crash with the unknown function error. +- Smart Transactions failed with GenID() when it no seq table has been created because the sql statement fails. Fix by Mark Newnham. +- Added $db->length, which holds name of function that returns strlen. +- Fixed error handling for bad driver in ADONewConnection - passed too few params to error-handler. +- Datadict did not handle types like 16.0 properly in _GetSize. Fixed. +- Oci8 driver SelectLimit() bug &= instead of =& used. Thx to Swen Thümmler. +- Jesse Mullan suggested not flushing outp when output buffering enabled. Due to Apache 2.0 bug. Added. +- MetaTables/MetaColumns return ref bug with PHP5 fixed in adodb-datadict.inc.php. +- New mysqli driver contributed by Arjen de Rijke. Based on adodb 3.40 driver. Then jlim added BeginTrans, CommitTrans, RollbackTrans, IfNull, SQLDate. Also fixed return ref bug. +- $ADODB_FLUSH added, if true then force flush in debugging outp. Default is false. In earlier versions, outp defaulted to flush, which is not compat with apache 2.0. +- Mysql driver's GenID() function did not work when when sql logging is on. Fixed. +- $ADODB_SESSION_TBL not declared as global var. Not available if adodb-session.inc.php included in function. Fixed. +- The input array not passed to Execute() in _adodb_getcount(). Fixed. + +## 4.04 - 13 Nov 2003 + +- Switched back to foreach - faster than list-each. +- Fixed bug in ado driver - wiping out $this->fields with date fields. +- Performance Monitor, View SQL, Explain Plan did not work if strlen($SQL)>max($_GET length). Fixed. +- Performance monitor, oci8 driver added memory sort ratio. +- Added random property, returns SQL to generate a floating point number between 0 and 1; + +## 4.03 - 6 Nov 2003 + +- The path to adodb-php4.inc.php and adodb-iterators.inc.php was not setup properly. +- Patched SQLDate in interbase to support hours/mins/secs. Thx to ari kuorikoski. +- Force autorollback for pgsql persistent connections - apparently pgsql did not autorollback properly before 4.3.4. See http://bugs.php.net/bug.php?id=25404 + +## 4.02 - 5 Nov 2003 + +- Some errors in adodb_error_pg() fixed. Thx to Styve. +- Spurious Insert_ID() error was generated by LogSQL(). Fixed. +- Insert_ID was interfering with Affected_Rows() and Replace() when LogSQL() enabled. Fixed. +- More foreach loops optimized with list/each. +- Null dates not handled properly in ADO driver (it becomes 31 Dec 1969!). +- Heinz Hombergs contributed patches for mysql MetaColumns - adding scale, made interbase MetaColumns work with firebird/interbase, and added lang/adodb-de.inc.php. +- Added INFORMIXSERVER environment variable. +- Added $ADODB_ANSI_PADDING_OFF for interbase/firebird. +- PHP 5 beta 2 compat check. Foreach (Iterator) support. Exceptions support. + +## 4.01 - 23 Oct 2003 + +- Fixed bug in rs2html(), tohtml.inc.php, that generated blank table cells. +- Fixed insert_id() incorrectly generated when logsql() enabled. +- Modified PostgreSQL _fixblobs to use list/each instead of foreach. +- Informix ErrorNo() implemented correctly. +- Modified several places to use list/each, including GetRowAssoc(). +- Added UserTimeStamp() to connection class. +- Added $ADODB_ANSI_PADDING_OFF for oci8po. + +## 4.00 - 20 Oct 2003 + +- Upgraded adodb-xmlschema to 1 Oct 2003 snapshot. +- Fix to rs2html warning message. Thx to Filo. +- Fix for odbc_mssql/mssql SQLDate(), hours was wrong. +- Added MetaColumns and MetaPrimaryKeys for sybase. Thx to Chris Phillipson. +- Added autoquoting to datadict for MySQL and PostgreSQL. Suggestion by Karsten Dambekalns diff --git a/www/include/adodb5/drivers/adodb-access.inc.php b/www/include/adodb/drivers/adodb-access.inc.php similarity index 57% rename from www/include/adodb5/drivers/adodb-access.inc.php rename to www/include/adodb/drivers/adodb-access.inc.php index 3a5a8edc..13461a35 100644 --- a/www/include/adodb5/drivers/adodb-access.inc.php +++ b/www/include/adodb/drivers/adodb-access.inc.php @@ -1,24 +1,34 @@ _has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; - $arr = $rs->GetArray(); //print_pre($arr); $arr2 = array(); @@ -80,9 +80,6 @@ class ADORecordSet_access extends ADORecordSet_odbc { var $databaseType = "access"; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } -}// class +} // class + } diff --git a/www/include/adodb5/drivers/adodb-ado.inc.php b/www/include/adodb/drivers/adodb-ado.inc.php similarity index 93% rename from www/include/adodb5/drivers/adodb-ado.inc.php rename to www/include/adodb/drivers/adodb-ado.inc.php index 449cdd00..fc000cec 100644 --- a/www/include/adodb5/drivers/adodb-ado.inc.php +++ b/www/include/adodb/drivers/adodb-ado.inc.php @@ -1,17 +1,25 @@ = 5) return $this->_affectedRows; - - return $this->_affectedRows->value; + return $this->_affectedRows; } // you can also pass a connection string like this: @@ -81,7 +87,7 @@ function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDAS // not yet //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename"; - //use trusted conection for SQL if username not specified + //use trusted connection for SQL if username not specified if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes"; } else if ($argProvider=='access') $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider @@ -225,7 +231,7 @@ function _query($sql,$inputarr=false) // Map by http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcreateparam.asp // Check issue http://bugs.php.net/bug.php?id=40664 !!! - while(list(, $val) = each($inputarr)) { + foreach ($inputarr as $val) { $type = gettype($val); $len=strlen($val); if ($type == 'boolean') @@ -350,7 +356,7 @@ function __construct($id,$mode=false) $mode = $ADODB_FETCH_MODE; } $this->fetchMode = $mode; - return parent::__construct($id,$mode); + parent::__construct($id); } @@ -498,6 +504,9 @@ function MetaType($t,$len=-1,$fieldobj=false) $t = $fieldobj->type; $len = $fieldobj->max_length; } + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; if (!is_numeric($t)) return $t; @@ -538,7 +547,7 @@ function MetaType($t,$len=-1,$fieldobj=false) case 19://adUnsignedInt = 19, case 20://adUnsignedBigInt = 21, return 'I'; - default: return 'N'; + default: return ADODB_DEFAULT_METATYPE; } } diff --git a/www/include/adodb5/drivers/adodb-ado5.inc.php b/www/include/adodb/drivers/adodb-ado5.inc.php similarity index 93% rename from www/include/adodb5/drivers/adodb-ado5.inc.php rename to www/include/adodb/drivers/adodb-ado5.inc.php index 21df32f1..36f9c3b8 100644 --- a/www/include/adodb5/drivers/adodb-ado5.inc.php +++ b/www/include/adodb/drivers/adodb-ado5.inc.php @@ -1,17 +1,25 @@ = 5) return $this->_affectedRows; - - return $this->_affectedRows->value; + return $this->_affectedRows; } // you can also pass a connection string like this: @@ -97,7 +103,7 @@ function _connect($argHostname, $argUsername, $argPassword,$argDBorProvider, $ar // not yet //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename"; - //use trusted conection for SQL if username not specified + //use trusted connection for SQL if username not specified if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes"; } else if ($argProvider=='access') $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider @@ -248,7 +254,7 @@ function _query($sql,$inputarr=false) $oCmd->CommandText = $sql; $oCmd->CommandType = 1; - while(list(, $val) = each($inputarr)) { + foreach ($inputarr as $val) { $type = gettype($val); $len=strlen($val); if ($type == 'boolean') @@ -384,7 +390,7 @@ function __construct($id,$mode=false) $mode = $ADODB_FETCH_MODE; } $this->fetchMode = $mode; - return parent::__construct($id,$mode); + parent::__construct($id); } @@ -539,8 +545,14 @@ function MetaType($t,$len=-1,$fieldobj=false) $t = $fieldobj->type; $len = $fieldobj->max_length; } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; - if (!is_numeric($t)) return $t; + if (!is_numeric($t)) + return $t; switch ($t) { case 0: @@ -579,7 +591,7 @@ function MetaType($t,$len=-1,$fieldobj=false) case 19://adUnsignedInt = 19, case 20://adUnsignedBigInt = 21, return 'I'; - default: return 'N'; + default: return ADODB_DEFAULT_METATYPE; } } diff --git a/www/include/adodb/drivers/adodb-ado_access.inc.php b/www/include/adodb/drivers/adodb-ado_access.inc.php new file mode 100644 index 00000000..ad7ab38c --- /dev/null +++ b/www/include/adodb/drivers/adodb-ado_access.inc.php @@ -0,0 +1,53 @@ += 5) include(ADODB_DIR."/drivers/adodb-ado5.inc.php"); - else include(ADODB_DIR."/drivers/adodb-ado.inc.php"); + include_once(ADODB_DIR . "/drivers/adodb-ado5.inc.php"); } @@ -41,14 +44,14 @@ class ADODB_ado_mssql extends ADODB_ado { //var $_inTransaction = 1; // always open recordsets, so no transaction problems. - function _insertid() + protected function _insertID($table = '', $column = '') { - return $this->GetOne('select SCOPE_IDENTITY()'); + return $this->GetOne('select SCOPE_IDENTITY()'); } function _affectedrows() { - return $this->GetOne('select @@rowcount'); + return $this->GetOne('select @@rowcount'); } function SetTransactionMode( $transaction_mode ) @@ -62,40 +65,40 @@ function SetTransactionMode( $transaction_mode ) $this->Execute("SET TRANSACTION ".$transaction_mode); } - function qstr($s,$magic_quotes=false) + function qStr($s, $magic_quotes=false) { - $s = ADOConnection::qstr($s, $magic_quotes); + $s = ADOConnection::qStr($s); return str_replace("\0", "\\\\000", $s); } function MetaColumns($table, $normalize=true) { - $table = strtoupper($table); - $arr= array(); - $dbc = $this->_connectionID; - - $osoptions = array(); - $osoptions[0] = null; - $osoptions[1] = null; - $osoptions[2] = $table; - $osoptions[3] = null; - - $adors=@$dbc->OpenSchema(4, $osoptions);//tables - - if ($adors){ - while (!$adors->EOF){ - $fld = new ADOFieldObject(); - $c = $adors->Fields(3); - $fld->name = $c->Value; - $fld->type = 'CHAR'; // cannot discover type in ADO! - $fld->max_length = -1; - $arr[strtoupper($fld->name)]=$fld; - - $adors->MoveNext(); - } - $adors->Close(); - } - $false = false; + $table = strtoupper($table); + $arr= array(); + $dbc = $this->_connectionID; + + $osoptions = array(); + $osoptions[0] = null; + $osoptions[1] = null; + $osoptions[2] = $table; + $osoptions[3] = null; + + $adors=@$dbc->OpenSchema(4, $osoptions);//tables + + if ($adors){ + while (!$adors->EOF){ + $fld = new ADOFieldObject(); + $c = $adors->Fields(3); + $fld->name = $c->Value; + $fld->type = 'CHAR'; // cannot discover type in ADO! + $fld->max_length = -1; + $arr[strtoupper($fld->name)]=$fld; + + $adors->MoveNext(); + } + $adors->Close(); + } + $false = false; return empty($arr) ? $false : $arr; } @@ -137,14 +140,10 @@ function GenID($seq='adodbseq',$start=1) //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'"); } - } // end class +} // end class - class ADORecordSet_ado_mssql extends ADORecordSet_ado { +class ADORecordSet_ado_mssql extends ADORecordSet_ado { var $databaseType = 'ado_mssql'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } diff --git a/www/include/adodb/drivers/adodb-ads.inc.php b/www/include/adodb/drivers/adodb-ads.inc.php new file mode 100644 index 00000000..b9d4adb5 --- /dev/null +++ b/www/include/adodb/drivers/adodb-ads.inc.php @@ -0,0 +1,818 @@ +debug && $argDatabasename && $this->databaseType != 'vfp') { + ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter."); + } + $last_php_error = $this->resetLastError(); + if ($this->curmode === false) { + $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword); + } else { + $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword, $this->curmode); + } + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); + if (isset($this->connectStmt)) { + $this->Execute($this->connectStmt); + } + + return $this->_connectionID != false; + } + + // returns true or false + function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) + { + if (!function_exists('ads_connect')) { + return null; + } + + $last_php_error = $this->resetLastError(); + $this->_errorMsg = ''; + if ($this->debug && $argDatabasename) { + ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter."); + } + // print "dsn=$argDSN u=$argUsername p=$argPassword
"; flush(); + if ($this->curmode === false) { + $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword); + } else { + $this->_connectionID = ads_pconnect($argDSN, $argUsername, $argPassword, $this->curmode); + } + + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); + if ($this->_connectionID && $this->autoRollback) { + @ads_rollback($this->_connectionID); + } + if (isset($this->connectStmt)) { + $this->Execute($this->connectStmt); + } + + return $this->_connectionID != false; + } + + // returns the Server version and Description + function ServerInfo() + { + + if (!empty($this->host)) { + $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()'); + $res = $this->Execute($stmt); + if (!$res) { + print $this->ErrorMsg(); + } else { + $ret["version"] = $res->fields[3]; + $ret["description"] = "Advantage Database Server"; + return $ret; + } + } else { + return ADOConnection::ServerInfo(); + } + } + + + // returns true or false + function CreateSequence($seqname = 'adodbseq', $start = 1) + { + $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE"); + if (!$res) { + print $this->ErrorMsg(); + return false; + } else { + return true; + } + + } + + // returns true or false + function DropSequence($seqname = 'adodbseq') + { + $res = $this->Execute("DROP TABLE $seqname"); + if (!$res) { + print $this->ErrorMsg(); + return false; + } else { + return true; + } + } + + + // returns the generated ID or false + // checks if the table already exists, else creates the table and inserts a record into the table + // and gets the ID number of the last inserted record. + function GenID($seqname = 'adodbseq', $start = 1) + { + $go = $this->Execute("select * from $seqname"); + if (!$go) { + $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE"); + if (!$res) { + print $this->ErrorMsg(); + return false; + } + } + $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )"); + if (!$res) { + print $this->ErrorMsg(); + return false; + } else { + $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota"); + $ret = $gen->fields[0]; + return $ret; + } + + } + + + function ErrorMsg() + { + if ($this->_errorMsg !== false) { + return $this->_errorMsg; + } + if (empty($this->_connectionID)) { + return @ads_errormsg(); + } + return @ads_errormsg($this->_connectionID); + } + + + function ErrorNo() + { + if ($this->_errorCode !== false) { + // bug in 4.0.6, error number can be corrupted string (should be 6 digits) + return (strlen($this->_errorCode) <= 2) ? 0 : $this->_errorCode; + } + + if (empty($this->_connectionID)) { + $e = @ads_error(); + } else { + $e = @ads_error($this->_connectionID); + } + + // bug in 4.0.6, error number can be corrupted string (should be 6 digits) + // so we check and patch + if (strlen($e) <= 2) { + return 0; + } + return $e; + } + + + function BeginTrans() + { + if (!$this->hasTransactions) { + return false; + } + if ($this->transOff) { + return true; + } + $this->transCnt += 1; + $this->_autocommit = false; + return ads_autocommit($this->_connectionID, false); + } + + function CommitTrans($ok = true) + { + if ($this->transOff) { + return true; + } + if (!$ok) { + return $this->RollbackTrans(); + } + if ($this->transCnt) { + $this->transCnt -= 1; + } + $this->_autocommit = true; + $ret = ads_commit($this->_connectionID); + ads_autocommit($this->_connectionID, true); + return $ret; + } + + function RollbackTrans() + { + if ($this->transOff) { + return true; + } + if ($this->transCnt) { + $this->transCnt -= 1; + } + $this->_autocommit = true; + $ret = ads_rollback($this->_connectionID); + ads_autocommit($this->_connectionID, true); + return $ret; + } + + + // Returns tables,Views or both on successful execution. Returns + // tables by default on successful execution. + function &MetaTables($ttype = false, $showSchema = false, $mask = false) + { + $recordSet1 = $this->Execute("select * from system.tables"); + if (!$recordSet1) { + print $this->ErrorMsg(); + return false; + } + $recordSet2 = $this->Execute("select * from system.views"); + if (!$recordSet2) { + print $this->ErrorMsg(); + return false; + } + $i = 0; + while (!$recordSet1->EOF) { + $arr["$i"] = $recordSet1->fields[0]; + $recordSet1->MoveNext(); + $i = $i + 1; + } + if ($ttype == 'FALSE') { + while (!$recordSet2->EOF) { + $arr["$i"] = $recordSet2->fields[0]; + $recordSet2->MoveNext(); + $i = $i + 1; + } + return $arr; + } elseif ($ttype == 'VIEWS') { + while (!$recordSet2->EOF) { + $arrV["$i"] = $recordSet2->fields[0]; + $recordSet2->MoveNext(); + $i = $i + 1; + } + return $arrV; + } else { + return $arr; + } + + } + + function &MetaPrimaryKeys($table, $owner = false) + { + $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'"); + if (!$recordSet) { + print $this->ErrorMsg(); + return false; + } + $i = 0; + while (!$recordSet->EOF) { + $arr["$i"] = $recordSet->fields[0]; + $recordSet->MoveNext(); + $i = $i + 1; + } + return $arr; + } + + /* + See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp + / SQL data type codes / + #define SQL_UNKNOWN_TYPE 0 + #define SQL_CHAR 1 + #define SQL_NUMERIC 2 + #define SQL_DECIMAL 3 + #define SQL_INTEGER 4 + #define SQL_SMALLINT 5 + #define SQL_FLOAT 6 + #define SQL_REAL 7 + #define SQL_DOUBLE 8 + #if (ODBCVER >= 0x0300) + #define SQL_DATETIME 9 + #endif + #define SQL_VARCHAR 12 + + + / One-parameter shortcuts for date/time data types / + #if (ODBCVER >= 0x0300) + #define SQL_TYPE_DATE 91 + #define SQL_TYPE_TIME 92 + #define SQL_TYPE_TIMESTAMP 93 + + #define SQL_UNICODE (-95) + #define SQL_UNICODE_VARCHAR (-96) + #define SQL_UNICODE_LONGVARCHAR (-97) + */ + function ODBCTypes($t) + { + switch ((integer)$t) { + case 1: + case 12: + case 0: + case -95: + case -96: + return 'C'; + case -97: + case -1: //text + return 'X'; + case -4: //image + return 'B'; + + case 9: + case 91: + return 'D'; + + case 10: + case 11: + case 92: + case 93: + return 'T'; + + case 4: + case 5: + case -6: + return 'I'; + + case -11: // uniqidentifier + return 'R'; + case -7: //bit + return 'L'; + + default: + return 'N'; + } + } + + function &MetaColumns($table, $normalize = true) + { + global $ADODB_FETCH_MODE; + + $false = false; + if ($this->uCaseTables) { + $table = strtoupper($table); + } + $schema = ''; + $this->_findschema($table, $schema); + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + /*if (false) { // after testing, confirmed that the following does not work because of a bug + $qid2 = ads_tables($this->_connectionID); + $rs = new ADORecordSet_ads($qid2); + $ADODB_FETCH_MODE = $savem; + if (!$rs) return false; + $rs->_fetch(); + + while (!$rs->EOF) { + if ($table == strtoupper($rs->fields[2])) { + $q = $rs->fields[0]; + $o = $rs->fields[1]; + break; + } + $rs->MoveNext(); + } + $rs->Close(); + + $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%'); + } */ + + switch ($this->databaseType) { + case 'access': + case 'vfp': + $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%'); + break; + + + case 'db2': + $colname = "%"; + $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname); + break; + + default: + $qid = @ads_columns($this->_connectionID, '%', '%', strtoupper($table), '%'); + if (empty($qid)) { + $qid = ads_columns($this->_connectionID); + } + break; + } + if (empty($qid)) { + return $false; + } + + $rs = new ADORecordSet_ads($qid); + $ADODB_FETCH_MODE = $savem; + + if (!$rs) { + return $false; + } + $rs->_fetch(); + + $retarr = array(); + + /* + $rs->fields indices + 0 TABLE_QUALIFIER + 1 TABLE_SCHEM + 2 TABLE_NAME + 3 COLUMN_NAME + 4 DATA_TYPE + 5 TYPE_NAME + 6 PRECISION + 7 LENGTH + 8 SCALE + 9 RADIX + 10 NULLABLE + 11 REMARKS + */ + while (!$rs->EOF) { + // adodb_pr($rs->fields); + if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { + $fld = new ADOFieldObject(); + $fld->name = $rs->fields[3]; + $fld->type = $this->ODBCTypes($rs->fields[4]); + + // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp + // access uses precision to store length for char/varchar + if ($fld->type == 'C' or $fld->type == 'X') { + if ($this->databaseType == 'access') { + $fld->max_length = $rs->fields[6]; + } else { + if ($rs->fields[4] <= -95) // UNICODE + { + $fld->max_length = $rs->fields[7] / 2; + } else { + $fld->max_length = $rs->fields[7]; + } + } + } else { + $fld->max_length = $rs->fields[7]; + } + $fld->not_null = !empty($rs->fields[10]); + $fld->scale = $rs->fields[8]; + $retarr[strtoupper($fld->name)] = $fld; + } else { + if (sizeof($retarr) > 0) { + break; + } + } + $rs->MoveNext(); + } + $rs->Close(); //-- crashes 4.03pl1 -- why? + + if (empty($retarr)) { + $retarr = false; + } + return $retarr; + } + + // Returns an array of columns names for a given table + function &MetaColumnNames($table, $numIndexes = false, $useattnum = false) + { + $recordSet = $this->Execute("select name from system.columns where parent='$table'"); + if (!$recordSet) { + print $this->ErrorMsg(); + return false; + } else { + $i = 0; + while (!$recordSet->EOF) { + $arr["FIELD$i"] = $recordSet->fields[0]; + $recordSet->MoveNext(); + $i = $i + 1; + } + return $arr; + } + } + + + function Prepare($sql) + { + if (!$this->_bindInputArray) { + return $sql; + } // no binding + $stmt = ads_prepare($this->_connectionID, $sql); + if (!$stmt) { + // we don't know whether odbc driver is parsing prepared stmts, so just return sql + return $sql; + } + return array($sql, $stmt, false); + } + + /* returns queryID or false */ + function _query($sql, $inputarr = false) + { + $last_php_error = $this->resetLastError(); + $this->_errorMsg = ''; + + if ($inputarr) { + if (is_array($sql)) { + $stmtid = $sql[1]; + } else { + $stmtid = ads_prepare($this->_connectionID, $sql); + + if ($stmtid == false) { + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); + return false; + } + } + + if (!ads_execute($stmtid, $inputarr)) { + //@ads_free_result($stmtid); + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + return false; + } + + } else { + if (is_array($sql)) { + $stmtid = $sql[1]; + if (!ads_execute($stmtid)) { + //@ads_free_result($stmtid); + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + return false; + } + } else { + + $stmtid = ads_exec($this->_connectionID, $sql); + + } + } + + $this->_lastAffectedRows = 0; + + if ($stmtid) { + + if (@ads_num_fields($stmtid) == 0) { + $this->_lastAffectedRows = ads_num_rows($stmtid); + $stmtid = true; + + } else { + + $this->_lastAffectedRows = 0; + ads_binmode($stmtid, $this->binmode); + ads_longreadlen($stmtid, $this->maxblobsize); + + } + + $this->_errorMsg = ''; + $this->_errorCode = 0; + } else { + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + } + + return $stmtid; + + } + + /* + Insert a null into the blob field of the table first. + Then use UpdateBlob to store the blob. + + Usage: + + $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); + $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); + */ + function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB') + { + $last_php_error = $this->resetLastError(); + $sql = "UPDATE $table SET $column=? WHERE $where"; + $stmtid = ads_prepare($this->_connectionID, $sql); + if ($stmtid == false) { + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); + return false; + } + if (!ads_execute($stmtid, array($val), array(SQL_BINARY))) { + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + return false; + } + return true; + } + + // returns true or false + function _close() + { + $ret = @ads_close($this->_connectionID); + $this->_connectionID = false; + return $ret; + } + + function _affectedrows() + { + return $this->_lastAffectedRows; + } + +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ + +class ADORecordSet_ads extends ADORecordSet +{ + + var $bind = false; + var $databaseType = "ads"; + var $dataProvider = "ads"; + var $useFetchArray; + + function __construct($id, $mode = false) + { + if ($mode === false) { + global $ADODB_FETCH_MODE; + $mode = $ADODB_FETCH_MODE; + } + $this->fetchMode = $mode; + + $this->_queryID = $id; + + // the following is required for mysql odbc driver in 4.3.1 -- why? + $this->EOF = false; + $this->_currentRow = -1; + //parent::__construct($id); + } + + + // returns the field object + function &FetchField($fieldOffset = -1) + { + + $off = $fieldOffset + 1; // offsets begin at 1 + + $o = new ADOFieldObject(); + $o->name = @ads_field_name($this->_queryID, $off); + $o->type = @ads_field_type($this->_queryID, $off); + $o->max_length = @ads_field_len($this->_queryID, $off); + if (ADODB_ASSOC_CASE == 0) { + $o->name = strtolower($o->name); + } else { + if (ADODB_ASSOC_CASE == 1) { + $o->name = strtoupper($o->name); + } + } + return $o; + } + + /* Use associative array to get fields array */ + function Fields($colname) + { + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + return $this->fields[$colname]; + } + if (!$this->bind) { + $this->bind = array(); + for ($i = 0; $i < $this->_numOfFields; $i++) { + $o = $this->FetchField($i); + $this->bind[strtoupper($o->name)] = $i; + } + } + + return $this->fields[$this->bind[strtoupper($colname)]]; + } + + + function _initrs() + { + global $ADODB_COUNTRECS; + $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1; + $this->_numOfFields = @ads_num_fields($this->_queryID); + // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 + if ($this->_numOfRows == 0) { + $this->_numOfRows = -1; + } + //$this->useFetchArray = $this->connection->useFetchArray; + } + + function _seek($row) + { + return false; + } + + // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated + function &GetArrayLimit($nrows, $offset = -1) + { + if ($offset <= 0) { + $rs =& $this->GetArray($nrows); + return $rs; + } + $savem = $this->fetchMode; + $this->fetchMode = ADODB_FETCH_NUM; + $this->Move($offset); + $this->fetchMode = $savem; + + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + $this->fields =& $this->GetRowAssoc(); + } + + $results = array(); + $cnt = 0; + while (!$this->EOF && $nrows != $cnt) { + $results[$cnt++] = $this->fields; + $this->MoveNext(); + } + + return $results; + } + + + function MoveNext() + { + if ($this->_numOfRows != 0 && !$this->EOF) { + $this->_currentRow++; + if ($this->_fetch()) { + return true; + } + } + $this->fields = false; + $this->EOF = true; + return false; + } + + function _fetch() + { + $this->fields = false; + $rez = @ads_fetch_into($this->_queryID, $this->fields); + if ($rez) { + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + $this->fields =& $this->GetRowAssoc(); + } + return true; + } + return false; + } + + function _close() + { + return @ads_free_result($this->_queryID); + } + +} diff --git a/www/include/adodb5/drivers/adodb-borland_ibase.inc.php b/www/include/adodb/drivers/adodb-borland_ibase.inc.php similarity index 66% rename from www/include/adodb5/drivers/adodb-borland_ibase.inc.php rename to www/include/adodb/drivers/adodb-borland_ibase.inc.php index d3de2caa..da2c7618 100644 --- a/www/include/adodb5/drivers/adodb-borland_ibase.inc.php +++ b/www/include/adodb/drivers/adodb-borland_ibase.inc.php @@ -1,18 +1,25 @@ 0) { if ($offset <= 0) $str = " ROWS $nrows "; else { @@ -80,8 +89,4 @@ class ADORecordSet_borland_ibase extends ADORecordSet_ibase { var $databaseType = "borland_ibase"; - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } } diff --git a/www/include/adodb5/drivers/adodb-csv.inc.php b/www/include/adodb/drivers/adodb-csv.inc.php similarity index 76% rename from www/include/adodb5/drivers/adodb-csv.inc.php rename to www/include/adodb/drivers/adodb-csv.inc.php index fd47784d..8a59626e 100644 --- a/www/include/adodb5/drivers/adodb-csv.inc.php +++ b/www/include/adodb/drivers/adodb-csv.inc.php @@ -1,21 +1,30 @@ _insertid; + return $this->_insertid; } function _affectedrows() { - return $this->_affectedrows; + return $this->_affectedrows; } function MetaDatabases() @@ -83,8 +88,10 @@ function MetaColumns($table, $normalize=true) // parameters use PostgreSQL convention, not MySQL function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0) { - global $ADODB_FETCH_MODE; + global $ADODB_FETCH_MODE; + $nrows = (int) $nrows; + $offset = (int) $offset; $url = $this->_url.'?sql='.urlencode($sql)."&nrows=$nrows&fetch=". (($this->fetchMode !== false)?$this->fetchMode : $ADODB_FETCH_MODE). "&offset=$offset"; @@ -176,7 +183,7 @@ function _Execute($sql,$inputarr=false) /* Returns: the last error message from previous database operation */ function ErrorMsg() { - return $this->_errorMsg; + return $this->_errorMsg; } /* Returns: the last error number from previous database operation */ @@ -193,10 +200,6 @@ function _close() } // class class ADORecordset_csv extends ADORecordset { - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } function _close() { diff --git a/www/include/adodb/drivers/adodb-db2.inc.php b/www/include/adodb/drivers/adodb-db2.inc.php new file mode 100644 index 00000000..16c4054f --- /dev/null +++ b/www/include/adodb/drivers/adodb-db2.inc.php @@ -0,0 +1,2008 @@ +doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename); + } + + public function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) + { + return $this->doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename,true); + } + + private function doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persistent=false) + { + + if (!function_exists('db2_connect')) { + ADOConnection::outp("DB2 extension not installed."); + return null; + } + + $connectionParameters = $this->unpackParameters($argDSN, + $argUsername, + $argPassword, + $argDatabasename); + + if ($connectionParameters == null) + { + /* + * Error thrown + */ + return null; + } + + $argDSN = $connectionParameters['dsn']; + $argUsername = $connectionParameters['uid']; + $argPassword = $connectionParameters['pwd']; + $argDatabasename = $connectionParameters['database']; + $useCataloguedConnection = $connectionParameters['catalogue']; + + if ($this->debug){ + if ($useCataloguedConnection){ + $connectMessage = "Catalogued connection using parameters: "; + $connectMessage .= "DB=$argDatabasename / "; + $connectMessage .= "UID=$argUsername / "; + $connectMessage .= "PWD=$argPassword"; + } + else + { + $connectMessage = "Uncatalogued connection using DSN: $argDSN"; + } + ADOConnection::outp($connectMessage); + } + /* + * This needs to be set before the connect(). + */ + ini_set('ibm_db2.binmode', $this->binmode); + + if ($persistent) + $db2Function = 'db2_pconnect'; + else + $db2Function = 'db2_connect'; + + /* + * We need to flatten out the connectionParameters + */ + + $db2Options = array(); + if ($this->connectionParameters) + { + foreach($this->connectionParameters as $p) + foreach($p as $k=>$v) + $db2Options[$k] = $v; + } + + if ($useCataloguedConnection) + $this->_connectionID = $db2Function($argDatabasename, + $argUsername, + $argPassword, + $db2Options); + else + $this->_connectionID = $db2Function($argDSN, + null, + null, + $db2Options); + + + $this->_errorMsg = @db2_conn_errormsg(); + + if ($this->_connectionID && $this->connectStmt) + $this->execute($this->connectStmt); + + return $this->_connectionID != false; + + } + + /** + * Validates and preprocesses the passed parameters for consistency + * + * @param string $argDSN Either DSN or database + * @param string $argUsername User name or null + * @param string $argPassword Password or null + * @param string $argDatabasename Either DSN or database + * + * @return mixed array if correct, null if not + */ + private function unpackParameters($argDSN, $argUsername, $argPassword, $argDatabasename) + { + + + $connectionParameters = array('dsn'=>'', + 'uid'=>'', + 'pwd'=>'', + 'database'=>'', + 'catalogue'=>true + ); + + /* + * Uou can either connect to a catalogued connection + * with a database name e.g. 'SAMPLE' + * or an uncatalogued connection with a DSN like connection + * DATABASE=database;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=password; + */ + + if (!$argDSN && !$argDatabasename) + { + $errorMessage = 'Supply either catalogued or uncatalogued connection parameters'; + $this->_errorMsg = $errorMessage; + if ($this->debug) + ADOConnection::outp($errorMessage); + return null; + } + + $useCataloguedConnection = true; + $schemaName = ''; + + if ($argDSN && $argDatabasename) + { + /* + * If a catalogued connection if provided, + * as well as user and password + * that will take priority + */ + if ($argUsername && $argPassword && !$this->isDsn($argDatabasename)) + { + if ($this->debug){ + $errorMessage = 'Warning: Because you provided user,'; + $errorMessage.= 'password and database, DSN connection '; + $errorMessage.= 'parameters were discarded'; + ADOConnection::outp($errorMessage); + + } + $argDSN = ''; + } + else if ($this->isDsn($argDSN) && $this->isDsn($argDatabasename)) + { + $errorMessage = 'Supply uncatalogued connection parameters '; + $errorMessage.= 'in either the database or DSN arguments, '; + $errorMessage.= 'but not both'; + + if ($this->debug) + ADOConnection::outp($errorMessage); + return null; + } + } + + if (!$this->isDsn($argDSN) && $this->isDsn($argDatabasename)) + { + /* + * Switch them around for next test + */ + $temp = $argDSN; + $argDsn = $argDatabasename; + $argDatabasenME = $temp; + } + + if ($this->isDsn($argDSN)) + { + + if (!preg_match('/uid=/i',$argDSN) + || !preg_match('/pwd=/i',$argDSN)) + { + $errorMessage = 'For uncatalogued connections, provide '; + $errorMessage.= 'both UID and PWD in the connection string'; + + if ($this->debug) + ADOConnection::outp($errorMessage); + return null; + } + + if (preg_match('/database=/i',$argDSN)) + { + if ($argDatabasename) + { + $argDatabasename = ''; + if ($this->debug) + { + $errorMessage = 'Warning: Because you provided '; + $errorMessage.= 'database information in the DSN '; + $errorMessage.= 'parameters, the supplied database '; + $errorMessage.= 'name was discarded'; + ADOConnection::outp($errorMessage); + } + } + $useCataloguedConnection = false; + + } + elseif ($argDatabasename) + { + $this->databaseName = $argDatabasename; + $argDSN .= ';database=' . $argDatabasename; + $argDatabasename = ''; + $useCataloguedConnection = false; + + } + else + { + $errorMessage = 'Uncatalogued connection parameters '; + $errorMessage.= 'must contain a database= argument'; + + if ($this->debug) + ADOConnection::outp($errorMessage); + return null; + } + } + + if ($argDSN && !$argDatabasename && $useCataloguedConnection) + { + $argDatabasename = $argDSN; + $argDSN = ''; + } + + + if ($useCataloguedConnection + && (!$argDatabasename + || !$argUsername + || !$argPassword)) + { + + $errorMessage = 'For catalogued connections, provide '; + $errorMessage.= 'database, username and password'; + $this->_errorMsg = $errorMessage; + if ($this->debug) + ADOConnection::outp($errorMessage); + return null; + + } + + if ($argDatabasename) + $this->databaseName = $argDatabasename; + elseif (!$this->databaseName) + $this->databaseName = $this->getDatabasenameFromDsn($argDSN); + + + $connectionParameters = array('dsn'=>$argDSN, + 'uid'=>$argUsername, + 'pwd'=>$argPassword, + 'database'=>$argDatabasename, + 'catalogue'=>$useCataloguedConnection + ); + + return $connectionParameters; + + } + + /** + * Does the provided string look like a DSN + * + * @param string $dsnString + * + * @return bool + */ + private function isDsn($dsnString){ + $dsnArray = preg_split('/[;=]+/',$dsnString); + if (count($dsnArray) > 2) + return true; + return false; + } + + + /** + * Gets the database name from the DSN + * + * @param string $dsnString + * + * @return string + */ + private function getDatabasenameFromDsn($dsnString){ + + $dsnArray = preg_split('/[;=]+/',$dsnString); + $dbIndex = array_search('database',$dsnArray); + + return $dsnArray[$dbIndex + 1]; + } + + + /** + * format and return date string in database timestamp format + * + * @param mixed $ts either a string or a unixtime + * @param bool $isField discarded + * + * @return string + */ + function dbTimeStamp($ts,$isField=false) + { + if (empty($ts) && $ts !== 0) return 'null'; + if (is_string($ts)) $ts = ADORecordSet::unixTimeStamp($ts); + return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'YYYY-MM-DD HH24:MI:SS')"; + } + + /** + * Format date column in sql string given an input format that understands Y M D + * + * @param string $fmt + * @param bool $col + * + * @return string + */ + function sqlDate($fmt, $col=false) + { + if (!$col) $col = $this->sysDate; + + /* use TO_CHAR() if $fmt is TO_CHAR() allowed fmt */ + if ($fmt== 'Y-m-d H:i:s') + return 'TO_CHAR('.$col.", 'YYYY-MM-DD HH24:MI:SS')"; + + $s = ''; + + $len = strlen($fmt); + for ($i=0; $i < $len; $i++) { + if ($s) $s .= $this->concat_operator; + $ch = $fmt[$i]; + switch($ch) { + case 'Y': + case 'y': + if ($len==1) return "year($col)"; + $s .= "char(year($col))"; + break; + case 'M': + if ($len==1) return "monthname($col)"; + $s .= "substr(monthname($col),1,3)"; + break; + case 'm': + if ($len==1) return "month($col)"; + $s .= "right(digits(month($col)),2)"; + break; + case 'D': + case 'd': + if ($len==1) return "day($col)"; + $s .= "right(digits(day($col)),2)"; + break; + case 'H': + case 'h': + if ($len==1) return "hour($col)"; + if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)"; + else $s .= "''"; + break; + case 'i': + case 'I': + if ($len==1) return "minute($col)"; + if ($col != $this->sysDate) + $s .= "right(digits(minute($col)),2)"; + else $s .= "''"; + break; + case 'S': + case 's': + if ($len==1) return "second($col)"; + if ($col != $this->sysDate) + $s .= "right(digits(second($col)),2)"; + else $s .= "''"; + break; + default: + if ($ch == '\\') { + $i++; + $ch = substr($fmt,$i,1); + } + $s .= $this->qstr($ch); + } + } + return $s; + } + + + function serverInfo() + { + $sql = "SELECT service_level, fixpack_num + FROM TABLE(sysproc.env_get_inst_info()) + AS INSTANCEINFO"; + $row = $this->GetRow($sql); + + + if ($row) { + $info['version'] = $row[0].':'.$row[1]; + $info['fixpack'] = $row[1]; + $info['description'] = ''; + } else { + return ADOConnection::serverInfo(); + } + + return $info; + } + + function createSequence($seqname='adodbseq',$start=1) + { + if (empty($this->_genSeqSQL)) + return false; + + $ok = $this->execute(sprintf($this->_genSeqSQL,$seqname,$start)); + if (!$ok) + return false; + return true; + } + + function dropSequence($seqname='adodbseq') + { + if (empty($this->_dropSeqSQL)) return false; + return $this->execute(sprintf($this->_dropSeqSQL,$seqname)); + } + + function selectLimit($sql,$nrows=-1,$offset=-1,$inputArr=false,$secs2cache=0) + { + $nrows = (integer) $nrows; + + if ($offset <= 0) + { + if ($nrows >= 0) + $sql .= " FETCH FIRST $nrows ROWS ONLY "; + + $rs = $this->execute($sql,$inputArr); + + } + else + { + if ($offset > 0 && $nrows < 0); + + else + { + $nrows += $offset; + $sql .= " FETCH FIRST $nrows ROWS ONLY "; + } + + /* + * DB2 has no native support for mid table offset + */ + $rs = ADOConnection::selectLimit($sql,$nrows,$offset,$inputArr); + + } + + return $rs; + } + + + function errorMsg() + { + if ($this->_errorMsg !== false) + return $this->_errorMsg; + + if (empty($this->_connectionID)) + return @db2_conn_errormsg(); + + return @db2_conn_errormsg($this->_connectionID); + } + + function errorNo() + { + + if ($this->_errorCode !== false) + return $this->_errorCode; + + + if (empty($this->_connectionID)) + $e = @db2_conn_error(); + + else + $e = @db2_conn_error($this->_connectionID); + + return $e; + } + + + + function beginTrans() + { + if (!$this->hasTransactions) + return false; + if ($this->transOff) + return true; + + $this->transCnt += 1; + + $this->_autocommit = false; + + return db2_autocommit($this->_connectionID,false); + } + + function CommitTrans($ok=true) + { + if ($this->transOff) + return true; + + if (!$ok) + return $this->RollbackTrans(); + + if ($this->transCnt) + $this->transCnt -= 1; + + $this->_autocommit = true; + $ret = @db2_commit($this->_connectionID); + @db2_autocommit($this->_connectionID,true); + return $ret; + } + + function RollbackTrans() + { + if ($this->transOff) return true; + if ($this->transCnt) $this->transCnt -= 1; + $this->_autocommit = true; + $ret = @db2_rollback($this->_connectionID); + @db2_autocommit($this->_connectionID,true); + return $ret; + } + + /** + * Return a list of Primary Keys for a specified table + * + * We don't use db2_statistics as the function does not seem to play + * well with mixed case table names + * + * @param string $table + * @param bool $primary (optional) only return primary keys + * @param bool $owner (optional) not used in this driver + * + * @return string[] Array of indexes + */ + public function metaPrimaryKeys($table,$owner=false) + { + + $primaryKeys = array(); + + global $ADODB_FETCH_MODE; + + $schema = ''; + $this->_findschema($table,$schema); + + $table = $this->getTableCasedValue($table); + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + $this->setFetchMode(ADODB_FETCH_NUM); + + + $sql = "SELECT * + FROM syscat.indexes + WHERE tabname='$table'"; + + $rows = $this->getAll($sql); + + $this->setFetchMode($savem); + $ADODB_FETCH_MODE = $savem; + + if (empty($rows)) + return false; + + foreach ($rows as $r) + { + if ($r[7] != 'P') + continue; + + $cols = explode('+',$r[6]); + foreach ($cols as $colIndex=>$col) + { + if ($colIndex == 0) + continue; + $columnName = $this->getMetaCasedValue($col); + $primaryKeys[] = $columnName; + } + break; + } + return $primaryKeys; + } + + /** + * Returns a list of Foreign Keys associated with a specific table. + * + * @param string $table + * @param string $owner discarded + * @param bool $upper discarded + * @param bool $associative discarded + * + * @return string[]|false An array where keys are tables, and values are foreign keys; + * false if no foreign keys could be found. + */ + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) + { + + global $ADODB_FETCH_MODE; + + $schema = ''; + $this->_findschema($table,$schema); + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + $this->setFetchMode(ADODB_FETCH_NUM); + + $sql = "SELECT SUBSTR(tabname,1,20) table_name, + SUBSTR(constname,1,20) fk_name, + SUBSTR(REFTABNAME,1,12) parent_table, + SUBSTR(refkeyname,1,20) pk_orig_table, + fk_colnames + FROM syscat.references + WHERE tabname = '$table'"; + + $results = $this->getAll($sql); + + $ADODB_FETCH_MODE = $savem; + $this->setFetchMode($savem); + + if (empty($results)) + return false; + + $foreignKeys = array(); + + foreach ($results as $r) + { + $parentTable = trim($this->getMetaCasedValue($r[2])); + $keyName = trim($this->getMetaCasedValue($r[1])); + $foreignKeys[$parentTable] = $keyName; + } + + return $foreignKeys; + } + + /** + * Returns a list of tables + * + * @param string $ttype (optional) + * @param string $schema (optional) + * @param string $mask (optional) + * + * @return array + */ + public function metaTables($ttype=false,$schema=false,$mask=false) + { + + global $ADODB_FETCH_MODE; + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + /* + * Values for TABLE_TYPE + * --------------------------- + * ALIAS, HIERARCHY TABLE, INOPERATIVE VIEW, NICKNAME, + * MATERIALIZED QUERY TABLE, SYSTEM TABLE, TABLE, + * TYPED TABLE, TYPED VIEW, and VIEW + * + * If $ttype passed as '', match 'TABLE' and 'VIEW' + * If $ttype passed as 'T' it is assumed to be 'TABLE' + * if $ttype passed as 'V' it is assumed to be 'VIEW' + */ + $ttype = strtoupper($ttype); + if ($ttype) { + /* + * @todo We could do valid type checking or array type + */ + if ($ttype == 'V') + $ttype = 'VIEW'; + if ($ttype == 'T') + $ttype = 'TABLE'; + } + + if (!$schema) + $schema = '%'; + + if (!$mask) + $mask = '%'; + + $qid = @db2_tables($this->_connectionID,NULL,$schema,$mask,$ttype); + + $rs = new ADORecordSet_db2($qid); + + $ADODB_FETCH_MODE = $savem; + + if (!$rs) + return false; + + $arr = $rs->getArray(); + + $rs->Close(); + + $tableList = array(); + + /* + * Array items + * --------------------------------- + * 0 TABLE_CAT The catalog that contains the table. + * The value is NULL if this table does not have catalogs. + * 1 TABLE_SCHEM Name of the schema that contains the table. + * 2 TABLE_NAME Name of the table. + * 3 TABLE_TYPE Table type identifier for the table. + * 4 REMARKS Description of the table. + */ + + for ($i=0; $i < sizeof($arr); $i++) + { + + $tableRow = $arr[$i]; + $tableName = $tableRow[2]; + $tableType = $tableRow[3]; + + if (!$tableName) + continue; + + if ($ttype == '' && (strcmp($tableType,'TABLE') <> 0 && strcmp($tableType,'VIEW') <> 0)) + continue; + + /* + * Set metacasing if required + */ + $tableName = $this->getMetaCasedValue($tableName); + + /* + * If we requested a schema, we prepend the schema + name to the table name + */ + if (strcmp($schema,'%') <> 0) + $tableName = $schema . '.' . $tableName; + + $tableList[] = $tableName; + + } + return $tableList; + } + + /** + * Return a list of indexes for a specified table + * + * We don't use db2_statistics as the function does not seem to play + * well with mixed case table names + * + * @param string $table + * @param bool $primary (optional) only return primary keys + * @param bool $owner (optional) not used in this driver + * + * @return string[] Array of indexes + */ + public function metaIndexes($table, $primary = false, $owner = false) { + + global $ADODB_FETCH_MODE; + + /* Array( + * [name_of_index] => Array( + * [unique] => true or false + * [columns] => Array( + * [0] => firstcol + * [1] => nextcol + * [2] => etc........ + * ) + * ) + * ) + */ + $indices = array(); + $primaryKeyName = ''; + + $table = $this->getTableCasedValue($table); + + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + $this->setFetchMode(ADODB_FETCH_NUM); + + $sql = "SELECT * + FROM syscat.indexes + WHERE tabname='$table'"; + + $rows = $this->getAll($sql); + + $this->setFetchMode($savem); + $ADODB_FETCH_MODE = $savem; + + if (empty($rows)) + return false; + + foreach ($rows as $r) + { + + $primaryIndex = $r[7] == 'P'?1:0; + if (!$primary) + /* + * Primary key not requested, ignore that one + */ + if ($r[7] == 'P') + continue; + + $indexName = $this->getMetaCasedValue($r[1]); + if (!isset($indices[$indexName])) + { + $unique = ($r[7] == 'U')?1:0; + $indices[$indexName] = array('unique'=>$unique, + 'primary'=>$primaryIndex, + 'columns'=>array() + ); + } + $cols = explode('+',$r[6]); + foreach ($cols as $colIndex=>$col) + { + if ($colIndex == 0) + continue; + $columnName = $this->getMetaCasedValue($col); + $indices[$indexName]['columns'][] = $columnName; + } + + } + + return $indices; + + } + + /** + * List procedures or functions in an array. + * + * We interrogate syscat.routines instead of calling the PHP + * function procedures because ADOdb requires the type of procedure + * this is not available in the php function + * + * @param string $procedureNamePattern (optional) + * @param string $catalog (optional) + * @param string $schemaPattern (optional) + + * @return array of procedures on current database. + * + */ + public function metaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null) { + + + global $ADODB_FETCH_MODE; + + $metaProcedures = array(); + $procedureSQL = ''; + $catalogSQL = ''; + $schemaSQL = ''; + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + if ($procedureNamePattern) + $procedureSQL = "AND ROUTINENAME LIKE " . strtoupper($this->qstr($procedureNamePattern)); + + if ($catalog) + $catalogSQL = "AND OWNER=" . strtoupper($this->qstr($catalog)); + + if ($schemaPattern) + $schemaSQL = "AND ROUTINESCHEMA LIKE {$this->qstr($schemaPattern)}"; + + + $fields = " + ROUTINENAME, + CASE ROUTINETYPE + WHEN 'P' THEN 'PROCEDURE' + WHEN 'F' THEN 'FUNCTION' + ELSE 'METHOD' + END AS ROUTINETYPE_NAME, + ROUTINESCHEMA, + REMARKS"; + + $SQL = "SELECT $fields + FROM syscat.routines + WHERE OWNER IS NOT NULL + $procedureSQL + $catalogSQL + $schemaSQL + ORDER BY ROUTINENAME + "; + + $result = $this->execute($SQL); + + $ADODB_FETCH_MODE = $savem; + + if (!$result) + return false; + + while ($r = $result->fetchRow()){ + $procedureName = $this->getMetaCasedValue($r[0]); + $schemaName = $this->getMetaCasedValue($r[2]); + $metaProcedures[$procedureName] = array('type'=> $r[1], + 'catalog' => '', + 'schema' => $schemaName, + 'remarks' => $r[3] + ); + } + + return $metaProcedures; + + } + + /** + * Lists databases. Because instances are independent, we only know about + * the current database name + * + * @return string[] + */ + public function metaDatabases(){ + + $dbName = $this->getMetaCasedValue($this->databaseName); + + return (array)$dbName; + + } + + + + +/* +See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2datetime_data_type_changes.asp +/ SQL data type codes / +#define SQL_UNKNOWN_TYPE 0 +#define SQL_CHAR 1 +#define SQL_NUMERIC 2 +#define SQL_DECIMAL 3 +#define SQL_INTEGER 4 +#define SQL_SMALLINT 5 +#define SQL_FLOAT 6 +#define SQL_REAL 7 +#define SQL_DOUBLE 8 +#if (DB2VER >= 0x0300) +#define SQL_DATETIME 9 +#endif +#define SQL_VARCHAR 12 + + +/ One-parameter shortcuts for date/time data types / +#if (DB2VER >= 0x0300) +#define SQL_TYPE_DATE 91 +#define SQL_TYPE_TIME 92 +#define SQL_TYPE_TIMESTAMP 93 + +#define SQL_UNICODE (-95) +#define SQL_UNICODE_VARCHAR (-96) +#define SQL_UNICODE_LONGVARCHAR (-97) +*/ + function DB2Types($t) + { + switch ((integer)$t) { + case 1: + case 12: + case 0: + case -95: + case -96: + return 'C'; + case -97: + case -1: //text + return 'X'; + case -4: //image + return 'B'; + + case 9: + case 91: + return 'D'; + + case 10: + case 11: + case 92: + case 93: + return 'T'; + + case 4: + case 5: + case -6: + return 'I'; + + case -11: // uniqidentifier + return 'R'; + case -7: //bit + return 'L'; + + default: + return 'N'; + } + } + + public function metaColumns($table, $normalize=true) + { + global $ADODB_FETCH_MODE; + + $savem = $ADODB_FETCH_MODE; + + $schema = '%'; + $this->_findschema($table,$schema); + $table = $this->getTableCasedValue($table); + $colname = "%"; + $qid = db2_columns($this->_connectionID, null, $schema, $table, $colname); + if (empty($qid)) + { + if ($this->debug) + { + $errorMessage = @db2_conn_errormsg($this->_connectionID); + ADOConnection::outp($errorMessage); + } + return false; + } + + $rs = new ADORecordSet_db2($qid); + + if (!$rs) + return false; + + $rs->_fetch(); + + $retarr = array(); + + /* + $rs->fields indices + 0 TABLE_QUALIFIER + 1 TABLE_SCHEM + 2 TABLE_NAME + 3 COLUMN_NAME + 4 DATA_TYPE + 5 TYPE_NAME + 6 PRECISION + 7 LENGTH + 8 SCALE + 9 RADIX + 10 NULLABLE + 11 REMARKS + 12 Column Default + 13 SQL Data Type + 14 SQL DateTime SubType + 15 Max length in Octets + 16 Ordinal Position + 17 Is NULLABLE + */ + while (!$rs->EOF) + { + if ($rs->fields[2] == $table) + { + + $fld = new ADOFieldObject(); + $fld->name = $rs->fields[3]; + $fld->type = $this->DB2Types($rs->fields[4]); + + // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp + // access uses precision to store length for char/varchar + + if ($fld->type == 'C' or $fld->type == 'X') { + if ($rs->fields[4] <= -95) // UNICODE + $fld->max_length = $rs->fields[7]/2; + else + $fld->max_length = $rs->fields[7]; + } else + $fld->max_length = $rs->fields[7]; + + $fld->not_null = !empty($rs->fields[10]); + $fld->scale = $rs->fields[8]; + $fld->primary_key = false; + + //$columnName = $this->getMetaCasedValue($fld->name); + $columnName = strtoupper($fld->name); + $retarr[$columnName] = $fld; + + } + else if (sizeof($retarr)>0) + break; + + $rs->MoveNext(); + + } + + $rs->Close(); + if (empty($retarr)) + $retarr = false; + + /* + * Now we find out if the column is part of a primary key + */ + + $qid = @db2_primary_keys($this->_connectionID, "", $schema, $table); + if (empty($qid)) + return false; + + $rs = new ADORecordSet_db2($qid); + + if (!$rs) + { + $ADODB_FETCH_MODE = $savem; + return $retarr; + } + $rs->_fetch(); + + /* + $rs->fields indices + 0 TABLE_CAT + 1 TABLE_SCHEM + 2 TABLE_NAME + 3 COLUMN_NAME + 4 KEY_SEQ + 5 PK_NAME + */ + while (!$rs->EOF) { + if (strtoupper(trim($rs->fields[2])) == $table + && (!$schema || strtoupper($rs->fields[1]) == $schema)) + { + $retarr[strtoupper($rs->fields[3])]->primary_key = true; + } + else if (sizeof($retarr)>0) + break; + + $rs->MoveNext(); + } + $rs->Close(); + + $ADODB_FETCH_MODE = $savem; + + if (empty($retarr)) + return false; + + /* + * If the fetch mode is numeric, return as numeric array + */ + if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) + $retarr = array_values($retarr); + + return $retarr; + } + + /** + * In this version if prepareSp, we just check to make sure + * that the name of the stored procedure is correct + * If true, we returns an array + * else false + * + * @param string $procedureName + * @param mixed $parameters (not used in db2 connections) + * @return mixed[] + */ + function prepareSp($procedureName,$parameters=false) { + + global $ADODB_FETCH_MODE; + + $this->storedProcedureParameters = array('name'=>'', + 'resource'=>false, + 'in'=>array(), + 'out'=>array(), + 'index'=>array(), + 'parameters'=>array(), + 'keyvalue' => array()); + + //$procedureName = strtoupper($procedureName); + //$procedureName = $this->getTableCasedValue($procedureName); + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + $qid = db2_procedures($this->_connectionID, NULL , '%' , $procedureName ); + + $ADODB_FETCH_MODE = $savem; + + if (!$qid) + { + if ($this->debug) + ADOConnection::outp(sprintf('No Procedure of name %s available',$procedureName)); + return false; + } + + + + $this->storedProcedureParameters['name'] = $procedureName; + /* + * Now we know we have a valid procedure name, lets see if it requires + * parameters + */ + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + $qid = db2_procedure_columns($this->_connectionID, NULL , '%' , $procedureName , NULL ); + + $ADODB_FETCH_MODE = $savem; + + if (!$qid) + { + if ($this->debug) + ADOConnection::outp(sprintf('No columns of name %s available',$procedureName)); + return false; + } + $rs = new ADORecordSet_db2($qid); + if (!$rs) + return false; + + $preparedStatement = 'CALL %s(%s)'; + $parameterMarkers = array(); + while (!$rs->EOF) + { + $parameterName = $rs->fields[3]; + if ($parameterName == '') + { + $rs->moveNext(); + continue; + } + $parameterType = $rs->fields[4]; + $ordinalPosition = $rs->fields[17]; + switch($parameterType) + { + case DB2_PARAM_IN: + case DB2_PARAM_INOUT: + $this->storedProcedureParameters['in'][$parameterName] = ''; + break; + case DB2_PARAM_INOUT: + case DB2_PARAM_OUT: + $this->storedProcedureParameters['out'][$parameterName] = ''; + break; + } + $this->storedProcedureParameters['index'][$parameterName] = $ordinalPosition; + $this->storedProcedureParameters['parameters'][$ordinalPosition] = $rs->fields; + $rs->moveNext(); + + } + $parameterCount = count($this->storedProcedureParameters['index']); + $parameterMarkers = array_fill(0,$parameterCount,'?'); + + /* + * We now know how many parameters to bind to the stored procedure + */ + $parameterList = implode(',',$parameterMarkers); + + $sql = sprintf($preparedStatement,$procedureName,$parameterList); + + $spResource = @db2_prepare($this->_connectionID,$sql); + + if (!$spResource) + { + $errorMessage = @db2_conn_errormsg($this->_connectionID); + $this->_errorMsg = $errorMessage; + + if ($this->debug) + ADOConnection::outp($errorMessage); + + return false; + } + + $this->storedProcedureParameters['resource'] = $spResource; + + if ($this->debug) + { + + ADOConnection::outp('The following parameters will be used in the SP call'); + ADOConnection::outp(print_r($this->storedProcedureParameters)); + } + /* + * We now have a stored parameter resource + * to bind to. The spResource and sql that is returned are + * not usable, its for dummy compatibility. Everything + * will be handled by the storedProcedureParameters + * array + */ + return array($sql,$spResource); + + } + + private function storedProcedureParameter(&$stmt, + &$var, + $name, + $isOutput=false, + $maxLen=4000, + $type=false) + { + + + $name = strtoupper($name); + + /* + * Must exist in the list of parameter names for the type + */ + if ($isOutput + && !isset( $this->storedProcedureParameters['out'][$name])) + { + $errorMessage = sprintf('%s is not a valid OUT parameter name',$name); + + $this->_errorMsg = $errorMessage; + if ($this->debug) + ADOConnection::outp($errorMessage); + return false; + } + + if (!$isOutput + && !isset( $this->storedProcedureParameters['in'][$name])) + { + $errorMessage = sprintf('%s is not a valid IN parameter name',$name); + + $this->_errorMsg = $errorMessage; + if ($this->debug) + ADOConnection::outp($errorMessage); + return false; + } + + /* + * We will use these values to bind to when we execute + * the query + */ + $this->storedProcedureParameters['keyvalue'][$name] = &$var; + + return true; + + } + + /** + * Executes a prepared stored procedure. + * + * The function uses the previously accumulated information and + * resources in the $storedProcedureParameters array + * + * @return mixed The statement id if successful, or false + */ + private function executeStoredProcedure() + { + + /* + * Get the previously built resource + */ + $stmtid = $this->storedProcedureParameters['resource']; + + /* + * Bind our variables to the DB2 procedure + */ + foreach ($this->storedProcedureParameters['keyvalue'] as $spName=>$spValue){ + + /* + * Get the ordinal position, required for binding + */ + $ordinalPosition = $this->storedProcedureParameters['index'][$spName]; + + /* + * Get the db2 column dictionary for the parameter + */ + $columnDictionary = $this->storedProcedureParameters['parameters'][$ordinalPosition]; + $parameterType = $columnDictionary[4]; + $dataType = $columnDictionary[5]; + $precision = $columnDictionary[10]; + $scale = $columnDictionary[9]; + + $ok = @db2_bind_param ($this->storedProcedureParameters['resource'], + $ordinalPosition , + $spName, + $parameterType, + $dataType, + $precision, + $scale + ); + + if (!$ok) + { + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + + if ($this->debug) + ADOConnection::outp($this->_errorMsg); + return false; + } + + if ($this->debug) + ADOConnection::outp("Correctly Bound parameter $spName to procedure"); + + /* + * Build a variable in the current environment that matches + * the parameter name + */ + ${$spName} = $spValue; + + } + + /* + * All bound, execute + */ + + if (!@db2_execute($stmtid)) + { + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + + if ($this->debug) + ADOConnection::outp($this->_errorMsg); + return false; + } + + /* + * We now take the changed parameters back into the + * stored procedures array where we can query them later + * Remember that $spValue was passed in by reference, so we + * can access the value in the variable that was originally + * passed to inParameter or outParameter + */ + foreach ($this->storedProcedureParameters['keyvalue'] as $spName=>$spValue) + { + /* + * We make it available to the environment + */ + $spValue = ${$spName}; + $this->storedProcedureParameters['keyvalue'][$spName] = $spValue; + } + + return $stmtid; + } + + /** + * + * Accepts an input or output parameter to bind to either a stored + * or prepared statements. For DB2, this should not be called as an + * API. always wrap with inParameter and outParameter + * + * @param mixed[] $stmt Statement returned by Prepare() or PrepareSP(). + * @param mixed $var PHP variable to bind to. Can set to null (for isNull support). + * @param string $name Name of stored procedure variable name to bind to. + * @param int $isOutput optional) Indicates direction of parameter + * 0/false=IN 1=OUT 2= IN/OUT + * This is ignored for Stored Procedures + * @param int $maxLen (optional)Holds an maximum length of the variable. + * This is ignored for Stored Procedures + * @param int $type (optional) The data type of $var. + * This is ignored for Stored Procedures + * + * @return bool Success of the operation + */ + public function parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false) + { + + /* + * If the $stmt is the name of a stored procedure we are + * setting up, we will process it one way, otherwise + * we assume we are setting up a prepared statement + */ + if (is_array($stmt)) + { + if ($this->debug) + ADOConnection::outp("Adding parameter to stored procedure"); + if ($stmt[1] == $this->storedProcedureParameters['resource']) + return $this->storedProcedureParameter($stmt[1], + $var, + $name, + $isOutput, + $maxLen, + $type); + + } + + /* + * We are going to add a parameter to a prepared statement + */ + if ($this->debug) + ADOConnection::outp("Adding parameter to prepared statement"); + } + + + /** + * Prepares a prepared SQL statement, not used for stored procedures + * + * @param string $sql + * + * @return mixed + */ + function prepare($sql) + { + + if (! $this->_bindInputArray) return $sql; // no binding + + $stmt = @db2_prepare($this->_connectionID,$sql); + if (!$stmt) { + // we don't know whether db2 driver is parsing prepared stmts, so just return sql + return $sql; + } + return array($sql,$stmt,false); + } + + /** + * Executes a query + * + * @param mixed $sql + * @param mixed $inputarr An optional array of parameters + * + * @return mixed either the queryID or false + */ + function _query(&$sql,$inputarr=false) + { + + $this->_error = ''; + + $db2Options = array(); + /* + * Use DB2 Internal case handling for best speed + */ + switch(ADODB_ASSOC_CASE) + { + case ADODB_ASSOC_CASE_UPPER: + $db2Options = array('db2_attr_case'=>DB2_CASE_UPPER); + $setOption = @db2_set_option($this->_connectionID,$db2Options,1); + break; + + case ADODB_ASSOC_CASE_LOWER: + $db2Options = array('db2_attr_case'=>DB2_CASE_LOWER); + $setOption = @db2_set_option($this->_connectionID,$db2Options,1); + break; + + default: + $db2Options = array('db2_attr_case'=>DB2_CASE_NATURAL); + $setOption = @db2_set_option($this->_connectionID,$db2Options,1); + } + + if ($inputarr) + { + if (is_array($sql)) + { + $stmtid = $sql[1]; + } + else + { + $stmtid = @db2_prepare($this->_connectionID,$sql); + + if ($stmtid == false) + { + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + + if ($this->debug) + ADOConnection::outp($this->_errorMsg); + + return false; + } + } + + if (! @db2_execute($stmtid,$inputarr)) + { + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + if ($this->debug) + ADOConnection::outp($this->_errorMsg); + return false; + } + + } + else if (is_array($sql)) + { + + /* + * Either a prepared statement or a stored procedure + */ + + if (is_array($this->storedProcedureParameters) + && is_resource($this->storedProcedureParameters['resource'] + )) + /* + * This is all handled in the separate method for + * readability + */ + return $this->executeStoredProcedure(); + + /* + * First, we prepare the statement + */ + $stmtid = @db2_prepare($this->_connectionID,$sql[0]); + if (!$stmtid){ + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + if ($this->debug) + ADOConnection::outp("Prepare failed: " . $this->_errorMsg); + + return false; + } + /* + * We next bind some input parameters + */ + $ordinal = 1; + foreach ($sql[1] as $psVar=>$psVal){ + ${$psVar} = $psVal; + $ok = @db2_bind_param($stmtid, $ordinal, $psVar, DB2_PARAM_IN); + if (!$ok) + { + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + if ($this->debug) + ADOConnection::outp("Bind failed: " . $this->_errorMsg); + return false; + } + } + + if (!@db2_execute($stmtid)) + { + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + if ($this->debug) + ADOConnection::outp($this->_errorMsg); + return false; + } + + return $stmtid; + } + else + { + + $stmtid = @db2_exec($this->_connectionID,$sql); + } + $this->_lastAffectedRows = 0; + if ($stmtid) + { + if (@db2_num_fields($stmtid) == 0) + { + $this->_lastAffectedRows = db2_num_rows($stmtid); + $stmtid = true; + } + else + { + $this->_lastAffectedRows = 0; + } + + $this->_errorMsg = ''; + $this->_errorCode = 0; + + } + else + { + + $this->_errorMsg = @db2_stmt_errormsg(); + $this->_errorCode = @db2_stmt_error(); + + } + return $stmtid; + } + + /* + Insert a null into the blob field of the table first. + Then use UpdateBlob to store the blob. + + Usage: + + $conn->execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); + $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); + */ + function updateBlob($table,$column,$val,$where,$blobtype='BLOB') + { + return $this->execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false; + } + + // returns true or false + function _close() + { + $ret = @db2_close($this->_connectionID); + $this->_connectionID = false; + return $ret; + } + + function _affectedrows() + { + return $this->_lastAffectedRows; + } + + /** + * Gets a meta cased parameter + * + * Receives an input variable to be processed per the metaCasing + * rule, and returns the same value, processed + * + * @param string $value + * + * @return string + */ + final public function getMetaCasedValue($value) + { + global $ADODB_ASSOC_CASE; + + switch($ADODB_ASSOC_CASE) + { + case ADODB_ASSOC_CASE_LOWER: + $value = strtolower($value); + break; + case ADODB_ASSOC_CASE_UPPER: + $value = strtoupper($value); + break; + } + return $value; + } + + + const TABLECASE_LOWER = 0; + const TABLECASE_UPPER = 1; + const TABLECASE_DEFAULT = 2; + + /** + * Controls the casing of the table provided to the meta functions + */ + private $tableCase = 2; + + /** + * Sets the table case parameter + * + * @param int $caseOption + * @return null + */ + final public function setTableCasing($caseOption) + { + $this->tableCase = $caseOption; + } + + /** + * Gets the table casing parameter + * + * @return int $caseOption + */ + final public function getTableCasing() + { + return $this->tableCase; + } + + /** + * Gets a table cased parameter + * + * Receives an input variable to be processed per the tableCasing + * rule, and returns the same value, processed + * + * @param string $value + * + * @return string + */ + final public function getTableCasedValue($value) + { + switch($this->tableCase) + { + case self::TABLECASE_LOWER: + $value = strtolower($value); + break; + case self::TABLECASE_UPPER: + $value = strtoupper($value); + break; + } + return $value; + } + +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ + +class ADORecordSet_db2 extends ADORecordSet { + + var $bind = false; + var $databaseType = "db2"; + var $dataProvider = "db2"; + var $useFetchArray; + + function __construct($id,$mode=false) + { + if ($mode === false) { + global $ADODB_FETCH_MODE; + $mode = $ADODB_FETCH_MODE; + } + $this->fetchMode = $mode; + + $this->_queryID = $id; + } + + + // returns the field object + function fetchField($offset = 0) + { + $o = new ADOFieldObject(); + $o->name = @db2_field_name($this->_queryID,$offset); + $o->type = @db2_field_type($this->_queryID,$offset); + $o->max_length = @db2_field_width($this->_queryID,$offset); + + /* + if (ADODB_ASSOC_CASE == 0) + $o->name = strtolower($o->name); + else if (ADODB_ASSOC_CASE == 1) + $o->name = strtoupper($o->name); + */ + return $o; + } + + /* Use associative array to get fields array */ + function fields($colname) + { + + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + return $this->fields[$colname]; + } + + if (!$this->bind) { + $this->bind = array(); + for ($i=0; $i < $this->_numOfFields; $i++) { + $o = $this->FetchField($i); + $this->bind[strtoupper($o->name)] = $i; + } + } + + return $this->fields[$this->bind[strtoupper($colname)]]; + } + + + function _initrs() + { + global $ADODB_COUNTRECS; + $this->_numOfRows = ($ADODB_COUNTRECS) ? @db2_num_rows($this->_queryID) : -1; + + $this->_numOfFields = @db2_num_fields($this->_queryID); + + // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 + + if ($this->_numOfRows == 0) + $this->_numOfRows = -1; + } + + function _seek($row) + { + return false; + } + + function getArrayLimit($nrows,$offset=0) + { + if ($offset <= 0) { + $rs = $this->GetArray($nrows); + return $rs; + } + + $this->Move($offset); + + + $results = array(); + $cnt = 0; + while (!$this->EOF && $nrows != $cnt) { + $results[$cnt++] = $this->fields; + $this->MoveNext(); + } + + return $results; + } + + function moveNext() + { + if ($this->EOF || $this->_numOfRows == 0) + return false; + + $this->_currentRow++; + + $this->processCoreFetch(); + return $this->processMoveRecord(); + + } + + private function processCoreFetch() + { + switch ($this->fetchMode){ + case ADODB_FETCH_ASSOC: + + /* + * Associative array + */ + $this->fields = @db2_fetch_assoc($this->_queryID); + break; + + case ADODB_FETCH_BOTH: + /* + * Fetch both numeric and Associative array + */ + $this->fields = @db2_fetch_both($this->_queryID); + break; + default: + /* + * Numeric array + */ + $this->fields = @db2_fetch_array($this->_queryID); + break; + } + } + + private function processMoveRecord() + { + if (!$this->fields){ + $this->EOF = true; + return false; + } + + return true; + } + + function _fetch() + { + $this->processCoreFetch(); + if ($this->fields) + return true; + + $this->fields = false; + return false; + } + + function _close() + { + $ok = @db2_free_result($this->_queryID); + if (!$ok) + { + $this->_errorMsg = @db2_stmt_errormsg($this->_queryId); + $this->_errorCode = @db2_stmt_error(); + + if ($this->debug) + ADOConnection::outp($this->_errorMsg); + return false; + } + + } + +} diff --git a/www/include/adodb5/drivers/adodb-db2oci.inc.php b/www/include/adodb/drivers/adodb-db2oci.inc.php similarity index 70% rename from www/include/adodb5/drivers/adodb-db2oci.inc.php rename to www/include/adodb/drivers/adodb-db2oci.inc.php index 91d61af1..eea63d94 100644 --- a/www/include/adodb5/drivers/adodb-db2oci.inc.php +++ b/www/include/adodb/drivers/adodb-db2oci.inc.php @@ -1,63 +1,43 @@ $_COLONSZ) return $p; - $_COLONARR[] = $v; - return '?'; -} - -// smart remapping of :0, :1 bind vars to ? ? -function _colonscope($sql,$arr) -{ -global $_COLONARR,$_COLONSZ; - - $_COLONARR = array(); - $_COLONSZ = sizeof($arr); - - $sql2 = preg_replace("/(:[0-9]+)/e","_colontrack('\\1')",$sql); - - if (empty($_COLONARR)) return array($sql,$arr); - - foreach($_COLONARR as $k => $v) { - $arr2[] = $arr[$v]; - } - - return array($sql2,$arr2); -} -*/ - -/* - Smart remapping of :0, :1 bind vars to ? ? - - Handles colons in comments -- and / * * / and in quoted strings. -*/ - +/** + * Smart remapping of :0, :1 bind vars to ? ? + * Handles colons in comments -- and / * * / and in quoted strings. + * @param string $sql SQL statement + * @param array $arr parameters + * @return array + */ function _colonparser($sql,$arr) { $lensql = strlen($sql); @@ -217,10 +197,6 @@ class ADORecordSet_db2oci extends ADORecordSet_db2 { var $databaseType = "db2oci"; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } } //define diff --git a/www/include/adodb5/drivers/adodb-db2ora.inc.php b/www/include/adodb/drivers/adodb-db2ora.inc.php similarity index 57% rename from www/include/adodb5/drivers/adodb-db2ora.inc.php rename to www/include/adodb/drivers/adodb-db2ora.inc.php index 1261689d..d343a8ae 100644 --- a/www/include/adodb5/drivers/adodb-db2ora.inc.php +++ b/www/include/adodb/drivers/adodb-db2ora.inc.php @@ -1,21 +1,32 @@ . - Set tabs to 8. -*/ +/** + * Frontbase driver. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Frank M. Kromann + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -25,11 +35,7 @@ class ADODB_fbsql extends ADOConnection { var $fmtTimeStamp = "'Y-m-d H:i:s'"; var $hasLimit = false; - function __construct() - { - } - - function _insertid() + protected function _insertID($table = '', $column = '') { return fbsql_insert_id($this->_connectionID); } @@ -177,7 +183,7 @@ function __construct($queryID,$mode=false) default: $this->fetchMode = FBSQL_BOTH; break; } - return parent::__construct($queryID); + parent::__construct($queryID); } function _initrs() @@ -226,8 +232,15 @@ function MetaType($t,$len=-1,$fieldobj=false) $t = $fieldobj->type; $len = $fieldobj->max_length; } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + $len = -1; // fbsql max_length is not accurate - switch (strtoupper($t)) { + + switch ($t) { case 'CHARACTER': case 'CHARACTER VARYING': case 'BLOB': @@ -259,7 +272,7 @@ function MetaType($t,$len=-1,$fieldobj=false) if (!empty($fieldobj->primary_key)) return 'R'; else return 'I'; - default: return 'N'; + default: return ADODB_DEFAULT_METATYPE; } } diff --git a/www/include/adodb/drivers/adodb-firebird.inc.php b/www/include/adodb/drivers/adodb-firebird.inc.php new file mode 100644 index 00000000..135b72c6 --- /dev/null +++ b/www/include/adodb/drivers/adodb-firebird.inc.php @@ -0,0 +1,1316 @@ +setTransactionMode(''); + } + + /** + * Sets the isolation level of a transaction. + * + * The default behavior is a more practical IBASE_WAIT | IBASE_REC_VERSION | IBASE_COMMITTED + * instead of IBASE_DEFAULT + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:settransactionmode + * + * @param string $transaction_mode The transaction mode to set. + * + * @return void + */ + public function setTransactionMode($transaction_mode) + { + $this->_transmode = $transaction_mode; + + if (empty($transaction_mode)) { + $this->_transmode = IBASE_WAIT | IBASE_REC_VERSION | IBASE_COMMITTED; + } + + } + + /** + * Connect to a database. + * + * @todo add: parameter int $port, parameter string $socket + * + * @param string|null $argHostname (Optional) The host to connect to. + * @param string|null $argUsername (Optional) The username to connect as. + * @param string|null $argPassword (Optional) The password to connect with. + * @param string|null $argDatabasename (Optional) The name of the database to start in when connected. + * @param bool $persist (Optional) Whether or not to use a persistent connection. + * + * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension + * isn't currently loaded. + */ + public function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$persist=false) + { + if (!function_exists('fbird_pconnect')) + return null; + + if ($argDatabasename) + $argHostname .= ':'.$argDatabasename; + + $fn = ($persist) ? 'fbird_pconnect':'fbird_connect'; + + /* + * Now merge in the standard connection parameters setting + */ + foreach ($this->connectionParameters as $options) + { + foreach($options as $k=>$v) + { + switch($k){ + case 'role': + $this->role = $v; + break; + case 'dialect': + $this->dialect = $v; + break; + case 'buffers': + $this->buffers = $v; + } + } + } + + if ($this->role) + $this->_connectionID = $fn($argHostname,$argUsername,$argPassword, + $this->charSet,$this->buffers,$this->dialect,$this->role); + else + $this->_connectionID = $fn($argHostname,$argUsername,$argPassword, + $this->charSet,$this->buffers,$this->dialect); + + if ($this->dialect == 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html + $this->replaceQuote = ""; + } + if ($this->_connectionID === false) { + $this->_handleError(); + return false; + } + + ini_set("ibase.timestampformat", $this->fbird_timestampfmt); + ini_set("ibase.dateformat", $this->fbird_datefmt); + ini_set("ibase.timeformat", $this->fbird_timefmt); + + return true; + } + + /** + * Connect to a database with a persistent connection. + * + * @param string|null $argHostname The host to connect to. + * @param string|null $argUsername The username to connect as. + * @param string|null $argPassword The password to connect with. + * @param string|null $argDatabasename The name of the database to start in when connected. + * + * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension + * isn't currently loaded. + */ + function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,true); + } + + + public function metaPrimaryKeys($table,$owner_notused=false,$internalKey=false) + { + if ($internalKey) { + return array('RDB$DB_KEY'); + } + + $table = strtoupper($table); + + $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME + FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME + WHERE I.RDB$RELATION_NAME=\''.$table.'\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\' + ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION'; + + $a = $this->GetCol($sql,false,true); + if ($a && sizeof($a)>0) return $a; + return false; + } + + /** + * Get information about the current Firebird server. + * + * @return array + */ + public function serverInfo() + { + $arr['dialect'] = $this->dialect; + switch($arr['dialect']) { + case '': + case '1': + $s = 'Firebird Dialect 1'; + break; + case '2': + $s = 'Firebird Dialect 2'; + break; + default: + case '3': + $s = 'Firebird Dialect 3'; + break; + } + $arr['version'] = ADOConnection::_findvers($s); + $arr['description'] = $s; + return $arr; + } + + /** + * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans(). + * + * @return bool true if succeeded or false if database does not support transactions + */ + public function beginTrans() + { + if ($this->transOff) return true; + $this->transCnt += 1; + $this->autoCommit = false; + /* + * We manage the transaction mode via fbird_trans + */ + $this->_transactionID = fbird_trans( $this->_transmode, $this->_connectionID ); + return $this->_transactionID; + } + + + /** + * Commits a transaction. + * + * @param bool $ok false to rollback transaction, true to commit + * + * @return bool + */ + public function commitTrans($ok=true) + { + if (!$ok) { + return $this->RollbackTrans(); + } + if ($this->transOff) { + return true; + } + if ($this->transCnt) { + $this->transCnt -= 1; + } + $ret = false; + $this->autoCommit = true; + if ($this->_transactionID) { + $ret = fbird_commit($this->_transactionID); + } + $this->_transactionID = false; + return $ret; + } + + function _affectedrows() + { + return fbird_affected_rows($this->_transactionID ?: $this->_connectionID); + } + + /** + * Rollback a smart transaction. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rollbacktrans + * + * @return bool + */ + public function rollbackTrans() + { + if ($this->transOff) + return true; + if ($this->transCnt) + $this->transCnt -= 1; + + $ret = false; + $this->autoCommit = true; + + if ($this->_transactionID) { + $ret = fbird_rollback($this->_transactionID); + } + $this->_transactionID = false; + + return $ret; + } + + /** + * Get a list of indexes on the specified table. + * + * @param string $table The name of the table to get indexes for. + * @param bool $primary (Optional) Whether or not to include the primary key. + * @param bool $owner (Optional) Unused. + * + * @return array|bool An array of the indexes, or false if the query to get the indexes failed. + */ + public function metaIndexes($table, $primary = false, $owner = false) + { + // save old fetch mode + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + if ($this->fetchMode !== FALSE) { + $savem = $this->SetFetchMode(FALSE); + } + + $table = strtoupper($table); + $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '".$table."'"; + if (!$primary) { + $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'"; + } else { + $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'"; + } + // get index details + $rs = $this->execute($sql); + if (!is_object($rs)) { + // restore fetchmode + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + return false; + } + $indexes = array(); + while ($row = $rs->FetchRow()) { + + $index = trim($row[0]); + if (!isset($indexes[$index])) { + if (is_null($row[3])) { + $row[3] = 0; + } + $indexes[$index] = array( + 'unique' => ($row[3] == 1), + 'columns' => array() + ); + } + $sql = sprintf("SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '%s' ORDER BY RDB\$FIELD_POSITION ASC",$index); + $rs1 = $this->execute($sql); + while ($row1 = $rs1->FetchRow()) { + $indexes[$index]['columns'][$row1[2]] = trim($row1[1]); + } + } + + // restore fetchmode + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + + return $indexes; + } + + /** + * Lock a table row for a duration of a transaction. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rowlock + * @link https://firebirdsql.org/refdocs/langrefupd21-notes-withlock.html + * + * @param string $table The table(s) to lock rows for. + * @param string $where (Optional) The WHERE clause to use to determine which rows to lock. + * @param string $col (Optional) The columns to select. + * + * @return bool True if the locking SQL statement executed successfully, otherwise false. + */ + public function rowLock($table,$where,$col=false) + { + if ($this->transCnt==0) + $this->beginTrans(); + + if ($where) $where = ' where '.$where; + $rs = $this->execute("SELECT $col FROM $table $where FOR UPDATE WITH LOCK"); + return !empty($rs); + } + + /** + * Creates a sequence in the database. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:createsequence + * + * @param string $seqname The sequence name. + * @param int $startID The start id. + * + * @return ADORecordSet|bool A record set if executed successfully, otherwise false. + */ + public function createSequence($seqname='adodbseq', $startID = 1) + { + $sql = sprintf($this->_genSeqSQL,$seqname,$startID); + return $this->execute($sql); + } + + /** + * A portable method of creating sequence numbers. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:genid + * + * @param string $seqname (Optional) The name of the sequence to use. + * @param int $startID (Optional) The point to start at in the sequence. + * + * @return int + */ + public function genID($seqname='adodbseq',$startID=1) + { + $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE"); + $rs = @$this->Execute($getnext); + if (!$rs) { + $this->Execute("CREATE SEQUENCE $seqname START WITH $startID"); + $rs = $this->Execute($getnext); + } + if ($rs && !$rs->EOF) { + $this->genID = (integer) reset($rs->fields); + } + else { + $this->genID = 0; // false + } + + if ($rs) { + $rs->Close(); + } + + return $this->genID; + } + + function selectDB($dbName) + { + return false; + } + + function _handleError() + { + $this->_errorCode = fbird_errcode(); + $this->_errorMsg = fbird_errmsg(); + } + + + public function errorNo() + { + return (integer) $this->_errorCode; + } + + function errorMsg() + { + return $this->_errorMsg; + } + + /** + * Prepares an SQL statement and returns a handle to use. + * This is not used by bound parameters anymore + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:prepare + * @todo update this function to handle prepared statements correctly + * + * @param string $sql The SQL to prepare. + * + * @return bool|array The SQL that was provided and the prepared parameters, + * or false if the preparation fails + */ + public function prepare($sql) + { + $stmt = fbird_prepare($this->_connectionID,$sql); + if (!$stmt) + return false; + return array($sql,$stmt); + } + + /** + * Return the query id. + * + * @param string|array $sql + * @param array $iarr + * + * @return bool|object + */ + function _query($sql, $iarr = false) + { + if (!$this->isConnected()) { + return false; + } + + if (!$this->autoCommit && $this->_transactionID) { + $conn = $this->_transactionID; + $docommit = false; + } else { + $conn = $this->_connectionID; + $docommit = true; + } + + if (is_array($sql)) { + // Prepared statement + $fn = 'fbird_execute'; + $args = [$sql[1]]; + } else { + $fn = 'fbird_query'; + $args = [$conn, $sql]; + } + if (is_array($iarr)) { + $args = array_merge($args, $iarr); + } + $ret = call_user_func_array($fn, $args); + + if ($docommit && $ret === true) { + fbird_commit($this->_connectionID); + } + + $this->_handleError(); + return $ret; + } + + // returns true or false + function _close() + { + if (!$this->autoCommit) { + @fbird_rollback($this->_connectionID); + } + return @fbird_close($this->_connectionID); + } + + //OPN STUFF start + function _ConvertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3) + { + $fscale = abs($fscale); + $fld->max_length = $flen; + $fld->scale = null; + switch($ftype){ + case 7: + case 8: + if ($dialect3) { + switch($fsubtype){ + case 0: + $fld->type = ($ftype == 7 ? 'smallint' : 'integer'); + break; + case 1: + $fld->type = 'numeric'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + case 2: + $fld->type = 'decimal'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + } // switch + } else { + if ($fscale !=0) { + $fld->type = 'decimal'; + $fld->scale = $fscale; + $fld->max_length = ($ftype == 7 ? 4 : 9); + } else { + $fld->type = ($ftype == 7 ? 'smallint' : 'integer'); + } + } + break; + case 16: + if ($dialect3) { + switch($fsubtype){ + case 0: + $fld->type = 'decimal'; + $fld->max_length = 18; + $fld->scale = 0; + break; + case 1: + $fld->type = 'numeric'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + case 2: + $fld->type = 'decimal'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + } // switch + } + break; + case 10: + $fld->type = 'float'; + break; + case 14: + $fld->type = 'char'; + break; + case 27: + if ($fscale !=0) { + $fld->type = 'decimal'; + $fld->max_length = 15; + $fld->scale = 5; + } else { + $fld->type = 'double'; + } + break; + case 35: + if ($dialect3) { + $fld->type = 'timestamp'; + } else { + $fld->type = 'date'; + } + break; + case 12: + $fld->type = 'date'; + break; + case 13: + $fld->type = 'time'; + break; + case 37: + $fld->type = 'varchar'; + break; + case 40: + $fld->type = 'cstring'; + break; + case 261: + $fld->type = 'blob'; + $fld->max_length = -1; + break; + } // switch + } + //OPN STUFF end + + /** + * Return an array of information about a table's columns. + * + * @param string $table The name of the table to get the column info for. + * @param bool $normalize (Optional) Unused. + * + * @return ADOFieldObject[]|bool An array of info for each column, + * or false if it could not determine the info. + */ + public function metaColumns($table, $normalize = true) + { + + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + $rs = $this->execute(sprintf($this->metaColumnsSQL,strtoupper($table))); + + $ADODB_FETCH_MODE = $save; + + if ($rs === false) { + return false; + } + + $retarr = array(); + //OPN STUFF start + $dialect3 = $this->dialect == 3; + //OPN STUFF end + while (!$rs->EOF) { //print_r($rs->fields); + $fld = new ADOFieldObject(); + $fld->name = trim($rs->fields[0]); + //OPN STUFF start + //print_r($rs->fields); + $this->_ConvertFieldType( + $fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $dialect3); + if (isset($rs->fields[1]) && $rs->fields[1]) { + $fld->not_null = true; + } + if (isset($rs->fields[2])) { + + $fld->has_default = true; + $d = substr($rs->fields[2],strlen('default ')); + switch ($fld->type) { + case 'smallint': + case 'integer': + $fld->default_value = (int)$d; + break; + case 'char': + case 'blob': + case 'text': + case 'varchar': + $fld->default_value = (string)substr($d, 1, strlen($d) - 2); + break; + case 'double': + case 'float': + $fld->default_value = (float)$d; + break; + default: + $fld->default_value = $d; + break; + } + // case 35:$tt = 'TIMESTAMP'; break; + } + if ((isset($rs->fields[5])) && ($fld->type == 'blob')) { + $fld->sub_type = $rs->fields[5]; + } else { + $fld->sub_type = null; + } + //OPN STUFF end + if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld; + else $retarr[strtoupper($fld->name)] = $fld; + + $rs->MoveNext(); + } + $rs->Close(); + if ( empty($retarr)) + return false; + else return $retarr; + } + + /** + * Retrieves a list of tables based on given criteria + * + * @param string|bool $ttype (Optional) Table type = 'TABLE', 'VIEW' or false=both (default) + * @param string|bool $showSchema (Optional) schema name, false = current schema (default) + * @param string|bool $mask (Optional) filters the table by name + * + * @return array list of tables + */ + public function metaTables($ttype = false, $showSchema = false, $mask = false) + { + $save = $this->metaTablesSQL; + if (!$showSchema) { + $this->metaTablesSQL .= " WHERE (rdb\$relation_name NOT LIKE 'RDB\$%' AND rdb\$relation_name NOT LIKE 'MON\$%' AND rdb\$relation_name NOT LIKE 'SEC\$%')"; + } elseif (is_string($showSchema)) { + $this->metaTablesSQL .= $this->qstr($showSchema); + } + + if ($mask) { + $mask = $this->qstr($mask); + $this->metaTablesSQL .= " AND table_name LIKE $mask"; + } + $ret = ADOConnection::metaTables($ttype,$showSchema); + + $this->metaTablesSQL = $save; + return $ret; + } + + /** + * Encodes a blob, then assigns an id ready to be used + * + * @param string $blob The blob to be encoded + * + * @return bool success + */ + public function blobEncode( $blob ) + { + $blobid = fbird_blob_create( $this->_connectionID); + fbird_blob_add( $blobid, $blob ); + return fbird_blob_close( $blobid ); + } + + /** + * Manually decode a blob + * + * since we auto-decode all blob's since 2.42, + * BlobDecode should not do any transforms + * + * @param string $blob + * + * @return string the same blob + */ + public function blobDecode($blob) + { + return $blob; + } + + /** + * Auto function called on read of blob to decode + * + * @param string $blob Value to decode + * + * @return string Decoded blob + */ + public function _blobDecode($blob) + { + if ($blob === null) { + return ''; + } + + $blob_data = fbird_blob_info($this->_connectionID, $blob); + $blobId = fbird_blob_open($this->_connectionID, $blob); + + if ($blob_data[0] > $this->maxblobsize) { + $realBlob = fbird_blob_get($blobId, $this->maxblobsize); + while ($string = fbird_blob_get($blobId, 8192)) { + $realBlob .= $string; + } + } else { + $realBlob = fbird_blob_get($blobId, $blob_data[0]); + } + + fbird_blob_close($blobId); + return $realBlob; + } + + /** + * Insert blob data into a database column directly + * from file + * + * @param string $table table to insert + * @param string $column column to insert + * @param string $path physical file name + * @param string $where string to find unique record + * @param string $blobtype BLOB or CLOB + * + * @return bool success + */ + public function updateBlobFile($table,$column,$path,$where,$blobtype='BLOB') + { + $fd = fopen($path,'rb'); + if ($fd === false) + return false; + + $blob_id = fbird_blob_create($this->_connectionID); + + /* fill with data */ + + while ($val = fread($fd,32768)){ + fbird_blob_add($blob_id, $val); + } + + /* close and get $blob_id_str for inserting into table */ + $blob_id_str = fbird_blob_close($blob_id); + + fclose($fd); + return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false; + } + + /** + * Insert blob data into a database column + * + * @param string $table table to insert + * @param string $column column to insert + * @param string $val value to insert + * @param string $where string to find unique record + * @param string $blobtype BLOB or CLOB + * + * @return bool success + */ + public function updateBlob($table,$column,$val,$where,$blobtype='BLOB') + { + $blob_id = fbird_blob_create($this->_connectionID); + + // fbird_blob_add($blob_id, $val); + + // replacement that solves the problem by which only the first modulus 64K / + // of $val are stored at the blob field //////////////////////////////////// + // Thx Abel Berenstein aberenstein#afip.gov.ar + $len = strlen($val); + $chunk_size = 32768; + $tail_size = $len % $chunk_size; + $n_chunks = ($len - $tail_size) / $chunk_size; + + for ($n = 0; $n < $n_chunks; $n++) { + $start = $n * $chunk_size; + $data = substr($val, $start, $chunk_size); + fbird_blob_add($blob_id, $data); + } + + if ($tail_size) { + $start = $n_chunks * $chunk_size; + $data = substr($val, $start, $tail_size); + fbird_blob_add($blob_id, $data); + } + // end replacement ///////////////////////////////////////////////////////// + + $blob_id_str = fbird_blob_close($blob_id); + + return $this->execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false; + + } + + + /** + * Returns a portably-formatted date string from a timestamp database column. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:sqldate + * + * Firebird does not support an AM/PM format, so the A indicator always shows AM + * + * @param string $fmt The date format to use. + * @param string|bool $col (Optional) The table column to date format, or if false, use NOW(). + * + * @return string The SQL DATE_FORMAT() string, or empty if the provided date format was empty. + */ + public function sqlDate($fmt, $col=false) + { + if (!$col) + $col = 'CURRENT_TIMESTAMP'; + + $s = ''; + + $len = strlen($fmt); + for ($i=0; $i < $len; $i++) { + if ($s) $s .= '||'; + $ch = $fmt[$i]; + $choice = strtoupper($ch); + switch($choice) { + case 'Y': + $s .= "EXTRACT(YEAR FROM $col)"; + break; + case 'M': + $s .= "RIGHT('0' || TRIM(EXTRACT(MONTH FROM $col)),2)"; + break; + case 'W': + // The more accurate way of doing this is with a stored procedure + // See http://wiki.firebirdsql.org/wiki/index.php?page=DATE+Handling+Functions for details + $s .= "((EXTRACT(YEARDAY FROM $col) - EXTRACT(WEEKDAY FROM $col - 1) + 7) / 7)"; + break; + case 'Q': + $s .= "CAST(((EXTRACT(MONTH FROM $col)+2) / 3) AS INTEGER)"; + break; + case 'D': + $s .= "RIGHT('0' || TRIM(EXTRACT(DAY FROM $col)),2)"; + break; + case 'H': + $s .= "RIGHT('0' || TRIM(EXTRACT(HOUR FROM $col)),2)"; + break; + case 'I': + $s .= "RIGHT('0' || TRIM(EXTRACT(MINUTE FROM $col)),2)"; + break; + case 'S': + //$s .= "CAST((EXTRACT(SECOND FROM $col)) AS INTEGER)"; + $s .= "RIGHT('0' || TRIM(EXTRACT(SECOND FROM $col)),2)"; + break; + case 'A': + $s .= $this->qstr('AM'); + break; + default: + if ($ch == '\\') { + $i++; + $ch = substr($fmt,$i,1); + } + $s .= $this->qstr($ch); + break; + } + } + return $s; + } + + /** + * Creates a portable date offset field, for use in SQL statements. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:offsetdate + * + * @param float $dayFraction A day in floating point + * @param string|bool $date (Optional) The date to offset. If false, uses CURDATE() + * + * @return string + */ + public function offsetDate($dayFraction, $date=false) + { + if (!$date) + $date = $this->sysTimeStamp; + + $fraction = $dayFraction * 24 * 3600; + return sprintf("DATEADD (second, %s, %s) FROM RDB\$DATABASE",$fraction,$date); + } + + + // Note that Interbase 6.5 uses this ROWS instead - don't you love forking wars! + // SELECT col1, col2 FROM table ROWS 5 -- get 5 rows + // SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2 + /** + * Executes a provided SQL statement and returns a handle to the result, with the ability to supply a starting + * offset and record count. + * + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:selectlimit + * + * @param string $sql The SQL to execute. + * @param int $nrows (Optional) The limit for the number of records you want returned. By default, all results. + * @param int $offset (Optional) The offset to use when selecting the results. By default, no offset. + * @param array|bool $inputarr (Optional) Any parameter values required by the SQL statement, or false if none. + * @param int $secs2cache (Optional) If greater than 0, perform a cached execute. By default, normal execution. + * + * @return ADORecordSet|false The query results, or false if the query failed to execute. + */ + public function selectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs2cache=0) + { + $nrows = (integer) $nrows; + $offset = (integer) $offset; + $str = 'SELECT '; + if ($nrows >= 0) $str .= "FIRST $nrows "; + $str .=($offset>=0) ? "SKIP $offset " : ''; + + $sql = preg_replace('/^[ \t]*select/i',$str,$sql); + if ($secs2cache) + $rs = $this->cacheExecute($secs2cache,$sql,$inputarr); + else + $rs = $this->execute($sql,$inputarr); + + return $rs; + } + +} + +/** + * Class ADORecordset_firebird + */ +class ADORecordset_firebird extends ADORecordSet +{ + var $databaseType = "firebird"; + var $bind = false; + + /** + * @var ADOFieldObject[] Holds a cached version of the metadata + */ + private $fieldObjects = false; + + /** + * @var bool Flags if we have retrieved the metadata + */ + private $fieldObjectsRetrieved = false; + + /** + * @var array Cross-reference the objects by name for easy access + */ + private $fieldObjectsIndex = array(); + + /** + * @var bool Flag to indicate if the result has a blob + */ + private $fieldObjectsHaveBlob = false; + + function __construct($id, $mode = false) + { + global $ADODB_FETCH_MODE; + + $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode; + parent::__construct($id); + } + + + /** + * Returns: an object containing field information. + * + * Get column information in the Recordset object. fetchField() + * can be used in order to obtain information about fields in a + * certain query result. If the field offset isn't specified, + * the next field that wasn't yet retrieved by fetchField() + * is retrieved. + * + * $param int $fieldOffset (optional default=-1 for all + * @return mixed an ADOFieldObject, or array of objects + */ + private function _fetchField($fieldOffset = -1) + { + if ($this->fieldObjectsRetrieved) { + if ($this->fieldObjects) { + // Already got the information + if ($fieldOffset == -1) { + return $this->fieldObjects; + } else { + return $this->fieldObjects[$fieldOffset]; + } + } else { + // No metadata available + return false; + } + } + + // Populate the field objects cache + $this->fieldObjectsRetrieved = true; + $this->fieldObjectsHaveBlob = false; + $this->_numOfFields = fbird_num_fields($this->_queryID); + for ($fieldIndex = 0; $fieldIndex < $this->_numOfFields; $fieldIndex++) { + $fld = new ADOFieldObject; + $ibf = fbird_field_info($this->_queryID, $fieldIndex); + + $name = empty($ibf['alias']) ? $ibf['name'] : $ibf['alias']; + + switch (ADODB_ASSOC_CASE) { + case ADODB_ASSOC_CASE_UPPER: + $fld->name = strtoupper($name); + break; + case ADODB_ASSOC_CASE_LOWER: + $fld->name = strtolower($name); + break; + case ADODB_ASSOC_CASE_NATIVE: + default: + $fld->name = $name; + break; + } + + $fld->type = $ibf['type']; + $fld->max_length = $ibf['length']; + + // This needs to be populated from the metadata + $fld->not_null = false; + $fld->has_default = false; + $fld->default_value = 'null'; + + $this->fieldObjects[$fieldIndex] = $fld; + $this->fieldObjectsIndex[$fld->name] = $fieldIndex; + + if ($fld->type == 'BLOB') { + $this->fieldObjectsHaveBlob = true; + } + } + + if ($fieldOffset == -1) { + return $this->fieldObjects; + } + + return $this->fieldObjects[$fieldOffset]; + } + + /** + * Fetchfield copies the oracle method, it loads the field information + * into the _fieldobjs array once, to save multiple calls to the + * fbird_ function + * + * @param int $fieldOffset (optional) + * + * @return adoFieldObject|false + */ + public function fetchField($fieldOffset = -1) + { + if ($fieldOffset == -1) { + return $this->fieldObjects; + } + + return $this->fieldObjects[$fieldOffset]; + } + + function _initrs() + { + $this->_numOfRows = -1; + + /* + * Retrieve all of the column information first. We copy + * this method from oracle + */ + $this->_fetchField(); + + } + + function _seek($row) + { + return false; + } + + public function _fetch() + { + // Case conversion function for use in Closure defined below + $localFnCaseConv = null; + + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + // Handle either associative or fetch both + $localNumeric = false; + + $f = @fbird_fetch_assoc($this->_queryID); + if (is_array($f)) { + // Optimally do the case_upper or case_lower + if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) { + $f = array_change_key_case($f, CASE_LOWER); + $localFnCaseConv = 'strtolower'; + } elseif (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_UPPER) { + $f = array_change_key_case($f, CASE_UPPER); + $localFnCaseConv = 'strtoupper'; + } + } + } else { + // Numeric fetch mode + $localNumeric = true; + $f = @fbird_fetch_row($this->_queryID); + } + + if ($f === false) { + $this->fields = false; + return false; + } + + // OPN stuff start - optimized + // fix missing nulls and decode blobs automatically + global $ADODB_ANSI_PADDING_OFF; + $rtrim = !empty($ADODB_ANSI_PADDING_OFF); + + // For optimal performance, only process if there is a possibility of something to do + if ($this->fieldObjectsHaveBlob || $rtrim) { + $localFieldObjects = $this->fieldObjects; + $localFieldObjectIndex = $this->fieldObjectsIndex; + /** @var ADODB_firebird $localConnection */ + $localConnection = &$this->connection; + + /** + * Closure for an efficient method of iterating over the elements. + * @param mixed $value + * @param string|int $key + * @return void + */ + $rowTransform = function ($value, $key) use ( + &$f, + $rtrim, + $localFieldObjects, + $localConnection, + $localNumeric, + $localFnCaseConv, + $localFieldObjectIndex + ) { + if ($localNumeric) { + $localKey = $key; + } else { + // Cross-reference the associative key back to numeric + // with appropriate case conversion + $index = $localFnCaseConv ? $localFnCaseConv($key) : $key; + $localKey = $localFieldObjectIndex[$index]; + } + + // As we iterate the elements check for blobs and padding + if ($localFieldObjects[$localKey]->type == 'BLOB') { + $f[$key] = $localConnection->_BlobDecode($value); + } else { + if ($rtrim && is_string($value)) { + $f[$key] = rtrim($value); + } + } + + }; + + // Walk the array, applying the above closure + array_walk($f, $rowTransform); + } + + if (!$localNumeric && $this->fetchMode & ADODB_FETCH_NUM) { + // Creates a fetch both + $fNum = array_values($f); + $f = array_merge($f, $fNum); + } + + $this->fields = $f; + + return true; + } + + /** + * Get the value of a field in the current row by column name. + * Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM. + * + * @param string $colname is the field to access + * + * @return mixed the value of $colname column + */ + public function fields($colname) + { + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + return $this->fields[$colname]; + } + + if (!$this->bind) { + // fieldsObjectIndex populated by the recordset load + $this->bind = array_change_key_case($this->fieldObjectsIndex, CASE_UPPER); + } + + return $this->fields[$this->bind[strtoupper($colname)]]; + } + + + function _close() + { + return @fbird_free_result($this->_queryID); + } + + public function metaType($t, $len = -1, $fieldObj = false) + { + if (is_object($t)) { + $fieldObj = $t; + $t = $fieldObj->type; + $len = $fieldObj->max_length; + } + + $t = strtoupper($t); + + if (array_key_exists($t, $this->connection->customActualTypes)) { + return $this->connection->customActualTypes[$t]; + } + + switch ($t) { + case 'CHAR': + return 'C'; + + case 'TEXT': + case 'VARCHAR': + case 'VARYING': + if ($len <= $this->blobSize) { + return 'C'; + } + return 'X'; + case 'BLOB': + return 'B'; + + case 'TIMESTAMP': + case 'DATE': + return 'D'; + case 'TIME': + return 'T'; + //case 'T': return 'T'; + + //case 'L': return 'L'; + case 'INT': + case 'SHORT': + case 'INTEGER': + return 'I'; + default: + return ADODB_DEFAULT_METATYPE; + } + } + +} + diff --git a/www/include/adodb5/drivers/adodb-ibase.inc.php b/www/include/adodb/drivers/adodb-ibase.inc.php similarity index 86% rename from www/include/adodb5/drivers/adodb-ibase.inc.php rename to www/include/adodb/drivers/adodb-ibase.inc.php index c4f0cbdb..81ab29b5 100644 --- a/www/include/adodb5/drivers/adodb-ibase.inc.php +++ b/www/include/adodb/drivers/adodb-ibase.inc.php @@ -1,29 +1,25 @@ - changed transaction handling and added experimental blob stuff - - Docs to interbase at the website - http://www.synectics.co.za/php3/tutorial/IB_PHP3_API.html - - To use gen_id(), see - http://www.volny.cz/iprenosil/interbase/ip_ib_code.htm#_code_creategen - - $rs = $conn->Execute('select gen_id(adodb,1) from rdb$database'); - $id = $rs->fields[0]; - $conn->Execute("insert into table (id, col1,...) values ($id, $val1,...)"); -*/ +/** + * Interbase driver. + * + * Requires interbase client. Works on Windows and Unix. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -350,46 +346,26 @@ function _query($sql,$iarr=false) $fn = 'ibase_execute'; $sql = $sql[1]; if (is_array($iarr)) { - if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4 - if ( !isset($iarr[0]) ) $iarr[0] = ''; // PHP5 compat hack - $fnarr = array_merge( array($sql) , $iarr); - $ret = call_user_func_array($fn,$fnarr); - } else { - switch(sizeof($iarr)) { - case 1: $ret = $fn($sql,$iarr[0]); break; - case 2: $ret = $fn($sql,$iarr[0],$iarr[1]); break; - case 3: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2]); break; - case 4: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break; - case 5: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break; - case 6: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break; - case 7: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break; - default: ADOConnection::outp( "Too many parameters to ibase query $sql"); - case 8: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break; - } - } - } else $ret = $fn($sql); + if ( !isset($iarr[0]) ) + $iarr[0] = ''; // PHP5 compat hack + $fnarr = array_merge( array($sql) , $iarr); + $ret = call_user_func_array($fn,$fnarr); + } + else { + $ret = $fn($sql); + } } else { $fn = 'ibase_query'; if (is_array($iarr)) { - if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4 - if (sizeof($iarr) == 0) $iarr[0] = ''; // PHP5 compat hack - $fnarr = array_merge( array($conn,$sql) , $iarr); - $ret = call_user_func_array($fn,$fnarr); - } else { - switch(sizeof($iarr)) { - case 1: $ret = $fn($conn,$sql,$iarr[0]); break; - case 2: $ret = $fn($conn,$sql,$iarr[0],$iarr[1]); break; - case 3: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2]); break; - case 4: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break; - case 5: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break; - case 6: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break; - case 7: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break; - default: ADOConnection::outp( "Too many parameters to ibase query $sql"); - case 8: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break; - } - } - } else $ret = $fn($conn,$sql); + if (sizeof($iarr) == 0) + $iarr[0] = ''; // PHP5 compat hack + $fnarr = array_merge( array($conn,$sql) , $iarr); + $ret = call_user_func_array($fn,$fnarr); + } + else { + $ret = $fn($conn, $sql); + } } if ($docommit && $ret === true) { ibase_commit($this->_connectionID); @@ -601,14 +577,8 @@ function _BlobDecode_old( $blob ) function _BlobDecode( $blob ) { - if (ADODB_PHPVER >= 0x5000) { - $blob_data = ibase_blob_info($this->_connectionID, $blob ); - $blobid = ibase_blob_open($this->_connectionID, $blob ); - } else { - - $blob_data = ibase_blob_info( $blob ); - $blobid = ibase_blob_open( $blob ); - } + $blob_data = ibase_blob_info($this->_connectionID, $blob ); + $blobid = ibase_blob_open($this->_connectionID, $blob ); if( $blob_data[0] > $this->maxblobsize ) { @@ -890,7 +860,14 @@ function MetaType($t,$len=-1,$fieldobj=false) $t = $fieldobj->type; $len = $fieldobj->max_length; } - switch (strtoupper($t)) { + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + + switch ($t) { + case 'CHAR': return 'C'; @@ -911,7 +888,7 @@ function MetaType($t,$len=-1,$fieldobj=false) case 'INT': case 'SHORT': case 'INTEGER': return 'I'; - default: return 'N'; + default: return ADODB_DEFAULT_METATYPE; } } diff --git a/www/include/adodb/drivers/adodb-informix.inc.php b/www/include/adodb/drivers/adodb-informix.inc.php new file mode 100644 index 00000000..8e99137c --- /dev/null +++ b/www/include/adodb/drivers/adodb-informix.inc.php @@ -0,0 +1,44 @@ + - -*/ +/** + * Informix driver. + * + * @deprecated + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Mitchell T. Young + * @author Samuel Carriere + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -83,7 +90,7 @@ function ServerInfo() - function _insertid() + protected function _insertID($table = '', $column = '') { $sqlca =ifx_getsqlca($this->lastQuery); return @$sqlca["sqlerrd1"]; @@ -246,12 +253,12 @@ function MetaColumns($table, $normalize=true) return $false; } - function xMetaColumns($table) - { + function xMetaColumns($table) + { return ADOConnection::MetaColumns($table,false); - } + } - function MetaForeignKeys($table, $owner=false, $upper=false) //!Eos + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { $sql = " select tr.tabname,updrule,delrule, @@ -403,7 +410,7 @@ function __construct($id,$mode=false) $mode = $ADODB_FETCH_MODE; } $this->fetchMode = $mode; - return parent::__construct($id); + parent::__construct($id); } @@ -501,7 +508,7 @@ function _close() } /** !Eos -* Auxiliar function to Parse coltype,collength. Used by Metacolumns +* Auxiliary function to Parse coltype,collength. Used by Metacolumns * return: array ($mtype,$length,$precision,$nullable) (similar to ifx_fieldpropierties) */ function ifx_props($coltype,$collength){ diff --git a/www/include/adodb5/drivers/adodb-ldap.inc.php b/www/include/adodb/drivers/adodb-ldap.inc.php similarity index 91% rename from www/include/adodb5/drivers/adodb-ldap.inc.php rename to www/include/adodb/drivers/adodb-ldap.inc.php index 633705e0..323b3585 100644 --- a/www/include/adodb5/drivers/adodb-ldap.inc.php +++ b/www/include/adodb/drivers/adodb-ldap.inc.php @@ -1,20 +1,26 @@ + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -45,10 +51,6 @@ class ADODB_ldap extends ADOConnection { # error on binding, eg. "Binding: invalid credentials" var $_bind_errmsg = "Binding: %s"; - function __construct() - { - } - // returns true or false function _connect( $host, $username, $password, $ldapbase) @@ -331,7 +333,7 @@ function _initrs() /* Return whole recordset as a multi-dimensional associative array */ - function GetAssoc($force_array = false, $first2cols = false) + function GetAssoc($force_array = false, $first2cols = false, $fetchMode = -1) { $records = $this->_numOfRows; $results = array(); diff --git a/www/include/adodb5/drivers/adodb-mssql.inc.php b/www/include/adodb/drivers/adodb-mssql.inc.php similarity index 73% rename from www/include/adodb5/drivers/adodb-mssql.inc.php rename to www/include/adodb/drivers/adodb-mssql.inc.php index 068dffce..8fb92249 100644 --- a/www/include/adodb5/drivers/adodb-mssql.inc.php +++ b/www/include/adodb/drivers/adodb-mssql.inc.php @@ -1,21 +1,25 @@ = 0x4300) { -// docs say 4.2.0, but testing shows only since 4.3.0 does it work! - ini_set('mssql.datetimeconvert',0); -} else { -global $ADODB_mssql_mths; // array, months must be upper-case - - - $ADODB_mssql_date_order = 'mdy'; - $ADODB_mssql_mths = array( - 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6, - 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12); -} - -//--------------------------------------------------------------------------- -// Call this to autoset $ADODB_mssql_date_order at the beginning of your code, -// just after you connect to the database. Supports mdy and dmy only. -// Not required for PHP 4.2.0 and above. -function AutoDetect_MSSQL_Date_Order($conn) -{ -global $ADODB_mssql_date_order; - $adate = $conn->GetOne('select getdate()'); - if ($adate) { - $anum = (int) $adate; - if ($anum > 0) { - if ($anum > 31) { - //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently"); - } else - $ADODB_mssql_date_order = 'dmy'; - } else - $ADODB_mssql_date_order = 'mdy'; - } -} +ini_set('mssql.datetimeconvert',0); class ADODB_mssql extends ADOConnection { var $databaseType = "mssql"; @@ -94,7 +66,6 @@ class ADODB_mssql extends ADOConnection { var $hasGenID = true; var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)'; var $sysTimeStamp = 'GetDate()'; - var $_has_mssql_init; var $maxParameterLen = 4000; var $arrayClass = 'ADORecordSet_array_mssql'; var $uniqueSort = true; @@ -107,11 +78,6 @@ class ADODB_mssql extends ADOConnection { var $_bindInputArray = true; var $forceNewConnect = false; - function __construct() - { - $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0); - } - function ServerInfo() { global $ADODB_FETCH_MODE; @@ -148,16 +114,16 @@ function IfNull( $field, $ifNull ) return " ISNULL($field, $ifNull) "; // if MS SQL Server } - function _insertid() + protected function _insertID($table = '', $column = '') { // SCOPE_IDENTITY() // Returns the last IDENTITY value inserted into an IDENTITY column in // the same scope. A scope is a module -- a stored procedure, trigger, // function, or batch. Thus, two statements are in the same scope if // they are in the same stored procedure, function, or batch. - if ($this->lastInsID !== false) { - return $this->lastInsID; // InsID from sp_executesql call - } else { + if ($this->lastInsID !== false) { + return $this->lastInsID; // InsID from sp_executesql call + } else { return $this->GetOne($this->identitySQL); } } @@ -165,37 +131,22 @@ function _insertid() /** - * Correctly quotes a string so that all strings are escaped. We prefix and append - * to the string single-quotes. - * An example is $db->qstr("Don't bother",magic_quotes_runtime()); - * - * @param s the string to quote - * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). - * This undoes the stupidity of magic quotes for GPC. - * - * @return quoted string to be sent back to database - */ - function qstr($s,$magic_quotes=false) + * Correctly quotes a string so that all strings are escaped. + * We prefix and append to the string single-quotes. + * An example is $db->qstr("Don't bother"); + * + * @param string $s The string to quote + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * + * @return string Quoted string to be sent back to database + * + * @noinspection PhpUnusedParameterInspection + */ + function qStr($s, $magic_quotes=false) { - if (!$magic_quotes) { - return "'".str_replace("'",$this->replaceQuote,$s)."'"; - } - - // undo magic quotes for " unless sybase is on - $sybase = ini_get('magic_quotes_sybase'); - if (!$sybase) { - $s = str_replace('\\"','"',$s); - if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything - return "'$s'"; - else {// change \' to '' for sybase/mssql - $s = str_replace('\\\\','\\',$s); - return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; - } - } else { - return "'".$s."'"; - } + return "'" . str_replace("'", $this->replaceQuote, $s) . "'"; } -// moodle change end - see readme_moodle.txt function _affectedrows() { @@ -245,6 +196,8 @@ function GenID($seq='adodbseq',$start=1) function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; if ($nrows > 0 && $offset <= 0) { $sql = preg_replace( '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql); @@ -307,7 +260,9 @@ function SQLDate($fmt, $col=false) case 'A': $s .= "substring(convert(char(19),$col,0),18,2)"; break; - + case 'l': + $s .= "datename(dw,$col)"; + break; default: if ($ch == '\\') { $i++; @@ -325,8 +280,8 @@ function BeginTrans() { if ($this->transOff) return true; $this->transCnt += 1; - $ok = $this->Execute('BEGIN TRAN'); - return $ok; + $ok = $this->Execute('BEGIN TRAN'); + return $ok; } function CommitTrans($ok=true) @@ -449,32 +404,32 @@ function MetaIndexes($table,$primary=false, $owner=false) global $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== FALSE) { + $savem = $this->SetFetchMode(FALSE); + } - $rs = $this->Execute($sql); - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; + $rs = $this->Execute($sql); + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; - if (!is_object($rs)) { - return FALSE; - } + if (!is_object($rs)) { + return FALSE; + } $indexes = array(); while ($row = $rs->FetchRow()) { if ($primary && !$row[5]) continue; - $indexes[$row[0]]['unique'] = $row[6]; - $indexes[$row[0]]['columns'][] = $row[1]; - } - return $indexes; + $indexes[$row[0]]['unique'] = $row[6]; + $indexes[$row[0]]['columns'][] = $row[1]; + } + return $indexes; } - function MetaForeignKeys($table, $owner=false, $upper=false) + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { global $ADODB_FETCH_MODE; @@ -486,7 +441,7 @@ function MetaForeignKeys($table, $owner=false, $upper=false) "select object_name(constid) as constraint_name, col_name(fkeyid, fkey) as column_name, object_name(rkeyid) as referenced_table_name, - col_name(rkeyid, rkey) as referenced_column_name + col_name(rkeyid, rkey) as referenced_column_name from sysforeignkeys where upper(object_name(fkeyid)) = $table order by constraint_name, referenced_table_name, keyno"; @@ -507,7 +462,11 @@ function MetaForeignKeys($table, $owner=false, $upper=false) foreach($arr as $k => $v) { foreach($v as $a => $b) { if ($upper) $a = strtoupper($a); - $arr2[$a] = $b; + if (is_array($arr2[$a])) { // a previous foreign key was define for this reference table, we merge the new one + $arr2[$a] = array_merge($arr2[$a], $b); + } else { + $arr2[$a] = $b; + } } } return $arr2; @@ -517,22 +476,24 @@ function MetaForeignKeys($table, $owner=false, $upper=false) function MetaDatabases() { if(@mssql_select_db("master")) { - $qry=$this->metaDatabasesSQL; - if($rs=@mssql_query($qry,$this->_connectionID)){ - $tmpAr=$ar=array(); - while($tmpAr=@mssql_fetch_row($rs)) - $ar[]=$tmpAr[0]; - @mssql_select_db($this->database); - if(sizeof($ar)) - return($ar); - else - return(false); - } else { - @mssql_select_db($this->database); - return(false); - } - } - return(false); + $qry = $this->metaDatabasesSQL; + if($rs = @mssql_query($qry,$this->_connectionID)) { + $tmpAr = $ar = array(); + while($tmpAr = @mssql_fetch_row($rs)) { + $ar[]=$tmpAr[0]; + } + @mssql_select_db($this->database); + if(sizeof($ar)) { + return($ar); + } else { + return(false); + } + } else { + @mssql_select_db($this->database); + return(false); + } + } + return(false); } // "Stein-Aksel Basma" @@ -605,14 +566,18 @@ function ErrorNo() if (!$id) return false; $arr = mssql_fetch_array($id); @mssql_free_result($id); - if (is_array($arr)) return $arr[0]; - else return -1; + if (is_array($arr)) { + return $arr[0]; + } else { + return -1; + } } // returns true or false, newconnect supported since php 5.1.0. function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$newconnect=false) { if (!function_exists('mssql_pconnect')) return null; + if (!empty($this->port)) $argHostname .= ":".$this->port; $this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword,$newconnect); if ($this->_connectionID === false) return false; if ($argDatabasename) return $this->SelectDB($argDatabasename); @@ -624,6 +589,7 @@ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$ne function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) { if (!function_exists('mssql_pconnect')) return null; + if (!empty($this->port)) $argHostname .= ":".$this->port; $this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword); if ($this->_connectionID === false) return false; @@ -637,9 +603,9 @@ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) } function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { + { return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true); - } + } function Prepare($sql) { @@ -654,38 +620,39 @@ function Prepare($sql) function PrepareSP($sql,$param=true) { - if (!$this->_has_mssql_init) { - ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0"); - return $sql; - } $stmt = mssql_init($sql,$this->_connectionID); if (!$stmt) return $sql; return array($sql,$stmt); } // returns concatenated string - // MSSQL requires integers to be cast as strings - // automatically cast every datatype to VARCHAR(255) - // @author David Rogers (introspectshun) - function Concat() - { - $s = ""; - $arr = func_get_args(); - - // Split single record on commas, if possible - if (sizeof($arr) == 1) { - foreach ($arr as $arg) { - $args = explode(',', $arg); - } - $arr = $args; - } - - array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";')); - $s = implode('+',$arr); - if (sizeof($arr) > 0) return "$s"; + // MSSQL requires integers to be cast as strings + // automatically cast every datatype to VARCHAR(255) + // @author David Rogers (introspectshun) + function Concat() + { + $s = ""; + $arr = func_get_args(); + + // Split single record on commas, if possible + if (sizeof($arr) == 1) { + foreach ($arr as $arg) { + $args = explode(',', $arg); + } + $arr = $args; + } + + array_walk( + $arr, + function(&$value, $key) { + $value = "CAST(" . $value . " AS VARCHAR(255))"; + } + ); + $s = implode('+',$arr); + if (sizeof($arr) > 0) return "$s"; return ''; - } + } /* Usage: @@ -707,11 +674,6 @@ function Concat() */ function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false) { - if (!$this->_has_mssql_init) { - ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0"); - return false; - } - $isNull = is_null($var); // php 4.0.4 and above... if ($type === false) @@ -721,7 +683,7 @@ function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=fa case 'double': $type = SQLFLT8; break; case 'integer': $type = SQLINT4; break; case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0 - } + } if ($this->debug) { $prefix = ($isOutput) ? 'Out' : 'In'; @@ -729,7 +691,7 @@ function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=fa ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);"); } /* - See http://phplens.com/lens/lensforum/msgs.php?id=7231 + See PHPLens Issue No: 7231 RETVAL is HARD CODED into php_mssql extension: The return value (a long integer value) is treated like a special OUTPUT parameter, @@ -773,11 +735,11 @@ function _query($sql,$inputarr=false) # bind input params with sp_executesql: # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm # works only with sql server 7 and newer - $getIdentity = false; - if (!is_array($sql) && preg_match('/^\\s*insert/i', $sql)) { - $getIdentity = true; - $sql .= (preg_match('/;\\s*$/i', $sql) ? ' ' : '; ') . $this->identitySQL; - } + $getIdentity = false; + if (!is_array($sql) && preg_match('/^\\s*insert/i', $sql)) { + $getIdentity = true; + $sql .= (preg_match('/;\\s*$/i', $sql) ? ' ' : '; ') . $this->identitySQL; + } if (!is_array($sql)) $sql = $this->Prepare($sql); $params = ''; $decl = ''; @@ -798,7 +760,16 @@ function _query($sql,$inputarr=false) $decl .= "@P$i NVARCHAR($len)"; } - $params .= "@P$i=N". (strncmp($v,"'",1)==0? $v : $this->qstr($v)); + if(substr($v,0,1) == "'" && substr($v,-1,1) == "'") + /* + * String is already fully quoted + */ + $inputVar = $v; + else + $inputVar = $db->this($v); + + $params .= "@P$i=N" . $inputVar; + } else if (is_integer($v)) { $decl .= "@P$i INT"; $params .= "@P$i=".$v; @@ -817,20 +788,20 @@ function _query($sql,$inputarr=false) $decl = $this->qstr($decl); if ($this->debug) ADOConnection::outp("sp_executesql N{$sql[1]},N$decl,$params"); $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params", $this->_connectionID); - if ($getIdentity) { - $arr = @mssql_fetch_row($rez); - $this->lastInsID = isset($arr[0]) ? $arr[0] : false; - @mssql_data_seek($rez, 0); - } + if ($getIdentity) { + $arr = @mssql_fetch_row($rez); + $this->lastInsID = isset($arr[0]) ? $arr[0] : false; + @mssql_data_seek($rez, 0); + } } else if (is_array($sql)) { # PrepareSP() $rez = mssql_execute($sql[1]); - $this->lastInsID = false; + $this->lastInsID = false; } else { $rez = mssql_query($sql,$this->_connectionID); - $this->lastInsID = false; + $this->lastInsID = false; } return $rez; } @@ -838,33 +809,54 @@ function _query($sql,$inputarr=false) // returns true or false function _close() { - if ($this->transCnt) $this->RollbackTrans(); - $rez = @mssql_close($this->_connectionID); + if ($this->transCnt) { + $this->RollbackTrans(); + } + if($this->_connectionID) { + $rez = mssql_close($this->_connectionID); + } $this->_connectionID = false; return $rez; } - // mssql uses a default date like Dec 30 2000 12:00AM - static function UnixDate($v) - { - return ADORecordSet_array_mssql::UnixDate($v); - } - static function UnixTimeStamp($v) + + /** + * Returns a substring of a varchar type field + * + * The SQL server version varies because the length is mandatory, so + * we append a reasonable string length + * + * @param string $fld The field to sub-string + * @param int $start The start point + * @param int $length An optional length + * + * @return The SQL text + */ + function substr($fld,$start,$length=0) { - return ADORecordSet_array_mssql::UnixTimeStamp($v); + if ($length == 0) + /* + * The length available to varchar is 2GB, but that makes no + * sense in a substring, so I'm going to arbitrarily limit + * the length to 1K, but you could change it if you want + */ + $length = 1024; + + $text = "SUBSTRING($fld,$start,$length)"; + return $text; } } /*-------------------------------------------------------------------------------------- - Class Name: Recordset + Class Name: Recordset --------------------------------------------------------------------------------------*/ class ADORecordset_mssql extends ADORecordSet { var $databaseType = "mssql"; var $canSeek = true; - var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083 + var $hasFetchAssoc; // see PHPLens Issue No: 6083 // _mths works only in non-localised system function __construct($id,$mode=false) @@ -878,7 +870,7 @@ function __construct($id,$mode=false) } $this->fetchMode = $mode; - return parent::__construct($id,$mode); + return parent::__construct($id); } @@ -914,7 +906,7 @@ function Fields($colname) } } - return $this->fields[$this->bind[strtoupper($colname)]]; + return $this->fields[$this->bind[strtoupper($colname)]]; } /* Returns: an object containing field information. @@ -954,7 +946,7 @@ function MoveNext() } else { if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later - $this->fields = @mssql_fetch_assoc($this->_queryID); + $this->fields = @mssql_fetch_assoc($this->_queryID); } else { $flds = @mssql_fetch_array($this->_queryID); if (is_array($flds)) { @@ -1011,9 +1003,9 @@ function _fetch($ignore_fields=false) $this->fields = @mssql_fetch_assoc($this->_queryID); else { $this->fields = @mssql_fetch_array($this->_queryID); - if (@is_array($$this->fields)) { + if (@is_array($this->fields)) { $fassoc = array(); - foreach($$this->fields as $k => $v) { + foreach($this->fields as $k => $v) { if (is_integer($k)) continue; $fassoc[$k] = $v; } @@ -1059,108 +1051,43 @@ function _close() return true; } - // mssql uses a default date like Dec 30 2000 12:00AM - static function UnixDate($v) + /** + * Returns the maximum size of a MetaType C field. Because of the + * database design, SQL Server places no limits on the size of data inserted + * Although the actual limit is 2^31-1 bytes. + * + * @return int + */ + function charMax() { - return ADORecordSet_array_mssql::UnixDate($v); + return ADODB_STRINGMAX_NOLIMIT; } - static function UnixTimeStamp($v) + /** + * Returns the maximum size of a MetaType X field. Because of the + * database design, SQL Server places no limits on the size of data inserted + * Although the actual limit is 2^31-1 bytes. + * + * @return int + */ + function textMax() { - return ADORecordSet_array_mssql::UnixTimeStamp($v); + return ADODB_STRINGMAX_NOLIMIT; } } -class ADORecordSet_array_mssql extends ADORecordSet_array { - function __construct($id=-1,$mode=false) - { - parent::__construct($id,$mode); - } - - // mssql uses a default date like Dec 30 2000 12:00AM - static function UnixDate($v) - { - - if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v); - - global $ADODB_mssql_mths,$ADODB_mssql_date_order; - - //Dec 30 2000 12:00AM - if ($ADODB_mssql_date_order == 'dmy') { - if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) { - return parent::UnixDate($v); - } - if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; - - $theday = $rr[1]; - $themth = substr(strtoupper($rr[2]),0,3); - } else { - if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) { - return parent::UnixDate($v); - } - if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; - - $theday = $rr[2]; - $themth = substr(strtoupper($rr[1]),0,3); - } - $themth = $ADODB_mssql_mths[$themth]; - if ($themth <= 0) return false; - // h-m-s-MM-DD-YY - return mktime(0,0,0,$themth,$theday,$rr[3]); - } - - static function UnixTimeStamp($v) - { - - if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v); - - global $ADODB_mssql_mths,$ADODB_mssql_date_order; - - //Dec 30 2000 12:00AM - if ($ADODB_mssql_date_order == 'dmy') { - if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|" - ,$v, $rr)) return parent::UnixTimeStamp($v); - if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; - - $theday = $rr[1]; - $themth = substr(strtoupper($rr[2]),0,3); - } else { - if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|" - ,$v, $rr)) return parent::UnixTimeStamp($v); - if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0; - - $theday = $rr[2]; - $themth = substr(strtoupper($rr[1]),0,3); - } - - $themth = $ADODB_mssql_mths[$themth]; - if ($themth <= 0) return false; - - switch (strtoupper($rr[6])) { - case 'P': - if ($rr[4]<12) $rr[4] += 12; - break; - case 'A': - if ($rr[4]==12) $rr[4] = 0; - break; - default: - break; - } - // h-m-s-MM-DD-YY - return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]); - } -} +class ADORecordSet_array_mssql extends ADORecordSet_array {} /* Code Example 1: -select object_name(constid) as constraint_name, - object_name(fkeyid) as table_name, - col_name(fkeyid, fkey) as column_name, +select object_name(constid) as constraint_name, + object_name(fkeyid) as table_name, + col_name(fkeyid, fkey) as column_name, object_name(rkeyid) as referenced_table_name, - col_name(rkeyid, rkey) as referenced_column_name + col_name(rkeyid, rkey) as referenced_column_name from sysforeignkeys where object_name(fkeyid) = x order by constraint_name, table_name, referenced_table_name, keyno diff --git a/www/include/adodb5/drivers/adodb-mssql_n.inc.php b/www/include/adodb/drivers/adodb-mssql_n.inc.php similarity index 66% rename from www/include/adodb5/drivers/adodb-mssql_n.inc.php rename to www/include/adodb/drivers/adodb-mssql_n.inc.php index 2bbac5b2..236c1546 100644 --- a/www/include/adodb5/drivers/adodb-mssql_n.inc.php +++ b/www/include/adodb/drivers/adodb-mssql_n.inc.php @@ -1,46 +1,27 @@ $inboundValue) { - + if (is_resource($inboundValue)) { /* @@ -105,7 +86,7 @@ function _appendN($inboundData) { continue; } - + if (strpos($inboundValue, SINGLEQUOTE) === false) { /* @@ -120,11 +101,11 @@ function _appendN($inboundData) { * Check we haven't an odd number of single quotes (this can cause problems below * and should be considered one wrong SQL). Exit with debug info. */ - if ((substr_count($inboundValue, SINGLEQUOTE) & 1)) + if ((substr_count($inboundValue, SINGLEQUOTE) & 1)) { if ($this->debug) ADOConnection::outp("{$this->databaseType} internal transformation: not converted. Wrong number of quotes (odd)"); - + break; } @@ -135,9 +116,9 @@ function _appendN($inboundData) { $regexp = '/(\\\\' . SINGLEQUOTE . '[^' . SINGLEQUOTE . '])/'; if (preg_match($regexp, $inboundValue)) { - if ($this->debug) + if ($this->debug) ADOConnection::outp("{$this->databaseType} internal transformation: not converted. Found bad use of backslash + single quote"); - + break; } @@ -147,16 +128,16 @@ function _appendN($inboundData) { $pairs = array(); $regexp = '/(' . SINGLEQUOTE . SINGLEQUOTE . ')/'; preg_match_all($regexp, $inboundValue, $list_of_pairs); - + if ($list_of_pairs) { foreach (array_unique($list_of_pairs[0]) as $key=>$value) $pairs['<@#@#@PAIR-'.$key.'@#@#@>'] = $value; - - + + if (!empty($pairs)) $inboundValue = str_replace($pairs, array_keys($pairs), $inboundValue); - + } /* @@ -165,13 +146,13 @@ function _appendN($inboundData) { $literals = array(); $regexp = '/(N?' . SINGLEQUOTE . '.*?' . SINGLEQUOTE . ')/is'; preg_match_all($regexp, $inboundValue, $list_of_literals); - + if ($list_of_literals) { foreach (array_unique($list_of_literals[0]) as $key=>$value) $literals['<#@#@#LITERAL-'.$key.'#@#@#>'] = $value; - - + + if (!empty($literals)) $inboundValue = str_replace($literals, array_keys($literals), $inboundValue); } @@ -184,11 +165,11 @@ function _appendN($inboundData) { foreach ($literals as $key=>$value) { if (!is_numeric(trim($value, SINGLEQUOTE))) /* - * Non numeric string, prepend our dear N, whilst + * Non numeric string, prepend our dear N, whilst * Trimming potentially existing previous "N" */ - $literals[$key] = 'N' . trim($value, 'N'); - + $literals[$key] = 'N' . trim($value, 'N'); + } } @@ -197,7 +178,7 @@ function _appendN($inboundData) { */ if (!empty($literals)) $inboundValue = str_replace(array_keys($literals), $literals, $inboundValue); - + /* * Any pairs followed by N' must be switched to N' followed by those pairs @@ -210,40 +191,36 @@ function _appendN($inboundData) { */ if (!empty($pairs)) $inboundValue = str_replace(array_keys($pairs), $pairs, $inboundValue); - + /* * Print transformation if debug = on */ if (strcmp($inboundValue,$inboundArray[$inboundKey]) <> 0 && $this->debug) ADOConnection::outp("{$this->databaseType} internal transformation: {$inboundArray[$inboundKey]} to {$inboundValue}"); - + if (strcmp($inboundValue,$inboundArray[$inboundKey]) <> 0) /* * Place the transformed value into the outbound array */ $outboundArray[$inboundKey] = $inboundValue; } - + /* * Any transformations are in the $outboundArray */ if ($inboundIsArray) return $outboundArray; - + /* * We passed a string in originally */ return $outboundArray[0]; - + } } class ADORecordset_mssql_n extends ADORecordset_mssql { var $databaseType = "mssql_n"; - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } } diff --git a/www/include/adodb5/drivers/adodb-mssqlnative.inc.php b/www/include/adodb/drivers/adodb-mssqlnative.inc.php similarity index 61% rename from www/include/adodb5/drivers/adodb-mssqlnative.inc.php rename to www/include/adodb/drivers/adodb-mssqlnative.inc.php index 23eb2c03..89eb42ed 100644 --- a/www/include/adodb5/drivers/adodb-mssqlnative.inc.php +++ b/www/include/adodb/drivers/adodb-mssqlnative.inc.php @@ -1,24 +1,26 @@ = 0x4300) { -// docs say 4.2.0, but testing shows only since 4.3.0 does it work! - ini_set('mssql.datetimeconvert',0); -} else { - global $ADODB_mssql_mths; // array, months must be upper-case - $ADODB_mssql_date_order = 'mdy'; - $ADODB_mssql_mths = array( - 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6, - 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12); -} - class ADODB_mssqlnative extends ADOConnection { var $databaseType = "mssqlnative"; var $dataProvider = "mssqlnative"; var $replaceQuote = "''"; // string to use to replace quotes var $fmtDate = "'Y-m-d'"; var $fmtTimeStamp = "'Y-m-d\TH:i:s'"; + /** + * Enabling InsertID capability will cause execution of an extra query + * {@see $identitySQL} after each INSERT statement. To improve performance + * when inserting a large number of records, you should switch this off by + * calling {@see enableLastInsertID enableLastInsertID(false)}. + * @var bool $hasInsertID + */ var $hasInsertID = true; var $substr = "substring"; var $length = 'len'; @@ -124,8 +96,10 @@ class ADODB_mssqlnative extends ADOConnection { var $uniqueOrderBy = true; var $_bindInputArray = true; var $_dropSeqSQL = "drop table %s"; - var $connectionInfo = array(); + + var $connectionInfo = array('ReturnDatesAsStrings'=>true); var $cachedSchemaFlush = false; + var $sequences = false; var $mssql_version = ''; @@ -163,7 +137,7 @@ function ServerVersion() { } function ServerInfo() { - global $ADODB_FETCH_MODE; + global $ADODB_FETCH_MODE; static $arr = false; if (is_array($arr)) return $arr; @@ -177,6 +151,8 @@ function ServerInfo() { $arrServerInfo = sqlsrv_server_info($this->_connectionID); $ADODB_FETCH_MODE = $savem; + + $arr = array(); $arr['description'] = $arrServerInfo['SQLServerName'].' connected to '.$arrServerInfo['CurrentDatabase']; $arr['version'] = $arrServerInfo['SQLServerVersion'];//ADOConnection::_findvers($arr['description']); return $arr; @@ -187,14 +163,23 @@ function IfNull( $field, $ifNull ) return " ISNULL($field, $ifNull) "; // if MS SQL Server } - function _insertid() + public function enableLastInsertID($enable = true) { + $this->hasInsertID = $enable; + $this->lastInsID = false; + } + + /** + * Get the last value inserted into an IDENTITY column. + * + * The value will actually be set in {@see _query()} when executing an + * INSERT statement, but only if the connection's $hasInsertId property + * is true; this can be set with {@see enableLastInsertId()}. + * + * @inheritDoc + */ + protected function _insertID($table = '', $column = '') { - // SCOPE_IDENTITY() - // Returns the last IDENTITY value inserted into an IDENTITY column in - // the same scope. A scope is a module -- a stored procedure, trigger, - // function, or batch. Thus, two statements are in the same scope if - // they are in the same stored procedure, function, or batch. - return $this->lastInsertID; + return $this->lastInsID; } function _affectedrows() @@ -204,8 +189,6 @@ function _affectedrows() } function GenID($seq='adodbseq',$start=1) { - if (!$this->mssql_version) - $this->ServerVersion(); switch($this->mssql_version){ case 9: case 10: @@ -219,9 +202,6 @@ function GenID($seq='adodbseq',$start=1) { function CreateSequence($seq='adodbseq',$start=1) { - if (!$this->mssql_version) - $this->ServerVersion(); - switch($this->mssql_version){ case 9: case 10: @@ -231,7 +211,6 @@ function CreateSequence($seq='adodbseq',$start=1) return $this->CreateSequence2012($seq, $start); break; } - } /** @@ -321,9 +300,26 @@ function GenID2012($seq='adodbseq',$start=1) // Format date column in sql string given an input format that understands Y M D function SQLDate($fmt, $col=false) { - if (!$col) $col = $this->sysTimeStamp; + if (!$col) { + $col = $this->sysTimeStamp; + } $s = ''; + $ConvertableFmt=array( + "m/d/Y"=>101, "m/d/y"=>101 // US + ,"Y.m.d"=>102, "y.m.d"=>102 // ANSI + ,"d/m/Y"=>103, "d/m/y"=>103 // French /english + ,"d.m.Y"=>104, "d.m.y"=>104 // German + ,"d-m-Y"=>105, "d-m-y"=>105 // Italian + ,"m-d-Y"=>110, "m-d-y"=>110 // US Dash + ,"Y/m/d"=>111, "y/m/d"=>111 // Japan + ,"Ymd"=>112, "ymd"=>112 // ISO + ,"H:i:s"=>108 // Time + ); + if (key_exists($fmt,$ConvertableFmt)) { + return "convert (varchar ,$col," . $ConvertableFmt[$fmt] . ")"; + } + $len = strlen($fmt); for ($i=0; $i < $len; $i++) { if ($s) $s .= '+'; @@ -365,7 +361,9 @@ function SQLDate($fmt, $col=false) case 'A': $s .= "substring(convert(char(19),$col,0),18,2)"; break; - + case 'l': + $s .= "datename(dw,$col)"; + break; default: if ($ch == '\\') { $i++; @@ -397,6 +395,7 @@ function CommitTrans($ok=true) sqlsrv_commit($this->_connectionID); return true; } + function RollbackTrans() { if ($this->transOff) return true; @@ -458,8 +457,6 @@ function ErrorMsg() $this->_errorMsg .= "Error Code: ".$arrError[ 'code']."\n"; $this->_errorMsg .= "Message: ".$arrError[ 'message']."\n"; } - } else { - $this->_errorMsg = "No errors found"; } return $this->_errorMsg; } @@ -467,30 +464,75 @@ function ErrorMsg() function ErrorNo() { $err = sqlsrv_errors(SQLSRV_ERR_ALL); - if($err[0]) return $err[0]['code']; - else return 0; + if ($err && $err[0]) + return $err[0]['code']; + else + return 0; } // returns true or false function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) { - if (!function_exists('sqlsrv_connect')) return null; - $connectionInfo = $this->connectionInfo; - $connectionInfo["Database"]=$argDatabasename; - $connectionInfo["UID"]=$argUsername; - $connectionInfo["PWD"]=$argPassword; - - foreach ($this->connectionParameters as $parameter=>$value) - $connectionInfo[$parameter] = $value; - - if ($this->debug) ADOConnection::outp("
connecting... hostname: $argHostname params: ".var_export($connectionInfo,true)); - //if ($this->debug) ADOConnection::outp("
_connectionID before: ".serialize($this->_connectionID)); - if(!($this->_connectionID = sqlsrv_connect($argHostname,$connectionInfo))) { - if ($this->debug) ADOConnection::outp( "
errors: ".print_r( sqlsrv_errors(), true)); + if (!function_exists('sqlsrv_connect')) + { + if ($this->debug) + ADOConnection::outp('Microsoft SQL Server native driver (mssqlnative) not installed'); + return null; + } + + if (!empty($this->port)) + /* + * Port uses a comma + */ + $argHostname .= ",".$this->port; + + $connectionInfo = $this->connectionInfo; + $connectionInfo["Database"] = $argDatabasename; + if ((string)$argUsername != '' || (string)$argPassword != '') + { + /* + * If they pass either a userid or password, we assume + * SQL Server authentication + */ + $connectionInfo["UID"] = $argUsername; + $connectionInfo["PWD"] = $argPassword; + + if ($this->debug) + ADOConnection::outp('userid or password supplied, attempting connection with SQL Server Authentication'); + + } + else + { + /* + * If they don't pass either value, we won't add them to the + * connection parameters. This will then force an attempt + * to use windows authentication + */ + if ($this->debug) + + ADOConnection::outp('No userid or password supplied, attempting connection with Windows Authentication'); + } + + + /* + * Now merge in the passed connection parameters setting + */ + foreach ($this->connectionParameters as $options) + { + foreach($options as $parameter=>$value) + $connectionInfo[$parameter] = $value; + } + + if ($this->debug) ADOConnection::outp("connecting to host: $argHostname params: ".var_export($connectionInfo,true)); + if(!($this->_connectionID = @sqlsrv_connect($argHostname,$connectionInfo))) + { + if ($this->debug) + ADOConnection::outp( 'Connection Failed: '.print_r( sqlsrv_errors(), true)); return false; } - //if ($this->debug) ADOConnection::outp(" _connectionID after: ".serialize($this->_connectionID)); - //if ($this->debug) ADOConnection::outp("
defined functions:
".var_export(get_defined_functions(),true)."
"); + + $this->ServerVersion(); + return true; } @@ -501,13 +543,10 @@ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); } + function Prepare($sql) { return $sql; // prepare does not work properly with bind parameters as bind parameters are managed by sqlsrv_prepare! - - $stmt = sqlsrv_prepare( $this->_connectionID, $sql); - if (!$stmt) return $sql; - return array($sql,$stmt); } // returns concatenated string @@ -527,7 +566,12 @@ function Concat() $arr = $args; } - array_walk($arr, create_function('&$v', '$v = "CAST(" . $v . " AS VARCHAR(255))";')); + array_walk( + $arr, + function(&$value, $key) { + $value = "CAST(" . $value . " AS VARCHAR(255))"; + } + ); $s = implode('+',$arr); if (sizeof($arr) > 0) return "$s"; @@ -557,34 +601,67 @@ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') return $this->Execute($sql) != false; } - // returns query ID if successful, otherwise false - function _query($sql,$inputarr=false) + /** + * Execute a query. + * + * If executing an INSERT statement and $hasInsertId is true, will set + * $lastInsId. + * + * @param string $sql + * @param array $inputarr + * @return resource|false Query Id if successful, otherwise false + */ + function _query($sql, $inputarr = false) { $this->_errorMsg = false; - if (is_array($sql)) $sql = $sql[1]; + if (is_array($sql)) { + $sql = $sql[1]; + } - $insert = false; - // handle native driver flaw for retrieving the last insert ID - if(preg_match('/^\W*insert[\s\w()",.]+values\s*\((?:[^;\']|\'\'|(?:(?:\'\')*\'[^\']+\'(?:\'\')*))*;?$/i', $sql)) { - $insert = true; - $sql .= '; '.$this->identitySQL; // select scope_identity() + // Handle native driver flaw for retrieving the last insert ID + if ($this->hasInsertID) { + // Check if it's an INSERT statement + $retrieveLastInsertID = preg_match( + '/^\W*insert[\s\w()[\]",.]+values\s*\((?:[^;\']|\'\'|(?:(?:\'\')*\'[^\']+\'(?:\'\')*))*;?$/i', + $sql + ); + if ($retrieveLastInsertID) { + // Append the identity SQL, so it is executed in the same + // scope as the insert query. + $sql .= '; ' . $this->identitySQL; + } + } else { + $retrieveLastInsertID = false; } - if($inputarr) { + + if ($inputarr) { + // Ensure that the input array is indexed numerically, as required + // by sqlsrv_query(). If param() was used to create portable binds + // then the array might be associative. + $inputarr = array_values($inputarr); $rez = sqlsrv_query($this->_connectionID, $sql, $inputarr); } else { - $rez = sqlsrv_query($this->_connectionID,$sql); + $rez = sqlsrv_query($this->_connectionID, $sql); } - if ($this->debug) ADOConnection::outp("
running query: ".var_export($sql,true)."
input array: ".var_export($inputarr,true)."
result: ".var_export($rez,true)); + if ($this->debug) { + ADOConnection::outp("
running query: " . var_export($sql, true) + . "
input array: " . var_export($inputarr, true) + . "
result: " . var_export($rez, true) + ); + } - if(!$rez) { + $this->lastInsID = false; + if (!$rez) { $rez = false; - } else if ($insert) { - // retrieve the last insert ID (where applicable) - while ( sqlsrv_next_result($rez) ) { + } elseif ($retrieveLastInsertID) { + // Get the inserted id from the last result + // Note: loop is required as server may return more than one row, + // e.g. if triggers are involved (see #41) + while (sqlsrv_next_result($rez)) { sqlsrv_fetch($rez); - $this->lastInsertID = sqlsrv_get_field($rez, 0); + $this->lastInsID = sqlsrv_get_field($rez, 0, SQLSRV_PHPTYPE_INT); } } return $rez; @@ -593,22 +670,16 @@ function _query($sql,$inputarr=false) // returns true or false function _close() { - if ($this->transCnt) $this->RollbackTrans(); - $rez = @sqlsrv_close($this->_connectionID); + if ($this->transCnt) { + $this->RollbackTrans(); + } + if($this->_connectionID) { + $rez = sqlsrv_close($this->_connectionID); + } $this->_connectionID = false; return $rez; } - // mssql uses a default date like Dec 30 2000 12:00AM - static function UnixDate($v) - { - return ADORecordSet_array_mssqlnative::UnixDate($v); - } - - static function UnixTimeStamp($v) - { - return ADORecordSet_array_mssqlnative::UnixTimeStamp($v); - } function MetaIndexes($table,$primary=false, $owner = false) { @@ -650,7 +721,7 @@ function MetaIndexes($table,$primary=false, $owner = false) return $indexes; } - function MetaForeignKeys($table, $owner=false, $upper=false) + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { global $ADODB_FETCH_MODE; @@ -667,7 +738,7 @@ function MetaForeignKeys($table, $owner=false, $upper=false) where upper(object_name(fkeyid)) = $table order by constraint_name, referenced_table_name, keyno"; - $constraints =& $this->GetArray($sql); + $constraints = $this->GetArray($sql); $ADODB_FETCH_MODE = $save; @@ -683,7 +754,11 @@ function MetaForeignKeys($table, $owner=false, $upper=false) foreach($arr as $k => $v) { foreach($v as $a => $b) { if ($upper) $a = strtoupper($a); - $arr2[$a] = $b; + if (is_array($arr2[$a])) { // a previous foreign key was define for this reference table, we merge the new one + $arr2[$a] = array_merge($arr2[$a], $b); + } else { + $arr2[$a] = $b; + } } } return $arr2; @@ -693,7 +768,7 @@ function MetaForeignKeys($table, $owner=false, $upper=false) function MetaDatabases() { $this->SelectDB("master"); - $rs =& $this->Execute($this->metaDatabasesSQL); + $rs = $this->Execute($this->metaDatabasesSQL); $rows = $rs->GetRows(); $ret = array(); for($i=0;$icachedSchemaFlush) $cached_columns = array(); @@ -757,10 +834,7 @@ function MetaColumns($table, $upper=true, $schema=false){ if (array_key_exists($table,$cached_columns)){ return $cached_columns[$table]; } - # end adg - if (!$this->mssql_version) - $this->ServerVersion(); $this->_findschema($table,$schema); if ($schema) { @@ -794,7 +868,7 @@ function MetaColumns($table, $upper=true, $schema=false){ $fld->type = $rs->fields[1]; $fld->max_length = $rs->fields[2]; $fld->precision = $rs->fields[3]; - $fld->scale = $rs->fields[4]; + $fld->scale = $rs->fields[4]; $fld->not_null =!$rs->fields[5]; $fld->has_default = $rs->fields[6]; $fld->xtype = $rs->fields[7]; @@ -805,7 +879,7 @@ function MetaColumns($table, $upper=true, $schema=false){ $fld->type = $rs->fields['type']; $fld->max_length = $rs->fields['length']; $fld->precision = $rs->fields['precision']; - $fld->scale = $rs->fields['scale']; + $fld->scale = $rs->fields['scale']; $fld->not_null =!$rs->fields['nullable']; $fld->has_default = $rs->fields['default_value']; $fld->xtype = $rs->fields['xtype']; @@ -822,16 +896,156 @@ function MetaColumns($table, $upper=true, $schema=false){ } $rs->Close(); - # start adg $cached_columns[$table] = $retarr; - # end adg + return $retarr; } + /** + * Returns a substring of a varchar type field + * + * The SQL server version varies because the length is mandatory, so + * we append a reasonable string length + * + * @param string $fld The field to sub-string + * @param int $start The start point + * @param int $length An optional length + * + * @return The SQL text + */ + function substr($fld,$start,$length=0) + { + if ($length == 0) + /* + * The length available to varchar is 2GB, but that makes no + * sense in a substring, so I'm going to arbitrarily limit + * the length to 1K, but you could change it if you want + */ + $length = 1024; + + $text = "SUBSTRING($fld,$start,$length)"; + return $text; + } + + /** + * Returns the maximum size of a MetaType C field. Because of the + * database design, SQL Server places no limits on the size of data inserted + * Although the actual limit is 2^31-1 bytes. + * + * @return int + */ + function charMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + /** + * Returns the maximum size of a MetaType X field. Because of the + * database design, SQL Server places no limits on the size of data inserted + * Although the actual limit is 2^31-1 bytes. + * + * @return int + */ + function textMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + /** + * Lists procedures, functions and methods in an array. + * + * @param string $procedureNamePattern (optional) + * @param string $catalog (optional) + * @param string $schemaPattern (optional) + + * @return array of stored objects in current database. + * + */ + public function metaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null) + { + $metaProcedures = array(); + $procedureSQL = ''; + $catalogSQL = ''; + $schemaSQL = ''; + + if ($procedureNamePattern) + $procedureSQL = "AND ROUTINE_NAME LIKE " . strtoupper($this->qstr($procedureNamePattern)); + + if ($catalog) + $catalogSQL = "AND SPECIFIC_SCHEMA=" . strtoupper($this->qstr($catalog)); + + if ($schemaPattern) + $schemaSQL = "AND ROUTINE_SCHEMA LIKE {$this->qstr($schemaPattern)}"; + + $fields = " ROUTINE_NAME,ROUTINE_TYPE,ROUTINE_SCHEMA,ROUTINE_CATALOG"; + + $SQL = "SELECT $fields + FROM {$this->database}.information_schema.routines + WHERE 1=1 + $procedureSQL + $catalogSQL + $schemaSQL + ORDER BY ROUTINE_NAME + "; + + $result = $this->execute($SQL); + + if (!$result) + return false; + while ($r = $result->fetchRow()){ + if (!isset($r[0])) + /* + * Convert to numeric + */ + $r = array_values($r); + + $procedureName = $r[0]; + $schemaName = $r[2]; + $routineCatalog= $r[3]; + $metaProcedures[$procedureName] = array('type'=> $r[1], + 'catalog' => $routineCatalog, + 'schema' => $schemaName, + 'remarks' => '', + ); + } + + return $metaProcedures; + } + + /** + * An SQL Statement that adds a specific number of + * days or part to local datetime + * + * @param float $dayFraction + * @param string $date + * + * @return string + */ + public function offsetDate($dayFraction, $date = false) + { + if (!$date) + /* + * Use GETDATE() via systTimestamp; + */ + $date = $this->sysTimeStamp; + + /* + * seconds, number of seconds, date base + */ + $dateFormat = "DATEADD(s, %s, %s)"; + + /* + * Adjust the offset back to seconds + */ + $fraction = $dayFraction * 24 * 3600; + + return sprintf($dateFormat,$fraction,$date); + + } + } /*-------------------------------------------------------------------------------------- - Class Name: Recordset + Class Name: Recordset --------------------------------------------------------------------------------------*/ class ADORecordset_mssqlnative extends ADORecordSet { @@ -841,6 +1055,62 @@ class ADORecordset_mssqlnative extends ADORecordSet { var $fieldOffset = 0; // _mths works only in non-localised system + /** + * @var bool True if we have retrieved the fields metadata + */ + private $fieldObjectsRetrieved = false; + + /* + * Cross-reference the objects by name for easy access + */ + private $fieldObjectsIndex = array(); + + /* + * Cross references the dateTime objects for faster decoding + */ + private $dateTimeObjects = array(); + + /* + * flags that we have dateTimeObjects to handle + */ + private $hasDateTimeObjects = false; + + /* + * This is cross reference between how the types are stored + * in SQL Server and their english-language description + * -154 is a time field, see #432 + */ + private $_typeConversion = array( + -155 => 'datetimeoffset', + -154 => 'char', + -152 => 'xml', + -151 => 'udt', + -11 => 'uniqueidentifier', + -10 => 'ntext', + -9 => 'nvarchar', + -8 => 'nchar', + -7 => 'bit', + -6 => 'tinyint', + -5 => 'bigint', + -4 => 'image', + -3 => 'varbinary', + -2 => 'timestamp', + -1 => 'text', + 1 => 'char', + 2 => 'numeric', + 3 => 'decimal', + 4 => 'int', + 5 => 'smallint', + 6 => 'float', + 7 => 'real', + 12 => 'varchar', + 91 => 'date', + 93 => 'datetime' + ); + + + + function __construct($id,$mode=false) { if ($mode === false) { @@ -849,29 +1119,15 @@ function __construct($id,$mode=false) } $this->fetchMode = $mode; - return parent::__construct($id,$mode); + parent::__construct($id); } function _initrs() { - global $ADODB_COUNTRECS; - # KMN # if ($this->connection->debug) ADOConnection::outp("(before) ADODB_COUNTRECS: {$ADODB_COUNTRECS} _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}"); - /*$retRowsAff = sqlsrv_rows_affected($this->_queryID);//"If you need to determine the number of rows a query will return before retrieving the actual results, appending a SELECT COUNT ... query would let you get that information, and then a call to next_result would move you to the "real" results." - ADOConnection::outp("rowsaff: ".serialize($retRowsAff)); - $this->_numOfRows = ($ADODB_COUNTRECS)? $retRowsAff:-1;*/ $this->_numOfRows = -1;//not supported - $fieldmeta = sqlsrv_field_metadata($this->_queryID); - $this->_numOfFields = ($fieldmeta)? count($fieldmeta):-1; - # KMN # if ($this->connection->debug) ADOConnection::outp("(after) _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}"); - /* - * Copy the oracle method and cache the metadata at init time - */ - if ($this->_numOfFields>0) { - $this->_fieldobjs = array(); - $max = $this->_numOfFields; - for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i); - } + // Cache the metadata right now + $this->_fetchField(); } @@ -891,7 +1147,14 @@ function NextRecordSet() /* Use associative array to get fields array */ function Fields($colname) { - if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname]; + if (!is_array($this->fields)) + /* + * Too early + */ + return; + if ($this->fetchMode != ADODB_FETCH_NUM) + return $this->fields[$colname]; + if (!$this->bind) { $this->bind = array(); for ($i=0; $i < $this->_numOfFields; $i++) { @@ -903,79 +1166,63 @@ function Fields($colname) return $this->fields[$this->bind[strtoupper($colname)]]; } - /* Returns: an object containing field information. - Get column information in the Recordset object. fetchField() can be used in order to obtain information about - fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by - fetchField() is retrieved. - Designed By jcortinap#jc.com.mx + /** + * Returns: an object containing field information. + * + * Get column information in the Recordset object. fetchField() + * can be used in order to obtain information about fields in a + * certain query result. If the field offset isn't specified, + * the next field that wasn't yet retrieved by fetchField() + * is retrieved. + * + * @param int $fieldOffset (optional default=-1 for all + * @return mixed an ADOFieldObject, or array of objects */ - function _FetchField($fieldOffset = -1) + private function _fetchField($fieldOffset = -1) { - $_typeConversion = array( - -155 => 'datetimeoffset', - -154 => 'time', - -152 => 'xml', - -151 => 'udt', - -11 => 'uniqueidentifier', - -10 => 'ntext', - -9 => 'nvarchar', - -8 => 'nchar', - -7 => 'bit', - -6 => 'tinyint', - -5 => 'bigint', - -4 => 'image', - -3 => 'varbinary', - -2 => 'timestamp', - -1 => 'text', - 1 => 'char', - 2 => 'numeric', - 3 => 'decimal', - 4 => 'int', - 5 => 'smallint', - 6 => 'float', - 7 => 'real', - 12 => 'varchar', - 91 => 'date', - 93 => 'datetime' - ); + if ($this->fieldObjectsRetrieved) { + if ($this->fieldObjectsCache) { + // Already got the information + if ($fieldOffset == -1) { + return $this->fieldObjectsCache; + } else { + return $this->fieldObjectsCache[$fieldOffset]; + } + } else { + // No metadata available + return false; + } + } - $fa = @sqlsrv_field_metadata($this->_queryID); - if ($fieldOffset != -1) { - $fa = $fa[$fieldOffset]; + $this->fieldObjectsRetrieved = true; + /* + * Retrieve all metadata in one go. This is always returned as a + * numeric array. + */ + $fieldMetaData = sqlsrv_field_metadata($this->_queryID); + + if (!$fieldMetaData) { + // Not a statement that gives us metaData + return false; } - $false = false; - if (empty($fa)) { - $f = false;//PHP Notice: Only variable references should be returned by reference + + $this->_numOfFields = count($fieldMetaData); + foreach ($fieldMetaData as $key=>$value) { + $fld = new ADOFieldObject; + // Caution - keys are case-sensitive, must respect casing of values + $fld->name = $value['Name']; + $fld->max_length = $value['Size']; + $fld->column_source = $value['Name']; + $fld->type = $this->_typeConversion[$value['Type']]; + + $this->fieldObjectsCache[$key] = $fld; + $this->fieldObjectsIndex[$fld->name] = $key; } - else - { - // Convert to an object - $fa = array_change_key_case($fa, CASE_LOWER); - $fb = array(); - if ($fieldOffset != -1) - { - $fb = array( - 'name' => $fa['name'], - 'max_length' => $fa['size'], - 'column_source' => $fa['name'], - 'type' => $_typeConversion[$fa['type']] - ); - } - else - { - foreach ($fa as $key => $value) - { - $fb[] = array( - 'name' => $value['name'], - 'max_length' => $value['size'], - 'column_source' => $value['name'], - 'type' => $_typeConversion[$value['type']] - ); - } - } - $f = (object) $fb; + if ($fieldOffset == -1) { + return $this->fieldObjectsCache; } - return $f; + + return $this->fieldObjectsCache[$fieldOffset]; } /* @@ -983,12 +1230,16 @@ function _FetchField($fieldOffset = -1) * into the _fieldobjs array once, to save multiple calls to the * sqlsrv_field_metadata function * + * @param int $fieldOffset (optional) + * + * @return adoFieldObject + * * @author KM Newnham * @date 02/20/2013 */ - function FetchField($fieldOffset = -1) + function fetchField($fieldOffset = -1) { - return $this->_fieldobjs[$fieldOffset]; + return $this->fieldObjectsCache[$fieldOffset]; } function _seek($row) @@ -999,178 +1250,73 @@ function _seek($row) // speedup function MoveNext() { - //# KMN # if ($this->connection->debug) ADOConnection::outp("movenext()"); - //# KMN # if ($this->connection->debug) ADOConnection::outp("eof (beginning): ".$this->EOF); - if ($this->EOF) return false; + if ($this->EOF) + return false; $this->_currentRow++; - // # KMN # if ($this->connection->debug) ADOConnection::outp("_currentRow: ".$this->_currentRow); - if ($this->_fetch()) return true; + if ($this->_fetch()) + return true; $this->EOF = true; - //# KMN # if ($this->connection->debug) ADOConnection::outp("eof (end): ".$this->EOF); return false; } - - // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4 - // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot! function _fetch($ignore_fields=false) { - # KMN # if ($this->connection->debug) ADOConnection::outp("_fetch()"); if ($this->fetchMode & ADODB_FETCH_ASSOC) { - if ($this->fetchMode & ADODB_FETCH_NUM) { - //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: both"); + if ($this->fetchMode & ADODB_FETCH_NUM) $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_BOTH); - } else { - //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: assoc"); + else $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_ASSOC); - } - if (is_array($this->fields)) { - if (ADODB_ASSOC_CASE == 0) { - foreach($this->fields as $k=>$v) { - $this->fields[strtolower($k)] = $v; - } - } else if (ADODB_ASSOC_CASE == 1) { - foreach($this->fields as $k=>$v) { - $this->fields[strtoupper($k)] = $v; - } - } - } - } else { - //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: num"); - $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_NUMERIC); - } - if(is_array($this->fields) && array_key_exists(1,$this->fields) && !array_key_exists(0,$this->fields)) {//fix fetch numeric keys since they're not 0 based - $arrFixed = array(); - foreach($this->fields as $key=>$value) { - if(is_numeric($key)) { - $arrFixed[$key-1] = $value; - } else { - $arrFixed[$key] = $value; - } - } - //if($this->connection->debug) ADOConnection::outp("
fixing non 0 based return array, old: ".print_r($this->fields,true)." new: ".print_r($arrFixed,true)); - $this->fields = $arrFixed; - } - if(is_array($this->fields)) { - foreach($this->fields as $key=>$value) { - if (is_object($value) && method_exists($value, 'format')) {//is DateTime object - $this->fields[$key] = $value->format("Y-m-d\TH:i:s\Z"); - } + if (is_array($this->fields)) + { + + if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) + $this->fields = array_change_key_case($this->fields,CASE_LOWER); + else if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_UPPER) + $this->fields = array_change_key_case($this->fields,CASE_UPPER); + } } - if($this->fields === null) $this->fields = false; - # KMN # if ($this->connection->debug) ADOConnection::outp("
after _fetch, fields:
".print_r($this->fields,true)." backtrace: ".adodb_backtrace(false));
+		else
+			$this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_NUMERIC);
+
+		if (!$this->fields)
+			return false;
+
 		return $this->fields;
 	}
 
-	/*	close() only needs to be called if you are worried about using too much memory while your script
-		is running. All associated result memory for the specified result identifier will automatically be freed.	*/
+	/**
+	 * close() only needs to be called if you are worried about using too much
+	 * memory while your script is running. All associated result memory for
+	 * the specified result identifier will automatically be freed.
+	 *
+	 * @return bool tru if we succeeded in closing down
+	 */
 	function _close()
 	{
-		if(is_object($this->_queryID)) {
+		/*
+		* If we are closing down a failed query, collect any
+		* error messages. This is a hack fix to the "close too early"
+		* problem so this might go away later
+		*/
+		$this->connection->errorMsg();
+		if(is_resource($this->_queryID)) {
 			$rez = sqlsrv_free_stmt($this->_queryID);
 			$this->_queryID = false;
 			return $rez;
 		}
-		return true;
-	}
 
-	// mssql uses a default date like Dec 30 2000 12:00AM
-	static function UnixDate($v)
-	{
-		return ADORecordSet_array_mssqlnative::UnixDate($v);
+		return true;
 	}
 
-	static function UnixTimeStamp($v)
-	{
-		return ADORecordSet_array_mssqlnative::UnixTimeStamp($v);
-	}
 }
 
 
-class ADORecordSet_array_mssqlnative extends ADORecordSet_array {
-	function __construct($id=-1,$mode=false)
-	{
-		parent::__construct($id,$mode);
-	}
-
-		// mssql uses a default date like Dec 30 2000 12:00AM
-	static function UnixDate($v)
-	{
-
-		if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
-
-		global $ADODB_mssql_mths,$ADODB_mssql_date_order;
-
-		//Dec 30 2000 12:00AM
-		if ($ADODB_mssql_date_order == 'dmy') {
-			if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
-				return parent::UnixDate($v);
-			}
-			if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
-			$theday = $rr[1];
-			$themth =  substr(strtoupper($rr[2]),0,3);
-		} else {
-			if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
-				return parent::UnixDate($v);
-			}
-			if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
-			$theday = $rr[2];
-			$themth = substr(strtoupper($rr[1]),0,3);
-		}
-		$themth = $ADODB_mssql_mths[$themth];
-		if ($themth <= 0) return false;
-		// h-m-s-MM-DD-YY
-		return  adodb_mktime(0,0,0,$themth,$theday,$rr[3]);
-	}
-
-	static function UnixTimeStamp($v)
-	{
-
-		if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
-
-		global $ADODB_mssql_mths,$ADODB_mssql_date_order;
-
-		//Dec 30 2000 12:00AM
-		 if ($ADODB_mssql_date_order == 'dmy') {
-			 if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
-			,$v, $rr)) return parent::UnixTimeStamp($v);
-			if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
-			$theday = $rr[1];
-			$themth =  substr(strtoupper($rr[2]),0,3);
-		} else {
-			if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
-			,$v, $rr)) return parent::UnixTimeStamp($v);
-			if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
-			$theday = $rr[2];
-			$themth = substr(strtoupper($rr[1]),0,3);
-		}
-
-		$themth = $ADODB_mssql_mths[$themth];
-		if ($themth <= 0) return false;
-
-		switch (strtoupper($rr[6])) {
-		case 'P':
-			if ($rr[4]<12) $rr[4] += 12;
-			break;
-		case 'A':
-			if ($rr[4]==12) $rr[4] = 0;
-			break;
-		default:
-			break;
-		}
-		// h-m-s-MM-DD-YY
-		return  adodb_mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
-	}
-}
+class ADORecordSet_array_mssqlnative extends ADORecordSet_array {}
 
 /*
 Code Example 1:
diff --git a/www/include/adodb/drivers/adodb-mssqlpo.inc.php b/www/include/adodb/drivers/adodb-mssqlpo.inc.php
new file mode 100644
index 00000000..f2d2f6fb
--- /dev/null
+++ b/www/include/adodb/drivers/adodb-mssqlpo.inc.php
@@ -0,0 +1,48 @@
+_connectionID);
+		if (!$stmt)  return $sql;
+		return array($sql,$stmt);
+	}
+
+	function _query($sql,$inputarr=false)
+	{
+		if (is_string($sql)) $sql = str_replace('||','+',$sql);
+		return ADODB_mssql::_query($sql,$inputarr);
+	}
+}
+
+class ADORecordset_mssqlpo extends ADORecordset_mssql {
+	var $databaseType = "mssqlpo";
+}
diff --git a/www/include/adodb/drivers/adodb-mysqli.inc.php b/www/include/adodb/drivers/adodb-mysqli.inc.php
new file mode 100644
index 00000000..0100e7f8
--- /dev/null
+++ b/www/include/adodb/drivers/adodb-mysqli.inc.php
@@ -0,0 +1,1974 @@
+_transmode = $transaction_mode;
+		if (empty($transaction_mode)) {
+			$this->execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
+			return;
+		}
+		if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+		$this->execute("SET SESSION TRANSACTION ".$transaction_mode);
+	}
+
+	/**
+	 * Adds a parameter to the connection string.
+	 *
+	 * Parameter must be one of the constants listed in mysqli_options().
+	 * @see https://www.php.net/manual/en/mysqli.options.php
+	 *
+	 * @param int    $parameter The parameter to set
+	 * @param string $value     The value of the parameter
+	 *
+	 * @return bool
+	 */
+	public function setConnectionParameter($parameter, $value) {
+		if(!is_numeric($parameter)) {
+			$this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
+			return false;
+		}
+		return parent::setConnectionParameter($parameter, $value);
+	}
+
+	/**
+	 * Connect to a database.
+	 *
+	 * @todo add: parameter int $port, parameter string $socket
+	 *
+	 * @param string|null $argHostname (Optional) The host to connect to.
+	 * @param string|null $argUsername (Optional) The username to connect as.
+	 * @param string|null $argPassword (Optional) The password to connect with.
+	 * @param string|null $argDatabasename (Optional) The name of the database to start in when connected.
+	 * @param bool $persist (Optional) Whether or not to use a persistent connection.
+	 *
+	 * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension
+	 * isn't currently loaded.
+	 */
+	function _connect($argHostname = null,
+					  $argUsername = null,
+					  $argPassword = null,
+					  $argDatabasename = null,
+					  $persist = false)
+	{
+		if(!extension_loaded("mysqli")) {
+			return null;
+		}
+		$this->_connectionID = @mysqli_init();
+
+		if (is_null($this->_connectionID)) {
+			// mysqli_init only fails if insufficient memory
+			if ($this->debug) {
+				ADOConnection::outp("mysqli_init() failed : "  . $this->errorMsg());
+			}
+			return false;
+		}
+		/*
+		I suggest a simple fix which would enable adodb and mysqli driver to
+		read connection options from the standard mysql configuration file
+		/etc/my.cnf - "Bastien Duclaux" 
+		*/
+		$this->optionFlags = array();
+		foreach($this->optionFlags as $arr) {
+			mysqli_options($this->_connectionID,$arr[0],$arr[1]);
+		}
+
+		// Now merge in the standard connection parameters setting
+		foreach ($this->connectionParameters as $options) {
+			foreach ($options as $parameter => $value) {
+				// Make sure parameter is numeric before calling mysqli_options()
+				// to avoid Warning (or TypeError exception on PHP 8).
+				if (!is_numeric($parameter)
+					|| !mysqli_options($this->_connectionID, $parameter, $value)
+				) {
+					$this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
+				}
+			}
+		}
+
+		//https://php.net/manual/en/mysqli.persistconns.php
+		if ($persist && strncmp($argHostname,'p:',2) != 0) {
+			$argHostname = 'p:' . $argHostname;
+		}
+
+		// SSL Connections for MySQLI
+		if ($this->ssl_key || $this->ssl_cert || $this->ssl_ca || $this->ssl_capath || $this->ssl_cipher) {
+			mysqli_ssl_set($this->_connectionID, $this->ssl_key, $this->ssl_cert, $this->ssl_ca, $this->ssl_capath, $this->ssl_cipher);
+			$this->socket = MYSQLI_CLIENT_SSL;
+			$this->clientFlags = MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
+		}
+
+		#if (!empty($this->port)) $argHostname .= ":".$this->port;
+		/** @noinspection PhpCastIsUnnecessaryInspection */
+		$ok = @mysqli_real_connect($this->_connectionID,
+					$argHostname,
+					$argUsername,
+					$argPassword,
+					$argDatabasename,
+					# PHP7 compat: port must be int. Use default port if cast yields zero
+					(int)$this->port != 0 ? (int)$this->port : 3306,
+					$this->socket,
+					$this->clientFlags);
+
+		if ($ok) {
+			if ($argDatabasename)  return $this->selectDB($argDatabasename);
+			return true;
+		} else {
+			if ($this->debug) {
+				ADOConnection::outp("Could not connect : "  . $this->errorMsg());
+			}
+			$this->_connectionID = null;
+			return false;
+		}
+	}
+
+	/**
+	 * Connect to a database with a persistent connection.
+	 *
+	 * @param string|null $argHostname The host to connect to.
+	 * @param string|null $argUsername The username to connect as.
+	 * @param string|null $argPassword The password to connect with.
+	 * @param string|null $argDatabasename The name of the database to start in when connected.
+	 *
+	 * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension
+	 * isn't currently loaded.
+	 */
+	function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+	{
+		return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
+	}
+
+	/**
+	 * Connect to a database, whilst setting $this->forceNewConnect to true.
+	 *
+	 * When is this used? Close old connection first?
+	 * In _connect(), check $this->forceNewConnect?
+	 *
+	 * @param string|null $argHostname The host to connect to.
+	 * @param string|null $argUsername The username to connect as.
+	 * @param string|null $argPassword The password to connect with.
+	 * @param string|null $argDatabaseName The name of the database to start in when connected.
+	 *
+	 * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension
+	 * isn't currently loaded.
+	 */
+	function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
+	{
+		$this->forceNewConnect = true;
+		return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
+	}
+
+	/**
+	 * Replaces a null value with a specified replacement.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:ifnull
+	 *
+	 * @param mixed $field The field in the table to check.
+	 * @param mixed $ifNull The value to replace the null value with if it is found.
+	 *
+	 * @return string
+	 */
+	function IfNull($field, $ifNull)
+	{
+		return " IFNULL($field, $ifNull) ";
+	}
+
+	/**
+	 * Retrieves the first column of the first matching row of an executed SQL statement.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:getone
+	 *
+	 * @param string $sql The SQL to execute.
+	 * @param bool|array $inputarr (Optional) An array containing any required SQL parameters, or false if none needed.
+	 *
+	 * @return bool|array|null
+	 */
+	function GetOne($sql, $inputarr = false)
+	{
+		global $ADODB_GETONE_EOF;
+
+		$ret = false;
+		$rs = $this->execute($sql,$inputarr);
+		if ($rs) {
+			if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
+			else $ret = reset($rs->fields);
+			$rs->close();
+		}
+		return $ret;
+	}
+
+	/**
+	 * Get information about the current MySQL server.
+	 *
+	 * @return array
+	 */
+	function ServerInfo()
+	{
+		$arr['description'] = $this->getOne("select version()");
+		$arr['version'] = ADOConnection::_findvers($arr['description']);
+		return $arr;
+	}
+
+	/**
+	 * Begins a granular transaction.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:begintrans
+	 *
+	 * @return bool Always returns true.
+	 */
+	function BeginTrans()
+	{
+		if ($this->transOff) return true;
+		$this->transCnt += 1;
+
+		//$this->execute('SET AUTOCOMMIT=0');
+		mysqli_autocommit($this->_connectionID, false);
+		$this->execute('BEGIN');
+		return true;
+	}
+
+	/**
+	 * Commits a granular transaction.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:committrans
+	 *
+	 * @param bool $ok (Optional) If false, will rollback the transaction instead.
+	 *
+	 * @return bool Always returns true.
+	 */
+	function CommitTrans($ok = true)
+	{
+		if ($this->transOff) return true;
+		if (!$ok) return $this->rollbackTrans();
+
+		if ($this->transCnt) $this->transCnt -= 1;
+		$this->execute('COMMIT');
+
+		//$this->execute('SET AUTOCOMMIT=1');
+		mysqli_autocommit($this->_connectionID, true);
+		return true;
+	}
+
+	/**
+	 * Rollback a smart transaction.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rollbacktrans
+	 *
+	 * @return bool Always returns true.
+	 */
+	function RollbackTrans()
+	{
+		if ($this->transOff) return true;
+		if ($this->transCnt) $this->transCnt -= 1;
+		$this->execute('ROLLBACK');
+		//$this->execute('SET AUTOCOMMIT=1');
+		mysqli_autocommit($this->_connectionID, true);
+		return true;
+	}
+
+	/**
+	 * Lock a table row for a duration of a transaction.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rowlock
+	 *
+	 * @param string $table The table(s) to lock rows for.
+	 * @param string $where (Optional) The WHERE clause to use to determine which rows to lock.
+	 * @param string $col (Optional) The columns to select.
+	 *
+	 * @return bool True if the locking SQL statement executed successfully, otherwise false.
+	 */
+	function RowLock($table, $where = '', $col = '1 as adodbignore')
+	{
+		if ($this->transCnt==0) $this->beginTrans();
+		if ($where) $where = ' where '.$where;
+		$rs = $this->execute("select $col from $table $where for update");
+		return !empty($rs);
+	}
+
+	/**
+	 * Appropriately quotes strings with ' characters for insertion into the database.
+	 *
+	 * Relies on mysqli_real_escape_string()
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr
+	 *
+	 * @param string $s            The string to quote
+	 * @param bool   $magic_quotes This param is not used since 5.21.0.
+	 *                             It remains for backwards compatibility.
+	 *
+	 * @return string Quoted string
+	 */
+	function qStr($s, $magic_quotes=false)
+	{
+		if (is_null($s)) {
+			return 'NULL';
+		}
+
+		// mysqli_real_escape_string() throws a warning when the given
+		// connection is invalid
+		if ($this->_connectionID) {
+			return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
+		}
+
+		if ($this->replaceQuote[0] == '\\') {
+			$s = str_replace(array('\\', "\0"), array('\\\\', "\\\0") ,$s);
+		}
+		return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
+	}
+
+	/**
+	 * Return the AUTO_INCREMENT id of the last row that has been inserted or updated in a table.
+	 *
+	 * @inheritDoc
+	 */
+	protected function _insertID($table = '', $column = '')
+	{
+		// mysqli_insert_id does not return the last_insert_id if called after
+		// execution of a stored procedure so we execute this instead.
+		if ($this->useLastInsertStatement)
+			$result = ADOConnection::getOne('SELECT LAST_INSERT_ID()');
+		else
+			$result = @mysqli_insert_id($this->_connectionID);
+
+		if ($result == -1) {
+			if ($this->debug)
+				ADOConnection::outp("mysqli_insert_id() failed : "  . $this->errorMsg());
+		}
+		// reset prepared statement flags
+		$this->usePreparedStatement   = false;
+		$this->useLastInsertStatement = false;
+		return $result;
+	}
+
+	/**
+	 * Returns how many rows were effected by the most recently executed SQL statement.
+	 * Only works for INSERT, UPDATE and DELETE queries.
+	 *
+	 * @return int The number of rows affected.
+	 */
+	function _affectedrows()
+	{
+		if ($this->isSelectStatement) {
+			// Affected rows works fine against selects, returning
+			// the rowcount, but ADOdb does not do that.
+			return false;
+		}
+		else if ($this->statementAffectedRows >= 0)
+		{
+			$result = $this->statementAffectedRows;
+			$this->statementAffectedRows = -1;
+		}
+		else
+		{
+			$result =  @mysqli_affected_rows($this->_connectionID);
+			if ($result == -1) {
+				if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : "  . $this->errorMsg());
+			}
+		}
+		return $result;
+	}
+
+	// Reference on Last_Insert_ID on the recommended way to simulate sequences
+	var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
+	var $_genSeqSQL = "create table if not exists %s (id int not null)";
+	var $_genSeqCountSQL = "select count(*) from %s";
+	var $_genSeq2SQL = "insert into %s values (%s)";
+	var $_dropSeqSQL = "drop table if exists %s";
+
+	/**
+	 * Creates a sequence in the database.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:createsequence
+	 *
+	 * @param string $seqname The sequence name.
+	 * @param int $startID The start id.
+	 *
+	 * @return ADORecordSet|bool A record set if executed successfully, otherwise false.
+	 */
+	function CreateSequence($seqname = 'adodbseq', $startID = 1)
+	{
+		if (empty($this->_genSeqSQL)) return false;
+
+		$ok = $this->execute(sprintf($this->_genSeqSQL,$seqname));
+		if (!$ok) return false;
+		return $this->execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+	}
+
+	/**
+	 * A portable method of creating sequence numbers.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:genid
+	 *
+	 * @param string $seqname (Optional) The name of the sequence to use.
+	 * @param int $startID (Optional) The point to start at in the sequence.
+	 *
+	 * @return bool|int|string
+	 */
+	function GenID($seqname = 'adodbseq', $startID = 1)
+	{
+		// post-nuke sets hasGenID to false
+		if (!$this->hasGenID) return false;
+
+		$getnext = sprintf($this->_genIDSQL,$seqname);
+		$holdtransOK = $this->_transOK; // save the current status
+		$rs = @$this->execute($getnext);
+		if (!$rs) {
+			if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
+			$this->execute(sprintf($this->_genSeqSQL,$seqname));
+			$cnt = $this->getOne(sprintf($this->_genSeqCountSQL,$seqname));
+			if (!$cnt) $this->execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+			$rs = $this->execute($getnext);
+		}
+
+		if ($rs) {
+			$this->genID = mysqli_insert_id($this->_connectionID);
+			if ($this->genID == 0) {
+				$getnext = "select LAST_INSERT_ID() from " . $seqname;
+				$rs = $this->execute($getnext);
+				$this->genID = (int)$rs->fields[0];
+			}
+			$rs->close();
+		} else
+			$this->genID = 0;
+
+		return $this->genID;
+	}
+
+	/**
+	 * Return a list of all visible databases except the 'mysql' database.
+	 *
+	 * @return array|false An array of database names, or false if the query failed.
+	 */
+	function MetaDatabases()
+	{
+		$query = "SHOW DATABASES";
+		$ret = $this->execute($query);
+		if ($ret && is_object($ret)){
+			$arr = array();
+			while (!$ret->EOF){
+				$db = $ret->fields('Database');
+				if ($db != 'mysql') $arr[] = $db;
+				$ret->moveNext();
+			}
+			return $arr;
+		}
+		return $ret;
+	}
+
+	/**
+	 * Get a list of indexes on the specified table.
+	 *
+	 * @param string $table The name of the table to get indexes for.
+	 * @param bool $primary (Optional) Whether or not to include the primary key.
+	 * @param bool $owner (Optional) Unused.
+	 *
+	 * @return array|bool An array of the indexes, or false if the query to get the indexes failed.
+	 */
+	function MetaIndexes($table, $primary = false, $owner = false)
+	{
+		// save old fetch mode
+		global $ADODB_FETCH_MODE;
+
+		$save = $ADODB_FETCH_MODE;
+		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+		if ($this->fetchMode !== FALSE) {
+			$savem = $this->setFetchMode(FALSE);
+		}
+
+		// get index details
+		$rs = $this->Execute(sprintf('SHOW INDEXES FROM `%s`',$table));
+
+		// restore fetchmode
+		if (isset($savem)) {
+			$this->setFetchMode($savem);
+		}
+		$ADODB_FETCH_MODE = $save;
+
+		if (!is_object($rs)) {
+			return false;
+		}
+
+		$indexes = array ();
+
+		// parse index data into array
+		while ($row = $rs->fetchRow()) {
+			if ($primary == FALSE AND $row[2] == 'PRIMARY') {
+				continue;
+			}
+
+			if (!isset($indexes[$row[2]])) {
+				$indexes[$row[2]] = array(
+					'unique' => ($row[1] == 0),
+					'columns' => array()
+				);
+			}
+
+			$indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
+		}
+
+		// sort columns by order in the index
+		foreach ( array_keys ($indexes) as $index )
+		{
+			ksort ($indexes[$index]['columns']);
+		}
+
+		return $indexes;
+	}
+
+	/**
+	 * Returns a portably-formatted date string from a timestamp database column.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:sqldate
+	 *
+	 * @param string $fmt The date format to use.
+	 * @param string|bool $col (Optional) The table column to date format, or if false, use NOW().
+	 *
+	 * @return string The SQL DATE_FORMAT() string, or false if the provided date format was empty.
+	 */
+	function SQLDate($fmt, $col = false)
+	{
+		if (!$col) $col = $this->sysTimeStamp;
+		$s = 'DATE_FORMAT('.$col.",'";
+		$concat = false;
+		$len = strlen($fmt);
+		for ($i=0; $i < $len; $i++) {
+			$ch = $fmt[$i];
+			switch($ch) {
+			case 'Y':
+			case 'y':
+				$s .= '%Y';
+				break;
+			case 'Q':
+			case 'q':
+				$s .= "'),Quarter($col)";
+
+				if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
+				else $s .= ",('";
+				$concat = true;
+				break;
+			case 'M':
+				$s .= '%b';
+				break;
+
+			case 'm':
+				$s .= '%m';
+				break;
+			case 'D':
+			case 'd':
+				$s .= '%d';
+				break;
+
+			case 'H':
+				$s .= '%H';
+				break;
+
+			case 'h':
+				$s .= '%I';
+				break;
+
+			case 'i':
+				$s .= '%i';
+				break;
+
+			case 's':
+				$s .= '%s';
+				break;
+
+			case 'a':
+			case 'A':
+				$s .= '%p';
+				break;
+
+			case 'w':
+				$s .= '%w';
+				break;
+
+			case 'l':
+				$s .= '%W';
+				break;
+
+			default:
+
+				if ($ch == '\\') {
+					$i++;
+					$ch = substr($fmt,$i,1);
+				}
+				$s .= $ch;
+				break;
+			}
+		}
+		$s.="')";
+		if ($concat) $s = "CONCAT($s)";
+		return $s;
+	}
+
+	/**
+	 * Returns a database-specific concatenation of strings.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:concat
+	 *
+	 * @return string
+	 */
+	function Concat()
+	{
+		$arr = func_get_args();
+
+		// suggestion by andrew005@mnogo.ru
+		$s = implode(',',$arr);
+		if (strlen($s) > 0) return "CONCAT($s)";
+		else return '';
+	}
+
+	/**
+	 * Creates a portable date offset field, for use in SQL statements.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:offsetdate
+	 *
+	 * @param float $dayFraction A day in floating point
+	 * @param string|bool $date (Optional) The date to offset. If false, uses CURDATE()
+	 *
+	 * @return string
+	 */
+	function OffsetDate($dayFraction, $date = false)
+	{
+		if (!$date) $date = $this->sysDate;
+
+		$fraction = $dayFraction * 24 * 3600;
+		return $date . ' + INTERVAL ' .	 $fraction.' SECOND';
+
+//		return "from_unixtime(unix_timestamp($date)+$fraction)";
+	}
+
+	/**
+	 * Returns information about stored procedures and stored functions.
+	 *
+	 * @param string|bool $procedureNamePattern (Optional) Only look for procedures/functions with a name matching this pattern.
+	 * @param null $catalog (Optional) Unused.
+	 * @param null $schemaPattern (Optional) Unused.
+	 *
+	 * @return array
+	 */
+	function MetaProcedures($procedureNamePattern = false, $catalog  = null, $schemaPattern  = null)
+	{
+		// save old fetch mode
+		global $ADODB_FETCH_MODE;
+
+		$save = $ADODB_FETCH_MODE;
+		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+		if ($this->fetchMode !== FALSE) {
+			$savem = $this->setFetchMode(FALSE);
+		}
+
+		$procedures = array ();
+
+		// get index details
+
+		$likepattern = '';
+		if ($procedureNamePattern) {
+			$likepattern = " LIKE '".$procedureNamePattern."'";
+		}
+		$rs = $this->execute('SHOW PROCEDURE STATUS'.$likepattern);
+		if (is_object($rs)) {
+
+			// parse index data into array
+			while ($row = $rs->fetchRow()) {
+				$procedures[$row[1]] = array(
+					'type' => 'PROCEDURE',
+					'catalog' => '',
+					'schema' => '',
+					'remarks' => $row[7],
+				);
+			}
+		}
+
+		$rs = $this->execute('SHOW FUNCTION STATUS'.$likepattern);
+		if (is_object($rs)) {
+			// parse index data into array
+			while ($row = $rs->fetchRow()) {
+				$procedures[$row[1]] = array(
+					'type' => 'FUNCTION',
+					'catalog' => '',
+					'schema' => '',
+					'remarks' => $row[7]
+				);
+			}
+		}
+
+		// restore fetchmode
+		if (isset($savem)) {
+				$this->setFetchMode($savem);
+		}
+		$ADODB_FETCH_MODE = $save;
+
+		return $procedures;
+	}
+
+	/**
+	 * Retrieves a list of tables based on given criteria
+	 *
+	 * @param string|bool $ttype (Optional) Table type = 'TABLE', 'VIEW' or false=both (default)
+	 * @param string|bool $showSchema (Optional) schema name, false = current schema (default)
+	 * @param string|bool $mask (Optional) filters the table by name
+	 *
+	 * @return array list of tables
+	 */
+	function MetaTables($ttype = false, $showSchema = false, $mask = false)
+	{
+		$save = $this->metaTablesSQL;
+		if ($showSchema && is_string($showSchema)) {
+			$this->metaTablesSQL .= $this->qstr($showSchema);
+		} else {
+			$this->metaTablesSQL .= "schema()";
+		}
+
+		if ($mask) {
+			$mask = $this->qstr($mask);
+			$this->metaTablesSQL .= " AND table_name LIKE $mask";
+		}
+		$ret = ADOConnection::metaTables($ttype,$showSchema);
+
+		$this->metaTablesSQL = $save;
+		return $ret;
+	}
+
+	/**
+	 * Return information about a table's foreign keys.
+	 *
+	 * @param string $table The name of the table to get the foreign keys for.
+	 * @param string|bool $owner (Optional) The database the table belongs to, or false to assume the current db.
+	 * @param string|bool $upper (Optional) Force uppercase table name on returned array keys.
+	 * @param bool $associative (Optional) Whether to return an associate or numeric array.
+	 *
+	 * @return array|bool An array of foreign keys, or false no foreign keys could be found.
+	 */
+	public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
+	{
+		global $ADODB_FETCH_MODE;
+
+		if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC
+		|| $this->fetchMode == ADODB_FETCH_ASSOC)
+			$associative = true;
+
+		$savem = $ADODB_FETCH_MODE;
+		$this->setFetchMode(ADODB_FETCH_ASSOC);
+
+		if ( !empty($owner) ) {
+			$table = "$owner.$table";
+		}
+
+		$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE `%s`', $table));
+
+		$this->setFetchMode($savem);
+
+		$create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
+
+		$matches = array();
+
+		if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
+		$foreign_keys = array();
+		$num_keys = count($matches[0]);
+		for ( $i = 0; $i < $num_keys; $i ++ ) {
+			$my_field  = explode('`, `', $matches[1][$i]);
+			$ref_table = $matches[2][$i];
+			$ref_field = explode('`, `', $matches[3][$i]);
+
+			if ( $upper ) {
+				$ref_table = strtoupper($ref_table);
+			}
+
+			// see https://sourceforge.net/p/adodb/bugs/100/
+			if (!isset($foreign_keys[$ref_table])) {
+				$foreign_keys[$ref_table] = array();
+			}
+			$num_fields = count($my_field);
+			for ( $j = 0; $j < $num_fields; $j ++ ) {
+				if ( $associative ) {
+					$foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
+				} else {
+					$foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
+				}
+			}
+		}
+
+		return $foreign_keys;
+	}
+
+	/**
+	 * Return an array of information about a table's columns.
+	 *
+	 * @param string $table The name of the table to get the column info for.
+	 * @param bool $normalize (Optional) Unused.
+	 *
+	 * @return ADOFieldObject[]|bool An array of info for each column, or false if it could not determine the info.
+	 */
+	function MetaColumns($table, $normalize = true)
+	{
+		$false = false;
+		if (!$this->metaColumnsSQL)
+			return $false;
+
+		global $ADODB_FETCH_MODE;
+		$save = $ADODB_FETCH_MODE;
+		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+		if ($this->fetchMode !== false)
+			$savem = $this->SetFetchMode(false);
+		/*
+		* Return assoc array where key is column name, value is column type
+		*    [1] => int unsigned
+		*/
+
+		$SQL = "SELECT column_name, column_type
+				  FROM information_schema.columns
+				 WHERE table_schema='{$this->databaseName}'
+				   AND table_name='$table'";
+
+		$schemaArray = $this->getAssoc($SQL);
+		$schemaArray = array_change_key_case($schemaArray,CASE_LOWER);
+
+		$rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+		if (isset($savem)) $this->SetFetchMode($savem);
+		$ADODB_FETCH_MODE = $save;
+		if (!is_object($rs))
+			return $false;
+
+		$retarr = array();
+		while (!$rs->EOF) {
+			$fld = new ADOFieldObject();
+			$fld->name = $rs->fields[0];
+
+			/*
+			* Type from information_schema returns
+			* the same format in V8 mysql as V5
+			*/
+			$type = $schemaArray[strtolower($fld->name)];
+
+			// split type into type(length):
+			$fld->scale = null;
+			if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
+				$fld->type = $query_array[1];
+				$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+				$fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
+			} elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
+				$fld->type = $query_array[1];
+				$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+			} elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
+				$fld->type = $query_array[1];
+				$arr = explode(",",$query_array[2]);
+				$fld->enums = $arr;
+				$zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
+				$fld->max_length = ($zlen > 0) ? $zlen : 1;
+			} else {
+				$fld->type = $type;
+				$fld->max_length = -1;
+			}
+
+			$fld->not_null = ($rs->fields[2] != 'YES');
+			$fld->primary_key = ($rs->fields[3] == 'PRI');
+			$fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
+			$fld->binary = (strpos($type,'blob') !== false);
+			$fld->unsigned = (strpos($type,'unsigned') !== false);
+			$fld->zerofill = (strpos($type,'zerofill') !== false);
+
+			if (!$fld->binary) {
+				$d = $rs->fields[4];
+				if ($d != '' && $d != 'NULL') {
+					$fld->has_default = true;
+					$fld->default_value = $d;
+				} else {
+					$fld->has_default = false;
+				}
+			}
+
+			if ($save == ADODB_FETCH_NUM) {
+				$retarr[] = $fld;
+			} else {
+				$retarr[strtoupper($fld->name)] = $fld;
+			}
+			$rs->moveNext();
+		}
+
+		$rs->close();
+		return $retarr;
+	}
+
+	/**
+	 * Select which database to connect to.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:selectdb
+	 *
+	 * @param string $dbName The name of the database to select.
+	 *
+	 * @return bool True if the database was selected successfully, otherwise false.
+	 */
+	function SelectDB($dbName)
+	{
+//		$this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
+		$this->database = $dbName;
+		$this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+
+		if ($this->_connectionID) {
+			$result = @mysqli_select_db($this->_connectionID, $dbName);
+			if (!$result) {
+				ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->errorMsg());
+			}
+			return $result;
+		}
+		return false;
+	}
+
+	/**
+	 * Executes a provided SQL statement and returns a handle to the result, with the ability to supply a starting
+	 * offset and record count.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:selectlimit
+	 *
+	 * @param string $sql The SQL to execute.
+	 * @param int $nrows (Optional) The limit for the number of records you want returned. By default, all results.
+	 * @param int $offset (Optional) The offset to use when selecting the results. By default, no offset.
+	 * @param array|bool $inputarr (Optional) Any parameter values required by the SQL statement, or false if none.
+	 * @param int $secs2cache (Optional) If greater than 0, perform a cached execute. By default, normal execution.
+	 *
+	 * @return ADORecordSet|false The query results, or false if the query failed to execute.
+	 */
+	function SelectLimit($sql,
+						 $nrows = -1,
+						 $offset = -1,
+						 $inputarr = false,
+						 $secs2cache = 0)
+	{
+		$nrows = (int) $nrows;
+		$offset = (int) $offset;
+		$offsetStr = ($offset >= 0) ? "$offset," : '';
+		if ($nrows < 0) $nrows = '18446744073709551615';
+
+		if ($secs2cache)
+			$rs = $this->cacheExecute($secs2cache, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
+		else
+			$rs = $this->execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
+
+		return $rs;
+	}
+
+	/**
+	 * Prepares an SQL statement and returns a handle to use.
+	 * This is not used by bound parameters anymore
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:prepare
+	 * @todo update this function to handle prepared statements correctly
+	 *
+	 * @param string $sql The SQL to prepare.
+	 *
+	 * @return string The original SQL that was provided.
+	 */
+	function Prepare($sql)
+	{
+		/*
+		* Flag the insert_id method to use the correct retrieval method
+		*/
+		$this->usePreparedStatement = true;
+
+		/*
+		* Prepared statements are not yet handled correctly
+		*/
+		return $sql;
+		$stmt = $this->_connectionID->prepare($sql);
+		if (!$stmt) {
+			echo $this->errorMsg();
+			return $sql;
+		}
+		return array($sql,$stmt);
+	}
+
+	/**
+	 * Execute SQL
+	 *
+	 * @param string     $sql      SQL statement to execute, or possibly an array
+	 *                             holding prepared statement ($sql[0] will hold sql text)
+	 * @param array|bool $inputarr holds the input data to bind to.
+	 *                             Null elements will be set to null.
+	 *
+	 * @return ADORecordSet|bool
+	 */
+	public function execute($sql, $inputarr = false)
+	{
+		if ($this->fnExecute) {
+			$fn = $this->fnExecute;
+			$ret = $fn($this, $sql, $inputarr);
+			if (isset($ret)) {
+				return $ret;
+			}
+		}
+
+		if ($inputarr === false || $inputarr === []) {
+			return $this->_execute($sql);
+		}
+
+		if (!is_array($inputarr)) {
+			$inputarr = array($inputarr);
+		}
+
+		if (!is_array($sql)) {
+			// Check if we are bulkbinding. If so, $inputarr is a 2d array,
+			// and we make a gross assumption that all rows have the same number
+			// of columns of the same type, and use the elements of the first row
+			// to determine the MySQL bind param types.
+			if (is_array($inputarr[0])) {
+				if (!$this->bulkBind) {
+					$this->outp_throw(
+						"2D Array of values sent to execute and 'ADOdb_mysqli::bulkBind' not set",
+						'Execute'
+					);
+					return false;
+				}
+
+				$bulkTypeArray = [];
+				foreach ($inputarr as $v) {
+					if (is_string($this->bulkBind)) {
+						$typeArray = array_merge((array)$this->bulkBind, $v);
+					} else {
+						$typeArray = $this->getBindParamWithType($v);
+					}
+					$bulkTypeArray[] = $typeArray;
+				}
+				$this->bulkBind = false;
+				$ret = $this->_execute($sql, $bulkTypeArray);
+			} else {
+				$typeArray = $this->getBindParamWithType($inputarr);
+				$ret = $this->_execute($sql, $typeArray);
+			}
+		} else {
+			$ret = $this->_execute($sql, $inputarr);
+		}
+		return $ret;
+	}
+
+	/**
+	 * Inserts the bind param type string at the front of the parameter array.
+	 *
+	 * @see https://www.php.net/manual/en/mysqli-stmt.bind-param.php
+	 *
+	 * @param array $inputArr
+	 * @return array
+	 */
+	private function getBindParamWithType($inputArr): array
+	{
+		$typeString = '';
+		foreach ($inputArr as $v) {
+			if (is_integer($v) || is_bool($v)) {
+				$typeString .= 'i';
+			} elseif (is_float($v)) {
+				$typeString .= 'd';
+			} elseif (is_object($v)) {
+				// Assume a blob
+				$typeString .= 'b';
+			} else {
+				$typeString .= 's';
+			}
+		}
+
+		// Place the field type list at the front of the parameter array.
+		// This is the mysql specific format
+		array_unshift($inputArr, $typeString);
+		return $inputArr;
+	}
+
+	/**
+	* Return the query id.
+	*
+	* @param string|array $sql
+	* @param array $inputarr
+	*
+	* @return bool|mysqli_result
+	*/
+	function _query($sql, $inputarr)
+	{
+		global $ADODB_COUNTRECS;
+		// Move to the next recordset, or return false if there is none. In a stored proc
+		// call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
+		// returns false. I think this is because the last "recordset" is actually just the
+		// return value of the stored proc (ie the number of rows affected).
+		// Commented out for reasons of performance. You should retrieve every recordset yourself.
+		//	if (!mysqli_next_result($this->connection->_connectionID))	return false;
+
+		if (is_array($sql)) {
+
+			// Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
+			// returns as bound variables.
+
+			$stmt = $sql[1];
+			$a = '';
+			foreach($inputarr as $v) {
+				if (is_string($v)) $a .= 's';
+				else if (is_integer($v)) $a .= 'i';
+				else $a .= 'd';
+			}
+
+			/*
+			 * set prepared statement flags
+			 */
+			if ($this->usePreparedStatement)
+				$this->useLastInsertStatement = true;
+
+			$fnarr = array_merge( array($stmt,$a) , $inputarr);
+			call_user_func_array('mysqli_stmt_bind_param',$fnarr);
+			return mysqli_stmt_execute($stmt);
+		}
+		else if (is_string($sql) && is_array($inputarr))
+		{
+
+			/*
+			* This is support for true prepared queries
+			* with bound parameters
+			*
+			* set prepared statement flags
+			*/
+			$this->usePreparedStatement = true;
+			$this->usingBoundVariables = true;
+
+			$bulkBindArray = array();
+			if (is_array($inputarr[0]))
+			{
+				$bulkBindArray = $inputarr;
+				$inputArrayCount = count($inputarr[0]) - 1;
+			}
+			else
+			{
+				$bulkBindArray[] = $inputarr;
+				$inputArrayCount = count($inputarr) - 1;
+			}
+
+
+			/*
+			* Prepare the statement with the placeholders,
+			* prepare will fail if the statement is invalid
+			* so we trap and error if necessary. Note that we
+			* are calling MySQL prepare here, not ADOdb
+			*/
+			$stmt = $this->_connectionID->prepare($sql);
+			if ($stmt === false)
+			{
+				$this->outp_throw(
+					"SQL Statement failed on preparation: " . htmlspecialchars($sql) . "'",
+					'Execute'
+				);
+				return false;
+			}
+			/*
+			* Make sure the number of parameters provided in the input
+			* array matches what the query expects. We must discount
+			* the first parameter which contains the data types in
+			* our inbound parameters
+			*/
+			$nparams = $stmt->param_count;
+
+			if ($nparams  != $inputArrayCount)
+			{
+
+				$this->outp_throw(
+					"Input array has " . $inputArrayCount .
+					" params, does not match query: '" . htmlspecialchars($sql) . "'",
+					'Execute'
+				);
+				return false;
+			}
+
+			foreach ($bulkBindArray as $inputarr)
+			{
+				/*
+				* Must pass references into call_user_func_array
+				*/
+				$paramsByReference = array();
+				foreach($inputarr as $key => $value) {
+					/** @noinspection PhpArrayAccessCanBeReplacedWithForeachValueInspection */
+					$paramsByReference[$key] = &$inputarr[$key];
+				}
+
+				/*
+				* Bind the params
+				*/
+				call_user_func_array(array($stmt, 'bind_param'), $paramsByReference);
+
+				/*
+				* Execute
+				*/
+
+				$ret = mysqli_stmt_execute($stmt);
+
+				/*
+				* Did we throw an error?
+				*/
+				if ($ret == false)
+					return false;
+			}
+
+			// Tells affected_rows to be compliant
+			$this->isSelectStatement = $stmt->affected_rows == -1;
+			if (!$this->isSelectStatement) {
+				$this->statementAffectedRows = $stmt->affected_rows;
+				return true;
+			}
+
+			// Turn the statement into a result set and return it
+			return $stmt->get_result();
+		}
+		else
+		{
+			/*
+			* reset prepared statement flags, in case we set them
+			* previously and didn't use them
+			*/
+			$this->usePreparedStatement   = false;
+			$this->useLastInsertStatement = false;
+		}
+
+		/*
+		if (!$mysql_res =  mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
+			if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->errorMsg());
+			return false;
+		}
+
+		return $mysql_res;
+		*/
+
+		if ($this->multiQuery) {
+			$rs = mysqli_multi_query($this->_connectionID, $sql.';');
+			if ($rs) {
+				$rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
+				return $rs ?: true; // mysqli_more_results( $this->_connectionID )
+			}
+		} else {
+			$rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
+			if ($rs) {
+				$this->isSelectStatement = is_object($rs);
+				return $rs;
+			}
+		}
+
+		if($this->debug)
+			ADOConnection::outp("Query: " . $sql . " failed. " . $this->errorMsg());
+
+		return false;
+
+	}
+
+	/**
+	 * Returns a database specific error message.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:errormsg
+	 *
+	 * @return string The last error message.
+	 */
+	function ErrorMsg()
+	{
+		if (empty($this->_connectionID))
+			$this->_errorMsg = @mysqli_connect_error();
+		else
+			$this->_errorMsg = @mysqli_error($this->_connectionID);
+		return $this->_errorMsg;
+	}
+
+	/**
+	 * Returns the last error number from previous database operation.
+	 *
+	 * @return int The last error number.
+	 */
+	function ErrorNo()
+	{
+		if (empty($this->_connectionID))
+			return @mysqli_connect_errno();
+		else
+			return @mysqli_errno($this->_connectionID);
+	}
+
+	/**
+	 * Close the database connection.
+	 *
+	 * @return void
+	 */
+	function _close()
+	{
+		if($this->_connectionID) {
+			mysqli_close($this->_connectionID);
+		}
+		$this->_connectionID = false;
+	}
+
+	/**
+	 * Returns the largest length of data that can be inserted into a character field.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:charmax
+	 *
+	 * @return int
+	 */
+	function CharMax()
+	{
+		return 255;
+	}
+
+	/**
+	 * Returns the largest length of data that can be inserted into a text field.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:textmax
+	 *
+	 * @return int
+	 */
+	function TextMax()
+	{
+		return 4294967295;
+	}
+
+	function getCharSet()
+	{
+		if (!$this->_connectionID || !method_exists($this->_connectionID,'character_set_name')) {
+			return false;
+		}
+
+		$this->charSet = $this->_connectionID->character_set_name();
+		return $this->charSet ?: false;
+	}
+
+	function setCharSet($charset)
+	{
+		if (!$this->_connectionID || !method_exists($this->_connectionID,'set_charset')) {
+			return false;
+		}
+
+		if ($this->charSet !== $charset) {
+			if (!$this->_connectionID->set_charset($charset)) {
+				return false;
+			}
+			$this->getCharSet();
+		}
+		return true;
+	}
+
+}
+
+/**
+ * Class ADORecordSet_mysqli
+ */
+class ADORecordSet_mysqli extends ADORecordSet{
+
+	var $databaseType = "mysqli";
+	var $canSeek = true;
+
+	/** @var ADODB_mysqli The parent connection */
+	var $connection = false;
+
+	/** @var mysqli_result result link identifier */
+	var $_queryID;
+
+	function __construct($queryID, $mode = false)
+	{
+		if ($mode === false) {
+			global $ADODB_FETCH_MODE;
+			$mode = $ADODB_FETCH_MODE;
+		}
+
+		switch ($mode) {
+			case ADODB_FETCH_NUM:
+				$this->fetchMode = MYSQLI_NUM;
+				break;
+			case ADODB_FETCH_ASSOC:
+				$this->fetchMode = MYSQLI_ASSOC;
+				break;
+			case ADODB_FETCH_DEFAULT:
+			case ADODB_FETCH_BOTH:
+			default:
+				$this->fetchMode = MYSQLI_BOTH;
+				break;
+		}
+		$this->adodbFetchMode = $mode;
+		parent::__construct($queryID);
+	}
+
+	function _initrs()
+	{
+	global $ADODB_COUNTRECS;
+
+		$this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
+		$this->_numOfFields = @mysqli_num_fields($this->_queryID);
+	}
+
+/*
+1      = MYSQLI_NOT_NULL_FLAG
+2      = MYSQLI_PRI_KEY_FLAG
+4      = MYSQLI_UNIQUE_KEY_FLAG
+8      = MYSQLI_MULTIPLE_KEY_FLAG
+16     = MYSQLI_BLOB_FLAG
+32     = MYSQLI_UNSIGNED_FLAG
+64     = MYSQLI_ZEROFILL_FLAG
+128    = MYSQLI_BINARY_FLAG
+256    = MYSQLI_ENUM_FLAG
+512    = MYSQLI_AUTO_INCREMENT_FLAG
+1024   = MYSQLI_TIMESTAMP_FLAG
+2048   = MYSQLI_SET_FLAG
+32768  = MYSQLI_NUM_FLAG
+16384  = MYSQLI_PART_KEY_FLAG
+32768  = MYSQLI_GROUP_FLAG
+65536  = MYSQLI_UNIQUE_FLAG
+131072 = MYSQLI_BINCMP_FLAG
+*/
+
+	/**
+	 * Returns raw, database specific information about a field.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:recordset:fetchfield
+	 *
+	 * @param int $fieldOffset (Optional) The field number to get information for.
+	 *
+	 * @return ADOFieldObject|bool
+	 */
+	function FetchField($fieldOffset = -1)
+	{
+		$fieldnr = $fieldOffset;
+		if ($fieldOffset != -1) {
+			$fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
+		}
+		$o = @mysqli_fetch_field($this->_queryID);
+		if (!$o) return false;
+
+		//Fix for HHVM
+		if ( !isset($o->flags) ) {
+			$o->flags = 0;
+		}
+		/* Properties of an ADOFieldObject as set by MetaColumns */
+		$o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG;
+		$o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG;
+		$o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG;
+		$o->binary = $o->flags & MYSQLI_BINARY_FLAG;
+		// $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
+		$o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
+
+		/*
+		* Trivial method to cast class to ADOfieldObject
+		*/
+		$a = new ADOFieldObject;
+		foreach (get_object_vars($o) as $key => $name)
+			$a->$key = $name;
+		return $a;
+	}
+
+	/**
+	 * Reads a row in associative mode if the recordset fetch mode is numeric.
+	 * Using this function when the fetch mode is set to ADODB_FETCH_ASSOC may produce unpredictable results.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:getrowassoc
+	 *
+	 * @param int $upper Indicates whether the keys of the recordset should be upper case or lower case.
+	 *
+	 * @return array|bool
+	 */
+	function GetRowAssoc($upper = ADODB_ASSOC_CASE)
+	{
+		if ($this->fetchMode == MYSQLI_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
+			return $this->fields;
+		}
+		return ADORecordSet::getRowAssoc($upper);
+	}
+
+	/**
+	 * Returns a single field in a single row of the current recordset.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:recordset:fields
+	 *
+	 * @param string $colname The name of the field to retrieve.
+	 *
+	 * @return mixed
+	 */
+	function Fields($colname)
+	{
+		if ($this->fetchMode != MYSQLI_NUM) {
+			return @$this->fields[$colname];
+		}
+
+		if (!$this->bind) {
+			$this->bind = array();
+			for ($i = 0; $i < $this->_numOfFields; $i++) {
+				$o = $this->fetchField($i);
+				$this->bind[strtoupper($o->name)] = $i;
+			}
+		}
+		return $this->fields[$this->bind[strtoupper($colname)]];
+	}
+
+	/**
+	 * Adjusts the result pointer to an arbitrary row in the result.
+	 *
+	 * @param int $row The row to seek to.
+	 *
+	 * @return bool False if the recordset contains no rows, otherwise true.
+	 */
+	function _seek($row)
+	{
+		if ($this->_numOfRows == 0 || $row < 0) {
+			return false;
+		}
+
+		mysqli_data_seek($this->_queryID, $row);
+		$this->EOF = false;
+		return true;
+	}
+
+	/**
+	 * In databases that allow accessing of recordsets, retrieves the next set.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:recordset:nextrecordset
+	 *
+	 * @return bool
+	 */
+	function NextRecordSet()
+	{
+		global $ADODB_COUNTRECS;
+
+		mysqli_free_result($this->_queryID);
+		$this->_queryID = -1;
+		// Move to the next recordset, or return false if there is none. In a stored proc
+		// call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
+		// returns false. I think this is because the last "recordset" is actually just the
+		// return value of the stored proc (ie the number of rows affected).
+		if (!mysqli_next_result($this->connection->_connectionID)) {
+			return false;
+		}
+
+		// CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
+		$this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result($this->connection->_connectionID)
+			: @mysqli_use_result($this->connection->_connectionID);
+
+		if (!$this->_queryID) {
+			return false;
+		}
+
+		$this->_inited     = false;
+		$this->bind        = false;
+		$this->_currentRow = -1;
+		$this->init();
+		return true;
+	}
+
+	/**
+	 * Moves the cursor to the next record of the recordset from the current position.
+	 *
+	 * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:movenext
+	 *
+	 * @return bool False if there are no more records to move on to, otherwise true.
+	 */
+	function MoveNext()
+	{
+		if ($this->EOF) return false;
+		$this->_currentRow++;
+		$this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
+
+		if (is_array($this->fields)) {
+			$this->_updatefields();
+			return true;
+		}
+		$this->EOF = true;
+		return false;
+	}
+
+	/**
+	 * Attempt to fetch a result row using the current fetch mode and return whether or not this was successful.
+	 *
+	 * @return bool True if row was fetched successfully, otherwise false.
+	 */
+	function _fetch()
+	{
+		$this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
+		$this->_updatefields();
+		return is_array($this->fields);
+	}
+
+	/**
+	 * Frees the memory associated with a result.
+	 *
+	 * @return void
+	 */
+	function _close()
+	{
+		//if results are attached to this pointer from Stored Procedure calls, the next standard query will die 2014
+		//only a problem with persistent connections
+
+		if (isset($this->connection->_connectionID) && $this->connection->_connectionID) {
+			while (mysqli_more_results($this->connection->_connectionID)) {
+				mysqli_next_result($this->connection->_connectionID);
+			}
+		}
+
+		if ($this->_queryID instanceof mysqli_result) {
+			mysqli_free_result($this->_queryID);
+		}
+		$this->_queryID = false;
+	}
+
+/*
+
+0 = MYSQLI_TYPE_DECIMAL
+1 = MYSQLI_TYPE_CHAR
+1 = MYSQLI_TYPE_TINY
+2 = MYSQLI_TYPE_SHORT
+3 = MYSQLI_TYPE_LONG
+4 = MYSQLI_TYPE_FLOAT
+5 = MYSQLI_TYPE_DOUBLE
+6 = MYSQLI_TYPE_NULL
+7 = MYSQLI_TYPE_TIMESTAMP
+8 = MYSQLI_TYPE_LONGLONG
+9 = MYSQLI_TYPE_INT24
+10 = MYSQLI_TYPE_DATE
+11 = MYSQLI_TYPE_TIME
+12 = MYSQLI_TYPE_DATETIME
+13 = MYSQLI_TYPE_YEAR
+14 = MYSQLI_TYPE_NEWDATE
+245 = MYSQLI_TYPE_JSON
+247 = MYSQLI_TYPE_ENUM
+248 = MYSQLI_TYPE_SET
+249 = MYSQLI_TYPE_TINY_BLOB
+250 = MYSQLI_TYPE_MEDIUM_BLOB
+251 = MYSQLI_TYPE_LONG_BLOB
+252 = MYSQLI_TYPE_BLOB
+253 = MYSQLI_TYPE_VAR_STRING
+254 = MYSQLI_TYPE_STRING
+255 = MYSQLI_TYPE_GEOMETRY
+*/
+
+	/**
+	 * Get the MetaType character for a given field type.
+	 *
+	 * @param string|object $t The type to get the MetaType character for.
+	 * @param int $len (Optional) Redundant. Will always be set to -1.
+	 * @param bool|object $fieldobj (Optional)
+	 *
+	 * @return string The MetaType
+	 */
+	function metaType($t, $len = -1, $fieldobj = false)
+	{
+		if (is_object($t)) {
+			$fieldobj = $t;
+			$t = $fieldobj->type;
+			$len = $fieldobj->max_length;
+		}
+
+		$t = strtoupper($t);
+		/*
+		* Add support for custom actual types. We do this
+		* first, that allows us to override existing types
+		*/
+		if (array_key_exists($t,$this->connection->customActualTypes))
+			return  $this->connection->customActualTypes[$t];
+
+		$len = -1; // mysql max_length is not accurate
+		switch ($t) {
+			case 'STRING':
+			case 'CHAR':
+			case 'VARCHAR':
+			case 'TINYBLOB':
+			case 'TINYTEXT':
+			case 'ENUM':
+			case 'SET':
+
+			case MYSQLI_TYPE_TINY_BLOB :
+//			case MYSQLI_TYPE_CHAR :
+			case MYSQLI_TYPE_STRING :
+			case MYSQLI_TYPE_ENUM :
+			case MYSQLI_TYPE_SET :
+			case 253 :
+				if ($len <= $this->blobSize) {
+					return 'C';
+				}
+
+			case 'TEXT':
+			case 'LONGTEXT':
+			case 'MEDIUMTEXT':
+				return 'X';
+
+			// php_mysql extension always returns 'blob' even if 'text'
+			// so we have to check whether binary...
+			case 'IMAGE':
+			case 'LONGBLOB':
+			case 'BLOB':
+			case 'MEDIUMBLOB':
+
+			case MYSQLI_TYPE_BLOB :
+			case MYSQLI_TYPE_LONG_BLOB :
+			case MYSQLI_TYPE_MEDIUM_BLOB :
+				return !empty($fieldobj->binary) ? 'B' : 'X';
+
+			case 'YEAR':
+			case 'DATE':
+			case MYSQLI_TYPE_DATE :
+			case MYSQLI_TYPE_YEAR :
+				return 'D';
+
+			case 'TIME':
+			case 'DATETIME':
+			case 'TIMESTAMP':
+
+			case MYSQLI_TYPE_DATETIME :
+			case MYSQLI_TYPE_NEWDATE :
+			case MYSQLI_TYPE_TIME :
+			case MYSQLI_TYPE_TIMESTAMP :
+				return 'T';
+
+			case 'INT':
+			case 'INTEGER':
+			case 'BIGINT':
+			case 'TINYINT':
+			case 'MEDIUMINT':
+			case 'SMALLINT':
+
+			case MYSQLI_TYPE_INT24 :
+			case MYSQLI_TYPE_LONG :
+			case MYSQLI_TYPE_LONGLONG :
+			case MYSQLI_TYPE_SHORT :
+			case MYSQLI_TYPE_TINY :
+				if (!empty($fieldobj->primary_key)) {
+					return 'R';
+				}
+				return 'I';
+
+			// Added floating-point types
+			// Maybe not necessary.
+			case 'FLOAT':
+			case 'DOUBLE':
+//			case 'DOUBLE PRECISION':
+			case 'DECIMAL':
+			case 'DEC':
+			case 'FIXED':
+			default:
+
+
+				//if (!is_numeric($t)) echo "

--- Error in type matching $t -----

"; + return 'N'; + } + } + + +} // rs class + +/** + * Class ADORecordSet_array_mysqli + */ +class ADORecordSet_array_mysqli extends ADORecordSet_array +{ + /** + * Get the MetaType character for a given field type. + * + * @param string|object $t The type to get the MetaType character for. + * @param int $len (Optional) Redundant. Will always be set to -1. + * @param bool|object $fieldobj (Optional) + * + * @return string The MetaType + */ + function MetaType($t, $len = -1, $fieldobj = false) + { + if (is_object($t)) { + $fieldobj = $t; + $t = $fieldobj->type; + $len = $fieldobj->max_length; + } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + + $len = -1; // mysql max_length is not accurate + + switch ($t) { + case 'STRING': + case 'CHAR': + case 'VARCHAR': + case 'TINYBLOB': + case 'TINYTEXT': + case 'ENUM': + case 'SET': + + case MYSQLI_TYPE_TINY_BLOB : +// case MYSQLI_TYPE_CHAR : + case MYSQLI_TYPE_STRING : + case MYSQLI_TYPE_ENUM : + case MYSQLI_TYPE_SET : + case 253 : + if ($len <= $this->blobSize) { + return 'C'; + } + + case 'TEXT': + case 'LONGTEXT': + case 'MEDIUMTEXT': + return 'X'; + + // php_mysql extension always returns 'blob' even if 'text' + // so we have to check whether binary... + case 'IMAGE': + case 'LONGBLOB': + case 'BLOB': + case 'MEDIUMBLOB': + + case MYSQLI_TYPE_BLOB : + case MYSQLI_TYPE_LONG_BLOB : + case MYSQLI_TYPE_MEDIUM_BLOB : + return !empty($fieldobj->binary) ? 'B' : 'X'; + + case 'YEAR': + case 'DATE': + case MYSQLI_TYPE_DATE : + case MYSQLI_TYPE_YEAR : + return 'D'; + + case 'TIME': + case 'DATETIME': + case 'TIMESTAMP': + + case MYSQLI_TYPE_DATETIME : + case MYSQLI_TYPE_NEWDATE : + case MYSQLI_TYPE_TIME : + case MYSQLI_TYPE_TIMESTAMP : + return 'T'; + + case 'INT': + case 'INTEGER': + case 'BIGINT': + case 'TINYINT': + case 'MEDIUMINT': + case 'SMALLINT': + + case MYSQLI_TYPE_INT24 : + case MYSQLI_TYPE_LONG : + case MYSQLI_TYPE_LONGLONG : + case MYSQLI_TYPE_SHORT : + case MYSQLI_TYPE_TINY : + if (!empty($fieldobj->primary_key)) { + return 'R'; + } + return 'I'; + + // Added floating-point types + // Maybe not necessary. + case 'FLOAT': + case 'DOUBLE': +// case 'DOUBLE PRECISION': + case 'DECIMAL': + case 'DEC': + case 'FIXED': + default: + //if (!is_numeric($t)) echo "

--- Error in type matching $t -----

"; + return 'N'; + } + } +} + +} // if defined _ADODB_MYSQLI_LAYER diff --git a/www/include/adodb5/drivers/adodb-netezza.inc.php b/www/include/adodb/drivers/adodb-netezza.inc.php similarity index 74% rename from www/include/adodb5/drivers/adodb-netezza.inc.php rename to www/include/adodb/drivers/adodb-netezza.inc.php index af3a1a11..dc7c58e4 100644 --- a/www/include/adodb5/drivers/adodb-netezza.inc.php +++ b/www/include/adodb/drivers/adodb-netezza.inc.php @@ -1,21 +1,35 @@ + */ + // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -50,11 +64,6 @@ class ADODB_netezza extends ADODB_postgres64 { // http://bugs.php.net/bug.php?id=25404 - function __construct() - { - - } - function MetaColumns($table,$upper=true) { @@ -141,11 +150,6 @@ class ADORecordSet_netezza extends ADORecordSet_postgres64 var $databaseType = "netezza"; var $canSeek = true; - function __construct($queryID,$mode=false) - { - parent::__construct($queryID,$mode); - } - // _initrs modified to disable blob handling function _initrs() { diff --git a/www/include/adodb5/drivers/adodb-oci8.inc.php b/www/include/adodb/drivers/adodb-oci8.inc.php similarity index 90% rename from www/include/adodb5/drivers/adodb-oci8.inc.php rename to www/include/adodb/drivers/adodb-oci8.inc.php index 928d1b84..c1f4e502 100644 --- a/www/include/adodb5/drivers/adodb-oci8.inc.php +++ b/www/include/adodb/drivers/adodb-oci8.inc.php @@ -1,20 +1,25 @@ - - 13 Nov 2000 jlim - removed all ora_* references. -*/ +/** + * FileDescription + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author John Lim + * @author George Fourlanos + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -89,7 +94,6 @@ class ADODB_oci8 extends ADOConnection { var $connectSID = false; var $_bind = false; var $_nestedSQL = true; - var $_hasOciFetchStatement = false; var $_getarray = false; // currently not working var $leftOuter = ''; // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER var $session_sharing_force_blob = false; // alter session on updateblob if set to true @@ -103,13 +107,20 @@ class ADODB_oci8 extends ADOConnection { // var $ansiOuter = true; // if oracle9 - function __construct() - { - $this->_hasOciFetchStatement = ADODB_PHPVER >= 0x4200; - if (defined('ADODB_EXTENSION')) { - $this->rsPrefix .= 'ext_'; - } - } + /* + * Legacy compatibility for sequence names for emulated auto-increments + */ + public $useCompactAutoIncrements = false; + + /* + * Defines the schema name for emulated auto-increment columns + */ + public $schema = false; + + /* + * Defines the prefix for emulated auto-increment columns + */ + public $seqPrefix = 'SEQ_'; /* function MetaColumns($table, $normalize=true) added by smondino@users.sourceforge.net*/ function MetaColumns($table, $normalize=true) @@ -308,6 +319,42 @@ function IfNull( $field, $ifNull ) return " NVL($field, $ifNull) "; // if Oracle } + protected function _insertID($table = '', $column = '') + { + + if (!$this->seqField) + return false; + + if ($this->schema) + { + $t = strpos($table,'.'); + if ($t !== false) + $tab = substr($table,$t+1); + else + $tab = $table; + + if ($this->useCompactAutoIncrements) + $tab = sprintf('%u',crc32(strtolower($tab))); + + $seqname = $this->schema.'.'.$this->seqPrefix.$tab; + } + else + { + if ($this->useCompactAutoIncrements) + $table = sprintf('%u',crc32(strtolower($table))); + + $seqname = $this->seqPrefix.$table; + } + + if (strlen($seqname) > 30) + /* + * We cannot successfully identify the sequence + */ + return false; + + return $this->getOne("SELECT $seqname.currval FROM dual"); + } + // format and return date string in database date format function DBDate($d,$isfld=false) { @@ -709,6 +756,8 @@ function GetRandRow($sql, $arr = false) */ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; // Since the methods used to limit the number of returned rows rely // on modifying the provided SQL query, we can't work with prepared // statements so we just extract the SQL string. @@ -742,6 +791,11 @@ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) $nrows += $offset; } $sql = "select * from (".$sql.") where rownum <= :adodb_offset"; + + // If non-bound statement, $inputarr is false + if (!$inputarr) { + $inputarr = array(); + } $inputarr['adodb_offset'] = $nrows; $nrows = -1; } @@ -924,9 +978,12 @@ function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB') /** * Execute SQL * - * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text) - * @param [inputarr] holds the input data to bind to. Null elements will be set to null. - * @return RecordSet or false + * @param string|array $sql SQL statement to execute, or possibly an array holding + * prepared statement ($sql[0] will hold sql text). + * @param array|false $inputarr holds the input data to bind to. + * Null elements will be set to null. + * + * @return ADORecordSet|false */ function Execute($sql,$inputarr=false) { @@ -945,7 +1002,7 @@ function Execute($sql,$inputarr=false) $element0 = reset($inputarr); $array2d = $this->bulkBind && is_array($element0) && !is_object(reset($element0)); - # see http://phplens.com/lens/lensforum/msgs.php?id=18786 + # see PHPLens Issue No: 18786 if ($array2d || !$this->_bindInputArray) { # is_object check because oci8 descriptors can be passed in @@ -1045,6 +1102,22 @@ function Prepare($sql,$cursor=false) return array($sql,$stmt,0,$BINDNUM); } + function releaseStatement(&$stmt) + { + if (is_array($stmt) + && isset($stmt[1]) + && is_resource($stmt[1]) + && oci_free_statement($stmt[1]) + ) { + // Clearing the resource to avoid it being of type Unknown + $stmt[1] = null; + return true; + } + + // Not a valid prepared statement + return false; + } + /* Call an oracle stored procedure and returns a cursor variable as a recordset. Concept by Robert Tuttle robert@ud.com @@ -1192,12 +1265,12 @@ function Param($name,$type='C') * $db->Parameter($stmt,$group,'group'); * $db->Execute($stmt); * - * @param $stmt Statement returned by Prepare() or PrepareSP(). + * @param $stmt Statement returned by {@see Prepare()} or {@see PrepareSP()}. * @param $var PHP variable to bind to * @param $name Name of stored procedure variable name to bind to. - * @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. - * @param [$maxLen] Holds an maximum length of the variable. - * @param [$type] The data type of $var. Legal values depend on driver. + * @param bool $isOutput Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. + * @param int $maxLen Holds an maximum length of the variable. + * @param mixed $type The data type of $var. Legal values depend on driver. * * @link http://php.net/oci_bind_by_name */ @@ -1435,16 +1508,17 @@ function MetaPrimaryKeys($table, $owner=false,$internalKey=false) } /** - * returns assoc array where keys are tables, and values are foreign keys + * Returns a list of Foreign Keys associated with a specific table. * - * @param str $table - * @param str $owner [optional][default=NULL] - * @param bool $upper [optional][discarded] - * @return mixed[] Array of foreign key information + * @param string $table + * @param string $owner + * @param bool $upper discarded + * @param bool $associative discarded * - * @link http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html + * @return string[]|false An array where keys are tables, and values are foreign keys; + * false if no foreign keys could be found. */ - function MetaForeignKeys($table, $owner=false, $upper=false) + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { global $ADODB_FETCH_MODE; @@ -1495,37 +1569,27 @@ function TextMax() } /** - * Quotes a string. - * An example is $db->qstr("Don't bother",magic_quotes_runtime()); + * Correctly quotes a string so that all strings are escaped. + * We prefix and append to the string single-quotes. + * An example is $db->qstr("Don't bother"); + * + * @param string $s The string to quote + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. * - * @param string $s the string to quote - * @param bool $magic_quotes if $s is GET/POST var, set to get_magic_quotes_gpc(). - * This undoes the stupidity of magic quotes for GPC. + * @return string Quoted string to be sent back to database * - * @return string quoted string to be sent back to database + * @noinspection PhpUnusedParameterInspection */ - function qstr($s,$magic_quotes=false) + function qStr($s, $magic_quotes=false) { - //$nofixquotes=false; - - if ($this->noNullStrings && strlen($s)==0) { + if ($this->noNullStrings && strlen($s) == 0) { $s = ' '; } - if (!$magic_quotes) { - if ($this->replaceQuote[0] == '\\'){ - $s = str_replace('\\','\\\\',$s); - } - return "'".str_replace("'",$this->replaceQuote,$s)."'"; - } - - // undo magic quotes for " unless sybase is on - if (!ini_get('magic_quotes_sybase')) { - $s = str_replace('\\"','"',$s); - $s = str_replace('\\\\','\\',$s); - return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; - } else { - return "'".$s."'"; + if ($this->replaceQuote[0] == '\\'){ + $s = str_replace('\\','\\\\',$s); } + return "'" . str_replace("'", $this->replaceQuote, $s) . "'"; } } @@ -1564,6 +1628,12 @@ function __construct($queryID,$mode=false) $this->_queryID = $queryID; } + /** + * Overrides the core destructor method as that causes problems here + * + * @return void + */ + function __destruct() {} function Init() { @@ -1583,7 +1653,7 @@ function Init() /* // based on idea by Gaetano Giunta to detect unusual oracle errors - // see http://phplens.com/lens/lensforum/msgs.php?id=6771 + // see PHPLens Issue No: 6771 $err = oci_error($this->_queryID); if ($err && $this->connection->debug) { ADOConnection::outp($err); @@ -1743,7 +1813,8 @@ function _close() oci_free_cursor($this->_refcursor); $this->_refcursor = false; } - @oci_free_statement($this->_queryID); + if (is_resource($this->_queryID)) + @oci_free_statement($this->_queryID); $this->_queryID = false; } @@ -1764,7 +1835,12 @@ function MetaType($t, $len=-1, $fieldobj=false) $len = $fieldobj->max_length; } - switch (strtoupper($t)) { + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + + switch ($t) { case 'VARCHAR': case 'VARCHAR2': case 'CHAR': @@ -1800,16 +1876,12 @@ function MetaType($t, $len=-1, $fieldobj=false) return 'I'; default: - return 'N'; + return ADODB_DEFAULT_METATYPE; } } } class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 { - function __construct($queryID,$mode=false) - { - parent::__construct($queryID, $mode); - } function MoveNext() { diff --git a/www/include/adodb5/drivers/adodb-oci805.inc.php b/www/include/adodb/drivers/adodb-oci805.inc.php similarity index 56% rename from www/include/adodb5/drivers/adodb-oci805.inc.php rename to www/include/adodb/drivers/adodb-oci805.inc.php index 112e9ecc..01958282 100644 --- a/www/include/adodb5/drivers/adodb-oci805.inc.php +++ b/www/include/adodb/drivers/adodb-oci805.inc.php @@ -1,18 +1,27 @@ - - Should some emulation of RecordCount() be implemented? - -*/ +/** + * Portable version of Oracle oci8 driver + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * Portable version of oci8 driver, to make it more similar to other database + * drivers. The main differences are + * 1. that the OCI_ASSOC names are in lowercase instead of uppercase. + * 2. bind variables are mapped using ? instead of : + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -30,12 +35,6 @@ class ADODB_oci8po extends ADODB_oci8 { var $metaColumnsSQL = "select lower(cname),coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net var $metaTablesSQL = "select lower(table_name),table_type from cat where table_type in ('TABLE','VIEW')"; - function __construct() - { - $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200; - # oci8po does not support adodb extension: adodb_movenext() - } - function Param($name,$type='C') { return '?'; @@ -81,29 +80,89 @@ function _query($sql,$inputarr=false) $arr['bind'.$i++] = $v; } } else { - // Need to identify if the ? is inside a quoted string, and if - // so not use it as a bind variable - preg_match_all('/".*\??"|\'.*\?.*?\'/', $sql, $matches); - foreach($matches[0] as $qmMatch){ - $qmReplace = str_replace('?', '-QUESTIONMARK-', $qmMatch); - $sql = str_replace($qmMatch, $qmReplace, $sql); - } - - // Replace parameters if any were found - $sqlarr = explode('?',$sql); - if(count($sqlarr) > 1) { - $sql = $sqlarr[0]; - - foreach ($inputarr as $k => $v) { - $sql .= ":$k" . $sqlarr[++$i]; - } - } - - $sql = str_replace('-QUESTIONMARK-', '?', $sql); + $sql = $this->extractBinds($sql,$inputarr); } } return ADODB_oci8::_query($sql,$inputarr); } + + /** + * Replaces compatibility bind markers with oracle ones and returns a + * valid sql statement + * + * This replaces a regexp based section of code that has been subject + * to numerous tweaks, as more extreme test cases have appeared. This + * is now done this like this to help maintainability and avoid the + * need to rely on regexp experienced maintainers + * + * @param string $sql The sql statement + * @param string[] $inputarr The bind array + * + * @return string The modified statement + */ + private function extractBinds($sql,$inputarr) + { + $inString = false; + $escaped = 0; + $sqlLength = strlen($sql) - 1; + $newSql = ''; + $bindCount = 0; + + /* + * inputarr is the passed in bind list, which is associative, but + * we only want the keys here + */ + $inputKeys = array_keys($inputarr); + + + for ($i=0;$i<=$sqlLength;$i++) + { + /* + * find the next character of the string + */ + $c = $sql[$i]; + + if ($c == "'" && !$inString && $escaped==0) + /* + * Found the start of a string inside the statement + */ + $inString = true; + elseif ($c == "\\" && $escaped==0) + /* + * The next character will be escaped + */ + $escaped = 1; + elseif ($c == "'" && $inString && $escaped==0) + /* + * We found the end of the string + */ + $inString = false; + + if ($escaped == 2) + $escaped = 0; + + if ($escaped==0 && !$inString && $c == '?') + /* + * We found a bind symbol, replace it with the oracle equivalent + */ + $newSql .= ':' . $inputKeys[$bindCount++]; + else + /* + * Add the current character the pile + */ + $newSql .= $c; + + if ($escaped == 1) + /* + * We have just found an escape character, make sure we ignore the + * next one that comes along, it might be a ' character + */ + $escaped = 2; + } + + return $newSql; + + } } /*-------------------------------------------------------------------------------------- @@ -114,11 +173,6 @@ class ADORecordset_oci8po extends ADORecordset_oci8 { var $databaseType = 'oci8po'; - function __construct($queryID,$mode=false) - { - parent::__construct($queryID,$mode); - } - function Fields($colname) { if ($this->fetchMode & OCI_ASSOC) return $this->fields[$colname]; diff --git a/www/include/adodb5/drivers/adodb-oci8quercus.inc.php b/www/include/adodb/drivers/adodb-oci8quercus.inc.php similarity index 66% rename from www/include/adodb5/drivers/adodb-oci8quercus.inc.php rename to www/include/adodb/drivers/adodb-oci8quercus.inc.php index 1940e802..f9312c9d 100644 --- a/www/include/adodb5/drivers/adodb-oci8quercus.inc.php +++ b/www/include/adodb/drivers/adodb-oci8quercus.inc.php @@ -1,23 +1,23 @@ - - Should some emulation of RecordCount() be implemented? - -*/ +/** + * Oracle "quercus" driver. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -28,10 +28,6 @@ class ADODB_oci8quercus extends ADODB_oci8 { var $databaseType = 'oci8quercus'; var $dataProvider = 'oci8'; - function __construct() - { - } - } /*-------------------------------------------------------------------------------------- @@ -42,11 +38,6 @@ class ADORecordset_oci8quercus extends ADORecordset_oci8 { var $databaseType = 'oci8quercus'; - function __construct($queryID,$mode=false) - { - parent::__construct($queryID,$mode); - } - function _FetchField($fieldOffset = -1) { global $QUERCUS; diff --git a/www/include/adodb5/drivers/adodb-odbc.inc.php b/www/include/adodb/drivers/adodb-odbc.inc.php similarity index 83% rename from www/include/adodb5/drivers/adodb-odbc.inc.php rename to www/include/adodb/drivers/adodb-odbc.inc.php index efaa5bb1..a9705e2d 100644 --- a/www/include/adodb5/drivers/adodb-odbc.inc.php +++ b/www/include/adodb/drivers/adodb-odbc.inc.php @@ -1,22 +1,41 @@ _haserrorfunctions = ADODB_PHPVER >= 0x4050; - $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200; - } + function __construct() {} // returns true or false function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) { - global $php_errormsg; - if (!function_exists('odbc_connect')) return null; if (!empty($argDatabasename) && stristr($argDSN, 'Database=') === false) { @@ -61,10 +77,10 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) $argDSN .= 'Database='.$argDatabasename; } - if (isset($php_errormsg)) $php_errormsg = ''; + $last_php_error = $this->resetLastError(); if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword); else $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,$this->curmode); - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); if (isset($this->connectStmt)) $this->Execute($this->connectStmt); return $this->_connectionID != false; @@ -73,12 +89,10 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) // returns true or false function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) { - global $php_errormsg; - if (!function_exists('odbc_connect')) return null; - if (isset($php_errormsg)) $php_errormsg = ''; - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + $last_php_error = $this->resetLastError(); + $this->_errorMsg = ''; if ($this->debug && $argDatabasename) { ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter."); } @@ -86,7 +100,7 @@ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword); else $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,$this->curmode); - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); if ($this->_connectionID && $this->autoRollback) @odbc_rollback($this->_connectionID); if (isset($this->connectStmt)) $this->Execute($this->connectStmt); @@ -97,7 +111,7 @@ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) function ServerInfo() { - if (!empty($this->host) && ADODB_PHPVER >= 0x4300) { + if (!empty($this->host)) { $dsn = strtoupper($this->host); $first = true; $found = false; @@ -184,30 +198,25 @@ function GenID($seq='adodbseq',$start=1) function ErrorMsg() { - if ($this->_haserrorfunctions) { - if ($this->_errorMsg !== false) return $this->_errorMsg; - if (empty($this->_connectionID)) return @odbc_errormsg(); - return @odbc_errormsg($this->_connectionID); - } else return ADOConnection::ErrorMsg(); + if ($this->_errorMsg !== false) return $this->_errorMsg; + if (empty($this->_connectionID)) return @odbc_errormsg(); + return @odbc_errormsg($this->_connectionID); } function ErrorNo() { + if ($this->_errorCode !== false) { + // bug in 4.0.6, error number can be corrupted string (should be 6 digits) + return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode; + } - if ($this->_haserrorfunctions) { - if ($this->_errorCode !== false) { - // bug in 4.0.6, error number can be corrupted string (should be 6 digits) - return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode; - } - - if (empty($this->_connectionID)) $e = @odbc_error(); - else $e = @odbc_error($this->_connectionID); + if (empty($this->_connectionID)) $e = @odbc_error(); + else $e = @odbc_error($this->_connectionID); - // bug in 4.0.6, error number can be corrupted string (should be 6 digits) - // so we check and patch - if (strlen($e)<=2) return 0; - return $e; - } else return ADOConnection::ErrorNo(); + // bug in 4.0.6, error number can be corrupted string (should be 6 digits) + // so we check and patch + if (strlen($e)<=2) return 0; + return $e; } @@ -262,7 +271,6 @@ function MetaPrimaryKeys($table,$owner=false) $ADODB_FETCH_MODE = $savem; if (!$rs) return false; - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; $arr = $rs->GetArray(); $rs->Close(); @@ -291,7 +299,6 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false) $false = false; return $false; } - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; $arr = $rs->GetArray(); //print_r($arr); @@ -394,12 +401,11 @@ function MetaColumns($table, $normalize=true) $savem = $ADODB_FETCH_MODE; $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - /*if (false) { // after testing, confirmed that the following does not work becoz of a bug + /*if (false) { // after testing, confirmed that the following does not work because of a bug $qid2 = odbc_tables($this->_connectionID); $rs = new ADORecordSet_odbc($qid2); $ADODB_FETCH_MODE = $savem; if (!$rs) return false; - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; $rs->_fetch(); while (!$rs->EOF) { @@ -438,7 +444,6 @@ function MetaColumns($table, $normalize=true) $ADODB_FETCH_MODE = $savem; if (!$rs) return $false; - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; $rs->_fetch(); $retarr = array(); @@ -463,7 +468,16 @@ function MetaColumns($table, $normalize=true) if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { $fld = new ADOFieldObject(); $fld->name = $rs->fields[3]; - $fld->type = $this->ODBCTypes($rs->fields[4]); + if ($this->metaColumnsReturnType == METACOLUMNS_RETURNS_META) + /* + * This is the broken, original value + */ + $fld->type = $this->ODBCTypes($rs->fields[4]); + else + /* + * This is the correct new value + */ + $fld->type = $rs->fields[4]; // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp // access uses precision to store length for char/varchar @@ -503,9 +517,8 @@ function Prepare($sql) /* returns queryID or false */ function _query($sql,$inputarr=false) { - GLOBAL $php_errormsg; - if (isset($php_errormsg)) $php_errormsg = ''; - $this->_error = ''; + $last_php_error = $this->resetLastError(); + $this->_errorMsg = ''; if ($inputarr) { if (is_array($sql)) { @@ -514,17 +527,15 @@ function _query($sql,$inputarr=false) $stmtid = odbc_prepare($this->_connectionID,$sql); if ($stmtid == false) { - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); return false; } } if (! odbc_execute($stmtid,$inputarr)) { //@odbc_free_result($stmtid); - if ($this->_haserrorfunctions) { - $this->_errorMsg = odbc_errormsg(); - $this->_errorCode = odbc_error(); - } + $this->_errorMsg = odbc_errormsg(); + $this->_errorCode = odbc_error(); return false; } @@ -532,10 +543,8 @@ function _query($sql,$inputarr=false) $stmtid = $sql[1]; if (!odbc_execute($stmtid)) { //@odbc_free_result($stmtid); - if ($this->_haserrorfunctions) { - $this->_errorMsg = odbc_errormsg(); - $this->_errorCode = odbc_error(); - } + $this->_errorMsg = odbc_errormsg(); + $this->_errorCode = odbc_error(); return false; } } else @@ -552,17 +561,11 @@ function _query($sql,$inputarr=false) odbc_longreadlen($stmtid,$this->maxblobsize); } - if ($this->_haserrorfunctions) { - $this->_errorMsg = ''; - $this->_errorCode = 0; - } else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + $this->_errorMsg = ''; + $this->_errorCode = 0; } else { - if ($this->_haserrorfunctions) { - $this->_errorMsg = odbc_errormsg(); - $this->_errorCode = odbc_error(); - } else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + $this->_errorMsg = odbc_errormsg(); + $this->_errorCode = odbc_error(); } return $stmtid; } @@ -606,7 +609,6 @@ class ADORecordSet_odbc extends ADORecordSet { var $databaseType = "odbc"; var $dataProvider = "odbc"; var $useFetchArray; - var $_has_stupid_odbc_fetch_api_change; function __construct($id,$mode=false) { @@ -664,7 +666,6 @@ function _initrs() // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 if ($this->_numOfRows == 0) $this->_numOfRows = -1; //$this->useFetchArray = $this->connection->useFetchArray; - $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200; } function _seek($row) @@ -715,12 +716,7 @@ function MoveNext() function _fetch() { $this->fields = false; - if ($this->_has_stupid_odbc_fetch_api_change) - $rez = @odbc_fetch_into($this->_queryID,$this->fields); - else { - $row = 0; - $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields); - } + $rez = @odbc_fetch_into($this->_queryID,$this->fields); if ($rez) { if ($this->fetchMode & ADODB_FETCH_ASSOC) { $this->fields = $this->GetRowAssoc(); diff --git a/www/include/adodb5/drivers/adodb-odbc_db2.inc.php b/www/include/adodb/drivers/adodb-odbc_db2.inc.php similarity index 65% rename from www/include/adodb5/drivers/adodb-odbc_db2.inc.php rename to www/include/adodb/drivers/adodb-odbc_db2.inc.php index fa6d8b84..8f0e60cb 100644 --- a/www/include/adodb5/drivers/adodb-odbc_db2.inc.php +++ b/www/include/adodb/drivers/adodb-odbc_db2.inc.php @@ -1,98 +1,29 @@ curMode = SQL_CUR_USE_ODBC; -$db->Connect($dsn, $userid, $pwd); - - - -USING CLI INTERFACE -=================== - -I have had reports that the $host and $database params have to be reversed in -Connect() when using the CLI interface. From Halmai Csongor csongor.halmai#nexum.hu: - -> The symptom is that if I change the database engine from postgres or any other to DB2 then the following -> connection command becomes wrong despite being described this version to be correct in the docs. -> -> $connection_object->Connect( $DATABASE_HOST, $DATABASE_AUTH_USER_NAME, $DATABASE_AUTH_PASSWORD, $DATABASE_NAME ) -> -> In case of DB2 I had to swap the first and last arguments in order to connect properly. - - -System Error 5 -============== -IF you get a System Error 5 when trying to Connect/Load, it could be a permission problem. Give the user connecting -to DB2 full rights to the DB2 SQLLIB directory, and place the user in the DBUSERS group. -*/ +/** + * DB2 driver via ODBC + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); if (!defined('_ADODB_ODBC_LAYER')) { - include(ADODB_DIR."/drivers/adodb-odbc.inc.php"); + include_once(ADODB_DIR."/drivers/adodb-odbc.inc.php"); } if (!defined('ADODB_ODBC_DB2')){ define('ADODB_ODBC_DB2',1); @@ -131,7 +62,7 @@ function ServerInfo() return array('description'=>'DB2 ODBC driver', 'version'=>$vers); } - function _insertid() + protected function _insertID($table = '', $column = '') { return $this->GetOne($this->identitySQL); } @@ -157,7 +88,6 @@ function MetaTables($ttype=false,$showSchema=false, $qtable="%", $qschema="%") $false = false; return $false; } - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; $arr = $rs->GetArray(); //print_r($arr); @@ -306,11 +236,6 @@ class ADORecordSet_odbc_db2 extends ADORecordSet_odbc { var $databaseType = "db2"; - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } - function MetaType($t,$len=-1,$fieldobj=false) { if (is_object($t)) { @@ -361,7 +286,7 @@ function MetaType($t,$len=-1,$fieldobj=false) case 'I': return 'I'; - default: return 'N'; + default: return ADODB_DEFAULT_METATYPE; } } } diff --git a/www/include/adodb5/drivers/adodb-odbc_mssql.inc.php b/www/include/adodb/drivers/adodb-odbc_mssql.inc.php similarity index 77% rename from www/include/adodb5/drivers/adodb-odbc_mssql.inc.php rename to www/include/adodb/drivers/adodb-odbc_mssql.inc.php index aa643168..9f53d3d7 100644 --- a/www/include/adodb5/drivers/adodb-odbc_mssql.inc.php +++ b/www/include/adodb/drivers/adodb-odbc_mssql.inc.php @@ -1,24 +1,29 @@ curmode = SQL_CUR_USE_ODBC; - } - // crashes php... function ServerInfo() { @@ -72,7 +71,7 @@ function IfNull( $field, $ifNull ) return " ISNULL($field, $ifNull) "; // if MS SQL Server } - function _insertid() + protected function _insertID($table = '', $column = '') { // SCOPE_IDENTITY() // Returns the last IDENTITY value inserted into an IDENTITY column in @@ -82,8 +81,7 @@ function _insertid() return $this->GetOne($this->identitySQL); } - - function MetaForeignKeys($table, $owner=false, $upper=false) + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { global $ADODB_FETCH_MODE; @@ -280,6 +278,8 @@ function MetaPrimaryKeys($table, $owner = false) function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; if ($nrows > 0 && $offset <= 0) { $sql = preg_replace( '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql); @@ -350,14 +350,89 @@ function SQLDate($fmt, $col=false) return $s; } + /** + * Returns a substring of a varchar type field + * + * The SQL server version varies because the length is mandatory, so + * we append a reasonable string length + * + * @param string $fld The field to sub-string + * @param int $start The start point + * @param int $length An optional length + * + * @return The SQL text + */ + function substr($fld,$start,$length=0) + { + if ($length == 0) + /* + * The length available to varchar is 2GB, but that makes no + * sense in a substring, so I'm going to arbitrarily limit + * the length to 1K, but you could change it if you want + */ + $length = 1024; + + $text = "SUBSTRING($fld,$start,$length)"; + return $text; + } + + /** + * Returns the maximum size of a MetaType C field. Because of the + * database design, SQL Server places no limits on the size of data inserted + * Although the actual limit is 2^31-1 bytes. + * + * @return int + */ + function charMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + /** + * Returns the maximum size of a MetaType X field. Because of the + * database design, SQL Server places no limits on the size of data inserted + * Although the actual limit is 2^31-1 bytes. + * + * @return int + */ + function textMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + // returns concatenated string + // MSSQL requires integers to be cast as strings + // automatically cast every datatype to VARCHAR(255) + // @author David Rogers (introspectshun) + function Concat() + { + $s = ""; + $arr = func_get_args(); + + // Split single record on commas, if possible + if (sizeof($arr) == 1) { + foreach ($arr as $arg) { + $args = explode(',', $arg); + } + $arr = $args; + } + + array_walk( + $arr, + function(&$value, $key) { + $value = "CAST(" . $value . " AS VARCHAR(255))"; + } + ); + $s = implode('+',$arr); + if (sizeof($arr) > 0) return "$s"; + + return ''; + } + } class ADORecordSet_odbc_mssql extends ADORecordSet_odbc { var $databaseType = 'odbc_mssql'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } diff --git a/www/include/adodb/drivers/adodb-odbc_mssql2012.inc.php b/www/include/adodb/drivers/adodb-odbc_mssql2012.inc.php new file mode 100644 index 00000000..79fa3251 --- /dev/null +++ b/www/include/adodb/drivers/adodb-odbc_mssql2012.inc.php @@ -0,0 +1,37 @@ +resetLastError(); $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,SQL_CUR_USE_ODBC ); - $this->_errorMsg = $php_errormsg; + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'"); //if ($this->_connectionID) odbc_autocommit($this->_connectionID,true); @@ -89,10 +94,9 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) // returns true or false function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) { - global $php_errormsg; - $php_errormsg = ''; + $last_php_error = $this->resetLastError(); $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,SQL_CUR_USE_ODBC ); - $this->_errorMsg = $php_errormsg; + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'"); //if ($this->_connectionID) odbc_autocommit($this->_connectionID,true); @@ -104,8 +108,4 @@ class ADORecordSet_odbc_oracle extends ADORecordSet_odbc { var $databaseType = 'odbc_oracle'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } diff --git a/www/include/adodb5/drivers/adodb-odbtp.inc.php b/www/include/adodb/drivers/adodb-odbtp.inc.php similarity index 95% rename from www/include/adodb5/drivers/adodb-odbtp.inc.php rename to www/include/adodb/drivers/adodb-odbtp.inc.php index ec374a5d..41bd0873 100644 --- a/www/include/adodb5/drivers/adodb-odbtp.inc.php +++ b/www/include/adodb/drivers/adodb-odbtp.inc.php @@ -1,15 +1,26 @@ +/** + * ODBTP driver + * + * @deprecated will be removed in ADOdb version 6 + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author stefan bogdan + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -35,10 +46,6 @@ class ADODB_odbtp extends ADOConnection{ var $_canPrepareSP = false; var $_dontPoolDBC = true; - function __construct() - { - } - function ServerInfo() { return array('description' => @odbtp_get_attr( ODB_ATTR_DBMSNAME, $this->_connectionID), @@ -80,7 +87,7 @@ function DBTimeStamp($d,$isfld=false) } */ - function _insertid() + protected function _insertID($table = '', $column = '') { // SCOPE_IDENTITY() // Returns the last IDENTITY value inserted into an IDENTITY column in @@ -386,7 +393,7 @@ function MetaPrimaryKeys($table, $owner='') return $arr2; } - function MetaForeignKeys($table, $owner='', $upper=false) + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { global $ADODB_FETCH_MODE; @@ -609,9 +616,8 @@ function IfNull( $field, $ifNull ) function _query($sql,$inputarr=false) { - global $php_errormsg; - - $this->_errorMsg = false; + $last_php_error = $this->resetLastError(); + $this->_errorMsg = false; $this->_errorCode = false; if ($inputarr) { @@ -620,7 +626,7 @@ function _query($sql,$inputarr=false) } else { $stmtid = @odbtp_prepare($sql,$this->_connectionID); if ($stmtid == false) { - $this->_errorMsg = $php_errormsg; + $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); return false; } } @@ -793,48 +799,28 @@ class ADORecordSet_odbtp_mssql extends ADORecordSet_odbtp { var $databaseType = 'odbtp_mssql'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } class ADORecordSet_odbtp_access extends ADORecordSet_odbtp { var $databaseType = 'odbtp_access'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } class ADORecordSet_odbtp_vfp extends ADORecordSet_odbtp { var $databaseType = 'odbtp_vfp'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } class ADORecordSet_odbtp_oci8 extends ADORecordSet_odbtp { var $databaseType = 'odbtp_oci8'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } class ADORecordSet_odbtp_sybase extends ADORecordSet_odbtp { var $databaseType = 'odbtp_sybase'; - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } } diff --git a/www/include/adodb/drivers/adodb-odbtp_unicode.inc.php b/www/include/adodb/drivers/adodb-odbtp_unicode.inc.php new file mode 100644 index 00000000..190c3ab5 --- /dev/null +++ b/www/include/adodb/drivers/adodb-odbtp_unicode.inc.php @@ -0,0 +1,41 @@ + + * Also, all SQL query strings must be submitted as UTF-8 encoded text. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Robert Twitty + */ + +// security - hide paths +if (!defined('ADODB_DIR')) die(); + +if (!defined('_ADODB_ODBTP_LAYER')) { + include_once(ADODB_DIR."/drivers/adodb-odbtp.inc.php"); +} + +class ADODB_odbtp_unicode extends ADODB_odbtp { + var $databaseType = 'odbtp'; + var $_useUnicodeSQL = true; +} diff --git a/www/include/adodb5/drivers/adodb-oracle.inc.php b/www/include/adodb/drivers/adodb-oracle.inc.php similarity index 91% rename from www/include/adodb5/drivers/adodb-oracle.inc.php rename to www/include/adodb/drivers/adodb-oracle.inc.php index ca737d66..1a2735b1 100644 --- a/www/include/adodb5/drivers/adodb-oracle.inc.php +++ b/www/include/adodb/drivers/adodb-oracle.inc.php @@ -1,18 +1,25 @@ pdoOptions = [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]; + */ + public $pdoParameters = array(); function _UpdatePDO() { @@ -102,6 +103,7 @@ function _UpdatePDO() $this->random = $d->random; $this->concat_operator = $d->concat_operator; $this->nameQuote = $d->nameQuote; + $this->arrayClass = $d->arrayClass; $this->hasGenID = $d->hasGenID; $this->_genIDSQL = $d->_genIDSQL; @@ -144,12 +146,22 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis case 'oci': case 'pgsql': case 'sqlite': + case 'firebird': default: $argDSN .= ';dbname='.$argDatabasename; } } + /* + * Configure for persistent connection if required, + * by adding the the pdo parameter into any provided + * ones + */ + if ($persist) { + $this->pdoParameters[\PDO::ATTR_PERSISTENT] = true; + } + try { - $this->_connectionID = new PDO($argDSN, $argUsername, $argPassword); + $this->_connectionID = new \PDO($argDSN, $argUsername, $argPassword, $this->pdoParameters); } catch (Exception $e) { $this->_connectionID = false; $this->_errorno = -1; @@ -175,6 +187,16 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis //$this->_connectionID->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT ); $this->_connectionID->setAttribute(PDO::ATTR_CASE,$m); + // Now merge in any provided attributes for PDO + foreach ($this->connectionParameters as $options) { + foreach($options as $k=>$v) { + if ($this->debug) { + ADOconnection::outp('Setting attribute: ' . $k . ' to ' . $v); + } + $this->_connectionID->setAttribute($k,$v); + } + } + $class = 'ADODB_pdo_'.$this->dsnType; //$this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true); switch($this->dsnType) { @@ -184,6 +206,8 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis case 'pgsql': case 'sqlite': case 'sqlsrv': + case 'firebird': + case 'dblib': include_once(ADODB_DIR.'/drivers/adodb-pdo_'.$this->dsnType.'.inc.php'); break; } @@ -210,10 +234,27 @@ function Concat() return call_user_func_array(array($this->_driver, 'Concat'), $args); } - if (PHP_VERSION >= 5.3) { - return call_user_func_array('parent::Concat', $args); + return call_user_func_array('parent::Concat', $args); + } + + /** + * Triggers a driver-specific request for a bind parameter + * + * @param string $name + * @param string $type + * + * @return string + */ + public function param($name,$type='C') { + + $args = func_get_args(); + if(method_exists($this->_driver, 'param')) { + // Return the driver specific entry, that mimics the native driver + return call_user_func_array(array($this->_driver, 'param'), $args); } - return call_user_func_array(array($this,'parent::Concat'), $args); + + // No driver specific method defined, use mysql format '?' + return call_user_func_array('parent::param', $args); } // returns true or false @@ -251,6 +292,65 @@ function MetaColumns($table,$normalize=true) return $this->_driver->MetaColumns($table,$normalize); } + public function metaIndexes($table,$normalize=true,$owner=false) + { + if (method_exists($this->_driver,'metaIndexes')) + return $this->_driver->metaIndexes($table,$normalize,$owner); + } + + /** + * Return a list of Primary Keys for a specified table. + * + * @param string $table + * @param bool $owner (optional) not used in this driver + * + * @return string[] Array of indexes + */ + public function metaPrimaryKeys($table,$owner=false) + { + if (method_exists($this->_driver,'metaPrimaryKeys')) + return $this->_driver->metaPrimaryKeys($table,$owner); + } + + /** + * Returns a list of Foreign Keys associated with a specific table. + * + * @param string $table + * @param string $owner (optional) not used in this driver + * @param bool $upper + * @param bool $associative + * + * @return string[]|false An array where keys are tables, and values are foreign keys; + * false if no foreign keys could be found. + */ + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { + if (method_exists($this->_driver,'metaForeignKeys')) + return $this->_driver->metaForeignKeys($table, $owner, $upper, $associative); + } + + /** + * List procedures or functions in an array. + * + * @param $procedureNamePattern A procedure name pattern; must match the procedure name as it is stored in the database. + * @param $catalog A catalog name; must match the catalog name as it is stored in the database. + * @param $schemaPattern A schema name pattern. + * + * @return false|array false if not supported, or array of procedures on current database with structure below + * Array( + * [name_of_procedure] => Array( + * [type] => PROCEDURE or FUNCTION + * [catalog] => Catalog_name + * [schema] => Schema_name + * [remarks] => explanatory comment on the procedure + * ) + * ) + */ + public function metaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null) { + if (method_exists($this->_driver,'metaProcedures')) + return $this->_driver->metaProcedures($procedureNamePattern,$catalog,$schemaPattern); + return false; + } + function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false) { $obj = $stmt[1]; @@ -335,19 +435,30 @@ function ErrorNo() return $err; } + /** + * @param bool $auto_commit + * @return void + */ + function SetAutoCommit($auto_commit) + { + if(method_exists($this->_driver, 'SetAutoCommit')) { + $this->_driver->SetAutoCommit($auto_commit); + } + } + function SetTransactionMode($transaction_mode) { if(method_exists($this->_driver, 'SetTransactionMode')) { return $this->_driver->SetTransactionMode($transaction_mode); } - return parent::SetTransactionMode($seqname); + return parent::SetTransactionMode($transaction_mode); } - function BeginTrans() + function beginTrans() { - if(method_exists($this->_driver, 'BeginTrans')) { - return $this->_driver->BeginTrans(); + if(method_exists($this->_driver, 'beginTrans')) { + return $this->_driver->beginTrans(); } if (!$this->hasTransactions) { @@ -358,15 +469,16 @@ function BeginTrans() } $this->transCnt += 1; $this->_autocommit = false; - $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,false); + $this->SetAutoCommit(false); return $this->_connectionID->beginTransaction(); } - function CommitTrans($ok=true) + function commitTrans($ok=true) { - if(method_exists($this->_driver, 'CommitTrans')) { - return $this->_driver->CommitTrans($ok); + + if(method_exists($this->_driver, 'commitTrans')) { + return $this->_driver->commitTrans($ok); } if (!$this->hasTransactions) { @@ -376,7 +488,7 @@ function CommitTrans($ok=true) return true; } if (!$ok) { - return $this->RollbackTrans(); + return $this->rollbackTrans(); } if ($this->transCnt) { $this->transCnt -= 1; @@ -384,7 +496,7 @@ function CommitTrans($ok=true) $this->_autocommit = true; $ret = $this->_connectionID->commit(); - $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true); + $this->SetAutoCommit(true); return $ret; } @@ -406,7 +518,7 @@ function RollbackTrans() $this->_autocommit = true; $ret = $this->_connectionID->rollback(); - $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true); + $this->SetAutoCommit(true); return $ret; } @@ -430,10 +542,10 @@ function PrepareStmt($sql) return $obj; } - function CreateSequence($seqname='adodbseq',$startID=1) + public function createSequence($seqname='adodbseq',$startID=1) { - if(method_exists($this->_driver, 'CreateSequence')) { - return $this->_driver->CreateSequence($seqname, $startID); + if(method_exists($this->_driver, 'createSequence')) { + return $this->_driver->createSequence($seqname, $startID); } return parent::CreateSequence($seqname, $startID); @@ -461,16 +573,23 @@ function GenID($seqname='adodbseq',$startID=1) /* returns queryID or false */ function _query($sql,$inputarr=false) { + $ok = false; if (is_array($sql)) { $stmt = $sql[1]; } else { $stmt = $this->_connectionID->prepare($sql); } - #adodb_backtrace(); - #var_dump($this->_bindInputArray); + if ($stmt) { - $this->_driver->debug = $this->debug; + if ($this->_driver instanceof ADODB_pdo) { + $this->_driver->debug = $this->debug; + } if ($inputarr) { + + /* + * inputarr must be numeric + */ + $inputarr = array_values($inputarr); $ok = $stmt->execute($inputarr); } else { @@ -514,32 +633,30 @@ function _affectedrows() return ($this->_stmt) ? $this->_stmt->rowCount() : 0; } - function _insertid() + protected function _insertID($table = '', $column = '') { return ($this->_connectionID) ? $this->_connectionID->lastInsertId() : 0; } /** * Quotes a string to be sent to the database. + * * If we have an active connection, delegates quoting to the underlying - * PDO object. Otherwise, replace "'" by the value of $replaceQuote (same - * behavior as mysqli driver) - * @param string $s The string to quote - * @param boolean $magic_quotes If false, use PDO::quote(). + * PDO object PDO::quote(). Otherwise, replace "'" by the value of + * $replaceQuote (same behavior as mysqli driver). + * + * @param string $s The string to quote + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * * @return string Quoted string */ - function qstr($s, $magic_quotes = false) + function qStr($s, $magic_quotes = false) { - if (!$magic_quotes) { - if ($this->_connectionID) { - return $this->_connectionID->quote($s); - } - return "'" . str_replace("'", $this->replaceQuote, $s) . "'"; + if ($this->_connectionID) { + return $this->_connectionID->quote($s); } - - // undo magic quotes for " - $s = str_replace('\\"', '"', $s); - return "'$s'"; + return "'" . str_replace("'", $this->replaceQuote, $s) . "'"; } } @@ -734,22 +851,22 @@ function FetchField($fieldOffset = -1) } //adodb_pr($arr); $o->name = $arr['name']; - if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null") + if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null") { /* * If the database is SQL server, use the native built-ins */ $o->type = $arr['sqlsrv:decl_type']; } - elseif (isset($arr['native_type']) && $arr['native_type'] <> "null") + elseif (isset($arr['native_type']) && $arr['native_type'] <> "null") { $o->type = $arr['native_type']; } - else + else { $o->type = adodb_pdo_type($arr['pdo_type']); } - + $o->max_length = $arr['len']; $o->precision = $arr['precision']; @@ -801,3 +918,5 @@ function Fields($colname) } } + +class ADORecordSet_array_pdo extends ADORecordSet_array {} diff --git a/www/include/adodb/drivers/adodb-pdo_dblib.inc.php b/www/include/adodb/drivers/adodb-pdo_dblib.inc.php new file mode 100644 index 00000000..aae561bf --- /dev/null +++ b/www/include/adodb/drivers/adodb-pdo_dblib.inc.php @@ -0,0 +1,190 @@ + 'master'"; + var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))"; + + var $metaColumnsSQL = "SELECT c.NAME, OBJECT_NAME(c.id) as tbl_name, c.length, c.isnullable, c.status, ( CASE WHEN c.xusertype=61 THEN 0 ELSE c.xprec END), ( CASE WHEN c.xusertype=61 THEN 0 ELSE c.xscale END), ISNULL(i.is_primary_key, 0) as primary_key FROM syscolumns c INNER JOIN systypes t ON t.xusertype=c.xusertype INNER JOIN sysobjects o ON o.id=c.id LEFT JOIN sys.index_columns ic ON ic.object_id = c.id AND c.colid = ic.column_id LEFT JOIN sys.indexes i ON i.object_id = ic.object_id AND i.index_id = ic.index_id WHERE c.id = OBJECT_ID('%s') ORDER by c.colid"; + + function _init(ADODB_pdo $parentDriver) + { + $parentDriver->hasTransactions = true; + $parentDriver->_bindInputArray = true; + $parentDriver->hasInsertID = true; + $parentDriver->fmtTimeStamp = "'Y-m-d H:i:s'"; + $parentDriver->fmtDate = "'Y-m-d'"; + } + + function BeginTrans() + { + $returnval = parent::BeginTrans(); + return $returnval; + } + + function MetaColumns($table, $normalize=true) + { + $this->_findschema($table,$schema); + if ($schema) { + $dbName = $this->database; + $this->SelectDB($schema); + } + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); + $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); + + if ($schema) { + $this->SelectDB($dbName); + } + + if (isset($savem)) $this->SetFetchMode($savem); + $ADODB_FETCH_MODE = $save; + if (!is_object($rs)) { + $false = false; + return $false; + } + + $retarr = array(); + while (!$rs->EOF) { + $fld = new ADOFieldObject(); + $fld->name = $rs->fields[0]; + $fld->type = $rs->fields[1]; + $fld->primary_key = $rs->fields[7]; + + $fld->not_null = (!$rs->fields[3]); + $fld->auto_increment = ($rs->fields[4] == 128); // sys.syscolumns status field. 0x80 = 128 ref: http://msdn.microsoft.com/en-us/library/ms186816.aspx + + if (isset($rs->fields[5]) && $rs->fields[5]) { + if ($rs->fields[5]>0) $fld->max_length = $rs->fields[5]; + $fld->scale = $rs->fields[6]; + if ($fld->scale>0) $fld->max_length += 1; + } else + $fld->max_length = $rs->fields[2]; + + if ($save == ADODB_FETCH_NUM) { + $retarr[] = $fld; + } else { + $retarr[strtoupper($fld->name)] = $fld; + } + $rs->MoveNext(); + } + + $rs->Close(); + return $retarr; + } + + function MetaTables($ttype=false,$showSchema=false,$mask=false) + { + if ($mask) { + $save = $this->metaTablesSQL; + $mask = $this->qstr(($mask)); + $this->metaTablesSQL .= " AND name like $mask"; + } + $ret = ADOConnection::MetaTables($ttype,$showSchema); + + if ($mask) { + $this->metaTablesSQL = $save; + } + return $ret; + } + + function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) + { + if ($nrows > 0 && $offset <= 0) { + $sql = preg_replace( + '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql); + + if ($secs2cache) + $rs = $this->CacheExecute($secs2cache, $sql, $inputarr); + else + $rs = $this->Execute($sql,$inputarr); + } else + $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache); + + return $rs; + } + + function _query($sql,$inputarr=false) + { + $this->_connectionID->setAttribute(\PDO::ATTR_EMULATE_PREPARES , true); + if (is_array($sql)) { + $stmt = $sql[1]; + } else { + $stmt = $this->_connectionID->prepare($sql); + } + + if ($stmt) { + $this->_driver->debug = $this->debug; + if ($inputarr) { + foreach ($inputarr as $key => $value) { + if(gettype($key) == 'integer') { + $key += 1; + } + $stmt->bindValue($key, $value, $this->GetPDODataType($value)); + } + } + } + + $ok = $stmt->execute(); + + $this->_errormsg = false; + $this->_errorno = false; + + if ($ok) { + $this->_stmt = $stmt; + return $stmt; + } + + if ($stmt) { + + $arr = $stmt->errorinfo(); + if ((integer)$arr[1]) { + $this->_errormsg = $arr[2]; + $this->_errorno = $arr[1]; + } + + } else { + $this->_errormsg = false; + $this->_errorno = false; + } + return false; + } + + private function GetPDODataType($var) + { + if(gettype($var) == 'integer') { + return PDO::PARAM_INT ; + } + return PDO::PARAM_STR; + } + + function ServerInfo() + { + return ADOConnection::ServerInfo(); + } +} diff --git a/www/include/adodb/drivers/adodb-pdo_firebird.inc.php b/www/include/adodb/drivers/adodb-pdo_firebird.inc.php new file mode 100644 index 00000000..0ee5e02b --- /dev/null +++ b/www/include/adodb/drivers/adodb-pdo_firebird.inc.php @@ -0,0 +1,452 @@ +pdoDriver = $parentDriver; + //$parentDriver->_bindInputArray = true; + //$parentDriver->hasTransactions = false; // // should be set to false because of PDO SQLite driver not supporting changing autocommit mode + //$parentDriver->hasInsertID = true; + } + + /** + * Gets the version iformation from the server + * + * @return string[] + */ + public function serverInfo() + { + $arr['dialect'] = $this->dialect; + switch ($arr['dialect']) { + case '': + case '1': + $s = 'Firebird Dialect 1'; + break; + case '2': + $s = 'Firebird Dialect 2'; + break; + default: + case '3': + $s = 'Firebird Dialect 3'; + break; + } + $arr['version'] = ADOConnection::_findvers($s); + $arr['description'] = $s; + return $arr; + } + + /** + * Returns the tables in the database. + * + * @param mixed $ttype + * @param bool $showSchema + * @param mixed $mask + * + * @return string[] + */ + public function metaTables($ttype = false, $showSchema = false, $mask = false) + { + $ret = ADOConnection::MetaTables($ttype, $showSchema); + + return $ret; + } + + public function metaColumns($table, $normalize = true) + { + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + $rs = $this->Execute(sprintf($this->metaColumnsSQL, strtoupper($table))); + + $ADODB_FETCH_MODE = $save; + + if ($rs === false) { + return false; + } + + $retarr = array(); + $dialect3 = $this->dialect == 3; + while (!$rs->EOF) { //print_r($rs->fields); + $fld = new ADOFieldObject(); + $fld->name = trim($rs->fields[0]); + $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], + $rs->fields[6], $dialect3); + if (isset($rs->fields[1]) && $rs->fields[1]) { + $fld->not_null = true; + } + if (isset($rs->fields[2])) { + + $fld->has_default = true; + $d = substr($rs->fields[2], strlen('default ')); + switch ($fld->type) { + case 'smallint': + case 'integer': + $fld->default_value = (int)$d; + break; + case 'char': + case 'blob': + case 'text': + case 'varchar': + $fld->default_value = (string)substr($d, 1, strlen($d) - 2); + break; + case 'double': + case 'float': + $fld->default_value = (float)$d; + break; + default: + $fld->default_value = $d; + break; + } + } + if ((isset($rs->fields[5])) && ($fld->type == 'blob')) { + $fld->sub_type = $rs->fields[5]; + } else { + $fld->sub_type = null; + } + if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) { + $retarr[] = $fld; + } else { + $retarr[strtoupper($fld->name)] = $fld; + } + + $rs->MoveNext(); + } + $rs->Close(); + if (empty($retarr)) { + return false; + } else { + return $retarr; + } + } + + public function metaIndexes($table, $primary = false, $owner = false) + { + // save old fetch mode + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== false) { + $savem = $this->SetFetchMode(false); + } + $table = strtoupper($table); + $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '" . $table . "'"; + if (!$primary) { + $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'"; + } else { + $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'"; + } + + // get index details + $rs = $this->Execute($sql); + if (!is_object($rs)) { + // restore fetchmode + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + return false; + } + + $indexes = array(); + while ($row = $rs->FetchRow()) { + $index = $row[0]; + if (!isset($indexes[$index])) { + if (is_null($row[3])) { + $row[3] = 0; + } + $indexes[$index] = array( + 'unique' => ($row[3] == 1), + 'columns' => array() + ); + } + $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '" . $index . "' ORDER BY RDB\$FIELD_POSITION ASC"; + $rs1 = $this->Execute($sql); + while ($row1 = $rs1->FetchRow()) { + $indexes[$index]['columns'][$row1[2]] = $row1[1]; + } + } + // restore fetchmode + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + + return $indexes; + } + + public function metaPrimaryKeys($table, $owner_notused = false, $internalKey = false) + { + if ($internalKey) { + return array('RDB$DB_KEY'); + } + + $table = strtoupper($table); + + $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME + FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME + WHERE I.RDB$RELATION_NAME=\'' . $table . '\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\' + ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION'; + + $a = $this->GetCol($sql, false, true); + if ($a && sizeof($a) > 0) { + return $a; + } + return false; + } + + public function createSequence($seqname = 'adodbseq', $startID = 1) + { + $ok = $this->execute("CREATE SEQUENCE $seqname"); + if (!$ok) { + return false; + } + + return $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1)); + } + + public function dropSequence($seqname = 'adodbseq') + { + $seqname = strtoupper($seqname); + return $this->Execute("DROP SEQUENCE $seqname"); + } + + + public function _affectedrows() + { + return fbird_affected_rows($this->_transactionID ? $this->_transactionID : $this->_connectionID); + } + + public function genId($seqname = 'adodbseq', $startID = 1) + { + $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE"); + $rs = @$this->execute($getnext); + if (!$rs) { + $this->execute(("CREATE SEQUENCE $seqname")); + $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1) . ';'); + $rs = $this->execute($getnext); + } + if ($rs && !$rs->EOF) { + $this->genID = (integer)reset($rs->fields); + } else { + $this->genID = 0; // false + } + + if ($rs) { + $rs->Close(); + } + + return $this->genID; + } + + public function selectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs = 0) + { + $nrows = (integer)$nrows; + $offset = (integer)$offset; + $str = 'SELECT '; + if ($nrows >= 0) { + $str .= "FIRST $nrows "; + } + $str .= ($offset >= 0) ? "SKIP $offset " : ''; + + $sql = preg_replace('/^[ \t]*select/i', $str, $sql); + if ($secs) { + $rs = $this->cacheExecute($secs, $sql, $inputarr); + } else { + $rs = $this->execute($sql, $inputarr); + } + + return $rs; + } + + /** + * Sets the appropriate type into the $fld variable + * + * @param ADOFieldObject $fld By reference + * @param int $ftype + * @param int $flen + * @param int $fscale + * @param int $fsubtype + * @param int $fprecision + * @param bool $dialect3 + */ + private function _convertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3) + { + $fscale = abs($fscale); + $fld->max_length = $flen; + $fld->scale = null; + switch ($ftype) { + case 7: + case 8: + if ($dialect3) { + switch ($fsubtype) { + case 0: + $fld->type = ($ftype == 7 ? 'smallint' : 'integer'); + break; + case 1: + $fld->type = 'numeric'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + case 2: + $fld->type = 'decimal'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + } // switch + } else { + if ($fscale != 0) { + $fld->type = 'decimal'; + $fld->scale = $fscale; + $fld->max_length = ($ftype == 7 ? 4 : 9); + } else { + $fld->type = ($ftype == 7 ? 'smallint' : 'integer'); + } + } + break; + case 16: + if ($dialect3) { + switch ($fsubtype) { + case 0: + $fld->type = 'decimal'; + $fld->max_length = 18; + $fld->scale = 0; + break; + case 1: + $fld->type = 'numeric'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + case 2: + $fld->type = 'decimal'; + $fld->max_length = $fprecision; + $fld->scale = $fscale; + break; + } // switch + } + break; + case 10: + $fld->type = 'float'; + break; + case 14: + $fld->type = 'char'; + break; + case 27: + if ($fscale != 0) { + $fld->type = 'decimal'; + $fld->max_length = 15; + $fld->scale = 5; + } else { + $fld->type = 'double'; + } + break; + case 35: + if ($dialect3) { + $fld->type = 'timestamp'; + } else { + $fld->type = 'date'; + } + break; + case 12: + $fld->type = 'date'; + break; + case 13: + $fld->type = 'time'; + break; + case 37: + $fld->type = 'varchar'; + break; + case 40: + $fld->type = 'cstring'; + break; + case 261: + $fld->type = 'blob'; + $fld->max_length = -1; + break; + } // switch + } +} + +/** + * Class ADORecordSet_pdo_firebird + */ +class ADORecordSet_pdo_firebird extends ADORecordSet_pdo +{ + + public $databaseType = "pdo_firebird"; + + /** + * returns the field object + * + * @param int $fieldOffset Optional field offset + * + * @return object The ADOFieldObject describing the field + */ + public function fetchField($fieldOffset = 0) + { + } +} + +/** + * Class ADORecordSet_array_pdo_firebird + */ +class ADORecordSet_array_pdo_firebird extends ADORecordSet_array_pdo +{ + public $databaseType = "pdo_firebird"; + public $canSeek = true; + + /** + * returns the field object + * + * @param int $fieldOffset Optional field offset + * + * @return object The ADOFieldObject describing the field + */ + public function fetchField($fieldOffset = 0) + { + + $fld = new ADOFieldObject; + $fld->name = $fieldOffset; + $fld->type = 'C'; + $fld->max_length = 0; + + // This needs to be populated from the metadata + $fld->not_null = false; + $fld->has_default = false; + $fld->default_value = 'null'; + + return $fld; + } +} diff --git a/www/include/adodb5/drivers/adodb-pdo_mssql.inc.php b/www/include/adodb/drivers/adodb-pdo_mssql.inc.php similarity index 61% rename from www/include/adodb5/drivers/adodb-pdo_mssql.inc.php rename to www/include/adodb/drivers/adodb-pdo_mssql.inc.php index 219cf131..ef63b654 100644 --- a/www/include/adodb5/drivers/adodb-pdo_mssql.inc.php +++ b/www/include/adodb/drivers/adodb-pdo_mssql.inc.php @@ -1,16 +1,23 @@ fetchMode !== FALSE) { + $savem = $this->setFetchMode(FALSE); + } + + // get index details + $rs = $this->execute(sprintf('SHOW INDEXES FROM %s',$table)); + + // restore fetchmode + if (isset($savem)) { + $this->setFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + + if (!is_object($rs)) { + return $false; + } + + $indexes = array (); + + // parse index data into array + while ($row = $rs->fetchRow()) { + if ($primary == FALSE AND $row[2] == 'PRIMARY') { + continue; + } + + if (!isset($indexes[$row[2]])) { + $indexes[$row[2]] = array( + 'unique' => ($row[1] == 0), + 'columns' => array() + ); + } + + $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4]; + } + + // sort columns by order in the index + foreach ( array_keys ($indexes) as $index ) + { + ksort ($indexes[$index]['columns']); + } + + return $indexes; + } function Concat() { @@ -85,6 +158,15 @@ function MetaTables($ttype=false, $showSchema=false, $mask=false) return $ret; } + /** + * @param bool $auto_commit + * @return void + */ + function SetAutoCommit($auto_commit) + { + $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT, $auto_commit); + } + function SetTransactionMode($transaction_mode) { $this->_transmode = $transaction_mode; @@ -192,8 +274,10 @@ function SelectDB($dbName) // parameters use PostgreSQL convention, not MySQL function SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; $offsetStr =($offset>=0) ? "$offset," : ''; - // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220 + // jason judge, see PHPLens Issue No: 9220 if ($nrows < 0) { $nrows = '18446744073709551615'; } @@ -299,4 +383,41 @@ function SQLDate($fmt, $col=false) } return $s; } + + function GenID($seqname='adodbseq',$startID=1) + { + $getnext = sprintf($this->_genIDSQL,$seqname); + $holdtransOK = $this->_transOK; // save the current status + $rs = @$this->Execute($getnext); + if (!$rs) { + if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset + $this->Execute(sprintf($this->_genSeqSQL,$seqname)); + $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname)); + if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); + $rs = $this->Execute($getnext); + } + + if ($rs) { + $this->genID = $this->_connectionID->lastInsertId($seqname); + $rs->Close(); + } else { + $this->genID = 0; + } + + return $this->genID; + } + + + function createSequence($seqname='adodbseq',$startID=1) + { + if (empty($this->_genSeqSQL)) { + return false; + } + $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID)); + if (!$ok) { + return false; + } + + return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); + } } diff --git a/www/include/adodb5/drivers/adodb-pdo_oci.inc.php b/www/include/adodb/drivers/adodb-pdo_oci.inc.php similarity index 61% rename from www/include/adodb5/drivers/adodb-pdo_oci.inc.php rename to www/include/adodb/drivers/adodb-pdo_oci.inc.php index 0bca35e3..20b47def 100644 --- a/www/include/adodb5/drivers/adodb-pdo_oci.inc.php +++ b/www/include/adodb/drivers/adodb-pdo_oci.inc.php @@ -1,16 +1,23 @@ EOF) { //print_r($rs->fields); $fld = new ADOFieldObject(); - $fld->name = $rs->fields[0]; - $fld->type = $rs->fields[1]; - $fld->max_length = $rs->fields[2]; + $fld->name = $rs->fields[0]; + $fld->type = $rs->fields[1]; + $fld->max_length = $rs->fields[2]; $fld->scale = $rs->fields[3]; if ($rs->fields[1] == 'NUMBER' && $rs->fields[3] == 0) { $fld->type ='INT'; - $fld->max_length = $rs->fields[4]; - } - $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0); + $fld->max_length = $rs->fields[4]; + } + $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0); $fld->binary = (strpos($fld->type,'BLOB') !== false); $fld->default_value = $rs->fields[6]; @@ -90,4 +97,26 @@ function MetaColumns($table,$normalize=true) else return $retarr; } + + /** + * @param bool $auto_commit + * @return void + */ + function SetAutoCommit($auto_commit) + { + $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT, $auto_commit); + } + + /** + * Returns a driver-specific format for a bind parameter + * + * @param string $name + * @param string $type (ignored in driver) + * + * @return string + */ + public function param($name,$type='C') + { + return sprintf(':%s', $name); + } } diff --git a/www/include/adodb5/drivers/adodb-pdo_pgsql.inc.php b/www/include/adodb/drivers/adodb-pdo_pgsql.inc.php similarity index 62% rename from www/include/adodb5/drivers/adodb-pdo_pgsql.inc.php rename to www/include/adodb/drivers/adodb-pdo_pgsql.inc.php index 9afe4b0e..6c06ac10 100644 --- a/www/include/adodb5/drivers/adodb-pdo_pgsql.inc.php +++ b/www/include/adodb/drivers/adodb-pdo_pgsql.inc.php @@ -1,23 +1,31 @@ 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum"; + AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum"; // used when schema defined var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum -FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n -WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) - and c.relnamespace=n.oid and n.nspname='%s' - and a.attname not like '....%%' AND a.attnum > 0 - AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum"; + FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n + WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) + and c.relnamespace=n.oid and n.nspname='%s' + and a.attname not like '....%%' AND a.attnum > 0 + AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum"; // get primary key etc -- from Freek Dijkstra var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key @@ -73,12 +81,14 @@ function ServerInfo() function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) { - $offsetStr = ($offset >= 0) ? " OFFSET $offset" : ''; - $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ''; - if ($secs2cache) - $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr); - else - $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr); + $nrows = (int) $nrows; + $offset = (int) $offset; + $offsetStr = ($offset >= 0) ? " OFFSET $offset" : ''; + $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ''; + if ($secs2cache) + $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr); + else + $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr); return $rs; } @@ -87,23 +97,27 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false) { $info = $this->ServerInfo(); if ($info['version'] >= 7.3) { - $this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%' - and schemaname not in ( 'pg_catalog','information_schema') - union - select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') "; + $this->metaTablesSQL = " +select tablename,'T' from pg_tables +where tablename not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') +union +select viewname,'V' from pg_views +where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema')"; } if ($mask) { $save = $this->metaTablesSQL; $mask = $this->qstr(strtolower($mask)); if ($info['version']>=7.3) $this->metaTablesSQL = " -select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema') - union -select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') "; +select tablename,'T' from pg_tables +where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema') +union +select viewname,'V' from pg_views +where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema')"; else $this->metaTablesSQL = " select tablename,'T' from pg_tables where tablename like $mask - union +union select viewname,'V' from pg_views where viewname like $mask"; } $ret = ADOConnection::MetaTables($ttype,$showSchema); @@ -227,4 +241,83 @@ function MetaColumns($table,$normalize=true) } + function BeginTrans() + { + if (!$this->hasTransactions) { + return false; + } + if ($this->transOff) { + return true; + } + $this->transCnt += 1; + + return $this->_connectionID->beginTransaction(); + } + + function CommitTrans($ok = true) + { + if (!$this->hasTransactions) { + return false; + } + if ($this->transOff) { + return true; + } + if (!$ok) { + return $this->RollbackTrans(); + } + if ($this->transCnt) { + $this->transCnt -= 1; + } + $this->_autocommit = true; + + $ret = $this->_connectionID->commit(); + return $ret; + } + + function RollbackTrans() + { + if (!$this->hasTransactions) { + return false; + } + if ($this->transOff) { + return true; + } + if ($this->transCnt) { + $this->transCnt -= 1; + } + $this->_autocommit = true; + + $ret = $this->_connectionID->rollback(); + return $ret; + } + + function SetTransactionMode( $transaction_mode ) + { + $this->_transmode = $transaction_mode; + if (empty($transaction_mode)) { + $this->_connectionID->query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); + return; + } + if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; + $this->_connectionID->query("SET TRANSACTION ".$transaction_mode); + } + + /** + * Returns a driver-specific format for a bind parameter + * + * Unlike the native driver, we use :name parameters + * instead of offsets + * + * @param string $name + * @param string $type (ignored in driver) + * + * @return string + */ + public function param($name,$type='C') { + if (!$name) { + return ''; + } + + return sprintf(':%s', $name); + } } diff --git a/www/include/adodb5/drivers/adodb-pdo_sqlite.inc.php b/www/include/adodb/drivers/adodb-pdo_sqlite.inc.php similarity index 63% rename from www/include/adodb5/drivers/adodb-pdo_sqlite.inc.php rename to www/include/adodb/drivers/adodb-pdo_sqlite.inc.php index d42c5191..dab1de99 100644 --- a/www/include/adodb5/drivers/adodb-pdo_sqlite.inc.php +++ b/www/include/adodb/drivers/adodb-pdo_sqlite.inc.php @@ -1,19 +1,25 @@ + * @author Sid Dunayer + */ class ADODB_pdo_sqlite extends ADODB_pdo { var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table'"; @@ -28,7 +34,7 @@ class ADODB_pdo_sqlite extends ADODB_pdo { var $_genSeq2SQL = 'INSERT INTO %s VALUES(%s)'; var $_dropSeqSQL = 'DROP TABLE %s'; var $concat_operator = '||'; - var $pdoDriver = false; + var $pdoDriver = false; var $random='abs(random())'; function _init($parentDriver) @@ -54,13 +60,15 @@ function ServerInfo() function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; $parent = $this->pdoDriver; $offsetStr = ($offset >= 0) ? " OFFSET $offset" : ''; $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : ''); - if ($secs2cache) - $rs = $parent->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr); - else - $rs = $parent->Execute($sql."$limitStr$offsetStr",$inputarr); + if ($secs2cache) + $rs = $parent->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr); + else + $rs = $parent->Execute($sql."$limitStr$offsetStr",$inputarr); return $rs; } @@ -148,40 +156,48 @@ function RollbackTrans() // mark newnham function MetaColumns($tab,$normalize=true) { - global $ADODB_FETCH_MODE; - - $parent = $this->pdoDriver; - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; - if ($parent->fetchMode !== false) $savem = $parent->SetFetchMode(false); - $rs = $parent->Execute("PRAGMA table_info('$tab')"); - if (isset($savem)) $parent->SetFetchMode($savem); - if (!$rs) { - $ADODB_FETCH_MODE = $save; - return $false; - } - $arr = array(); - while ($r = $rs->FetchRow()) { - $type = explode('(',$r['type']); - $size = ''; - if (sizeof($type)==2) - $size = trim($type[1],')'); - $fn = strtoupper($r['name']); - $fld = new ADOFieldObject; - $fld->name = $r['name']; - $fld->type = $type[0]; - $fld->max_length = $size; - $fld->not_null = $r['notnull']; - $fld->primary_key = $r['pk']; - $fld->default_value = $r['dflt_value']; - $fld->scale = 0; - if ($save == ADODB_FETCH_NUM) $arr[] = $fld; - else $arr[strtoupper($fld->name)] = $fld; - } - $rs->Close(); - $ADODB_FETCH_MODE = $save; - return $arr; + global $ADODB_FETCH_MODE; + + $parent = $this->pdoDriver; + $false = false; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; + if ($parent->fetchMode !== false) { + $savem = $parent->SetFetchMode(false); + } + $rs = $parent->Execute("PRAGMA table_info('$tab')"); + if (isset($savem)) { + $parent->SetFetchMode($savem); + } + if (!$rs) { + $ADODB_FETCH_MODE = $save; + return $false; + } + $arr = array(); + while ($r = $rs->FetchRow()) { + $type = explode('(', $r['type']); + $size = ''; + if (sizeof($type) == 2) { + $size = trim($type[1], ')'); + } + $fn = strtoupper($r['name']); + $fld = new ADOFieldObject; + $fld->name = $r['name']; + $fld->type = $type[0]; + $fld->max_length = $size; + $fld->not_null = $r['notnull']; + $fld->primary_key = $r['pk']; + $fld->default_value = $r['dflt_value']; + $fld->scale = 0; + if ($save == ADODB_FETCH_NUM) { + $arr[] = $fld; + } else { + $arr[strtoupper($fld->name)] = $fld; + } + } + $rs->Close(); + $ADODB_FETCH_MODE = $save; + return $arr; } function MetaTables($ttype=false,$showSchema=false,$mask=false) @@ -200,5 +216,18 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false) $this->metaTablesSQL = $save; } return $ret; - } + } + + /** + * Returns a driver-specific format for a bind parameter + * + * @param string $name + * @param string $type (ignored in driver) + * + * @return string + */ + public function param($name,$type='C') + { + return sprintf(':%s', $name); + } } diff --git a/www/include/adodb/drivers/adodb-pdo_sqlsrv.inc.php b/www/include/adodb/drivers/adodb-pdo_sqlsrv.inc.php new file mode 100644 index 00000000..ed73f3a2 --- /dev/null +++ b/www/include/adodb/drivers/adodb-pdo_sqlsrv.inc.php @@ -0,0 +1,181 @@ +hasTransactions = true; + $parentDriver->_bindInputArray = true; + $parentDriver->hasInsertID = true; + $parentDriver->fmtTimeStamp = "'Y-m-d H:i:s'"; + $parentDriver->fmtDate = "'Y-m-d'"; + } + + function BeginTrans() + { + $returnval = parent::BeginTrans(); + return $returnval; + } + + function MetaColumns($table, $normalize = true) + { + return false; + } + + function MetaTables($ttype = false, $showSchema = false, $mask = false) + { + return false; + } + + function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0) + { + $ret = ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); + return $ret; + } + + function ServerInfo() + { + return ADOConnection::ServerInfo(); + } +} + +class ADORecordSet_pdo_sqlsrv extends ADORecordSet_pdo +{ + + public $databaseType = "pdo_sqlsrv"; + + /** + * returns the field object + * + * @param int $fieldOffset Optional field offset + * + * @return object The ADOFieldObject describing the field + */ + public function fetchField($fieldOffset = 0) + { + + // Default behavior allows passing in of -1 offset, which crashes the method + if ($fieldOffset == -1) { + $fieldOffset++; + } + + $o = new ADOFieldObject(); + $arr = @$this->_queryID->getColumnMeta($fieldOffset); + + if (!$arr) { + $o->name = 'bad getColumnMeta()'; + $o->max_length = -1; + $o->type = 'VARCHAR'; + $o->precision = 0; + return $o; + } + $o->name = $arr['name']; + if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null") { + // Use the SQL Server driver specific value + $o->type = $arr['sqlsrv:decl_type']; + } else { + $o->type = adodb_pdo_type($arr['pdo_type']); + } + $o->max_length = $arr['len']; + $o->precision = $arr['precision']; + + switch (ADODB_ASSOC_CASE) { + case ADODB_ASSOC_CASE_LOWER: + $o->name = strtolower($o->name); + break; + case ADODB_ASSOC_CASE_UPPER: + $o->name = strtoupper($o->name); + break; + } + + return $o; + } +} + +class ADORecordSet_array_pdo_sqlsrv extends ADORecordSet_array_pdo +{ + + /** + * returns the field object + * + * Note that this is a direct copy of the ADORecordSet_pdo_sqlsrv method + * + * @param int $fieldOffset Optional field offset + * + * @return object The ADOfieldobject describing the field + */ + public function fetchField($fieldOffset = 0) + { + // Default behavior allows passing in of -1 offset, which crashes the method + if ($fieldOffset == -1) { + $fieldOffset++; + } + + $o = new ADOFieldObject(); + $arr = @$this->_queryID->getColumnMeta($fieldOffset); + + if (!$arr) { + $o->name = 'bad getColumnMeta()'; + $o->max_length = -1; + $o->type = 'VARCHAR'; + $o->precision = 0; + return $o; + } + $o->name = $arr['name']; + if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null") { + // Use the SQL Server driver specific value + $o->type = $arr['sqlsrv:decl_type']; + } else { + $o->type = adodb_pdo_type($arr['pdo_type']); + } + $o->max_length = $arr['len']; + $o->precision = $arr['precision']; + + switch (ADODB_ASSOC_CASE) { + case ADODB_ASSOC_CASE_LOWER: + $o->name = strtolower($o->name); + break; + case ADODB_ASSOC_CASE_UPPER: + $o->name = strtoupper($o->name); + break; + } + + return $o; + } + + function SetTransactionMode( $transaction_mode ) + { + $this->_transmode = $transaction_mode; + if (empty($transaction_mode)) { + $this->_connectionID->query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); + return; + } + if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; + $this->_connectionID->query("SET TRANSACTION ".$transaction_mode); + } +} diff --git a/www/include/adodb/drivers/adodb-postgres.inc.php b/www/include/adodb/drivers/adodb-postgres.inc.php new file mode 100644 index 00000000..070ac1c7 --- /dev/null +++ b/www/include/adodb/drivers/adodb-postgres.inc.php @@ -0,0 +1,25 @@ + - jlim - changed concat operator to || and data types to MetaType to match documented pgsql types - see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm - 22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" - 27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" - 15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk. - 31 Jan 2002 jlim - finally installed postgresql. testing - 01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type - - See http://www.varlena.com/varlena/GeneralBits/47.php - - -- What indexes are on my table? - select * from pg_indexes where tablename = 'tablename'; - - -- What triggers are on my table? - select c.relname as "Table", t.tgname as "Trigger Name", - t.tgconstrname as "Constraint Name", t.tgenabled as "Enabled", - t.tgisconstraint as "Is Constraint", cc.relname as "Referenced Table", - p.proname as "Function Name" - from pg_trigger t, pg_class c, pg_class cc, pg_proc p - where t.tgfoid = p.oid and t.tgrelid = c.oid - and t.tgconstrrelid = cc.oid - and c.relname = 'tablename'; - - -- What constraints are on my table? - select r.relname as "Table", c.conname as "Constraint Name", - contype as "Constraint Type", conkey as "Key Columns", - confkey as "Foreign Columns", consrc as "Source" - from pg_class r, pg_constraint c - where r.oid = c.conrelid - and relname = 'tablename'; - -*/ +/** + * ADOdb PostgreSQL 6.4 driver + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); -function adodb_addslashes($s) -{ - $len = strlen($s); - if ($len == 0) return "''"; - if (strncmp($s,"'",1) === 0 && substr($s,$len-1) == "'") return $s; // already quoted - - return "'".addslashes($s)."'"; -} - class ADODB_postgres64 extends ADOConnection{ var $databaseType = 'postgres64'; var $dataProvider = 'postgres'; var $hasInsertID = true; + /** @var PgSql\Connection|resource|false */ var $_resultid = false; var $concat_operator='||'; var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1"; @@ -114,6 +81,7 @@ class ADODB_postgres64 extends ADOConnection{ var $_bindInputArray = false; // requires postgresql 7.3+ and ability to modify database var $disableBlobs = false; // set to true to disable blob checking, resulting in 2-5% improvement in performance. + /** @var int $_pnum Number of the last assigned query parameter {@see param()} */ var $_pnum = 0; // The last (fmtTimeStamp is not entirely correct: @@ -124,19 +92,40 @@ class ADODB_postgres64 extends ADOConnection{ // to know what the concequences are. The other values are correct (wheren't in 0.94) // -- Freek Dijkstra - function __construct() + /** + * Retrieve Server information. + * In addition to server version and description, the function also returns + * the client version. + * @param bool $detailed If true, retrieve detailed version string (executes + * a SQL query) in addition to the version number + * @return array|bool Server info or false if version could not be retrieved + * e.g. if there is no active connection + */ + function ServerInfo($detailed = true) { - // changes the metaColumnsSQL, adds columns: attnum[6] - } + if (empty($this->version['version'])) { + // We don't have a connection, so we can't retrieve server info + if (!$this->_connectionID) { + return false; + } - function ServerInfo() - { - if (isset($this->version)) return $this->version; + $version = pg_version($this->_connectionID); + $this->version = array( + // If PHP has been compiled with PostgreSQL 7.3 or lower, then + // server version is not set so we use pg_parameter_status() + // which includes logic to obtain values server_version + 'version' => isset($version['server']) + ? $version['server'] + : pg_parameter_status($this->_connectionID, 'server_version'), + 'client' => $version['client'], + 'description' => null, + ); + } + if ($detailed && $this->version['description'] === null) { + $this->version['description'] = $this->GetOne('select version()'); + } - $arr['description'] = $this->GetOne("select version()"); - $arr['version'] = ADOConnection::_findvers($arr['description']); - $this->version = $arr; - return $arr; + return $this->version; } function IfNull( $field, $ifNull ) @@ -161,24 +150,26 @@ function pg_insert_id($tablename,$fieldname) * Using a OID as a unique identifier is not generally wise. * Unless you are very careful, you might end up with a tuple having * a different OID if a database must be reloaded. + * + * @inheritDoc */ - function _insertid($table,$column) + protected function _insertID($table = '', $column = '') { - if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false; - $oid = pg_getlastoid($this->_resultid); + if ($this->_resultid === false) return false; + $oid = pg_last_oid($this->_resultid); // to really return the id, we need the table and column-name, else we can only return the oid != id return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid); } function _affectedrows() { - if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false; + if ($this->_resultid === false) return false; return pg_affected_rows($this->_resultid); } /** - * @return true/false + * @return bool */ function BeginTrans() { @@ -243,31 +234,32 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false) } - // if magic quotes disabled, use pg_escape_string() - function qstr($s,$magic_quotes=false) + /** + * Quotes a string to be sent to the database. + * + * Relies on pg_escape_string() + * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr + * + * @param string $s The string to quote + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. + * + * @return string Quoted string + */ + function qStr($s, $magic_quotes=false) { - if (is_bool($s)) return $s ? 'true' : 'false'; - - if (!$magic_quotes) { - if (ADODB_PHPVER >= 0x5200 && $this->_connectionID) { - return "'".pg_escape_string($this->_connectionID,$s)."'"; - } - if (ADODB_PHPVER >= 0x4200) { - return "'".pg_escape_string($s)."'"; - } - if ($this->replaceQuote[0] == '\\'){ - $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\\000"),$s); - } - return "'".str_replace("'",$this->replaceQuote,$s)."'"; + if (is_bool($s)) { + return $s ? 'true' : 'false'; } - // undo magic quotes for " - $s = str_replace('\\"','"',$s); - return "'$s'"; + if ($this->_connectionID) { + return "'" . pg_escape_string($this->_connectionID, $s) . "'"; + } else { + return "'" . pg_escape_string($s) . "'"; + } } - // Format date column in sql string given an input format that understands Y M D function SQLDate($fmt, $col=false) { @@ -387,13 +379,13 @@ function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB') function BlobDelete( $blob ) { pg_query($this->_connectionID, 'begin'); - $result = @pg_lo_unlink($blob); + $result = @pg_lo_unlink($this->_connectionID, $blob); pg_query($this->_connectionID, 'commit'); return( $result ); } /* - Hueristic - not guaranteed to work. + Heuristic - not guaranteed to work. */ function GuessOID($oid) { @@ -425,29 +417,25 @@ function BlobDecode($blob,$maxsize=false,$hastrans=true) } if (!$maxsize) $maxsize = $this->maxblobsize; $realblob = @pg_lo_read($fd,$maxsize); - @pg_loclose($fd); + @pg_lo_close($fd); if ($hastrans) pg_query($this->_connectionID,'commit'); return $realblob; } - /* - See http://www.postgresql.org/idocs/index.php?datatype-binary.html - - NOTE: SQL string literals (input strings) must be preceded with two backslashes - due to the fact that they must pass through two parsers in the PostgreSQL - backend. - */ + /** + * Encode binary value prior to DB storage. + * + * See https://www.postgresql.org/docs/current/static/datatype-binary.html + * + * NOTE: SQL string literals (input strings) must be preceded with two + * backslashes due to the fact that they must pass through two parsers in + * the PostgreSQL backend. + * + * @param string $blob + */ function BlobEncode($blob) { - if (ADODB_PHPVER >= 0x5200) return pg_escape_bytea($this->_connectionID, $blob); - if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob); - - /*92=backslash, 0=null, 39=single-quote*/ - $badch = array(chr(92),chr(0),chr(39)); # \ null ' - $fixch = array('\\\\134','\\\\000','\\\\047'); - return adodb_str_replace($badch,$fixch,$blob); - - // note that there is a pg_escape_bytea function only for php 4.2.0 or later + return pg_escape_bytea($this->_connectionID, $blob); } // assumes bytea for blob, and varchar for clob @@ -492,7 +480,7 @@ protected function _generateMetaColumnsSQL($table, $schema) // for schema support, pass in the $table param "$schema.$tabname". // converts field names to lowercase, $upper is ignored - // see http://phplens.com/lens/lensforum/msgs.php?id=14018 for more info + // see PHPLens Issue No: 14018 for more info function MetaColumns($table,$normalize=true) { global $ADODB_FETCH_MODE; @@ -606,15 +594,18 @@ function MetaColumns($table,$normalize=true) } - function Param($name,$type='C') + function param($name, $type='C') { - if ($name) { - $this->_pnum += 1; - } else { - // Reset param num if $name is false - $this->_pnum = 1; + if (!$name) { + // Reset parameter number if $name is falsy + $this->_pnum = 0; + if ($name === false) { + // and don't return placeholder if false (see #380) + return ''; + } } - return '$'.$this->_pnum; + + return '$' . ++$this->_pnum; } function MetaIndexes ($table, $primary = FALSE, $owner = false) @@ -666,8 +657,8 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false) } $col_names = $this->MetaColumnNames($table,true,true); - //3rd param is use attnum, - // see http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976 + // 3rd param is use attnum, + // see https://sourceforge.net/p/adodb/bugs/45/ $indexes = array(); while ($row = $rs->FetchRow()) { $columns = array(); @@ -683,36 +674,58 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false) return $indexes; } - // returns true or false - // - // examples: - // $db->Connect("host=host1 user=user1 password=secret port=4341"); - // $db->Connect('host1','user1','secret'); - function _connect($str,$user='',$pwd='',$db='',$ctype=0) + /** + * Connect to a database. + * + * Examples: + * $db->Connect("host=host1 user=user1 password=secret port=4341"); + * $db->Connect('host1:4341', 'user1', 'secret'); + * + * @param string $str pg_connect() Connection string or Hostname[:port] + * @param string $user (Optional) The username to connect as. + * @param string $pwd (Optional) The password to connect with. + * @param string $db (Optional) The name of the database to start in when connected. + * @param int $ctype Connection type + * @return bool|null True if connected successfully, false if connection failed, or + * null if the PostgreSQL extension is not loaded. + */ + function _connect($str, $user='', $pwd='', $db='', $ctype=0) { - if (!function_exists('pg_connect')) return null; + if (!function_exists('pg_connect')) { + return null; + } $this->_errorMsg = false; + // If $user, $pwd and $db are all null, then $str is a pg_connect() + // connection string. Otherwise we expect it to be a hostname, + // with optional port separated by ':' if ($user || $pwd || $db) { - $user = adodb_addslashes($user); - $pwd = adodb_addslashes($pwd); - if (strlen($db) == 0) $db = 'template1'; - $db = adodb_addslashes($db); - if ($str) { - $host = explode(":", $str); - if ($host[0]) $str = "host=".adodb_addslashes($host[0]); - else $str = ''; - if (isset($host[1])) $str .= " port=$host[1]"; - else if (!empty($this->port)) $str .= " port=".$this->port; + // Hostname & port + if ($str) { + $host = explode(':', $str); + if ($host[0]) { + $conn['host'] = $host[0]; + } + if (isset($host[1])) { + $conn['port'] = (int)$host[1]; + } elseif (!empty($this->port)) { + $conn['port'] = $this->port; + } + } + $conn['user'] = $user; + $conn['password'] = $pwd; + // @TODO not sure why we default to 'template1', pg_connect() uses the username when dbname is empty + $conn['dbname'] = $db ?: 'template1'; + + // Generate connection string + $str = ''; + foreach ($conn as $param => $value) { + // Escaping single quotes and backslashes per pg_connect() documentation + $str .= $param . "='" . addcslashes($value, "'\\") . "' "; } - if ($user) $str .= " user=".$user; - if ($pwd) $str .= " password=".$pwd; - if ($db) $str .= " dbname=".$db; } - //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432"; - if ($ctype === 1) { // persistent $this->_connectionID = pg_pconnect($str); } else { @@ -729,9 +742,9 @@ function _connect($str,$user='',$pwd='',$db='',$ctype=0) if ($this->_connectionID === false) return false; $this->Execute("set datestyle='ISO'"); - $info = $this->ServerInfo(); - $this->pgVersion = (float) substr($info['version'],0,3); - if ($this->pgVersion >= 7.1) { // good till version 999 + $info = $this->ServerInfo(false); + + if (version_compare($info['version'], '7.1', '>=')) { $this->_nestedSQL = true; } @@ -739,7 +752,10 @@ function _connect($str,$user='',$pwd='',$db='',$ctype=0) # PHP does not handle 'hex' properly ('x74657374' is returned as 't657374') # https://bugs.php.net/bug.php?id=59831 states this is in fact not a bug, # so we manually set bytea_output - if ( !empty($this->connection->noBlobs) && version_compare($info['version'], '9.0', '>=')) { + if (!empty($this->connection->noBlobs) + && version_compare($info['version'], '9.0', '>=') + && version_compare($info['client'], '9.2', '<') + ) { $this->Execute('set bytea_output=escape'); } @@ -793,8 +809,7 @@ function _query($sql,$inputarr=false) if ($execp) $exsql = "EXECUTE $plan ($execp)"; else $exsql = "EXECUTE $plan"; - - $rez = @pg_execute($this->_connectionID,$exsql); + $rez = @pg_query($this->_connectionID, $exsql); if (!$rez) { # Perhaps plan does not exist? Prepare/compile plan. $params = ''; @@ -818,18 +833,18 @@ function _query($sql,$inputarr=false) } $s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2); //adodb_pr($s); - $rez = pg_execute($this->_connectionID,$s); + $rez = pg_query($this->_connectionID, $s); //echo $this->ErrorMsg(); } if ($rez) - $rez = pg_execute($this->_connectionID,$exsql); + $rez = pg_query($this->_connectionID, $exsql); } else { //adodb_backtrace(); - $rez = pg_query($this->_connectionID,$sql); + $rez = pg_query($this->_connectionID, $sql); } // check if no data returned, then no need to create real recordset if ($rez && pg_num_fields($rez) <= 0) { - if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') { + if ($this->_resultid !== false) { pg_free_result($this->_resultid); } $this->_resultid = $rez; @@ -848,20 +863,23 @@ function _errconnect() /* Returns: the last error message from previous database operation */ function ErrorMsg() { - if ($this->_errorMsg !== false) return $this->_errorMsg; - if (ADODB_PHPVER >= 0x4300) { - if (!empty($this->_resultid)) { - $this->_errorMsg = @pg_result_error($this->_resultid); - if ($this->_errorMsg) return $this->_errorMsg; + if ($this->_errorMsg !== false) { + return $this->_errorMsg; + } + + if (!empty($this->_resultid)) { + $this->_errorMsg = @pg_result_error($this->_resultid); + if ($this->_errorMsg) { + return $this->_errorMsg; } + } - if (!empty($this->_connectionID)) { - $this->_errorMsg = @pg_last_error($this->_connectionID); - } else $this->_errorMsg = $this->_errconnect(); + if (!empty($this->_connectionID)) { + $this->_errorMsg = @pg_last_error($this->_connectionID); } else { - if (empty($this->_connectionID)) $this->_errconnect(); - else $this->_errorMsg = @pg_errormessage($this->_connectionID); + $this->_errorMsg = $this->_errconnect(); } + return $this->_errorMsg; } @@ -946,10 +964,9 @@ function GetRowAssoc($upper = ADODB_ASSOC_CASE) return $row; } - - function _initrs() + function _initRS() { - global $ADODB_COUNTRECS; + global $ADODB_COUNTRECS; $qid = $this->_queryID; $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_num_rows($qid):-1; $this->_numOfFields = @pg_num_fields($qid); @@ -964,10 +981,11 @@ function _initrs() } } - /* Use associative array to get fields array */ - function Fields($colname) + function fields($colname) { - if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname]; + if ($this->fetchMode != PGSQL_NUM) { + return @$this->fields[$colname]; + } if (!$this->bind) { $this->bind = array(); @@ -979,14 +997,14 @@ function Fields($colname) return $this->fields[$this->bind[strtoupper($colname)]]; } - function FetchField($off = 0) + function fetchField($fieldOffset = 0) { // offsets begin at 0 - $o= new ADOFieldObject(); - $o->name = @pg_field_name($this->_queryID,$off); - $o->type = @pg_field_type($this->_queryID,$off); - $o->max_length = @pg_fieldsize($this->_queryID,$off); + $o = new ADOFieldObject(); + $o->name = @pg_field_name($this->_queryID, $fieldOffset); + $o->type = @pg_field_type($this->_queryID, $fieldOffset); + $o->max_length = @pg_field_size($this->_queryID, $fieldOffset); return $o; } @@ -998,12 +1016,24 @@ function _seek($row) function _decode($blob) { if ($blob === NULL) return NULL; -// eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";'); +// eval('$realblob="'.str_replace(array('"','$'),array('\"','\$'),$blob).'";'); return pg_unescape_bytea($blob); } - function _fixblobs() + /** + * Fetches and prepares the RecordSet's fields. + * + * Fixes the blobs if there are any. + */ + protected function _prepFields() { + $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode); + + // Check prerequisites and bail early if we do not have what we need. + if (!isset($this->_blobArr) || $this->fields === false) { + return; + } + if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) { foreach($this->_blobArr as $k => $v) { $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]); @@ -1022,9 +1052,8 @@ function MoveNext() if (!$this->EOF) { $this->_currentRow++; if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) { - $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode); - if (is_array($this->fields) && $this->fields) { - if (isset($this->_blobArr)) $this->_fixblobs(); + $this->_prepfields(); + if ($this->fields !== false) { return true; } } @@ -1036,20 +1065,20 @@ function MoveNext() function _fetch() { - - if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0) + if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0) { return false; + } - $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode); - - if ($this->fields && isset($this->_blobArr)) $this->_fixblobs(); - - return (is_array($this->fields)); + $this->_prepfields(); + return $this->fields !== false; } function _close() { - return @pg_free_result($this->_queryID); + if ($this->_queryID === false) { + return true; + } + return pg_free_result($this->_queryID); } function MetaType($t,$len=-1,$fieldobj=false) @@ -1059,7 +1088,13 @@ function MetaType($t,$len=-1,$fieldobj=false) $t = $fieldobj->type; $len = $fieldobj->max_length; } - switch (strtoupper($t)) { + + $t = strtoupper($t); + + if (array_key_exists($t,$this->connection->customActualTypes)) + return $this->connection->customActualTypes[$t]; + + switch ($t) { case 'MONEY': // stupid, postgres expects money to be a string case 'INTERVAL': case 'CHAR': @@ -1068,8 +1103,10 @@ function MetaType($t,$len=-1,$fieldobj=false) case 'NAME': case 'BPCHAR': case '_VARCHAR': + case 'CIDR': case 'INET': case 'MACADDR': + case 'UUID': if ($len <= $this->blobSize) return 'C'; case 'TEXT': @@ -1110,8 +1147,14 @@ function MetaType($t,$len=-1,$fieldobj=false) case 'SERIAL': return 'R'; - default: + case 'NUMERIC': + case 'DECIMAL': + case 'FLOAT4': + case 'FLOAT8': return 'N'; + + default: + return ADODB_DEFAULT_METATYPE; } } diff --git a/www/include/adodb5/drivers/adodb-postgres7.inc.php b/www/include/adodb/drivers/adodb-postgres7.inc.php similarity index 64% rename from www/include/adodb5/drivers/adodb-postgres7.inc.php rename to www/include/adodb/drivers/adodb-postgres7.inc.php index ebdf2acf..b5e63acf 100644 --- a/www/include/adodb5/drivers/adodb-postgres7.inc.php +++ b/www/include/adodb/drivers/adodb-postgres7.inc.php @@ -1,17 +1,23 @@ rsPrefix .= 'assoc_'; } - $this->_bindInputArray = PHP_VERSION >= 5.1; + $this->_bindInputArray = true; } @@ -109,6 +115,8 @@ function __construct() // which makes obsolete the LIMIT limit,offset syntax function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; $offsetStr = ($offset >= 0) ? " OFFSET ".((integer)$offset) : ''; $limitStr = ($nrows >= 0) ? " LIMIT ".((integer)$nrows) : ''; if ($secs2cache) @@ -146,10 +154,7 @@ protected function _generateMetaColumnsSQL($table, $schema) } } - /** - * @returns assoc array where keys are tables, and values are foreign keys - */ - function MetaForeignKeys($table, $owner=false, $upper=false) + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) { # Regex isolates the 2 terms between parenthesis using subexpressions $regex = '^.*\((.*)\).*\((.*)\).*$'; @@ -185,50 +190,18 @@ function MetaForeignKeys($table, $owner=false, $upper=false) $a = array(); while (!$rs->EOF) { + $lookup_table = $rs->fields('lookup_table'); + $fields = $rs->fields('dep_field') . '=' . $rs->fields('lookup_field'); if ($upper) { - $a[strtoupper($rs->Fields('lookup_table'))][] = strtoupper(str_replace('"','',$rs->Fields('dep_field').'='.$rs->Fields('lookup_field'))); - } else { - $a[$rs->Fields('lookup_table')][] = str_replace('"','',$rs->Fields('dep_field').'='.$rs->Fields('lookup_field')); + $lookup_table = strtoupper($lookup_table); + $fields = strtoupper($fields); } + $a[$lookup_table][] = str_replace('"','', $fields); + $rs->MoveNext(); } return $a; - - } - - // from Edward Jaramilla, improved version - works on pg 7.4 - function _old_MetaForeignKeys($table, $owner=false, $upper=false) - { - $sql = 'SELECT t.tgargs as args - FROM - pg_trigger t,pg_class c,pg_proc p - WHERE - t.tgenabled AND - t.tgrelid = c.oid AND - t.tgfoid = p.oid AND - p.proname = \'RI_FKey_check_ins\' AND - c.relname = \''.strtolower($table).'\' - ORDER BY - t.tgrelid'; - - $rs = $this->Execute($sql); - - if (!$rs || $rs->EOF) return false; - - $arr = $rs->GetArray(); - $a = array(); - foreach($arr as $v) { - $data = explode(chr(0), $v['args']); - $size = count($data)-1; //-1 because the last node is empty - for($i = 4; $i < $size; $i++) { - if ($upper) - $a[strtoupper($data[2])][] = strtoupper($data[$i].'='.$data[++$i]); - else - $a[$data[2]][] = $data[$i].'='.$data[++$i]; - } - } - return $a; } function _query($sql,$inputarr=false) @@ -258,7 +231,7 @@ function _query($sql,$inputarr=false) } // check if no data returned, then no need to create real recordset if ($rez && pg_num_fields($rez) <= 0) { - if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') { + if ($this->_resultid !== false) { pg_free_result($this->_resultid); } $this->_resultid = $rez; @@ -267,34 +240,47 @@ function _query($sql,$inputarr=false) return $rez; } - // this is a set of functions for managing client encoding - very important if the encodings - // of your database and your output target (i.e. HTML) don't match - //for instance, you may have UNICODE database and server it on-site as WIN1251 etc. - // GetCharSet - get the name of the character set the client is using now - // the functions should work with Postgres 7.0 and above, the set of charsets supported - // depends on compile flags of postgres distribution - if no charsets were compiled into the server - // it will return 'SQL_ANSI' always - function GetCharSet() + /** + * Retrieve the client connection's current character set. + + * If no charsets were compiled into the server, the function will always + * return 'SQL_ASCII'. + * @see https://www.php.net/manual/en/function.pg-client-encoding.php + * + * @return string|false The character set, or false if it can't be determined. + */ + function getCharSet() { - //we will use ADO's builtin property charSet - $this->charSet = @pg_client_encoding($this->_connectionID); - if (!$this->charSet) { + if (!$this->_connectionID) { return false; - } else { - return $this->charSet; } + $this->charSet = pg_client_encoding($this->_connectionID); + return $this->charSet ?: false; } - // SetCharSet - switch the client encoding - function SetCharSet($charset_name) + /** + * Sets the client-side character set (encoding). + * + * Allows managing client encoding - very important if the database and + * the output target (i.e. HTML) don't match; for instance, you may have a + * UNICODE database and server your pages as WIN1251, etc. + * + * Supported on PostgreSQL 7.0 and above. Available charsets depend on + * PostgreSQL version and the distribution's compile flags. + * + * @param string $charset The character set to switch to. + * + * @return bool True if the character set was changed successfully, false otherwise. + */ + function setCharSet($charset) { - $this->GetCharSet(); - if ($this->charSet !== $charset_name) { - $if = pg_set_client_encoding($this->_connectionID, $charset_name); - if ($if == "0" & $this->GetCharSet() == $charset_name) { - return true; - } else return false; - } else return true; + if ($this->charSet !== $charset) { + if (!$this->_connectionID || pg_set_client_encoding($this->_connectionID, $charset) != 0) { + return false; + } + $this->getCharSet(); + } + return true; } } @@ -307,22 +293,14 @@ class ADORecordSet_postgres7 extends ADORecordSet_postgres64{ var $databaseType = "postgres7"; - - function __construct($queryID, $mode=false) - { - parent::__construct($queryID, $mode); - } - // 10% speedup to move MoveNext to child class function MoveNext() { if (!$this->EOF) { $this->_currentRow++; if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) { - $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode); - - if (is_array($this->fields)) { - if ($this->fields && isset($this->_blobArr)) $this->_fixblobs(); + $this->_prepfields(); + if ($this->fields !== false) { return true; } } @@ -339,25 +317,19 @@ class ADORecordSet_assoc_postgres7 extends ADORecordSet_postgres64{ var $databaseType = "postgres7"; - function __construct($queryID, $mode=false) - { - parent::__construct($queryID, $mode); - } - function _fetch() { if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0) { return false; } - $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode); - - if ($this->fields) { - if (isset($this->_blobArr)) $this->_fixblobs(); + $this->_prepfields(); + if ($this->fields !== false) { $this->_updatefields(); + return true; } - return (is_array($this->fields)); + return false; } function MoveNext() @@ -365,19 +337,13 @@ function MoveNext() if (!$this->EOF) { $this->_currentRow++; if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) { - $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode); - - if (is_array($this->fields)) { - if ($this->fields) { - if (isset($this->_blobArr)) $this->_fixblobs(); - - $this->_updatefields(); - } + $this->_prepfields(); + if ($this->fields !== false) { + $this->_updatefields(); return true; } } - $this->fields = false; $this->EOF = true; } diff --git a/www/include/adodb/drivers/adodb-postgres8.inc.php b/www/include/adodb/drivers/adodb-postgres8.inc.php new file mode 100644 index 00000000..37c2aae1 --- /dev/null +++ b/www/include/adodb/drivers/adodb-postgres8.inc.php @@ -0,0 +1,64 @@ +GetOne("SELECT lastval()") + : $this->GetOne("SELECT currval(pg_get_serial_sequence('$table', '$column'))"); + } +} + +class ADORecordSet_postgres8 extends ADORecordSet_postgres7 +{ + var $databaseType = "postgres8"; +} + +class ADORecordSet_assoc_postgres8 extends ADORecordSet_assoc_postgres7 +{ + var $databaseType = "postgres8"; +} diff --git a/www/include/adodb/drivers/adodb-postgres9.inc.php b/www/include/adodb/drivers/adodb-postgres9.inc.php new file mode 100644 index 00000000..fb9c6785 --- /dev/null +++ b/www/include/adodb/drivers/adodb-postgres9.inc.php @@ -0,0 +1,40 @@ +curmode = SQL_CUR_USE_ODBC; - parent::__construct(); - } - function ServerInfo() { $info = ADODB_odbc::ServerInfo(); @@ -55,7 +54,7 @@ function MetaPrimaryKeys($table, $owner = false) return $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table AND mode='KEY' ORDER BY pos"); } - function MetaIndexes ($table, $primary = FALSE, $owner = false) + function MetaIndexes ($table, $primary = FALSE, $owner = false) { $table = $this->Quote(strtoupper($table)); @@ -65,43 +64,43 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false) global $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== FALSE) { + $savem = $this->SetFetchMode(FALSE); + } - $rs = $this->Execute($sql); - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; + $rs = $this->Execute($sql); + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; - if (!is_object($rs)) { - return FALSE; - } + if (!is_object($rs)) { + return FALSE; + } $indexes = array(); while ($row = $rs->FetchRow()) { - $indexes[$row[0]]['unique'] = $row[1] == 'UNIQUE'; - $indexes[$row[0]]['columns'][] = $row[2]; - } + $indexes[$row[0]]['unique'] = $row[1] == 'UNIQUE'; + $indexes[$row[0]]['columns'][] = $row[2]; + } if ($primary) { $indexes['SYSPRIMARYKEYINDEX'] = array( 'unique' => True, // by definition 'columns' => $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table AND mode='KEY' ORDER BY pos"), ); } - return $indexes; + return $indexes; } function MetaColumns ($table, $normalize = true) { global $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== FALSE) { + $savem = $this->SetFetchMode(FALSE); + } $table = $this->Quote(strtoupper($table)); $retarr = array(); @@ -134,10 +133,10 @@ function MetaColumns ($table, $normalize = true) } $retarr[$fld->name] = $fld; } - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; return $retarr; } @@ -150,7 +149,7 @@ function MetaColumnNames($table, $numIndexes = false, $useattnum = false) } // unlike it seems, this depends on the db-session and works in a multiuser environment - function _insertid($table,$column) + protected function _insertID($table = '', $column = '') { return empty($table) ? False : $this->GetOne("SELECT $table.CURRVAL FROM DUAL"); } @@ -158,13 +157,13 @@ function _insertid($table,$column) /* SelectLimit implementation problems: - The following will return random 10 rows as order by performed after "WHERE rowno<10" - which is not ideal... + The following will return random 10 rows as order by performed after "WHERE rowno<10" + which is not ideal... - select * from table where rowno < 10 order by 1 + select * from table where rowno < 10 order by 1 - This means that we have to use the adoconnection base class SelectLimit when - there is an "order by". + This means that we have to use the adoconnection base class SelectLimit when + there is an "order by". See http://listserv.sap.com/pipermail/sapdb.general/2002-January/010405.html */ @@ -172,14 +171,10 @@ function _insertid($table,$column) }; -class ADORecordSet_sapdb extends ADORecordSet_odbc { +class ADORecordSet_sapdb extends ADORecordSet_odbc { var $databaseType = "sapdb"; - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } } } //define diff --git a/www/include/adodb5/drivers/adodb-sqlanywhere.inc.php b/www/include/adodb/drivers/adodb-sqlanywhere.inc.php similarity index 58% rename from www/include/adodb5/drivers/adodb-sqlanywhere.inc.php rename to www/include/adodb/drivers/adodb-sqlanywhere.inc.php index 03a9da2a..88897af9 100644 --- a/www/include/adodb5/drivers/adodb-sqlanywhere.inc.php +++ b/www/include/adodb/drivers/adodb-sqlanywhere.inc.php @@ -1,66 +1,44 @@ create_blobvar($blobVarName); - - b) load blob var from file. $filename must be complete path - - $dbcon->load_blobvar_from_file($blobVarName, $filename); - - c) Use the $blobVarName in SQL insert or update statement in the values - clause: - - $recordSet = $dbconn->Execute('INSERT INTO tabname (idcol, blobcol) ' - . - 'VALUES (\'test\', ' . $blobVarName . ')'); - - instead of loading blob from a file, you can also load from - an unformatted (raw) blob variable: - $dbcon->load_blobvar_from_var($blobVarName, $varName); - - d) drop blob variable on db server to free up resources: - $dbconn->drop_blobvar($blobVarName); - - Sybase_SQLAnywhere data driver. Requires ODBC. - -*/ +/** + * SAP SQL Anywhere driver (previously Sybase SQL Anywhere) + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); if (!defined('_ADODB_ODBC_LAYER')) { - include(ADODB_DIR."/drivers/adodb-odbc.inc.php"); + include_once(ADODB_DIR."/drivers/adodb-odbc.inc.php"); } if (!defined('ADODB_SYBASE_SQLANYWHERE')){ define('ADODB_SYBASE_SQLANYWHERE',1); - class ADODB_sqlanywhere extends ADODB_odbc { - var $databaseType = "sqlanywhere"; - var $hasInsertID = true; + class ADODB_sqlanywhere extends ADODB_odbc + { + var $databaseType = "sqlanywhere"; + var $hasInsertID = true; - function _insertid() { - return $this->GetOne('select @@identity'); - } + protected function _insertID($table = '', $column = '') + { + return $this->GetOne('select @@identity'); + } function create_blobvar($blobVarName) { $this->Execute("create variable $blobVarName long binary"); @@ -153,11 +131,6 @@ class ADORecordSet_sqlanywhere extends ADORecordSet_odbc { var $databaseType = "sqlanywhere"; - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } - }; //class diff --git a/www/include/adodb5/drivers/adodb-sqlite.inc.php b/www/include/adodb/drivers/adodb-sqlite.inc.php similarity index 82% rename from www/include/adodb5/drivers/adodb-sqlite.inc.php rename to www/include/adodb/drivers/adodb-sqlite.inc.php index 5cc6b9ea..0711f1dd 100644 --- a/www/include/adodb5/drivers/adodb-sqlite.inc.php +++ b/www/include/adodb/drivers/adodb-sqlite.inc.php @@ -1,27 +1,34 @@ hasInsertID = true; } - function _insertid() + protected function _insertID($table = '', $column = '') { return sqlite_last_insert_rowid($this->_connectionID); } @@ -226,6 +229,8 @@ function _query($sql,$inputarr=false) function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) { + $nrows = (int) $nrows; + $offset = (int) $offset; $offsetStr = ($offset >= 0) ? " OFFSET $offset" : ''; $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : ''); if ($secs2cache) { @@ -353,6 +358,63 @@ function MetaIndexes($table, $primary = FALSE, $owner = false) return $indexes; } + /** + * Returns the maximum size of a MetaType C field. Because of the + * database design, sqlite places no limits on the size of data inserted + * + * @return int + */ + function charMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + /** + * Returns the maximum size of a MetaType X field. Because of the + * database design, sqlite places no limits on the size of data inserted + * + * @return int + */ + function textMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + /* + * Converts a date to a month only field and pads it to 2 characters + * + * @param str $fld The name of the field to process + * @return str The SQL Statement + */ + function month($fld) + { + $x = "strftime('%m',$fld)"; + + return $x; + } + + /* + * Converts a date to a day only field and pads it to 2 characters + * + * @param str $fld The name of the field to process + * @return str The SQL Statement + */ + function day($fld) { + $x = "strftime('%d',$fld)"; + return $x; + } + + /* + * Converts a date to a year only field + * + * @param str $fld The name of the field to process + * @return str The SQL Statement + */ + function year($fld) { + $x = "strftime('%Y',$fld)"; + + return $x; + } } /*-------------------------------------------------------------------------------------- diff --git a/www/include/adodb/drivers/adodb-sqlite3.inc.php b/www/include/adodb/drivers/adodb-sqlite3.inc.php new file mode 100644 index 00000000..318171a8 --- /dev/null +++ b/www/include/adodb/drivers/adodb-sqlite3.inc.php @@ -0,0 +1,810 @@ +transOff) { + return true; + } + $this->Execute("BEGIN TRANSACTION"); + $this->transCnt += 1; + return true; + } + + function CommitTrans($ok=true) + { + if ($this->transOff) { + return true; + } + if (!$ok) { + return $this->RollbackTrans(); + } + $ret = $this->Execute("COMMIT"); + if ($this->transCnt > 0) { + $this->transCnt -= 1; + } + return !empty($ret); + } + + function RollbackTrans() + { + if ($this->transOff) { + return true; + } + $ret = $this->Execute("ROLLBACK"); + if ($this->transCnt > 0) { + $this->transCnt -= 1; + } + return !empty($ret); + } + + function metaType($t,$len=-1,$fieldobj=false) + { + + if (is_object($t)) + { + $fieldobj = $t; + $t = $fieldobj->type; + $len = $fieldobj->max_length; + } + + $t = strtoupper($t); + + if (array_key_exists($t,$this->customActualTypes)) + return $this->customActualTypes[$t]; + + /* + * We are using the Sqlite affinity method here + * @link https://www.sqlite.org/datatype3.html + */ + $affinity = array( + 'INT'=>'INTEGER', + 'INTEGER'=>'INTEGER', + 'TINYINT'=>'INTEGER', + 'SMALLINT'=>'INTEGER', + 'MEDIUMINT'=>'INTEGER', + 'BIGINT'=>'INTEGER', + 'UNSIGNED BIG INT'=>'INTEGER', + 'INT2'=>'INTEGER', + 'INT8'=>'INTEGER', + + 'CHARACTER'=>'TEXT', + 'VARCHAR'=>'TEXT', + 'VARYING CHARACTER'=>'TEXT', + 'NCHAR'=>'TEXT', + 'NATIVE CHARACTER'=>'TEXT', + 'NVARCHAR'=>'TEXT', + 'TEXT'=>'TEXT', + 'CLOB'=>'TEXT', + + 'BLOB'=>'BLOB', + + 'REAL'=>'REAL', + 'DOUBLE'=>'REAL', + 'DOUBLE PRECISION'=>'REAL', + 'FLOAT'=>'REAL', + + 'NUMERIC'=>'NUMERIC', + 'DECIMAL'=>'NUMERIC', + 'BOOLEAN'=>'NUMERIC', + 'DATE'=>'NUMERIC', + 'DATETIME'=>'NUMERIC' + ); + + if (!isset($affinity[$t])) + return ADODB_DEFAULT_METATYPE; + + $subt = $affinity[$t]; + /* + * Now that we have subclassed the provided data down + * the sqlite 'affinity', we convert to ADOdb metatype + */ + + $subclass = array('INTEGER'=>'I', + 'TEXT'=>'X', + 'BLOB'=>'B', + 'REAL'=>'N', + 'NUMERIC'=>'N'); + + return $subclass[$subt]; + } + // mark newnham + function MetaColumns($table, $normalize=true) + { + global $ADODB_FETCH_MODE; + $false = false; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; + if ($this->fetchMode !== false) { + $savem = $this->SetFetchMode(false); + } + $rs = $this->Execute("PRAGMA table_info('$table')"); + if (isset($savem)) { + $this->SetFetchMode($savem); + } + if (!$rs) { + $ADODB_FETCH_MODE = $save; + return $false; + } + $arr = array(); + while ($r = $rs->FetchRow()) { + $type = explode('(',$r['type']); + $size = ''; + if (sizeof($type)==2) { + $size = trim($type[1],')'); + } + $fn = strtoupper($r['name']); + $fld = new ADOFieldObject; + $fld->name = $r['name']; + $fld->type = $type[0]; + $fld->max_length = $size; + $fld->not_null = $r['notnull']; + $fld->default_value = $r['dflt_value']; + $fld->scale = 0; + if (isset($r['pk']) && $r['pk']) { + $fld->primary_key=1; + } + if ($save == ADODB_FETCH_NUM) { + $arr[] = $fld; + } else { + $arr[strtoupper($fld->name)] = $fld; + } + } + $rs->Close(); + $ADODB_FETCH_MODE = $save; + return $arr; + } + + public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) + { + global $ADODB_FETCH_MODE; + if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC + || $this->fetchMode == ADODB_FETCH_ASSOC) + $associative = true; + + /* + * Read sqlite master to find foreign keys + */ + $sql = "SELECT sql + FROM ( + SELECT sql sql, type type, tbl_name tbl_name, name name + FROM sqlite_master + ) + WHERE type != 'meta' + AND sql NOTNULL + AND LOWER(name) ='" . strtolower($table) . "'"; + + $tableSql = $this->getOne($sql); + + $fkeyList = array(); + $ylist = preg_split("/,+/",$tableSql); + foreach ($ylist as $y) + { + if (!preg_match('/FOREIGN/',$y)) + continue; + + $matches = false; + preg_match_all('/\((.+?)\)/i',$y,$matches); + $tmatches = false; + preg_match_all('/REFERENCES (.+?)\(/i',$y,$tmatches); + + if ($associative) + { + if (!isset($fkeyList[$tmatches[1][0]])) + $fkeyList[$tmatches[1][0]] = array(); + $fkeyList[$tmatches[1][0]][$matches[1][0]] = $matches[1][1]; + } + else + $fkeyList[$tmatches[1][0]][] = $matches[1][0] . '=' . $matches[1][1]; + } + + if ($associative) + { + if ($upper) + $fkeyList = array_change_key_case($fkeyList,CASE_UPPER); + else + $fkeyList = array_change_key_case($fkeyList,CASE_LOWER); + } + return $fkeyList; + } + + + function _init($parentDriver) + { + $parentDriver->hasTransactions = false; + $parentDriver->hasInsertID = true; + } + + protected function _insertID($table = '', $column = '') + { + return $this->_connectionID->lastInsertRowID(); + } + + function _affectedrows() + { + return $this->_connectionID->changes(); + } + + function ErrorMsg() + { + if ($this->_logsql) { + return $this->_errorMsg; + } + return ($this->_errorNo) ? $this->ErrorNo() : ''; //**tochange? + } + + function ErrorNo() + { + return $this->_connectionID->lastErrorCode(); //**tochange?? + } + + function SQLDate($fmt, $col=false) + { + /* + * In order to map the values correctly, we must ensure the proper + * casing for certain fields + * Y must be UC, because y is a 2 digit year + * d must be LC, because D is 3 char day + * A must be UC because a is non-portable am + * Q must be UC because q means nothing + */ + $fromChars = array('y','D','a','q'); + $toChars = array('Y','d','A','Q'); + $fmt = str_replace($fromChars,$toChars,$fmt); + + $fmt = $this->qstr($fmt); + return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)"; + } + + function _createFunctions() + { + $this->_connectionID->createFunction('adodb_date', 'adodb_date', 1); + $this->_connectionID->createFunction('adodb_date2', 'adodb_date2', 2); + } + + /** @noinspection PhpUnusedParameterInspection */ + function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + if (empty($argHostname) && $argDatabasename) { + $argHostname = $argDatabasename; + } + $this->_connectionID = new SQLite3($argHostname); + $this->_createFunctions(); + + return true; + } + + function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) + { + // There's no permanent connect in SQLite3 + return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); + } + + // returns query ID if successful, otherwise false + function _query($sql,$inputarr=false) + { + $rez = $this->_connectionID->query($sql); + if ($rez === false) { + $this->_errorNo = $this->_connectionID->lastErrorCode(); + } + // If no data was returned, we don't need to create a real recordset + elseif ($rez->numColumns() == 0) { + $rez->finalize(); + $rez = true; + } + + return $rez; + } + + function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) + { + $nrows = (int) $nrows; + $offset = (int) $offset; + $offsetStr = ($offset >= 0) ? " OFFSET $offset" : ''; + $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : ''); + if ($secs2cache) { + $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr); + } else { + $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr); + } + + return $rs; + } + + /* + This algorithm is not very efficient, but works even if table locking + is not available. + + Will return false if unable to generate an ID after $MAXLOOPS attempts. + */ + var $_genSeqSQL = "create table %s (id integer)"; + + function GenID($seq='adodbseq',$start=1) + { + // if you have to modify the parameter below, your database is overloaded, + // or you need to implement generation of id's yourself! + $MAXLOOPS = 100; + //$this->debug=1; + while (--$MAXLOOPS>=0) { + @($num = $this->GetOne("select id from $seq")); + if ($num === false) { + $this->Execute(sprintf($this->_genSeqSQL ,$seq)); + $start -= 1; + $num = '0'; + $ok = $this->Execute("insert into $seq values($start)"); + if (!$ok) { + return false; + } + } + $this->Execute("update $seq set id=id+1 where id=$num"); + + if ($this->affected_rows() > 0) { + $num += 1; + $this->genID = $num; + return $num; + } + } + if ($fn = $this->raiseErrorFn) { + $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num); + } + return false; + } + + function createSequence($seqname='adodbseq', $startID=1) + { + if (empty($this->_genSeqSQL)) { + return false; + } + $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); + if (!$ok) { + return false; + } + $startID -= 1; + return $this->Execute("insert into $seqname values($startID)"); + } + + var $_dropSeqSQL = 'drop table %s'; + function DropSequence($seqname = 'adodbseq') + { + if (empty($this->_dropSeqSQL)) { + return false; + } + return $this->Execute(sprintf($this->_dropSeqSQL,$seqname)); + } + + // returns true or false + function _close() + { + return $this->_connectionID->close(); + } + + function metaIndexes($table, $primary = FALSE, $owner = false) + { + $false = false; + // save old fetch mode + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== FALSE) { + $savem = $this->SetFetchMode(FALSE); + } + + $pragmaData = array(); + + /* + * If we want the primary key, we must extract + * it from the table statement, and the pragma + */ + if ($primary) + { + $sql = sprintf('PRAGMA table_info([%s]);', + strtolower($table) + ); + $pragmaData = $this->getAll($sql); + } + + /* + * Exclude the empty entry for the primary index + */ + $sqlite = "SELECT name,sql + FROM sqlite_master + WHERE type='index' + AND sql IS NOT NULL + AND LOWER(tbl_name)='%s'"; + + $SQL = sprintf($sqlite, + strtolower($table) + ); + + $rs = $this->execute($SQL); + + if (!is_object($rs)) { + if (isset($savem)) { + $this->SetFetchMode($savem); + } + $ADODB_FETCH_MODE = $save; + return $false; + } + + $indexes = array (); + + while ($row = $rs->FetchRow()) + { + + if (!isset($indexes[$row[0]])) { + $indexes[$row[0]] = array( + 'unique' => preg_match("/unique/i",$row[1]), + 'columns' => array() + ); + } + /** + * The index elements appear in the SQL statement + * in cols[1] between parentheses + * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse) + */ + preg_match_all('/\((.*)\)/',$row[1],$indexExpression); + $indexes[$row[0]]['columns'] = array_map('trim',explode(',',$indexExpression[1][0])); + } + + if (isset($savem)) { + $this->SetFetchMode($savem); + $ADODB_FETCH_MODE = $save; + } + + /* + * If we want primary, add it here + */ + if ($primary){ + + /* + * Check the previously retrieved pragma to search + * with a closure + */ + + $pkIndexData = array('unique'=>1,'columns'=>array()); + + $pkCallBack = function ($value, $key) use (&$pkIndexData) { + + /* + * As we iterate the elements check for pk index and sort + */ + if ($value[5] > 0) + { + $pkIndexData['columns'][$value[5]] = strtolower($value[1]); + ksort($pkIndexData['columns']); + } + }; + + array_walk($pragmaData,$pkCallBack); + + /* + * If we found no columns, there is no + * primary index + */ + if (count($pkIndexData['columns']) > 0) + $indexes['PRIMARY'] = $pkIndexData; + } + + return $indexes; + } + + /** + * Returns the maximum size of a MetaType C field. Because of the + * database design, sqlite places no limits on the size of data inserted + * + * @return int + */ + function charMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + /** + * Returns the maximum size of a MetaType X field. Because of the + * database design, sqlite places no limits on the size of data inserted + * + * @return int + */ + function textMax() + { + return ADODB_STRINGMAX_NOLIMIT; + } + + /** + * Converts a date to a month only field and pads it to 2 characters + * + * This uses the more efficient strftime native function to process + * + * @param string $fld The name of the field to process + * + * @return string The SQL Statement + */ + function month($fld) + { + return "strftime('%m',$fld)"; + } + + /** + * Converts a date to a day only field and pads it to 2 characters + * + * This uses the more efficient strftime native function to process + * + * @param string $fld The name of the field to process + * + * @return string The SQL Statement + */ + function day($fld) { + return "strftime('%d',$fld)"; + } + + /** + * Converts a date to a year only field + * + * This uses the more efficient strftime native function to process + * + * @param string $fld The name of the field to process + * + * @return string The SQL Statement + */ + function year($fld) + { + return "strftime('%Y',$fld)"; + } + + /** + * SQLite update for blob + * + * SQLite must be a fully prepared statement (all variables must be bound), + * so $where can either be an array (array params) or a string that we will + * do our best to unpack and turn into a prepared statement. + * + * @param string $table + * @param string $column + * @param string $val Blob value to set + * @param mixed $where An array of parameters (key => value pairs), + * or a string (where clause). + * @param string $blobtype ignored + * + * @return bool success + */ + function updateBlob($table, $column, $val, $where, $blobtype = 'BLOB') + { + if (is_array($where)) { + // We were passed a set of key=>value pairs + $params = $where; + } else { + // Given a where clause string, we have to disassemble the + // statements into keys and values + $params = array(); + $temp = preg_split('/(where|and)/i', $where); + $where = array_filter($temp); + + foreach ($where as $wValue) { + $wTemp = preg_split('/[= \']+/', $wValue); + $wTemp = array_filter($wTemp); + $wTemp = array_values($wTemp); + $params[$wTemp[0]] = $wTemp[1]; + } + } + + $paramWhere = array(); + foreach ($params as $bindKey => $bindValue) { + $paramWhere[] = $bindKey . '=?'; + } + + $sql = "UPDATE $table SET $column=? WHERE " + . implode(' AND ', $paramWhere); + + // Prepare the statement + $stmt = $this->_connectionID->prepare($sql); + + // Set the first bind value equal to value we want to update + if (!$stmt->bindValue(1, $val, SQLITE3_BLOB)) { + return false; + } + + // Build as many keys as available + $bindIndex = 2; + foreach ($params as $bindValue) { + if (is_integer($bindValue) || is_bool($bindValue) || is_float($bindValue)) { + $type = SQLITE3_NUM; + } elseif (is_object($bindValue)) { + // Assume a blob, this should never appear in + // the binding for a where statement anyway + $type = SQLITE3_BLOB; + } else { + $type = SQLITE3_TEXT; + } + + if (!$stmt->bindValue($bindIndex, $bindValue, $type)) { + return false; + } + + $bindIndex++; + } + + // Now execute the update. NB this is SQLite execute, not ADOdb + $ok = $stmt->execute(); + return is_object($ok); + } + + /** + * SQLite update for blob from a file + * + * @param string $table + * @param string $column + * @param string $path Filename containing blob data + * @param mixed $where {@see updateBlob()} + * @param string $blobtype ignored + * + * @return bool success + */ + function updateBlobFile($table, $column, $path, $where, $blobtype = 'BLOB') + { + if (!file_exists($path)) { + return false; + } + + // Read file information + $fileContents = file_get_contents($path); + if ($fileContents === false) + // Distinguish between an empty file and failure + return false; + + return $this->updateBlob($table, $column, $fileContents, $where, $blobtype); + } + +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ + +class ADORecordset_sqlite3 extends ADORecordSet { + + var $databaseType = "sqlite3"; + var $bind = false; + + /** @var SQLite3Result */ + var $_queryID; + + /** @noinspection PhpMissingParentConstructorInspection */ + function __construct($queryID,$mode=false) + { + if ($mode === false) { + global $ADODB_FETCH_MODE; + $mode = $ADODB_FETCH_MODE; + } + switch($mode) { + case ADODB_FETCH_NUM: + $this->fetchMode = SQLITE3_NUM; + break; + case ADODB_FETCH_ASSOC: + $this->fetchMode = SQLITE3_ASSOC; + break; + default: + $this->fetchMode = SQLITE3_BOTH; + break; + } + $this->adodbFetchMode = $mode; + + $this->_queryID = $queryID; + + $this->_inited = true; + $this->fields = array(); + if ($queryID) { + $this->_currentRow = 0; + $this->EOF = !$this->_fetch(); + @$this->_initrs(); + } else { + $this->_numOfRows = 0; + $this->_numOfFields = 0; + $this->EOF = true; + } + + return $this->_queryID; + } + + + function FetchField($fieldOffset = -1) + { + $fld = new ADOFieldObject; + $fld->name = $this->_queryID->columnName($fieldOffset); + $fld->type = 'VARCHAR'; + $fld->max_length = -1; + return $fld; + } + + function _initrs() + { + $this->_numOfFields = $this->_queryID->numColumns(); + + } + + function Fields($colname) + { + if ($this->fetchMode != SQLITE3_NUM) { + return $this->fields[$colname]; + } + if (!$this->bind) { + $this->bind = array(); + for ($i=0; $i < $this->_numOfFields; $i++) { + $o = $this->FetchField($i); + $this->bind[strtoupper($o->name)] = $i; + } + } + + return $this->fields[$this->bind[strtoupper($colname)]]; + } + + function _seek($row) + { + // sqlite3 does not implement seek + if ($this->debug) { + ADOConnection::outp("SQLite3 does not implement seek"); + } + return false; + } + + function _fetch($ignore_fields=false) + { + $this->fields = $this->_queryID->fetchArray($this->fetchMode); + return !empty($this->fields); + } + + function _close() + { + } + +} diff --git a/www/include/adodb/drivers/adodb-sqlitepo.inc.php b/www/include/adodb/drivers/adodb-sqlitepo.inc.php new file mode 100644 index 00000000..cb69ff9e --- /dev/null +++ b/www/include/adodb/drivers/adodb-sqlitepo.inc.php @@ -0,0 +1,61 @@ + + */ + +if (!defined('ADODB_DIR')) die(); + +include_once(ADODB_DIR.'/drivers/adodb-sqlite.inc.php'); + +class ADODB_sqlitepo extends ADODB_sqlite { + var $databaseType = 'sqlitepo'; +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ + +class ADORecordset_sqlitepo extends ADORecordset_sqlite { + + var $databaseType = 'sqlitepo'; + + // Modified to strip table names from returned fields + function _fetch($ignore_fields=false) + { + $this->fields = array(); + $fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode); + if(is_array($fields)) + foreach($fields as $n => $v) + { + if(($p = strpos($n, ".")) !== false) + $n = substr($n, $p+1); + $this->fields[$n] = $v; + } + + return !empty($this->fields); + } +} diff --git a/www/include/adodb5/drivers/adodb-sybase.inc.php b/www/include/adodb/drivers/adodb-sybase.inc.php similarity index 88% rename from www/include/adodb5/drivers/adodb-sybase.inc.php rename to www/include/adodb/drivers/adodb-sybase.inc.php index 6ba392d3..b8db0747 100644 --- a/www/include/adodb5/drivers/adodb-sybase.inc.php +++ b/www/include/adodb/drivers/adodb-sybase.inc.php @@ -1,21 +1,24 @@ + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -44,15 +47,15 @@ class ADODB_sybase extends ADOConnection { var $port; - function __construct() - { - } - - // might require begintrans -- committrans - function _insertid() + /** + * might require begintrans -- committrans + * @inheritDoc + */ + protected function _insertID($table = '', $column = '') { return $this->GetOne('select @@identity'); } + // might require begintrans -- committrans function _affectedrows() { @@ -117,8 +120,10 @@ function ErrorMsg() if ($this->_logsql) return $this->_errorMsg; if (function_exists('sybase_get_last_message')) $this->_errorMsg = sybase_get_last_message(); - else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : 'SYBASE error messages not supported on this platform'; + else { + $this->_errorMsg = 'SYBASE error messages not supported on this platform'; + } + return $this->_errorMsg; } @@ -133,9 +138,9 @@ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) } if ($this->charSet) { - $this->_connectionID = sybase_connect($argHostname,$argUsername,$argPassword, $this->charSet); + $this->_connectionID = @sybase_connect($argHostname,$argUsername,$argPassword, $this->charSet); } else { - $this->_connectionID = sybase_connect($argHostname,$argUsername,$argPassword); + $this->_connectionID = @sybase_connect($argHostname,$argUsername,$argPassword); } if ($this->_connectionID === false) return false; @@ -154,9 +159,9 @@ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) } if ($this->charSet) { - $this->_connectionID = sybase_pconnect($argHostname,$argUsername,$argPassword, $this->charSet); + $this->_connectionID = @sybase_pconnect($argHostname,$argUsername,$argPassword, $this->charSet); } else { - $this->_connectionID = sybase_pconnect($argHostname,$argUsername,$argPassword); + $this->_connectionID = @sybase_pconnect($argHostname,$argUsername,$argPassword); } if ($this->_connectionID === false) return false; @@ -169,7 +174,7 @@ function _query($sql,$inputarr=false) { global $ADODB_COUNTRECS; - if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300) + if ($ADODB_COUNTRECS == false) return sybase_unbuffered_query($sql,$this->_connectionID); else return sybase_query($sql,$this->_connectionID); @@ -318,7 +323,7 @@ function __construct($id,$mode=false) } if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC; else $this->fetchMode = $mode; - parent::__construct($id,$mode); + parent::__construct($id); } /* Returns: an object containing field information. @@ -391,12 +396,8 @@ static function UnixTimeStamp($v) } class ADORecordSet_array_sybase extends ADORecordSet_array { - function __construct($id=-1) - { - parent::__construct($id); - } - // sybase/mssql uses a default date like Dec 30 2000 12:00AM + // sybase/mssql uses a default date like Dec 30 2000 12:00AM static function UnixDate($v) { global $ADODB_sybase_mths; diff --git a/www/include/adodb5/drivers/adodb-sybase_ase.inc.php b/www/include/adodb/drivers/adodb-sybase_ase.inc.php similarity index 75% rename from www/include/adodb5/drivers/adodb-sybase_ase.inc.php rename to www/include/adodb/drivers/adodb-sybase_ase.inc.php index 669dd22f..d301ba99 100644 --- a/www/include/adodb5/drivers/adodb-sybase_ase.inc.php +++ b/www/include/adodb/drivers/adodb-sybase_ase.inc.php @@ -1,17 +1,24 @@ + */ require_once ADODB_DIR."/drivers/adodb-sybase.inc.php"; @@ -22,10 +29,6 @@ class ADODB_sybase_ase extends ADODB_sybase { var $metaColumnsSQL = "SELECT syscolumns.name AS field_name, systypes.name AS type, systypes.length AS width FROM sysobjects, syscolumns, systypes WHERE sysobjects.name='%s' AND syscolumns.id = sysobjects.id AND systypes.type=syscolumns.type"; var $metaDatabasesSQL ="SELECT a.name FROM master.dbo.sysdatabases a, master.dbo.syslogins b WHERE a.suid = b.suid and a.name like '%' and a.name != 'tempdb' and a.status3 != 256 order by 1"; - function __construct() - { - } - // split the Views, Tables and procedures. function MetaTables($ttype=false,$showSchema=false,$mask=false) { @@ -111,10 +114,5 @@ function ErrorMsg() } class adorecordset_sybase_ase extends ADORecordset_sybase { -var $databaseType = "sybase_ase"; -function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } - + var $databaseType = "sybase_ase"; } diff --git a/www/include/adodb5/drivers/adodb-text.inc.php b/www/include/adodb/drivers/adodb-text.inc.php similarity index 73% rename from www/include/adodb5/drivers/adodb-text.inc.php rename to www/include/adodb/drivers/adodb-text.inc.php index 347167a7..77ad06a0 100644 --- a/www/include/adodb5/drivers/adodb-text.inc.php +++ b/www/include/adodb/drivers/adodb-text.inc.php @@ -1,63 +1,25 @@ Connect($array,[$types],[$colnames]); - - Parameter $array is the 2 dimensional array of data. The first row can contain the - column names. If column names is not defined in first row, you MUST define $colnames, - the 3rd parameter. - - Parameter $types is optional. If defined, it should contain an array matching - the number of columns in $array, with each element matching the correct type defined - by MetaType: (B,C,I,L,N). If undefined, we will probe for $this->_proberows rows - to guess the type. Only C,I and N are recognised. - - Parameter $colnames is optional. If defined, it is an array that contains the - column names of $array. If undefined, we assume the first row of $array holds the - column names. - - The Execute() function will return a recordset. The recordset works like a normal recordset. - We have partial support for SQL parsing. We process the SQL using the following rules: - - 1. SQL order by's always work for the first column ordered. Subsequent cols are ignored - - 2. All operations take place on the same table. No joins possible. In fact the FROM clause - is ignored! You can use any name for the table. - - 3. To simplify code, all columns are returned, except when selecting 1 column - - $rs = $db->Execute('select col1,col2 from table'); // sql ignored, will generate all cols - - We special case handling of 1 column because it is used in filter popups - - $rs = $db->Execute('select col1 from table'); - // sql accepted and processed -- any table name is accepted - - $rs = $db->Execute('select distinct col1 from table'); - // sql accepted and processed - -4. Where clauses are ignored, but searching with the 3rd parameter of Execute is permitted. - This has to use PHP syntax and we will eval() it. You can even use PHP functions. - - $rs = $db->Execute('select * from table',false,"\$COL1='abc' and $\COL2=3") - // the 3rd param is searched -- make sure that $COL1 is a legal column name - // and all column names must be in upper case. - -4. Group by, having, other clauses are ignored - -5. Expression columns, min(), max() are ignored - -6. All data is readonly. Only SELECTs permitted. -*/ +/** + * ADOdb Plain Text driver + * + * @deprecated + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // security - hide paths if (!defined('ADODB_DIR')) die(); @@ -90,10 +52,6 @@ class ADODB_text extends ADOConnection { var $_reznames; var $_reztypes; - function __construct() - { - } - function RSRecordCount() { if (!empty($this->_rezarray)) return sizeof($this->_rezarray); @@ -101,11 +59,6 @@ function RSRecordCount() return sizeof($this->_origarray); } - function _insertid() - { - return false; - } - function _affectedrows() { return false; @@ -209,7 +162,7 @@ function _query($sql,$input_arr,$eval=false) $where_arr = array(); reset($this->_origarray); - while (list($k_arr,$arr) = each($this->_origarray)) { + foreach ($this->_origarray as $arr) { if ($i == 0 && $this->_skiprow1) $where_arr[] = $arr; @@ -247,7 +200,7 @@ function _query($sql,$input_arr,$eval=false) $i = 0; $n = ''; reset($this->_colnames); - while (list($k_n,$n) = each($this->_colnames)) { + foreach ($this->_colnames as $n) { if ($col == strtoupper(trim($n))) break; $i += 1; @@ -259,8 +212,7 @@ function _query($sql,$input_arr,$eval=false) $projtypes = array($this->_types[$i]); $projnames = array($n); - reset($where_arr); - while (list($k_a,$a) = each($where_arr)) { + foreach ($where_arr as $a) { if ($i == 0 && $this->_skiprow1) { $projarray[] = array($n); continue; @@ -302,7 +254,7 @@ function _query($sql,$input_arr,$eval=false) if ($at == 0) { $i = 0; reset($projnames); - while (list($k_n,$n) = each($projnames)) { + foreach ($projnames as $n) { if (strtoupper(trim($n)) == $col) { $at = $i+1; break; @@ -326,7 +278,7 @@ function _query($sql,$input_arr,$eval=false) // check for desc sort $orderby = substr($orderby,strlen($col)+1); - $arr == array(); + $arr = array(); preg_match('/([A-Z_0-9]*)/i',$orderby,$arr); if (trim($arr[1]) == 'DESC') $sortf = 'adodb_cmpr'; @@ -376,7 +328,7 @@ class ADORecordSet_text extends ADORecordSet_array var $databaseType = "text"; - function __construct(&$conn,$mode=false) + function __construct( $conn,$mode=false) { parent::__construct(); $this->InitArray($conn->_rezarray,$conn->_reztypes,$conn->_reznames); diff --git a/www/include/adodb5/drivers/adodb-vfp.inc.php b/www/include/adodb/drivers/adodb-vfp.inc.php similarity index 67% rename from www/include/adodb5/drivers/adodb-vfp.inc.php rename to www/include/adodb/drivers/adodb-vfp.inc.php index 840c9c10..bb435168 100644 --- a/www/include/adodb5/drivers/adodb-vfp.inc.php +++ b/www/include/adodb/drivers/adodb-vfp.inc.php @@ -1,23 +1,31 @@ +/** + * Arabic language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author El-Shamaa, Khaled + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'ar', DB_ERROR => 'خطأ غير محدد', diff --git a/www/include/adodb5/lang/adodb-bg.inc.php b/www/include/adodb/lang/adodb-bg.inc.php similarity index 74% rename from www/include/adodb5/lang/adodb-bg.inc.php rename to www/include/adodb/lang/adodb-bg.inc.php index 07069b42..bbfd92f2 100644 --- a/www/include/adodb5/lang/adodb-bg.inc.php +++ b/www/include/adodb/lang/adodb-bg.inc.php @@ -1,8 +1,24 @@ -*/ +/** + * Bulgarian language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Valentin Sheiretsky + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'bg', diff --git a/www/include/adodb5/lang/adodb-ca.inc.php b/www/include/adodb/lang/adodb-ca.inc.php similarity index 71% rename from www/include/adodb5/lang/adodb-ca.inc.php rename to www/include/adodb/lang/adodb-ca.inc.php index adbafac9..4b046884 100644 --- a/www/include/adodb5/lang/adodb-ca.inc.php +++ b/www/include/adodb/lang/adodb-ca.inc.php @@ -1,6 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'ca', DB_ERROR => 'error desconegut', diff --git a/www/include/adodb5/lang/adodb-cn.inc.php b/www/include/adodb/lang/adodb-cn.inc.php similarity index 69% rename from www/include/adodb5/lang/adodb-cn.inc.php rename to www/include/adodb/lang/adodb-cn.inc.php index 9c973413..512ffb82 100644 --- a/www/include/adodb5/lang/adodb-cn.inc.php +++ b/www/include/adodb/lang/adodb-cn.inc.php @@ -1,6 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'cn', DB_ERROR => '未知错误', diff --git a/www/include/adodb5/lang/adodb-cz.inc.php b/www/include/adodb/lang/adodb-cz.inc.php similarity index 69% rename from www/include/adodb5/lang/adodb-cz.inc.php rename to www/include/adodb/lang/adodb-cz.inc.php index d79d7142..eb2fb2e3 100644 --- a/www/include/adodb5/lang/adodb-cz.inc.php +++ b/www/include/adodb/lang/adodb-cz.inc.php @@ -1,7 +1,24 @@ +/** + * Czech language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Kamil Jakubovic + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'cz', diff --git a/www/include/adodb5/lang/adodb-da.inc.php b/www/include/adodb/lang/adodb-da.inc.php similarity index 70% rename from www/include/adodb5/lang/adodb-da.inc.php rename to www/include/adodb/lang/adodb-da.inc.php index 14e720b8..e4c655be 100644 --- a/www/include/adodb5/lang/adodb-da.inc.php +++ b/www/include/adodb/lang/adodb-da.inc.php @@ -1,5 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'da', DB_ERROR => 'ukendt fejl', diff --git a/www/include/adodb/lang/adodb-de.inc.php b/www/include/adodb/lang/adodb-de.inc.php new file mode 100644 index 00000000..a02dd729 --- /dev/null +++ b/www/include/adodb/lang/adodb-de.inc.php @@ -0,0 +1,52 @@ + + */ + +$ADODB_LANG_ARRAY = array ( + 'LANG' => 'de', + DB_ERROR => 'unbekannter Fehler', + DB_ERROR_ALREADY_EXISTS => 'existiert bereits', + DB_ERROR_CANNOT_CREATE => 'kann nicht erstellen', + DB_ERROR_CANNOT_DELETE => 'kann nicht löschen', + DB_ERROR_CANNOT_DROP => 'Tabelle oder Index konnte nicht gelöscht werden', + DB_ERROR_CONSTRAINT => 'Randbedingung verletzt', + DB_ERROR_DIVZERO => 'Division durch Null', + DB_ERROR_INVALID => 'ungültig', + DB_ERROR_INVALID_DATE => 'ungültiges Datum oder Zeit', + DB_ERROR_INVALID_NUMBER => 'ungültige Zahl', + DB_ERROR_MISMATCH => 'Unverträglichkeit', + DB_ERROR_NODBSELECTED => 'Keine Datenbank ausgewählt', + DB_ERROR_NOSUCHFIELD => 'Feld nicht vorhanden', + DB_ERROR_NOSUCHTABLE => 'Tabelle nicht vorhanden', + DB_ERROR_NOT_CAPABLE => 'Funktion nicht installiert', + DB_ERROR_NOT_FOUND => 'nicht gefunden', + DB_ERROR_NOT_LOCKED => 'nicht gesperrt', + DB_ERROR_SYNTAX => 'Syntaxfehler', + DB_ERROR_UNSUPPORTED => 'nicht unterstützt', + DB_ERROR_VALUE_COUNT_ON_ROW => 'Anzahl der zurückgelieferten Felder entspricht nicht der Anzahl der Felder in der Abfrage', + DB_ERROR_INVALID_DSN => 'ungültiger DSN', + DB_ERROR_CONNECT_FAILED => 'Verbindung konnte nicht hergestellt werden', + 0 => 'kein Fehler', // DB_OK + DB_ERROR_NEED_MORE_DATA => 'Nicht genügend Daten geliefert', + DB_ERROR_EXTENSION_NOT_FOUND=> 'Erweiterung nicht gefunden', + DB_ERROR_NOSUCHDB => 'keine Datenbank', + DB_ERROR_ACCESS_VIOLATION => 'ungenügende Rechte' +); diff --git a/www/include/adodb5/lang/adodb-en.inc.php b/www/include/adodb/lang/adodb-en.inc.php similarity index 72% rename from www/include/adodb5/lang/adodb-en.inc.php rename to www/include/adodb/lang/adodb-en.inc.php index 05828554..74c4ea02 100644 --- a/www/include/adodb5/lang/adodb-en.inc.php +++ b/www/include/adodb/lang/adodb-en.inc.php @@ -1,4 +1,23 @@ 'en', diff --git a/www/include/adodb5/lang/adodb-eo.inc.php b/www/include/adodb/lang/adodb-eo.inc.php similarity index 69% rename from www/include/adodb5/lang/adodb-eo.inc.php rename to www/include/adodb/lang/adodb-eo.inc.php index baa589c1..107a3b37 100644 --- a/www/include/adodb5/lang/adodb-eo.inc.php +++ b/www/include/adodb/lang/adodb-eo.inc.php @@ -1,6 +1,24 @@ + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'eo', diff --git a/www/include/adodb5/lang/adodb-es.inc.php b/www/include/adodb/lang/adodb-es.inc.php similarity index 70% rename from www/include/adodb5/lang/adodb-es.inc.php rename to www/include/adodb/lang/adodb-es.inc.php index a80a6441..bcb0ccea 100644 --- a/www/include/adodb5/lang/adodb-es.inc.php +++ b/www/include/adodb/lang/adodb-es.inc.php @@ -1,5 +1,25 @@ +/** + * Spanish language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Horacio Degiorgi + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'es', DB_ERROR => 'error desconocido', diff --git a/www/include/adodb5/lang/adodb-fa.inc.php b/www/include/adodb/lang/adodb-fa.inc.php similarity index 72% rename from www/include/adodb5/lang/adodb-fa.inc.php rename to www/include/adodb/lang/adodb-fa.inc.php index 7fa46183..84f17bd8 100644 --- a/www/include/adodb5/lang/adodb-fa.inc.php +++ b/www/include/adodb/lang/adodb-fa.inc.php @@ -1,6 +1,24 @@ */ +/** + * Farsi language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Peyman Hooshmandi Raad" + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'fa', diff --git a/www/include/adodb5/lang/adodb-fr.inc.php b/www/include/adodb/lang/adodb-fr.inc.php similarity index 68% rename from www/include/adodb5/lang/adodb-fr.inc.php rename to www/include/adodb/lang/adodb-fr.inc.php index 620196b4..b010d1e5 100644 --- a/www/include/adodb5/lang/adodb-fr.inc.php +++ b/www/include/adodb/lang/adodb-fr.inc.php @@ -1,4 +1,23 @@ 'fr', diff --git a/www/include/adodb5/lang/adodb-hu.inc.php b/www/include/adodb/lang/adodb-hu.inc.php similarity index 70% rename from www/include/adodb5/lang/adodb-hu.inc.php rename to www/include/adodb/lang/adodb-hu.inc.php index 49357ce2..5a73827b 100644 --- a/www/include/adodb5/lang/adodb-hu.inc.php +++ b/www/include/adodb/lang/adodb-hu.inc.php @@ -1,6 +1,25 @@ +/** + * Hungarian language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Halászvári Gábor + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'hu', DB_ERROR => 'ismeretlen hiba', diff --git a/www/include/adodb/lang/adodb-id.inc.php b/www/include/adodb/lang/adodb-id.inc.php new file mode 100644 index 00000000..abd38eee --- /dev/null +++ b/www/include/adodb/lang/adodb-id.inc.php @@ -0,0 +1,55 @@ + + */ + +$ADODB_LANG_ARRAY = array ( + 'LANG' => 'id', + DB_ERROR => 'kesalahan tidak diketahui', + DB_ERROR_ALREADY_EXISTS => 'sudah ada', + DB_ERROR_CANNOT_CREATE => 'tak dapat membuat', + DB_ERROR_CANNOT_DELETE => 'tak dapat menghapus', + DB_ERROR_CANNOT_DROP => 'tak dapat menghapus', + DB_ERROR_CONSTRAINT => 'pelanggaran kendala', + DB_ERROR_DIVZERO => 'pembagian dengan 0', + DB_ERROR_INVALID => 'tidak sah', + DB_ERROR_INVALID_DATE => 'tanggal atau waktu tidak valid', + DB_ERROR_INVALID_NUMBER => 'nomor tidak sah', + DB_ERROR_MISMATCH => 'tak cocok', + DB_ERROR_NODBSELECTED => 'tak ada database dipilih', + DB_ERROR_NOSUCHFIELD => 'kolom tak ditemukan', + DB_ERROR_NOSUCHTABLE => 'tabel tak ditemukan', + DB_ERROR_NOT_CAPABLE => 'kemampuan DB tak memadai', + DB_ERROR_NOT_FOUND => 'tidak ditemukan', + DB_ERROR_NOT_LOCKED => 'tidak terkunci', + DB_ERROR_SYNTAX => 'kesalahan sintak', + DB_ERROR_UNSUPPORTED => 'tak didukung', + DB_ERROR_VALUE_COUNT_ON_ROW => 'menghitung isi pada baris', + DB_ERROR_INVALID_DSN => 'DSN tidak sah', + DB_ERROR_CONNECT_FAILED => 'koneksi gagal', + 0 => 'tak ada kesalahan', // DB_OK + DB_ERROR_NEED_MORE_DATA => 'data yang dimasukan tidak memadai', + DB_ERROR_EXTENSION_NOT_FOUND=> 'ekstensi tak ditemukan', + DB_ERROR_NOSUCHDB => 'database tak ditemukan', + DB_ERROR_ACCESS_VIOLATION => 'izin tidak memadai', + DB_ERROR_DEADLOCK => 'kebuntuan terdeteksi', + DB_ERROR_STATEMENT_TIMEOUT => 'perintah kehabisan waktu', + DB_ERROR_SERIALIZATION_FAILURE => 'tak dapat melanjutkan akses' +); diff --git a/www/include/adodb5/lang/adodb-it.inc.php b/www/include/adodb/lang/adodb-it.inc.php similarity index 70% rename from www/include/adodb5/lang/adodb-it.inc.php rename to www/include/adodb/lang/adodb-it.inc.php index 80524e1d..a6516308 100644 --- a/www/include/adodb5/lang/adodb-it.inc.php +++ b/www/include/adodb/lang/adodb-it.inc.php @@ -1,6 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'it', DB_ERROR => 'errore sconosciuto', diff --git a/www/include/adodb5/lang/adodb-nl.inc.php b/www/include/adodb/lang/adodb-nl.inc.php similarity index 69% rename from www/include/adodb5/lang/adodb-nl.inc.php rename to www/include/adodb/lang/adodb-nl.inc.php index 43e3ee69..8a898193 100644 --- a/www/include/adodb5/lang/adodb-nl.inc.php +++ b/www/include/adodb/lang/adodb-nl.inc.php @@ -1,5 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'nl', DB_ERROR => 'onbekende fout', diff --git a/www/include/adodb/lang/adodb-oc.inc.php b/www/include/adodb/lang/adodb-oc.inc.php new file mode 100644 index 00000000..3481e79a --- /dev/null +++ b/www/include/adodb/lang/adodb-oc.inc.php @@ -0,0 +1,51 @@ + 'oc', + DB_ERROR => 'error desconeguda', + DB_ERROR_ALREADY_EXISTS => 'existís ja', + DB_ERROR_CANNOT_CREATE => 'creacion impossibla', + DB_ERROR_CANNOT_DELETE => 'escafament impossible', + DB_ERROR_CANNOT_DROP => 'supression impossibla', + DB_ERROR_CONSTRAINT => 'violacion de constrenta', + DB_ERROR_DIVZERO => 'division per zèro', + DB_ERROR_INVALID => 'invalid', + DB_ERROR_INVALID_DATE => 'data o ora invalida', + DB_ERROR_INVALID_NUMBER => 'nombre invalid', + DB_ERROR_MISMATCH => 'error de concordància', + DB_ERROR_NODBSELECTED => 'pas de basa de donadas de seleccionada', + DB_ERROR_NOSUCHFIELD => 'nom de colomna invalid', + DB_ERROR_NOSUCHTABLE => 'taula o vista inexistenta', + DB_ERROR_NOT_CAPABLE => 'foncion opcionala pas installada', + DB_ERROR_NOT_FOUND => 'pas trobat', + DB_ERROR_NOT_LOCKED => 'pas verrolhat', + DB_ERROR_SYNTAX => 'error de sintaxi', + DB_ERROR_UNSUPPORTED => 'pas suportat', + DB_ERROR_VALUE_COUNT_ON_ROW => 'valor inserida tròp granda per colomna', + DB_ERROR_INVALID_DSN => 'DSN invalid', + DB_ERROR_CONNECT_FAILED => 'fracàs a la connexion', + 0 => "pas d'error", // DB_OK + DB_ERROR_NEED_MORE_DATA => 'donadas provesidas insufisentas', + DB_ERROR_EXTENSION_NOT_FOUND=> 'extension pas trobada', + DB_ERROR_NOSUCHDB => 'basa de donadas desconeguda', + DB_ERROR_ACCESS_VIOLATION => 'dreits insufisents' +); diff --git a/www/include/adodb5/lang/adodb-pl.inc.php b/www/include/adodb/lang/adodb-pl.inc.php similarity index 70% rename from www/include/adodb5/lang/adodb-pl.inc.php rename to www/include/adodb/lang/adodb-pl.inc.php index ffa10e33..f855153e 100644 --- a/www/include/adodb5/lang/adodb-pl.inc.php +++ b/www/include/adodb/lang/adodb-pl.inc.php @@ -1,6 +1,24 @@ +/** + * Polish language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Grzegorz Pacan + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'pl', diff --git a/www/include/adodb5/lang/adodb-pt-br.inc.php b/www/include/adodb/lang/adodb-pt-br.inc.php similarity index 69% rename from www/include/adodb5/lang/adodb-pt-br.inc.php rename to www/include/adodb/lang/adodb-pt-br.inc.php index 9c687b06..b6c0d1c9 100644 --- a/www/include/adodb5/lang/adodb-pt-br.inc.php +++ b/www/include/adodb/lang/adodb-pt-br.inc.php @@ -1,6 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'pt-br', DB_ERROR => 'erro desconhecido', diff --git a/www/include/adodb5/lang/adodb-ro.inc.php b/www/include/adodb/lang/adodb-ro.inc.php similarity index 70% rename from www/include/adodb5/lang/adodb-ro.inc.php rename to www/include/adodb/lang/adodb-ro.inc.php index b6ddd313..011c0163 100644 --- a/www/include/adodb5/lang/adodb-ro.inc.php +++ b/www/include/adodb/lang/adodb-ro.inc.php @@ -1,6 +1,24 @@ */ +/** + * Romanian language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Bogdan Stefan + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'ro', diff --git a/www/include/adodb5/lang/adodb-ru.inc.php b/www/include/adodb/lang/adodb-ru.inc.php similarity index 74% rename from www/include/adodb5/lang/adodb-ru.inc.php rename to www/include/adodb/lang/adodb-ru.inc.php index 67d80f2c..a311784a 100644 --- a/www/include/adodb5/lang/adodb-ru.inc.php +++ b/www/include/adodb/lang/adodb-ru.inc.php @@ -1,6 +1,24 @@ + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'ru', diff --git a/www/include/adodb5/lang/adodb-sv.inc.php b/www/include/adodb/lang/adodb-sv.inc.php similarity index 69% rename from www/include/adodb5/lang/adodb-sv.inc.php rename to www/include/adodb/lang/adodb-sv.inc.php index d3be6b0e..72e24301 100644 --- a/www/include/adodb5/lang/adodb-sv.inc.php +++ b/www/include/adodb/lang/adodb-sv.inc.php @@ -1,5 +1,25 @@ + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'en', DB_ERROR => 'Okänt fel', diff --git a/www/include/adodb5/lang/adodb-th.inc.php b/www/include/adodb/lang/adodb-th.inc.php similarity index 67% rename from www/include/adodb5/lang/adodb-th.inc.php rename to www/include/adodb/lang/adodb-th.inc.php index a0685645..354acca1 100644 --- a/www/include/adodb5/lang/adodb-th.inc.php +++ b/www/include/adodb/lang/adodb-th.inc.php @@ -1,5 +1,25 @@ +/** + * Thai language strings. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + * @author Trirat Petchsingh + */ + $ADODB_LANG_ARRAY = array ( 'LANG' => 'th', DB_ERROR => 'error ไม่รู้สาเหตุ', diff --git a/www/include/adodb5/lang/adodb-uk.inc.php b/www/include/adodb/lang/adodb-uk.inc.php similarity index 73% rename from www/include/adodb5/lang/adodb-uk.inc.php rename to www/include/adodb/lang/adodb-uk.inc.php index 2ace5bc4..e54a9670 100644 --- a/www/include/adodb5/lang/adodb-uk.inc.php +++ b/www/include/adodb/lang/adodb-uk.inc.php @@ -1,6 +1,24 @@ + */ $ADODB_LANG_ARRAY = array ( 'LANG' => 'uk', diff --git a/www/include/adodb/pear/Auth/Container/ADOdb.php b/www/include/adodb/pear/Auth/Container/ADOdb.php new file mode 100644 index 00000000..807da9d7 --- /dev/null +++ b/www/include/adodb/pear/Auth/Container/ADOdb.php @@ -0,0 +1,406 @@ + + * @author Richard Tango-Lowy + */ + +require_once 'Auth/Container.php'; +require_once 'adodb.inc.php'; +require_once 'adodb-pear.inc.php'; +require_once 'adodb-errorpear.inc.php'; + + +class Auth_Container_ADOdb extends Auth_Container +{ + + /** + * Additional options for the storage container + * @var array + */ + var $options = array(); + + /** + * DB object + * @var object + */ + var $db = null; + var $dsn = ''; + + /** + * User that is currently selected from the DB. + * @var string + */ + var $activeUser = ''; + + // {{{ Constructor + + /** + * Constructor of the container class + * + * Initiate connection to the database via PEAR::ADOdb + * + * @param string Connection data or DB object + * @return object Returns an error object if something went wrong + */ + function __construct($dsn) + { + $this->_setDefaults(); + + if (is_array($dsn)) { + $this->_parseOptions($dsn); + + if (empty($this->options['dsn'])) { + PEAR::raiseError('No connection parameters specified!'); + } + } else { + // Extract db_type from dsn string. + $this->options['dsn'] = $dsn; + } + } + + // }}} + // {{{ _connect() + + /** + * Connect to database by using the given DSN string + * + * @access private + * @param string DSN string + * @return mixed Object on error, otherwise bool + */ + function _connect($dsn) + { + if (is_string($dsn) || is_array($dsn)) { + if(!$this->db) { + $this->db = ADONewConnection($dsn); + if( $err = ADODB_Pear_error() ) { + return PEAR::raiseError($err); + } + } + + } else { + return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__, + 41, + PEAR_ERROR_RETURN, + null, + null + ); + } + + if(!$this->db) { + return PEAR::raiseError(ADODB_Pear_error()); + } else { + return true; + } + } + + // }}} + // {{{ _prepare() + + /** + * Prepare database connection + * + * This function checks if we have already opened a connection to + * the database. If that's not the case, a new connection is opened. + * + * @access private + * @return mixed True or a DB error object. + */ + function _prepare() + { + if(!$this->db) { + $res = $this->_connect($this->options['dsn']); + } + return true; + } + + // }}} + // {{{ query() + + /** + * Prepare query to the database + * + * This function checks if we have already opened a connection to + * the database. If that's not the case, a new connection is opened. + * After that the query is passed to the database. + * + * @access public + * @param string Query string + * @return mixed a DB_result object or DB_OK on success, a DB + * or PEAR error on failure + */ + function query($query) + { + $err = $this->_prepare(); + if ($err !== true) { + return $err; + } + return $this->db->query($query); + } + + // }}} + // {{{ _setDefaults() + + /** + * Set some default options + * + * @access private + * @return void + */ + function _setDefaults() + { + $this->options['db_type'] = 'mysql'; + $this->options['table'] = 'auth'; + $this->options['usernamecol'] = 'username'; + $this->options['passwordcol'] = 'password'; + $this->options['dsn'] = ''; + $this->options['db_fields'] = ''; + $this->options['cryptType'] = 'md5'; + } + + // }}} + // {{{ _parseOptions() + + /** + * Parse options passed to the container class + * + * @access private + * @param array + */ + function _parseOptions($array) + { + foreach ($array as $key => $value) { + if (isset($this->options[$key])) { + $this->options[$key] = $value; + } + } + + /* Include additional fields if they exist */ + if(!empty($this->options['db_fields'])){ + if(is_array($this->options['db_fields'])){ + $this->options['db_fields'] = join(', ', $this->options['db_fields']); + } + $this->options['db_fields'] = ', '.$this->options['db_fields']; + } + } + + // }}} + // {{{ fetchData() + + /** + * Get user information from database + * + * This function uses the given username to fetch + * the corresponding login data from the database + * table. If an account that matches the passed username + * and password is found, the function returns true. + * Otherwise it returns false. + * + * @param string Username + * @param string Password + * @return mixed Error object or boolean + */ + function fetchData($username, $password) + { + // Prepare for a database query + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + // Find if db_fields contains a *, i so assume all col are selected + if(strstr($this->options['db_fields'], '*')){ + $sql_from = "*"; + } + else{ + $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields']; + } + + $query = "SELECT ".$sql_from. + " FROM ".$this->options['table']. + " WHERE ".$this->options['usernamecol']." = " . $this->db->Quote($username); + + $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; + $rset = $this->db->Execute( $query ); + $res = $rset->fetchRow(); + + if (DB::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->getCode()); + } + if (!is_array($res)) { + $this->activeUser = ''; + return false; + } + if ($this->verifyPassword(trim($password, "\r\n"), + trim($res[$this->options['passwordcol']], "\r\n"), + $this->options['cryptType'])) { + // Store additional field values in the session + foreach ($res as $key => $value) { + if ($key == $this->options['passwordcol'] || + $key == $this->options['usernamecol']) { + continue; + } + // Use reference to the auth object if exists + // This is because the auth session variable can change so a static call to setAuthData does not make sense + if(is_object($this->_auth_obj)){ + $this->_auth_obj->setAuthData($key, $value); + } else { + Auth::setAuthData($key, $value); + } + } + + return true; + } + + $this->activeUser = $res[$this->options['usernamecol']]; + return false; + } + + // }}} + // {{{ listUsers() + + function listUsers() + { + $err = $this->_prepare(); + if ($err !== true) { + return PEAR::raiseError($err->getMessage(), $err->getCode()); + } + + $retVal = array(); + + // Find if db_fileds contains a *, i so assume all col are selected + if(strstr($this->options['db_fields'], '*')){ + $sql_from = "*"; + } + else{ + $sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields']; + } + + $query = sprintf("SELECT %s FROM %s", + $sql_from, + $this->options['table'] + ); + $res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->getCode()); + } else { + foreach ($res as $user) { + $user['username'] = $user[$this->options['usernamecol']]; + $retVal[] = $user; + } + } + return $retVal; + } + + // }}} + // {{{ addUser() + + /** + * Add user to the storage container + * + * @access public + * @param string Username + * @param string Password + * @param mixed Additional information that are stored in the DB + * + * @return mixed True on success, otherwise error object + */ + function addUser($username, $password, $additional = "") + { + if (function_exists($this->options['cryptType'])) { + $cryptFunction = $this->options['cryptType']; + } else { + $cryptFunction = 'md5'; + } + + $additional_key = ''; + $additional_value = ''; + + if (is_array($additional)) { + foreach ($additional as $key => $value) { + $additional_key .= ', ' . $key; + $additional_value .= ", '" . $value . "'"; + } + } + + $query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)", + $this->options['table'], + $this->options['usernamecol'], + $this->options['passwordcol'], + $additional_key, + $username, + $cryptFunction($password), + $additional_value + ); + + $res = $this->query($query); + + if (DB::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->getCode()); + } else { + return true; + } + } + + // }}} + // {{{ removeUser() + + /** + * Remove user from the storage container + * + * @access public + * @param string Username + * + * @return mixed True on success, otherwise error object + */ + function removeUser($username) + { + $query = sprintf("DELETE FROM %s WHERE %s = '%s'", + $this->options['table'], + $this->options['usernamecol'], + $username + ); + + $res = $this->query($query); + + if (DB::isError($res)) { + return PEAR::raiseError($res->getMessage(), $res->getCode()); + } else { + return true; + } + } + + // }}} +} + +function showDbg( $string ) { + print " +-- $string

"; +} +function dump( $var, $str, $vardump = false ) { + print "

$str

";
+	( !$vardump ) ? ( print_r( $var )) : ( var_dump( $var ));
+	print "
"; +} diff --git a/www/include/adodb/pear/auth_adodb_example.php b/www/include/adodb/pear/auth_adodb_example.php new file mode 100644 index 00000000..77af9395 --- /dev/null +++ b/www/include/adodb/pear/auth_adodb_example.php @@ -0,0 +1,46 @@ + +
+ + + + + $dsn, 'table' => 'auth', 'cryptType' => 'none', + 'usernamecol' => 'username', 'passwordcol' => 'password'); +$a = new Auth("ADOdb", $params, "loginFunction"); +$a->start(); + +if ($a->getAuth()) { + echo "Success"; + // * The output of your site goes here. +} diff --git a/www/include/adodb/pear/readme.Auth.txt b/www/include/adodb/pear/readme.Auth.txt new file mode 100644 index 00000000..f5b162cc --- /dev/null +++ b/www/include/adodb/pear/readme.Auth.txt @@ -0,0 +1,20 @@ +From: Rich Tango-Lowy (richtl#arscognita.com) +Date: Sat, May 29, 2004 11:20 am + +OK, I hacked out an ADOdb container for PEAR-Auth. The error handling's +a bit of a mess, but all the methods work. + +Copy ADOdb.php to your pear/Auth/Container/ directory. + +Use the ADOdb container exactly as you would the DB +container, but specify 'ADOdb' instead of 'DB': + +$dsn = "mysql://myuser:mypass@localhost/authdb"; +$a = new Auth("ADOdb", $dsn, "loginFunction"); + + +------------------- + +John Lim adds: + +See http://pear.php.net/manual/en/package.authentication.php diff --git a/www/include/adodb/perf/perf-db2.inc.php b/www/include/adodb/perf/perf-db2.inc.php new file mode 100644 index 00000000..fc05219d --- /dev/null +++ b/www/include/adodb/perf/perf-db2.inc.php @@ -0,0 +1,113 @@ + array('RATIO', + "SELECT + case when sum(POOL_DATA_L_READS+POOL_INDEX_L_READS)=0 then 0 + else 100*(1-sum(POOL_DATA_P_READS+POOL_INDEX_P_READS)/sum(POOL_DATA_L_READS+POOL_INDEX_L_READS)) end + FROM TABLE(SNAPSHOT_APPL('',-2)) as t", + '=WarnCacheRatio'), + + 'Data Cache', + 'data cache buffers' => array('DATAC', + 'select sum(npages) from SYSCAT.BUFFERPOOLS', + 'See tuning reference.' ), + 'cache blocksize' => array('DATAC', + 'select avg(pagesize) from SYSCAT.BUFFERPOOLS', + '' ), + 'data cache size' => array('DATAC', + 'select sum(npages*pagesize) from SYSCAT.BUFFERPOOLS', + '' ), + 'Connections', + 'current connections' => array('SESS', + "SELECT count(*) FROM TABLE(SNAPSHOT_APPL_INFO('',-2)) as t", + ''), + + false + ); + + + function __construct(&$conn) + { + $this->conn = $conn; + } + + function Explain($sql,$partial=false) + { + $save = $this->conn->LogSQL(false); + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); + if ($arr) { + foreach($arr as $row) { + $sql = reset($row); + if (crc32($sql) == $partial) break; + } + } + } + $qno = rand(); + $ok = $this->conn->Execute("EXPLAIN PLAN SET QUERYNO=$qno FOR $sql"); + ob_start(); + if (!$ok) echo "

Have EXPLAIN tables been created?

"; + else { + $rs = $this->conn->Execute("select * from explain_statement where queryno=$qno"); + if ($rs) rs2html($rs); + } + $s = ob_get_contents(); + ob_end_clean(); + $this->conn->LogSQL($save); + + $s .= $this->Tracer($sql); + return $s; + } + + /** + * Gets a list of tables + * + * @param int $throwaway discarded variable to match the parent method + * @return string The formatted table list + */ + function Tables($throwaway=0) + { + $rs = $this->conn->Execute("select tabschema,tabname,card as rows, + npages pages_used,fpages pages_allocated, tbspace tablespace + from syscat.tables where tabschema not in ('SYSCAT','SYSIBM','SYSSTAT') order by 1,2"); + return rs2html($rs,false,false,false,false); + } +} diff --git a/www/include/adodb/perf/perf-informix.inc.php b/www/include/adodb/perf/perf-informix.inc.php new file mode 100644 index 00000000..88802bcc --- /dev/null +++ b/www/include/adodb/perf/perf-informix.inc.php @@ -0,0 +1,76 @@ + array('RATIOH', + "select round((1-(wt.value / (rd.value + wr.value)))*100,2) + from sysmaster:sysprofile wr, sysmaster:sysprofile rd, sysmaster:sysprofile wt + where rd.name = 'pagreads' and + wr.name = 'pagwrites' and + wt.name = 'buffwts'", + '=WarnCacheRatio'), + 'IO', + 'data reads' => array('IO', + "select value from sysmaster:sysprofile where name='pagreads'", + 'Page reads'), + + 'data writes' => array('IO', + "select value from sysmaster:sysprofile where name='pagwrites'", + 'Page writes'), + + 'Connections', + 'current connections' => array('SESS', + 'select count(*) from sysmaster:syssessions', + 'Number of sessions'), + + false + + ); + + function __construct(&$conn) + { + $this->conn = $conn; + } + +} diff --git a/www/include/adodb/perf/perf-mssql.inc.php b/www/include/adodb/perf/perf-mssql.inc.php new file mode 100644 index 00000000..5d832032 --- /dev/null +++ b/www/include/adodb/perf/perf-mssql.inc.php @@ -0,0 +1,168 @@ + array('RATIO', + "select round((a.cntr_value*100.0)/b.cntr_value,2) from master.dbo.sysperfinfo a, master.dbo.sysperfinfo b where a.counter_name = 'Buffer cache hit ratio' and b.counter_name='Buffer cache hit ratio base'", + '=WarnCacheRatio'), + 'prepared sql hit ratio' => array('RATIO', + array('dbcc cachestats','Prepared',1,100), + ''), + 'adhoc sql hit ratio' => array('RATIO', + array('dbcc cachestats','Adhoc',1,100), + ''), + 'IO', + 'data reads' => array('IO', + "select cntr_value from master.dbo.sysperfinfo where counter_name = 'Page reads/sec'"), + 'data writes' => array('IO', + "select cntr_value from master.dbo.sysperfinfo where counter_name = 'Page writes/sec'"), + + 'Data Cache', + 'data cache size' => array('DATAC', + "select cntr_value*8192 from master.dbo.sysperfinfo where counter_name = 'Total Pages' and object_name='SQLServer:Buffer Manager'", + '' ), + 'data cache blocksize' => array('DATAC', + "select 8192",'page size'), + 'Connections', + 'current connections' => array('SESS', + '=sp_who', + ''), + 'max connections' => array('SESS', + "SELECT @@MAX_CONNECTIONS", + ''), + + false + ); + + + function __construct(&$conn) + { + if ($conn->dataProvider == 'odbc') { + $this->sql1 = 'sql1'; + //$this->explain = false; + } + $this->conn = $conn; + } + + function Explain($sql,$partial=false) + { + + $save = $this->conn->LogSQL(false); + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); + if ($arr) { + foreach($arr as $row) { + $sql = reset($row); + if (crc32($sql) == $partial) break; + } + } + } + + $s = '

Explain: '.htmlspecialchars($sql).'

'; + $this->conn->Execute("SET SHOWPLAN_ALL ON;"); + $sql = str_replace('?',"''",$sql); + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + $rs = $this->conn->Execute($sql); + //adodb_printr($rs); + $ADODB_FETCH_MODE = $save; + if ($rs && !$rs->EOF) { + $rs->MoveNext(); + $s .= '
'; + while (!$rs->EOF) { + $s .= '\n"; ## NOTE CORRUPT tag is intentional!!!! + $rs->MoveNext(); + } + $s .= '
Rows IO CPU     Plan
'.round($rs->fields[8],1).''.round($rs->fields[9],3).''.round($rs->fields[10],3).'
'.htmlspecialchars($rs->fields[0])."
'; + + $rs->NextRecordSet(); + } + + $this->conn->Execute("SET SHOWPLAN_ALL OFF;"); + $this->conn->LogSQL($save); + $s .= $this->Tracer($sql); + return $s; + } + + function Tables() + { + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + //$this->conn->debug=1; + $s = ''; + $rs1 = $this->conn->Execute("select distinct name from sysobjects where xtype='U'"); + if ($rs1) { + while (!$rs1->EOF) { + $tab = $rs1->fields[0]; + $tabq = $this->conn->qstr($tab); + $rs2 = $this->conn->Execute("sp_spaceused $tabq"); + if ($rs2) { + $s .= ''; + $rs2->Close(); + } + $rs1->MoveNext(); + } + $rs1->Close(); + } + $ADODB_FETCH_MODE = $save; + return $s.'
tablenamesize_in_kindex sizereserved size
'.$tab.''.$rs2->fields[3].''.$rs2->fields[4].''.$rs2->fields[2].'
'; + } + + function sp_who() + { + $arr = $this->conn->GetArray('sp_who'); + return sizeof($arr); + } + + function HealthCheck($cli=false) + { + + $this->conn->Execute('dbcc traceon(3604)'); + $html = adodb_perf::HealthCheck($cli); + $this->conn->Execute('dbcc traceoff(3604)'); + return $html; + } + + +} diff --git a/www/include/adodb/perf/perf-mssqlnative.inc.php b/www/include/adodb/perf/perf-mssqlnative.inc.php new file mode 100644 index 00000000..c2c90fc7 --- /dev/null +++ b/www/include/adodb/perf/perf-mssqlnative.inc.php @@ -0,0 +1,168 @@ + array('RATIO', + "select round((a.cntr_value*100.0)/b.cntr_value,2) from master.dbo.sysperfinfo a, master.dbo.sysperfinfo b where a.counter_name = 'Buffer cache hit ratio' and b.counter_name='Buffer cache hit ratio base'", + '=WarnCacheRatio'), + 'prepared sql hit ratio' => array('RATIO', + array('dbcc cachestats','Prepared',1,100), + ''), + 'adhoc sql hit ratio' => array('RATIO', + array('dbcc cachestats','Adhoc',1,100), + ''), + 'IO', + 'data reads' => array('IO', + "select cntr_value from master.dbo.sysperfinfo where counter_name = 'Page reads/sec'"), + 'data writes' => array('IO', + "select cntr_value from master.dbo.sysperfinfo where counter_name = 'Page writes/sec'"), + + 'Data Cache', + 'data cache size' => array('DATAC', + "select cntr_value*8192 from master.dbo.sysperfinfo where counter_name = 'Total Pages' and object_name='SQLServer:Buffer Manager'", + '' ), + 'data cache blocksize' => array('DATAC', + "select 8192",'page size'), + 'Connections', + 'current connections' => array('SESS', + '=sp_who', + ''), + 'max connections' => array('SESS', + "SELECT @@MAX_CONNECTIONS", + ''), + + false + ); + + + function __construct(&$conn) + { + if ($conn->dataProvider == 'odbc') { + $this->sql1 = 'sql1'; + //$this->explain = false; + } + $this->conn =& $conn; + } + + function Explain($sql,$partial=false) + { + + $save = $this->conn->LogSQL(false); + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); + if ($arr) { + foreach($arr as $row) { + $sql = reset($row); + if (crc32($sql) == $partial) break; + } + } + } + + $s = '

Explain: '.htmlspecialchars($sql).'

'; + $this->conn->Execute("SET SHOWPLAN_ALL ON;"); + $sql = str_replace('?',"''",$sql); + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + $rs =& $this->conn->Execute($sql); + //adodb_printr($rs); + $ADODB_FETCH_MODE = $save; + if ($rs) { + $rs->MoveNext(); + $s .= ''; + while (!$rs->EOF) { + $s .= '\n"; ## NOTE CORRUPT tag is intentional!!!! + $rs->MoveNext(); + } + $s .= '
Rows IO CPU     Plan
'.round($rs->fields[8],1).''.round($rs->fields[9],3).''.round($rs->fields[10],3).'
'.htmlspecialchars($rs->fields[0])."
'; + + $rs->NextRecordSet(); + } + + $this->conn->Execute("SET SHOWPLAN_ALL OFF;"); + $this->conn->LogSQL($save); + $s .= $this->Tracer($sql); + return $s; + } + + function Tables($orderby='1') + { + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + //$this->conn->debug=1; + $s = ''; + $rs1 = $this->conn->Execute("select distinct name from sysobjects where xtype='U'"); + if ($rs1) { + while (!$rs1->EOF) { + $tab = $rs1->fields[0]; + $tabq = $this->conn->qstr($tab); + $rs2 = $this->conn->Execute("sp_spaceused $tabq"); + if ($rs2) { + $s .= ''; + $rs2->Close(); + } + $rs1->MoveNext(); + } + $rs1->Close(); + } + $ADODB_FETCH_MODE = $save; + return $s.'
tablenamesize_in_kindex sizereserved size
'.$tab.''.$rs2->fields[3].''.$rs2->fields[4].''.$rs2->fields[2].'
'; + } + + function sp_who() + { + $arr = $this->conn->GetArray('sp_who'); + return sizeof($arr); + } + + function HealthCheck($cli=false) + { + + $this->conn->Execute('dbcc traceon(3604)'); + $html = adodb_perf::HealthCheck($cli); + $this->conn->Execute('dbcc traceoff(3604)'); + return $html; + } + + +} diff --git a/www/include/adodb/perf/perf-mysql.inc.php b/www/include/adodb/perf/perf-mysql.inc.php new file mode 100644 index 00000000..ed92c805 --- /dev/null +++ b/www/include/adodb/perf/perf-mysql.inc.php @@ -0,0 +1,325 @@ + array('RATIO', + '=GetKeyHitRatio', + '=WarnCacheRatio'), + 'InnoDB cache hit ratio' => array('RATIO', + '=GetInnoDBHitRatio', + '=WarnCacheRatio'), + 'data cache hit ratio' => array('HIDE', # only if called + '=FindDBHitRatio', + '=WarnCacheRatio'), + 'sql cache hit ratio' => array('RATIO', + '=GetQHitRatio', + ''), + 'IO', + 'data reads' => array('IO', + '=GetReads', + 'Number of selects (Key_reads is not accurate)'), + 'data writes' => array('IO', + '=GetWrites', + 'Number of inserts/updates/deletes * coef (Key_writes is not accurate)'), + + 'Data Cache', + 'MyISAM data cache size' => array('DATAC', + array("show variables", 'key_buffer_size'), + '' ), + 'BDB data cache size' => array('DATAC', + array("show variables", 'bdb_cache_size'), + '' ), + 'InnoDB data cache size' => array('DATAC', + array("show variables", 'innodb_buffer_pool_size'), + '' ), + 'Memory Usage', + 'read buffer size' => array('CACHE', + array("show variables", 'read_buffer_size'), + '(per session)'), + 'sort buffer size' => array('CACHE', + array("show variables", 'sort_buffer_size'), + 'Size of sort buffer (per session)' ), + 'table cache' => array('CACHE', + array("show variables", 'table_cache'), + 'Number of tables to keep open'), + 'Connections', + 'current connections' => array('SESS', + array('show status','Threads_connected'), + ''), + 'max connections' => array( 'SESS', + array("show variables",'max_connections'), + ''), + + false + ); + + function __construct(&$conn) + { + $this->conn = $conn; + } + + function Explain($sql,$partial=false) + { + + if (strtoupper(substr(trim($sql),0,6)) !== 'SELECT') return '

Unable to EXPLAIN non-select statement

'; + $save = $this->conn->LogSQL(false); + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); + if ($arr) { + foreach($arr as $row) { + $sql = reset($row); + if (crc32($sql) == $partial) break; + } + } + } + $sql = str_replace('?',"''",$sql); + + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $sql = $this->conn->GetOne("select sql1 from adodb_logsql where sql1 like $sqlq"); + } + + $s = '

Explain: '.htmlspecialchars($sql).'

'; + $rs = $this->conn->Execute('EXPLAIN '.$sql); + $s .= rs2html($rs,false,false,false,false); + $this->conn->LogSQL($save); + $s .= $this->Tracer($sql); + return $s; + } + + /** + * Returns a list of table statuses. + * + * @param string $orderby Unused (compatibility with parent method) + * @return string A formatted set of recordsets + */ + function tables($orderby='1') + { + if (!$this->tablesSQL) return false; + + $rs = $this->conn->Execute($this->tablesSQL); + if (!$rs) return false; + + $html = rs2html($rs,false,false,false,false); + return $html; + } + + function GetReads() + { + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); + + $rs = $this->conn->Execute('show status'); + + if (isset($savem)) $this->conn->SetFetchMode($savem); + $ADODB_FETCH_MODE = $save; + + if (!$rs) return 0; + $val = 0; + while (!$rs->EOF) { + switch($rs->fields[0]) { + case 'Com_select': + $val = $rs->fields[1]; + $rs->Close(); + return $val; + } + $rs->MoveNext(); + } + + $rs->Close(); + + return $val; + } + + function GetWrites() + { + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); + + $rs = $this->conn->Execute('show status'); + + if (isset($savem)) $this->conn->SetFetchMode($savem); + $ADODB_FETCH_MODE = $save; + + if (!$rs) return 0; + $val = 0.0; + while (!$rs->EOF) { + switch($rs->fields[0]) { + case 'Com_insert': + $val += $rs->fields[1]; break; + case 'Com_delete': + $val += $rs->fields[1]; break; + case 'Com_update': + $val += $rs->fields[1]/2; + $rs->Close(); + return $val; + } + $rs->MoveNext(); + } + + $rs->Close(); + + return $val; + } + + function FindDBHitRatio() + { + // first find out type of table + //$this->conn->debug=1; + + global $ADODB_FETCH_MODE; + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); + + $rs = $this->conn->Execute('show table status'); + + if (isset($savem)) $this->conn->SetFetchMode($savem); + $ADODB_FETCH_MODE = $save; + + if (!$rs) return ''; + $type = strtoupper($rs->fields[1]); + $rs->Close(); + switch($type){ + case 'MYISAM': + case 'ISAM': + return $this->DBParameter('MyISAM cache hit ratio').' (MyISAM)'; + case 'INNODB': + return $this->DBParameter('InnoDB cache hit ratio').' (InnoDB)'; + default: + return $type.' not supported'; + } + + } + + function GetQHitRatio() + { + //Total number of queries = Qcache_inserts + Qcache_hits + Qcache_not_cached + $hits = $this->_DBParameter(array("show status","Qcache_hits")); + $total = $this->_DBParameter(array("show status","Qcache_inserts")); + $total += $this->_DBParameter(array("show status","Qcache_not_cached")); + + $total += $hits; + if ($total) return round(($hits*100)/$total,2); + return 0; + } + + /* + Use session variable to store Hit percentage, because MySQL + does not remember last value of SHOW INNODB STATUS hit ratio + + # 1st query to SHOW INNODB STATUS + 0.00 reads/s, 0.00 creates/s, 0.00 writes/s + Buffer pool hit rate 1000 / 1000 + + # 2nd query to SHOW INNODB STATUS + 0.00 reads/s, 0.00 creates/s, 0.00 writes/s + No buffer pool activity since the last printout + */ + function GetInnoDBHitRatio() + { + global $ADODB_FETCH_MODE; + + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); + + $rs = $this->conn->Execute('show engine innodb status'); + + if (isset($savem)) $this->conn->SetFetchMode($savem); + $ADODB_FETCH_MODE = $save; + + if (!$rs || $rs->EOF) return 0; + $stat = $rs->fields[0]; + $rs->Close(); + $at = strpos($stat,'Buffer pool hit rate'); + $stat = substr($stat,$at,200); + if (preg_match('!Buffer pool hit rate\s*([0-9]*) / ([0-9]*)!',$stat,$arr)) { + $val = 100*$arr[1]/$arr[2]; + $_SESSION['INNODB_HIT_PCT'] = $val; + return round($val,2); + } else { + if (isset($_SESSION['INNODB_HIT_PCT'])) return $_SESSION['INNODB_HIT_PCT']; + return 0; + } + return 0; + } + + function GetKeyHitRatio() + { + $hits = $this->_DBParameter(array("show status","Key_read_requests")); + $reqs = $this->_DBParameter(array("show status","Key_reads")); + if ($reqs == 0) return 0; + + return round(($hits/($reqs+$hits))*100,2); + } + + // start hack + var $optimizeTableLow = 'CHECK TABLE %s FAST QUICK'; + var $optimizeTableHigh = 'OPTIMIZE TABLE %s'; + + /** + * @see adodb_perf::optimizeTable() + */ + function optimizeTable( $table, $mode = ADODB_OPT_LOW) + { + if ( !is_string( $table)) return false; + + $conn = $this->conn; + if ( !$conn) return false; + + $sql = ''; + switch( $mode) { + case ADODB_OPT_LOW : $sql = $this->optimizeTableLow; break; + case ADODB_OPT_HIGH : $sql = $this->optimizeTableHigh; break; + default : + // May don't use __FUNCTION__ constant for BC (__FUNCTION__ Added in PHP 4.3.0) + ADOConnection::outp( sprintf( "

%s: '%s' using of undefined mode '%s'

", __CLASS__, __FUNCTION__, $mode)); + return false; + } + $sql = sprintf( $sql, $table); + + return $conn->Execute( $sql) !== false; + } + // end hack +} diff --git a/www/include/adodb/perf/perf-oci8.inc.php b/www/include/adodb/perf/perf-oci8.inc.php new file mode 100644 index 00000000..c11b261f --- /dev/null +++ b/www/include/adodb/perf/perf-oci8.inc.php @@ -0,0 +1,708 @@ + array('RATIOH', + "select round((1-(phy.value / (cur.value + con.value)))*100,2) + from v\$sysstat cur, v\$sysstat con, v\$sysstat phy + where cur.name = 'db block gets' and + con.name = 'consistent gets' and + phy.name = 'physical reads'", + '=WarnCacheRatio'), + + 'sql cache hit ratio' => array( 'RATIOH', + 'select round(100*(sum(pins)-sum(reloads))/sum(pins),2) from v$librarycache', + 'increase shared_pool_size if too ratio low'), + + 'datadict cache hit ratio' => array('RATIOH', + "select + round((1 - (sum(getmisses) / (sum(gets) + + sum(getmisses))))*100,2) + from v\$rowcache", + 'increase shared_pool_size if too ratio low'), + + 'memory sort ratio' => array('RATIOH', + "SELECT ROUND((100 * b.VALUE) /DECODE ((a.VALUE + b.VALUE), + 0,1,(a.VALUE + b.VALUE)),2) +FROM v\$sysstat a, + v\$sysstat b +WHERE a.name = 'sorts (disk)' +AND b.name = 'sorts (memory)'", + "% of memory sorts compared to disk sorts - should be over 95%"), + + 'IO', + 'data reads' => array('IO', + "select value from v\$sysstat where name='physical reads'"), + + 'data writes' => array('IO', + "select value from v\$sysstat where name='physical writes'"), + + 'Data Cache', + + 'data cache buffers' => array( 'DATAC', + "select a.value/b.value from v\$parameter a, v\$parameter b + where a.name = 'db_cache_size' and b.name= 'db_block_size'", + 'Number of cache buffers. Tune db_cache_size if the data cache hit ratio is too low.'), + 'data cache blocksize' => array('DATAC', + "select value from v\$parameter where name='db_block_size'", + '' ), + + 'Memory Pools', + 'Mem Max Target (11g+)' => array( 'DATAC', + "select value from v\$parameter where name = 'memory_max_target'", + 'The memory_max_size is the maximum value to which memory_target can be set.' ), + 'Memory target (11g+)' => array( 'DATAC', + "select value from v\$parameter where name = 'memory_target'", + 'If memory_target is defined then SGA and PGA targets are consolidated into one memory_target.' ), + 'SGA Max Size' => array( 'DATAC', + "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'sga_max_size'", + 'The sga_max_size is the maximum value to which sga_target can be set.' ), + 'SGA target' => array( 'DATAC', + "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'sga_target'", + 'If sga_target is defined then data cache, shared, java and large pool size can be 0. This is because all these pools are consolidated into one sga_target.' ), + 'PGA aggr target' => array( 'DATAC', + "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'pga_aggregate_target'", + 'If pga_aggregate_target is defined then this is the maximum memory that can be allocated for cursor operations such as sorts, group by, joins, merges. When in doubt, set it to 20% of sga_target.' ), + 'data cache size' => array('DATAC', + "select value from v\$parameter where name = 'db_cache_size'", + 'db_cache_size' ), + 'shared pool size' => array('DATAC', + "select value from v\$parameter where name = 'shared_pool_size'", + 'shared_pool_size, which holds shared sql, stored procedures, dict cache and similar shared structs' ), + 'java pool size' => array('DATAJ', + "select value from v\$parameter where name = 'java_pool_size'", + 'java_pool_size' ), + 'large pool buffer size' => array('CACHE', + "select value from v\$parameter where name='large_pool_size'", + 'this pool is for large mem allocations (not because it is larger than shared pool), for MTS sessions, parallel queries, io buffers (large_pool_size) ' ), + + 'dynamic memory usage' => array('CACHE', "select '-' from dual", '=DynMemoryUsage'), + + 'Connections', + 'current connections' => array('SESS', + 'select count(*) from sys.v_$session where username is not null', + ''), + 'max connections' => array( 'SESS', + "select value from v\$parameter where name='sessions'", + ''), + + 'Memory Utilization', + 'data cache utilization ratio' => array('RATIOU', + "select round((1-bytes/sgasize)*100, 2) + from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f + where name = 'free memory' and pool = 'shared pool'", + 'Percentage of data cache actually in use - should be over 85%'), + + 'shared pool utilization ratio' => array('RATIOU', + 'select round((sga.bytes/case when p.value=0 then sga.bytes else to_number(p.value) end)*100,2) + from v$sgastat sga, v$parameter p + where sga.name = \'free memory\' and sga.pool = \'shared pool\' + and p.name = \'shared_pool_size\'', + 'Percentage of shared pool actually used - too low is bad, too high is worse'), + + 'large pool utilization ratio' => array('RATIOU', + "select round((1-bytes/sgasize)*100, 2) + from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f + where name = 'free memory' and pool = 'large pool'", + 'Percentage of large_pool actually in use - too low is bad, too high is worse'), + 'sort buffer size' => array('CACHE', + "select value from v\$parameter where name='sort_area_size'", + 'max in-mem sort_area_size (per query), uses memory in pga' ), + + /*'pga usage at peak' => array('RATIOU', + '=PGA','Mb utilization at peak transactions (requires Oracle 9i+)'),*/ + 'Transactions', + 'rollback segments' => array('ROLLBACK', + "select count(*) from sys.v_\$rollstat", + ''), + + 'peak transactions' => array('ROLLBACK', + "select max_utilization tx_hwm + from sys.v_\$resource_limit + where resource_name = 'transactions'", + 'Taken from high-water-mark'), + 'max transactions' => array('ROLLBACK', + "select value from v\$parameter where name = 'transactions'", + 'max transactions / rollback segments < 3.5 (or transactions_per_rollback_segment)'), + 'Parameters', + 'cursor sharing' => array('CURSOR', + "select value from v\$parameter where name = 'cursor_sharing'", + 'Cursor reuse strategy. Recommended is FORCE (8i+) or SIMILAR (9i+). See cursor_sharing.'), + /* + 'cursor reuse' => array('CURSOR', + "select count(*) from (select sql_text_wo_constants, count(*) + from t1 + group by sql_text_wo_constants +having count(*) > 100)",'These are sql statements that should be using bind variables'),*/ + 'index cache cost' => array('COST', + "select value from v\$parameter where name = 'optimizer_index_caching'", + '=WarnIndexCost'), + 'random page cost' => array('COST', + "select value from v\$parameter where name = 'optimizer_index_cost_adj'", + '=WarnPageCost'), + 'Waits', + 'Recent wait events' => array('WAITS','select \'Top 5 events\' from dual','=TopRecentWaits'), +// 'Historical wait SQL' => array('WAITS','select \'Last 2 days\' from dual','=TopHistoricalWaits'), -- requires AWR license + 'Backup', + 'Achivelog Mode' => array('BACKUP', 'select log_mode from v$database', '=LogMode'), + + 'DBID' => array('BACKUP','select dbid from v$database','Primary key of database, used for recovery with an RMAN Recovery Catalog'), + 'Archive Log Dest' => array('BACKUP', "SELECT NVL(v1.value,v2.value) +FROM v\$parameter v1, v\$parameter v2 WHERE v1.name='log_archive_dest' AND v2.name='log_archive_dest_10'", ''), + + 'Flashback Area' => array('BACKUP', "select nvl(value,'Flashback Area not used') from v\$parameter where name=lower('DB_RECOVERY_FILE_DEST')", 'Flashback area is a folder where all backup data and logs can be stored and managed by Oracle. If Error: message displayed, then it is not in use.'), + + 'Flashback Usage' => array('BACKUP', "select nvl('-','Flashback Area not used') from v\$parameter where name=lower('DB_RECOVERY_FILE_DEST')", '=FlashUsage', 'Flashback area usage.'), + + 'Control File Keep Time' => array('BACKUP', "select value from v\$parameter where name='control_file_record_keep_time'",'No of days to keep RMAN info in control file. Recommended set to x2 or x3 times the frequency of your full backup.'), + 'Recent RMAN Jobs' => array('BACKUP', "select '-' from dual", "=RMAN"), + + // 'Control File Keep Time' => array('BACKUP', "select value from v\$parameter where name='control_file_record_keep_time'",'No of days to keep RMAN info in control file. I recommend it be set to x2 or x3 times the frequency of your full backup.'), + 'Storage', 'Tablespaces' => array('TABLESPACE', "select '-' from dual", "=TableSpace"), + false + + ); + + + function __construct(&$conn) + { + global $gSQLBlockRows; + + $gSQLBlockRows = 1000; + $savelog = $conn->LogSQL(false); + $this->version = $conn->ServerInfo(); + $conn->LogSQL($savelog); + $this->conn = $conn; + } + + function LogMode() + { + $mode = $this->conn->GetOne("select log_mode from v\$database"); + + if ($mode == 'ARCHIVELOG') return 'To turn off archivelog:
+

+        SQLPLUS> connect sys as sysdba;
+        SQLPLUS> shutdown immediate;
+
+        SQLPLUS> startup mount exclusive;
+        SQLPLUS> alter database noarchivelog;
+        SQLPLUS> alter database open;
+
'; + + return 'To turn on archivelog:
+

+        SQLPLUS> connect sys as sysdba;
+        SQLPLUS> shutdown immediate;
+
+        SQLPLUS> startup mount exclusive;
+        SQLPLUS> alter database archivelog;
+        SQLPLUS> archive log start;
+        SQLPLUS> alter database open;
+
'; + } + + function TopRecentWaits() + { + + $rs = $this->conn->Execute("select * from ( + select event, round(100*time_waited/(select sum(time_waited) from v\$system_event where wait_class <> 'Idle'),1) \"% Wait\", + total_waits,time_waited, average_wait,wait_class from v\$system_event where wait_class <> 'Idle' order by 2 desc + ) where rownum <=5"); + + $ret = rs2html($rs,false,false,false,false); + return " 

".$ret." 

"; + + } + + function TopHistoricalWaits() + { + $days = 2; + + $rs = $this->conn->Execute("select * from ( SELECT + b.wait_class,B.NAME, + round(sum(wait_time+TIME_WAITED)/1000000) waitsecs, + parsing_schema_name, + C.SQL_TEXT, a.sql_id +FROM V\$ACTIVE_SESSION_HISTORY A + join V\$EVENT_NAME B on A.EVENT# = B.EVENT# + join V\$SQLAREA C on A.SQL_ID = C.SQL_ID +WHERE A.SAMPLE_TIME BETWEEN sysdate-$days and sysdate + and parsing_schema_name not in ('SYS','SYSMAN','DBSNMP','SYSTEM') +GROUP BY b.wait_class,parsing_schema_name,C.SQL_TEXT, B.NAME,A.sql_id +order by 3 desc) where rownum <=10"); + + $ret = rs2html($rs,false,false,false,false); + return " 

".$ret." 

"; + + } + + function TableSpace() + { + + $rs = $this->conn->Execute( + "select tablespace_name,round(sum(bytes)/1024/1024) as Used_MB,round(sum(maxbytes)/1024/1024) as Max_MB, round(sum(bytes)/sum(maxbytes),4) * 100 as PCT + from dba_data_files + group by tablespace_name order by 2 desc"); + + $ret = "

Tablespace".rs2html($rs,false,false,false,false); + + $rs = $this->conn->Execute("select * from dba_data_files order by tablespace_name, 1"); + $ret .= "

Datafile".rs2html($rs,false,false,false,false); + + return " 

".$ret." 

"; + } + + function RMAN() + { + $rs = $this->conn->Execute("select * from (select start_time, end_time, operation, status, mbytes_processed, output_device_type + from V\$RMAN_STATUS order by start_time desc) where rownum <=10"); + + $ret = rs2html($rs,false,false,false,false); + return " 

".$ret." 

"; + + } + + function DynMemoryUsage() + { + if (@$this->version['version'] >= 11) { + $rs = $this->conn->Execute("select component, current_size/1024./1024 as \"CurrSize (M)\" from V\$MEMORY_DYNAMIC_COMPONENTS"); + + } else + $rs = $this->conn->Execute("select name, round(bytes/1024./1024,2) as \"CurrSize (M)\" from V\$sgainfo"); + + + $ret = rs2html($rs,false,false,false,false); + return " 

".$ret." 

"; + } + + function FlashUsage() + { + $rs = $this->conn->Execute("select * from V\$FLASH_RECOVERY_AREA_USAGE"); + $ret = rs2html($rs,false,false,false,false); + return " 

".$ret." 

"; + } + + function WarnPageCost($val) + { + if ($val == 100 && $this->version['version'] < 10) $s = 'Too High. '; + else $s = ''; + + return $s.'Recommended is 20-50 for TP, and 50 for data warehouses. Default is 100. See optimizer_index_cost_adj. '; + } + + function WarnIndexCost($val) + { + if ($val == 0 && $this->version['version'] < 10) $s = 'Too Low. '; + else $s = ''; + + return $s.'Percentage of indexed data blocks expected in the cache. + Recommended is 20 (fast disk array) to 30 (slower hard disks). Default is 0. + See optimizer_index_caching.'; + } + + function PGA() + { + + //if ($this->version['version'] < 9) return 'Oracle 9i or later required'; + } + + function PGA_Advice() + { + $t = "

PGA Advice Estimate

"; + if ($this->version['version'] < 9) return $t.'Oracle 9i or later required'; + + $rs = $this->conn->Execute('select a.MB, + case when a.targ = 1 then \'<<= Current \' + when a.targ < 1 or a.pct <= b.pct then null + else + \'- BETTER than Current by \'||round(a.pct/b.pct*100-100,2)||\'%\' end as "Percent Improved", + a.targ as "PGA Size Factor",a.pct "% Perf" + from + (select round(pga_target_for_estimate/1024.0/1024.0,0) MB, + pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r + from v$pga_target_advice) a left join + (select round(pga_target_for_estimate/1024.0/1024.0,0) MB, + pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r + from v$pga_target_advice) b on + a.r = b.r+1 where + b.pct < 100'); + if (!$rs) return $t."Only in 9i or later"; + // $rs->Close(); + if ($rs->EOF) return $t."PGA could be too big"; + + return $t.rs2html($rs,false,false,true,false); + } + + function Explain($sql,$partial=false) + { + $savelog = $this->conn->LogSQL(false); + $rs = $this->conn->SelectLimit("select ID FROM PLAN_TABLE"); + if (!$rs) { + echo "

Missing PLAN_TABLE

+
+CREATE TABLE PLAN_TABLE (
+  STATEMENT_ID                    VARCHAR2(30),
+  TIMESTAMP                       DATE,
+  REMARKS                         VARCHAR2(80),
+  OPERATION                       VARCHAR2(30),
+  OPTIONS                         VARCHAR2(30),
+  OBJECT_NODE                     VARCHAR2(128),
+  OBJECT_OWNER                    VARCHAR2(30),
+  OBJECT_NAME                     VARCHAR2(30),
+  OBJECT_INSTANCE                 NUMBER(38),
+  OBJECT_TYPE                     VARCHAR2(30),
+  OPTIMIZER                       VARCHAR2(255),
+  SEARCH_COLUMNS                  NUMBER,
+  ID                              NUMBER(38),
+  PARENT_ID                       NUMBER(38),
+  POSITION                        NUMBER(38),
+  COST                            NUMBER(38),
+  CARDINALITY                     NUMBER(38),
+  BYTES                           NUMBER(38),
+  OTHER_TAG                       VARCHAR2(255),
+  PARTITION_START                 VARCHAR2(255),
+  PARTITION_STOP                  VARCHAR2(255),
+  PARTITION_ID                    NUMBER(38),
+  OTHER                           LONG,
+  DISTRIBUTION                    VARCHAR2(30)
+);
+
"; + return false; + } + + $rs->Close(); + // $this->conn->debug=1; + + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); + if ($arr) { + foreach($arr as $row) { + $sql = reset($row); + if (crc32($sql) == $partial) break; + } + } + } + + $s = "

Explain: ".htmlspecialchars($sql)."

"; + + $this->conn->BeginTrans(); + $id = "ADODB ".microtime(); + + $rs = $this->conn->Execute("EXPLAIN PLAN SET STATEMENT_ID='$id' FOR $sql"); + $m = $this->conn->ErrorMsg(); + if ($m) { + $this->conn->RollbackTrans(); + $this->conn->LogSQL($savelog); + $s .= "

$m

"; + return $s; + } + $rs = $this->conn->Execute(" + select + '
'||lpad('--', (level-1)*2,'-') || trim(operation) || ' ' || trim(options)||'
' as Operation, + object_name,COST,CARDINALITY,bytes + FROM plan_table +START WITH id = 0 and STATEMENT_ID='$id' +CONNECT BY prior id=parent_id and statement_id='$id'"); + + $s .= rs2html($rs,false,false,false,false); + $this->conn->RollbackTrans(); + $this->conn->LogSQL($savelog); + $s .= $this->Tracer($sql,$partial); + return $s; + } + + function CheckMemory() + { + if ($this->version['version'] < 9) return 'Oracle 9i or later required'; + + $rs = $this->conn->Execute(" +select a.name Buffer_Pool, b.size_for_estimate as cache_mb_estimate, + case when b.size_factor=1 then + '<<= Current' + when a.estd_physical_read_factor-b.estd_physical_read_factor > 0.001 and b.estd_physical_read_factor<1 then + '- BETTER than current by ' || round((1-b.estd_physical_read_factor)/b.estd_physical_read_factor*100,2) || '%' + else ' ' end as RATING, + b.estd_physical_read_factor \"Phys. Reads Factor\", + round((a.estd_physical_read_factor-b.estd_physical_read_factor)/b.estd_physical_read_factor*100,2) as \"% Improve\" + from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r,name from v\$db_cache_advice order by name,1) a , + (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r,name from v\$db_cache_advice order by name,1) b + where a.r = b.r-1 and a.name = b.name + "); + if (!$rs) return false; + + /* + The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size + */ + $s = "

Data Cache Advice Estimate

"; + if ($rs->EOF) { + $s .= "

Cache that is 50% of current size is still too big

"; + } else { + $s .= "Ideal size of Data Cache is when %BETTER gets close to zero."; + $s .= rs2html($rs,false,false,false,false); + } + return $s.$this->PGA_Advice(); + } + + /* + Generate html for suspicious/expensive sql + */ + function tohtml(&$rs,$type) + { + $o1 = $rs->FetchField(0); + $o2 = $rs->FetchField(1); + $o3 = $rs->FetchField(2); + if ($rs->EOF) return '

None found

'; + $check = ''; + $sql = ''; + $s = "\n\n'; + while (!$rs->EOF) { + if ($check != $rs->fields[0].'::'.$rs->fields[1]) { + if ($check) { + $carr = explode('::',$check); + $prefix = "'; + $suffix = ''; + if (strlen($prefix)>2000) { + $prefix = ''; + $suffix = ''; + } + + $s .= "\n'; + } + $sql = $rs->fields[2]; + $check = $rs->fields[0].'::'.$rs->fields[1]; + } else + $sql .= $rs->fields[2]; + if (substr($sql,strlen($sql)-1) == "\0") $sql = substr($sql,0,strlen($sql)-1); + $rs->MoveNext(); + } + $rs->Close(); + + $carr = explode('::',$check); + $prefix = "'; + $suffix = ''; + if (strlen($prefix)>2000) { + $prefix = ''; + $suffix = ''; + } + $s .= "\n'; + + return $s."
".$o1->name.''.$o2->name.''.$o3->name.'
".$carr[0].''.$carr[1].''.$prefix.$sql.$suffix.'
".$carr[0].''.$carr[1].''.$prefix.$sql.$suffix.'
\n\n"; + } + + // code thanks to Ixora. + // http://www.ixora.com.au/scripts/query_opt.htm + // requires oracle 8.1.7 or later + function SuspiciousSQL($numsql=10) + { + $sql = " +select + substr(to_char(s.pct, '99.00'), 2) || '%' load, + s.executions executes, + p.sql_text +from + ( + select + address, + buffer_gets, + executions, + pct, + rank() over (order by buffer_gets desc) ranking + from + ( + select + address, + buffer_gets, + executions, + 100 * ratio_to_report(buffer_gets) over () pct + from + sys.v_\$sql + where + command_type != 47 and module != 'T.O.A.D.' + ) + where + buffer_gets > 50 * executions + ) s, + sys.v_\$sqltext p +where + s.ranking <= $numsql and + p.address = s.address +order by + 1 desc, s.address, p.piece"; + + global $ADODB_CACHE_MODE; + if (isset($_GET['expsixora']) && isset($_GET['sql'])) { + $partial = empty($_GET['part']); + echo "".$this->Explain($_GET['sql'],$partial)."\n"; + } + + if (isset($_GET['sql'])) return $this->_SuspiciousSQL($numsql); + + $s = ''; + $timer = time(); + $s .= $this->_SuspiciousSQL($numsql); + $timer = time() - $timer; + + if ($timer > $this->noShowIxora) return $s; + $s .= '

'; + + $save = $ADODB_CACHE_MODE; + $ADODB_CACHE_MODE = ADODB_FETCH_NUM; + if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); + + $savelog = $this->conn->LogSQL(false); + $rs = $this->conn->SelectLimit($sql); + $this->conn->LogSQL($savelog); + + if (isset($savem)) $this->conn->SetFetchMode($savem); + $ADODB_CACHE_MODE = $save; + if ($rs) { + $s .= "\n

Ixora Suspicious SQL

"; + $s .= $this->tohtml($rs,'expsixora'); + } + + return $s; + } + + // code thanks to Ixora. + // http://www.ixora.com.au/scripts/query_opt.htm + // requires oracle 8.1.7 or later + function ExpensiveSQL($numsql = 10) + { + $sql = " +select + substr(to_char(s.pct, '99.00'), 2) || '%' load, + s.executions executes, + p.sql_text +from + ( + select + address, + disk_reads, + executions, + pct, + rank() over (order by disk_reads desc) ranking + from + ( + select + address, + disk_reads, + executions, + 100 * ratio_to_report(disk_reads) over () pct + from + sys.v_\$sql + where + command_type != 47 and module != 'T.O.A.D.' + ) + where + disk_reads > 50 * executions + ) s, + sys.v_\$sqltext p +where + s.ranking <= $numsql and + p.address = s.address +order by + 1 desc, s.address, p.piece +"; + global $ADODB_CACHE_MODE; + if (isset($_GET['expeixora']) && isset($_GET['sql'])) { + $partial = empty($_GET['part']); + echo "".$this->Explain($_GET['sql'],$partial)."\n"; + } + if (isset($_GET['sql'])) { + $var = $this->_ExpensiveSQL($numsql); + return $var; + } + + $s = ''; + $timer = time(); + $s .= $this->_ExpensiveSQL($numsql); + $timer = time() - $timer; + if ($timer > $this->noShowIxora) return $s; + + $s .= '

'; + $save = $ADODB_CACHE_MODE; + $ADODB_CACHE_MODE = ADODB_FETCH_NUM; + if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); + + $savelog = $this->conn->LogSQL(false); + $rs = $this->conn->Execute($sql); + $this->conn->LogSQL($savelog); + + if (isset($savem)) $this->conn->SetFetchMode($savem); + $ADODB_CACHE_MODE = $save; + + if ($rs) { + $s .= "\n

Ixora Expensive SQL

"; + $s .= $this->tohtml($rs,'expeixora'); + } + + return $s; + } + + function clearsql() + { + $perf_table = adodb_perf::table(); + // using the naive "delete from $perf_table where created<".$this->conn->sysTimeStamp will cause the table to lock, possibly + // for a long time + $sql = +"DECLARE cnt pls_integer; +BEGIN + cnt := 0; + FOR rec IN (SELECT ROWID AS rr FROM $perf_table WHERE createdconn->Execute($sql); + } + +} diff --git a/www/include/adodb/perf/perf-postgres.inc.php b/www/include/adodb/perf/perf-postgres.inc.php new file mode 100644 index 00000000..16b767d2 --- /dev/null +++ b/www/include/adodb/perf/perf-postgres.inc.php @@ -0,0 +1,156 @@ + array('RATIO', + "select case when count(*)=3 then 'TRUE' else 'FALSE' end from pg_settings where (name='stats_block_level' or name='stats_row_level' or name='stats_start_collector') and setting='on' ", + 'Value must be TRUE to enable hit ratio statistics (stats_start_collector,stats_row_level and stats_block_level must be set to true in postgresql.conf)'), + 'data cache hit ratio' => array('RATIO', + "select case when blks_hit=0 then 0 else round( ((1-blks_read::float/blks_hit)*100)::numeric, 2) end from pg_stat_database where datname='\$DATABASE'", + '=WarnCacheRatio'), + 'IO', + 'data reads' => array('IO', + 'select sum(heap_blks_read+toast_blks_read) from pg_statio_user_tables', + ), + 'data writes' => array('IO', + 'select round((sum(n_tup_ins/4.0+n_tup_upd/8.0+n_tup_del/4.0)/16)::numeric,2) from pg_stat_user_tables', + 'Count of inserts/updates/deletes * coef'), + + 'Data Cache', + 'data cache buffers' => array('DATAC', + "select setting from pg_settings where name='shared_buffers'", + 'Number of cache buffers. Tuning'), + 'cache blocksize' => array('DATAC', + 'select 8192', + '(estimate)' ), + 'data cache size' => array( 'DATAC', + "select setting::integer*8192 from pg_settings where name='shared_buffers'", + '' ), + 'operating system cache size' => array( 'DATA', + "select setting::integer*8192 from pg_settings where name='effective_cache_size'", + '(effective cache size)' ), + 'Memory Usage', + # Postgres 7.5 changelog: Rename server parameters SortMem and VacuumMem to work_mem and maintenance_work_mem; + 'sort/work buffer size' => array('CACHE', + "select setting::integer*1024 from pg_settings where name='sort_mem' or name = 'work_mem' order by name", + 'Size of sort buffer (per query)' ), + 'Connections', + 'current connections' => array('SESS', + 'select count(*) from pg_stat_activity', + ''), + 'max connections' => array('SESS', + "select setting from pg_settings where name='max_connections'", + ''), + 'Parameters', + 'rollback buffers' => array('COST', + "select setting from pg_settings where name='wal_buffers'", + 'WAL buffers'), + 'random page cost' => array('COST', + "select setting from pg_settings where name='random_page_cost'", + 'Cost of doing a seek (default=4). See random_page_cost'), + false + ); + + function __construct(&$conn) + { + $this->conn = $conn; + } + + var $optimizeTableLow = 'VACUUM %s'; + var $optimizeTableHigh = 'VACUUM ANALYZE %s'; + +/** + * @see adodb_perf::optimizeTable() + */ + + function optimizeTable($table, $mode = ADODB_OPT_LOW) + { + if(! is_string($table)) return false; + + $conn = $this->conn; + if (! $conn) return false; + + $sql = ''; + switch($mode) { + case ADODB_OPT_LOW : $sql = $this->optimizeTableLow; break; + case ADODB_OPT_HIGH: $sql = $this->optimizeTableHigh; break; + default : + ADOConnection::outp(sprintf("

%s: '%s' using of undefined mode '%s'

", __CLASS__, 'optimizeTable', $mode)); + return false; + } + $sql = sprintf($sql, $table); + + return $conn->Execute($sql) !== false; + } + + function Explain($sql,$partial=false) + { + $save = $this->conn->LogSQL(false); + + if ($partial) { + $sqlq = $this->conn->qstr($sql.'%'); + $arr = $this->conn->getArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); + if ($arr) { + foreach($arr as $row) { + $sql = reset($row); + if (crc32($sql) == $partial) break; + } + } + } + $sql = str_replace('?',"''",$sql); + $s = '

Explain: '.htmlspecialchars($sql).'

'; + $rs = $this->conn->Execute('EXPLAIN '.$sql); + $this->conn->LogSQL($save); + $s .= '
';
+		if ($rs)
+			while (!$rs->EOF) {
+				$s .= reset($rs->fields)."\n";
+				$rs->MoveNext();
+			}
+		$s .= '
'; + $s .= $this->Tracer($sql,$partial); + return $s; + } +} diff --git a/www/include/adodb/perf/perf-sqlite3.inc.php b/www/include/adodb/perf/perf-sqlite3.inc.php new file mode 100644 index 00000000..19198d5b --- /dev/null +++ b/www/include/adodb/perf/perf-sqlite3.inc.php @@ -0,0 +1,40 @@ +conn = $conn; + } + + function tables($orderby='1') + { + if (!$this->tablesSQL){ + return false; + } + + $rs = $this->conn->execute($this->tablesSQL); + if (!$rs) { + return false; + } + + $html = rs2html($rs, false, false, false, false); + return $html; + } +} diff --git a/www/include/adodb/phpdoc b/www/include/adodb/phpdoc new file mode 100644 index 00000000..d4cb73a9 --- /dev/null +++ b/www/include/adodb/phpdoc @@ -0,0 +1,20 @@ + + + + docs/api + docs/cache + + + + + + + scripts + tests + vendor/**/* + xsl + + + + diff --git a/www/include/adodb5/pivottable.inc.php b/www/include/adodb/pivottable.inc.php similarity index 88% rename from www/include/adodb5/pivottable.inc.php rename to www/include/adodb/pivottable.inc.php index dd7d5d88..14d8eebe 100644 --- a/www/include/adodb5/pivottable.inc.php +++ b/www/include/adodb/pivottable.inc.php @@ -1,15 +1,23 @@ + */ + +if (!function_exists('bzcompress')) { + trigger_error('bzip2 functions are not available', E_USER_ERROR); + return 0; +} + +/** + */ +class ADODB_Compress_Bzip2 { + /** + */ + var $_block_size = null; + + /** + */ + var $_work_level = null; + + /** + */ + var $_min_length = 1; + + /** + */ + function getBlockSize() { + return $this->_block_size; + } + + /** + */ + function setBlockSize($block_size) { + assert($block_size >= 1); + assert($block_size <= 9); + $this->_block_size = (int) $block_size; + } + + /** + */ + function getWorkLevel() { + return $this->_work_level; + } + + /** + */ + function setWorkLevel($work_level) { + assert($work_level >= 0); + assert($work_level <= 250); + $this->_work_level = (int) $work_level; + } + + /** + */ + function getMinLength() { + return $this->_min_length; + } + + /** + */ + function setMinLength($min_length) { + assert($min_length >= 0); + $this->_min_length = (int) $min_length; + } + + /** + */ + function __construct($block_size = null, $work_level = null, $min_length = null) { + if (!is_null($block_size)) { + $this->setBlockSize($block_size); + } + + if (!is_null($work_level)) { + $this->setWorkLevel($work_level); + } + + if (!is_null($min_length)) { + $this->setMinLength($min_length); + } + } + + /** + */ + function write($data, $key) { + if (strlen($data) < $this->_min_length) { + return $data; + } + + if (!is_null($this->_block_size)) { + if (!is_null($this->_work_level)) { + return bzcompress($data, $this->_block_size, $this->_work_level); + } else { + return bzcompress($data, $this->_block_size); + } + } + + return bzcompress($data); + } + + /** + */ + function read($data, $key) { + return $data ? bzdecompress($data) : $data; + } + +} + +return 1; diff --git a/www/include/adodb/session/adodb-compress-gzip.php b/www/include/adodb/session/adodb-compress-gzip.php new file mode 100644 index 00000000..bbaf6c63 --- /dev/null +++ b/www/include/adodb/session/adodb-compress-gzip.php @@ -0,0 +1,99 @@ +_level; + } + + /** + */ + function setLevel($level) { + assert($level >= 0); + assert($level <= 9); + $this->_level = (int) $level; + } + + /** + */ + function getMinLength() { + return $this->_min_length; + } + + /** + */ + function setMinLength($min_length) { + assert($min_length >= 0); + $this->_min_length = (int) $min_length; + } + + /** + */ + function __construct($level = null, $min_length = null) { + if (!is_null($level)) { + $this->setLevel($level); + } + + if (!is_null($min_length)) { + $this->setMinLength($min_length); + } + } + + /** + */ + function write($data, $key) { + if (strlen($data) < $this->_min_length) { + return $data; + } + + if (!is_null($this->_level)) { + return gzcompress($data, $this->_level); + } else { + return gzcompress($data); + } + } + + /** + */ + function read($data, $key) { + return $data ? gzuncompress($data) : $data; + } + +} + +return 1; diff --git a/www/include/adodb/session/adodb-cryptsession.php b/www/include/adodb/session/adodb-cryptsession.php new file mode 100644 index 00000000..08805321 --- /dev/null +++ b/www/include/adodb/session/adodb-cryptsession.php @@ -0,0 +1,30 @@ +_cipher; + } + + /** + */ + function setCipher($cipher) { + $this->_cipher = $cipher; + } + + /** + */ + function getMode() { + return $this->_mode; + } + + /** + */ + function setMode($mode) { + $this->_mode = $mode; + } + + /** + */ + function getSource() { + return $this->_source; + } + + /** + */ + function setSource($source) { + $this->_source = $source; + } + + /** + */ + function __construct($cipher = null, $mode = null, $source = null) { + if (!$cipher) { + $cipher = MCRYPT_RIJNDAEL_256; + } + if (!$mode) { + $mode = MCRYPT_MODE_ECB; + } + if (!$source) { + $source = MCRYPT_RAND; + } + + $this->_cipher = $cipher; + $this->_mode = $mode; + $this->_source = $source; + } + + /** + */ + function write($data, $key) { + $iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode); + $iv = mcrypt_create_iv($iv_size, $this->_source); + return mcrypt_encrypt($this->_cipher, $key, $data, $this->_mode, $iv); + } + + /** + */ + function read($data, $key) { + $iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode); + $iv = mcrypt_create_iv($iv_size, $this->_source); + $rv = mcrypt_decrypt($this->_cipher, $key, $data, $this->_mode, $iv); + return rtrim($rv, "\0"); + } + +} + +return 1; diff --git a/www/include/adodb/session/adodb-encrypt-md5.php b/www/include/adodb/session/adodb-encrypt-md5.php new file mode 100644 index 00000000..7ae9b56e --- /dev/null +++ b/www/include/adodb/session/adodb-encrypt-md5.php @@ -0,0 +1,46 @@ +encrypt($data, $key); + } + + /** + */ + function read($data, $key) { + $md5crypt = new MD5Crypt(); + return $md5crypt->decrypt($data, $key); + } + +} + +return 1; diff --git a/www/include/adodb/session/adodb-encrypt-secret.php b/www/include/adodb/session/adodb-encrypt-secret.php new file mode 100644 index 00000000..2c29f7a0 --- /dev/null +++ b/www/include/adodb/session/adodb-encrypt-secret.php @@ -0,0 +1,47 @@ +encrypt($data, $key); + + } + + + function read($data, $key) + { + $sha1crypt = new SHA1Crypt(); + return $sha1crypt->decrypt($data, $key); + + } +} + + + +return 1; diff --git a/www/include/adodb/session/adodb-sess.txt b/www/include/adodb/session/adodb-sess.txt new file mode 100644 index 00000000..1e9a8aac --- /dev/null +++ b/www/include/adodb/session/adodb-sess.txt @@ -0,0 +1,131 @@ +John, + +I have been an extremely satisfied ADODB user for several years now. + +To give you something back for all your hard work, I've spent the last 3 +days rewriting the adodb-session.php code. + +---------- +What's New +---------- + +Here's a list of the new code's benefits: + +* Combines the functionality of the three files: + +adodb-session.php +adodb-session-clob.php +adodb-cryptsession.php + +each with very similar functionality, into a single file adodb-session.php. +This will ease maintenance and support issues. + +* Supports multiple encryption and compression schemes. + Currently, we support: + + MD5Crypt (crypt.inc.php) + MCrypt + Secure (Horde's emulation of MCrypt, if MCrypt module is not available.) + GZip + BZip2 + +These can be stacked, so if you want to compress and then encrypt your +session data, it's easy. +Also, the built-in MCrypt functions will be *much* faster, and more secure, +than the MD5Crypt code. + +* adodb-session.php contains a single class ADODB_Session that encapsulates +all functionality. + This eliminates the use of global vars and defines (though they are +supported for backwards compatibility). + +* All user defined parameters are now static functions in the ADODB_Session +class. + +New parameters include: + +* encryptionKey(): Define the encryption key used to encrypt the session. +Originally, it was a hard coded string. + +* persist(): Define if the database will be opened in persistent mode. +Originally, the user had to call adodb_sess_open(). + +* dataFieldName(): Define the field name used to store the session data, as +'DATA' appears to be a reserved word in the following cases: + ANSI SQL + IBM DB2 + MS SQL Server + Postgres + SAP + +* filter(): Used to support multiple, simultaneous encryption/compression +schemes. + +* Debug support is improved through _rsdump() function, which is called after +every database call. + +------------ +What's Fixed +------------ + +The new code includes several bug fixes and enhancements: + +* sesskey is compared in BINARY mode for MySQL, to avoid problems with +session keys that differ only by case. + Of course, the user should define the sesskey field as BINARY, to +correctly fix this problem, otherwise performance will suffer. + +* In ADODB_Session::gc(), if $expire_notify is true, the multiple DELETES in +the original code have been optimized to a single DELETE. + +* In ADODB_Session::destroy(), since "SELECT expireref, sesskey FROM $table +WHERE sesskey = $qkey" will only return a single value, we don't loop on the +result, we simply process the row, if any. + +* We close $rs after every use. + +--------------- +What's the Same +--------------- + +I know backwards compatibility is *very* important to you. Therefore, the +new code is 100% backwards compatible. + +If you like my code, but don't "trust" it's backwards compatible, maybe we +offer it as beta code, in a new directory for a release or two? + +------------ +What's To Do +------------ + +I've vascillated over whether to use a single function to get/set +parameters: + +$user = ADODB_Session::user(); // get +ADODB_Session::user($user); // set + +or to use separate functions (which is the PEAR/Java way): + +$user = ADODB_Session::getUser(); +ADODB_Session::setUser($user); + +I've chosen the former as it's makes for a simpler API, and reduces the +amount of code, but I'd be happy to change it to the latter. + +Also, do you think the class should be a singleton class, versus a static +class? + +Let me know if you find this code useful, and will be including it in the +next release of ADODB. + +If so, I will modify the current documentation to detail the new +functionality. To that end, what file(s) contain the documentation? Please +send them to me if they are not publicly available. + +Also, if there is *anything* in the code that you like to see changed, let +me know. + +Thanks, + +Ross + diff --git a/www/include/adodb/session/adodb-session-clob.php b/www/include/adodb/session/adodb-session-clob.php new file mode 100644 index 00000000..8c5e9fb3 --- /dev/null +++ b/www/include/adodb/session/adodb-session-clob.php @@ -0,0 +1,27 @@ + + */ + +if (!defined('ADODB_SESSION')) { + require_once dirname(__FILE__) . '/adodb-session2.php'; +} +ADODB_Session::clob('CLOB'); diff --git a/www/include/adodb/session/adodb-session.php b/www/include/adodb/session/adodb-session.php new file mode 100644 index 00000000..9e716232 --- /dev/null +++ b/www/include/adodb/session/adodb-session.php @@ -0,0 +1,941 @@ + + */ + +/* + You may want to rename the 'data' field to 'session_data' as + 'data' appears to be a reserved word for one or more of the following: + ANSI SQL + IBM DB2 + MS SQL Server + Postgres + SAP + + If you do, then execute: + + ADODB_Session::dataFieldName('session_data'); + +*/ + +if (!defined('_ADODB_LAYER')) { + require realpath(dirname(__FILE__) . '/../adodb.inc.php'); +} + +if (defined('ADODB_SESSION')) return 1; + +define('ADODB_SESSION', dirname(__FILE__)); + + +/* + Unserialize session data manually. See PHPLens Issue No: 9821 + + From Kerr Schere, to unserialize session data stored via ADOdb. + 1. Pull the session data from the db and loop through it. + 2. Inside the loop, you will need to urldecode the data column. + 3. After urldecode, run the serialized string through this function: + +*/ +function adodb_unserialize( $serialized_string ) +{ + $variables = array( ); + $a = preg_split( "/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE ); + for( $i = 0; $i < count( $a ); $i = $i+2 ) { + $variables[$a[$i]] = unserialize( $a[$i+1] ); + } + return( $variables ); +} + +/* + Thanks Joe Li. See PHPLens Issue No: 11487&x=1 + Since adodb 4.61. +*/ +function adodb_session_regenerate_id() +{ + $conn = ADODB_Session::_conn(); + if (!$conn) return false; + + $old_id = session_id(); + if (function_exists('session_regenerate_id')) { + session_regenerate_id(); + } else { + session_id(md5(uniqid(rand(), true))); + $ck = session_get_cookie_params(); + setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure'], $ck['httponly']); + //@session_start(); + } + $new_id = session_id(); + $ok = $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id)); + + /* it is possible that the update statement fails due to a collision */ + if (!$ok) { + session_id($old_id); + if (empty($ck)) $ck = session_get_cookie_params(); + setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure'], $ck['httponly']); + return false; + } + + return true; +} + +/* + Generate database table for session data + @see PHPLens Issue No: 12280 + @return 0 if failure, 1 if errors, 2 if successful. + @author Markus Staab http://www.public-4u.de +*/ +function adodb_session_create_table($schemaFile=null,$conn = null) +{ + // set default values + if ($schemaFile===null) $schemaFile = ADODB_SESSION . '/session_schema.xml'; + if ($conn===null) $conn = ADODB_Session::_conn(); + + if (!$conn) return 0; + + $schema = new adoSchema($conn); + $schema->ParseSchema($schemaFile); + return $schema->ExecuteSchema(); +} + +/*! + \static +*/ +class ADODB_Session { + ///////////////////// + // getter/setter methods + ///////////////////// + + /* + + function Lock($lock=null) + { + static $_lock = false; + + if (!is_null($lock)) $_lock = $lock; + return $lock; + } + */ + /*! + */ + function driver($driver = null) { + static $_driver = 'mysql'; + static $set = false; + + if (!is_null($driver)) { + $_driver = trim($driver); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) { + return $GLOBALS['ADODB_SESSION_DRIVER']; + } + } + + return $_driver; + } + + /*! + */ + function host($host = null) { + static $_host = 'localhost'; + static $set = false; + + if (!is_null($host)) { + $_host = trim($host); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) { + return $GLOBALS['ADODB_SESSION_CONNECT']; + } + } + + return $_host; + } + + /*! + */ + function user($user = null) { + static $_user = 'root'; + static $set = false; + + if (!is_null($user)) { + $_user = trim($user); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_USER'])) { + return $GLOBALS['ADODB_SESSION_USER']; + } + } + + return $_user; + } + + /*! + */ + function password($password = null) { + static $_password = ''; + static $set = false; + + if (!is_null($password)) { + $_password = $password; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_PWD'])) { + return $GLOBALS['ADODB_SESSION_PWD']; + } + } + + return $_password; + } + + /*! + */ + function database($database = null) { + static $_database = 'xphplens_2'; + static $set = false; + + if (!is_null($database)) { + $_database = trim($database); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_DB'])) { + return $GLOBALS['ADODB_SESSION_DB']; + } + } + + return $_database; + } + + /*! + */ + function persist($persist = null) + { + static $_persist = true; + + if (!is_null($persist)) { + $_persist = trim($persist); + } + + return $_persist; + } + + /*! + */ + function lifetime($lifetime = null) { + static $_lifetime; + static $set = false; + + if (!is_null($lifetime)) { + $_lifetime = (int) $lifetime; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESS_LIFE'])) { + return $GLOBALS['ADODB_SESS_LIFE']; + } + } + if (!$_lifetime) { + $_lifetime = ini_get('session.gc_maxlifetime'); + if ($_lifetime <= 1) { + // bug in PHP 4.0.3 pl 1 -- how about other versions? + //print "

Session Error: PHP.INI setting session.gc_maxlifetimenot set: $lifetime

"; + $_lifetime = 1440; + } + } + + return $_lifetime; + } + + /*! + */ + function debug($debug = null) { + static $_debug = false; + static $set = false; + + if (!is_null($debug)) { + $_debug = (bool) $debug; + + $conn = ADODB_Session::_conn(); + if ($conn) { + $conn->debug = $_debug; + } + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESS_DEBUG'])) { + return $GLOBALS['ADODB_SESS_DEBUG']; + } + } + + return $_debug; + } + + /*! + */ + function expireNotify($expire_notify = null) { + static $_expire_notify; + static $set = false; + + if (!is_null($expire_notify)) { + $_expire_notify = $expire_notify; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) { + return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY']; + } + } + + return $_expire_notify; + } + + /*! + */ + function table($table = null) { + static $_table = 'sessions'; + static $set = false; + + if (!is_null($table)) { + $_table = trim($table); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_TBL'])) { + return $GLOBALS['ADODB_SESSION_TBL']; + } + } + + return $_table; + } + + /*! + */ + function optimize($optimize = null) { + static $_optimize = false; + static $set = false; + + if (!is_null($optimize)) { + $_optimize = (bool) $optimize; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (defined('ADODB_SESSION_OPTIMIZE')) { + return true; + } + } + + return $_optimize; + } + + /*! + */ + function syncSeconds($sync_seconds = null) { + static $_sync_seconds = 60; + static $set = false; + + if (!is_null($sync_seconds)) { + $_sync_seconds = (int) $sync_seconds; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (defined('ADODB_SESSION_SYNCH_SECS')) { + return ADODB_SESSION_SYNCH_SECS; + } + } + + return $_sync_seconds; + } + + /*! + */ + function clob($clob = null) { + static $_clob = false; + static $set = false; + + if (!is_null($clob)) { + $_clob = strtolower(trim($clob)); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) { + return $GLOBALS['ADODB_SESSION_USE_LOBS']; + } + } + + return $_clob; + } + + /*! + */ + function dataFieldName($data_field_name = null) { + static $_data_field_name = 'data'; + + if (!is_null($data_field_name)) { + $_data_field_name = trim($data_field_name); + } + + return $_data_field_name; + } + + /*! + */ + function filter($filter = null) { + static $_filter = array(); + + if (!is_null($filter)) { + if (!is_array($filter)) { + $filter = array($filter); + } + $_filter = $filter; + } + + return $_filter; + } + + /*! + */ + function encryptionKey($encryption_key = null) { + static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!'; + + if (!is_null($encryption_key)) { + $_encryption_key = $encryption_key; + } + + return $_encryption_key; + } + + ///////////////////// + // private methods + ///////////////////// + + /*! + */ + function _conn($conn=null) { + return $GLOBALS['ADODB_SESS_CONN']; + } + + /*! + */ + function _crc($crc = null) { + static $_crc = false; + + if (!is_null($crc)) { + $_crc = $crc; + } + + return $_crc; + } + + /*! + */ + function _init() { + session_set_save_handler( + array('ADODB_Session', 'open'), + array('ADODB_Session', 'close'), + array('ADODB_Session', 'read'), + array('ADODB_Session', 'write'), + array('ADODB_Session', 'destroy'), + array('ADODB_Session', 'gc') + ); + } + + + /*! + */ + function _sessionKey() { + // use this function to create the encryption key for crypted sessions + // crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt + return crypt(ADODB_Session::encryptionKey(), session_id()); + } + + /*! + */ + function _dumprs($rs) { + $conn = ADODB_Session::_conn(); + $debug = ADODB_Session::debug(); + + if (!$conn) { + return; + } + + if (!$debug) { + return; + } + + if (!$rs) { + echo "
\$rs is null or false
\n"; + return; + } + + //echo "
\nAffected_Rows=",$conn->Affected_Rows(),"
\n"; + + if (!is_object($rs)) { + return; + } + + require_once ADODB_SESSION.'/../tohtml.inc.php'; + rs2html($rs); + } + + ///////////////////// + // public methods + ///////////////////// + + function config($driver, $host, $user, $password, $database=false,$options=false) + { + ADODB_Session::driver($driver); + ADODB_Session::host($host); + ADODB_Session::user($user); + ADODB_Session::password($password); + ADODB_Session::database($database); + + if ($driver == 'oci8' || $driver == 'oci8po') $options['lob'] = 'CLOB'; + + if (isset($options['table'])) ADODB_Session::table($options['table']); + if (isset($options['lob'])) ADODB_Session::clob($options['lob']); + if (isset($options['debug'])) ADODB_Session::debug($options['debug']); + } + + /*! + Create the connection to the database. + + If $conn already exists, reuse that connection + */ + function open($save_path, $session_name, $persist = null) + { + $conn = ADODB_Session::_conn(); + + if ($conn) { + return true; + } + + $database = ADODB_Session::database(); + $debug = ADODB_Session::debug(); + $driver = ADODB_Session::driver(); + $host = ADODB_Session::host(); + $password = ADODB_Session::password(); + $user = ADODB_Session::user(); + + if (!is_null($persist)) { + ADODB_Session::persist($persist); + } else { + $persist = ADODB_Session::persist(); + } + +# these can all be defaulted to in php.ini +# assert('$database'); +# assert('$driver'); +# assert('$host'); + + $conn = ADONewConnection($driver); + + if ($debug) { + $conn->debug = true; +// ADOConnection::outp( " driver=$driver user=$user pwd=$password db=$database "); + } + + if ($persist) { + switch($persist) { + default: + case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break; + case 'C': $ok = $conn->Connect($host, $user, $password, $database); break; + case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break; + } + } else { + $ok = $conn->Connect($host, $user, $password, $database); + } + + if ($ok) $GLOBALS['ADODB_SESS_CONN'] = $conn; + else + ADOConnection::outp('

Session: connection failed

', false); + + + return $ok; + } + + /*! + Close the connection + */ + function close() + { +/* + $conn = ADODB_Session::_conn(); + if ($conn) $conn->Close(); +*/ + return true; + } + + /* + Slurp in the session variables and return the serialized string + */ + function read($key) + { + $conn = ADODB_Session::_conn(); + $data = ADODB_Session::dataFieldName(); + $filter = ADODB_Session::filter(); + $table = ADODB_Session::table(); + + if (!$conn) { + return ''; + } + + //assert('$table'); + + $qkey = $conn->quote($key); + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + $sql = "SELECT $data FROM $table WHERE sesskey = $binary $qkey AND expiry >= " . time(); + /* Lock code does not work as it needs to hold transaction within whole page, and we don't know if + developer has committed elsewhere... :( + */ + #if (ADODB_Session::Lock()) + # $rs = $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), $data); + #else + + $rs = $conn->Execute($sql); + //ADODB_Session::_dumprs($rs); + if ($rs) { + if ($rs->EOF) { + $v = ''; + } else { + $v = reset($rs->fields); + $filter = array_reverse($filter); + foreach ($filter as $f) { + if (is_object($f)) { + $v = $f->read($v, ADODB_Session::_sessionKey()); + } + } + $v = rawurldecode($v); + } + + $rs->Close(); + + ADODB_Session::_crc(strlen($v) . crc32($v)); + return $v; + } + + return ''; + } + + /*! + Write the serialized data to a database. + + If the data has not been modified since the last read(), we do not write. + */ + function write($key, $val) + { + global $ADODB_SESSION_READONLY; + + if (!empty($ADODB_SESSION_READONLY)) return; + + $clob = ADODB_Session::clob(); + $conn = ADODB_Session::_conn(); + $crc = ADODB_Session::_crc(); + $data = ADODB_Session::dataFieldName(); + $debug = ADODB_Session::debug(); + $driver = ADODB_Session::driver(); + $expire_notify = ADODB_Session::expireNotify(); + $filter = ADODB_Session::filter(); + $lifetime = ADODB_Session::lifetime(); + $table = ADODB_Session::table(); + + if (!$conn) { + return false; + } + $qkey = $conn->qstr($key); + + //assert('$table'); + + $expiry = time() + $lifetime; + + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + // crc32 optimization since adodb 2.1 + // now we only update expiry date, thx to sebastian thom in adodb 2.32 + if ($crc !== false && $crc == (strlen($val) . crc32($val))) { + if ($debug) { + ADOConnection::outp( '

Session: Only updating date - crc32 not changed

'); + } + + $expirevar = ''; + if ($expire_notify) { + $var = reset($expire_notify); + global $$var; + if (isset($$var)) { + $expirevar = $$var; + } + } + + + $sql = "UPDATE $table SET expiry = ".$conn->Param('0').",expireref=".$conn->Param('1')." WHERE $binary sesskey = ".$conn->Param('2')." AND expiry >= ".$conn->Param('3'); + $rs = $conn->Execute($sql,array($expiry,$expirevar,$key,time())); + return true; + } + $val = rawurlencode($val); + foreach ($filter as $f) { + if (is_object($f)) { + $val = $f->write($val, ADODB_Session::_sessionKey()); + } + } + + $arr = array('sesskey' => $key, 'expiry' => $expiry, $data => $val, 'expireref' => ''); + if ($expire_notify) { + $var = reset($expire_notify); + global $$var; + if (isset($$var)) { + $arr['expireref'] = $$var; + } + } + + if (!$clob) { // no lobs, simply use replace() + $arr[$data] = $val; + $rs = $conn->Replace($table, $arr, 'sesskey', $autoQuote = true); + + } else { + // what value shall we insert/update for lob row? + switch ($driver) { + // empty_clob or empty_lob for oracle dbs + case 'oracle': + case 'oci8': + case 'oci8po': + case 'oci805': + $lob_value = sprintf('empty_%s()', strtolower($clob)); + break; + + // null for all other + default: + $lob_value = 'null'; + break; + } + + $conn->StartTrans(); + $expiryref = $conn->qstr($arr['expireref']); + // do we insert or update? => as for sesskey + $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = $qkey"); + if ($rs && reset($rs->fields) > 0) { + $sql = "UPDATE $table SET expiry = $expiry, $data = $lob_value, expireref=$expiryref WHERE sesskey = $qkey"; + } else { + $sql = "INSERT INTO $table (expiry, $data, sesskey,expireref) VALUES ($expiry, $lob_value, $qkey,$expiryref)"; + } + if ($rs)$rs->Close(); + + + $err = ''; + $rs1 = $conn->Execute($sql); + if (!$rs1) $err = $conn->ErrorMsg()."\n"; + + $rs2 = $conn->UpdateBlob($table, $data, $val, " sesskey=$qkey", strtoupper($clob)); + if (!$rs2) $err .= $conn->ErrorMsg()."\n"; + + $rs = ($rs && $rs2) ? true : false; + $conn->CompleteTrans(); + } + + if (!$rs) { + ADOConnection::outp('

Session Replace: ' . $conn->ErrorMsg() . '

', false); + return false; + } else { + // bug in access driver (could be odbc?) means that info is not committed + // properly unless select statement executed in Win2000 + if ($conn->databaseType == 'access') { + $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + if ($rs) { + $rs->Close(); + } + } + }/* + if (ADODB_Session::Lock()) { + $conn->CommitTrans(); + }*/ + return $rs ? true : false; + } + + /*! + */ + function destroy($key) { + $conn = ADODB_Session::_conn(); + $table = ADODB_Session::table(); + $expire_notify = ADODB_Session::expireNotify(); + + if (!$conn) { + return false; + } + + //assert('$table'); + + $qkey = $conn->quote($key); + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + if ($expire_notify) { + reset($expire_notify); + $fn = next($expire_notify); + $savem = $conn->SetFetchMode(ADODB_FETCH_NUM); + $sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + $conn->SetFetchMode($savem); + if (!$rs) { + return false; + } + if (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + //assert('$ref'); + //assert('$key'); + $fn($ref, $key); + } + $rs->Close(); + } + + $sql = "DELETE FROM $table WHERE $binary sesskey = $qkey"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + + return $rs ? true : false; + } + + /*! + */ + function gc($maxlifetime) + { + $conn = ADODB_Session::_conn(); + $debug = ADODB_Session::debug(); + $expire_notify = ADODB_Session::expireNotify(); + $optimize = ADODB_Session::optimize(); + $sync_seconds = ADODB_Session::syncSeconds(); + $table = ADODB_Session::table(); + + if (!$conn) { + return false; + } + + + $time = time(); + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + if ($expire_notify) { + reset($expire_notify); + $fn = next($expire_notify); + $savem = $conn->SetFetchMode(ADODB_FETCH_NUM); + $sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + $conn->SetFetchMode($savem); + if ($rs) { + $conn->StartTrans(); + $keys = array(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref, $key); + $del = $conn->Execute("DELETE FROM $table WHERE sesskey=".$conn->Param('0'),array($key)); + $rs->MoveNext(); + } + $rs->Close(); + + $conn->CompleteTrans(); + } + } else { + + if (1) { + $sql = "SELECT sesskey FROM $table WHERE expiry < $time"; + $arr = $conn->GetAll($sql); + foreach ($arr as $row) { + $sql2 = "DELETE FROM $table WHERE sesskey=".$conn->Param('0'); + $conn->Execute($sql2,array(reset($row))); + } + } else { + $sql = "DELETE FROM $table WHERE expiry < $time"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + if ($rs) $rs->Close(); + } + if ($debug) { + ADOConnection::outp("

Garbage Collection: $sql

"); + } + } + + // suggested by Cameron, "GaM3R" + if ($optimize) { + $driver = ADODB_Session::driver(); + + if (preg_match('/mysql/i', $driver)) { + $sql = "OPTIMIZE TABLE $table"; + } + if (preg_match('/postgres/i', $driver)) { + $sql = "VACUUM $table"; + } + if (!empty($sql)) { + $conn->Execute($sql); + } + } + + if ($sync_seconds) { + $sql = 'SELECT '; + if ($conn->dataProvider === 'oci8') { + $sql .= "TO_CHAR({$conn->sysTimeStamp}, 'RRRR-MM-DD HH24:MI:SS')"; + } else { + $sql .= $conn->sysTimeStamp; + } + $sql .= " FROM $table"; + + $rs = $conn->SelectLimit($sql, 1); + if ($rs && !$rs->EOF) { + $dbts = reset($rs->fields); + $rs->Close(); + $dbt = $conn->UnixTimeStamp($dbts); + $t = time(); + + if (abs($dbt - $t) >= $sync_seconds) { + $msg = __FILE__ . + ": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: " . + " database=$dbt ($dbts), webserver=$t (diff=". (abs($dbt - $t) / 60) . ' minutes)'; + error_log($msg); + if ($debug) { + ADOConnection::outp("

$msg

"); + } + } + } + } + + return true; + } +} + +ADODB_Session::_init(); +if (empty($ADODB_SESSION_READONLY)) + register_shutdown_function('session_write_close'); + +// for backwards compatibility only +function adodb_sess_open($save_path, $session_name, $persist = true) { + return ADODB_Session::open($save_path, $session_name, $persist); +} + +// for backwards compatibility only +function adodb_sess_gc($t) +{ + return ADODB_Session::gc($t); +} diff --git a/www/include/adodb/session/adodb-session2.php b/www/include/adodb/session/adodb-session2.php new file mode 100644 index 00000000..bf64b416 --- /dev/null +++ b/www/include/adodb/session/adodb-session2.php @@ -0,0 +1,915 @@ +Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id)); + + /* it is possible that the update statement fails due to a collision */ + if (!$ok) { + session_id($old_id); + if (empty($ck)) $ck = session_get_cookie_params(); + setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure'], $ck['httponly']); + return false; + } + + return true; +} + +/* + Generate database table for session data + @see PHPLens Issue No: 12280 + @return 0 if failure, 1 if errors, 2 if successful. + @author Markus Staab http://www.public-4u.de +*/ +function adodb_session_create_table($schemaFile=null,$conn = null) +{ + // set default values + if ($schemaFile===null) $schemaFile = ADODB_SESSION . '/session_schema2.xml'; + if ($conn===null) $conn = ADODB_Session::_conn(); + + if (!$conn) return 0; + + $schema = new adoSchema($conn); + $schema->ParseSchema($schemaFile); + return $schema->ExecuteSchema(); +} + +/*! + \static +*/ +class ADODB_Session { + ///////////////////// + // getter/setter methods + ///////////////////// + + /* + + function Lock($lock=null) + { + static $_lock = false; + + if (!is_null($lock)) $_lock = $lock; + return $lock; + } + */ + /*! + */ + static function driver($driver = null) + { + static $_driver = 'mysqli'; + static $set = false; + + if (!is_null($driver)) { + $_driver = trim($driver); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) { + return $GLOBALS['ADODB_SESSION_DRIVER']; + } + } + + return $_driver; + } + + /*! + */ + static function host($host = null) { + static $_host = 'localhost'; + static $set = false; + + if (!is_null($host)) { + $_host = trim($host); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) { + return $GLOBALS['ADODB_SESSION_CONNECT']; + } + } + + return $_host; + } + + /*! + */ + static function user($user = null) + { + static $_user = 'root'; + static $set = false; + + if (!is_null($user)) { + $_user = trim($user); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_USER'])) { + return $GLOBALS['ADODB_SESSION_USER']; + } + } + + return $_user; + } + + /*! + */ + static function password($password = null) + { + static $_password = ''; + static $set = false; + + if (!is_null($password)) { + $_password = $password; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_PWD'])) { + return $GLOBALS['ADODB_SESSION_PWD']; + } + } + + return $_password; + } + + /*! + */ + static function database($database = null) + { + static $_database = ''; + static $set = false; + + if (!is_null($database)) { + $_database = trim($database); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_DB'])) { + return $GLOBALS['ADODB_SESSION_DB']; + } + } + return $_database; + } + + /*! + */ + static function persist($persist = null) + { + static $_persist = true; + + if (!is_null($persist)) { + $_persist = trim($persist); + } + + return $_persist; + } + + /*! + */ + static function lifetime($lifetime = null) + { + static $_lifetime; + static $set = false; + + if (!is_null($lifetime)) { + $_lifetime = (int) $lifetime; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESS_LIFE'])) { + return $GLOBALS['ADODB_SESS_LIFE']; + } + } + if (!$_lifetime) { + $_lifetime = ini_get('session.gc_maxlifetime'); + if ($_lifetime <= 1) { + // bug in PHP 4.0.3 pl 1 -- how about other versions? + //print "

Session Error: PHP.INI setting session.gc_maxlifetimenot set: $lifetime

"; + $_lifetime = 1440; + } + } + + return $_lifetime; + } + + /*! + */ + static function debug($debug = null) + { + static $_debug = false; + static $set = false; + + if (!is_null($debug)) { + $_debug = (bool) $debug; + + $conn = ADODB_Session::_conn(); + if ($conn) { + #$conn->debug = $_debug; + } + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESS_DEBUG'])) { + return $GLOBALS['ADODB_SESS_DEBUG']; + } + } + + return $_debug; + } + + /*! + */ + static function expireNotify($expire_notify = null) + { + static $_expire_notify; + static $set = false; + + if (!is_null($expire_notify)) { + $_expire_notify = $expire_notify; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) { + return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY']; + } + } + + return $_expire_notify; + } + + /*! + */ + static function table($table = null) + { + static $_table = 'sessions2'; + static $set = false; + + if (!is_null($table)) { + $_table = trim($table); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_TBL'])) { + return $GLOBALS['ADODB_SESSION_TBL']; + } + } + + return $_table; + } + + /*! + */ + static function optimize($optimize = null) + { + static $_optimize = false; + static $set = false; + + if (!is_null($optimize)) { + $_optimize = (bool) $optimize; + $set = true; + } elseif (!$set) { + // backwards compatibility + if (defined('ADODB_SESSION_OPTIMIZE')) { + return true; + } + } + + return $_optimize; + } + + /*! + */ + static function syncSeconds($sync_seconds = null) { + //echo ("

WARNING: ADODB_SESSION::syncSeconds is longer used, please remove this function for your code

"); + + return 0; + } + + /*! + */ + static function clob($clob = null) { + static $_clob = false; + static $set = false; + + if (!is_null($clob)) { + $_clob = strtolower(trim($clob)); + $set = true; + } elseif (!$set) { + // backwards compatibility + if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) { + return $GLOBALS['ADODB_SESSION_USE_LOBS']; + } + } + + return $_clob; + } + + /*! + */ + static function dataFieldName($data_field_name = null) { + //echo ("

WARNING: ADODB_SESSION::dataFieldName() is longer used, please remove this function for your code

"); + return ''; + } + + /*! + */ + static function filter($filter = null) { + static $_filter = array(); + + if (!is_null($filter)) { + if (!is_array($filter)) { + $filter = array($filter); + } + $_filter = $filter; + } + + return $_filter; + } + + /*! + */ + static function encryptionKey($encryption_key = null) { + static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!'; + + if (!is_null($encryption_key)) { + $_encryption_key = $encryption_key; + } + + return $_encryption_key; + } + + ///////////////////// + // private methods + ///////////////////// + + /*! + */ + static function _conn($conn=null) { + return isset($GLOBALS['ADODB_SESS_CONN']) ? $GLOBALS['ADODB_SESS_CONN'] : false; + } + + /*! + */ + static function _crc($crc = null) { + static $_crc = false; + + if (!is_null($crc)) { + $_crc = $crc; + } + + return $_crc; + } + + /*! + */ + static function _init() { + session_set_save_handler( + array('ADODB_Session', 'open'), + array('ADODB_Session', 'close'), + array('ADODB_Session', 'read'), + array('ADODB_Session', 'write'), + array('ADODB_Session', 'destroy'), + array('ADODB_Session', 'gc') + ); + } + + + /*! + */ + static function _sessionKey() { + // use this function to create the encryption key for crypted sessions + // crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt + return crypt(ADODB_Session::encryptionKey(), session_id()); + } + + /*! + */ + static function _dumprs(&$rs) { + $conn = ADODB_Session::_conn(); + $debug = ADODB_Session::debug(); + + if (!$conn) { + return; + } + + if (!$debug) { + return; + } + + if (!$rs) { + echo "
\$rs is null or false
\n"; + return; + } + + //echo "
\nAffected_Rows=",$conn->Affected_Rows(),"
\n"; + + if (!is_object($rs)) { + return; + } + $rs = $conn->_rs2rs($rs); + + require_once ADODB_SESSION.'/../tohtml.inc.php'; + rs2html($rs); + $rs->MoveFirst(); + } + + ///////////////////// + // public methods + ///////////////////// + + static function config($driver, $host, $user, $password, $database=false,$options=false) + { + ADODB_Session::driver($driver); + ADODB_Session::host($host); + ADODB_Session::user($user); + ADODB_Session::password($password); + ADODB_Session::database($database); + + if (strncmp($driver, 'oci8', 4) == 0) $options['lob'] = 'CLOB'; + + if (isset($options['table'])) ADODB_Session::table($options['table']); + if (isset($options['lob'])) ADODB_Session::clob($options['lob']); + if (isset($options['debug'])) ADODB_Session::debug($options['debug']); + } + + /*! + Create the connection to the database. + + If $conn already exists, reuse that connection + */ + static function open($save_path, $session_name, $persist = null) + { + $conn = ADODB_Session::_conn(); + + if ($conn) { + return true; + } + + $database = ADODB_Session::database(); + $debug = ADODB_Session::debug(); + $driver = ADODB_Session::driver(); + $host = ADODB_Session::host(); + $password = ADODB_Session::password(); + $user = ADODB_Session::user(); + + if (!is_null($persist)) { + ADODB_Session::persist($persist); + } else { + $persist = ADODB_Session::persist(); + } + +# these can all be defaulted to in php.ini +# assert('$database'); +# assert('$driver'); +# assert('$host'); + if (strpos($driver, 'pdo_') === 0){ + $conn = ADONewConnection('pdo'); + $driver = str_replace('pdo_', '', $driver); + $dsn = $driver.':'.'hostname='.$host.';dbname='.$database.';'; + if ($persist) { + switch($persist) { + default: + case 'P': $ok = $conn->PConnect($dsn,$user,$password); break; + case 'C': $ok = $conn->Connect($dsn,$user,$password); break; + case 'N': $ok = $conn->NConnect($dsn,$user,$password); break; + } + } else { + $ok = $conn->Connect($dsn,$user,$password); + } + }else{ + $conn = ADONewConnection($driver); + if ($debug) { + $conn->debug = true; + ADOConnection::outp( " driver=$driver user=$user db=$database "); + } + + if (empty($conn->_connectionID)) { // not dsn + if ($persist) { + switch($persist) { + default: + case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break; + case 'C': $ok = $conn->Connect($host, $user, $password, $database); break; + case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break; + } + } else { + $ok = $conn->Connect($host, $user, $password, $database); + } + } else { + $ok = true; // $conn->_connectionID is set after call to ADONewConnection + } + } + + + if ($ok) $GLOBALS['ADODB_SESS_CONN'] = $conn; + else + ADOConnection::outp('

Session: connection failed

', false); + + + return $ok; + } + + /*! + Close the connection + */ + static function close() + { +/* + $conn = ADODB_Session::_conn(); + if ($conn) $conn->Close(); +*/ + return true; + } + + /* + Slurp in the session variables and return the serialized string + */ + static function read($key) + { + $conn = ADODB_Session::_conn(); + $filter = ADODB_Session::filter(); + $table = ADODB_Session::table(); + + if (!$conn) { + return ''; + } + + //assert('$table'); + + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + global $ADODB_SESSION_SELECT_FIELDS; + if (!isset($ADODB_SESSION_SELECT_FIELDS)) $ADODB_SESSION_SELECT_FIELDS = 'sessdata'; + $sql = "SELECT $ADODB_SESSION_SELECT_FIELDS FROM $table WHERE sesskey = $binary ".$conn->Param(0)." AND expiry >= " . $conn->sysTimeStamp; + + /* Lock code does not work as it needs to hold transaction within whole page, and we don't know if + developer has committed elsewhere... :( + */ + #if (ADODB_Session::Lock()) + # $rs = $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), sessdata); + #else + $rs = $conn->Execute($sql, array($key)); + //ADODB_Session::_dumprs($rs); + if ($rs) { + if ($rs->EOF) { + $v = ''; + } else { + $v = reset($rs->fields); + $filter = array_reverse($filter); + foreach ($filter as $f) { + if (is_object($f)) { + $v = $f->read($v, ADODB_Session::_sessionKey()); + } + } + $v = rawurldecode($v); + } + + $rs->Close(); + + ADODB_Session::_crc(strlen($v) . crc32($v)); + return $v; + } + + return ''; + } + + /*! + Write the serialized data to a database. + + If the data has not been modified since the last read(), we do not write. + */ + static function write($key, $oval) + { + global $ADODB_SESSION_READONLY; + + if (!empty($ADODB_SESSION_READONLY)) return; + + $clob = ADODB_Session::clob(); + $conn = ADODB_Session::_conn(); + $crc = ADODB_Session::_crc(); + $debug = ADODB_Session::debug(); + $driver = ADODB_Session::driver(); + $expire_notify = ADODB_Session::expireNotify(); + $filter = ADODB_Session::filter(); + $lifetime = ADODB_Session::lifetime(); + $table = ADODB_Session::table(); + + if (!$conn) { + return false; + } + if ($debug) $conn->debug = 1; + $sysTimeStamp = $conn->sysTimeStamp; + + //assert('$table'); + + $expiry = $conn->OffsetDate($lifetime/(24*3600),$sysTimeStamp); + + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + // crc32 optimization since adodb 2.1 + // now we only update expiry date, thx to sebastian thom in adodb 2.32 + if ($crc !== '00' && $crc !== false && $crc == (strlen($oval) . crc32($oval))) { + if ($debug) { + echo '

Session: Only updating date - crc32 not changed

'; + } + + $expirevar = ''; + if ($expire_notify) { + $var = reset($expire_notify); + global $$var; + if (isset($$var)) { + $expirevar = $$var; + } + } + + + $sql = "UPDATE $table SET expiry = $expiry ,expireref=".$conn->Param('0').", modified = $sysTimeStamp WHERE $binary sesskey = ".$conn->Param('1')." AND expiry >= $sysTimeStamp"; + $rs = $conn->Execute($sql,array($expirevar,$key)); + return true; + } + $val = rawurlencode($oval); + foreach ($filter as $f) { + if (is_object($f)) { + $val = $f->write($val, ADODB_Session::_sessionKey()); + } + } + + $expireref = ''; + if ($expire_notify) { + $var = reset($expire_notify); + global $$var; + if (isset($$var)) { + $expireref = $$var; + } + } + + if (!$clob) { // no lobs, simply use replace() + $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key)); + if ($rs) $rs->Close(); + + if ($rs && reset($rs->fields) > 0) { + $sql = "UPDATE $table SET expiry=$expiry, sessdata=".$conn->Param(0).", expireref= ".$conn->Param(1).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param(2); + + } else { + $sql = "INSERT INTO $table (expiry, sessdata, expireref, sesskey, created, modified) + VALUES ($expiry,".$conn->Param('0').", ". $conn->Param('1').", ".$conn->Param('2').", $sysTimeStamp, $sysTimeStamp)"; + } + + + $rs = $conn->Execute($sql,array($val,$expireref,$key)); + + } else { + // what value shall we insert/update for lob row? + if (strncmp($driver, 'oci8', 4) == 0) $lob_value = sprintf('empty_%s()', strtolower($clob)); + else $lob_value = 'null'; + + $conn->StartTrans(); + + $rs = $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = ".$conn->Param(0),array($key)); + + if ($rs && reset($rs->fields) > 0) { + $sql = "UPDATE $table SET expiry=$expiry, sessdata=$lob_value, expireref= ".$conn->Param(0).",modified=$sysTimeStamp WHERE sesskey = ".$conn->Param('1'); + + } else { + $sql = "INSERT INTO $table (expiry, sessdata, expireref, sesskey, created, modified) + VALUES ($expiry,$lob_value, ". $conn->Param('0').", ".$conn->Param('1').", $sysTimeStamp, $sysTimeStamp)"; + } + + $rs = $conn->Execute($sql,array($expireref,$key)); + + $qkey = $conn->qstr($key); + $rs2 = $conn->UpdateBlob($table, 'sessdata', $val, " sesskey=$qkey", strtoupper($clob)); + if ($debug) echo "
",htmlspecialchars($oval), "
"; + $rs = @$conn->CompleteTrans(); + + + } + + if (!$rs) { + ADOConnection::outp('

Session Replace: ' . $conn->ErrorMsg() . '

', false); + return false; + } else { + // bug in access driver (could be odbc?) means that info is not committed + // properly unless select statement executed in Win2000 + if ($conn->databaseType == 'access') { + $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + if ($rs) { + $rs->Close(); + } + } + }/* + if (ADODB_Session::Lock()) { + $conn->CommitTrans(); + }*/ + return $rs ? true : false; + } + + /*! + */ + static function destroy($key) { + $conn = ADODB_Session::_conn(); + $table = ADODB_Session::table(); + $expire_notify = ADODB_Session::expireNotify(); + + if (!$conn) { + return false; + } + $debug = ADODB_Session::debug(); + if ($debug) $conn->debug = 1; + //assert('$table'); + + $qkey = $conn->quote($key); + $binary = $conn->dataProvider === 'mysql' || $conn->dataProvider === 'pdo' ? '/*! BINARY */' : ''; + + if ($expire_notify) { + reset($expire_notify); + $fn = next($expire_notify); + $savem = $conn->SetFetchMode(ADODB_FETCH_NUM); + $sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey"; + $rs = $conn->Execute($sql); + ADODB_Session::_dumprs($rs); + $conn->SetFetchMode($savem); + if (!$rs) { + return false; + } + if (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + //assert('$ref'); + //assert('$key'); + $fn($ref, $key); + } + $rs->Close(); + } + + $sql = "DELETE FROM $table WHERE $binary sesskey = $qkey"; + $rs = $conn->Execute($sql); + if ($rs) { + $rs->Close(); + } + + return $rs ? true : false; + } + + /*! + */ + static function gc($maxlifetime) + { + $conn = ADODB_Session::_conn(); + $debug = ADODB_Session::debug(); + $expire_notify = ADODB_Session::expireNotify(); + $optimize = ADODB_Session::optimize(); + $table = ADODB_Session::table(); + + if (!$conn) { + return false; + } + + + $debug = ADODB_Session::debug(); + if ($debug) { + $conn->debug = 1; + $COMMITNUM = 2; + } else { + $COMMITNUM = 20; + } + + //assert('$table'); + + $time = $conn->OffsetDate(-$maxlifetime/24/3600,$conn->sysTimeStamp); + $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : ''; + + if ($expire_notify) { + reset($expire_notify); + $fn = next($expire_notify); + } else { + $fn = false; + } + + $savem = $conn->SetFetchMode(ADODB_FETCH_NUM); + $sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time ORDER BY 2"; # add order by to prevent deadlock + $rs = $conn->SelectLimit($sql,1000); + if ($debug) ADODB_Session::_dumprs($rs); + $conn->SetFetchMode($savem); + if ($rs) { + $tr = $conn->hasTransactions; + if ($tr) $conn->BeginTrans(); + $keys = array(); + $ccnt = 0; + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + if ($fn) $fn($ref, $key); + $del = $conn->Execute("DELETE FROM $table WHERE sesskey=".$conn->Param('0'),array($key)); + $rs->MoveNext(); + $ccnt += 1; + if ($tr && $ccnt % $COMMITNUM == 0) { + if ($debug) echo "Commit
\n"; + $conn->CommitTrans(); + $conn->BeginTrans(); + } + } + $rs->Close(); + + if ($tr) $conn->CommitTrans(); + } + + + // suggested by Cameron, "GaM3R" + if ($optimize) { + $driver = ADODB_Session::driver(); + + if (preg_match('/mysql/i', $driver)) { + $sql = "OPTIMIZE TABLE $table"; + } + if (preg_match('/postgres/i', $driver)) { + $sql = "VACUUM $table"; + } + if (!empty($sql)) { + $conn->Execute($sql); + } + } + + + return true; + } +} + +ADODB_Session::_init(); +if (empty($ADODB_SESSION_READONLY)) + register_shutdown_function('session_write_close'); + +// for backwards compatibility only +function adodb_sess_open($save_path, $session_name, $persist = true) { + return ADODB_Session::open($save_path, $session_name, $persist); +} + +// for backwards compatibility only +function adodb_sess_gc($t) +{ + return ADODB_Session::gc($t); +} diff --git a/www/include/adodb/session/adodb-sessions.mysql.sql b/www/include/adodb/session/adodb-sessions.mysql.sql new file mode 100644 index 00000000..f90de449 --- /dev/null +++ b/www/include/adodb/session/adodb-sessions.mysql.sql @@ -0,0 +1,16 @@ +-- $CVSHeader$ + +CREATE DATABASE /*! IF NOT EXISTS */ adodb_sessions; + +USE adodb_sessions; + +DROP TABLE /*! IF EXISTS */ sessions; + +CREATE TABLE /*! IF NOT EXISTS */ sessions ( + sesskey CHAR(32) /*! BINARY */ NOT NULL DEFAULT '', + expiry INT(11) /*! UNSIGNED */ NOT NULL DEFAULT 0, + expireref VARCHAR(64) DEFAULT '', + data LONGTEXT DEFAULT '', + PRIMARY KEY (sesskey), + INDEX expiry (expiry) +); diff --git a/www/include/adodb/session/adodb-sessions.oracle.clob.sql b/www/include/adodb/session/adodb-sessions.oracle.clob.sql new file mode 100644 index 00000000..c5c4f2d0 --- /dev/null +++ b/www/include/adodb/session/adodb-sessions.oracle.clob.sql @@ -0,0 +1,15 @@ +-- $CVSHeader$ + +DROP TABLE adodb_sessions; + +CREATE TABLE sessions ( + sesskey CHAR(32) DEFAULT '' NOT NULL, + expiry INT DEFAULT 0 NOT NULL, + expireref VARCHAR(64) DEFAULT '', + data CLOB DEFAULT '', + PRIMARY KEY (sesskey) +); + +CREATE INDEX ix_expiry ON sessions (expiry); + +QUIT; diff --git a/www/include/adodb/session/adodb-sessions.oracle.sql b/www/include/adodb/session/adodb-sessions.oracle.sql new file mode 100644 index 00000000..8fd5a342 --- /dev/null +++ b/www/include/adodb/session/adodb-sessions.oracle.sql @@ -0,0 +1,16 @@ +-- $CVSHeader$ + +DROP TABLE adodb_sessions; + +CREATE TABLE sessions ( + sesskey CHAR(32) DEFAULT '' NOT NULL, + expiry INT DEFAULT 0 NOT NULL, + expireref VARCHAR(64) DEFAULT '', + data VARCHAR(4000) DEFAULT '', + PRIMARY KEY (sesskey), + INDEX expiry (expiry) +); + +CREATE INDEX ix_expiry ON sessions (expiry); + +QUIT; diff --git a/www/include/adodb/session/crypt.inc.php b/www/include/adodb/session/crypt.inc.php new file mode 100644 index 00000000..82121e39 --- /dev/null +++ b/www/include/adodb/session/crypt.inc.php @@ -0,0 +1,172 @@ + + */ + +class MD5Crypt{ + function keyED($txt,$encrypt_key) + { + $encrypt_key = md5($encrypt_key); + $ctr=0; + $tmp = ""; + for ($i=0;$ikeyED($tmp,$key)); + } + + function Decrypt($txt,$key) + { + $txt = $this->keyED(base64_decode($txt),$key); + $tmp = ""; + for ($i=0;$i= 58 && $randnumber <= 64) || ($randnumber >= 91 && $randnumber <= 96)) + { + $randnumber = rand(48,120); + } + + $randomPassword .= chr($randnumber); + } + return $randomPassword; + } + +} + + +class SHA1Crypt{ + function keyED($txt,$encrypt_key) + { + + $encrypt_key = sha1($encrypt_key); + $ctr=0; + $tmp = ""; + + for ($i=0;$ikeyED($tmp,$key)); + + } + + + + function Decrypt($txt,$key) + { + + $txt = $this->keyED(base64_decode($txt),$key); + + $tmp = ""; + + for ($i=0;$i= 58 && $randnumber <= 64) || ($randnumber >= 91 && $randnumber <= 96)) + { + $randnumber = rand(48,120); + } + + $randomPassword .= chr($randnumber); + } + + return $randomPassword; + + } + + + +} diff --git a/www/include/adodb/session/old/adodb-cryptsession.php b/www/include/adodb/session/old/adodb-cryptsession.php new file mode 100644 index 00000000..6616de3d --- /dev/null +++ b/www/include/adodb/session/old/adodb-cryptsession.php @@ -0,0 +1,331 @@ +"; + + + Installation + ============ + 1. Create a new database in MySQL or Access "sessions" like +so: + + create table sessions ( + SESSKEY char(32) not null, + EXPIRY int(11) unsigned not null, + EXPIREREF varchar(64), + DATA CLOB, + primary key (sesskey) + ); + + 2. Then define the following parameters. You can either modify + this file, or define them before this file is included: + + $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase'; + $ADODB_SESSION_CONNECT='server to connect to'; + $ADODB_SESSION_USER ='user'; + $ADODB_SESSION_PWD ='password'; + $ADODB_SESSION_DB ='database'; + $ADODB_SESSION_TBL = 'sessions' + + 3. Recommended is PHP 4.0.2 or later. There are documented +session bugs in earlier versions of PHP. + +*/ + + +include_once('crypt.inc.php'); + +if (!defined('_ADODB_LAYER')) { + include (dirname(__FILE__).'/adodb.inc.php'); +} + + /* if database time and system time is difference is greater than this, then give warning */ + define('ADODB_SESSION_SYNCH_SECS',60); + +if (!defined('ADODB_SESSION')) { + + define('ADODB_SESSION',1); + +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_CONN, + $ADODB_SESS_LIFE, + $ADODB_SESS_DEBUG, + $ADODB_SESS_INSERT, + $ADODB_SESSION_EXPIRE_NOTIFY, + $ADODB_SESSION_TBL; + + //$ADODB_SESS_DEBUG = true; + + /* SET THE FOLLOWING PARAMETERS */ +if (empty($ADODB_SESSION_DRIVER)) { + $ADODB_SESSION_DRIVER='mysql'; + $ADODB_SESSION_CONNECT='localhost'; + $ADODB_SESSION_USER ='root'; + $ADODB_SESSION_PWD =''; + $ADODB_SESSION_DB ='xphplens_2'; +} + +if (empty($ADODB_SESSION_TBL)){ + $ADODB_SESSION_TBL = 'sessions'; +} + +if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) { + $ADODB_SESSION_EXPIRE_NOTIFY = false; +} + +function ADODB_Session_Key() +{ +$ADODB_CRYPT_KEY = 'CRYPTED ADODB SESSIONS ROCK!'; + + /* USE THIS FUNCTION TO CREATE THE ENCRYPTION KEY FOR CRYPTED SESSIONS */ + /* Crypt the used key, $ADODB_CRYPT_KEY as key and session_ID as SALT */ + return crypt($ADODB_CRYPT_KEY, session_ID()); +} + +$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime'); +if ($ADODB_SESS_LIFE <= 1) { + // bug in PHP 4.0.3 pl 1 -- how about other versions? + //print "

Session Error: PHP.INI setting session.gc_maxlifetimenot set: $ADODB_SESS_LIFE

"; + $ADODB_SESS_LIFE=1440; +} + +function adodb_sess_open($save_path, $session_name) +{ +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_CONN, + $ADODB_SESS_DEBUG; + + $ADODB_SESS_INSERT = false; + + if (isset($ADODB_SESS_CONN)) return true; + + $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER); + if (!empty($ADODB_SESS_DEBUG)) { + $ADODB_SESS_CONN->debug = true; + print" conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB "; + } + return $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT, + $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); + +} + +function adodb_sess_close() +{ +global $ADODB_SESS_CONN; + + if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close(); + return true; +} + +function adodb_sess_read($key) +{ +$Crypt = new MD5Crypt; +global $ADODB_SESS_CONN,$ADODB_SESS_INSERT,$ADODB_SESSION_TBL; + $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time()); + if ($rs) { + if ($rs->EOF) { + $ADODB_SESS_INSERT = true; + $v = ''; + } else { + // Decrypt session data + $v = rawurldecode($Crypt->Decrypt(reset($rs->fields), ADODB_Session_Key())); + } + $rs->Close(); + return $v; + } + else $ADODB_SESS_INSERT = true; + + return ''; +} + +function adodb_sess_write($key, $val) +{ +$Crypt = new MD5Crypt; + global $ADODB_SESS_INSERT,$ADODB_SESS_CONN, $ADODB_SESS_LIFE, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; + + $expiry = time() + $ADODB_SESS_LIFE; + + // encrypt session data.. + $val = $Crypt->Encrypt(rawurlencode($val), ADODB_Session_Key()); + + $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val); + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + $var = reset($ADODB_SESSION_EXPIRE_NOTIFY); + global $$var; + $arr['expireref'] = $$var; + } + $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL, + $arr, + 'sesskey',$autoQuote = true); + + if (!$rs) { + ADOConnection::outp( ' +-- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'

',false); + } else { + // bug in access driver (could be odbc?) means that info is not committed + // properly unless select statement executed in Win2000 + + if ($ADODB_SESS_CONN->databaseType == 'access') $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); + } + return isset($rs); +} + +function adodb_sess_destroy($key) +{ + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; + + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + reset($ADODB_SESSION_EXPIRE_NOTIFY); + $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); + $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); + $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $ADODB_SESS_CONN->SetFetchMode($savem); + if ($rs) { + $ADODB_SESS_CONN->BeginTrans(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref,$key); + $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $rs->MoveNext(); + } + $ADODB_SESS_CONN->CommitTrans(); + } + } else { + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; + $rs = $ADODB_SESS_CONN->Execute($qry); + } + return $rs ? true : false; +} + + +function adodb_sess_gc($maxlifetime) { + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY,$ADODB_SESS_DEBUG; + + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + reset($ADODB_SESSION_EXPIRE_NOTIFY); + $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); + $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); + $t = time(); + $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t"); + $ADODB_SESS_CONN->SetFetchMode($savem); + if ($rs) { + $ADODB_SESS_CONN->BeginTrans(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref,$key); + //$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $rs->MoveNext(); + } + $rs->Close(); + + $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t"); + $ADODB_SESS_CONN->CommitTrans(); + } + } else { + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time(); + $ADODB_SESS_CONN->Execute($qry); + } + + // suggested by Cameron, "GaM3R" + if (defined('ADODB_SESSION_OPTIMIZE')) + { + global $ADODB_SESSION_DRIVER; + + switch( $ADODB_SESSION_DRIVER ) { + case 'mysql': + case 'mysqlt': + $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL; + break; + case 'postgresql': + case 'postgresql7': + $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL; + break; + } + } + + if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL; + else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL; + + $rs = $ADODB_SESS_CONN->SelectLimit($sql,1); + if ($rs && !$rs->EOF) { + + $dbts = reset($rs->fields); + $rs->Close(); + $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts); + $t = time(); + if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) { + $msg = + __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)"; + error_log($msg); + if ($ADODB_SESS_DEBUG) ADOConnection::outp(" +-- $msg

"); + } + } + + return true; +} + +session_set_save_handler( + "adodb_sess_open", + "adodb_sess_close", + "adodb_sess_read", + "adodb_sess_write", + "adodb_sess_destroy", + "adodb_sess_gc"); +} + +/* TEST SCRIPT -- UNCOMMENT */ +/* +if (0) { + + session_start(); + session_register('AVAR'); + $_SESSION['AVAR'] += 1; + print " +-- \$_SESSION['AVAR']={$_SESSION['AVAR']}

"; +} +*/ diff --git a/www/include/adodb/session/old/adodb-session-clob.php b/www/include/adodb/session/old/adodb-session-clob.php new file mode 100644 index 00000000..864fdfd7 --- /dev/null +++ b/www/include/adodb/session/old/adodb-session-clob.php @@ -0,0 +1,457 @@ +"; + +To force non-persistent connections, call adodb_session_open first before session_start(): + + include('adodb.inc.php'); + include('adodb-session.php'); + adodb_session_open(false,false,false); + session_start(); + session_register('AVAR'); + $_SESSION['AVAR'] += 1; + print " +-- \$_SESSION['AVAR']={$_SESSION['AVAR']}

"; + + + Installation + ============ + 1. Create this table in your database (syntax might vary depending on your db): + + create table sessions ( + SESSKEY char(32) not null, + EXPIRY int(11) unsigned not null, + EXPIREREF varchar(64), + DATA CLOB, + primary key (sesskey) + ); + + + 2. Then define the following parameters in this file: + $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase'; + $ADODB_SESSION_CONNECT='server to connect to'; + $ADODB_SESSION_USER ='user'; + $ADODB_SESSION_PWD ='password'; + $ADODB_SESSION_DB ='database'; + $ADODB_SESSION_TBL = 'sessions' + $ADODB_SESSION_USE_LOBS = false; (or, if you wanna use CLOBS (= 'CLOB') or ( = 'BLOB') + + 3. Recommended is PHP 4.1.0 or later. There are documented + session bugs in earlier versions of PHP. + + 4. If you want to receive notifications when a session expires, then + you can tag a session with an EXPIREREF, and before the session + record is deleted, we can call a function that will pass the EXPIREREF + as the first parameter, and the session key as the second parameter. + + To do this, define a notification function, say NotifyFn: + + function NotifyFn($expireref, $sesskey) + { + } + + Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY. + This is an array with 2 elements, the first being the name of the variable + you would like to store in the EXPIREREF field, and the 2nd is the + notification function's name. + + In this example, we want to be notified when a user's session + has expired, so we store the user id in the global variable $USERID, + store this value in the EXPIREREF field: + + $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn'); + + Then when the NotifyFn is called, we are passed the $USERID as the first + parameter, eg. NotifyFn($userid, $sesskey). +*/ + +if (!defined('_ADODB_LAYER')) { + include (dirname(__FILE__).'/adodb.inc.php'); +} + +if (!defined('ADODB_SESSION')) { + + define('ADODB_SESSION',1); + + /* if database time and system time is difference is greater than this, then give warning */ + define('ADODB_SESSION_SYNCH_SECS',60); + +/****************************************************************************************\ + Global definitions +\****************************************************************************************/ +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_CONN, + $ADODB_SESS_LIFE, + $ADODB_SESS_DEBUG, + $ADODB_SESSION_EXPIRE_NOTIFY, + $ADODB_SESSION_CRC, + $ADODB_SESSION_USE_LOBS, + $ADODB_SESSION_TBL; + + if (!isset($ADODB_SESSION_USE_LOBS)) $ADODB_SESSION_USE_LOBS = 'CLOB'; + + $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime'); + if ($ADODB_SESS_LIFE <= 1) { + // bug in PHP 4.0.3 pl 1 -- how about other versions? + //print "

Session Error: PHP.INI setting session.gc_maxlifetimenot set: $ADODB_SESS_LIFE

"; + $ADODB_SESS_LIFE=1440; + } + $ADODB_SESSION_CRC = false; + //$ADODB_SESS_DEBUG = true; + + ////////////////////////////////// + /* SET THE FOLLOWING PARAMETERS */ + ////////////////////////////////// + + if (empty($ADODB_SESSION_DRIVER)) { + $ADODB_SESSION_DRIVER='mysql'; + $ADODB_SESSION_CONNECT='localhost'; + $ADODB_SESSION_USER ='root'; + $ADODB_SESSION_PWD =''; + $ADODB_SESSION_DB ='xphplens_2'; + } + + if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) { + $ADODB_SESSION_EXPIRE_NOTIFY = false; + } + // Made table name configurable - by David Johnson djohnson@inpro.net + if (empty($ADODB_SESSION_TBL)){ + $ADODB_SESSION_TBL = 'sessions'; + } + + + // defaulting $ADODB_SESSION_USE_LOBS + if (!isset($ADODB_SESSION_USE_LOBS) || empty($ADODB_SESSION_USE_LOBS)) { + $ADODB_SESSION_USE_LOBS = false; + } + + /* + $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER; + $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT; + $ADODB_SESS['user'] = $ADODB_SESSION_USER; + $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD; + $ADODB_SESS['db'] = $ADODB_SESSION_DB; + $ADODB_SESS['life'] = $ADODB_SESS_LIFE; + $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; + + $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; + $ADODB_SESS['table'] = $ADODB_SESS_TBL; + */ + +/****************************************************************************************\ + Create the connection to the database. + + If $ADODB_SESS_CONN already exists, reuse that connection +\****************************************************************************************/ +function adodb_sess_open($save_path, $session_name,$persist=true) +{ +GLOBAL $ADODB_SESS_CONN; + if (isset($ADODB_SESS_CONN)) return true; + +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_DEBUG; + + // cannot use & below - do not know why... + $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER); + if (!empty($ADODB_SESS_DEBUG)) { + $ADODB_SESS_CONN->debug = true; + ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB "); + } + if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT, + $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); + else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT, + $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); + + if (!$ok) ADOConnection::outp( " +-- Session: connection failed

",false); +} + +/****************************************************************************************\ + Close the connection +\****************************************************************************************/ +function adodb_sess_close() +{ +global $ADODB_SESS_CONN; + + if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close(); + return true; +} + +/****************************************************************************************\ + Slurp in the session variables and return the serialized string +\****************************************************************************************/ +function adodb_sess_read($key) +{ +global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC; + + $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time()); + if ($rs) { + if ($rs->EOF) { + $v = ''; + } else + $v = rawurldecode(reset($rs->fields)); + + $rs->Close(); + + // new optimization adodb 2.1 + $ADODB_SESSION_CRC = strlen($v).crc32($v); + + return $v; + } + + return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com +} + +/****************************************************************************************\ + Write the serialized data to a database. + + If the data has not been modified since adodb_sess_read(), we do not write. +\****************************************************************************************/ +function adodb_sess_write($key, $val) +{ + global + $ADODB_SESS_CONN, + $ADODB_SESS_LIFE, + $ADODB_SESSION_TBL, + $ADODB_SESS_DEBUG, + $ADODB_SESSION_CRC, + $ADODB_SESSION_EXPIRE_NOTIFY, + $ADODB_SESSION_DRIVER, // added + $ADODB_SESSION_USE_LOBS; // added + + $expiry = time() + $ADODB_SESS_LIFE; + + // crc32 optimization since adodb 2.1 + // now we only update expiry date, thx to sebastian thom in adodb 2.32 + if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) { + if ($ADODB_SESS_DEBUG) echo " +-- Session: Only updating date - crc32 not changed

"; + $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time(); + $rs = $ADODB_SESS_CONN->Execute($qry); + return true; + } + $val = rawurlencode($val); + + $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val); + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + $var = reset($ADODB_SESSION_EXPIRE_NOTIFY); + global $$var; + $arr['expireref'] = $$var; + } + + + if ($ADODB_SESSION_USE_LOBS === false) { // no lobs, simply use replace() + $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 'sesskey',$autoQuote = true); + if (!$rs) { + $err = $ADODB_SESS_CONN->ErrorMsg(); + } + } else { + // what value shall we insert/update for lob row? + switch ($ADODB_SESSION_DRIVER) { + // empty_clob or empty_lob for oracle dbs + case "oracle": + case "oci8": + case "oci8po": + case "oci805": + $lob_value = sprintf("empty_%s()", strtolower($ADODB_SESSION_USE_LOBS)); + break; + + // null for all other + default: + $lob_value = "null"; + break; + } + + // do we insert or update? => as for sesskey + $res = $ADODB_SESS_CONN->Execute("select count(*) as cnt from $ADODB_SESSION_TBL where sesskey = '$key'"); + if ($res && reset($res->fields) > 0) { + $qry = sprintf("update %s set expiry = %d, data = %s where sesskey = '%s'", $ADODB_SESSION_TBL, $expiry, $lob_value, $key); + } else { + // insert + $qry = sprintf("insert into %s (sesskey, expiry, data) values ('%s', %d, %s)", $ADODB_SESSION_TBL, $key, $expiry, $lob_value); + } + + $err = ""; + $rs1 = $ADODB_SESS_CONN->Execute($qry); + if (!$rs1) { + $err .= $ADODB_SESS_CONN->ErrorMsg()."\n"; + } + $rs2 = $ADODB_SESS_CONN->UpdateBlob($ADODB_SESSION_TBL, 'data', $val, "sesskey='$key'", strtoupper($ADODB_SESSION_USE_LOBS)); + if (!$rs2) { + $err .= $ADODB_SESS_CONN->ErrorMsg()."\n"; + } + $rs = ($rs1 && $rs2) ? true : false; + } + + if (!$rs) { + ADOConnection::outp( ' +-- Session Replace: '.nl2br($err).'

',false); + } else { + // bug in access driver (could be odbc?) means that info is not committed + // properly unless select statement executed in Win2000 + if ($ADODB_SESS_CONN->databaseType == 'access') + $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); + } + return !empty($rs); +} + +function adodb_sess_destroy($key) +{ + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; + + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + reset($ADODB_SESSION_EXPIRE_NOTIFY); + $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); + $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); + $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $ADODB_SESS_CONN->SetFetchMode($savem); + if ($rs) { + $ADODB_SESS_CONN->BeginTrans(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref,$key); + $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $rs->MoveNext(); + } + $ADODB_SESS_CONN->CommitTrans(); + } + } else { + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; + $rs = $ADODB_SESS_CONN->Execute($qry); + } + return $rs ? true : false; +} + +function adodb_sess_gc($maxlifetime) +{ + global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; + + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + reset($ADODB_SESSION_EXPIRE_NOTIFY); + $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); + $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); + $t = time(); + $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t"); + $ADODB_SESS_CONN->SetFetchMode($savem); + if ($rs) { + $ADODB_SESS_CONN->BeginTrans(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref,$key); + $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $rs->MoveNext(); + } + $rs->Close(); + + //$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t"); + $ADODB_SESS_CONN->CommitTrans(); + + } + } else { + $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time()); + + if ($ADODB_SESS_DEBUG) ADOConnection::outp(" +-- Garbage Collection: $qry

"); + } + // suggested by Cameron, "GaM3R" + if (defined('ADODB_SESSION_OPTIMIZE')) { + global $ADODB_SESSION_DRIVER; + + switch( $ADODB_SESSION_DRIVER ) { + case 'mysql': + case 'mysqlt': + $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL; + break; + case 'postgresql': + case 'postgresql7': + $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL; + break; + } + if (!empty($opt_qry)) { + $ADODB_SESS_CONN->Execute($opt_qry); + } + } + if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL; + else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL; + + $rs = $ADODB_SESS_CONN->SelectLimit($sql,1); + if ($rs && !$rs->EOF) { + + $dbts = reset($rs->fields); + $rs->Close(); + $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts); + $t = time(); + if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) { + $msg = + __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)"; + error_log($msg); + if ($ADODB_SESS_DEBUG) ADOConnection::outp(" +-- $msg

"); + } + } + + return true; +} + +session_set_save_handler( + "adodb_sess_open", + "adodb_sess_close", + "adodb_sess_read", + "adodb_sess_write", + "adodb_sess_destroy", + "adodb_sess_gc"); +} + +/* TEST SCRIPT -- UNCOMMENT */ + +if (0) { + + session_start(); + session_register('AVAR'); + $_SESSION['AVAR'] += 1; + ADOConnection::outp( " +-- \$_SESSION['AVAR']={$_SESSION['AVAR']}

",false); +} diff --git a/www/include/adodb/session/old/adodb-session.php b/www/include/adodb/session/old/adodb-session.php new file mode 100644 index 00000000..5fd43abc --- /dev/null +++ b/www/include/adodb/session/old/adodb-session.php @@ -0,0 +1,449 @@ +"; + +To force non-persistent connections, call adodb_session_open first before session_start(): + + include('adodb.inc.php'); + include('adodb-session.php'); + adodb_sess_open(false,false,false); + session_start(); + session_register('AVAR'); + $_SESSION['AVAR'] += 1; + print " +-- \$_SESSION['AVAR']={$_SESSION['AVAR']}

"; + + + Installation + ============ + 1. Create this table in your database (syntax might vary depending on your db): + + create table sessions ( + SESSKEY char(32) not null, + EXPIRY int(11) unsigned not null, + EXPIREREF varchar(64), + DATA text not null, + primary key (sesskey) + ); + + For oracle: + create table sessions ( + SESSKEY char(32) not null, + EXPIRY DECIMAL(16) not null, + EXPIREREF varchar(64), + DATA varchar(4000) not null, + primary key (sesskey) + ); + + + 2. Then define the following parameters. You can either modify + this file, or define them before this file is included: + + $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase'; + $ADODB_SESSION_CONNECT='server to connect to'; + $ADODB_SESSION_USER ='user'; + $ADODB_SESSION_PWD ='password'; + $ADODB_SESSION_DB ='database'; + $ADODB_SESSION_TBL = 'sessions' + + 3. Recommended is PHP 4.1.0 or later. There are documented + session bugs in earlier versions of PHP. + + 4. If you want to receive notifications when a session expires, then + you can tag a session with an EXPIREREF, and before the session + record is deleted, we can call a function that will pass the EXPIREREF + as the first parameter, and the session key as the second parameter. + + To do this, define a notification function, say NotifyFn: + + function NotifyFn($expireref, $sesskey) + { + } + + Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY. + This is an array with 2 elements, the first being the name of the variable + you would like to store in the EXPIREREF field, and the 2nd is the + notification function's name. + + In this example, we want to be notified when a user's session + has expired, so we store the user id in the global variable $USERID, + store this value in the EXPIREREF field: + + $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn'); + + Then when the NotifyFn is called, we are passed the $USERID as the first + parameter, eg. NotifyFn($userid, $sesskey). +*/ + +if (!defined('_ADODB_LAYER')) { + include (dirname(__FILE__).'/adodb.inc.php'); +} + +if (!defined('ADODB_SESSION')) { + + define('ADODB_SESSION',1); + + /* if database time and system time is difference is greater than this, then give warning */ + define('ADODB_SESSION_SYNCH_SECS',60); + + /* + Thanks Joe Li. See PHPLens Issue No: 11487&x=1 +*/ +function adodb_session_regenerate_id() +{ + $conn = ADODB_Session::_conn(); + if (!$conn) return false; + + $old_id = session_id(); + if (function_exists('session_regenerate_id')) { + session_regenerate_id(); + } else { + session_id(md5(uniqid(rand(), true))); + $ck = session_get_cookie_params(); + setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']); + //@session_start(); + } + $new_id = session_id(); + $ok = $conn->Execute('UPDATE '. ADODB_Session::table(). ' SET sesskey='. $conn->qstr($new_id). ' WHERE sesskey='.$conn->qstr($old_id)); + + /* it is possible that the update statement fails due to a collision */ + if (!$ok) { + session_id($old_id); + if (empty($ck)) $ck = session_get_cookie_params(); + setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']); + return false; + } + + return true; +} + +/****************************************************************************************\ + Global definitions +\****************************************************************************************/ +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_CONN, + $ADODB_SESS_LIFE, + $ADODB_SESS_DEBUG, + $ADODB_SESSION_EXPIRE_NOTIFY, + $ADODB_SESSION_CRC, + $ADODB_SESSION_TBL; + + + $ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime'); + if ($ADODB_SESS_LIFE <= 1) { + // bug in PHP 4.0.3 pl 1 -- how about other versions? + //print "

Session Error: PHP.INI setting session.gc_maxlifetimenot set: $ADODB_SESS_LIFE

"; + $ADODB_SESS_LIFE=1440; + } + $ADODB_SESSION_CRC = false; + //$ADODB_SESS_DEBUG = true; + + ////////////////////////////////// + /* SET THE FOLLOWING PARAMETERS */ + ////////////////////////////////// + + if (empty($ADODB_SESSION_DRIVER)) { + $ADODB_SESSION_DRIVER='mysql'; + $ADODB_SESSION_CONNECT='localhost'; + $ADODB_SESSION_USER ='root'; + $ADODB_SESSION_PWD =''; + $ADODB_SESSION_DB ='xphplens_2'; + } + + if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) { + $ADODB_SESSION_EXPIRE_NOTIFY = false; + } + // Made table name configurable - by David Johnson djohnson@inpro.net + if (empty($ADODB_SESSION_TBL)){ + $ADODB_SESSION_TBL = 'sessions'; + } + + /* + $ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER; + $ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT; + $ADODB_SESS['user'] = $ADODB_SESSION_USER; + $ADODB_SESS['pwd'] = $ADODB_SESSION_PWD; + $ADODB_SESS['db'] = $ADODB_SESSION_DB; + $ADODB_SESS['life'] = $ADODB_SESS_LIFE; + $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; + + $ADODB_SESS['debug'] = $ADODB_SESS_DEBUG; + $ADODB_SESS['table'] = $ADODB_SESS_TBL; + */ + +/****************************************************************************************\ + Create the connection to the database. + + If $ADODB_SESS_CONN already exists, reuse that connection +\****************************************************************************************/ +function adodb_sess_open($save_path, $session_name,$persist=true) +{ +GLOBAL $ADODB_SESS_CONN; + if (isset($ADODB_SESS_CONN)) return true; + +GLOBAL $ADODB_SESSION_CONNECT, + $ADODB_SESSION_DRIVER, + $ADODB_SESSION_USER, + $ADODB_SESSION_PWD, + $ADODB_SESSION_DB, + $ADODB_SESS_DEBUG; + + // cannot use & below - do not know why... + $ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER); + if (!empty($ADODB_SESS_DEBUG)) { + $ADODB_SESS_CONN->debug = true; + ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB "); + } + if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT, + $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); + else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT, + $ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB); + + if (!$ok) ADOConnection::outp( " +-- Session: connection failed

",false); +} + +/****************************************************************************************\ + Close the connection +\****************************************************************************************/ +function adodb_sess_close() +{ +global $ADODB_SESS_CONN; + + if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close(); + return true; +} + +/****************************************************************************************\ + Slurp in the session variables and return the serialized string +\****************************************************************************************/ +function adodb_sess_read($key) +{ +global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC; + + $rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time()); + if ($rs) { + if ($rs->EOF) { + $v = ''; + } else + $v = rawurldecode(reset($rs->fields)); + + $rs->Close(); + + // new optimization adodb 2.1 + $ADODB_SESSION_CRC = strlen($v).crc32($v); + + return $v; + } + + return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com +} + +/****************************************************************************************\ + Write the serialized data to a database. + + If the data has not been modified since adodb_sess_read(), we do not write. +\****************************************************************************************/ +function adodb_sess_write($key, $val) +{ + global + $ADODB_SESS_CONN, + $ADODB_SESS_LIFE, + $ADODB_SESSION_TBL, + $ADODB_SESS_DEBUG, + $ADODB_SESSION_CRC, + $ADODB_SESSION_EXPIRE_NOTIFY; + + $expiry = time() + $ADODB_SESS_LIFE; + + // crc32 optimization since adodb 2.1 + // now we only update expiry date, thx to sebastian thom in adodb 2.32 + if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) { + if ($ADODB_SESS_DEBUG) echo " +-- Session: Only updating date - crc32 not changed

"; + $qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time(); + $rs = $ADODB_SESS_CONN->Execute($qry); + return true; + } + $val = rawurlencode($val); + + $arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val); + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + $var = reset($ADODB_SESSION_EXPIRE_NOTIFY); + global $$var; + $arr['expireref'] = $$var; + } + $rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, + 'sesskey',$autoQuote = true); + + if (!$rs) { + ADOConnection::outp( ' +-- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'

',false); + } else { + // bug in access driver (could be odbc?) means that info is not committed + // properly unless select statement executed in Win2000 + if ($ADODB_SESS_CONN->databaseType == 'access') + $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'"); + } + return !empty($rs); +} + +function adodb_sess_destroy($key) +{ + global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; + + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + reset($ADODB_SESSION_EXPIRE_NOTIFY); + $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); + $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); + $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $ADODB_SESS_CONN->SetFetchMode($savem); + if ($rs) { + $ADODB_SESS_CONN->BeginTrans(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref,$key); + $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $rs->MoveNext(); + } + $ADODB_SESS_CONN->CommitTrans(); + } + } else { + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'"; + $rs = $ADODB_SESS_CONN->Execute($qry); + } + return $rs ? true : false; +} + +function adodb_sess_gc($maxlifetime) +{ + global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY; + + if ($ADODB_SESSION_EXPIRE_NOTIFY) { + reset($ADODB_SESSION_EXPIRE_NOTIFY); + $fn = next($ADODB_SESSION_EXPIRE_NOTIFY); + $savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM); + $t = time(); + $rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t"); + $ADODB_SESS_CONN->SetFetchMode($savem); + if ($rs) { + $ADODB_SESS_CONN->BeginTrans(); + while (!$rs->EOF) { + $ref = $rs->fields[0]; + $key = $rs->fields[1]; + $fn($ref,$key); + $del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'"); + $rs->MoveNext(); + } + $rs->Close(); + + $ADODB_SESS_CONN->CommitTrans(); + + } + } else { + $qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time(); + $ADODB_SESS_CONN->Execute($qry); + + if ($ADODB_SESS_DEBUG) ADOConnection::outp(" +-- Garbage Collection: $qry

"); + } + // suggested by Cameron, "GaM3R" + if (defined('ADODB_SESSION_OPTIMIZE')) { + global $ADODB_SESSION_DRIVER; + + switch( $ADODB_SESSION_DRIVER ) { + case 'mysql': + case 'mysqlt': + $opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL; + break; + case 'postgresql': + case 'postgresql7': + $opt_qry = 'VACUUM '.$ADODB_SESSION_TBL; + break; + } + if (!empty($opt_qry)) { + $ADODB_SESS_CONN->Execute($opt_qry); + } + } + if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL; + else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL; + + $rs = $ADODB_SESS_CONN->SelectLimit($sql,1); + if ($rs && !$rs->EOF) { + + $dbts = reset($rs->fields); + $rs->Close(); + $dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts); + $t = time(); + + if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) { + + $msg = + __FILE__.": Server time for webserver {$_SERVER['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)"; + error_log($msg); + if ($ADODB_SESS_DEBUG) ADOConnection::outp(" +-- $msg

"); + } + } + + return true; +} + +session_set_save_handler( + "adodb_sess_open", + "adodb_sess_close", + "adodb_sess_read", + "adodb_sess_write", + "adodb_sess_destroy", + "adodb_sess_gc"); +} + +/* TEST SCRIPT -- UNCOMMENT */ + +if (0) { + + session_start(); + session_register('AVAR'); + $_SESSION['AVAR'] += 1; + ADOConnection::outp( " +-- \$_SESSION['AVAR']={$_SESSION['AVAR']}

",false); +} diff --git a/www/include/adodb/session/old/crypt.inc.php b/www/include/adodb/session/old/crypt.inc.php new file mode 100644 index 00000000..089e24a0 --- /dev/null +++ b/www/include/adodb/session/old/crypt.inc.php @@ -0,0 +1,83 @@ + + */ + +class MD5Crypt{ + function keyED($txt,$encrypt_key) + { + $encrypt_key = md5($encrypt_key); + $ctr=0; + $tmp = ""; + for ($i=0;$ikeyED($tmp,$key)); + } + + function Decrypt($txt,$key) + { + $txt = $this->keyED(base64_decode($txt),$key); + $tmp = ""; + for ($i=0;$i= 58 && $randnumber <= 64) || ($randnumber >= 91 && $randnumber <= 96)) + { + $randnumber = rand(48,120); + } + + $randomPassword .= chr($randnumber); + } + return $randomPassword; + } + +} diff --git a/www/include/adodb/session/session_schema.xml b/www/include/adodb/session/session_schema.xml new file mode 100644 index 00000000..c1f75316 --- /dev/null +++ b/www/include/adodb/session/session_schema.xml @@ -0,0 +1,26 @@ + + + + table for ADOdb session-management + + + session key + + + + + + + + + + + + + + + + + +
+
diff --git a/www/include/adodb/session/session_schema2.xml b/www/include/adodb/session/session_schema2.xml new file mode 100644 index 00000000..a8a1b229 --- /dev/null +++ b/www/include/adodb/session/session_schema2.xml @@ -0,0 +1,34 @@ + + + + Table for ADOdb session management + + Session key to identify a user's browser session. + + + + + Slightly redundant as it can be dynamically calculated by NOW() and MODIFIED field, + but it enables forcing a fixed timeout for specific sessions. + + + + + New session creation Timestamp. + + + + Timestamp which is usually updated when the user interacts with a site, to extend the expire time. + + + + Usually a User Id or unique username of your application. + The name EXPIREREF is a bit weird, it may be better to call it USERREF? + + + + PHP's serialized session data or encrypted serialized session data. + + +
+
diff --git a/www/include/adodb5/toexport.inc.php b/www/include/adodb/toexport.inc.php similarity index 79% rename from www/include/adodb5/toexport.inc.php rename to www/include/adodb/toexport.inc.php index 94c394b8..66bbf542 100644 --- a/www/include/adodb5/toexport.inc.php +++ b/www/include/adodb/toexport.inc.php @@ -1,14 +1,6 @@ name : 'Field'.($i++); if ($escquote) $v = str_replace($quote,$escquotequote,$v); diff --git a/www/include/adodb5/tohtml.inc.php b/www/include/adodb/tohtml.inc.php similarity index 82% rename from www/include/adodb5/tohtml.inc.php rename to www/include/adodb/tohtml.inc.php index d39ed291..e92c8b44 100644 --- a/www/include/adodb5/tohtml.inc.php +++ b/www/include/adodb/tohtml.inc.php @@ -1,14 +1,29 @@ -*/ +/** + * RecordSet to HTML Table + * + * Convert a recordset to a html table. Multiple tables are generated + * if the number of rows is > $gSQLBlockRows. This is because + * web browsers normally require the whole table to be downloaded + * before it can be rendered, so we break the output into several + * smaller, faster rendering tables. + * + * This file is part of ADOdb, a Database Abstraction Layer library for PHP. + * + * @package ADOdb + * @link https://adodb.org Project's web site and documentation + * @link https://github.com/ADOdb/ADOdb Source code and issue tracker + * + * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause + * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, + * any later version. This means you can use it in proprietary products. + * See the LICENSE.md file distributed with this source code for details. + * @license BSD-3-Clause + * @license LGPL-2.1-or-later + * + * @copyright 2000-2013 John Lim + * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community + */ // specific code for tohtml GLOBAL $gSQLMaxRows,$gSQLBlockRows,$ADODB_ROUND; @@ -17,14 +32,6 @@ $gSQLMaxRows = 1000; // max no of rows to download $gSQLBlockRows=20; // max no of rows per table block -// RecordSet to HTML Table -//------------------------------------------------------------ -// Convert a recordset to a html table. Multiple tables are generated -// if the number of rows is > $gSQLBlockRows. This is because -// web browsers normally require the whole table to be downloaded -// before it can be rendered, so we break the output into several -// smaller faster rendering tables. -// // $rs: the recordset // $ztabhtml: the table tag attributes (optional) // $zheaderarray: contains the replacement strings for the headers (optional) diff --git a/www/include/adodb5/xmlschema.dtd b/www/include/adodb/xmlschema.dtd similarity index 100% rename from www/include/adodb5/xmlschema.dtd rename to www/include/adodb/xmlschema.dtd diff --git a/www/include/adodb5/xmlschema03.dtd b/www/include/adodb/xmlschema03.dtd similarity index 65% rename from www/include/adodb5/xmlschema03.dtd rename to www/include/adodb/xmlschema03.dtd index 97850bc7..351ea44b 100644 --- a/www/include/adodb5/xmlschema03.dtd +++ b/www/include/adodb/xmlschema03.dtd @@ -1,17 +1,22 @@ - - - + - + - + - + @@ -24,20 +29,25 @@ - + - + - - + + - - + + -]> \ No newline at end of file diff --git a/www/include/adodb5/xsl/convert-0.1-0.2.xsl b/www/include/adodb/xsl/convert-0.1-0.2.xsl similarity index 100% rename from www/include/adodb5/xsl/convert-0.1-0.2.xsl rename to www/include/adodb/xsl/convert-0.1-0.2.xsl diff --git a/www/include/adodb5/xsl/convert-0.1-0.3.xsl b/www/include/adodb/xsl/convert-0.1-0.3.xsl similarity index 100% rename from www/include/adodb5/xsl/convert-0.1-0.3.xsl rename to www/include/adodb/xsl/convert-0.1-0.3.xsl diff --git a/www/include/adodb5/xsl/convert-0.2-0.1.xsl b/www/include/adodb/xsl/convert-0.2-0.1.xsl similarity index 100% rename from www/include/adodb5/xsl/convert-0.2-0.1.xsl rename to www/include/adodb/xsl/convert-0.2-0.1.xsl diff --git a/www/include/adodb5/xsl/convert-0.2-0.3.xsl b/www/include/adodb/xsl/convert-0.2-0.3.xsl similarity index 100% rename from www/include/adodb5/xsl/convert-0.2-0.3.xsl rename to www/include/adodb/xsl/convert-0.2-0.3.xsl diff --git a/www/include/adodb5/xsl/remove-0.2.xsl b/www/include/adodb/xsl/remove-0.2.xsl similarity index 100% rename from www/include/adodb5/xsl/remove-0.2.xsl rename to www/include/adodb/xsl/remove-0.2.xsl diff --git a/www/include/adodb5/xsl/remove-0.3.xsl b/www/include/adodb/xsl/remove-0.3.xsl similarity index 100% rename from www/include/adodb5/xsl/remove-0.3.xsl rename to www/include/adodb/xsl/remove-0.3.xsl diff --git a/www/include/adodb5/.mailmap b/www/include/adodb5/.mailmap deleted file mode 100644 index 1f2f7e7f..00000000 --- a/www/include/adodb5/.mailmap +++ /dev/null @@ -1,4 +0,0 @@ -Andreas Fernandez -Mike Benoit MikeB -Mike Benoit mike.benoit - diff --git a/www/include/adodb5/README.md b/www/include/adodb5/README.md deleted file mode 100644 index 958cca56..00000000 --- a/www/include/adodb5/README.md +++ /dev/null @@ -1,109 +0,0 @@ -ADOdb Library for PHP5 -====================== - -[![Join chat on Gitter](https://img.shields.io/gitter/room/form-data/form-data.svg)](https://gitter.im/adodb/adodb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Download ADOdb](https://img.shields.io/sourceforge/dm/adodb.svg)](https://sourceforge.net/projects/adodb/files/latest/download) - -(c) 2000-2013 John Lim (jlim@natsoft.com) -(c) 2014 Damien Regad, Mark Newnham and the ADOdb community - -Released under both [BSD 3-Clause](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md#bsd-3-clause-license) -and [GNU Lesser GPL library 2.1](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md#gnu-lesser-general-public-license) -licenses. -This means you can use it in proprietary products; -see [License](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md) for details. - -Home page: http://adodb.org/ - -> **WARNING: known issue with Associative Fetch Mode in ADOdb v5.19 --- PLEASE UPGRADE TO v5.20 !** -> When fetching data in Associative mode (i.e. when `$ADODB_FETCH_MODE` is -> set to *ADODB_FETCH_ASSOC*), recordsets do not return any data (empty strings) -> when using some database drivers. The problem has been reported on MSSQL, -> Interbase and Foxpro, but possibly affects other drivers as well; all drivers -> derived from the above are also impacted. -> For further details, please refer to [Issue #20](https://github.com/ADOdb/ADOdb/issues/20). - - -Introduction -============ - -PHP's database access functions are not standardized. This creates a -need for a database class library to hide the differences between the -different databases (encapsulate the differences) so we can easily -switch databases. - -The library currently supports MySQL, Interbase, Sybase, PostgreSQL, Oracle, -Microsoft SQL server, Foxpro ODBC, Access ODBC, Informix, DB2, -Sybase SQL Anywhere, generic ODBC and Microsoft's ADO. - -We hope more people will contribute drivers to support other databases. - - -Installation -============ - -Unpack all the files into a directory accessible by your web server. - -To test, try modifying some of the tutorial examples. -Make sure you customize the connection settings correctly. - -You can debug using: - -``` php -debug = true; -$db->Connect($server, $user, $password, $database); -$rs = $db->Execute('select * from some_small_table'); -print "
";
-print_r($rs->GetRows());
-print "
"; -``` - - -Documentation and Examples -========================== - -Refer to the [ADOdb website](http://adodb.org/) for library documentation and examples. The documentation can also be [downloaded for offline viewing](https://sourceforge.net/projects/adodb/files/Documentation/). - -- [Main documentation](http://adodb.org/dokuwiki/doku.php?id=v5:userguide:userguide_index): Query, update and insert records using a portable API. -- [Data dictionary](http://adodb.org/dokuwiki/doku.php?id=v5:dictionary:dictionary_index) describes how to create database tables and indexes in a portable manner. -- [Database performance monitoring](http://adodb.org/dokuwiki/doku.php?id=v5:performance:performance_index) allows you to perform health checks, tune and monitor your database. -- [Database-backed sessions](http://adodb.org/dokuwiki/doku.php?id=v5:session:session_index). - -There is also a [tutorial](http://adodb.org/dokuwiki/doku.php?id=v5:userguide:mysql_tutorial) that contrasts ADOdb code with PHP native MySQL code. - - -Files -===== - -- `adodb.inc.php` is the library's main file. You only need to include this file. -- `adodb-*.inc.php` are the database specific driver code. -- `adodb-session.php` is the PHP4 session handling code. -- `test.php` contains a list of test commands to exercise the class library. -- `testdatabases.inc.php` contains the list of databases to apply the tests on. -- `Benchmark.php` is a simple benchmark to test the throughput of a SELECT -statement for databases described in testdatabases.inc.php. The benchmark -tables are created in test.php. - - -Support -======= - -To discuss with the ADOdb development team and users, connect to our -[Gitter chatroom](https://gitter.im/adodb/adodb) using your Github credentials. - -Please report bugs, issues and feature requests on Github: - -https://github.com/ADOdb/ADOdb/issues - -You may also find legacy issues in - -- the old [ADOdb forums](http://phplens.com/lens/lensforum/topics.php?id=4) on phplens.com -- the [SourceForge tickets section](http://sourceforge.net/p/adodb/_list/tickets) - -However, please note that they are not actively monitored and should -only be used as reference. diff --git a/www/include/adodb5/adodb-iterator.inc.php b/www/include/adodb5/adodb-iterator.inc.php deleted file mode 100644 index cfc067bc..00000000 --- a/www/include/adodb5/adodb-iterator.inc.php +++ /dev/null @@ -1,26 +0,0 @@ -Execute("select * from adoxyz"); - foreach($rs as $k => $v) { - echo $k; print_r($v); echo "
"; - } - - - Iterator code based on http://cvs.php.net/cvs.php/php-src/ext/spl/examples/cachingiterator.inc?login=2 - - - Moved to adodb.inc.php to improve performance. - */ diff --git a/www/include/adodb5/adodb-memcache.lib.inc.php b/www/include/adodb5/adodb-memcache.lib.inc.php deleted file mode 100644 index 42d2be62..00000000 --- a/www/include/adodb5/adodb-memcache.lib.inc.php +++ /dev/null @@ -1,190 +0,0 @@ -memCache = true; /// should we use memCache instead of caching in files -$db->memCacheHost = array($ip1, $ip2, $ip3); -$db->memCachePort = 11211; /// this is default memCache port -$db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) - -$db->Connect(...); -$db->CacheExecute($sql); - - Note the memcache class is shared by all connections, is created during the first call to Connect/PConnect. - - Class instance is stored in $ADODB_CACHE -*/ - - class ADODB_Cache_MemCache { - var $createdir = false; // create caching directory structure? - - //----------------------------- - // memcache specific variables - - var $hosts; // array of hosts - var $port = 11211; - var $compress = false; // memcache compression with zlib - - var $_connected = false; - var $_memcache = false; - - function __construct(&$obj) - { - $this->hosts = $obj->memCacheHost; - $this->port = $obj->memCachePort; - $this->compress = $obj->memCacheCompress; - } - - // implement as lazy connection. The connection only occurs on CacheExecute call - function connect(&$err) - { - if (!function_exists('memcache_pconnect')) { - $err = 'Memcache module PECL extension not found!'; - return false; - } - - $memcache = new MemCache; - - if (!is_array($this->hosts)) $this->hosts = array($this->hosts); - - $failcnt = 0; - foreach($this->hosts as $host) { - if (!@$memcache->addServer($host,$this->port,true)) { - $failcnt += 1; - } - } - if ($failcnt == sizeof($this->hosts)) { - $err = 'Can\'t connect to any memcache server'; - return false; - } - $this->_connected = true; - $this->_memcache = $memcache; - return true; - } - - // returns true or false. true if successful save - function writecache($filename, $contents, $debug, $secs2cache) - { - if (!$this->_connected) { - $err = ''; - if (!$this->connect($err) && $debug) ADOConnection::outp($err); - } - if (!$this->_memcache) return false; - - if (!$this->_memcache->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) { - if ($debug) ADOConnection::outp(" Failed to save data at the memcached server!
\n"); - return false; - } - - return true; - } - - // returns a recordset - function readcache($filename, &$err, $secs2cache, $rsClass) - { - $false = false; - if (!$this->_connected) $this->connect($err); - if (!$this->_memcache) return $false; - - $rs = $this->_memcache->get($filename); - if (!$rs) { - $err = 'Item with such key doesn\'t exists on the memcached server.'; - return $false; - } - - // hack, should actually use _csv2rs - $rs = explode("\n", $rs); - unset($rs[0]); - $rs = join("\n", $rs); - $rs = unserialize($rs); - if (! is_object($rs)) { - $err = 'Unable to unserialize $rs'; - return $false; - } - if ($rs->timeCreated == 0) return $rs; // apparently have been reports that timeCreated was set to 0 somewhere - - $tdiff = intval($rs->timeCreated+$secs2cache - time()); - if ($tdiff <= 2) { - switch($tdiff) { - case 2: - if ((rand() & 15) == 0) { - $err = "Timeout 2"; - return $false; - } - break; - case 1: - if ((rand() & 3) == 0) { - $err = "Timeout 1"; - return $false; - } - break; - default: - $err = "Timeout 0"; - return $false; - } - } - return $rs; - } - - function flushall($debug=false) - { - if (!$this->_connected) { - $err = ''; - if (!$this->connect($err) && $debug) ADOConnection::outp($err); - } - if (!$this->_memcache) return false; - - $del = $this->_memcache->flush(); - - if ($debug) - if (!$del) ADOConnection::outp("flushall: failed!
\n"); - else ADOConnection::outp("flushall: succeeded!
\n"); - - return $del; - } - - function flushcache($filename, $debug=false) - { - if (!$this->_connected) { - $err = ''; - if (!$this->connect($err) && $debug) ADOConnection::outp($err); - } - if (!$this->_memcache) return false; - - $del = $this->_memcache->delete($filename); - - if ($debug) - if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcached server!
\n"); - else ADOConnection::outp("flushcache: $key entry flushed from memcached server!
\n"); - - return $del; - } - - // not used for memcache - function createdir($dir, $hash) - { - return true; - } - } diff --git a/www/include/adodb5/adodb-php4.inc.php b/www/include/adodb5/adodb-php4.inc.php deleted file mode 100644 index 132f25d0..00000000 --- a/www/include/adodb5/adodb-php4.inc.php +++ /dev/null @@ -1,16 +0,0 @@ -connection) ) { - return $name; - } - - $quote = $this->connection->nameQuote; - - // if name is of the form `name`, quote it - if ( preg_match('/^`(.+)`$/', $name, $matches) ) { - return $quote . $matches[1] . $quote; - } - - // if name contains special characters, quote it - if ( !preg_match('/^[' . $this->nameRegex . ']+$/', $name) ) { - return $quote . $name . $quote; - } - - return $quote . $name . $quote; - } - - function CreateDatabase($dbname, $options=false) - { - $options = $this->_Options($options); - $sql = array(); - - $sql[] = "DECLARE EXTERNAL FUNCTION LOWER CSTRING(80) RETURNS CSTRING(80) FREE_IT ENTRY_POINT 'IB_UDF_lower' MODULE_NAME 'ib_udf'"; - - return $sql; - } - - function _DropAutoIncrement($t) - { - if (strpos($t,'.') !== false) { - $tarr = explode('.',$t); - return 'DROP GENERATOR '.$tarr[0].'."gen_'.$tarr[1].'"'; - } - return 'DROP GENERATOR "GEN_'.$t; - } - - - function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) - { - $suffix = ''; - - if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault"; - if ($fnotnull) $suffix .= ' NOT NULL'; - if ($fautoinc) $this->seqField = $fname; - if ($fconstraint) $suffix .= ' '.$fconstraint; - - return $suffix; - } - -/* -CREATE or replace TRIGGER jaddress_insert -before insert on jaddress -for each row -begin -IF ( NEW."seqField" IS NULL OR NEW."seqField" = 0 ) THEN - NEW."seqField" = GEN_ID("GEN_tabname", 1); -end; -*/ - function _Triggers($tabname,$tableoptions) - { - if (!$this->seqField) return array(); - - $tab1 = preg_replace( '/"/', '', $tabname ); - if ($this->schema) { - $t = strpos($tab1,'.'); - if ($t !== false) $tab = substr($tab1,$t+1); - else $tab = $tab1; - $seqField = $this->seqField; - $seqname = $this->schema.'.'.$this->seqPrefix.$tab; - $trigname = $this->schema.'.trig_'.$this->seqPrefix.$tab; - } else { - $seqField = $this->seqField; - $seqname = $this->seqPrefix.$tab1; - $trigname = 'trig_'.$seqname; - } - if (isset($tableoptions['REPLACE'])) - { $sql[] = "DROP GENERATOR \"$seqname\""; - $sql[] = "CREATE GENERATOR \"$seqname\""; - $sql[] = "ALTER TRIGGER \"$trigname\" BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END"; - } - else - { $sql[] = "CREATE GENERATOR \"$seqname\""; - $sql[] = "CREATE TRIGGER \"$trigname\" FOR $tabname BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END"; - } - - $this->seqField = false; - return $sql; - } - -} diff --git a/www/include/adodb5/drivers/adodb-ado_access.inc.php b/www/include/adodb5/drivers/adodb-ado_access.inc.php deleted file mode 100644 index c167ce63..00000000 --- a/www/include/adodb5/drivers/adodb-ado_access.inc.php +++ /dev/null @@ -1,50 +0,0 @@ -= 5) include(ADODB_DIR."/drivers/adodb-ado5.inc.php"); - else include(ADODB_DIR."/drivers/adodb-ado.inc.php"); -} - -class ADODB_ado_access extends ADODB_ado { - var $databaseType = 'ado_access'; - var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE - var $fmtDate = "#Y-m-d#"; - var $fmtTimeStamp = "#Y-m-d h:i:sA#";// note no comma - var $sysDate = "FORMAT(NOW,'yyyy-mm-dd')"; - var $sysTimeStamp = 'NOW'; - var $upperCase = 'ucase'; - - /*function BeginTrans() { return false;} - - function CommitTrans() { return false;} - - function RollbackTrans() { return false;}*/ - -} - - -class ADORecordSet_ado_access extends ADORecordSet_ado { - - var $databaseType = "ado_access"; - - function __construct($id,$mode=false) - { - return parent::__construct($id,$mode); - } -} diff --git a/www/include/adodb5/drivers/adodb-ads.inc.php b/www/include/adodb5/drivers/adodb-ads.inc.php deleted file mode 100644 index d59df663..00000000 --- a/www/include/adodb5/drivers/adodb-ads.inc.php +++ /dev/null @@ -1,784 +0,0 @@ -_haserrorfunctions = ADODB_PHPVER >= 0x4050; - $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200; - } - - // returns true or false - function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) - { - global $php_errormsg; - - if (!function_exists('ads_connect')) return null; - - if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') { - ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter."); - } - if (isset($php_errormsg)) $php_errormsg = ''; - if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword); - else $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword,$this->curmode); - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); - - return $this->_connectionID != false; - } - - // returns true or false - function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) - { - global $php_errormsg; - - if (!function_exists('ads_connect')) return null; - - if (isset($php_errormsg)) $php_errormsg = ''; - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - if ($this->debug && $argDatabasename) { - ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter."); - } - // print "dsn=$argDSN u=$argUsername p=$argPassword
"; flush(); - if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword); - else $this->_connectionID = ads_pconnect($argDSN,$argUsername,$argPassword,$this->curmode); - - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - if ($this->_connectionID && $this->autoRollback) @ads_rollback($this->_connectionID); - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); - - return $this->_connectionID != false; - } - - // returns the Server version and Description - function ServerInfo() - { - - if (!empty($this->host) && ADODB_PHPVER >= 0x4300) { - $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()'); - $res = $this->Execute($stmt); - if(!$res) - print $this->ErrorMsg(); - else{ - $ret["version"]= $res->fields[3]; - $ret["description"]="Advantage Database Server"; - return $ret; - } - } - else { - return ADOConnection::ServerInfo(); - } - } - - - // returns true or false - function CreateSequence($seqname = 'adodbseq', $start = 1) - { - $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE"); - if(!$res){ - print $this->ErrorMsg(); - return false; - } - else - return true; - - } - - // returns true or false - function DropSequence($seqname = 'adodbseq') - { - $res = $this->Execute("DROP TABLE $seqname"); - if(!$res){ - print $this->ErrorMsg(); - return false; - } - else - return true; - } - - - // returns the generated ID or false - // checks if the table already exists, else creates the table and inserts a record into the table - // and gets the ID number of the last inserted record. - function GenID($seqname = 'adodbseq', $start = 1) - { - $go = $this->Execute("select * from $seqname"); - if (!$go){ - $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE"); - if(!res){ - print $this->ErrorMsg(); - return false; - } - } - $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )"); - if(!$res){ - print $this->ErrorMsg(); - return false; - } - else{ - $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota"); - $ret = $gen->fields[0]; - return $ret; - } - - } - - - - - function ErrorMsg() - { - if ($this->_haserrorfunctions) { - if ($this->_errorMsg !== false) return $this->_errorMsg; - if (empty($this->_connectionID)) return @ads_errormsg(); - return @ads_errormsg($this->_connectionID); - } else return ADOConnection::ErrorMsg(); - } - - - function ErrorNo() - { - - if ($this->_haserrorfunctions) { - if ($this->_errorCode !== false) { - // bug in 4.0.6, error number can be corrupted string (should be 6 digits) - return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode; - } - - if (empty($this->_connectionID)) $e = @ads_error(); - else $e = @ads_error($this->_connectionID); - - // bug in 4.0.6, error number can be corrupted string (should be 6 digits) - // so we check and patch - if (strlen($e)<=2) return 0; - return $e; - } else return ADOConnection::ErrorNo(); - } - - - - function BeginTrans() - { - if (!$this->hasTransactions) return false; - if ($this->transOff) return true; - $this->transCnt += 1; - $this->_autocommit = false; - return ads_autocommit($this->_connectionID,false); - } - - function CommitTrans($ok=true) - { - if ($this->transOff) return true; - if (!$ok) return $this->RollbackTrans(); - if ($this->transCnt) $this->transCnt -= 1; - $this->_autocommit = true; - $ret = ads_commit($this->_connectionID); - ads_autocommit($this->_connectionID,true); - return $ret; - } - - function RollbackTrans() - { - if ($this->transOff) return true; - if ($this->transCnt) $this->transCnt -= 1; - $this->_autocommit = true; - $ret = ads_rollback($this->_connectionID); - ads_autocommit($this->_connectionID,true); - return $ret; - } - - - // Returns tables,Views or both on succesfull execution. Returns - // tables by default on succesfull execustion. - function &MetaTables($ttype = false, $showSchema = false, $mask = false) - { - $recordSet1 = $this->Execute("select * from system.tables"); - if(!$recordSet1){ - print $this->ErrorMsg(); - return false; - } - $recordSet2 = $this->Execute("select * from system.views"); - if(!$recordSet2){ - print $this->ErrorMsg(); - return false; - } - $i=0; - while (!$recordSet1->EOF){ - $arr["$i"] = $recordSet1->fields[0]; - $recordSet1->MoveNext(); - $i=$i+1; - } - if($ttype=='FALSE'){ - while (!$recordSet2->EOF){ - $arr["$i"] = $recordSet2->fields[0]; - $recordSet2->MoveNext(); - $i=$i+1; - } - return $arr; - } - elseif($ttype=='VIEWS'){ - while (!$recordSet2->EOF){ - $arrV["$i"] = $recordSet2->fields[0]; - $recordSet2->MoveNext(); - $i=$i+1; - } - return $arrV; - } - else{ - return $arr; - } - - } - - function &MetaPrimaryKeys($table, $owner = false) - { - $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'"); - if(!$recordSet){ - print $this->ErrorMsg(); - return false; - } - $i=0; - while (!$recordSet->EOF){ - $arr["$i"] = $recordSet->fields[0]; - $recordSet->MoveNext(); - $i=$i+1; - } - return $arr; - } - -/* -See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp -/ SQL data type codes / -#define SQL_UNKNOWN_TYPE 0 -#define SQL_CHAR 1 -#define SQL_NUMERIC 2 -#define SQL_DECIMAL 3 -#define SQL_INTEGER 4 -#define SQL_SMALLINT 5 -#define SQL_FLOAT 6 -#define SQL_REAL 7 -#define SQL_DOUBLE 8 -#if (ODBCVER >= 0x0300) -#define SQL_DATETIME 9 -#endif -#define SQL_VARCHAR 12 - - -/ One-parameter shortcuts for date/time data types / -#if (ODBCVER >= 0x0300) -#define SQL_TYPE_DATE 91 -#define SQL_TYPE_TIME 92 -#define SQL_TYPE_TIMESTAMP 93 - -#define SQL_UNICODE (-95) -#define SQL_UNICODE_VARCHAR (-96) -#define SQL_UNICODE_LONGVARCHAR (-97) -*/ - function ODBCTypes($t) - { - switch ((integer)$t) { - case 1: - case 12: - case 0: - case -95: - case -96: - return 'C'; - case -97: - case -1: //text - return 'X'; - case -4: //image - return 'B'; - - case 9: - case 91: - return 'D'; - - case 10: - case 11: - case 92: - case 93: - return 'T'; - - case 4: - case 5: - case -6: - return 'I'; - - case -11: // uniqidentifier - return 'R'; - case -7: //bit - return 'L'; - - default: - return 'N'; - } - } - - function &MetaColumns($table, $normalize = true) - { - global $ADODB_FETCH_MODE; - - $false = false; - if ($this->uCaseTables) $table = strtoupper($table); - $schema = ''; - $this->_findschema($table,$schema); - - $savem = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - - /*if (false) { // after testing, confirmed that the following does not work becoz of a bug - $qid2 = ads_tables($this->_connectionID); - $rs = new ADORecordSet_ads($qid2); - $ADODB_FETCH_MODE = $savem; - if (!$rs) return false; - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; - $rs->_fetch(); - - while (!$rs->EOF) { - if ($table == strtoupper($rs->fields[2])) { - $q = $rs->fields[0]; - $o = $rs->fields[1]; - break; - } - $rs->MoveNext(); - } - $rs->Close(); - - $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%'); - } */ - - switch ($this->databaseType) { - case 'access': - case 'vfp': - $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%'); - break; - - - case 'db2': - $colname = "%"; - $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname); - break; - - default: - $qid = @ads_columns($this->_connectionID,'%','%',strtoupper($table),'%'); - if (empty($qid)) $qid = ads_columns($this->_connectionID); - break; - } - if (empty($qid)) return $false; - - $rs = new ADORecordSet_ads($qid); - $ADODB_FETCH_MODE = $savem; - - if (!$rs) return $false; - $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; - $rs->_fetch(); - - $retarr = array(); - - /* - $rs->fields indices - 0 TABLE_QUALIFIER - 1 TABLE_SCHEM - 2 TABLE_NAME - 3 COLUMN_NAME - 4 DATA_TYPE - 5 TYPE_NAME - 6 PRECISION - 7 LENGTH - 8 SCALE - 9 RADIX - 10 NULLABLE - 11 REMARKS - */ - while (!$rs->EOF) { - // adodb_pr($rs->fields); - if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { - $fld = new ADOFieldObject(); - $fld->name = $rs->fields[3]; - $fld->type = $this->ODBCTypes($rs->fields[4]); - - // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp - // access uses precision to store length for char/varchar - if ($fld->type == 'C' or $fld->type == 'X') { - if ($this->databaseType == 'access') - $fld->max_length = $rs->fields[6]; - else if ($rs->fields[4] <= -95) // UNICODE - $fld->max_length = $rs->fields[7]/2; - else - $fld->max_length = $rs->fields[7]; - } else - $fld->max_length = $rs->fields[7]; - $fld->not_null = !empty($rs->fields[10]); - $fld->scale = $rs->fields[8]; - $retarr[strtoupper($fld->name)] = $fld; - } else if (sizeof($retarr)>0) - break; - $rs->MoveNext(); - } - $rs->Close(); //-- crashes 4.03pl1 -- why? - - if (empty($retarr)) $retarr = false; - return $retarr; - } - - // Returns an array of columns names for a given table - function &MetaColumnNames($table, $numIndexes = false, $useattnum = false) - { - $recordSet = $this->Execute("select name from system.columns where parent='$table'"); - if(!$recordSet){ - print $this->ErrorMsg(); - return false; - } - else{ - $i=0; - while (!$recordSet->EOF){ - $arr["FIELD$i"] = $recordSet->fields[0]; - $recordSet->MoveNext(); - $i=$i+1; - } - return $arr; - } - } - - - function Prepare($sql) - { - if (! $this->_bindInputArray) return $sql; // no binding - $stmt = ads_prepare($this->_connectionID,$sql); - if (!$stmt) { - // we don't know whether odbc driver is parsing prepared stmts, so just return sql - return $sql; - } - return array($sql,$stmt,false); - } - - /* returns queryID or false */ - function _query($sql,$inputarr=false) - { - GLOBAL $php_errormsg; - if (isset($php_errormsg)) $php_errormsg = ''; - $this->_error = ''; - - if ($inputarr) { - if (is_array($sql)) { - $stmtid = $sql[1]; - } else { - $stmtid = ads_prepare($this->_connectionID,$sql); - - if ($stmtid == false) { - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - return false; - } - } - - if (! ads_execute($stmtid,$inputarr)) { - //@ads_free_result($stmtid); - if ($this->_haserrorfunctions) { - $this->_errorMsg = ads_errormsg(); - $this->_errorCode = ads_error(); - } - return false; - } - - } else if (is_array($sql)) { - $stmtid = $sql[1]; - if (!ads_execute($stmtid)) { - //@ads_free_result($stmtid); - if ($this->_haserrorfunctions) { - $this->_errorMsg = ads_errormsg(); - $this->_errorCode = ads_error(); - } - return false; - } - } else - { - - $stmtid = ads_exec($this->_connectionID,$sql); - - } - - $this->_lastAffectedRows = 0; - - if ($stmtid) - { - - if (@ads_num_fields($stmtid) == 0) { - $this->_lastAffectedRows = ads_num_rows($stmtid); - $stmtid = true; - - } else { - - $this->_lastAffectedRows = 0; - ads_binmode($stmtid,$this->binmode); - ads_longreadlen($stmtid,$this->maxblobsize); - - } - - if ($this->_haserrorfunctions) - { - - $this->_errorMsg = ''; - $this->_errorCode = 0; - } - else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - } - else - { - if ($this->_haserrorfunctions) { - $this->_errorMsg = ads_errormsg(); - $this->_errorCode = ads_error(); - } else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - } - - return $stmtid; - - } - - /* - Insert a null into the blob field of the table first. - Then use UpdateBlob to store the blob. - - Usage: - - $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); - $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); - */ - function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') - { - $sql = "UPDATE $table SET $column=? WHERE $where"; - $stmtid = ads_prepare($this->_connectionID,$sql); - if ($stmtid == false){ - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - return false; - } - if (! ads_execute($stmtid,array($val),array(SQL_BINARY) )){ - if ($this->_haserrorfunctions){ - $this->_errorMsg = ads_errormsg(); - $this->_errorCode = ads_error(); - } - return false; - } - return TRUE; - } - - // returns true or false - function _close() - { - $ret = @ads_close($this->_connectionID); - $this->_connectionID = false; - return $ret; - } - - function _affectedrows() - { - return $this->_lastAffectedRows; - } - -} - -/*-------------------------------------------------------------------------------------- - Class Name: Recordset ---------------------------------------------------------------------------------------*/ - -class ADORecordSet_ads extends ADORecordSet { - - var $bind = false; - var $databaseType = "ads"; - var $dataProvider = "ads"; - var $useFetchArray; - var $_has_stupid_odbc_fetch_api_change; - - function __construct($id,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - $this->fetchMode = $mode; - - $this->_queryID = $id; - - // the following is required for mysql odbc driver in 4.3.1 -- why? - $this->EOF = false; - $this->_currentRow = -1; - //parent::__construct($id); - } - - - // returns the field object - function &FetchField($fieldOffset = -1) - { - - $off=$fieldOffset+1; // offsets begin at 1 - - $o= new ADOFieldObject(); - $o->name = @ads_field_name($this->_queryID,$off); - $o->type = @ads_field_type($this->_queryID,$off); - $o->max_length = @ads_field_len($this->_queryID,$off); - if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name); - else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name); - return $o; - } - - /* Use associative array to get fields array */ - function Fields($colname) - { - if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname]; - if (!$this->bind) { - $this->bind = array(); - for ($i=0; $i < $this->_numOfFields; $i++) { - $o = $this->FetchField($i); - $this->bind[strtoupper($o->name)] = $i; - } - } - - return $this->fields[$this->bind[strtoupper($colname)]]; - } - - - function _initrs() - { - global $ADODB_COUNTRECS; - $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1; - $this->_numOfFields = @ads_num_fields($this->_queryID); - // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 - if ($this->_numOfRows == 0) $this->_numOfRows = -1; - //$this->useFetchArray = $this->connection->useFetchArray; - $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200; - } - - function _seek($row) - { - return false; - } - - // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated - function &GetArrayLimit($nrows,$offset=-1) - { - if ($offset <= 0) { - $rs =& $this->GetArray($nrows); - return $rs; - } - $savem = $this->fetchMode; - $this->fetchMode = ADODB_FETCH_NUM; - $this->Move($offset); - $this->fetchMode = $savem; - - if ($this->fetchMode & ADODB_FETCH_ASSOC) { - $this->fields =& $this->GetRowAssoc(); - } - - $results = array(); - $cnt = 0; - while (!$this->EOF && $nrows != $cnt) { - $results[$cnt++] = $this->fields; - $this->MoveNext(); - } - - return $results; - } - - - function MoveNext() - { - if ($this->_numOfRows != 0 && !$this->EOF) { - $this->_currentRow++; - if( $this->_fetch() ) { - return true; - } - } - $this->fields = false; - $this->EOF = true; - return false; - } - - function _fetch() - { - $this->fields = false; - if ($this->_has_stupid_odbc_fetch_api_change) - $rez = @ads_fetch_into($this->_queryID,$this->fields); - else { - $row = 0; - $rez = @ads_fetch_into($this->_queryID,$row,$this->fields); - } - if ($rez) { - if ($this->fetchMode & ADODB_FETCH_ASSOC) { - $this->fields =& $this->GetRowAssoc(); - } - return true; - } - return false; - } - - function _close() - { - return @ads_free_result($this->_queryID); - } - -} diff --git a/www/include/adodb5/drivers/adodb-db2.inc.php b/www/include/adodb5/drivers/adodb-db2.inc.php deleted file mode 100644 index e7b9dbdd..00000000 --- a/www/include/adodb5/drivers/adodb-db2.inc.php +++ /dev/null @@ -1,849 +0,0 @@ -_haserrorfunctions = ADODB_PHPVER >= 0x4050; - } - - // returns true or false - function _connect($argDSN, $argUsername, $argPassword, $argDatabasename) - { - global $php_errormsg; - - if (!function_exists('db2_connect')) { - ADOConnection::outp("Warning: The old ODBC based DB2 driver has been renamed 'odbc_db2'. This ADOdb driver calls PHP's native db2 extension which is not installed."); - return null; - } - // This needs to be set before the connect(). - // Replaces the odbc_binmode() call that was in Execute() - ini_set('ibm_db2.binmode', $this->binmode); - - if ($argDatabasename && empty($argDSN)) { - - if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_connect($argDatabasename,null,null); - else $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword); - } else { - if ($argDatabasename) $schema = $argDatabasename; - if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_connect($argDSN,null,null); - else $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword); - } - if (isset($php_errormsg)) $php_errormsg = ''; - - // For db2_connect(), there is an optional 4th arg. If present, it must be - // an array of valid options. So far, we don't use them. - - $this->_errorMsg = @db2_conn_errormsg(); - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); - - if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema"); - return $this->_connectionID != false; - } - - // returns true or false - function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename) - { - global $php_errormsg; - - if (!function_exists('db2_connect')) return null; - - // This needs to be set before the connect(). - // Replaces the odbc_binmode() call that was in Execute() - ini_set('ibm_db2.binmode', $this->binmode); - - if (isset($php_errormsg)) $php_errormsg = ''; - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - - if ($argDatabasename && empty($argDSN)) { - - if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_pconnect($argDatabasename,null,null); - else $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword); - } else { - if ($argDatabasename) $schema = $argDatabasename; - if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_pconnect($argDSN,null,null); - else $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword); - } - if (isset($php_errormsg)) $php_errormsg = ''; - - $this->_errorMsg = @db2_conn_errormsg(); - if ($this->_connectionID && $this->autoRollback) @db2_rollback($this->_connectionID); - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); - - if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema"); - return $this->_connectionID != false; - } - - // format and return date string in database timestamp format - function DBTimeStamp($ts, $isfld = false) - { - if (empty($ts) && $ts !== 0) return 'null'; - if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); - return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'YYYY-MM-DD HH24:MI:SS')"; - } - - // Format date column in sql string given an input format that understands Y M D - function SQLDate($fmt, $col=false) - { - // use right() and replace() ? - if (!$col) $col = $this->sysDate; - - /* use TO_CHAR() if $fmt is TO_CHAR() allowed fmt */ - if ($fmt== 'Y-m-d H:i:s') - return 'TO_CHAR('.$col.", 'YYYY-MM-DD HH24:MI:SS')"; - - $s = ''; - - $len = strlen($fmt); - for ($i=0; $i < $len; $i++) { - if ($s) $s .= $this->concat_operator; - $ch = $fmt[$i]; - switch($ch) { - case 'Y': - case 'y': - if ($len==1) return "year($col)"; - $s .= "char(year($col))"; - break; - case 'M': - if ($len==1) return "monthname($col)"; - $s .= "substr(monthname($col),1,3)"; - break; - case 'm': - if ($len==1) return "month($col)"; - $s .= "right(digits(month($col)),2)"; - break; - case 'D': - case 'd': - if ($len==1) return "day($col)"; - $s .= "right(digits(day($col)),2)"; - break; - case 'H': - case 'h': - if ($len==1) return "hour($col)"; - if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)"; - else $s .= "''"; - break; - case 'i': - case 'I': - if ($len==1) return "minute($col)"; - if ($col != $this->sysDate) - $s .= "right(digits(minute($col)),2)"; - else $s .= "''"; - break; - case 'S': - case 's': - if ($len==1) return "second($col)"; - if ($col != $this->sysDate) - $s .= "right(digits(second($col)),2)"; - else $s .= "''"; - break; - default: - if ($ch == '\\') { - $i++; - $ch = substr($fmt,$i,1); - } - $s .= $this->qstr($ch); - } - } - return $s; - } - - - function ServerInfo() - { - $row = $this->GetRow("SELECT service_level, fixpack_num FROM TABLE(sysproc.env_get_inst_info()) - as INSTANCEINFO"); - - - if ($row) { - $info['version'] = $row[0].':'.$row[1]; - $info['fixpack'] = $row[1]; - $info['description'] = ''; - } else { - return ADOConnection::ServerInfo(); - } - - return $info; - } - - function CreateSequence($seqname='adodbseq',$start=1) - { - if (empty($this->_genSeqSQL)) return false; - $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$start)); - if (!$ok) return false; - return true; - } - - function DropSequence($seqname = 'adodbseq') - { - if (empty($this->_dropSeqSQL)) return false; - return $this->Execute(sprintf($this->_dropSeqSQL,$seqname)); - } - - function SelectLimit($sql, $nrows = -1, $offset = -1, $inputArr = false, $secs2cache = 0) - { - $nrows = (integer) $nrows; - if ($offset <= 0) { - // could also use " OPTIMIZE FOR $nrows ROWS " - if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY "; - $rs = $this->Execute($sql,$inputArr); - } else { - if ($offset > 0 && $nrows < 0); - else { - $nrows += $offset; - $sql .= " FETCH FIRST $nrows ROWS ONLY "; - } - $rs = ADOConnection::SelectLimit($sql,-1,$offset,$inputArr); - } - - return $rs; - } - - /* - This algorithm is not very efficient, but works even if table locking - is not available. - - Will return false if unable to generate an ID after $MAXLOOPS attempts. - */ - function GenID($seq='adodbseq',$start=1) - { - // if you have to modify the parameter below, your database is overloaded, - // or you need to implement generation of id's yourself! - $num = $this->GetOne("VALUES NEXTVAL FOR $seq"); - return $num; - } - - - function ErrorMsg() - { - if ($this->_haserrorfunctions) { - if ($this->_errorMsg !== false) return $this->_errorMsg; - if (empty($this->_connectionID)) return @db2_conn_errormsg(); - return @db2_conn_errormsg($this->_connectionID); - } else return ADOConnection::ErrorMsg(); - } - - function ErrorNo() - { - - if ($this->_haserrorfunctions) { - if ($this->_errorCode !== false) { - // bug in 4.0.6, error number can be corrupted string (should be 6 digits) - return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode; - } - - if (empty($this->_connectionID)) $e = @db2_conn_error(); - else $e = @db2_conn_error($this->_connectionID); - - // bug in 4.0.6, error number can be corrupted string (should be 6 digits) - // so we check and patch - if (strlen($e)<=2) return 0; - return $e; - } else return ADOConnection::ErrorNo(); - } - - - - function BeginTrans() - { - if (!$this->hasTransactions) return false; - if ($this->transOff) return true; - $this->transCnt += 1; - $this->_autocommit = false; - return db2_autocommit($this->_connectionID,false); - } - - function CommitTrans($ok=true) - { - if ($this->transOff) return true; - if (!$ok) return $this->RollbackTrans(); - if ($this->transCnt) $this->transCnt -= 1; - $this->_autocommit = true; - $ret = db2_commit($this->_connectionID); - db2_autocommit($this->_connectionID,true); - return $ret; - } - - function RollbackTrans() - { - if ($this->transOff) return true; - if ($this->transCnt) $this->transCnt -= 1; - $this->_autocommit = true; - $ret = db2_rollback($this->_connectionID); - db2_autocommit($this->_connectionID,true); - return $ret; - } - - function MetaPrimaryKeys($table, $owner = false) - { - global $ADODB_FETCH_MODE; - - if ($this->uCaseTables) $table = strtoupper($table); - $schema = ''; - $this->_findschema($table,$schema); - - $savem = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - $qid = @db2_primarykeys($this->_connectionID,'',$schema,$table); - - if (!$qid) { - $ADODB_FETCH_MODE = $savem; - return false; - } - $rs = new ADORecordSet_db2($qid); - $ADODB_FETCH_MODE = $savem; - - if (!$rs) return false; - - $arr = $rs->GetArray(); - $rs->Close(); - $arr2 = array(); - for ($i=0; $i < sizeof($arr); $i++) { - if ($arr[$i][3]) $arr2[] = $arr[$i][3]; - } - return $arr2; - } - - function MetaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE ) - { - global $ADODB_FETCH_MODE; - - if ($this->uCaseTables) $table = strtoupper($table); - $schema = ''; - $this->_findschema($table,$schema); - - $savem = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - $qid = @db2_foreign_keys($this->_connectionID,'',$schema,$table); - if (!$qid) { - $ADODB_FETCH_MODE = $savem; - return false; - } - $rs = new ADORecordSet_db2($qid); - - $ADODB_FETCH_MODE = $savem; - /* - $rs->fields indices - 0 PKTABLE_CAT - 1 PKTABLE_SCHEM - 2 PKTABLE_NAME - 3 PKCOLUMN_NAME - 4 FKTABLE_CAT - 5 FKTABLE_SCHEM - 6 FKTABLE_NAME - 7 FKCOLUMN_NAME - */ - if (!$rs) return false; - - $foreign_keys = array(); - while (!$rs->EOF) { - if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { - if (!is_array($foreign_keys[$rs->fields[5].'.'.$rs->fields[6]])) - $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]] = array(); - $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]][$rs->fields[7]] = $rs->fields[3]; - } - $rs->MoveNext(); - } - - $rs->Close(); - return $foreign_key; - } - - - function MetaTables($ttype = false, $schema = false, $mask = false) - { - global $ADODB_FETCH_MODE; - - $savem = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - $qid = db2_tables($this->_connectionID); - - $rs = new ADORecordSet_db2($qid); - - $ADODB_FETCH_MODE = $savem; - if (!$rs) { - $false = false; - return $false; - } - - $arr = $rs->GetArray(); - $rs->Close(); - $arr2 = array(); - - if ($ttype) { - $isview = strncmp($ttype,'V',1) === 0; - } - for ($i=0; $i < sizeof($arr); $i++) { - if (!$arr[$i][2]) continue; - $type = $arr[$i][3]; - $owner = $arr[$i][1]; - $schemaval = ($schema) ? $arr[$i][1].'.' : ''; - if ($ttype) { - if ($isview) { - if (strncmp($type,'V',1) === 0) $arr2[] = $schemaval.$arr[$i][2]; - } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; - } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; - } - return $arr2; - } - -/* -See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2datetime_data_type_changes.asp -/ SQL data type codes / -#define SQL_UNKNOWN_TYPE 0 -#define SQL_CHAR 1 -#define SQL_NUMERIC 2 -#define SQL_DECIMAL 3 -#define SQL_INTEGER 4 -#define SQL_SMALLINT 5 -#define SQL_FLOAT 6 -#define SQL_REAL 7 -#define SQL_DOUBLE 8 -#if (DB2VER >= 0x0300) -#define SQL_DATETIME 9 -#endif -#define SQL_VARCHAR 12 - - -/ One-parameter shortcuts for date/time data types / -#if (DB2VER >= 0x0300) -#define SQL_TYPE_DATE 91 -#define SQL_TYPE_TIME 92 -#define SQL_TYPE_TIMESTAMP 93 - -#define SQL_UNICODE (-95) -#define SQL_UNICODE_VARCHAR (-96) -#define SQL_UNICODE_LONGVARCHAR (-97) -*/ - function DB2Types($t) - { - switch ((integer)$t) { - case 1: - case 12: - case 0: - case -95: - case -96: - return 'C'; - case -97: - case -1: //text - return 'X'; - case -4: //image - return 'B'; - - case 9: - case 91: - return 'D'; - - case 10: - case 11: - case 92: - case 93: - return 'T'; - - case 4: - case 5: - case -6: - return 'I'; - - case -11: // uniqidentifier - return 'R'; - case -7: //bit - return 'L'; - - default: - return 'N'; - } - } - - function MetaColumns($table, $normalize=true) - { - global $ADODB_FETCH_MODE; - - $false = false; - if ($this->uCaseTables) $table = strtoupper($table); - $schema = ''; - $this->_findschema($table,$schema); - - $savem = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - - $colname = "%"; - $qid = db2_columns($this->_connectionID, "", $schema, $table, $colname); - if (empty($qid)) return $false; - - $rs = new ADORecordSet_db2($qid); - $ADODB_FETCH_MODE = $savem; - - if (!$rs) return $false; - $rs->_fetch(); - - $retarr = array(); - - /* - $rs->fields indices - 0 TABLE_QUALIFIER - 1 TABLE_SCHEM - 2 TABLE_NAME - 3 COLUMN_NAME - 4 DATA_TYPE - 5 TYPE_NAME - 6 PRECISION - 7 LENGTH - 8 SCALE - 9 RADIX - 10 NULLABLE - 11 REMARKS - */ - while (!$rs->EOF) { - if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { - $fld = new ADOFieldObject(); - $fld->name = $rs->fields[3]; - $fld->type = $this->DB2Types($rs->fields[4]); - - // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp - // access uses precision to store length for char/varchar - if ($fld->type == 'C' or $fld->type == 'X') { - if ($rs->fields[4] <= -95) // UNICODE - $fld->max_length = $rs->fields[7]/2; - else - $fld->max_length = $rs->fields[7]; - } else - $fld->max_length = $rs->fields[7]; - $fld->not_null = !empty($rs->fields[10]); - $fld->scale = $rs->fields[8]; - $fld->primary_key = false; - $retarr[strtoupper($fld->name)] = $fld; - } else if (sizeof($retarr)>0) - break; - $rs->MoveNext(); - } - $rs->Close(); - if (empty($retarr)) $retarr = false; - - $qid = db2_primary_keys($this->_connectionID, "", $schema, $table); - if (empty($qid)) return $false; - - $rs = new ADORecordSet_db2($qid); - $ADODB_FETCH_MODE = $savem; - - if (!$rs) return $retarr; - $rs->_fetch(); - - /* - $rs->fields indices - 0 TABLE_CAT - 1 TABLE_SCHEM - 2 TABLE_NAME - 3 COLUMN_NAME - 4 KEY_SEQ - 5 PK_NAME - */ - while (!$rs->EOF) { - if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { - $retarr[strtoupper($rs->fields[3])]->primary_key = true; - } else if (sizeof($retarr)>0) - break; - $rs->MoveNext(); - } - $rs->Close(); - - if (empty($retarr)) $retarr = false; - return $retarr; - } - - - function Prepare($sql) - { - if (! $this->_bindInputArray) return $sql; // no binding - $stmt = db2_prepare($this->_connectionID,$sql); - if (!$stmt) { - // we don't know whether db2 driver is parsing prepared stmts, so just return sql - return $sql; - } - return array($sql,$stmt,false); - } - - /* returns queryID or false */ - function _query($sql,$inputarr=false) - { - GLOBAL $php_errormsg; - if (isset($php_errormsg)) $php_errormsg = ''; - $this->_error = ''; - - if ($inputarr) { - if (is_array($sql)) { - $stmtid = $sql[1]; - } else { - $stmtid = db2_prepare($this->_connectionID,$sql); - - if ($stmtid == false) { - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - return false; - } - } - - if (! db2_execute($stmtid,$inputarr)) { - if ($this->_haserrorfunctions) { - $this->_errorMsg = db2_stmt_errormsg(); - $this->_errorCode = db2_stmt_error(); - } - return false; - } - - } else if (is_array($sql)) { - $stmtid = $sql[1]; - if (!db2_execute($stmtid)) { - if ($this->_haserrorfunctions) { - $this->_errorMsg = db2_stmt_errormsg(); - $this->_errorCode = db2_stmt_error(); - } - return false; - } - } else - $stmtid = @db2_exec($this->_connectionID,$sql); - - $this->_lastAffectedRows = 0; - if ($stmtid) { - if (@db2_num_fields($stmtid) == 0) { - $this->_lastAffectedRows = db2_num_rows($stmtid); - $stmtid = true; - } else { - $this->_lastAffectedRows = 0; - } - - if ($this->_haserrorfunctions) { - $this->_errorMsg = ''; - $this->_errorCode = 0; - } else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - } else { - if ($this->_haserrorfunctions) { - $this->_errorMsg = db2_stmt_errormsg(); - $this->_errorCode = db2_stmt_error(); - } else - $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - - } - return $stmtid; - } - - /* - Insert a null into the blob field of the table first. - Then use UpdateBlob to store the blob. - - Usage: - - $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); - $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); - */ - function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') - { - return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false; - } - - // returns true or false - function _close() - { - $ret = @db2_close($this->_connectionID); - $this->_connectionID = false; - return $ret; - } - - function _affectedrows() - { - return $this->_lastAffectedRows; - } - -} - -/*-------------------------------------------------------------------------------------- - Class Name: Recordset ---------------------------------------------------------------------------------------*/ - -class ADORecordSet_db2 extends ADORecordSet { - - var $bind = false; - var $databaseType = "db2"; - var $dataProvider = "db2"; - var $useFetchArray; - - function __construct($id,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - $this->fetchMode = $mode; - - $this->_queryID = $id; - } - - - // returns the field object - function FetchField($offset = -1) - { - $o= new ADOFieldObject(); - $o->name = @db2_field_name($this->_queryID,$offset); - $o->type = @db2_field_type($this->_queryID,$offset); - $o->max_length = db2_field_width($this->_queryID,$offset); - if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name); - else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name); - return $o; - } - - /* Use associative array to get fields array */ - function Fields($colname) - { - if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname]; - if (!$this->bind) { - $this->bind = array(); - for ($i=0; $i < $this->_numOfFields; $i++) { - $o = $this->FetchField($i); - $this->bind[strtoupper($o->name)] = $i; - } - } - - return $this->fields[$this->bind[strtoupper($colname)]]; - } - - - function _initrs() - { - global $ADODB_COUNTRECS; - $this->_numOfRows = ($ADODB_COUNTRECS) ? @db2_num_rows($this->_queryID) : -1; - $this->_numOfFields = @db2_num_fields($this->_queryID); - // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 - if ($this->_numOfRows == 0) $this->_numOfRows = -1; - } - - function _seek($row) - { - return false; - } - - // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated - function GetArrayLimit($nrows,$offset=-1) - { - if ($offset <= 0) { - $rs = $this->GetArray($nrows); - return $rs; - } - $savem = $this->fetchMode; - $this->fetchMode = ADODB_FETCH_NUM; - $this->Move($offset); - $this->fetchMode = $savem; - - if ($this->fetchMode & ADODB_FETCH_ASSOC) { - $this->fields = $this->GetRowAssoc(); - } - - $results = array(); - $cnt = 0; - while (!$this->EOF && $nrows != $cnt) { - $results[$cnt++] = $this->fields; - $this->MoveNext(); - } - - return $results; - } - - - function MoveNext() - { - if ($this->_numOfRows != 0 && !$this->EOF) { - $this->_currentRow++; - - $this->fields = @db2_fetch_array($this->_queryID); - if ($this->fields) { - if ($this->fetchMode & ADODB_FETCH_ASSOC) { - $this->fields = $this->GetRowAssoc(); - } - return true; - } - } - $this->fields = false; - $this->EOF = true; - return false; - } - - function _fetch() - { - - $this->fields = db2_fetch_array($this->_queryID); - if ($this->fields) { - if ($this->fetchMode & ADODB_FETCH_ASSOC) { - $this->fields = $this->GetRowAssoc(); - } - return true; - } - $this->fields = false; - return false; - } - - function _close() - { - return @db2_free_result($this->_queryID); - } - -} diff --git a/www/include/adodb5/drivers/adodb-firebird.inc.php b/www/include/adodb5/drivers/adodb-firebird.inc.php deleted file mode 100644 index 415f66f2..00000000 --- a/www/include/adodb5/drivers/adodb-firebird.inc.php +++ /dev/null @@ -1,73 +0,0 @@ -dialect; - switch($arr['dialect']) { - case '': - case '1': $s = 'Firebird Dialect 1'; break; - case '2': $s = 'Firebird Dialect 2'; break; - default: - case '3': $s = 'Firebird Dialect 3'; break; - } - $arr['version'] = ADOConnection::_findvers($s); - $arr['description'] = $s; - return $arr; - } - - // Note that Interbase 6.5 uses this ROWS instead - don't you love forking wars! - // SELECT col1, col2 FROM table ROWS 5 -- get 5 rows - // SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2 - function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs=0) - { - $nrows = (integer) $nrows; - $offset = (integer) $offset; - $str = 'SELECT '; - if ($nrows >= 0) $str .= "FIRST $nrows "; - $str .=($offset>=0) ? "SKIP $offset " : ''; - - $sql = preg_replace('/^[ \t]*select/i',$str,$sql); - if ($secs) - $rs = $this->CacheExecute($secs,$sql,$inputarr); - else - $rs = $this->Execute($sql,$inputarr); - - return $rs; - } - - -}; - - -class ADORecordSet_firebird extends ADORecordSet_ibase { - - var $databaseType = "firebird"; - - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } -} diff --git a/www/include/adodb5/drivers/adodb-informix.inc.php b/www/include/adodb5/drivers/adodb-informix.inc.php deleted file mode 100644 index 801451ea..00000000 --- a/www/include/adodb5/drivers/adodb-informix.inc.php +++ /dev/null @@ -1,41 +0,0 @@ -_has_mssql_init) { - ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0"); - return $sql; - } - if (is_string($sql)) $sql = str_replace('||','+',$sql); - $stmt = mssql_init($sql,$this->_connectionID); - if (!$stmt) return $sql; - return array($sql,$stmt); - } - - function _query($sql,$inputarr=false) - { - if (is_string($sql)) $sql = str_replace('||','+',$sql); - return ADODB_mssql::_query($sql,$inputarr); - } -} - -class ADORecordset_mssqlpo extends ADORecordset_mssql { - var $databaseType = "mssqlpo"; - function __construct($id,$mode=false) - { - parent::__construct($id,$mode); - } -} diff --git a/www/include/adodb5/drivers/adodb-mysql.inc.php b/www/include/adodb5/drivers/adodb-mysql.inc.php deleted file mode 100644 index 2d999c6b..00000000 --- a/www/include/adodb5/drivers/adodb-mysql.inc.php +++ /dev/null @@ -1,891 +0,0 @@ -rsPrefix .= 'ext_'; - } - - - // SetCharSet - switch the client encoding - function SetCharSet($charset_name) - { - if (!function_exists('mysql_set_charset')) { - return false; - } - - if ($this->charSet !== $charset_name) { - $ok = @mysql_set_charset($charset_name,$this->_connectionID); - if ($ok) { - $this->charSet = $charset_name; - return true; - } - return false; - } - return true; - } - - function ServerInfo() - { - $arr['description'] = ADOConnection::GetOne("select version()"); - $arr['version'] = ADOConnection::_findvers($arr['description']); - return $arr; - } - - function IfNull( $field, $ifNull ) - { - return " IFNULL($field, $ifNull) "; // if MySQL - } - - function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null) - { - // save old fetch mode - global $ADODB_FETCH_MODE; - - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } - - $procedures = array (); - - // get index details - - $likepattern = ''; - if ($NamePattern) { - $likepattern = " LIKE '".$NamePattern."'"; - } - $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern); - if (is_object($rs)) { - - // parse index data into array - while ($row = $rs->FetchRow()) { - $procedures[$row[1]] = array( - 'type' => 'PROCEDURE', - 'catalog' => '', - 'schema' => '', - 'remarks' => $row[7], - ); - } - } - - $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern); - if (is_object($rs)) { - // parse index data into array - while ($row = $rs->FetchRow()) { - $procedures[$row[1]] = array( - 'type' => 'FUNCTION', - 'catalog' => '', - 'schema' => '', - 'remarks' => $row[7] - ); - } - } - - // restore fetchmode - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; - - return $procedures; - } - - /** - * Retrieves a list of tables based on given criteria - * - * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default) - * @param string $showSchema schema name, false = current schema (default) - * @param string $mask filters the table by name - * - * @return array list of tables - */ - function MetaTables($ttype=false,$showSchema=false,$mask=false) - { - $save = $this->metaTablesSQL; - if ($showSchema && is_string($showSchema)) { - $this->metaTablesSQL .= $this->qstr($showSchema); - } else { - $this->metaTablesSQL .= "schema()"; - } - - if ($mask) { - $mask = $this->qstr($mask); - $this->metaTablesSQL .= " AND table_name LIKE $mask"; - } - $ret = ADOConnection::MetaTables($ttype,$showSchema); - - $this->metaTablesSQL = $save; - return $ret; - } - - - function MetaIndexes ($table, $primary = FALSE, $owner=false) - { - // save old fetch mode - global $ADODB_FETCH_MODE; - - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } - - // get index details - $rs = $this->Execute(sprintf('SHOW INDEX FROM %s',$table)); - - // restore fetchmode - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; - - if (!is_object($rs)) { - return $false; - } - - $indexes = array (); - - // parse index data into array - while ($row = $rs->FetchRow()) { - if ($primary == FALSE AND $row[2] == 'PRIMARY') { - continue; - } - - if (!isset($indexes[$row[2]])) { - $indexes[$row[2]] = array( - 'unique' => ($row[1] == 0), - 'columns' => array() - ); - } - - $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4]; - } - - // sort columns by order in the index - foreach ( array_keys ($indexes) as $index ) - { - ksort ($indexes[$index]['columns']); - } - - return $indexes; - } - - - // if magic quotes disabled, use mysql_real_escape_string() - function qstr($s,$magic_quotes=false) - { - if (is_null($s)) return 'NULL'; - if (!$magic_quotes) { - - if (ADODB_PHPVER >= 0x4300) { - if (is_resource($this->_connectionID)) - return "'".mysql_real_escape_string($s,$this->_connectionID)."'"; - } - if ($this->replaceQuote[0] == '\\'){ - $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); - } - return "'".str_replace("'",$this->replaceQuote,$s)."'"; - } - - // undo magic quotes for " - $s = str_replace('\\"','"',$s); - return "'$s'"; - } - - function _insertid() - { - return ADOConnection::GetOne('SELECT LAST_INSERT_ID()'); - //return mysql_insert_id($this->_connectionID); - } - - function GetOne($sql,$inputarr=false) - { - global $ADODB_GETONE_EOF; - if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) { - $rs = $this->SelectLimit($sql,1,-1,$inputarr); - if ($rs) { - $rs->Close(); - if ($rs->EOF) return $ADODB_GETONE_EOF; - return reset($rs->fields); - } - } else { - return ADOConnection::GetOne($sql,$inputarr); - } - return false; - } - - function BeginTrans() - { - if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver"); - } - - function _affectedrows() - { - return mysql_affected_rows($this->_connectionID); - } - - // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html - // Reference on Last_Insert_ID on the recommended way to simulate sequences - var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);"; - var $_genSeqSQL = "create table if not exists %s (id int not null)"; - var $_genSeqCountSQL = "select count(*) from %s"; - var $_genSeq2SQL = "insert into %s values (%s)"; - var $_dropSeqSQL = "drop table if exists %s"; - - function CreateSequence($seqname='adodbseq',$startID=1) - { - if (empty($this->_genSeqSQL)) return false; - $u = strtoupper($seqname); - - $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); - if (!$ok) return false; - return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); - } - - - function GenID($seqname='adodbseq',$startID=1) - { - // post-nuke sets hasGenID to false - if (!$this->hasGenID) return false; - - $savelog = $this->_logsql; - $this->_logsql = false; - $getnext = sprintf($this->_genIDSQL,$seqname); - $holdtransOK = $this->_transOK; // save the current status - $rs = @$this->Execute($getnext); - if (!$rs) { - if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset - $u = strtoupper($seqname); - $this->Execute(sprintf($this->_genSeqSQL,$seqname)); - $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname)); - if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); - $rs = $this->Execute($getnext); - } - - if ($rs) { - $this->genID = mysql_insert_id($this->_connectionID); - $rs->Close(); - } else - $this->genID = 0; - - $this->_logsql = $savelog; - return $this->genID; - } - - function MetaDatabases() - { - $qid = mysql_list_dbs($this->_connectionID); - $arr = array(); - $i = 0; - $max = mysql_num_rows($qid); - while ($i < $max) { - $db = mysql_tablename($qid,$i); - if ($db != 'mysql') $arr[] = $db; - $i += 1; - } - return $arr; - } - - - // Format date column in sql string given an input format that understands Y M D - function SQLDate($fmt, $col=false) - { - if (!$col) $col = $this->sysTimeStamp; - $s = 'DATE_FORMAT('.$col.",'"; - $concat = false; - $len = strlen($fmt); - for ($i=0; $i < $len; $i++) { - $ch = $fmt[$i]; - switch($ch) { - - default: - if ($ch == '\\') { - $i++; - $ch = substr($fmt,$i,1); - } - /** FALL THROUGH */ - case '-': - case '/': - $s .= $ch; - break; - - case 'Y': - case 'y': - $s .= '%Y'; - break; - case 'M': - $s .= '%b'; - break; - - case 'm': - $s .= '%m'; - break; - case 'D': - case 'd': - $s .= '%d'; - break; - - case 'Q': - case 'q': - $s .= "'),Quarter($col)"; - - if ($len > $i+1) $s .= ",DATE_FORMAT($col,'"; - else $s .= ",('"; - $concat = true; - break; - - case 'H': - $s .= '%H'; - break; - - case 'h': - $s .= '%I'; - break; - - case 'i': - $s .= '%i'; - break; - - case 's': - $s .= '%s'; - break; - - case 'a': - case 'A': - $s .= '%p'; - break; - - case 'w': - $s .= '%w'; - break; - - case 'W': - $s .= '%U'; - break; - - case 'l': - $s .= '%W'; - break; - } - } - $s.="')"; - if ($concat) $s = "CONCAT($s)"; - return $s; - } - - - // returns concatenated string - // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator - function Concat() - { - $s = ""; - $arr = func_get_args(); - - // suggestion by andrew005@mnogo.ru - $s = implode(',',$arr); - if (strlen($s) > 0) return "CONCAT($s)"; - else return ''; - } - - function OffsetDate($dayFraction,$date=false) - { - if (!$date) $date = $this->sysDate; - - $fraction = $dayFraction * 24 * 3600; - return '('. $date . ' + INTERVAL ' . $fraction.' SECOND)'; - -// return "from_unixtime(unix_timestamp($date)+$fraction)"; - } - - // returns true or false - function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - if (!empty($this->port)) $argHostname .= ":".$this->port; - - if (ADODB_PHPVER >= 0x4300) - $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword, - $this->forceNewConnect,$this->clientFlags); - else if (ADODB_PHPVER >= 0x4200) - $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword, - $this->forceNewConnect); - else - $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword); - - if ($this->_connectionID === false) return false; - if ($argDatabasename) return $this->SelectDB($argDatabasename); - return true; - } - - // returns true or false - function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - if (!empty($this->port)) $argHostname .= ":".$this->port; - - if (ADODB_PHPVER >= 0x4300) - $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags); - else - $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword); - if ($this->_connectionID === false) return false; - if ($this->autoRollback) $this->RollbackTrans(); - if ($argDatabasename) return $this->SelectDB($argDatabasename); - return true; - } - - function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - $this->forceNewConnect = true; - return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); - } - - function MetaColumns($table, $normalize=true) - { - $this->_findschema($table,$schema); - if ($schema) { - $dbName = $this->database; - $this->SelectDB($schema); - } - global $ADODB_FETCH_MODE; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - - if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); - $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); - - if ($schema) { - $this->SelectDB($dbName); - } - - if (isset($savem)) $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - if (!is_object($rs)) { - $false = false; - return $false; - } - - $retarr = array(); - while (!$rs->EOF){ - $fld = new ADOFieldObject(); - $fld->name = $rs->fields[0]; - $type = $rs->fields[1]; - - // split type into type(length): - $fld->scale = null; - if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) { - $fld->type = $query_array[1]; - $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; - $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1; - } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) { - $fld->type = $query_array[1]; - $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; - } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) { - $fld->type = $query_array[1]; - $arr = explode(",",$query_array[2]); - $fld->enums = $arr; - $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6 - $fld->max_length = ($zlen > 0) ? $zlen : 1; - } else { - $fld->type = $type; - $fld->max_length = -1; - } - $fld->not_null = ($rs->fields[2] != 'YES'); - $fld->primary_key = ($rs->fields[3] == 'PRI'); - $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false); - $fld->binary = (strpos($type,'blob') !== false || strpos($type,'binary') !== false); - $fld->unsigned = (strpos($type,'unsigned') !== false); - $fld->zerofill = (strpos($type,'zerofill') !== false); - - if (!$fld->binary) { - $d = $rs->fields[4]; - if ($d != '' && $d != 'NULL') { - $fld->has_default = true; - $fld->default_value = $d; - } else { - $fld->has_default = false; - } - } - - if ($save == ADODB_FETCH_NUM) { - $retarr[] = $fld; - } else { - $retarr[strtoupper($fld->name)] = $fld; - } - $rs->MoveNext(); - } - - $rs->Close(); - return $retarr; - } - - // returns true or false - function SelectDB($dbName) - { - $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions - if ($this->_connectionID) { - return @mysql_select_db($dbName,$this->_connectionID); - } - else return false; - } - - // parameters use PostgreSQL convention, not MySQL - function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0) - { - $offsetStr =($offset>=0) ? ((integer)$offset)."," : ''; - // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220 - if ($nrows < 0) $nrows = '18446744073709551615'; - - if ($secs) - $rs = $this->CacheExecute($secs,$sql." LIMIT $offsetStr".((integer)$nrows),$inputarr); - else - $rs = $this->Execute($sql." LIMIT $offsetStr".((integer)$nrows),$inputarr); - return $rs; - } - - // returns queryID or false - function _query($sql,$inputarr=false) - { - - return mysql_query($sql,$this->_connectionID); - /* - global $ADODB_COUNTRECS; - if($ADODB_COUNTRECS) - return mysql_query($sql,$this->_connectionID); - else - return @mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6 - */ - } - - /* Returns: the last error message from previous database operation */ - function ErrorMsg() - { - - if ($this->_logsql) return $this->_errorMsg; - if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error(); - else $this->_errorMsg = @mysql_error($this->_connectionID); - return $this->_errorMsg; - } - - /* Returns: the last error number from previous database operation */ - function ErrorNo() - { - if ($this->_logsql) return $this->_errorCode; - if (empty($this->_connectionID)) return @mysql_errno(); - else return @mysql_errno($this->_connectionID); - } - - // returns true or false - function _close() - { - @mysql_close($this->_connectionID); - - $this->charSet = ''; - $this->_connectionID = false; - } - - - /* - * Maximum size of C field - */ - function CharMax() - { - return 255; - } - - /* - * Maximum size of X field - */ - function TextMax() - { - return 4294967295; - } - - // "Innox - Juan Carlos Gonzalez" - function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE ) - { - global $ADODB_FETCH_MODE; - if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true; - - if ( !empty($owner) ) { - $table = "$owner.$table"; - } - $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table)); - if ($associative) { - $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"]; - } else { - $create_sql = $a_create_table[1]; - } - - $matches = array(); - - if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false; - $foreign_keys = array(); - $num_keys = count($matches[0]); - for ( $i = 0; $i < $num_keys; $i ++ ) { - $my_field = explode('`, `', $matches[1][$i]); - $ref_table = $matches[2][$i]; - $ref_field = explode('`, `', $matches[3][$i]); - - if ( $upper ) { - $ref_table = strtoupper($ref_table); - } - - // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976 - if (!isset($foreign_keys[$ref_table])) { - $foreign_keys[$ref_table] = array(); - } - $num_fields = count($my_field); - for ( $j = 0; $j < $num_fields; $j ++ ) { - if ( $associative ) { - $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j]; - } else { - $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}"; - } - } - } - - return $foreign_keys; - } - - -} - -/*-------------------------------------------------------------------------------------- - Class Name: Recordset ---------------------------------------------------------------------------------------*/ - - -class ADORecordSet_mysql extends ADORecordSet{ - - var $databaseType = "mysql"; - var $canSeek = true; - - function __construct($queryID,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - switch ($mode) - { - case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break; - case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break; - case ADODB_FETCH_DEFAULT: - case ADODB_FETCH_BOTH: - default: - $this->fetchMode = MYSQL_BOTH; break; - } - $this->adodbFetchMode = $mode; - parent::__construct($queryID); - } - - function _initrs() - { - //GLOBAL $ADODB_COUNTRECS; - // $this->_numOfRows = ($ADODB_COUNTRECS) ? @mysql_num_rows($this->_queryID):-1; - $this->_numOfRows = @mysql_num_rows($this->_queryID); - $this->_numOfFields = @mysql_num_fields($this->_queryID); - } - - function FetchField($fieldOffset = -1) - { - if ($fieldOffset != -1) { - $o = @mysql_fetch_field($this->_queryID, $fieldOffset); - $f = @mysql_field_flags($this->_queryID,$fieldOffset); - if ($o) $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); // suggested by: Jim Nicholson (jnich#att.com) - //$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable - if ($o) $o->binary = (strpos($f,'binary')!== false); - } - else { /* The $fieldOffset argument is not provided thus its -1 */ - $o = @mysql_fetch_field($this->_queryID); - //if ($o) $o->max_length = @mysql_field_len($this->_queryID); // suggested by: Jim Nicholson (jnich#att.com) - $o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable - } - - return $o; - } - - function GetRowAssoc($upper = ADODB_ASSOC_CASE) - { - if ($this->fetchMode == MYSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) { - $row = $this->fields; - } - else { - $row = ADORecordSet::GetRowAssoc($upper); - } - return $row; - } - - /* Use associative array to get fields array */ - function Fields($colname) - { - // added @ by "Michael William Miller" - if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname]; - - if (!$this->bind) { - $this->bind = array(); - for ($i=0; $i < $this->_numOfFields; $i++) { - $o = $this->FetchField($i); - $this->bind[strtoupper($o->name)] = $i; - } - } - return $this->fields[$this->bind[strtoupper($colname)]]; - } - - function _seek($row) - { - if ($this->_numOfRows == 0) return false; - return @mysql_data_seek($this->_queryID,$row); - } - - function MoveNext() - { - //return adodb_movenext($this); - //if (defined('ADODB_EXTENSION')) return adodb_movenext($this); - if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) { - $this->_updatefields(); - $this->_currentRow += 1; - return true; - } - if (!$this->EOF) { - $this->_currentRow += 1; - $this->EOF = true; - } - return false; - } - - function _fetch() - { - $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode); - $this->_updatefields(); - return is_array($this->fields); - } - - function _close() { - @mysql_free_result($this->_queryID); - $this->_queryID = false; - } - - function MetaType($t,$len=-1,$fieldobj=false) - { - if (is_object($t)) { - $fieldobj = $t; - $t = $fieldobj->type; - $len = $fieldobj->max_length; - } - - $len = -1; // mysql max_length is not accurate - switch (strtoupper($t)) { - case 'STRING': - case 'CHAR': - case 'VARCHAR': - case 'TINYBLOB': - case 'TINYTEXT': - case 'ENUM': - case 'SET': - if ($len <= $this->blobSize) return 'C'; - - case 'TEXT': - case 'LONGTEXT': - case 'MEDIUMTEXT': - return 'X'; - - // php_mysql extension always returns 'blob' even if 'text' - // so we have to check whether binary... - case 'IMAGE': - case 'LONGBLOB': - case 'BLOB': - case 'MEDIUMBLOB': - case 'BINARY': - return !empty($fieldobj->binary) ? 'B' : 'X'; - - case 'YEAR': - case 'DATE': return 'D'; - - case 'TIME': - case 'DATETIME': - case 'TIMESTAMP': return 'T'; - - case 'INT': - case 'INTEGER': - case 'BIGINT': - case 'TINYINT': - case 'MEDIUMINT': - case 'SMALLINT': - - if (!empty($fieldobj->primary_key)) return 'R'; - else return 'I'; - - default: return 'N'; - } - } - -} - -class ADORecordSet_ext_mysql extends ADORecordSet_mysql { - function __construct($queryID,$mode=false) - { - parent::__construct($queryID,$mode); - } - - function MoveNext() - { - return @adodb_movenext($this); - } -} - -} diff --git a/www/include/adodb5/drivers/adodb-mysqli.inc.php b/www/include/adodb5/drivers/adodb-mysqli.inc.php deleted file mode 100644 index 188efc9f..00000000 --- a/www/include/adodb5/drivers/adodb-mysqli.inc.php +++ /dev/null @@ -1,1293 +0,0 @@ -_transmode = $transaction_mode; - if (empty($transaction_mode)) { - $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ'); - return; - } - if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; - $this->Execute("SET SESSION TRANSACTION ".$transaction_mode); - } - - // returns true or false - // To add: parameter int $port, - // parameter string $socket - function _connect($argHostname = NULL, - $argUsername = NULL, - $argPassword = NULL, - $argDatabasename = NULL, $persist=false) - { - if(!extension_loaded("mysqli")) { - return null; - } - $this->_connectionID = @mysqli_init(); - - if (is_null($this->_connectionID)) { - // mysqli_init only fails if insufficient memory - if ($this->debug) { - ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg()); - } - return false; - } - /* - I suggest a simple fix which would enable adodb and mysqli driver to - read connection options from the standard mysql configuration file - /etc/my.cnf - "Bastien Duclaux" - */ - foreach($this->optionFlags as $arr) { - mysqli_options($this->_connectionID,$arr[0],$arr[1]); - } - - //http ://php.net/manual/en/mysqli.persistconns.php - if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname; - - #if (!empty($this->port)) $argHostname .= ":".$this->port; - $ok = mysqli_real_connect($this->_connectionID, - $argHostname, - $argUsername, - $argPassword, - $argDatabasename, - # PHP7 compat: port must be int. Use default port if cast yields zero - (int)$this->port != 0 ? (int)$this->port : 3306, - $this->socket, - $this->clientFlags); - - if ($ok) { - if ($argDatabasename) return $this->SelectDB($argDatabasename); - return true; - } else { - if ($this->debug) { - ADOConnection::outp("Could't connect : " . $this->ErrorMsg()); - } - $this->_connectionID = null; - return false; - } - } - - // returns true or false - // How to force a persistent connection - function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true); - } - - // When is this used? Close old connection first? - // In _connect(), check $this->forceNewConnect? - function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - $this->forceNewConnect = true; - return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); - } - - function IfNull( $field, $ifNull ) - { - return " IFNULL($field, $ifNull) "; // if MySQL - } - - // do not use $ADODB_COUNTRECS - function GetOne($sql,$inputarr=false) - { - global $ADODB_GETONE_EOF; - - $ret = false; - $rs = $this->Execute($sql,$inputarr); - if ($rs) { - if ($rs->EOF) $ret = $ADODB_GETONE_EOF; - else $ret = reset($rs->fields); - $rs->Close(); - } - return $ret; - } - - function ServerInfo() - { - $arr['description'] = $this->GetOne("select version()"); - $arr['version'] = ADOConnection::_findvers($arr['description']); - return $arr; - } - - - function BeginTrans() - { - if ($this->transOff) return true; - $this->transCnt += 1; - - //$this->Execute('SET AUTOCOMMIT=0'); - mysqli_autocommit($this->_connectionID, false); - $this->Execute('BEGIN'); - return true; - } - - function CommitTrans($ok=true) - { - if ($this->transOff) return true; - if (!$ok) return $this->RollbackTrans(); - - if ($this->transCnt) $this->transCnt -= 1; - $this->Execute('COMMIT'); - - //$this->Execute('SET AUTOCOMMIT=1'); - mysqli_autocommit($this->_connectionID, true); - return true; - } - - function RollbackTrans() - { - if ($this->transOff) return true; - if ($this->transCnt) $this->transCnt -= 1; - $this->Execute('ROLLBACK'); - //$this->Execute('SET AUTOCOMMIT=1'); - mysqli_autocommit($this->_connectionID, true); - return true; - } - - function RowLock($tables,$where='',$col='1 as adodbignore') - { - if ($this->transCnt==0) $this->BeginTrans(); - if ($where) $where = ' where '.$where; - $rs = $this->Execute("select $col from $tables $where for update"); - return !empty($rs); - } - - /** - * Quotes a string to be sent to the database - * When there is no active connection, - * @param string $s The string to quote - * @param boolean $magic_quotes If false, use mysqli_real_escape_string() - * if you are quoting a string extracted from a POST/GET variable, - * then pass get_magic_quotes_gpc() as the second parameter. This will - * ensure that the variable is not quoted twice, once by qstr() and - * once by the magic_quotes_gpc. - * Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc()); - * @return string Quoted string - */ - function qstr($s, $magic_quotes = false) - { - if (is_null($s)) return 'NULL'; - if (!$magic_quotes) { - // mysqli_real_escape_string() throws a warning when the given - // connection is invalid - if (PHP_VERSION >= 5 && $this->_connectionID) { - return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'"; - } - - if ($this->replaceQuote[0] == '\\') { - $s = adodb_str_replace(array('\\',"\0"), array('\\\\',"\\\0") ,$s); - } - return "'" . str_replace("'", $this->replaceQuote, $s) . "'"; - } - // undo magic quotes for " - $s = str_replace('\\"','"',$s); - return "'$s'"; - } - - function _insertid() - { - $result = @mysqli_insert_id($this->_connectionID); - if ($result == -1) { - if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg()); - } - return $result; - } - - // Only works for INSERT, UPDATE and DELETE query's - function _affectedrows() - { - $result = @mysqli_affected_rows($this->_connectionID); - if ($result == -1) { - if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg()); - } - return $result; - } - - // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html - // Reference on Last_Insert_ID on the recommended way to simulate sequences - var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);"; - var $_genSeqSQL = "create table if not exists %s (id int not null)"; - var $_genSeqCountSQL = "select count(*) from %s"; - var $_genSeq2SQL = "insert into %s values (%s)"; - var $_dropSeqSQL = "drop table if exists %s"; - - function CreateSequence($seqname='adodbseq',$startID=1) - { - if (empty($this->_genSeqSQL)) return false; - $u = strtoupper($seqname); - - $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); - if (!$ok) return false; - return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); - } - - function GenID($seqname='adodbseq',$startID=1) - { - // post-nuke sets hasGenID to false - if (!$this->hasGenID) return false; - - $getnext = sprintf($this->_genIDSQL,$seqname); - $holdtransOK = $this->_transOK; // save the current status - $rs = @$this->Execute($getnext); - if (!$rs) { - if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset - $u = strtoupper($seqname); - $this->Execute(sprintf($this->_genSeqSQL,$seqname)); - $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname)); - if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1)); - $rs = $this->Execute($getnext); - } - - if ($rs) { - $this->genID = mysqli_insert_id($this->_connectionID); - $rs->Close(); - } else - $this->genID = 0; - - return $this->genID; - } - - function MetaDatabases() - { - $query = "SHOW DATABASES"; - $ret = $this->Execute($query); - if ($ret && is_object($ret)){ - $arr = array(); - while (!$ret->EOF){ - $db = $ret->Fields('Database'); - if ($db != 'mysql') $arr[] = $db; - $ret->MoveNext(); - } - return $arr; - } - return $ret; - } - - - function MetaIndexes ($table, $primary = FALSE, $owner = false) - { - // save old fetch mode - global $ADODB_FETCH_MODE; - - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } - - // get index details - $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table)); - - // restore fetchmode - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; - - if (!is_object($rs)) { - return $false; - } - - $indexes = array (); - - // parse index data into array - while ($row = $rs->FetchRow()) { - if ($primary == FALSE AND $row[2] == 'PRIMARY') { - continue; - } - - if (!isset($indexes[$row[2]])) { - $indexes[$row[2]] = array( - 'unique' => ($row[1] == 0), - 'columns' => array() - ); - } - - $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4]; - } - - // sort columns by order in the index - foreach ( array_keys ($indexes) as $index ) - { - ksort ($indexes[$index]['columns']); - } - - return $indexes; - } - - - // Format date column in sql string given an input format that understands Y M D - function SQLDate($fmt, $col=false) - { - if (!$col) $col = $this->sysTimeStamp; - $s = 'DATE_FORMAT('.$col.",'"; - $concat = false; - $len = strlen($fmt); - for ($i=0; $i < $len; $i++) { - $ch = $fmt[$i]; - switch($ch) { - case 'Y': - case 'y': - $s .= '%Y'; - break; - case 'Q': - case 'q': - $s .= "'),Quarter($col)"; - - if ($len > $i+1) $s .= ",DATE_FORMAT($col,'"; - else $s .= ",('"; - $concat = true; - break; - case 'M': - $s .= '%b'; - break; - - case 'm': - $s .= '%m'; - break; - case 'D': - case 'd': - $s .= '%d'; - break; - - case 'H': - $s .= '%H'; - break; - - case 'h': - $s .= '%I'; - break; - - case 'i': - $s .= '%i'; - break; - - case 's': - $s .= '%s'; - break; - - case 'a': - case 'A': - $s .= '%p'; - break; - - case 'w': - $s .= '%w'; - break; - - case 'l': - $s .= '%W'; - break; - - default: - - if ($ch == '\\') { - $i++; - $ch = substr($fmt,$i,1); - } - $s .= $ch; - break; - } - } - $s.="')"; - if ($concat) $s = "CONCAT($s)"; - return $s; - } - - // returns concatenated string - // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator - function Concat() - { - $s = ""; - $arr = func_get_args(); - - // suggestion by andrew005@mnogo.ru - $s = implode(',',$arr); - if (strlen($s) > 0) return "CONCAT($s)"; - else return ''; - } - - // dayFraction is a day in floating point - function OffsetDate($dayFraction,$date=false) - { - if (!$date) $date = $this->sysDate; - - $fraction = $dayFraction * 24 * 3600; - return $date . ' + INTERVAL ' . $fraction.' SECOND'; - -// return "from_unixtime(unix_timestamp($date)+$fraction)"; - } - - function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null) - { - // save old fetch mode - global $ADODB_FETCH_MODE; - - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } - - $procedures = array (); - - // get index details - - $likepattern = ''; - if ($NamePattern) { - $likepattern = " LIKE '".$NamePattern."'"; - } - $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern); - if (is_object($rs)) { - - // parse index data into array - while ($row = $rs->FetchRow()) { - $procedures[$row[1]] = array( - 'type' => 'PROCEDURE', - 'catalog' => '', - 'schema' => '', - 'remarks' => $row[7], - ); - } - } - - $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern); - if (is_object($rs)) { - // parse index data into array - while ($row = $rs->FetchRow()) { - $procedures[$row[1]] = array( - 'type' => 'FUNCTION', - 'catalog' => '', - 'schema' => '', - 'remarks' => $row[7] - ); - } - } - - // restore fetchmode - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; - - return $procedures; - } - - /** - * Retrieves a list of tables based on given criteria - * - * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default) - * @param string $showSchema schema name, false = current schema (default) - * @param string $mask filters the table by name - * - * @return array list of tables - */ - function MetaTables($ttype=false,$showSchema=false,$mask=false) - { - $save = $this->metaTablesSQL; - if ($showSchema && is_string($showSchema)) { - $this->metaTablesSQL .= $this->qstr($showSchema); - } else { - $this->metaTablesSQL .= "schema()"; - } - - if ($mask) { - $mask = $this->qstr($mask); - $this->metaTablesSQL .= " AND table_name LIKE $mask"; - } - $ret = ADOConnection::MetaTables($ttype,$showSchema); - - $this->metaTablesSQL = $save; - return $ret; - } - - // "Innox - Juan Carlos Gonzalez" - function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE ) - { - global $ADODB_FETCH_MODE; - - if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true; - - if ( !empty($owner) ) { - $table = "$owner.$table"; - } - $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table)); - if ($associative) { - $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"]; - } else $create_sql = $a_create_table[1]; - - $matches = array(); - - if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false; - $foreign_keys = array(); - $num_keys = count($matches[0]); - for ( $i = 0; $i < $num_keys; $i ++ ) { - $my_field = explode('`, `', $matches[1][$i]); - $ref_table = $matches[2][$i]; - $ref_field = explode('`, `', $matches[3][$i]); - - if ( $upper ) { - $ref_table = strtoupper($ref_table); - } - - // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976 - if (!isset($foreign_keys[$ref_table])) { - $foreign_keys[$ref_table] = array(); - } - $num_fields = count($my_field); - for ( $j = 0; $j < $num_fields; $j ++ ) { - if ( $associative ) { - $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j]; - } else { - $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}"; - } - } - } - - return $foreign_keys; - } - - function MetaColumns($table, $normalize=true) - { - $false = false; - if (!$this->metaColumnsSQL) - return $false; - - global $ADODB_FETCH_MODE; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== false) - $savem = $this->SetFetchMode(false); - $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); - if (isset($savem)) $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - if (!is_object($rs)) - return $false; - - $retarr = array(); - while (!$rs->EOF) { - $fld = new ADOFieldObject(); - $fld->name = $rs->fields[0]; - $type = $rs->fields[1]; - - // split type into type(length): - $fld->scale = null; - if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) { - $fld->type = $query_array[1]; - $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; - $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1; - } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) { - $fld->type = $query_array[1]; - $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1; - } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) { - $fld->type = $query_array[1]; - $arr = explode(",",$query_array[2]); - $fld->enums = $arr; - $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6 - $fld->max_length = ($zlen > 0) ? $zlen : 1; - } else { - $fld->type = $type; - $fld->max_length = -1; - } - $fld->not_null = ($rs->fields[2] != 'YES'); - $fld->primary_key = ($rs->fields[3] == 'PRI'); - $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false); - $fld->binary = (strpos($type,'blob') !== false); - $fld->unsigned = (strpos($type,'unsigned') !== false); - $fld->zerofill = (strpos($type,'zerofill') !== false); - - if (!$fld->binary) { - $d = $rs->fields[4]; - if ($d != '' && $d != 'NULL') { - $fld->has_default = true; - $fld->default_value = $d; - } else { - $fld->has_default = false; - } - } - - if ($save == ADODB_FETCH_NUM) { - $retarr[] = $fld; - } else { - $retarr[strtoupper($fld->name)] = $fld; - } - $rs->MoveNext(); - } - - $rs->Close(); - return $retarr; - } - - // returns true or false - function SelectDB($dbName) - { -// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID); - $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions - - if ($this->_connectionID) { - $result = @mysqli_select_db($this->_connectionID, $dbName); - if (!$result) { - ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg()); - } - return $result; - } - return false; - } - - // parameters use PostgreSQL convention, not MySQL - function SelectLimit($sql, - $nrows = -1, - $offset = -1, - $inputarr = false, - $secs = 0) - { - $offsetStr = ($offset >= 0) ? "$offset," : ''; - if ($nrows < 0) $nrows = '18446744073709551615'; - - if ($secs) - $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr ); - else - $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr ); - - return $rs; - } - - - function Prepare($sql) - { - return $sql; - $stmt = $this->_connectionID->prepare($sql); - if (!$stmt) { - echo $this->ErrorMsg(); - return $sql; - } - return array($sql,$stmt); - } - - - // returns queryID or false - function _query($sql, $inputarr) - { - global $ADODB_COUNTRECS; - // Move to the next recordset, or return false if there is none. In a stored proc - // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result - // returns false. I think this is because the last "recordset" is actually just the - // return value of the stored proc (ie the number of rows affected). - // Commented out for reasons of performance. You should retrieve every recordset yourself. - // if (!mysqli_next_result($this->connection->_connectionID)) return false; - - if (is_array($sql)) { - - // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but - // returns as bound variables. - - $stmt = $sql[1]; - $a = ''; - foreach($inputarr as $k => $v) { - if (is_string($v)) $a .= 's'; - else if (is_integer($v)) $a .= 'i'; - else $a .= 'd'; - } - - $fnarr = array_merge( array($stmt,$a) , $inputarr); - $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr); - $ret = mysqli_stmt_execute($stmt); - return $ret; - } - - /* - if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) { - if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); - return false; - } - - return $mysql_res; - */ - - if ($this->multiQuery) { - $rs = mysqli_multi_query($this->_connectionID, $sql.';'); - if ($rs) { - $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID ); - return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID ) - } - } else { - $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); - - if ($rs) return $rs; - } - - if($this->debug) - ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); - - return false; - - } - - /* Returns: the last error message from previous database operation */ - function ErrorMsg() - { - if (empty($this->_connectionID)) - $this->_errorMsg = @mysqli_connect_error(); - else - $this->_errorMsg = @mysqli_error($this->_connectionID); - return $this->_errorMsg; - } - - /* Returns: the last error number from previous database operation */ - function ErrorNo() - { - if (empty($this->_connectionID)) - return @mysqli_connect_errno(); - else - return @mysqli_errno($this->_connectionID); - } - - // returns true or false - function _close() - { - @mysqli_close($this->_connectionID); - $this->_connectionID = false; - } - - /* - * Maximum size of C field - */ - function CharMax() - { - return 255; - } - - /* - * Maximum size of X field - */ - function TextMax() - { - return 4294967295; - } - - - // this is a set of functions for managing client encoding - very important if the encodings - // of your database and your output target (i.e. HTML) don't match - // for instance, you may have UTF8 database and server it on-site as latin1 etc. - // GetCharSet - get the name of the character set the client is using now - // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported - // depends on compile flags of mysql distribution - - function GetCharSet() - { - //we will use ADO's builtin property charSet - if (!method_exists($this->_connectionID,'character_set_name')) - return false; - - $this->charSet = @$this->_connectionID->character_set_name(); - if (!$this->charSet) { - return false; - } else { - return $this->charSet; - } - } - - // SetCharSet - switch the client encoding - function SetCharSet($charset_name) - { - if (!method_exists($this->_connectionID,'set_charset')) { - return false; - } - - if ($this->charSet !== $charset_name) { - $if = @$this->_connectionID->set_charset($charset_name); - return ($if === true & $this->GetCharSet() == $charset_name); - } else { - return true; - } - } - -} - -/*-------------------------------------------------------------------------------------- - Class Name: Recordset ---------------------------------------------------------------------------------------*/ - -class ADORecordSet_mysqli extends ADORecordSet{ - - var $databaseType = "mysqli"; - var $canSeek = true; - - function __construct($queryID, $mode = false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - - switch ($mode) { - case ADODB_FETCH_NUM: - $this->fetchMode = MYSQLI_NUM; - break; - case ADODB_FETCH_ASSOC: - $this->fetchMode = MYSQLI_ASSOC; - break; - case ADODB_FETCH_DEFAULT: - case ADODB_FETCH_BOTH: - default: - $this->fetchMode = MYSQLI_BOTH; - break; - } - $this->adodbFetchMode = $mode; - parent::__construct($queryID); - } - - function _initrs() - { - global $ADODB_COUNTRECS; - - $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1; - $this->_numOfFields = @mysqli_num_fields($this->_queryID); - } - -/* -1 = MYSQLI_NOT_NULL_FLAG -2 = MYSQLI_PRI_KEY_FLAG -4 = MYSQLI_UNIQUE_KEY_FLAG -8 = MYSQLI_MULTIPLE_KEY_FLAG -16 = MYSQLI_BLOB_FLAG -32 = MYSQLI_UNSIGNED_FLAG -64 = MYSQLI_ZEROFILL_FLAG -128 = MYSQLI_BINARY_FLAG -256 = MYSQLI_ENUM_FLAG -512 = MYSQLI_AUTO_INCREMENT_FLAG -1024 = MYSQLI_TIMESTAMP_FLAG -2048 = MYSQLI_SET_FLAG -32768 = MYSQLI_NUM_FLAG -16384 = MYSQLI_PART_KEY_FLAG -32768 = MYSQLI_GROUP_FLAG -65536 = MYSQLI_UNIQUE_FLAG -131072 = MYSQLI_BINCMP_FLAG -*/ - - function FetchField($fieldOffset = -1) - { - $fieldnr = $fieldOffset; - if ($fieldOffset != -1) { - $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr); - } - $o = @mysqli_fetch_field($this->_queryID); - if (!$o) return false; - - //Fix for HHVM - if ( !isset($o->flags) ) { - $o->flags = 0; - } - /* Properties of an ADOFieldObject as set by MetaColumns */ - $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG; - $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG; - $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG; - $o->binary = $o->flags & MYSQLI_BINARY_FLAG; - // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */ - $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG; - - return $o; - } - - function GetRowAssoc($upper = ADODB_ASSOC_CASE) - { - if ($this->fetchMode == MYSQLI_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) { - return $this->fields; - } - $row = ADORecordSet::GetRowAssoc($upper); - return $row; - } - - /* Use associative array to get fields array */ - function Fields($colname) - { - if ($this->fetchMode != MYSQLI_NUM) { - return @$this->fields[$colname]; - } - - if (!$this->bind) { - $this->bind = array(); - for ($i = 0; $i < $this->_numOfFields; $i++) { - $o = $this->FetchField($i); - $this->bind[strtoupper($o->name)] = $i; - } - } - return $this->fields[$this->bind[strtoupper($colname)]]; - } - - function _seek($row) - { - if ($this->_numOfRows == 0 || $row < 0) { - return false; - } - - mysqli_data_seek($this->_queryID, $row); - $this->EOF = false; - return true; - } - - - function NextRecordSet() - { - global $ADODB_COUNTRECS; - - mysqli_free_result($this->_queryID); - $this->_queryID = -1; - // Move to the next recordset, or return false if there is none. In a stored proc - // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result - // returns false. I think this is because the last "recordset" is actually just the - // return value of the stored proc (ie the number of rows affected). - if(!mysqli_next_result($this->connection->_connectionID)) { - return false; - } - // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using - $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID ) - : @mysqli_use_result( $this->connection->_connectionID ); - if(!$this->_queryID) { - return false; - } - $this->_inited = false; - $this->bind = false; - $this->_currentRow = -1; - $this->Init(); - return true; - } - - // 10% speedup to move MoveNext to child class - // This is the only implementation that works now (23-10-2003). - // Other functions return no or the wrong results. - function MoveNext() - { - if ($this->EOF) return false; - $this->_currentRow++; - $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode); - - if (is_array($this->fields)) { - $this->_updatefields(); - return true; - } - $this->EOF = true; - return false; - } - - function _fetch() - { - $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode); - $this->_updatefields(); - return is_array($this->fields); - } - - function _close() - { - //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014 - //only a problem with persistant connections - - if(isset($this->connection->_connectionID) && $this->connection->_connectionID) { - while(mysqli_more_results($this->connection->_connectionID)){ - mysqli_next_result($this->connection->_connectionID); - } - } - - if($this->_queryID instanceof mysqli_result) { - mysqli_free_result($this->_queryID); - } - $this->_queryID = false; - } - -/* - -0 = MYSQLI_TYPE_DECIMAL -1 = MYSQLI_TYPE_CHAR -1 = MYSQLI_TYPE_TINY -2 = MYSQLI_TYPE_SHORT -3 = MYSQLI_TYPE_LONG -4 = MYSQLI_TYPE_FLOAT -5 = MYSQLI_TYPE_DOUBLE -6 = MYSQLI_TYPE_NULL -7 = MYSQLI_TYPE_TIMESTAMP -8 = MYSQLI_TYPE_LONGLONG -9 = MYSQLI_TYPE_INT24 -10 = MYSQLI_TYPE_DATE -11 = MYSQLI_TYPE_TIME -12 = MYSQLI_TYPE_DATETIME -13 = MYSQLI_TYPE_YEAR -14 = MYSQLI_TYPE_NEWDATE -247 = MYSQLI_TYPE_ENUM -248 = MYSQLI_TYPE_SET -249 = MYSQLI_TYPE_TINY_BLOB -250 = MYSQLI_TYPE_MEDIUM_BLOB -251 = MYSQLI_TYPE_LONG_BLOB -252 = MYSQLI_TYPE_BLOB -253 = MYSQLI_TYPE_VAR_STRING -254 = MYSQLI_TYPE_STRING -255 = MYSQLI_TYPE_GEOMETRY -*/ - - function MetaType($t, $len = -1, $fieldobj = false) - { - if (is_object($t)) { - $fieldobj = $t; - $t = $fieldobj->type; - $len = $fieldobj->max_length; - } - - - $len = -1; // mysql max_length is not accurate - switch (strtoupper($t)) { - case 'STRING': - case 'CHAR': - case 'VARCHAR': - case 'TINYBLOB': - case 'TINYTEXT': - case 'ENUM': - case 'SET': - - case MYSQLI_TYPE_TINY_BLOB : - #case MYSQLI_TYPE_CHAR : - case MYSQLI_TYPE_STRING : - case MYSQLI_TYPE_ENUM : - case MYSQLI_TYPE_SET : - case 253 : - if ($len <= $this->blobSize) return 'C'; - - case 'TEXT': - case 'LONGTEXT': - case 'MEDIUMTEXT': - return 'X'; - - // php_mysql extension always returns 'blob' even if 'text' - // so we have to check whether binary... - case 'IMAGE': - case 'LONGBLOB': - case 'BLOB': - case 'MEDIUMBLOB': - - case MYSQLI_TYPE_BLOB : - case MYSQLI_TYPE_LONG_BLOB : - case MYSQLI_TYPE_MEDIUM_BLOB : - return !empty($fieldobj->binary) ? 'B' : 'X'; - - case 'YEAR': - case 'DATE': - case MYSQLI_TYPE_DATE : - case MYSQLI_TYPE_YEAR : - return 'D'; - - case 'TIME': - case 'DATETIME': - case 'TIMESTAMP': - - case MYSQLI_TYPE_DATETIME : - case MYSQLI_TYPE_NEWDATE : - case MYSQLI_TYPE_TIME : - case MYSQLI_TYPE_TIMESTAMP : - return 'T'; - - case 'INT': - case 'INTEGER': - case 'BIGINT': - case 'TINYINT': - case 'MEDIUMINT': - case 'SMALLINT': - - case MYSQLI_TYPE_INT24 : - case MYSQLI_TYPE_LONG : - case MYSQLI_TYPE_LONGLONG : - case MYSQLI_TYPE_SHORT : - case MYSQLI_TYPE_TINY : - if (!empty($fieldobj->primary_key)) return 'R'; - return 'I'; - - // Added floating-point types - // Maybe not necessery. - case 'FLOAT': - case 'DOUBLE': -// case 'DOUBLE PRECISION': - case 'DECIMAL': - case 'DEC': - case 'FIXED': - default: - //if (!is_numeric($t)) echo "

--- Error in type matching $t -----

"; - return 'N'; - } - } // function - - -} // rs class - -} - -class ADORecordSet_array_mysqli extends ADORecordSet_array { - - function __construct($id=-1,$mode=false) - { - parent::__construct($id,$mode); - } - - function MetaType($t, $len = -1, $fieldobj = false) - { - if (is_object($t)) { - $fieldobj = $t; - $t = $fieldobj->type; - $len = $fieldobj->max_length; - } - - - $len = -1; // mysql max_length is not accurate - switch (strtoupper($t)) { - case 'STRING': - case 'CHAR': - case 'VARCHAR': - case 'TINYBLOB': - case 'TINYTEXT': - case 'ENUM': - case 'SET': - - case MYSQLI_TYPE_TINY_BLOB : - #case MYSQLI_TYPE_CHAR : - case MYSQLI_TYPE_STRING : - case MYSQLI_TYPE_ENUM : - case MYSQLI_TYPE_SET : - case 253 : - if ($len <= $this->blobSize) return 'C'; - - case 'TEXT': - case 'LONGTEXT': - case 'MEDIUMTEXT': - return 'X'; - - // php_mysql extension always returns 'blob' even if 'text' - // so we have to check whether binary... - case 'IMAGE': - case 'LONGBLOB': - case 'BLOB': - case 'MEDIUMBLOB': - - case MYSQLI_TYPE_BLOB : - case MYSQLI_TYPE_LONG_BLOB : - case MYSQLI_TYPE_MEDIUM_BLOB : - - return !empty($fieldobj->binary) ? 'B' : 'X'; - case 'YEAR': - case 'DATE': - case MYSQLI_TYPE_DATE : - case MYSQLI_TYPE_YEAR : - - return 'D'; - - case 'TIME': - case 'DATETIME': - case 'TIMESTAMP': - - case MYSQLI_TYPE_DATETIME : - case MYSQLI_TYPE_NEWDATE : - case MYSQLI_TYPE_TIME : - case MYSQLI_TYPE_TIMESTAMP : - - return 'T'; - - case 'INT': - case 'INTEGER': - case 'BIGINT': - case 'TINYINT': - case 'MEDIUMINT': - case 'SMALLINT': - - case MYSQLI_TYPE_INT24 : - case MYSQLI_TYPE_LONG : - case MYSQLI_TYPE_LONGLONG : - case MYSQLI_TYPE_SHORT : - case MYSQLI_TYPE_TINY : - - if (!empty($fieldobj->primary_key)) return 'R'; - - return 'I'; - - - // Added floating-point types - // Maybe not necessery. - case 'FLOAT': - case 'DOUBLE': -// case 'DOUBLE PRECISION': - case 'DECIMAL': - case 'DEC': - case 'FIXED': - default: - //if (!is_numeric($t)) echo "

--- Error in type matching $t -----

"; - return 'N'; - } - } // function - -} diff --git a/www/include/adodb5/drivers/adodb-mysqlpo.inc.php b/www/include/adodb5/drivers/adodb-mysqlpo.inc.php deleted file mode 100644 index 26b354ae..00000000 --- a/www/include/adodb5/drivers/adodb-mysqlpo.inc.php +++ /dev/null @@ -1,128 +0,0 @@ - - - This driver extends the deprecated mysql driver, and was originally designed to be a - portable driver in the same manner as oci8po and mssqlpo. Its functionality - is exactly duplicated in the mysqlt driver, which is itself deprecated. - This driver will be removed in ADOdb version 6.0.0. - - Requires mysql client. Works on Windows and Unix. -*/ - -// security - hide paths -if (!defined('ADODB_DIR')) die(); - -include_once(ADODB_DIR."/drivers/adodb-mysql.inc.php"); - - -class ADODB_mysqlt extends ADODB_mysql { - var $databaseType = 'mysqlt'; - var $ansiOuter = true; // for Version 3.23.17 or later - var $hasTransactions = true; - var $autoRollback = true; // apparently mysql does not autorollback properly - - function __construct() - { - global $ADODB_EXTENSION; if ($ADODB_EXTENSION) $this->rsPrefix .= 'ext_'; - } - - function BeginTrans() - { - if ($this->transOff) return true; - $this->transCnt += 1; - $this->Execute('SET AUTOCOMMIT=0'); - $this->Execute('BEGIN'); - return true; - } - - function CommitTrans($ok=true) - { - if ($this->transOff) return true; - if (!$ok) return $this->RollbackTrans(); - - if ($this->transCnt) $this->transCnt -= 1; - $this->Execute('COMMIT'); - $this->Execute('SET AUTOCOMMIT=1'); - return true; - } - - function RollbackTrans() - { - if ($this->transOff) return true; - if ($this->transCnt) $this->transCnt -= 1; - $this->Execute('ROLLBACK'); - $this->Execute('SET AUTOCOMMIT=1'); - return true; - } - - function RowLock($tables,$where='',$col='1 as adodbignore') - { - if ($this->transCnt==0) $this->BeginTrans(); - if ($where) $where = ' where '.$where; - $rs = $this->Execute("select $col from $tables $where for update"); - return !empty($rs); - } - -} - -class ADORecordSet_mysqlt extends ADORecordSet_mysql{ - var $databaseType = "mysqlt"; - - function __construct($queryID,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - - switch ($mode) - { - case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break; - case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break; - - case ADODB_FETCH_DEFAULT: - case ADODB_FETCH_BOTH: - default: $this->fetchMode = MYSQL_BOTH; break; - } - - $this->adodbFetchMode = $mode; - parent::__construct($queryID); - } - - function MoveNext() - { - if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) { - $this->_currentRow += 1; - return true; - } - if (!$this->EOF) { - $this->_currentRow += 1; - $this->EOF = true; - } - return false; - } -} - -class ADORecordSet_ext_mysqlt extends ADORecordSet_mysqlt { - - function __construct($queryID,$mode=false) - { - parent::__construct($queryID,$mode); - } - - function MoveNext() - { - return adodb_movenext($this); - } -} diff --git a/www/include/adodb5/drivers/adodb-mysqlt.inc.php b/www/include/adodb5/drivers/adodb-mysqlt.inc.php deleted file mode 100644 index 79c93760..00000000 --- a/www/include/adodb5/drivers/adodb-mysqlt.inc.php +++ /dev/null @@ -1,137 +0,0 @@ -rsPrefix .= 'ext_'; - } - - /* set transaction mode - - SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL -{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE } - - */ - function SetTransactionMode( $transaction_mode ) - { - $this->_transmode = $transaction_mode; - if (empty($transaction_mode)) { - $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ'); - return; - } - if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; - $this->Execute("SET SESSION TRANSACTION ".$transaction_mode); - } - - function BeginTrans() - { - if ($this->transOff) return true; - $this->transCnt += 1; - $this->Execute('SET AUTOCOMMIT=0'); - $this->Execute('BEGIN'); - return true; - } - - function CommitTrans($ok=true) - { - if ($this->transOff) return true; - if (!$ok) return $this->RollbackTrans(); - - if ($this->transCnt) $this->transCnt -= 1; - $ok = $this->Execute('COMMIT'); - $this->Execute('SET AUTOCOMMIT=1'); - return $ok ? true : false; - } - - function RollbackTrans() - { - if ($this->transOff) return true; - if ($this->transCnt) $this->transCnt -= 1; - $ok = $this->Execute('ROLLBACK'); - $this->Execute('SET AUTOCOMMIT=1'); - return $ok ? true : false; - } - - function RowLock($tables,$where='',$col='1 as adodbignore') - { - if ($this->transCnt==0) $this->BeginTrans(); - if ($where) $where = ' where '.$where; - $rs = $this->Execute("select $col from $tables $where for update"); - return !empty($rs); - } - -} - -class ADORecordSet_mysqlt extends ADORecordSet_mysql{ - var $databaseType = "mysqlt"; - - function __construct($queryID,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - - switch ($mode) - { - case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break; - case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break; - - case ADODB_FETCH_DEFAULT: - case ADODB_FETCH_BOTH: - default: $this->fetchMode = MYSQL_BOTH; break; - } - - $this->adodbFetchMode = $mode; - parent::__construct($queryID); - } - - function MoveNext() - { - if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) { - $this->_currentRow += 1; - return true; - } - if (!$this->EOF) { - $this->_currentRow += 1; - $this->EOF = true; - } - return false; - } -} - -class ADORecordSet_ext_mysqlt extends ADORecordSet_mysqlt { - - function MoveNext() - { - return adodb_movenext($this); - } -} diff --git a/www/include/adodb5/drivers/adodb-odbtp_unicode.inc.php b/www/include/adodb5/drivers/adodb-odbtp_unicode.inc.php deleted file mode 100644 index 5ca03e71..00000000 --- a/www/include/adodb5/drivers/adodb-odbtp_unicode.inc.php +++ /dev/null @@ -1,35 +0,0 @@ - - -// security - hide paths -if (!defined('ADODB_DIR')) die(); - -/* - Because the ODBTP server sends and reads UNICODE text data using UTF-8 - encoding, the following HTML meta tag must be included within the HTML - head section of every HTML form and script page: - - - - Also, all SQL query strings must be submitted as UTF-8 encoded text. -*/ - -if (!defined('_ADODB_ODBTP_LAYER')) { - include(ADODB_DIR."/drivers/adodb-odbtp.inc.php"); -} - -class ADODB_odbtp_unicode extends ADODB_odbtp { - var $databaseType = 'odbtp'; - var $_useUnicodeSQL = true; -} diff --git a/www/include/adodb5/drivers/adodb-pdo_sqlsrv.inc.php b/www/include/adodb5/drivers/adodb-pdo_sqlsrv.inc.php deleted file mode 100644 index 869e8e18..00000000 --- a/www/include/adodb5/drivers/adodb-pdo_sqlsrv.inc.php +++ /dev/null @@ -1,49 +0,0 @@ -hasTransactions = true; - $parentDriver->_bindInputArray = true; - $parentDriver->hasInsertID = true; - $parentDriver->fmtTimeStamp = "'Y-m-d H:i:s'"; - $parentDriver->fmtDate = "'Y-m-d'"; - } - - function BeginTrans() - { - $returnval = parent::BeginTrans(); - return $returnval; - } - - function MetaColumns($table, $normalize = true) - { - return false; - } - - function MetaTables($ttype = false, $showSchema = false, $mask = false) - { - return false; - } - - function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0) - { - $ret = ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); - return $ret; - } - - function ServerInfo() - { - return ADOConnection::ServerInfo(); - } - -} diff --git a/www/include/adodb5/drivers/adodb-postgres.inc.php b/www/include/adodb5/drivers/adodb-postgres.inc.php deleted file mode 100644 index 3c866b72..00000000 --- a/www/include/adodb5/drivers/adodb-postgres.inc.php +++ /dev/null @@ -1,14 +0,0 @@ -GetOne("SELECT lastval()") - : $this->GetOne("SELECT currval(pg_get_serial_sequence('$table', '$column'))"); - } -} - -class ADORecordSet_postgres8 extends ADORecordSet_postgres7 -{ - var $databaseType = "postgres8"; -} - -class ADORecordSet_assoc_postgres8 extends ADORecordSet_assoc_postgres7 -{ - var $databaseType = "postgres8"; -} diff --git a/www/include/adodb5/drivers/adodb-postgres9.inc.php b/www/include/adodb5/drivers/adodb-postgres9.inc.php deleted file mode 100644 index fb589188..00000000 --- a/www/include/adodb5/drivers/adodb-postgres9.inc.php +++ /dev/null @@ -1,32 +0,0 @@ -transOff) { - return true; - } - $ret = $this->Execute("BEGIN TRANSACTION"); - $this->transCnt += 1; - return true; - } - - function CommitTrans($ok=true) - { - if ($this->transOff) { - return true; - } - if (!$ok) { - return $this->RollbackTrans(); - } - $ret = $this->Execute("COMMIT"); - if ($this->transCnt > 0) { - $this->transCnt -= 1; - } - return !empty($ret); - } - - function RollbackTrans() - { - if ($this->transOff) { - return true; - } - $ret = $this->Execute("ROLLBACK"); - if ($this->transCnt > 0) { - $this->transCnt -= 1; - } - return !empty($ret); - } - - // mark newnham - function MetaColumns($table, $normalize=true) - { - global $ADODB_FETCH_MODE; - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; - if ($this->fetchMode !== false) { - $savem = $this->SetFetchMode(false); - } - $rs = $this->Execute("PRAGMA table_info('$table')"); - if (isset($savem)) { - $this->SetFetchMode($savem); - } - if (!$rs) { - $ADODB_FETCH_MODE = $save; - return $false; - } - $arr = array(); - while ($r = $rs->FetchRow()) { - $type = explode('(',$r['type']); - $size = ''; - if (sizeof($type)==2) { - $size = trim($type[1],')'); - } - $fn = strtoupper($r['name']); - $fld = new ADOFieldObject; - $fld->name = $r['name']; - $fld->type = $type[0]; - $fld->max_length = $size; - $fld->not_null = $r['notnull']; - $fld->default_value = $r['dflt_value']; - $fld->scale = 0; - if (isset($r['pk']) && $r['pk']) { - $fld->primary_key=1; - } - if ($save == ADODB_FETCH_NUM) { - $arr[] = $fld; - } else { - $arr[strtoupper($fld->name)] = $fld; - } - } - $rs->Close(); - $ADODB_FETCH_MODE = $save; - return $arr; - } - - function _init($parentDriver) - { - $parentDriver->hasTransactions = false; - $parentDriver->hasInsertID = true; - } - - function _insertid() - { - return $this->_connectionID->lastInsertRowID(); - } - - function _affectedrows() - { - return $this->_connectionID->changes(); - } - - function ErrorMsg() - { - if ($this->_logsql) { - return $this->_errorMsg; - } - return ($this->_errorNo) ? $this->ErrorNo() : ''; //**tochange? - } - - function ErrorNo() - { - return $this->_connectionID->lastErrorCode(); //**tochange?? - } - - function SQLDate($fmt, $col=false) - { - $fmt = $this->qstr($fmt); - return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)"; - } - - - function _createFunctions() - { - $this->_connectionID->createFunction('adodb_date', 'adodb_date', 1); - $this->_connectionID->createFunction('adodb_date2', 'adodb_date2', 2); - } - - - // returns true or false - function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - if (empty($argHostname) && $argDatabasename) { - $argHostname = $argDatabasename; - } - $this->_connectionID = new SQLite3($argHostname); - $this->_createFunctions(); - - return true; - } - - // returns true or false - function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - // There's no permanent connect in SQLite3 - return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); - } - - // returns query ID if successful, otherwise false - function _query($sql,$inputarr=false) - { - $rez = $this->_connectionID->query($sql); - if ($rez === false) { - $this->_errorNo = $this->_connectionID->lastErrorCode(); - } - // If no data was returned, we don't need to create a real recordset - elseif ($rez->numColumns() == 0) { - $rez->finalize(); - $rez = true; - } - - return $rez; - } - - function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) - { - $offsetStr = ($offset >= 0) ? " OFFSET $offset" : ''; - $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : ''); - if ($secs2cache) { - $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr); - } else { - $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr); - } - - return $rs; - } - - /* - This algorithm is not very efficient, but works even if table locking - is not available. - - Will return false if unable to generate an ID after $MAXLOOPS attempts. - */ - var $_genSeqSQL = "create table %s (id integer)"; - - function GenID($seq='adodbseq',$start=1) - { - // if you have to modify the parameter below, your database is overloaded, - // or you need to implement generation of id's yourself! - $MAXLOOPS = 100; - //$this->debug=1; - while (--$MAXLOOPS>=0) { - @($num = $this->GetOne("select id from $seq")); - if ($num === false) { - $this->Execute(sprintf($this->_genSeqSQL ,$seq)); - $start -= 1; - $num = '0'; - $ok = $this->Execute("insert into $seq values($start)"); - if (!$ok) { - return false; - } - } - $this->Execute("update $seq set id=id+1 where id=$num"); - - if ($this->affected_rows() > 0) { - $num += 1; - $this->genID = $num; - return $num; - } - } - if ($fn = $this->raiseErrorFn) { - $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num); - } - return false; - } - - function CreateSequence($seqname='adodbseq',$start=1) - { - if (empty($this->_genSeqSQL)) { - return false; - } - $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); - if (!$ok) { - return false; - } - $start -= 1; - return $this->Execute("insert into $seqname values($start)"); - } - - var $_dropSeqSQL = 'drop table %s'; - function DropSequence($seqname = 'adodbseq') - { - if (empty($this->_dropSeqSQL)) { - return false; - } - return $this->Execute(sprintf($this->_dropSeqSQL,$seqname)); - } - - // returns true or false - function _close() - { - return $this->_connectionID->close(); - } - - function MetaIndexes($table, $primary = FALSE, $owner = false) - { - $false = false; - // save old fetch mode - global $ADODB_FETCH_MODE; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } - $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table)); - $rs = $this->Execute($SQL); - if (!is_object($rs)) { - if (isset($savem)) { - $this->SetFetchMode($savem); - } - $ADODB_FETCH_MODE = $save; - return $false; - } - - $indexes = array (); - while ($row = $rs->FetchRow()) { - if ($primary && preg_match("/primary/i",$row[1]) == 0) { - continue; - } - if (!isset($indexes[$row[0]])) { - $indexes[$row[0]] = array( - 'unique' => preg_match("/unique/i",$row[1]), - 'columns' => array() - ); - } - /** - * There must be a more elegant way of doing this, - * the index elements appear in the SQL statement - * in cols[1] between parentheses - * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse) - */ - $cols = explode("(",$row[1]); - $cols = explode(")",$cols[1]); - array_pop($cols); - $indexes[$row[0]]['columns'] = $cols; - } - if (isset($savem)) { - $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - } - return $indexes; - } - -} - -/*-------------------------------------------------------------------------------------- - Class Name: Recordset ---------------------------------------------------------------------------------------*/ - -class ADORecordset_sqlite3 extends ADORecordSet { - - var $databaseType = "sqlite3"; - var $bind = false; - - function __construct($queryID,$mode=false) - { - - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - switch($mode) { - case ADODB_FETCH_NUM: - $this->fetchMode = SQLITE3_NUM; - break; - case ADODB_FETCH_ASSOC: - $this->fetchMode = SQLITE3_ASSOC; - break; - default: - $this->fetchMode = SQLITE3_BOTH; - break; - } - $this->adodbFetchMode = $mode; - - $this->_queryID = $queryID; - - $this->_inited = true; - $this->fields = array(); - if ($queryID) { - $this->_currentRow = 0; - $this->EOF = !$this->_fetch(); - @$this->_initrs(); - } else { - $this->_numOfRows = 0; - $this->_numOfFields = 0; - $this->EOF = true; - } - - return $this->_queryID; - } - - - function FetchField($fieldOffset = -1) - { - $fld = new ADOFieldObject; - $fld->name = $this->_queryID->columnName($fieldOffset); - $fld->type = 'VARCHAR'; - $fld->max_length = -1; - return $fld; - } - - function _initrs() - { - $this->_numOfFields = $this->_queryID->numColumns(); - - } - - function Fields($colname) - { - if ($this->fetchMode != SQLITE3_NUM) { - return $this->fields[$colname]; - } - if (!$this->bind) { - $this->bind = array(); - for ($i=0; $i < $this->_numOfFields; $i++) { - $o = $this->FetchField($i); - $this->bind[strtoupper($o->name)] = $i; - } - } - - return $this->fields[$this->bind[strtoupper($colname)]]; - } - - function _seek($row) - { - // sqlite3 does not implement seek - if ($this->debug) { - ADOConnection::outp("SQLite3 does not implement seek"); - } - return false; - } - - function _fetch($ignore_fields=false) - { - $this->fields = $this->_queryID->fetchArray($this->fetchMode); - return !empty($this->fields); - } - - function _close() - { - } - -} diff --git a/www/include/adodb5/drivers/adodb-sqlitepo.inc.php b/www/include/adodb5/drivers/adodb-sqlitepo.inc.php deleted file mode 100644 index b167e8c8..00000000 --- a/www/include/adodb5/drivers/adodb-sqlitepo.inc.php +++ /dev/null @@ -1,58 +0,0 @@ -fields = array(); - $fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode); - if(is_array($fields)) - foreach($fields as $n => $v) - { - if(($p = strpos($n, ".")) !== false) - $n = substr($n, $p+1); - $this->fields[$n] = $v; - } - - return !empty($this->fields); - } -} diff --git a/www/include/adodb5/lang/adodb-de.inc.php b/www/include/adodb5/lang/adodb-de.inc.php deleted file mode 100644 index dca4ffef..00000000 --- a/www/include/adodb5/lang/adodb-de.inc.php +++ /dev/null @@ -1,32 +0,0 @@ - -$ADODB_LANG_ARRAY = array ( - 'LANG' => 'de', - DB_ERROR => 'Unbekannter Fehler', - DB_ERROR_ALREADY_EXISTS => 'existiert bereits', - DB_ERROR_CANNOT_CREATE => 'kann nicht erstellen', - DB_ERROR_CANNOT_DELETE => 'kann nicht löschen', - DB_ERROR_CANNOT_DROP => 'Tabelle oder Index konnte nicht gelöscht werden', - DB_ERROR_CONSTRAINT => 'Constraint Verletzung', - DB_ERROR_DIVZERO => 'Division durch Null', - DB_ERROR_INVALID => 'ungültig', - DB_ERROR_INVALID_DATE => 'ungültiges Datum oder Zeit', - DB_ERROR_INVALID_NUMBER => 'ungültige Zahl', - DB_ERROR_MISMATCH => 'Unverträglichkeit', - DB_ERROR_NODBSELECTED => 'keine Dantebank ausgewählt', - DB_ERROR_NOSUCHFIELD => 'Feld nicht vorhanden', - DB_ERROR_NOSUCHTABLE => 'Tabelle nicht vorhanden', - DB_ERROR_NOT_CAPABLE => 'Funktion nicht installiert', - DB_ERROR_NOT_FOUND => 'nicht gefunden', - DB_ERROR_NOT_LOCKED => 'nicht gesperrt', - DB_ERROR_SYNTAX => 'Syntaxfehler', - DB_ERROR_UNSUPPORTED => 'nicht Unterstützt', - DB_ERROR_VALUE_COUNT_ON_ROW => 'Anzahl der zurückgelieferten Felder entspricht nicht der Anzahl der Felder in der Abfrage', - DB_ERROR_INVALID_DSN => 'ungültiger DSN', - DB_ERROR_CONNECT_FAILED => 'Verbindung konnte nicht hergestellt werden', - 0 => 'kein Fehler', // DB_OK - DB_ERROR_NEED_MORE_DATA => 'Nicht genügend Daten geliefert', - DB_ERROR_EXTENSION_NOT_FOUND=> 'erweiterung nicht gefunden', - DB_ERROR_NOSUCHDB => 'keine Datenbank', - DB_ERROR_ACCESS_VIOLATION => 'ungenügende Rechte' -); diff --git a/www/include/adodb5/server.php b/www/include/adodb5/server.php deleted file mode 100644 index c61287e7..00000000 --- a/www/include/adodb5/server.php +++ /dev/null @@ -1,100 +0,0 @@ -Connect($host,$uid,$pwd,$database)) err($conn->ErrorNo(). $sep . $conn->ErrorMsg()); -$sql = undomq($_REQUEST['sql']); - -if (isset($_REQUEST['fetch'])) - $ADODB_FETCH_MODE = $_REQUEST['fetch']; - -if (isset($_REQUEST['nrows'])) { - $nrows = $_REQUEST['nrows']; - $offset = isset($_REQUEST['offset']) ? $_REQUEST['offset'] : -1; - $rs = $conn->SelectLimit($sql,$nrows,$offset); -} else - $rs = $conn->Execute($sql); -if ($rs){ - //$rs->timeToLive = 1; - echo _rs2serialize($rs,$conn,$sql); - $rs->Close(); -} else - err($conn->ErrorNo(). $sep .$conn->ErrorMsg()); diff --git a/www/include/auth/local.class.php b/www/include/auth/local.class.php index 52d11ca7..cd4c96a4 100644 --- a/www/include/auth/local.class.php +++ b/www/include/auth/local.class.php @@ -98,7 +98,7 @@ function getUserData($login_name) { // Load the user's groups list($status, $rows, $records) = db_get_records($onadb, 'group_assignments', array('user_id' => $user['id'])); foreach ($records as $record) { - list($status, $rows, $group) = db_get_record($onadb, 'groups', array('id' => $record['group_id'])); + list($status, $rows, $group) = db_get_record($onadb, 'auth_groups', array('id' => $record['group_id'])); $user['grps'][$group['name']] = $group['id']; if ($group['level'] > $user['level']) { $user['level'] = $group['level']; } } @@ -109,4 +109,4 @@ function getUserData($login_name) { } -//Setup VIM: ex: et ts=2 enc=utf-8 : \ No newline at end of file +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/www/include/functions_auth.inc.php b/www/include/functions_auth.inc.php index af61db84..a89a223a 100644 --- a/www/include/functions_auth.inc.php +++ b/www/include/functions_auth.inc.php @@ -159,7 +159,7 @@ function get_perms($login_name='') { // Load the users permissions based on their group ids foreach ((array)$userinfo['grps'] as $group => $grpid) { // Look up the group id stored in local tables using the name - list($status, $rows, $grp) = db_get_record($onadb, 'groups', array('name' => $group)); + list($status, $rows, $grp) = db_get_record($onadb, 'auth_groups', array('name' => $group)); // get permission assignments per group id list($status, $rows, $records) = db_get_records($onadb, 'permission_assignments', array('group_id' => $grp['id'])); foreach ($records as $record) { @@ -225,7 +225,7 @@ function auth_cryptPassword($clear,$method='',$salt=null){ $text .= substr($bin, 0, min(16, $i)); } for($i = $len; $i > 0; $i >>= 1) { - $text .= ($i & 1) ? chr(0) : $clear{0}; + $text .= ($i & 1) ? chr(0) : $clear[0]; } $bin = pack("H32", md5($text)); for($i = 0; $i < 1000; $i++) { diff --git a/www/include/functions_db.inc.php b/www/include/functions_db.inc.php index 5be4e9e6..c3b5fd8e 100644 --- a/www/include/functions_db.inc.php +++ b/www/include/functions_db.inc.php @@ -891,6 +891,7 @@ function db_get_record($dbh=0, $table="", $where="", $order="") { function db_get_records($dbh=0, $table="", $where="", $order="", $rows=-1, $offset=-1) { global $self; @$self['db_get_records_count']++; + $self['error'] = ''; // Debugging printmsg("DEBUG => db_get_records(\$dbh, \$where, $table, $order, $rows, $offset) called", 3); @@ -2210,8 +2211,8 @@ function ona_find_device_type($search="") { } // It's a string - do several sql queries and see if we can get a unique match - list($manufmodel, $role) = split("\(",$search); - list($manuf, $model) = split(", ",$manufmodel); + list($manufmodel, $role) = preg_split("/\(/",$search); + list($manuf, $model) = explode(", ",$manufmodel); $role = preg_replace(array('/\(/','/\)/'),'',"{$role}"); list($status, $rows, $manu) = ona_get_manufacturer_record(array('name' => $manuf)); list($status, $rows, $rol) = ona_get_role_record(array('name' => $role)); @@ -2523,7 +2524,7 @@ function ona_find_vlan($vlan_search="", $campus_search="") { /////////////////////////////////////////////////////////////////////// function ona_find_config($options=array()) { - global $self; + global $onadb, $self; $status = 1; $rows = 0; @@ -2537,6 +2538,8 @@ function ona_find_config($options=array()) { } list($status, $rows, $config) = ona_get_config_record(array('id' => $options['config'])); + // Shove it in to an 'array' so it is consistent + $config[0] = $config; } // Otherwise we're selecting a config by hostname and type @@ -2558,18 +2561,17 @@ function ona_find_config($options=array()) { } // Select the first config record of the specified type and host - list($status, $rows, $config) = ona_get_config_record(array('host_id' => $host['id'], - 'configuration_type_id' => $config_type['id'])); + list($status, $rows, $config) = db_get_records($onadb, 'configurations', array('host_id' => $host['id'], 'configuration_type_id' => $config_type['id']), 'ctime DESC', 1); - if ($status) { - $self['error'] = "ERROR => The config type specified, {$options['type']}, is invalid!"; + if (!$config[0]['id']) { + $self['error'] = "ERROR => Unable to find configuration for host: {$options['host']}, with type {$options['type']}"; return(array(5, 0, array())); } } // Return the config record we got - return(array($status, $rows, $config)); + return(array($status, $rows, $config[0])); } diff --git a/www/include/functions_general.inc.php b/www/include/functions_general.inc.php index 99adbffc..07b11972 100644 --- a/www/include/functions_general.inc.php +++ b/www/include/functions_general.inc.php @@ -64,7 +64,7 @@ function printmsg($msg="",$debugLevel=0) { if ($conf['log_to_db'] and $debugLevel == 0) { global $onadb; // MP TODO: log using tia64n - list($status, $rows) = db_insert_record($onadb, 'ona_logs', array('username' => $username, 'remote_addr' => $_SERVER['REMOTE_ADDR'], 'message' => $msg,'context_name' => $self['context_name'])); + list($status, $rows) = db_insert_record($onadb, 'ona_logs', array('username' => $username, 'timestamp' => date('Y-m-j G:i:s',time()), 'remote_addr' => $_SERVER['REMOTE_ADDR'], 'message' => $msg,'context_name' => $self['context_name'])); } // Print to syslogd if needed @@ -144,6 +144,16 @@ function ona_logmsg($message, $logfile="") { $username = "anonymous"; } + // If we don't have a remote address, set it to localhost + if (!isset($_SERVER['REMOTE_ADDR'])) { + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + } + + // If we don't have a context name, set it to UNKNOWN_CONTEXT + if (!isset($self['context_name'])) { + $self['context_name'] = 'UNKNOWN_CONTEXT'; + } + // Build the exact line we want to write to the file $logdata = date("M j G:i:s ") . "{$uname['nodename']} {$username}@{$_SERVER['REMOTE_ADDR']}: [{$self['context_name']}] {$message}\n"; @@ -634,7 +644,7 @@ function ipv6gz($ip) { } // If we get here, then the input must be in numeric format (1) - else { + else if ($ip != '') { $ip = gmp_init(strval($ip), 10); if ($format == "default") { if(is_ipv4($ip)) @@ -644,6 +654,10 @@ function ipv6gz($ip) { } } + // If we got this far, then we will just return an error because it does not match sanity. + else { + return(-1); + } // If the address wasn't valid return an error -- // check for out-of-range values (< 0 or > 2**128) @@ -757,30 +771,30 @@ function ipcalc_info($ip='', $mask='') { $retarray['mask_cidr'] = ip_mangle($retarray['in_mask'], 'cidr'); // Process the IP address - $retarray['ip_dotted'] = ip_mangle($retarray['in_ip'], dotted); - $retarray['ip_numeric'] = ip_mangle($retarray['in_ip'], numeric); - $retarray['ip_binary'] = ip_mangle($retarray['in_ip'], binary); - $retarray['ip_bin128'] = ip_mangle($retarray['in_ip'], bin128); - $retarray['ip_ipv6'] = ip_mangle($retarray['in_ip'], ipv6); - $retarray['ip_ipv6gz'] = ip_mangle($retarray['in_ip'], ipv6gz); - $retarray['ip_flip'] = ip_mangle($retarray['in_ip'], flip); + $retarray['ip_dotted'] = ip_mangle($retarray['in_ip'], 'dotted'); + $retarray['ip_numeric'] = ip_mangle($retarray['in_ip'], 'numeric'); + $retarray['ip_binary'] = ip_mangle($retarray['in_ip'], 'binary'); + $retarray['ip_bin128'] = ip_mangle($retarray['in_ip'], 'bin128'); + $retarray['ip_ipv6'] = ip_mangle($retarray['in_ip'], 'ipv6'); + $retarray['ip_ipv6gz'] = ip_mangle($retarray['in_ip'], 'ipv6gz'); + $retarray['ip_flip'] = ip_mangle($retarray['in_ip'], 'flip'); // Process the mask - $retarray['mask_dotted'] = ip_mangle($retarray['in_mask'], dotted); - $retarray['mask_numeric'] = ip_mangle($retarray['in_mask'], numeric); - $retarray['mask_binary'] = ip_mangle($retarray['in_mask'], binary); - $retarray['mask_bin128'] = ip_mangle($retarray['in_mask'], bin128); - $retarray['mask_ipv6'] = ip_mangle($retarray['in_mask'], ipv6); - $retarray['mask_ipv6gz'] = ip_mangle($retarray['in_mask'], ipv6gz); - $retarray['mask_flip'] = ip_mangle($retarray['in_mask'], flip); + $retarray['mask_dotted'] = ip_mangle($retarray['in_mask'], 'dotted'); + $retarray['mask_numeric'] = ip_mangle($retarray['in_mask'], 'numeric'); + $retarray['mask_binary'] = ip_mangle($retarray['in_mask'], 'binary'); + $retarray['mask_bin128'] = ip_mangle($retarray['in_mask'], 'bin128'); + $retarray['mask_ipv6'] = ip_mangle($retarray['in_mask'], 'ipv6'); + $retarray['mask_ipv6gz'] = ip_mangle($retarray['in_mask'], 'ipv6gz'); + $retarray['mask_flip'] = ip_mangle($retarray['in_mask'], 'flip'); // Invert the binary mask - $inverted = str_replace("0", "x", ip_mangle($retarray['in_mask'], binary)); + $inverted = str_replace("0", "x", ip_mangle($retarray['in_mask'], 'binary')); $inverted = str_replace("1", "0", $inverted); $inverted = str_replace("x", "1", $inverted); $retarray['mask_bin_invert'] = $inverted; - $retarray['mask_dotted_invert'] = ip_mangle($inverted, dotted); + $retarray['mask_dotted_invert'] = ip_mangle($inverted, 'dotted'); // Check boundaries @@ -797,7 +811,7 @@ function ipcalc_info($ip='', $mask='') { $ip2 = str_pad(substr($ip1, 0, $retarray['mask_cidr']), $padding, '0'); $total = (0xffffffff - $retarray['mask_numeric']) + 1; $usable = $total - 2; - $lastip = ip_mangle($ip2, numeric) - 1 + $total; + $lastip = ip_mangle($ip2, 'numeric') - 1 + $total; $retarray['ip_last'] = ip_mangle($lastip, 'dotted'); } else { // echo "ipv6"; @@ -1221,6 +1235,8 @@ function validate_username($input) { function startSession() { global $conf; + $secure=false; + // If the command line agent, dcm.pl, is making the request, don't really start a session. if (preg_match('/console-module-interface/', $_SERVER['HTTP_USER_AGENT'])) { @@ -1235,16 +1251,20 @@ function startSession() { // Set the name of the cookie (nicer than default name) session_name("ONA_SESSION_ID"); - // Set cookie to expire at end of session - // secure cookie - if (isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS']) { + // Set cookie to expire at end of session + // secure cookie + if (isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS']) { + $secure=true; + } - session_set_cookie_params(0, '/', $_SERVER["SERVER_NAME"], 1); - } - // normal cookie - else { - session_set_cookie_params(0, '/'); - } + session_set_cookie_params([ + 'lifetime' => $conf['cookie_life'], + 'path' => '/', + 'domain' => $_SERVER['SERVER_NAME'], + 'secure' => $secure, + 'httponly' => true, + 'samesite' => 'Strict' + ]); // (Re)start the session session_start(); @@ -1329,6 +1349,8 @@ function loggedIn() { ////////////////////////////////////////////////////////////////////////////// function auth($resource,$msg_level=1) { + // for some reason the default above does not work + if (!isset($msg_level)) $msg_level=1; if (!is_string($resource)) return false; if (array_key_exists($resource, (array)$_SESSION['ona']['auth']['perms'])) { printmsg("DEBUG => auth() User[{$_SESSION['ona']['auth']['user']['username']}] has the {$resource} permission",5); @@ -1538,7 +1560,7 @@ function run_module($module='', $options='', $transaction=1) { if ($has_trans) { // If there was any sort of failure, make sure the status has incremented, this catches sub module output errors; - if ($onadb->HasFailedTrans()) $status = $status + 1; + if ($onadb->HasFailedTrans()) $status = $status + 100; // If the user passed the rollback flag then dont commit the transaction // FIXME: not complete or tested.. it would be nice to have an ability for the user to pass diff --git a/www/include/functions_gui.inc.php b/www/include/functions_gui.inc.php index 4c5cd635..34d948e4 100644 --- a/www/include/functions_gui.inc.php +++ b/www/include/functions_gui.inc.php @@ -151,6 +151,7 @@ function workspace_plugin_loader($modulename, $record=array(), $extravars=array( //Default the module title $title_left_html = $modulename; $title_right_html = ''; + $title_description = ''; // Load the modules contents from the modules directory. // Check for an installed module first. if not then use a builtin one @@ -320,12 +321,33 @@ function get_host_suggestions($q, $max_results=10) { // If we are not using views, limit to the default if (!$conf['dns_views']) $limit_to_view = 'dns_view_id = 0 AND '; + // If there is a dot in what is typed, split that out and check the right hand side for domains first + // then use any found domainid in the search + if (strpos($q,'.') !== false) { + $orig_q = $q; + // Split the query into host and domain portions + list($q,$dom) = explode('.', $q, 2); + // Gather list of all domains that might match + list($status, $rows, $domains) = db_get_records($onadb, 'domains', "name like '{$dom}%'"); + if ($rows) { + foreach ($domains as $domain) { + $domlist .= "{$domain['id']}, "; + } + // Add the list of domains to our search. use a fake -1 domain id to fix the last comma + $domsearch = "domain_id in ($domlist -1) AND "; + } else { + // Since we didnt find any domains, lets try it as a dotted host name + // Note: you can not suggest dotted host names that include their domain as well. Only the hostname will show. + $q = $orig_q; + } + } + // wildcard the query before searching $q = $q . '%'; $table = 'dns'; $field = 'name'; - $where = "{$limit_to_view} {$field} LIKE " . $onadb->qstr($q); + $where = "{$limit_to_view} {$domsearch} {$field} LIKE " . $onadb->qstr($q); $order = "{$field} ASC"; // Search the db for results @@ -584,15 +606,15 @@ function suggest_qsearch($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Command intrepreter if (strpos($q, '/') === 0) { $js .= "suggestions = Array('Enter a command...');"; $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } // Search the DB for ip addressees @@ -665,8 +687,8 @@ function suggest_qsearch($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -679,7 +701,7 @@ function suggest_a_record($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -699,8 +721,8 @@ function suggest_a_record($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_set_a_record_edit_record($q, $el_input, $el_suggest) { return(suggest_a_record($q, $el_input, $el_suggest)); @@ -716,7 +738,7 @@ function suggest_hostname($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -736,8 +758,8 @@ function suggest_hostname($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_move_hostname($q, $el_input, $el_suggest) { return(suggest_hostname($q, $el_input, $el_suggest)); @@ -781,7 +803,7 @@ function suggest_server($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -803,8 +825,8 @@ function suggest_server($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } // FIXME: (PK) do we still use these functions anywhere? Check & remove, if not. @@ -830,7 +852,7 @@ function suggest_domain($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -850,8 +872,8 @@ function suggest_domain($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_domain_alias_edit($q, $el_input, $el_suggest) { return(suggest_domain($q, $el_input, $el_suggest)); @@ -883,7 +905,7 @@ function suggest_notes($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -903,8 +925,8 @@ function suggest_notes($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -921,7 +943,7 @@ function suggest_mac($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -941,8 +963,8 @@ function suggest_mac($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -962,7 +984,7 @@ function suggest_ip($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -980,8 +1002,8 @@ function suggest_ip($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } // The following are just wrappers around suggest_ip(); function suggest_ip_thru($q, $el_input, $el_suggest) { @@ -1025,7 +1047,7 @@ function suggest_vlan_campus($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1045,8 +1067,8 @@ function suggest_vlan_campus($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_vlan_edit($q, $el_input, $el_suggest) { return(suggest_vlan_campus($q, $el_input, $el_suggest)); @@ -1065,7 +1087,7 @@ function suggest_custom_attribute_type($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1085,8 +1107,8 @@ function suggest_custom_attribute_type($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_custom_attribute_type_net($q, $el_input, $el_suggest) { @@ -1102,7 +1124,7 @@ function suggest_manufacturer($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1122,8 +1144,8 @@ function suggest_manufacturer($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -1136,7 +1158,7 @@ function suggest_model($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1156,8 +1178,8 @@ function suggest_model($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -1170,7 +1192,7 @@ function suggest_tag($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1190,8 +1212,8 @@ function suggest_tag($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_tag_qf($q, $el_input, $el_suggest) { return(suggest_tag($q, $el_input, $el_suggest)); @@ -1213,7 +1235,7 @@ function suggest_role($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1233,8 +1255,8 @@ function suggest_role($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -1247,7 +1269,7 @@ function suggest_block($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1267,8 +1289,8 @@ function suggest_block($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -1286,7 +1308,7 @@ function suggest_subnet($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1306,8 +1328,8 @@ function suggest_subnet($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_set_subnet_edit_interface($q, $el_input, $el_suggest) { return(suggest_subnet($q, $el_input, $el_suggest)); @@ -1334,7 +1356,7 @@ function suggest_masks_edit_subnet($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; $q = trim($q); @@ -1433,8 +1455,8 @@ function suggest_masks_edit_subnet($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -1449,7 +1471,7 @@ function suggest_location($q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; // Search the DB @@ -1469,8 +1491,8 @@ function suggest_location($q, $el_input, $el_suggest) { // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } // Used in all QF (tool-tip based) search boxes function suggest_location_qf($q, $el_input, $el_suggest) { diff --git a/www/include/functions_network_map.inc.php b/www/include/functions_network_map.inc.php index 290f5b34..acb32387 100644 --- a/www/include/functions_network_map.inc.php +++ b/www/include/functions_network_map.inc.php @@ -5,7 +5,7 @@ // Returns javascript to set the portal function get_portal_js($window_name, $ip,$version=4) { - + $zoom = array(); if ($version == 4) { $zoom[7]['row_height'] = 8; @@ -230,8 +230,8 @@ function ws_draw_block($window_name, $form='') { $ip = ip_mangle($form['ip'], 'numeric'); if ($ip == -1) { $js .= "alert('Invalid IP address!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } // Build a few variables @@ -259,8 +259,8 @@ function ws_draw_block($window_name, $form='') { $el_name = $ip . '_row'; // Add a row label - $response->addCreate("{$window_name}_substrate", "div", $el_name . '_label'); - $response->addScript(<<create("{$window_name}_substrate", "div", $el_name . '_label'); + $response->script(<<addCreate("{$window_name}_substrate", "div", $el_name); - $response->addScript(<<create("{$window_name}_substrate", "div", $el_name); + $response->script(<<addAssign($el_name, "innerHTML", $html); - $response->addAssign($el_name . '_label', "innerHTML", $label); + $response->assign($el_name, "innerHTML", $html); + $response->assign($el_name . '_label', "innerHTML", $label); // Javascript to make sure the container (row) div is the exact length to hold it's contents in one row - $response->addScript(<<script(<<addScript(<<script(<<addScript($js); } + if ($js) { $response->script($js); } - return($response->getXML()); + return $response; } diff --git a/www/include/html_desktop.inc.php b/www/include/html_desktop.inc.php index 75c9334a..a8d08213 100644 --- a/www/include/html_desktop.inc.php +++ b/www/include/html_desktop.inc.php @@ -3,10 +3,12 @@ // Do some HTML headers before printing anything header("Cache-control: private"); -$year = date('Y'); +global $year; +$ws_plugin_js=''; // If there is a message of the day file, display it. $motdfile = $base.'/local/config/motd.txt'; +$MOTD = ''; if (file_exists($motdfile)) { printmsg("INFO => Displaying MOTD: {$motdfile}",1); $MOTD = file_get_contents($motdfile); @@ -17,7 +19,7 @@ $selected = ""; // If this entry matches the record you are editing, set it to selected if ($entry == $self['context_name']) { $selected = "SELECTED=\"yes\""; } - if ($entry) {$context_list .= "\n";} + if (isset($entry)) {$context_list = "\n";} } // Lets start building the page! @@ -31,6 +33,8 @@ + + {$conf['html_headers']} @@ -61,7 +65,7 @@ class="edit" style="width: 150px;" type="text" title="Quick Search for IP, MAC, DNS" - value="Quick Search..." + placeholder="Quick Search..." name="q" maxlength="100" onFocus="this.value='';" @@ -300,20 +304,15 @@ function update_task_bar(_parent, _bar) {
-
- -
- @@ -321,8 +320,8 @@ function update_task_bar(_parent, _bar) { // Open the work_space that was requested -if ($work_space or $ws) { - if ($ws) $work_space = $ws; +if (isset($work_space) or isset($ws)) { + if (isset($ws)) $work_space = $ws; // Take the query from the URL and process it for use in the window_submit $ws_qry = str_replace('&',',',$_SERVER['QUERY_STRING']); $ws_qry = str_replace('=','=>',$ws_qry); @@ -334,8 +333,8 @@ function update_task_bar(_parent, _bar) { } // Process any search that was passed -if ($search or $q) { - if ($q) $search = $q; +if (isset($search) or isset($q)) { + if (isset($q)) $search = $q; print <<"; + + // validate the hash + $sHash = md5(implode($aSections)); + if (false == $this->bValidateHash || $sHash == $this->sHash) + { + $sType = 'text/javascript'; + if ('style' == $this->sRequest) + $sType = 'text/css'; + + $objResponse = new xajaxCustomResponse($sType); + + foreach ($aSections as $sSection) + $objResponse->append($sSection . "\n"); + + $objResponseManager = xajaxResponseManager::getInstance(); + $objResponseManager->append($objResponse); + + header ('Expires: ' . gmdate('D, d M Y H:i:s', time() + (60*60*24)) . ' GMT'); + + return true; + } + + return 'Invalid script or style request.'; + trigger_error('Hash mismatch: ' . $this->sRequest . ': ' . $sHash . ' <==> ' . $this->sHash, E_USER_ERROR); + } + } +} + +/* + Register the plugin with the xajax plugin manager. +*/ +$objPluginManager = xajaxPluginManager::getInstance(); +$objPluginManager->registerPlugin(new xajaxScriptPlugin(), 9999); diff --git a/www/include/xajax/xajax_core/xajax.inc.php b/www/include/xajax/xajax_core/xajax.inc.php new file mode 100644 index 00000000..f0d9c3f9 --- /dev/null +++ b/www/include/xajax/xajax_core/xajax.inc.php @@ -0,0 +1,1093 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajax.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Section: Standard Definitions +*/ + +/* + String: XAJAX_DEFAULT_CHAR_ENCODING + + Default character encoding used by both the and + classes. +*/ +if (!defined ('XAJAX_DEFAULT_CHAR_ENCODING')) define ('XAJAX_DEFAULT_CHAR_ENCODING', 'utf-8'); + +/* + String: XAJAX_PROCESSING_EVENT + String: XAJAX_PROCESSING_EVENT_BEFORE + String: XAJAX_PROCESSING_EVENT_AFTER + String: XAJAX_PROCESSING_EVENT_INVALID + + Identifiers used to register processing events. Processing events are essentially + hooks into the xajax core that can be used to add functionality into the request + processing sequence. +*/ +if (!defined ('XAJAX_PROCESSING_EVENT')) define ('XAJAX_PROCESSING_EVENT', 'xajax processing event'); +if (!defined ('XAJAX_PROCESSING_EVENT_BEFORE')) define ('XAJAX_PROCESSING_EVENT_BEFORE', 'beforeProcessing'); +if (!defined ('XAJAX_PROCESSING_EVENT_AFTER')) define ('XAJAX_PROCESSING_EVENT_AFTER', 'afterProcessing'); +if (!defined ('XAJAX_PROCESSING_EVENT_INVALID')) define ('XAJAX_PROCESSING_EVENT_INVALID', 'invalidRequest'); + +/* + Class: xajax + + The xajax class uses a modular plug-in system to facilitate the processing + of special Ajax requests made by a PHP page. It generates Javascript that + the page must include in order to make requests. It handles the output + of response commands (see ). Many flags and settings can be + adjusted to effect the behavior of the xajax class as well as the client-side + javascript. +*/ +final class xajax +{ + /* + Array: aSettings + + This array is used to store all the configuration settings that are set during + the run of the script. This provides a single data store for the settings + in case we need to return the value of a configuration option for some reason. + + It is advised that individual plugins store a local copy of the settings they + wish to track, however, settings are available via a reference to the + object using getConfiguration>. + */ + private $aSettings = array(); + + /* + Boolean: bErrorHandler + + This is a configuration setting that the main xajax object tracks. It is used + to enable an error handler function which will trap php errors and return them + to the client as part of the response. The client can then display the errors + to the user if so desired. + */ + private $bErrorHandler; + + /* + Array: aProcessingEvents + + Stores the processing event handlers that have been assigned during this run + of the script. + */ + private $aProcessingEvents; + + /* + Boolean: bExitAllowed + + A configuration option that is tracked by the main object. Setting this + to true allows to exit immediatly after processing a xajax request. If + this is set to false, xajax will allow the remaining code and HTML to be sent + as part of the response. Typically this would result in an error, however, + a response processor on the client side could be designed to handle this condition. + */ + private $bExitAllowed; + + /* + Boolean: bCleanBuffer + + A configuration option that is tracked by the main object. Setting this + to true allows to clear out any pending output buffers so that the + is (virtually) the only output when handling a request. + */ + private $bCleanBuffer; + + /* + String: sLogFile + + A configuration setting tracked by the main object. Set the name of the + file on the server that you wish to have php error messages written to during + the processing of requests. + */ + private $sLogFile; + + /* + String: sCoreIncludeOutput + + This is populated with any errors or warnings produced while including the xajax + core components. This is useful for debugging core updates. + */ + private $sCoreIncludeOutput; + + /* + Object: objPluginManager + + This stores a reference to the global + */ + private $objPluginManager; + + /* + Object: objArgumentManager + + Stores a reference to the global + */ + private $objArgumentManager; + + /* + Object: objResponseManager + + Stores a reference to the global + */ + private $objResponseManager; + + /* + Object: objLanguageManager + + Stores a reference to the global + */ + private $objLanguageManager; + + private $challengeResponse; + + /* + Constructor: xajax + + Constructs a xajax instance and initializes the plugin system. + + Parameters: + + sRequestURI - (optional): The sRequestURI> to be used + for calls back to the server. If empty, xajax fills in the current + URI that initiated this request. + */ + public function __construct($sRequestURI=null, $sLanguage=null) + { + $this->bErrorHandler = false; + $this->aProcessingEvents = array(); + $this->bExitAllowed = true; + $this->bCleanBuffer = true; + $this->sLogFile = ''; + + $this->__wakeup(); + + // The default configuration settings. + $this->configureMany( + array( + 'characterEncoding' => XAJAX_DEFAULT_CHAR_ENCODING, + 'decodeUTF8Input' => false, + 'outputEntities' => false, + 'responseType' => 'JSON', + 'defaultMode' => 'asynchronous', + 'defaultMethod' => 'POST', // W3C: Method is case sensitive + 'wrapperPrefix' => 'xajax_', + 'debug' => false, + 'verbose' => false, + 'useUncompressedScripts' => false, + 'statusMessages' => false, + 'waitCursor' => true, + 'deferScriptGeneration' => true, + 'exitAllowed' => true, + 'errorHandler' => false, + 'cleanBuffer' => false, + 'allowBlankResponse' => false, + 'allowAllResponseTypes' => false, + 'generateStubs' => true, + 'logFile' => '', + 'timeout' => 6000, + 'version' => $this->getVersion() + ) + ); + + if (null !== $sRequestURI) + $this->configure('requestURI', $sRequestURI); + else + $this->configure('requestURI', $this->_detectURI()); + + if (null !== $sLanguage) + $this->configure('language', $sLanguage); + + if ('utf-8' != XAJAX_DEFAULT_CHAR_ENCODING) $this->configure("decodeUTF8Input", true); + + } + + /* + Function: __sleep + */ + public function __sleep() + { + $aMembers = get_class_vars(get_class($this)); + + if (isset($aMembers['objLanguageManager'])) + unset($aMembers['objLanguageManager']); + + if (isset($aMembers['objPluginManager'])) + unset($aMembers['objPluginManager']); + + if (isset($aMembers['objArgumentManager'])) + unset($aMembers['objArgumentManager']); + + if (isset($aMembers['objResponseManager'])) + unset($aMembers['objResponseManager']); + + if (isset($aMembers['sCoreIncludeOutput'])) + unset($aMembers['sCoreIncludeOutput']); + + return array_keys($aMembers); + } + + /* + Function: __wakeup + */ + public function __wakeup() + { + + $sLocalFolder = dirname(__FILE__); + +//SkipAIO + require $sLocalFolder . '/xajaxPluginManager.inc.php'; + require $sLocalFolder . '/xajaxLanguageManager.inc.php'; + require $sLocalFolder . '/xajaxArgumentManager.inc.php'; + require $sLocalFolder . '/xajaxResponseManager.inc.php'; + require $sLocalFolder . '/xajaxRequest.inc.php'; + require $sLocalFolder . '/xajaxResponse.inc.php'; +//EndSkipAIO + + // this is the list of folders where xajax will look for plugins + // that will be automatically included at startup. + $aPluginFolders = array(); + $aPluginFolders[] = dirname($sLocalFolder) . '/xajax_plugins'; + +//SkipAIO + $aPluginFolders[] = $sLocalFolder . '/plugin_layer'; +//EndSkipAIO + + // Setup plugin manager + $this->objPluginManager = xajaxPluginManager::getInstance(); + $this->objPluginManager->loadPlugins($aPluginFolders); + + $this->objLanguageManager = xajaxLanguageManager::getInstance(); + $this->objArgumentManager = xajaxArgumentManager::getInstance(); + $this->objResponseManager = xajaxResponseManager::getInstance(); + + $this->configureMany($this->aSettings); + + } + + /* + Function: getGlobalResponse + + Returns the object preconfigured with the encoding + and entity settings from this instance of . This is used + for singleton-pattern response development. + + Returns: + + : A object which can be used to return + response commands. See also the class. + */ + public static function &getGlobalResponse() + { + static $obj; + if (!$obj) { + $obj = new xajaxResponse(); + } + return $obj; + } + + /* + Function: getVersion + + Returns: + + string : The current xajax version. + */ + public static function getVersion() + { + return 'xajax 0.6 beta 1'; + } + + /* + Function: register + + Call this function to register request handlers, including functions, + callable objects and events. New plugins can be added that support + additional registration methods and request processors. + + + Parameters: + + $sType - (string): Type of request handler being registered; standard + options include: + XAJAX_FUNCTION: a function declared at global scope. + XAJAX_CALLABLE_OBJECT: an object who's methods are to be registered. + XAJAX_EVENT: an event which will cause zero or more event handlers + to be called. + XAJAX_EVENT_HANDLER: register an event handler function. + + $sFunction || $objObject || $sEvent - (mixed): + when registering a function, this is the name of the function + when registering a callable object, this is the object being registered + when registering an event or event handler, this is the name of the event + + $sIncludeFile || $aCallOptions || $sEventHandler + when registering a function, this is the (optional) include file. + when registering a callable object, this is an (optional) array + of call options for the functions being registered. + when registering an event handler, this is the name of the function. + */ + public function register($sType, $mArg) + { + $aArgs = func_get_args(); + $nArgs = func_num_args(); + + if (2 < $nArgs) + { + if (XAJAX_PROCESSING_EVENT == $aArgs[0]) + { + $sEvent = $aArgs[1]; + $xuf = $aArgs[2]; + + if (false == is_a($xuf, 'xajaxUserFunction')) + $xuf = new xajaxUserFunction($xuf); + + $this->aProcessingEvents[$sEvent] = $xuf; + + return true; + } + } + + return $this->objPluginManager->register($aArgs); + } + + /* + Function: configure + + Call this function to set options that will effect the processing of + xajax requests. Configuration settings can be specific to the xajax + core, request processor plugins and response plugins. + + + Parameters: + + Options include: + javascript URI - (string): The path to the folder that contains the + xajax javascript files. + errorHandler - (boolean): true to enable the xajax error handler, see + bErrorHandler> + exitAllowed - (boolean): true to allow xajax to exit after processing + a request. See bExitAllowed> for more information. + */ + public function configure($sName, $mValue) + { + if ('errorHandler' == $sName) { + if (true === $mValue || false === $mValue) + $this->bErrorHandler = $mValue; + } else if ('exitAllowed' == $sName) { + if (true === $mValue || false === $mValue) + $this->bExitAllowed = $mValue; + } else if ('cleanBuffer' == $sName) { + if (true === $mValue || false === $mValue) + $this->bCleanBuffer = $mValue; + } else if ('logFile' == $sName) { + $this->sLogFile = $mValue; + } + + $this->objLanguageManager->configure($sName, $mValue); + $this->objArgumentManager->configure($sName, $mValue); + $this->objPluginManager->configure($sName, $mValue); + $this->objResponseManager->configure($sName, $mValue); + + $this->aSettings[$sName] = $mValue; + } + + /* + Function: configureMany + + Set an array of configuration options. + + Parameters: + + $aOptions - (array): Associative array of configuration settings + */ + public function configureMany($aOptions) + { + foreach ($aOptions as $sName => $mValue) + $this->configure($sName, $mValue); + } + + /* + Function: getConfiguration + + Get the current value of a configuration setting that was previously set + via configure> or configureMany> + + Parameters: + + $sName - (string): The name of the configuration setting + + Returns: + + $mValue : (mixed): The value of the setting if set, null otherwise. + */ + public function getConfiguration($sName) + { + if (isset($this->aSettings[$sName])) + return $this->aSettings[$sName]; + return NULL; + } + + /* + Function: canProcessRequest + + Determines if a call is a xajax request or a page load request. + + Return: + + boolean - True if this is a xajax request, false otherwise. + */ + public function canProcessRequest() + { + return $this->objPluginManager->canProcessRequest(); + } + + /* + Function: VerifySession + + Ensure that an active session is available (primarily used + for storing challenge / response codes). + */ + private function verifySession() + { + $sessionID = session_id(); + if ($sessionID === '') { + $this->objResponseManager->debug( + 'Must enable sessions to use challenge/response.' + ); + return false; + } + return true; + } + + private function loadChallenges($sessionKey) + { + $challenges = array(); + + if (isset($_SESSION[$sessionKey])) + $challenges = $_SESSION[$sessionKey]; + + return $challenges; + } + + private function saveChallenges($sessionKey, $challenges) + { + if (count($challenges) > 10) + array_shift($challenges); + + $_SESSION[$sessionKey] = $challenges; + } + + private function makeChallenge($algo, $value) + { + // TODO: Move to configuration option + if (null === $algo) + $algo = 'md5'; + + // TODO: Move to configuration option + if (null === $value) + $value = rand(100000, 999999); + + return hash($algo, $value); + } + + /* + Function: challenge + + Call this from the top of a xajax enabled request handler + to introduce a challenge and response cycle into the request + response process. + + NOTE: Sessions must be enabled to use this feature. + */ + public function challenge($algo=null, $value=null) + { + if (false === $this->verifySession()) + return false; + + // TODO: Move to configuration option + $sessionKey = 'xajax_challenges'; + + $challenges = $this->loadChallenges($sessionKey); + + if (isset($this->challengeResponse)) + { + $key = array_search($this->challengeResponse, $challenges); + + if ($key !== false) + { + unset($challenges[$key]); + $this->saveChallenges($sessionKey, $challenges); + return true; + } + } + + $challenge = $this->makeChallenge($algo, $value); + + $challenges[] = $challenge; + + $this->saveChallenges($sessionKey, $challenges); + + header("challenge: {$challenge}"); + + return false; + } + + /* + Function: processRequest + + If this is a xajax request (see canProcessRequest>), call the + requested PHP function, build the response and send it back to the + browser. + + This is the main server side engine for xajax. It handles all the + incoming requests, including the firing of events and handling of the + response. If your RequestURI is the same as your web page, then this + function should be called before ANY headers or HTML is output from + your script. + + This function may exit, if a request is processed. See bAllowExit> + */ + public function processRequest() + { + if (isset($_SERVER['HTTP_CHALLENGE_RESPONSE'])) + $this->challengeResponse = $_SERVER['HTTP_CHALLENGE_RESPONSE']; + +//SkipDebug + // Check to see if headers have already been sent out, in which case we can't do our job + if (headers_sent($filename, $linenumber)) { + echo "Output has already been sent to the browser at {$filename}:{$linenumber}.\n"; + echo 'Please make sure the command $xajax->processRequest() is placed before this.'; + exit(); + } +//EndSkipDebug + + if ($this->canProcessRequest()) + { + // Use xajax error handler if necessary + if ($this->bErrorHandler) { + $GLOBALS['xajaxErrorHandlerText'] = ""; + set_error_handler("xajaxErrorHandler"); + } + + $mResult = true; + + // handle beforeProcessing event + if (isset($this->aProcessingEvents[XAJAX_PROCESSING_EVENT_BEFORE])) + { + $bEndRequest = false; + + $this->aProcessingEvents[XAJAX_PROCESSING_EVENT_BEFORE]->call( + array(&$bEndRequest) + ); + + $mResult = (false === $bEndRequest); + } + + if (true === $mResult) + $mResult = $this->objPluginManager->processRequest(); + + if (true === $mResult) + { + if ($this->bCleanBuffer) { + $er = error_reporting(0); + while (ob_get_level() > 0) ob_end_clean(); + error_reporting($er); + } + + // handle afterProcessing event + if (isset($this->aProcessingEvents[XAJAX_PROCESSING_EVENT_AFTER])) + { + $bEndRequest = false; + + $this->aProcessingEvents[XAJAX_PROCESSING_EVENT_AFTER]->call( + array($bEndRequest) + ); + + if (true === $bEndRequest) + { + $this->objResponseManager->clear(); + $this->objResponseManager->append($aResult[1]); + } + } + } + else if (is_string($mResult)) + { + if ($this->bCleanBuffer) { + $er = error_reporting(0); + while (ob_get_level() > 0) ob_end_clean(); + error_reporting($er); + } + + // $mResult contains an error message + // the request was missing the cooresponding handler function + // or an error occurred while attempting to execute the + // handler. replace the response, if one has been started + // and send a debug message. + + $this->objResponseManager->clear(); + $this->objResponseManager->append(new xajaxResponse()); + + // handle invalidRequest event + if (isset($this->aProcessingEvents[XAJAX_PROCESSING_EVENT_INVALID])) + $this->aProcessingEvents[XAJAX_PROCESSING_EVENT_INVALID]->call(); + else + $this->objResponseManager->debug($mResult); + } + + if ($this->bErrorHandler) { + $sErrorMessage = $GLOBALS['xajaxErrorHandlerText']; + if (!empty($sErrorMessage)) { + if (0 < strlen($this->sLogFile)) { + $fH = @fopen($this->sLogFile, "a"); + if (NULL != $fH) { + fwrite( + $fH, + $this->objLanguageManager->getText('LOGHDR:01') + . strftime("%b %e %Y %I:%M:%S %p") + . $this->objLanguageManager->getText('LOGHDR:02') + . $sErrorMessage + . $this->objLanguageManager->getText('LOGHDR:03') + ); + fclose($fH); + } else { + $this->objResponseManager->debug( + $this->objLanguageManager->getText('LOGERR:01') + . $this->sLogFile + ); + } + } + $this->objResponseManager->debug( + $this->objLanguageManager->getText('LOGMSG:01') + . $sErrorMessage + ); + } + } + + $this->objResponseManager->send(); + + if ($this->bErrorHandler) restore_error_handler(); + + if ($this->bExitAllowed) exit(); + } + } + + /* + Function: printJavascript + + Prints the xajax Javascript header and wrapper code into your page. + This should be used to print the javascript code between the HEAD + and /HEAD tags at the top of the page. + + The javascript code output by this function is dependent on the plugins + that are included and the functions that are registered. + + */ + public function printJavascript() + { + $this->objPluginManager->generateClientScript(); + } + + /* + Function: getJavascript + + See printJavascript> for more information. + */ + public function getJavascript() + { + ob_start(); + $this->printJavascript(); + return ob_get_clean(); + } + + /* + Function: autoCompressJavascript + + Creates a new xajax_core, xajax_debug, etc... file out of the + _uncompressed file with a similar name. This strips out the + comments and extraneous whitespace so the file is as small as + possible without modifying the function of the code. + + Parameters: + + sJsFullFilename - (string): The relative path and name of the file + to be compressed. + bAlways - (boolean): Compress the file, even if it already exists. + */ + public function autoCompressJavascript($sJsFullFilename=NULL, $bAlways=false) + { + $sJsFile = 'xajax_js/xajax_core.js'; + + if ($sJsFullFilename) { + $realJsFile = $sJsFullFilename; + } + else { + $realPath = realpath(dirname(dirname(__FILE__))); + $realJsFile = $realPath . '/'. $sJsFile; + } + + // Create a compressed file if necessary + if (!file_exists($realJsFile) || true == $bAlways) { + $srcFile = str_replace('.js', '_uncompressed.js', $realJsFile); + if (!file_exists($srcFile)) { + trigger_error( + $this->objLanguageManager->getText('CMPRSJS:RDERR:01') + . dirname($realJsFile) + . $this->objLanguageManager->getText('CMPRSJS:RDERR:02') + , E_USER_ERROR + ); + } + + require_once(dirname(__FILE__) . '/xajaxCompress.inc.php'); + $javaScript = implode('', file($srcFile)); + $compressedScript = xajaxCompressFile($javaScript); + $fH = @fopen($realJsFile, 'w'); + if (!$fH) { + trigger_error( + $this->objLanguageManager->getText('CMPRSJS:WTERR:01') + . dirname($realJsFile) + . $this->objLanguageManager->getText('CMPRSJS:WTERR:02') + , E_USER_ERROR + ); + } + else { + fwrite($fH, $compressedScript); + fclose($fH); + } + } + } + + private function _compressSelf($sFolder=null) + { + if (null == $sFolder) + $sFolder = dirname(dirname(__FILE__)); + + require_once(dirname(__FILE__) . '/xajaxCompress.inc.php'); + + if ($handle = opendir($sFolder)) { + while (!(false === ($sName = readdir($handle)))) { + if ('.' != $sName && '..' != $sName && is_dir($sFolder . '/' . $sName)) { + $this->_compressSelf($sFolder . '/' . $sName); + } else if (8 < strlen($sName) && 0 == strpos($sName, '.compressed')) { + if ('.inc.php' == substr($sName, strlen($sName) - 8, 8)) { + $sName = substr($sName, 0, strlen($sName) - 8); + $sPath = $sFolder . '/' . $sName . '.inc.php'; + if (file_exists($sPath)) { + + $aParsed = array(); + $aFile = file($sPath); + $nSkip = 0; + foreach (array_keys($aFile) as $sKey) + if ('//SkipDebug' == $aFile[$sKey]) + ++$nSkip; + else if ('//EndSkipDebug' == $aFile[$sKey]) + --$nSkip; + else if (0 == $nSkip) + $aParsed[] = $aFile[$sKey]; + unset($aFile); + + $compressedScript = xajaxCompressFile(implode('', $aParsed)); + + $sNewPath = $sPath; + $fH = @fopen($sNewPath, 'w'); + if (!$fH) { + trigger_error( + $this->objLanguageManager->getText('CMPRSPHP:WTERR:01') + . $sNewPath + . $this->objLanguageManager->getText('CMPRSPHP:WTERR:02') + , E_USER_ERROR + ); + } + else { + fwrite($fH, $compressedScript); + fclose($fH); + } + } + } + } + } + + closedir($handle); + } + } + + public function _compile($sFolder=null, $bWriteFile=true) + { + if (null == $sFolder) + $sFolder = dirname(__FILE__); + + require_once(dirname(__FILE__) . '/xajaxCompress.inc.php'); + + $aOutput = array(); + + if ($handle = opendir($sFolder)) { + while (!(false === ($sName = readdir($handle)))) { + if ('.' != $sName && '..' != $sName && is_dir($sFolder . '/' . $sName)) { + $aOutput[] = $this->_compile($sFolder . '/' . $sName, false); + } else if (8 < strlen($sName)) { + if ('.inc.php' == substr($sName, strlen($sName) - 8, 8)) { + $sName = substr($sName, 0, strlen($sName) - 8); + $sPath = $sFolder . '/' . $sName . '.inc.php'; + if ( + 'xajaxAIO' != $sName && + 'xajaxCompress' != $sName + ) { + if (file_exists($sPath)) { + + $aParsed = array(); + $aFile = file($sPath); + $nSkip = 0; + foreach (array_keys($aFile) as $sKey) + if ('//SkipDebug' == substr($aFile[$sKey], 0, 11)) + ++$nSkip; + else if ('//EndSkipDebug' == substr($aFile[$sKey], 0, 14)) + --$nSkip; + else if ('//SkipAIO' == substr($aFile[$sKey], 0, 9)) + ++$nSkip; + else if ('//EndSkipAIO' == substr($aFile[$sKey], 0, 12)) + --$nSkip; + else if ('<'.'?php' == substr($aFile[$sKey], 0, 5)) {} + else if ('?'.'>' == substr($aFile[$sKey], 0, 2)) {} + else if (0 == $nSkip) + $aParsed[] = $aFile[$sKey]; + unset($aFile); + + $aOutput[] = xajaxCompressFile(implode('', $aParsed)); + } + } + } + } + } + + closedir($handle); + } + + if ($bWriteFile) + { + $fH = @fopen($sFolder . '/xajaxAIO.inc.php', 'w'); + if (!$fH) { + trigger_error( + $this->objLanguageManager->getText('CMPRSAIO:WTERR:01') + . $sFolder + . $this->objLanguageManager->getText('CMPRSAIO:WTERR:02') + , E_USER_ERROR + ); + } + else { + fwrite($fH, '<'.'?php '); + fwrite($fH, implode('', $aOutput)); + fclose($fH); + } + } + + return implode('', $aOutput); + } + + /* + Function: _detectURI + + Returns the current requests URL based upon the SERVER vars. + + Returns: + + string : The URL of the current request. + */ + private function _detectURI() { + $aURL = array(); + + // Try to get the request URL + if (!empty($_SERVER['REQUEST_URI'])) { + + $_SERVER['REQUEST_URI'] = str_replace( + array('"',"'",'<','>'), + array('%22','%27','%3C','%3E'), + $_SERVER['REQUEST_URI'] + ); + + $aURL = parse_url($_SERVER['REQUEST_URI']); + } + + // Fill in the empty values + if (empty($aURL['scheme'])) { + if (!empty($_SERVER['HTTP_SCHEME'])) { + $aURL['scheme'] = $_SERVER['HTTP_SCHEME']; + } else { + $aURL['scheme'] = + (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') + ? 'https' + : 'http'; + } + } + + if (empty($aURL['host'])) { + if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) { + if (strpos($_SERVER['HTTP_X_FORWARDED_HOST'], ':') > 0) { + list($aURL['host'], $aURL['port']) = explode(':', $_SERVER['HTTP_X_FORWARDED_HOST']); + } else { + $aURL['host'] = $_SERVER['HTTP_X_FORWARDED_HOST']; + } + } else if (!empty($_SERVER['HTTP_HOST'])) { + if (strpos($_SERVER['HTTP_HOST'], ':') > 0) { + list($aURL['host'], $aURL['port']) = explode(':', $_SERVER['HTTP_HOST']); + } else { + $aURL['host'] = $_SERVER['HTTP_HOST']; + } + } else if (!empty($_SERVER['SERVER_NAME'])) { + $aURL['host'] = $_SERVER['SERVER_NAME']; + } else { + echo $this->objLanguageManager->getText('DTCTURI:01'); + echo $this->objLanguageManager->getText('DTCTURI:02'); + exit(); + } + } + + if (empty($aURL['port']) && !empty($_SERVER['SERVER_PORT'])) { + $aURL['port'] = $_SERVER['SERVER_PORT']; + } + + if (!empty($aURL['path'])) + if (0 == strlen(basename($aURL['path']))) + unset($aURL['path']); + + if (empty($aURL['path'])) { + $sPath = array(); + if (!empty($_SERVER['PATH_INFO'])) { + $sPath = parse_url($_SERVER['PATH_INFO']); + } else { + $sPath = parse_url($_SERVER['PHP_SELF']); + } + if (isset($sPath['path'])) + $aURL['path'] = str_replace(array('"',"'",'<','>'), array('%22','%27','%3C','%3E'), $sPath['path']); + unset($sPath); + } + + if (empty($aURL['query']) && !empty($_SERVER['QUERY_STRING'])) { + $aURL['query'] = $_SERVER['QUERY_STRING']; + } + + if (!empty($aURL['query'])) { + $aURL['query'] = '?'.$aURL['query']; + } + + // Build the URL: Start with scheme, user and pass + $sURL = $aURL['scheme'].'://'; + if (!empty($aURL['user'])) { + $sURL.= $aURL['user']; + if (!empty($aURL['pass'])) { + $sURL.= ':'.$aURL['pass']; + } + $sURL.= '@'; + } + + // Add the host + $sURL.= $aURL['host']; + + // Add the port if needed + if (!empty($aURL['port']) + && (($aURL['scheme'] == 'http' && $aURL['port'] != 80) + || ($aURL['scheme'] == 'https' && $aURL['port'] != 443))) { + $sURL.= ':'.$aURL['port']; + } + + // Add the path and the query string + $sURL.= $aURL['path'].($aURL['query'] ?? ''); + + // Clean up + unset($aURL); + + $aURL = explode('?', $sURL); + + if (1 < count($aURL)) { + $aQueries = explode('&', $aURL[1]); + + foreach ($aQueries as $sKey => $sQuery) { + if ('xjxGenerate' === substr($sQuery, 0, 11)) { + unset($aQueries[$sKey]); + } + } + + $sQueries = implode('&', $aQueries); + + $aURL[1] = $sQueries; + + $sURL = implode('?', $aURL); + } + + return $sURL; + } + +} + +/* + Section: Global functions +*/ + +/* + Function xajaxErrorHandler + + This function is registered with PHP's set_error_handler if the xajax + error handling system is enabled. + + See bUserErrorHandler> +*/ +function xajaxErrorHandler($errno, $errstr, $errfile, $errline) +{ + $errorReporting = error_reporting(); + if (($errno & $errorReporting) == 0) return; + + if ($errno == E_NOTICE) { + $errTypeStr = 'NOTICE'; + } + else if ($errno == E_WARNING) { + $errTypeStr = 'WARNING'; + } + else if ($errno == E_USER_NOTICE) { + $errTypeStr = 'USER NOTICE'; + } + else if ($errno == E_USER_WARNING) { + $errTypeStr = 'USER WARNING'; + } + else if ($errno == E_USER_ERROR) { + $errTypeStr = 'USER FATAL ERROR'; + } + else if (defined('E_STRICT') && $errno == E_STRICT) { + return; + } + else { + $errTypeStr = 'UNKNOWN: ' . $errno; + } + + $sCrLf = "\n"; + + ob_start(); + echo $GLOBALS['xajaxErrorHandlerText']; + echo $sCrLf; + echo '----'; + echo $sCrLf; + echo '['; + echo $errTypeStr; + echo '] '; + echo $errstr; + echo $sCrLf; + echo 'Error on line '; + echo $errline; + echo ' of file '; + echo $errfile; + $GLOBALS['xajaxErrorHandlerText'] = ob_get_clean(); +} + diff --git a/www/include/xajax/xajax_core/xajaxArgumentManager.inc.php b/www/include/xajax/xajax_core/xajaxArgumentManager.inc.php new file mode 100644 index 00000000..d518d536 --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxArgumentManager.inc.php @@ -0,0 +1,341 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxArgumentManager.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +if (!defined('XAJAX_METHOD_UNKNOWN')) define('XAJAX_METHOD_UNKNOWN', 0); +if (!defined('XAJAX_METHOD_GET')) define('XAJAX_METHOD_GET', 1); +if (!defined('XAJAX_METHOD_POST')) define('XAJAX_METHOD_POST', 2); + +/* + Class: xajaxArgumentManager + + This class processes the input arguments from the GET or POST data of + the request. If this is a request for the initial page load, no arguments + will be processed. During a xajax request, any arguments found in the + GET or POST will be converted to a PHP array. +*/ +final class xajaxArgumentManager +{ + /* + Array: aArgs + + An array of arguments received via the GET or POST parameter + xjxargs. + */ + private $aArgs; + + /* + Boolean: bDecodeUTF8Input + + A configuration option used to indicate whether input data should be + UTF8 decoded automatically. + */ + private $bDecodeUTF8Input; + + /* + String: sCharacterEncoding + + The character encoding in which the input data will be received. + */ + private $sCharacterEncoding; + + /* + Integer: nMethod + + Stores the method that was used to send the arguments from the client. Will + be one of: XAJAX_METHOD_UNKNOWN, XAJAX_METHOD_GET, XAJAX_METHOD_POST + */ + private $nMethod; + + /* + Array: aSequence + + Stores the decoding sequence table. + */ + private $aSequence; + + /* + Function: __convertStringToBool + + Converts a string to a bool var. + + Parameters: + $sValue - (string): + + Returns: + (bool) : true / false + + */ + + private function __convertStringToBool($sValue) + { + if (0 == strcasecmp($sValue, 'true')) + return true; + if (0 == strcasecmp($sValue, 'false')) + return false; + if (is_numeric($sValue)) + { + if (0 == $sValue) + return false; + return true; + } + return false; + } + + private function __argumentStripSlashes(&$sArg) + { + if (false == is_string($sArg)) + return; + + $sArg = stripslashes($sArg); + } + + private function __convertValue($value) + { + $cType = substr($value, 0, 1); + $sValue = substr($value, 1); + switch ($cType) { + case 'S': $value = false === $sValue ? '' : $sValue; break; + case 'B': $value = $this->__convertStringToBool($sValue); break; + case 'N': $value = $sValue == floor($sValue) ? (int)$sValue : (float)$sValue; break; + case '*': $value = null; break; + } + return $value; + } + +// private function __decodeXML($xml) +// { +// $return = array(); +// $nodes = $xml->e; +// foreach ($nodes as $node) { +// $key = (string) $node->k; +// if (isset($node->v->xjxobj)) { +// $value = $this->__decodeXML($node->v->xjxobj); +// } else { +// $value = $this->__convertValue( (string) $node->v ); +// } +// $return[$key] = $value; +// } +// +// return $return; +// } + + + private function __argumentDecode( &$sArg ) + { + + if ('' == $sArg ) return; + + $data = json_decode( $sArg , true ); + + if ( null !== $data && $sArg != $data) { + $sArg = $data; + } else { + $sArg = $this->__convertValue( $sArg ); + } + } + + private function __argumentDecodeUTF8_iconv( &$mArg ) + { + + + if ( is_array( $mArg ) ) + { + foreach ( array_keys( $mArg ) as $sKey ) + { + $sNewKey = $sKey; + $this->__argumentDecodeUTF8_iconv($sNewKey); + + if ($sNewKey != $sKey) + { + $mArg[$sNewKey] = $mArg[$sKey]; + unset($mArg[$sKey]); + $sKey = $sNewKey; + } + + $this->__argumentDecodeUTF8_iconv($mArg[$sKey]); + } + } + else if (is_string($mArg)) + $mArg = iconv("UTF-8", $this->sCharacterEncoding.'//TRANSLIT', $mArg); + } + + private function __argumentDecodeUTF8_mb_convert_encoding(&$mArg) + { + if (is_array($mArg)) + { + foreach (array_keys($mArg) as $sKey) + { + $sNewKey = $sKey; + $this->__argumentDecodeUTF8_mb_convert_encoding($sNewKey); + + if ($sNewKey != $sKey) + { + $mArg[$sNewKey] = $mArg[$sKey]; + unset($mArg[$sKey]); + $sKey = $sNewKey; + } + + $this->__argumentDecodeUTF8_mb_convert_encoding($mArg[$sKey]); + } + } + else if (is_string($mArg)) + $mArg = mb_convert_encoding($mArg, $this->sCharacterEncoding, "UTF-8"); + } + + private function __argumentDecodeUTF8_utf8_decode(&$mArg) + { + if (is_array($mArg)) + { + foreach (array_keys($mArg) as $sKey) + { + $sNewKey = $sKey; + $this->__argumentDecodeUTF8_utf8_decode($sNewKey); + + if ($sNewKey != $sKey) + { + $mArg[$sNewKey] = $mArg[$sKey]; + unset($mArg[$sKey]); + $sKey = $sNewKey; + } + + $this->__argumentDecodeUTF8_utf8_decode($mArg[$sKey]); + } + } + else if (is_string($mArg)) + $mArg = utf8_decode($mArg); + } + + /* + Constructor: xajaxArgumentManager + + Initializes configuration settings to their default values and reads + the argument data from the GET or POST data. + */ + private function __construct() + { + + $this->aArgs = array(); + $this->bDecodeUTF8Input = false; + $this->sCharacterEncoding = 'UTF-8'; + $this->nMethod = XAJAX_METHOD_UNKNOWN; + + if (isset($_POST['xjxargs'])) { + $this->nMethod = XAJAX_METHOD_POST; + $this->aArgs = $_POST['xjxargs']; + } else if (isset($_GET['xjxargs'])) { + $this->nMethod = XAJAX_METHOD_GET; + $this->aArgs = $_GET['xjxargs']; + } + + //As of PHP 7.4 get_magic_quotes_gpc() is deprecated + if (PHP_VERSION_ID < 70400 && 1 == get_magic_quotes_gpc()) { + array_walk($this->aArgs, array(&$this, '__argumentStripSlashes')); + } + + array_walk($this->aArgs, array(&$this, '__argumentDecode')); + } + + /* + Function: getInstance + + Returns: + + object - A reference to an instance of this class. This function is + used to implement the singleton pattern. + */ + public static function &getInstance() + { + static $obj; + if (!$obj) { + $obj = new xajaxArgumentManager(); + } + return $obj; + } + + /* + Function: configure + + Accepts configuration settings from the main object. + + Parameters: + + + The tracks the following configuration settings: + + - (boolean): See bDecodeUTF8Input> + - (string): See sCharacterEncoding> + */ + public function configure($sName, $mValue) + { + if ('decodeUTF8Input' == $sName) { + if (true === $mValue || false === $mValue) + $this->bDecodeUTF8Input = $mValue; + } else if ('characterEncoding' == $sName) { + $this->sCharacterEncoding = $mValue; + } + } + + /* + Function: getRequestMethod + + Returns the method that was used to send the arguments from the client. + */ + public function getRequestMethod() + { + return $this->nMethod; + } + + /* + Function: process + + Returns the array of arguments that were extracted and parsed from + the GET or POST data. + */ + public function process() + { + if ($this->bDecodeUTF8Input) + { + + $sFunction = ''; + + if (function_exists('iconv')) + $sFunction = "iconv"; + else if (function_exists('mb_convert_encoding')) + $sFunction = "mb_convert_encoding"; + else if ($this->sCharacterEncoding == "ISO-8859-1") + $sFunction = "utf8_decode"; + else { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('ARGMGR:ERR:03') + , E_USER_NOTICE + ); + } + + $mFunction = array(&$this, '__argumentDecodeUTF8_' . $sFunction); + + array_walk($this->aArgs, $mFunction); + $this->bDecodeUTF8Input = false; + } + + return $this->aArgs; + } +} diff --git a/www/include/xajax_0.2.4/xajaxCompress.php b/www/include/xajax/xajax_core/xajaxCompress.inc.php similarity index 50% rename from www/include/xajax_0.2.4/xajaxCompress.php rename to www/include/xajax/xajax_core/xajaxCompress.inc.php index 327a92df..5f68cd98 100644 --- a/www/include/xajax_0.2.4/xajaxCompress.php +++ b/www/include/xajax/xajax_core/xajaxCompress.inc.php @@ -1,70 +1,42 @@ will call this function internally to compress the javascript code for + more efficient delivery. + + Parameters: + + $sFile - (stirng): The file to be compressed. +*/ +function xajaxCompressFile($sFile) { //remove windows cariage returns - $sJS = str_replace("\r","",$sJS); + $sFile = str_replace("\r",'',$sFile); //array to store replaced literal strings $literal_strings = array(); //explode the string into lines - $lines = explode("\n",$sJS); + $lines = explode("\n",$sFile); //loop through all the lines, building a new string at the same time as removing literal strings - $clean = ""; + $clean = ''; $inComment = false; - $literal = ""; + $literal = ''; $inQuote = false; $escaped = false; - $quoteChar = ""; + $quoteChar = ''; - for($i=0;$i \ No newline at end of file diff --git a/www/include/xajax/xajax_core/xajaxControl.inc.php b/www/include/xajax/xajax_core/xajaxControl.inc.php new file mode 100644 index 00000000..322e9570 --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxControl.inc.php @@ -0,0 +1,795 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxControl.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +require_once('xajaxRequest.inc.php'); + +/* + Constant: XAJAX_HTML_CONTROL_DOCTYPE_FORMAT + + Defines the doctype of the current document; this will effect how the HTML is formatted + when the html control library is used to construct html documents and fragments. This can + be one of the following values: + + 'XHTML' - (default) Typical effects are that certain elements are closed with '/>' + 'HTML' - Typical differences are that closing tags for certain elements cannot be '/>' +*/ +if (false == defined('XAJAX_HTML_CONTROL_DOCTYPE_FORMAT')) define('XAJAX_HTML_CONTROL_DOCTYPE_FORMAT', 'XHTML'); + +/* + Constant: XAJAX_HTML_CONTROL_DOCTYPE_VERSION +*/ +if (false == defined('XAJAX_HTML_CONTROL_DOCTYPE_VERSION')) define('XAJAX_HTML_CONTROL_DOCTYPE_VERSION', '1.0'); + +/* + Constant: XAJAX_HTML_CONTROL_DOCTYPE_VALIDATION +*/ +if (false == defined('XAJAX_HTML_CONTROL_DOCTYPE_VALIDATION')) define('XAJAX_HTML_CONTROL_DOCTYPE_VALIDATION', 'TRANSITIONAL'); + + +define('XAJAX_DOMRESPONSE_APPENDCHILD', 100); +define('XAJAX_DOMRESPONSE_INSERTBEFORE', 101); +define('XAJAX_DOMRESPONSE_INSERTAFTER', 102); +/* + Class: xajaxControl + + The base class for all xajax enabled controls. Derived classes will generate the + HTML and javascript code that will be sent to the browser via printHTML> + or sent to the browser in a via getHTML>. +*/ +class xajaxControl +{ + /* + String: sTag + */ + protected $sTag; + + /* + Boolean: sEndTag + + 'required' - (default) Indicates the control must have a full end tag + 'optional' - The control may have an abbr. begin tag or a full end tag + 'forbidden' - The control must have an abbr. begin tag and no end tag + */ + protected $sEndTag; + + /* + Array: aAttributes + + An associative array of attributes that will be used in the generation + of the HMTL code for this control. + */ + protected $aAttributes; + + /* + Array: aEvents + + An associative array of events that will be assigned to this control. Each + event declaration will include a reference to a object; it's + script will be extracted using printScript> or + getScript>. + */ + protected $aEvents; + + /* + String: sClass + + Contains a declaration of the class of this control. %inline controls do not + need to be indented, %block controls should be indented. + */ + protected $sClass; + + /* + Function: xajaxControl + + Parameters: + + $aConfiguration - (array): An associative array that contains a variety + of configuration options for this object. + + Note: + This array may contain the following entries: + + 'attributes' - (array): An associative array containing attributes + that will be passed to the setAttribute> function. + + 'children' - (array): An array of derived objects that + will be the children of this control. + */ + protected function __construct($sTag, $aConfiguration=array()) + { + $this->sTag = $sTag; + + $this->clearAttributes(); + + if (isset($aConfiguration['attributes'])) + if (is_array($aConfiguration['attributes'])) + foreach ($aConfiguration['attributes'] as $sKey => $sValue) + $this->setAttribute($sKey, $sValue); + + $this->clearEvents(); + + if (isset($aConfiguration['event'])) + call_user_func_array( + array($this, 'setEvent'), + $aConfiguration['event'] + ); + + else if (isset($aConfiguration['events'])) + if (is_array($aConfiguration['events'])) + foreach ($aConfiguration['events'] as $aEvent) + call_user_func_array( + array($this, 'setEvent'), + $aEvent + ); + + $this->sClass = '%block'; + $this->sEndTag = 'forbidden'; + } + + /* + Function: getClass + + Returns the *adjusted* class of the element + */ + public function getClass() + { + return $this->sClass; + } + + /* + Function: clearAttributes + + Removes all attributes assigned to this control. + */ + public function clearAttributes() + { + $this->aAttributes = array(); + } + + /* + Function: setAttribute + + Call to set various control specific attributes to be included in the HTML + script that is returned when printHTML> or getHTML> + is called. + + Parameters: + $sName - (string): The attribute name to set the value. + $sValue - (string): The value to be set. + */ + public function setAttribute($sName, $sValue) + { +//SkipDebug + if (class_exists('clsValidator')) + { + $objValidator = clsValidator::getInstance(); + if (false == $objValidator->attributeValid($this->sTag, $sName)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:IAERR:01') + . $sName + . $objLanguageManager->getText('XJXCTL:IAERR:02') + . $this->sTag + . $objLanguageManager->getText('XJXCTL:IAERR:03') + , E_USER_ERROR + ); + } + } +//EndSkipDebug + + $this->aAttributes[$sName] = $sValue; + } + + /* + Function: getAttribute + + Call to obtain the value currently associated with the specified attribute + if set. + + Parameters: + + sName - (string): The name of the attribute to be returned. + + Returns: + + mixed : The value associated with the attribute, or null. + */ + public function getAttribute($sName) + { + if (false == isset($this->aAttributes[$sName])) + return null; + + return $this->aAttributes[$sName]; + } + + /* + Function: clearEvents + + Clear the events that have been associated with this object. + */ + public function clearEvents() + { + $this->aEvents = array(); + } + + /* + Function: setEvent + + Call this function to assign a object as the handler for + the specific DOM event. The printScript> function will + be called to generate the javascript for this request. + + Parameters: + + sEvent - (string): A string containing the name of the event to be assigned. + objRequest - (xajaxRequest object): The object to be associated + with the specified event. + aParameters - (array, optional): An array containing parameter declarations + that will be passed to this object just before the javascript + is generated. + sBeforeRequest - (string, optional): a string containing a snippet of javascript code + to execute prior to calling the xajaxRequest function + sAfterRequest - (string, optional): a string containing a snippet of javascript code + to execute after calling the xajaxRequest function + */ + public function setEvent($sEvent, $objRequest, $aParameters=array(), $sBeforeRequest='', $sAfterRequest='; return false;') + { +//SkipDebug + if (false == ($objRequest instanceof xajaxRequest)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:IRERR:01') + . $this->backtrace() + , E_USER_ERROR + ); + } + + if (class_exists('clsValidator')) { + $objValidator = clsValidator::getInstance(); + if (false == $objValidator->attributeValid($this->sTag, $sEvent)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:IEERR:01') + . $sEvent + . $objLanguageManager->getText('XJXCTL:IEERR:02') + . $this->sTag + . $objLanguageManager->getText('XJXCTL:IEERR:03') + , E_USER_ERROR + ); + } + } +//EndSkipDebug + + $objRequest = clone($objRequest); + + $this->aEvents[$sEvent] = array( + $objRequest, + $aParameters, + $sBeforeRequest, + $sAfterRequest + ); + } + + /* + Function: getHTML + + Generates and returns the HTML representation of this control and + it's children. + + Returns: + + string : The HTML representation of this control. + */ + public function getHTML($bFormat=false) + { + ob_start(); + if ($bFormat) + $this->printHTML(); + else + $this->printHTML(false); + return ob_get_clean(); + } + + /* + Function: printHTML + + Generates and prints the HTML representation of this control and + it's children. + + Returns: + + string : The HTML representation of this control. + */ + public function printHTML($sIndent='') + { +//SkipDebug + if (class_exists('clsValidator')) + { + $objValidator = clsValidator::getInstance(); + $sMissing = ''; + if (false == $objValidator->checkRequiredAttributes($this->sTag, $this->aAttributes, $sMissing)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:MAERR:01') + . $sMissing + . $objLanguageManager->getText('XJXCTL:MAERR:02') + . $this->sTag + . $objLanguageManager->getText('XJXCTL:MAERR:03') + , E_USER_ERROR + ); + } + } +//EndSkipDebug + + $sClass = $this->getClass(); + + if ('%inline' != $sClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo $sIndent; + + echo '<'; + echo $this->sTag; + echo ' '; + $this->_printAttributes(); + $this->_printEvents(); + + if ('forbidden' == $this->sEndTag) + { + if ('HTML' == XAJAX_HTML_CONTROL_DOCTYPE_FORMAT) + echo '>'; + else if ('XHTML' == XAJAX_HTML_CONTROL_DOCTYPE_FORMAT) + echo '/>'; + + if ('%inline' != $sClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo "\n"; + + return; + } + else if ('optional' == $this->sEndTag) + { + echo '/>'; + + if ('%inline' == $sClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo "\n"; + + return; + } +//SkipDebug + else + { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:IETERR:01') + . $this->backtrace() + , E_USER_ERROR + ); + } +//EndSkipDebug + } + + public function getResponse($count, $parent, $flag=XAJAX_DOMRESPONSE_APPENDCHILD) + { + $variable = "xjxElm[{$count}]"; + + $response = $this->beginGetResponse($variable, $count); + $this->getResponseAttributes($response, $variable); + $this->getResponseEvents($response, $variable); + $this->endGetResponse($response, $variable, $count, $parent, $flag); + + return $response; + } + + protected function beginGetResponse($variable, $count) + { + $response = new xajaxResponse(); + + if ($count == 0) + $response->domStartResponse(); + + $response->domCreateElement($variable, $this->sTag); + + return $response; + } + + protected function getResponseAttributes($response, $variable) + { + foreach ($this->aAttributes as $sKey => $sValue) + if ('disabled' != $sKey || 'false' != $sValue) + $response->domSetAttribute($variable, $sKey, $sValue); + } + + protected function endGetResponse($response, $variable, $count, $parent, $flag) + { + if ($flag == XAJAX_DOMRESPONSE_APPENDCHILD) + $response->domAppendChild($parent, $variable); + else if ($flag == XAJAX_DOMRESPONSE_INSERTBEFORE) + $response->domInsertBefore($parent, $variable); + else if ($flag == XAJAX_DOMRESPONSE_INSERTAFTER) + $response->domInsertAfter($parent, $variable); + + if ($count == 0) + $response->domEndResponse(); + } + + protected function getResponseEvents($response, $variable) + { + foreach (array_keys($this->aEvents) as $sKey) + { + $aEvent = $this->aEvents[$sKey]; + $objRequest = $aEvent[0]; + $aParameters = $aEvent[1]; + $sBeforeRequest = $aEvent[2]; + $sAfterRequest = $aEvent[3]; + + foreach ($aParameters as $aParameter) + { + $nParameter = $aParameter[0]; + $sType = $aParameter[1]; + $sValue = $aParameter[2]; + $objRequest->setParameter($nParameter, $sType, $sValue); + } + + $objRequest->useDoubleQuote(); + + $response->script( + "{$variable}.{$sKey} = function(evt) { " . + "if (!evt) var evt = window.event; " . + $sBeforeRequest . + $objRequest->getScript() . + $sAfterRequest . + " } " + ); + } + } + + protected function _printAttributes() + { + // NOTE: Special case here: disabled='false' does not work in HTML; does work in javascript + foreach ($this->aAttributes as $sKey => $sValue) + if ('disabled' != $sKey || 'false' != $sValue) + echo "{$sKey}='{$sValue}' "; + } + + protected function _printEvents() + { + foreach (array_keys($this->aEvents) as $sKey) + { + $aEvent = $this->aEvents[$sKey]; + $objRequest = $aEvent[0]; + $aParameters = $aEvent[1]; + $sBeforeRequest = $aEvent[2]; + $sAfterRequest = $aEvent[3]; + + foreach ($aParameters as $aParameter) + { + $nParameter = $aParameter[0]; + $sType = $aParameter[1]; + $sValue = $aParameter[2]; + $objRequest->setParameter($nParameter, $sType, $sValue); + } + + $objRequest->useDoubleQuote(); + + echo "{$sKey}='{$sBeforeRequest}"; + + $objRequest->printScript(); + + echo "{$sAfterRequest}' "; + } + } + + public function backtrace() + { + // debug_backtrace was added to php in version 4.3.0 + // version_compare was added to php in version 4.0.7 + if (0 <= version_compare(PHP_VERSION, '4.3.0')) + return '
Backtrace:
' 
+				. print_r(debug_backtrace(), true) 
+				. '
'; + return ''; + } +} + +/* + Class: xajaxControlContainer + + This class is used as the base class for controls that will contain + other child controls. +*/ +class xajaxControlContainer extends xajaxControl +{ + /* + Array: aChildren + + An array of child controls. + */ + protected $aChildren; + + /* + Boolean: sChildClass + + Will contain '%inline' if all children are class = '%inline', '%block' if all children are '%block' or + '%flow' if both '%inline' and '%block' elements are detected. + */ + protected $sChildClass; + + /* + Function: xajaxControlContainer + + Called to construct and configure this control. + + Parameters: + + aConfiguration - (array): See xajaxControl> for more + information. + */ + protected function __construct($sTag, $aConfiguration=array()) + { + parent::__construct($sTag, $aConfiguration); + + $this->clearChildren(); + + if (isset($aConfiguration['child'])) + $this->addChild($aConfiguration['child']); + + else if (isset($aConfiguration['children'])) + $this->addChildren($aConfiguration['children']); + + $this->sEndTag = 'required'; + } + + /* + Function: getClass + + Returns the *adjusted* class of the element + */ + public function getClass() + { + $sClass = xajaxControl::getClass(); + + if (0 < count($this->aChildren) && '%flow' == $sClass) + return $this->getContentClass(); + else if (0 == count($this->aChildren) || '%inline' == $sClass || '%block' == $sClass) + return $sClass; + + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:ICERR:01') + . $this->backtrace() + , E_USER_ERROR + ); + } + + /* + Function: getContentClass + + Returns the *adjusted* class of the content (children) of this element + */ + public function getContentClass() + { + $sClass = ''; + + foreach (array_keys($this->aChildren) as $sKey) + { + if ('' == $sClass) + $sClass = $this->aChildren[$sKey]->getClass(); + else if ($sClass != $this->aChildren[$sKey]->getClass()) + return '%flow'; + } + + if ('' == $sClass) + return '%inline'; + + return $sClass; + } + + /* + Function: clearChildren + + Clears the list of child controls associated with this control. + */ + public function clearChildren() + { + $this->sChildClass = '%inline'; + $this->aChildren = array(); + } + + /* + Function: addChild + + Adds a control to the array of child controls. Child controls + must be derived from . + */ + public function addChild($objControl) + { +//SkipDebug + if (false == ($objControl instanceof xajaxControl )) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:ICLERR:01') + . $this->backtrace() + , E_USER_ERROR + ); + } + + if (class_exists('clsValidator')) + { + $objValidator = clsValidator::getInstance(); + if (false == $objValidator->childValid($this->sTag, $objControl->sTag)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:ICLERR:02') + . $objControl->sTag + . $objLanguageManager->getText('XJXCTL:ICLERR:03') + . $this->sTag + . $objLanguageManager->getText('XJXCTL:ICLERR:04') + . $this->backtrace() + , E_USER_ERROR + ); + } + } +//EndSkipDebug + + $this->aChildren[] = $objControl; + } + + public function addChildren($aChildren) + { +//SkipDebug + if (false == is_array($aChildren)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:ICHERR:01') + . $this->backtrace() + , E_USER_ERROR + ); + } +//EndSkipDebug + + foreach (array_keys($aChildren) as $sKey) + $this->addChild($aChildren[$sKey]); + } + + public function printHTML($sIndent='') + { +//SkipDebug + if (class_exists('clsValidator')) + { + $objValidator = clsValidator::getInstance(); + $sMissing = ''; + if (false == $objValidator->checkRequiredAttributes($this->sTag, $this->aAttributes, $sMissing)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXCTL:MRAERR:01') + . $sMissing + . $objLanguageManager->getText('XJXCTL:MRAERR:02') + . $this->sTag + . $objLanguageManager->getText('XJXCTL:MRAERR:03') + , E_USER_ERROR + ); + } + } +//EndSkipDebug + + $sClass = $this->getClass(); + + if ('%inline' != $sClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo $sIndent; + + echo '<'; + echo $this->sTag; + echo ' '; + $this->_printAttributes(); + $this->_printEvents(); + + if (0 == count($this->aChildren)) + { + if ('optional' == $this->sEndTag) + { + echo '/>'; + + if ('%inline' != $sClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo "\n"; + + return; + } +//SkipDebug + else if ('required' != $this->sEndTag) + trigger_error("Invalid end tag designation; should be optional or required.\n" + . $this->backtrace(), + E_USER_ERROR + ); +//EndSkipDebug + } + + echo '>'; + + $sContentClass = $this->getContentClass(); + + if ('%inline' != $sContentClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo "\n"; + + $this->_printChildren($sIndent); + + if ('%inline' != $sContentClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo $sIndent; + + echo '<' . '/'; + echo $this->sTag; + echo '>'; + + if ('%inline' != $sClass) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + echo "\n"; + } + + protected function _printChildren($sIndent='') + { + if (false == ($this instanceof clsDocument )) + // this odd syntax is necessary to detect request for no formatting + if (false === (false === $sIndent)) + $sIndent .= "\t"; + + // children + foreach (array_keys($this->aChildren) as $sKey) + { + $objChild = $this->aChildren[$sKey]; + $objChild->printHTML($sIndent); + } + } + + public function getResponse($count, $parent, $flag=XAJAX_DOMRESPONSE_APPENDCHILD) + { + $variable = "xjxElm[{$count}]"; + + $response = $this->beginGetResponse($variable, $count); + $this->getResponseAttributes($response, $variable); + $this->getResponseEvents($response, $variable); + $this->getResponseChildren($response, $variable, $count); + $this->endGetResponse($response, $variable, $count, $parent, $flag); + + return $response; + } + + protected function getResponseChildren($response, $variable, $count) + { + foreach (array_keys($this->aChildren) as $sKey) + { + $objChild = $this->aChildren[$sKey]; + $response->appendResponse( + $objChild->getResponse($count+1, $variable) + ); + } + } +} diff --git a/www/include/xajax/xajax_core/xajaxLanguageManager.inc.php b/www/include/xajax/xajax_core/xajaxLanguageManager.inc.php new file mode 100644 index 00000000..40f4a477 --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxLanguageManager.inc.php @@ -0,0 +1,188 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxLanguageManager.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajaxLanguageManager + + This class contains the default language (english) and the code used to supply + debug and error messages upon request; as well as the code used to load alternate + language text as requested via the function. +*/ +final class xajaxLanguageManager +{ + /* + Array: aMessages + + An array of the currently registered languages. + */ + private $aMessages; + + /* + String: sLanguage + + The currently configured language. + */ + private $sLanguage; + + /* + Function: xajaxLanguageManager + + Construct and initialize the one and only xajax language manager object. + */ + private function __construct() + { + $this->aMessages = array(); + + $this->aMessages['en'] = array( + 'LOGHDR:01' => '** xajax Error Log - ', + 'LOGHDR:02' => " **\n", + 'LOGHDR:03' => "\n\n\n", + 'LOGERR:01' => "** Logging Error **\n\nxajax was unable to write to the error log file:\n", + 'LOGMSG:01' => "** PHP Error Messages: **", + 'CMPRSJS:RDERR:01' => 'The xajax uncompressed Javascript file could not be found in the ', + 'CMPRSJS:RDERR:02' => ' folder. Error ', + 'CMPRSJS:WTERR:01' => 'The xajax compressed javascript file could not be written in the ', + 'CMPRSJS:WTERR:02' => ' folder. Error ', + 'CMPRSPHP:WTERR:01' => 'The xajax compressed file ', + 'CMPRSPHP:WTERR:02' => ' could not be written to. Error ', + 'CMPRSAIO:WTERR:01' => 'The xajax compressed file ', + 'CMPRSAIO:WTERR:02' => '/xajaxAIO.inc.php could not be written to. Error ', + 'DTCTURI:01' => 'xajax Error: xajax failed to automatically identify your Request URI.', + 'DTCTURI:02' => 'Please set the Request URI explicitly when you instantiate the xajax object.', + 'ARGMGR:ERR:01' => 'Malformed object argument received: ', + 'ARGMGR:ERR:02' => ' <==> ', + 'ARGMGR:ERR:03' => 'The incoming xajax data could not be converted from UTF-8', + 'XJXCTL:IAERR:01' => 'Invalid attribute [', + 'XJXCTL:IAERR:02' => '] for element [', + 'XJXCTL:IAERR:03' => '].', + 'XJXCTL:IRERR:01' => 'Invalid request object passed to xajaxControl::setEvent', + 'XJXCTL:IEERR:01' => 'Invalid attribute (event name) [', + 'XJXCTL:IEERR:02' => '] for element [', + 'XJXCTL:IEERR:03' => '].', + 'XJXCTL:MAERR:01' => 'Missing required attribute [', + 'XJXCTL:MAERR:02' => '] for element [', + 'XJXCTL:MAERR:03' => '].', + 'XJXCTL:IETERR:01' => "Invalid end tag designation; should be forbidden or optional.\n", + 'XJXCTL:ICERR:01' => "Invalid class specified for html control; should be %inline, %block or %flow.\n", + 'XJXCTL:ICLERR:01' => 'Invalid control passed to addChild; should be derived from xajaxControl.', + 'XJXCTL:ICLERR:02' => 'Invalid control passed to addChild [', + 'XJXCTL:ICLERR:03' => '] for element [', + 'XJXCTL:ICLERR:04' => "].\n", + 'XJXCTL:ICHERR:01' => 'Invalid parameter passed to xajaxControl::addChildren; should be array of xajaxControl objects', + 'XJXCTL:MRAERR:01' => 'Missing required attribute [', + 'XJXCTL:MRAERR:02' => '] for element [', + 'XJXCTL:MRAERR:03' => '].', + 'XJXPLG:GNERR:01' => 'Response plugin should override the getName function.', + 'XJXPLG:PERR:01' => 'Response plugin should override the process function.', + 'XJXPM:IPLGERR:01' => 'Attempt to register invalid plugin: ', + 'XJXPM:IPLGERR:02' => ' should be derived from xajaxRequestPlugin or xajaxResponsePlugin.', + 'XJXPM:MRMERR:01' => 'Failed to locate registration method for the following: ', + 'XJXRSP:EDERR:01' => 'Passing character encoding to the xajaxResponse constructor is deprecated, instead use $xajax->configure("characterEncoding", ...);', + 'XJXRSP:MPERR:01' => 'Invalid or missing plugin name detected in call to xajaxResponse::plugin', + 'XJXRSP:CPERR:01' => "The \$sType parameter of addCreate has been deprecated. Use the addCreateInput() method instead.", + 'XJXRSP:LCERR:01' => "The xajax response object could not load commands as the data provided was not a valid array.", + 'XJXRSP:AKERR:01' => 'Invalid tag name encoded in array.', + 'XJXRSP:IEAERR:01' => 'Improperly encoded array.', + 'XJXRSP:NEAERR:01' => 'Non-encoded array detected.', + 'XJXRSP:MBEERR:01' => 'The xajax response output could not be converted to HTML entities because the mb_convert_encoding function is not available', + 'XJXRSP:MXRTERR' => 'Error: Cannot mix types in a single response.', + 'XJXRSP:MXCTERR' => 'Error: Cannot mix content types in a single response.', + 'XJXRSP:MXCEERR' => 'Error: Cannot mix character encodings in a single response.', + 'XJXRSP:MXOEERR' => 'Error: Cannot mix output entities (true/false) in a single response.', + 'XJXRM:IRERR' => 'An invalid response was returned while processing this request.', + 'XJXRM:MXRTERR' => 'Error: You cannot mix response types while processing a single request: ' + ); + + $this->sLanguage = 'en'; + } + + /* + Function: getInstance + + Implements the singleton pattern: provides a single instance of the xajax + language manager object to all object which request it. + */ + public static function &getInstance() + { + static $obj; + if (!$obj) { + $obj = new xajaxLanguageManager(); + } + return $obj; + } + + /* + Function: configure + + Called by the main xajax object as configuration options are set. See also: + . The tracks the following configuration + options. + Parameters: + + - language (string, default 'en'): The currently selected language. + */ + public function configure($sName, $mValue) + { + if ('language' == $sName) { + if ($mValue !== $this->sLanguage) { + $sFolder = dirname(__FILE__); + @include $sFolder . '/xajax_lang_' . $mValue . '.inc.php'; + // require $sFolder . '/xajax_lang_' . $mValue . '.inc.php'; + $this->sLanguage = $mValue; + } + } + } + + /* + Function: register + + Called to register an array of alternate language messages. + + Parameters: + + sLanguage - (string): the character code which represents the language being registered. + aMessages - (array): the array of translated debug and error messages + */ + public function register($sLanguage, $aMessages) { + $this->aMessages[$sLanguage] = $aMessages; + } + + /* + Function: getText + + Called by the main xajax object and other objects during the initial page generation + or request processing phase to obtain language specific debug and error messages. + + sMessage - (string): A code indicating the message text being requested. + */ + public function getText($sMessage) + { + if (isset($this->aMessages[$this->sLanguage])) + if (isset($this->aMessages[$this->sLanguage][$sMessage])) + return $this->aMessages[$this->sLanguage][$sMessage]; + + return '(Unknown language or message identifier)' + . $this->sLanguage + . '::' + . $sMessage; + } +} diff --git a/www/include/xajax/xajax_core/xajaxPlugin.inc.php b/www/include/xajax/xajax_core/xajaxPlugin.inc.php new file mode 100644 index 00000000..fe26c87b --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxPlugin.inc.php @@ -0,0 +1,194 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxPlugin.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajaxPlugin + + The base class for all xajax plugins. +*/ +class xajaxPlugin +{ +} + +/* + Class: xajaxRequestPlugin + + The base class for all xajax request plugins. + + Request plugins handle the registration, client script generation and processing of + xajax enabled requests. Each plugin should have a unique signature for both + the registration and processing of requests. During registration, the user will + specify a type which will allow the plugin to detect and handle it. During client + script generation, the plugin will generate a stub with the + prescribed call options and request signature. During request processing, the + plugin will detect the signature generated previously and process the request + accordingly. +*/ +class xajaxRequestPlugin extends xajaxPlugin +{ + /* + Function: configure + + Called by the when a configuration setting is changing. + Plugins should store a local copy of the settings they wish to use during + registration, client script generation or request processing. + */ + function configure($sName, $mValue) + { + } + + /* + Function: register + + Called by the when a user script when a function, event + or callable object is to be registered. Additional plugins may support other + registration types. + */ + function register($aArgs) + { + return false; + } + + function generateHash() + {} + + /* + Function: generateClientScript + + Called by when the page's HTML is being sent to the browser. + This allows each plugin to inject some script / style or other appropriate tags + into the HEAD of the document. Each block must be appropriately enclosed, meaning + javascript code must be enclosed in SCRIPT and /SCRIPT tags. + */ + function generateClientScript() + { + } + + /* + Function: canProcessRequest + + Called by the when a request has been received to determine + if the request is for a xajax enabled function or for the initial page load. + */ + function canProcessRequest() + { + return false; + } + + /* + Function: processRequest + + Called by the when a request is being processed. This + will only occur when has determined that the current request is a valid + (registered) xajax enabled function via canProcessRequest>. + + Returns: + false + */ + function processRequest() + { + return false; + } +} + +/* + Class: xajaxResponsePlugin + + Base class for all xajax response plugins. + + A response plugin provides additional services not already provided by the + class with regard to sending response commands to the + client. In addition, a response command may send javascript to the browser + at page load to aid in the processing of it's response commands. +*/ +class xajaxResponsePlugin extends xajaxPlugin +{ + /* + Object: objResponse + + A reference to the current object that is being used + to build the response that will be sent to the client browser. + */ + var $objResponse; + + /* + Function: setResponse + + Called by the object that is currently being used + to build the response that will be sent to the client browser. + + Parameters: + + objResponse - (object): A reference to the object + */ + function setResponse($objResponse) + { + $this->objResponse = $objResponse; + } + + /* + Function: addCommand + + Used internally to add a command to the response command list. This + will call addPluginCommand> using the reference provided + in setResponse>. + */ + function addCommand($aAttributes, $sData) + { + $this->objResponse->addPluginCommand($this, $aAttributes, $sData); + } + + /* + Function: getName + + Called by the when the user script requests a plugin. + This name must match the plugin name requested in the called to + plugin>. + */ + function getName() + { +//SkipDebug + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXPLG:GNERR:01') + , E_USER_ERROR + ); +//EndSkipDebug + } + + /* + Function: process + + Called by when a user script requests the service of a + response plugin. The parameters provided by the user will be used to + determine which response command and parameters will be sent to the + client upon completion of the xajax request process. + */ + function process() + { +//SkipDebug + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXPLG:PERR:01') + , E_USER_ERROR + ); +//EndSkipDebug + } +} diff --git a/www/include/xajax/xajax_core/xajaxPluginManager.inc.php b/www/include/xajax/xajax_core/xajaxPluginManager.inc.php new file mode 100644 index 00000000..5a581911 --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxPluginManager.inc.php @@ -0,0 +1,717 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxPluginManager.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +//SkipAIO +require(dirname(__FILE__) . '/xajaxPlugin.inc.php'); +//EndSkipAIO + +/* + Class: xajaxPluginManager +*/ +final class xajaxPluginManager +{ + /* + Array: aRequestPlugins + */ + private $aRequestPlugins; + + /* + Array: aResponsePlugins + */ + private $aResponsePlugins; + + /* + Array: aConfigurable + */ + private $aConfigurable; + + /* + Array: aRegistrars + */ + private $aRegistrars; + + /* + Array: aProcessors + */ + private $aProcessors; + + /* + Array: aClientScriptGenerators + */ + private $aClientScriptGenerators; + + /* + Function: xajaxPluginManager + + Construct and initialize the one and only xajax plugin manager. + */ + + private $sJsURI; + public $aJsFiles = array(); + private $sDefer; + private $sRequestURI; + private $sStatusMessages; + private $sWaitCursor; + private $sVersion; + private $sDefaultMode; + private $sDefaultMethod; + private $bDebug; + private $bVerboseDebug; + private $nScriptLoadTimeout; + private $bUseUncompressedScripts; + private $bDeferScriptGeneration; + private $sLanguage; + private $nResponseQueueSize; + private $sDebugOutputID; + private $sResponseType; + + private function __construct() + { + $this->aRequestPlugins = array(); + $this->aResponsePlugins = array(); + + $this->aConfigurable = array(); + $this->aRegistrars = array(); + $this->aProcessors = array(); + $this->aClientScriptGenerators = array(); + + $this->sJsURI = ''; + $this->aJsFiles = array(); + $this->sDefer = ''; + $this->sRequestURI = ''; + $this->sStatusMessages = 'false'; + $this->sWaitCursor = 'true'; + $this->sVersion = 'unknown'; + $this->sDefaultMode = 'asynchronous'; + $this->sDefaultMethod = 'POST'; // W3C: Method is case sensitive + $this->bDebug = false; + $this->bVerboseDebug = false; + $this->nScriptLoadTimeout = 2000; + $this->bUseUncompressedScripts = false; + $this->bDeferScriptGeneration = false; + $this->sLanguage = null; + $this->nResponseQueueSize = null; + $this->sDebugOutputID = null; + } + + /* + Function: getInstance + + Implementation of the singleton pattern: returns the one and only instance of the + xajax plugin manager. + + Returns: + + object : a reference to the one and only instance of the + plugin manager. + */ + public static function &getInstance() + { + static $obj; + if (!$obj) { + $obj = new xajaxPluginManager(); + } + return $obj; + } + + /* + Function: loadPlugins + + Loads plugins from the folders specified. + + Parameters: + $aFolders - (array): Array of folders to check for plugins + */ + public function loadPlugins($aFolders) + { + foreach ($aFolders as $sFolder) { + if (is_dir($sFolder)) + if ($handle = opendir($sFolder)) { + while (!(false === ($sName = readdir($handle)))) { + $nLength = strlen($sName); + if (8 < $nLength) { + $sFileName = substr($sName, 0, $nLength - 8); + $sExtension = substr($sName, $nLength - 8, 8); + if ('.inc.php' == $sExtension) { + require $sFolder . '/' . $sFileName . $sExtension; + } + } + } + + closedir($handle); + } + } + } + + /* + Function: _insertIntoArray + + Inserts an entry into an array given the specified priority number. + If a plugin already exists with the given priority, the priority is + automatically incremented until a free spot is found. The plugin + is then inserted into the empty spot in the array. + + Parameters: + + $aPlugins - (array): Plugins array + $objPlugin - (object): A reference to an instance of a plugin. + $nPriority - (number): The desired priority, used to order + the plugins. + + */ + private function _insertIntoArray(&$aPlugins, $objPlugin, $nPriority) + { + while (isset($aPlugins[$nPriority])) + $nPriority++; + + $aPlugins[$nPriority] = $objPlugin; + } + + /* + Function: registerPlugin + + Registers a plugin. + + Parameters: + + objPlugin - (object): A reference to an instance of a plugin. + + Note: + Below is a table for priorities and their description: + 0 thru 999: Plugins that are part of or extensions to the xajax core + 1000 thru 8999: User created plugins, typically, these plugins don't care about order + 9000 thru 9999: Plugins that generally need to be last or near the end of the plugin list + */ + public function registerPlugin($objPlugin, $nPriority=1000) + { + if ($objPlugin instanceof xajaxRequestPlugin) + { + $this->_insertIntoArray($this->aRequestPlugins, $objPlugin, $nPriority); + + if (method_exists($objPlugin, 'register')) + $this->_insertIntoArray($this->aRegistrars, $objPlugin, $nPriority); + + if (method_exists($objPlugin, 'canProcessRequest')) + if (method_exists($objPlugin, 'processRequest')) + $this->_insertIntoArray($this->aProcessors, $objPlugin, $nPriority); + } + else if ( $objPlugin instanceof xajaxResponsePlugin) + { + $this->aResponsePlugins[] = $objPlugin; + } + else + { +//SkipDebug + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXPM:IPLGERR:01') + . get_class($objPlugin) + . $objLanguageManager->getText('XJXPM:IPLGERR:02') + , E_USER_ERROR + ); +//EndSkipDebug + } + + if (method_exists($objPlugin, 'configure')) + $this->_insertIntoArray($this->aConfigurable, $objPlugin, $nPriority); + + if (method_exists($objPlugin, 'generateClientScript')) + $this->_insertIntoArray($this->aClientScriptGenerators, $objPlugin, $nPriority); + } + + /* + Function: canProcessRequest + + Calls each of the request plugins and determines if the + current request can be processed by one of them. If no processor identifies + the current request, then the request must be for the initial page load. + + See canProcessRequest> for more information. + */ + public function canProcessRequest() + { + + $aKeys = array_keys($this->aProcessors); + sort($aKeys); + foreach ($aKeys as $sKey) { + $mResult = $this->aProcessors[$sKey]->canProcessRequest(); + if (true === $mResult) + return true; + else if (is_string($mResult)) + return $mResult; + } + return false; + } + + /* + Function: processRequest + + Calls each of the request plugins to request that they process the + current request. If the plugin processes the request, it will + return true. + */ + public function processRequest() + { + $bHandled = false; + + $aKeys = array_keys($this->aProcessors); + sort($aKeys); + foreach ($aKeys as $sKey) { + $mResult = $this->aProcessors[$sKey]->processRequest(); + if (true === $mResult) + $bHandled = true; + else if (is_string($mResult)) + return $mResult; + } + + return $bHandled; + } + + /* + Function: configure + + Call each of the request plugins passing along the configuration + setting specified. + + Parameters: + + sName - (string): The name of the configuration setting to set. + mValue - (mixed): The value to be set. + */ + public function configure($sName, $mValue) + { + + + $aKeys = array_keys($this->aConfigurable); + sort($aKeys); + foreach ($aKeys as $sKey) + $this->aConfigurable[$sKey]->configure($sName, $mValue); + + if ('javascript URI' == $sName) { + $this->sJsURI = $mValue; + } else if ("javascript files" == $sName) { + $this->aJsFiles = array_merge($this->aJsFiles,$mValue); + } else if ("scriptDefferal" == $sName) { + if (true === $mValue) $this->sDefer = "defer "; + else $this->sDefer = ""; + } else if ("requestURI" == $sName) { + $this->sRequestURI = $mValue; + } else if ("statusMessages" == $sName) { + if (true === $mValue) $this->sStatusMessages = "true"; + else $this->sStatusMessages = "false"; + } else if ("waitCursor" == $sName) { + if (true === $mValue) $this->sWaitCursor = "true"; + else $this->sWaitCursor = "false"; + } else if ("version" == $sName) { + $this->sVersion = $mValue; + } else if ("defaultMode" == $sName) { + if ("asynchronous" == $mValue || "synchronous" == $mValue) + $this->sDefaultMode = $mValue; + } else if ("defaultMethod" == $sName) { + if ("POST" == $mValue || "GET" == $mValue) // W3C: Method is case sensitive + $this->sDefaultMethod = $mValue; + } else if ("debug" == $sName) { + if (true === $mValue || false === $mValue) + $this->bDebug = $mValue; + } else if ("verboseDebug" == $sName) { + if (true === $mValue || false === $mValue) + $this->bVerboseDebug = $mValue; + } else if ("scriptLoadTimeout" == $sName) { + $this->nScriptLoadTimeout = $mValue; + } else if ("useUncompressedScripts" == $sName) { + if (true === $mValue || false === $mValue) + $this->bUseUncompressedScripts = $mValue; + } else if ('deferScriptGeneration' == $sName) { + if (true === $mValue || false === $mValue) + $this->bDeferScriptGeneration = $mValue; + else if ('deferred' == $mValue) + $this->bDeferScriptGeneration = $mValue; + } else if ('language' == $sName) { + $this->sLanguage = $mValue; + } else if ('responseQueueSize' == $sName) { + $this->nResponseQueueSize = $mValue; + } else if ('debugOutputID' == $sName) { + $this->sDebugOutputID = $mValue; + } else if ('responseType' == $sName) { + $this->sResponseType = $mValue; + } + + } + + /* + Function: register + + Call each of the request plugins and give them the opportunity to + handle the registration of the specified function, event or callable object. + + Parameters: + $aArgs - (array) : + */ + public function register($aArgs) + { + $aKeys = array_keys($this->aRegistrars); + sort($aKeys); + foreach ($aKeys as $sKey) + { + $objPlugin = $this->aRegistrars[$sKey]; + $mResult = $objPlugin->register($aArgs); + if ( $mResult instanceof xajaxRequest ) + return $mResult; + if (is_array($mResult)) + return $mResult; + if (is_bool($mResult)) + if (true === $mResult) + return true; + } +//SkipDebug + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXPM:MRMERR:01') + . print_r($aArgs, true) + , E_USER_ERROR + ); +//EndSkipDebug + } + + /* + Function: _getScriptFilename + + Returns the name of the script file, based on the current settings. + + sFilename - (string): The base filename. + + Returns: + + string - The filename as it should be specified in the script tags + on the browser. + */ + private function _getScriptFilename($sFilename) + { + if ($this->bUseUncompressedScripts) { + return str_replace('.js', '_uncompressed.js', $sFilename); + } + return $sFilename; + } + + /* + Function: generateClientScript + + Call each of the request and response plugins giving them the + opportunity to output some javascript to the page being generated. This + is called only when the page is being loaded initially. This is not + called when processing a request. + */ + public function generateClientScript() + { + + $sJsURI = $this->sJsURI; + + $aJsFiles = $this->aJsFiles; + + if ($sJsURI != '' && substr($sJsURI, -1) != '/') + $sJsURI .= '/'; + + if($this->bDeferScriptGeneration == true){ + $sJsURI .= 'xajax_js/'; + } + + $aJsFiles[] = array($this->_getScriptFilename('xajax_js/xajax_core.js'), 'xajax'); + + if (true === $this->bDebug) + $aJsFiles[] = array($this->_getScriptFilename('xajax_js/xajax_debug.js'), 'xajax.debug'); + + if (true === $this->bVerboseDebug) + $aJsFiles[] = array($this->_getScriptFilename('xajax_js/xajax_verbose.js'), 'xajax.debug.verbose'); + + if (null !== $this->sLanguage) + $aJsFiles[] = array($this->_getScriptFilename('xajax_js/xajax_lang_' . $this->sLanguage . '.js'), 'xajax'); + + $sCrLf = "\n"; + echo $sCrLf; + echo '<'; + echo 'script type="text/javascript" '; + echo $this->sDefer; + echo 'charset="UTF-8">'; + echo $sCrLf; + echo '/* <'; + echo '![CDATA[ */'; + echo $sCrLf; + echo 'try { if (undefined == typeof xajax.config) xajax.config = {}; } catch (e) { xajax = {}; xajax.config = {}; };'; + echo $sCrLf; + echo 'xajax.config.requestURI = "'; + echo $this->sRequestURI; + echo '";'; + echo $sCrLf; + echo 'xajax.config.statusMessages = '; + echo $this->sStatusMessages; + echo ';'; + echo $sCrLf; + echo 'xajax.config.waitCursor = '; + echo $this->sWaitCursor; + echo ';'; + echo $sCrLf; + echo 'xajax.config.version = "'; + echo $this->sVersion; + echo '";'; + echo $sCrLf; + echo 'xajax.config.defaultMode = "'; + echo $this->sDefaultMode; + echo '";'; + echo $sCrLf; + echo 'xajax.config.defaultMethod = "'; + echo $this->sDefaultMethod; + echo '";'; + echo $sCrLf; + echo 'xajax.config.JavaScriptURI = "'; + echo $this->sJsURI; + echo '";'; + echo $sCrLf; + echo 'xajax.config.responseType = "'; + echo $this->sResponseType; + echo '";'; + + if (false === (null === $this->nResponseQueueSize)) + { + echo $sCrLf; + echo 'xajax.config.responseQueueSize = '; + echo $this->nResponseQueueSize; + echo ';'; + } + + if (true === $this->bDebug) + { + if (false === (null === $this->sDebugOutputID)) + { + echo $sCrLf; + echo 'xajax.debug = {};'; + echo $sCrLf; + echo 'xajax.debug.outputID = "'; + echo $this->sDebugOutputID; + echo '";'; + } + } + if (0 < $this->nScriptLoadTimeout) { + foreach ($aJsFiles as $aJsFile) { + // echo '<'; + // echo 'script type="text/javascript" '; + // echo $this->sDefer; + // echo 'charset="UTF-8">'; + echo $sCrLf; + echo '/* <'; + echo '![CDATA[ */'; + echo $sCrLf; + echo 'window.setTimeout('; + echo $sCrLf; + echo ' function() {'; + echo $sCrLf; + echo ' var scriptExists = false;'; + echo $sCrLf; + echo ' try { if ('; + echo $aJsFile[1]; + echo '.isLoaded) scriptExists = true; }'; + echo $sCrLf; + echo ' catch (e) {}'; + echo $sCrLf; + echo ' if (!scriptExists) {'; + echo $sCrLf; + echo ' alert("Error: the '; + echo $aJsFile[1]; + echo ' Javascript component could not be included. Perhaps the URL is incorrect?\nURL: '; + echo $sJsURI; + echo $aJsFile[0]; + echo '");'; + echo $sCrLf; + echo ' }'; + echo $sCrLf; + echo ' }, '; + echo $this->nScriptLoadTimeout; + echo ');'; + echo $sCrLf; + // echo '/* ]]> */'; + // echo $sCrLf; + // echo '<'; + // echo '/script>'; + // echo $sCrLf; + } + } + + echo $sCrLf; + echo '/* ]]> */'; + echo $sCrLf; + echo '<'; + echo '/script>'; + echo $sCrLf; + + + if (true === $this->bDeferScriptGeneration) + { + + $sHash = $this->generateHash(); + + $sOutFile = $sHash.'.js'; + $sOutPath = dirname(dirname(__FILE__)).'/xajax_js/deferred/'; + + if (!is_file($sOutPath.$sOutFile) ) + { + ob_start(); + + + $sInPath = dirname(dirname(__FILE__)).'/'; + + foreach ($aJsFiles as $aJsFile) { + + print file_get_contents($sInPath.$aJsFile[0]); + } + print $sCrLf; + + print $this->printPluginScripts(); + + $sScriptCode = stripslashes(ob_get_clean()); + + require_once(dirname(__FILE__) . '/xajaxCompress.inc.php'); + $sScriptCode = xajaxCompressFile( $sScriptCode ); + + file_put_contents($sOutPath.$sOutFile,$sScriptCode); + } + + + + echo '<'; + echo 'script type="text/javascript" src="'; + echo $sJsURI; + echo 'deferred/'; + echo $sOutFile; + echo '" '; + echo $this->sDefer; + echo 'charset="UTF-8"><'; + echo '/script>'; + echo $sCrLf; + + + + } else { + + + + echo $sCrLf; + echo '<'; + echo 'script type="text/javascript" '; + echo $this->sDefer; + echo 'charset="UTF-8">'; + echo $sCrLf; + echo '/* <'; + echo '![CDATA[ */'; + echo $sCrLf; + + $this->printPluginScripts(); + + echo $sCrLf; + echo '/* ]]> */'; + echo $sCrLf; + echo '<'; + echo '/script>'; + echo $sCrLf; + + foreach ($aJsFiles as $aJsFile) { + echo '<'; + echo 'script type="text/javascript" src="'; + echo $sJsURI; + echo $aJsFile[0]; + echo '" '; + echo $this->sDefer; + echo 'charset="UTF-8"><'; + echo '/script>'; + echo $sCrLf; + } + } + } + + private function generateHash() + { + $aKeys = array_keys($this->aClientScriptGenerators); + sort($aKeys); + $sHash = ''; + foreach ($aKeys as $sKey) + { + $sHash .= $this->aClientScriptGenerators[$sKey]->generateHash(); + } + return md5($sHash); + } + + private function printPluginScripts() + { + $aKeys = array_keys($this->aClientScriptGenerators); + sort($aKeys); + foreach ($aKeys as $sKey) + { + $this->aClientScriptGenerators[$sKey]->generateClientScript(); + } + } + + /* + Function: getResponsePlugin + + Locate the specified response plugin by name and return + a reference to it if one exists. + + Parameters: + $sName - (string): Name of the plugin. + + Returns: + mixed : Returns plugin or false if not found. + */ + public function getResponsePlugin($sName) + { + $aKeys = array_keys($this->aResponsePlugins); + sort($aKeys); + foreach ($aKeys as $sKey) + if ( $this->aResponsePlugins[$sKey] instanceof $sName ) + return $this->aResponsePlugins[$sKey]; + $bFailure = false; + return $bFailure; + } + + /* + Function: getRequestPlugin + + Locate the specified response plugin by name and return + a reference to it if one exists. + + Parameters: + $sName - (string): Name of the plugin. + + Returns: + mixed : Returns plugin or false if not found. + */ + public function getRequestPlugin($sName) + { + $aKeys = array_keys($this->aRequestPlugins); + sort($aKeys); + foreach ($aKeys as $sKey) { + if ( get_class($this->aRequestPlugins[$sKey]) == $sName ) { + return $this->aRequestPlugins[$sKey]; + } + } + + + $bFailure = false; + return $bFailure; + } +} diff --git a/www/include/xajax/xajax_core/xajaxRequest.inc.php b/www/include/xajax/xajax_core/xajaxRequest.inc.php new file mode 100644 index 00000000..706ebbfd --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxRequest.inc.php @@ -0,0 +1,359 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxRequest.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Constant: XAJAX_FORM_VALUES + Specifies that the parameter will consist of an array of form values. +*/ +if (!defined ('XAJAX_FORM_VALUES')) define ('XAJAX_FORM_VALUES', 'get form values'); +/* + Constant: XAJAX_INPUT_VALUE + Specifies that the parameter will contain the value of an input control. +*/ +if (!defined ('XAJAX_INPUT_VALUE')) define ('XAJAX_INPUT_VALUE', 'get input value'); +/* + Constant: XAJAX_CHECKED_VALUE + Specifies that the parameter will consist of a boolean value of a checkbox. +*/ +if (!defined ('XAJAX_CHECKED_VALUE')) define ('XAJAX_CHECKED_VALUE', 'get checked value'); +/* + Constant: XAJAX_ELEMENT_INNERHTML + Specifies that the parameter value will be the innerHTML value of the element. +*/ +if (!defined ('XAJAX_ELEMENT_INNERHTML')) define ('XAJAX_ELEMENT_INNERHTML', 'get element innerHTML'); +/* + Constant: XAJAX_QUOTED_VALUE + Specifies that the parameter will be a quoted value (string). +*/ +if (!defined ('XAJAX_QUOTED_VALUE')) define ('XAJAX_QUOTED_VALUE', 'quoted value'); +/* + Constant: XAJAX_JS_VALUE + Specifies that the parameter will be a non-quoted value (evaluated by the + browsers javascript engine at run time. +*/ +if (!defined ('XAJAX_JS_VALUE')) define ('XAJAX_JS_VALUE', 'unquoted value'); + +/* + Class: xajaxRequest + + Used to store and generate the client script necessary to invoke + a xajax request from the browser to the server script. + + This object is typically generated by the register> method + and can be used to quickly generate the javascript that is used + to initiate a xajax request to the registered function, object, event + or other xajax call. +*/ +class xajaxRequest +{ + /* + String: sName + + The name of the function. + */ + private $sName; + + /* + String: sQuoteCharacter + + A string containing either a single or a double quote character + that will be used during the generation of the javascript for + this function. This can be set prior to calling printScript> + */ + private $sQuoteCharacter; + + /* + Array: aParameters + + An array of parameters that will be used to populate the argument list + for this function when the javascript is output in printScript> + */ + private $aParameters; + + /* + Function: xajaxRequest + + Construct and initialize this request. + + sName - (string): The name of this request. + */ + public function __construct($sName) + { + $this->aParameters = array(); + $this->sQuoteCharacter = '"'; + $this->sName = $sName; + } + + /* + Function: useSingleQuote + + Call this to instruct the request to use single quotes when generating + the javascript. + */ + public function useSingleQuote() + { + $this->sQuoteCharacter = "'"; + } + + /* + Function: useDoubleQuote + + Call this to instruct the request to use double quotes while generating + the javascript. + */ + public function useDoubleQuote() + { + $this->sQuoteCharacter = '"'; + } + + /* + Function: clearParameters + + Clears the parameter list associated with this request. + */ + public function clearParameters() + { + $this->aParameters = array(); + } + + /* + Function: addParameter + + Adds a parameter value to the parameter list for this request. + + sType - (string): The type of the value to be used. + sValue - (string: The value to be used. + + See Also: + See setParameter> for details. + */ + public function addParameter() + { + $aArgs = func_get_args(); + + if (1 < count($aArgs)) + $this->setParameter( + count($this->aParameters), + $aArgs[0], + $aArgs[1]); + } + + /* + Function: setParameter + + Sets a specific parameter value. + + Parameters: + + nParameter - (number): The index of the parameter to set + sType - (string): The type of value + sValue - (string): The value as it relates to the specified type + + Note: + + Types should be one of the following , , + , , . + The value should be as follows: + - Use the ID of the form you want to process. + - The string data to be passed. + - A string containing valid javascript (either a javascript + variable name that will be in scope at the time of the call or a + javascript function call whose return value will become the parameter. + + */ + public function setParameter() + { + $aArgs = func_get_args(); + + if (2 < count($aArgs)) + { + $nParameter = $aArgs[0]; + $sType = $aArgs[1]; + + if (XAJAX_FORM_VALUES == $sType) + { + $sFormID = $aArgs[2]; + $this->aParameters[$nParameter] = + "xajax.getFormValues(" + . $this->sQuoteCharacter + . $sFormID + . $this->sQuoteCharacter + . ")"; + } + else if (XAJAX_INPUT_VALUE == $sType) + { + $sInputID = $aArgs[2]; + $this->aParameters[$nParameter] = + "xajax.$(" + . $this->sQuoteCharacter + . $sInputID + . $this->sQuoteCharacter + . ").value"; + } + else if (XAJAX_CHECKED_VALUE == $sType) + { + $sCheckedID = $aArgs[2]; + $this->aParameters[$nParameter] = + "xajax.$(" + . $this->sQuoteCharacter + . $sCheckedID + . $this->sQuoteCharacter + . ").checked"; + } + else if (XAJAX_ELEMENT_INNERHTML == $sType) + { + $sElementID = $aArgs[2]; + $this->aParameters[$nParameter] = + "xajax.$(" + . $this->sQuoteCharacter + . $sElementID + . $this->sQuoteCharacter + . ").innerHTML"; + } + else if (XAJAX_QUOTED_VALUE == $sType) + { + $sValue = $aArgs[2]; + $this->aParameters[$nParameter] = + $this->sQuoteCharacter + . $sValue + . $this->sQuoteCharacter; + } + else if (XAJAX_JS_VALUE == $sType) + { + $sValue = $aArgs[2]; + $this->aParameters[$nParameter] = $sValue; + } + } + } + + /* + Function: getScript + + Returns a string representation of the script output (javascript) from + this request object. See also: + */ + public function getScript() + { + ob_start(); + $this->printScript(); + return ob_get_clean(); + } + + /* + Function: printScript + + Generates a block of javascript code that can be used to invoke + the specified xajax request. + */ + public function printScript() + { + echo $this->sName; + echo '('; + + $sSeparator = ''; + + foreach ($this->aParameters as $sParameter) + { + echo $sSeparator; + echo $sParameter; + $sSeparator = ', '; + } + + echo ')'; + } +} + +/* + Class: xajaxCustomRequest + + This class extends the class such that simple javascript + can be put in place of a xajax request to the server. The primary purpose + of this class is to provide simple scripting services to the + based objects, like , and . +*/ +class xajaxCustomRequest extends xajaxRequest +{ + /* + Array: aVariables; + */ + var $aVariables; + + /* + String: sScript; + */ + var $sScript; + + /* + Function: xajaxCustomRequest + + Constructs and initializes an instance of the object. + + Parameters: + + sScript - (string): The javascript (template) that will be printed + upon request. + aVariables - (associative array, optional): An array of variable name, + value pairs that will be passed to setVariable> + */ + function __construct($sScript) + { + $this->aVariables = array(); + $this->sScript = $sScript; + } + + /* + Function: clearVariables + + Clears the array of variables that will be used to modify the script before + it is printed and sent to the client. + */ + function clearVariables() + { + $this->aVariables = array(); + } + + /* + Function: setVariable + + Sets a value that will be used to modify the script before it is sent to + the browser. The object will perform a string + replace operation on each of the values set with this function. + + Parameters: + $sName - (string): Variable name + $sValue - (string): Value + + */ + function setVariable($sName, $sValue) + { + $this->aVariables[$sName] = $sValue; + } + + /* + Function: printScript + */ + function printScript() + { + $sScript = $this->sScript; + foreach ($this->aVariables as $sKey => $sValue) + $sScript = str_replace($sKey, $sValue, $sScript); + echo $sScript; + } +} diff --git a/www/include/xajax/xajax_core/xajaxResponse.inc.php b/www/include/xajax/xajax_core/xajaxResponse.inc.php new file mode 100644 index 00000000..3deadf56 --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxResponse.inc.php @@ -0,0 +1,2076 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxResponse.inc.php 361 2007-05-24 12:48:14Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajaxResponse + + Collect commands to be sent back to the browser in response to a xajax + request. Commands are encoded and packaged in a format that is acceptable + to the response handler from the javascript library running on the client + side. + + Common commands include: + - assign>: Assign a value to an elements property. + - append>: Append a value on to an elements property. + - script>: Execute a portion of javascript code. + - call>: Execute an existing javascript function. + - alert>: Display an alert dialog to the user. + + Elements are identified by the value of the HTML id attribute. If you do + not see your updates occuring on the browser side, ensure that you are + using the correct id in your response. +*/ +class xajaxResponse +{ + /* + Array: aCommands + + Stores the commands that will be sent to the browser in the response. + */ + public $aCommands; + + /* + String: sCharacterEncoding + + The name of the encoding method you wish to use when dealing with + special characters. See setEncoding> for more information. + */ + private $sCharacterEncoding; + + /* + Boolean: bOutputEntities + + Convert special characters to the HTML equivellent. See also + bOutputEntities> and configure>. + */ + private $bOutputEntities; + + /* + Mixed: returnValue + + A string, array or integer value to be returned to the caller when + using 'synchronous' mode requests. See setMode> for details. + */ + private $returnValue; + + /* + Object: objPluginManager + + A reference to the global plugin manager. + */ + private $objPluginManager; + + // sorry but this config is static atm + private $sContentType = 'application/json'; //'text/xml'; + + /* + Constructor: xajaxResponse + + Create and initialize a xajaxResponse object. + */ + public function __construct() + { + //SkipDebug + if (0 < func_num_args()) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:EDERR:01') + , E_USER_ERROR + ); + } + //EndSkipDebug + + $this->aCommands = array(); + + $objResponseManager = xajaxResponseManager::getInstance(); + + $this->sCharacterEncoding = $objResponseManager->getCharacterEncoding(); + $this->bOutputEntities = $objResponseManager->getOutputEntities(); + $this->setResponseType($objResponseManager->getConfiguration('responseType')); + + $this->objPluginManager = xajaxPluginManager::getInstance(); + } + + function getResponseType() + { + return $this->sResponseType; + } + + function setResponseType($sResponseType) { + + if (NULL == $sResponseType) return; + + $this->sResponseType = $sResponseType ; + + if ('XML' == $sResponseType) { + $this->setContentType('text/xml'); + } + elseif ('JSON' == $sResponseType) { + $this->setContentType('application/json'); + } + } + + + /* + Function: setCharacterEncoding + + Overrides the default character encoding (or the one specified in the + constructor) to the specified character encoding. + + Parameters: + + sCharacterEncoding - (string): The encoding method to use for this response. + + See also, xajaxResponse>() + + Returns: + + object - The xajaxResponse object. + */ + public function setCharacterEncoding($sCharacterEncoding) + { + $this->sCharacterEncoding = $sCharacterEncoding; + return $this; + } + + + /* + Function: setOutputEntities + + Convert special characters to their HTML equivellent automatically + (only works if the mb_string extension is available). + + Parameters: + + bOption - (boolean): Convert special characters + + Returns: + + object - The xajaxResponse object. + */ + public function setOutputEntities($bOutputEntities) + { + $this->bOutputEntities = (boolean)$bOutputEntities; + return $this; + } + + /* + Function: plugin + + Provides access to registered response plugins. If you are using PHP + 4 or 5, pass the plugin name as the first argument, the plugin method + name as the second argument and subsequent arguments (if any) to be + passed along to the plugin. + + Optionally, if you use PHP 5, you can pass just the plugin name as the + first argument and the plugin object will be returned. You can then + access the methods of the plugin directly. + + Parameters: + + sName - (string): Name of the plugin. + sFunction - (string, optional): The name of the method to call. + arg1...argn - (mixed, optional): Additional arguments to pass on to + the plugin function. + + Returns: + + object - The plugin specified by sName. + */ + public function plugin() + { + $aArgs = func_get_args(); + $nArgs = func_num_args(); + + //SkipDebug + if (false == (0 < $nArgs)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:MPERR:01') + , E_USER_ERROR + ); + } + //EndSkipDebug + + $sName = array_shift($aArgs); + + $objPlugin = $this->objPluginManager->getResponsePlugin($sName); + + if (false === $objPlugin) + { + $bReturn = false; + return $bReturn; + } + + $objPlugin->setResponse($this); + + if (0 < count($aArgs)) + { + $sMethod = array_shift($aArgs); + + $aFunction = array($objPlugin, $sMethod); + call_user_func_array($aFunction, $aArgs); + } + + return $objPlugin; + } + + /* + Function: __get + + Magic function for PHP 5. Used to permit plugins to be called as if they + where native members of the xajaxResponse instance. + + Parameters: + + sPluginName - (string): The name of the plugin. + + Returns: + + object - The plugin specified by sPluginName. + */ + public function __get($sPluginName) + { + $objPlugin = $this->plugin($sPluginName); + return $objPlugin; + } + + /* + Function: confirmCommands + + Response command that prompts user with [ok] [cancel] style + message box. If the user clicks cancel, the specified + number of response commands following this one, will be + skipped. + + Parameters: + + iCmdNumber - (integer): The number of commands to skip upon cancel. + sMessage - (string): The message to display to the user. + + Returns: + + object : The xajaxResponse object. + */ + public function confirmCommands($iCmdNumber, $sMessage) + { + return $this->addCommand( + array( + 'cmd'=>'cc', + 'id'=>$iCmdNumber + ), + $sMessage + ); + } + + /* + Function: assign + + Response command indicating that the specified value should be + assigned to the given element's attribute. + + Parameters: + + sTarget - (string): The id of the html element on the browser. + sAttribute - (string): The property to be assigned. + sData - (string): The value to be assigned to the property. + + Returns: + + object : The object. + + */ + public function assign($sTarget,$sAttribute,$sData) + { + return $this->addCommand( + array( + 'cmd'=>'as', + 'id'=>$sTarget, + 'prop'=>$sAttribute + ), + $sData + ); + } + + /* + Function: append + + Response command that indicates the specified data should be appended + to the given element's property. + + Parameters: + + sTarget - (string): The id of the element to be updated. + sAttribute - (string): The name of the property to be appended to. + sData - (string): The data to be appended to the property. + + Returns: + + object : The object. + */ + public function append($sTarget,$sAttribute,$sData) + { + return $this->addCommand( + array( + 'cmd'=>'ap', + 'id'=>$sTarget, + 'prop'=>$sAttribute + ), + $sData + ); + } + + /* + Function: prepend + + Response command to prepend the specified value onto the given + element's property. + + Parameters: + + sTarget - (string): The id of the element to be updated. + sAttribute - (string): The property to be updated. + sData - (string): The value to be prepended. + + Returns: + + object : The object. + */ + public function prepend($sTarget,$sAttribute,$sData) + { + return $this->addCommand( + array( + 'cmd'=>'pp', + 'id'=>$sTarget, + 'prop'=>$sAttribute + ), + $sData + ); + } + + /* + Function: replace + + Replace a specified value with another value within the given + element's property. + + Parameters: + + sTarget - (string): The id of the element to update. + sAttribute - (string): The property to be updated. + sSearch - (string): The needle to search for. + sData - (string): The data to use in place of the needle. + */ + public function replace($sTarget,$sAttribute,$sSearch,$sData) + { + return $this->addCommand( + array( + 'cmd'=>'rp', + 'id'=>$sTarget, + 'prop'=>$sAttribute + ), + array( + 's' => $sSearch, + 'r' => $sData + ) + ); + } + + /* + Function: clear + + Response command used to clear the specified property of the + given element. + + Parameters: + + sTarget - (string): The id of the element to be updated. + sAttribute - (string): The property to be clared. + + Returns: + + object - The object. + */ + public function clear($sTarget,$sAttribute) + { + return $this->assign( + $sTarget, + $sAttribute, + '' + ); + } + + /* + Function: contextAssign + + Response command used to assign a value to a member of a + javascript object (or element) that is specified by the context + member of the request. The object is referenced using the 'this' keyword + in the sAttribute parameter. + + Parameters: + + sAttribute - (string): The property to be updated. + sData - (string): The value to assign. + + Returns: + + object : The object. + */ + public function contextAssign($sAttribute, $sData) + { + return $this->addCommand( + array( + 'cmd'=>'c:as', + 'prop'=>$sAttribute + ), + $sData + ); + } + + /* + Function: contextAppend + + Response command used to append a value onto the specified member + of the javascript context object (or element) specified by the context + member of the request. The object is referenced using the 'this' keyword + in the sAttribute parameter. + + Parameters: + + sAttribute - (string): The member to be appended to. + sData - (string): The value to append. + + Returns: + + object : The object. + */ + public function contextAppend($sAttribute, $sData) + { + return $this->addCommand( + array( + 'cmd'=>'c:ap', + 'prop'=>$sAttribute + ), + $sData + ); + } + + /* + Function: contextPrepend + + Response command used to prepend the speicified data to the given + member of the current javascript object specified by context in the + current request. The object is access via the 'this' keyword in the + sAttribute parameter. + + Parameters: + + sAttribute - (string): The member to be updated. + sData - (string): The value to be prepended. + + Returns: + + object : The object. + */ + public function contextPrepend($sAttribute, $sData) + { + return $this->addCommand( + array( + 'cmd'=>'c:pp', + 'prop'=>$sAttribute + ), + $sData + ); + } + + /* + Function: contextClear + + Response command used to clear the value of the property specified + in the sAttribute parameter. The member is access via the 'this' + keyword and can be used to update a javascript object specified + by context in the request parameters. + + Parameters: + + sAttribute - (string): The member to be cleared. + + Returns: + + object : The object. + */ + public function contextClear($sAttribute) + { + return $this->contextAssign( + $sAttribute, + '' + ); + } + + /* + Function: alert + + Response command that is used to display an alert message to the user. + + Parameters: + + sMsg - (string): The message to be displayed. + + Returns: + + object : The object. + */ + public function alert($sMsg) + { + return $this->addCommand( + array( + 'cmd'=>'al' + ), + $sMsg + ); + } + + public function debug($sMessage) + { + return $this->addCommand( + array( + 'cmd'=>'dbg' + ), + $sMessage + ); + } + + /* + Function: redirect + + Response command that causes the browser to navigate to the specified + URL. + + Parameters: + + sURL - (string): The relative or fully qualified URL. + iDelay - (integer, optional): Number of seconds to delay before + the redirect occurs. + + Returns: + + object : The object. + */ + public function redirect($sURL, $iDelay=0) + { + //we need to parse the query part so that the values are rawurlencode()'ed + //can't just use parse_url() cos we could be dealing with a relative URL which + // parse_url() can't deal with. + $queryStart = strpos($sURL, '?', strrpos($sURL, '/')); + if ($queryStart !== FALSE) + { + $queryStart++; + $queryEnd = strpos($sURL, '#', $queryStart); + if ($queryEnd === FALSE) + $queryEnd = strlen($sURL); + $queryPart = substr($sURL, $queryStart, $queryEnd-$queryStart); + parse_str($queryPart, $queryParts); + $newQueryPart = ""; + if ($queryParts) + { + $first = true; + foreach($queryParts as $key => $value) + { + if ($first) + $first = false; + else + $newQueryPart .= '&'; + $newQueryPart .= rawurlencode($key).'='.rawurlencode($value); + } + } else if ($_SERVER['QUERY_STRING']) { + //couldn't break up the query, but there's one there + //possibly "http://url/page.html?query1234" type of query? + //just encode it and hope it works + $newQueryPart = rawurlencode($_SERVER['QUERY_STRING']); + } + $sURL = str_replace($queryPart, $newQueryPart, $sURL); + } + if ($iDelay) + $this->script( + 'window.setTimeout("window.location = \'' + . $sURL + . '\';",' + . ($iDelay*1000) + . ');' + ); + else + $this->script( + 'window.location = "' + . $sURL + . '";' + ); + return $this; + } + + /* + Function: script + + Response command that is used to execute a portion of javascript on + the browser. The script runs in it's own context, so variables declared + locally, using the 'var' keyword, will no longer be available after the + call. To construct a variable that will be accessable globally, even + after the script has executed, leave off the 'var' keyword. + + Parameters: + + sJS - (string): The script to execute. + + Returns: + + object : The object. + */ + public function script($sJS) + { + return $this->addCommand( + array( + 'cmd'=>'js' + ), + $sJS + ); + } + + /* + Function: call + + Response command that indicates that the specified javascript + function should be called with the given (optional) parameters. + + Parameters: + + arg1 - (string): The name of the function to call. + arg2 .. argn : arguments to be passed to the function. + + Returns: + + object : The object. + */ + public function call() { + $aArgs = func_get_args(); + $sFunc = array_shift($aArgs); + return $this->addCommand( + array( + 'cmd'=>'jc', + 'func'=>$sFunc + ), + $aArgs + ); + } + + /* + Function: remove + + Response command used to remove an element from the document. + + Parameters: + + sTarget - (string): The id of the element to be removed. + + Returns: + + object : The object. + */ + public function remove($sTarget) + { + return $this->addCommand( + array( + 'cmd'=>'rm', + 'id'=>$sTarget), + '' + ); + } + + /* + Function: create + + Response command used to create a new element on the browser. + + Parameters: + + sParent - (string): The id of the parent element. + sTag - (string): The tag name to be used for the new element. + sId - (string): The id to assign to the new element. + + + Returns: + + object : The object. + */ + + public function create($sParent, $sTag, $sId) + { + + + return $this->addCommand( + array( + 'cmd'=>'ce', + 'id'=>$sParent, + 'prop'=>$sId + ), + $sTag + ); + } + + /* + Function: insert + + Response command used to insert a new element just prior to the specified + element. + + Parameters: + + sBefore - (string): The element used as a reference point for the + insertion. + sTag - (string): The tag to be used for the new element. + sId - (string): The id to be used for the new element. + + Returns: + + object : The object. + */ + public function insert($sBefore, $sTag, $sId) + { + return $this->addCommand( + array( + 'cmd'=>'ie', + 'id'=>$sBefore, + 'prop'=>$sId + ), + $sTag + ); + } + + /* + Function: insertAfter + + Response command used to insert a new element after the specified + one. + + Parameters: + + sAfter - (string): The id of the element that will be used as a reference + for the insertion. + sTag - (string): The tag name to be used for the new element. + sId - (string): The id to be used for the new element. + + Returns: + + object : The object. + */ + public function insertAfter($sAfter, $sTag, $sId) + { + return $this->addCommand( + array( + 'cmd'=>'ia', + 'id'=>$sAfter, + 'prop'=>$sId + ), + $sTag + ); + } + + /* + Function: createInput + + Response command used to create an input element on the browser. + + Parameters: + + sParent - (string): The id of the parent element. + sType - (string): The type of the new input element. + sName - (string): The name of the new input element. + sId - (string): The id of the new element. + + Returns: + + object : The object. + */ + public function createInput($sParent, $sType, $sName, $sId) + { + return $this->addCommand( + array( + 'cmd'=>'ci', + 'id'=>$sParent, + 'prop'=>$sId, + 'type'=>$sType + ), + $sName + ); + } + + /* + Function: insertInput + + Response command used to insert a new input element preceeding the + specified element. + + Parameters: + + sBefore - (string): The id of the element to be used as the reference + point for the insertion. + sType - (string): The type of the new input element. + sName - (string): The name of the new input element. + sId - (string): The id of the new input element. + + Returns: + + object : The object. + */ + public function insertInput($sBefore, $sType, $sName, $sId) + { + return $this->addCommand( + array( + 'cmd'=>'ii', + 'id'=>$sBefore, + 'prop'=>$sId, + 'type'=>$sType + ), + $sName + ); + } + + /* + Function: insertInputAfter + + Response command used to insert a new input element after the + specified element. + + Parameters: + + sAfter - (string): The id of the element that is to be used + as the insertion point for the new element. + sType - (string): The type of the new input element. + sName - (string): The name of the new input element. + sId - (string): The id of the new input element. + + Returns: + + object : The object. + */ + public function insertInputAfter($sAfter, $sType, $sName, $sId) + { + return $this->addCommand( + array( + 'cmd'=>'iia', + 'id'=>$sAfter, + 'prop'=>$sId, + 'type'=>$sType + ), + $sName + ); + } + + /* + Function: setEvent + + Response command used to set an event handler on the browser. + + Parameters: + + sTarget - (string): The id of the element that contains the event. + sEvent - (string): The name of the event. + sScript - (string): The javascript to execute when the event is fired. + + Returns: + + object : The object. + */ + public function setEvent($sTarget,$sEvent,$sScript) + { + return $this->addCommand( + array( + 'cmd'=>'ev', + 'id'=>$sTarget, + 'prop'=>$sEvent + ), + $sScript + ); + } + + + /* + Function: addEvent + + Response command used to set an event handler on the browser. + + Parameters: + + sTarget - (string): The id of the element that contains the event. + sEvent - (string): The name of the event. + sScript - (string): The javascript to execute when the event is fired. + + Returns: + + object : The object. + + Note: + + This function is depreciated and will be removed in a future version. + Use instead. + */ + public function addEvent($sTarget,$sEvent,$sScript) + { + return $this->setEvent( + $sTarget, + $sEvent, + $sScript + ); + } + + /* + Function: addHandler + + Response command used to install an event handler on the specified element. + + Parameters: + + sTarget - (string): The id of the element. + sEvent - (string): The name of the event to add the handler to. + sHandler - (string): The javascript function to call when the event is fired. + + You can add more than one event handler to an element's event using this method. + + Returns: + + object - The object. + */ + public function addHandler($sTarget,$sEvent,$sHandler) + { + return $this->addCommand( + array( + 'cmd'=>'ah', + 'id'=>$sTarget, + 'prop'=>$sEvent + ), + $sHandler + ); + } + + /* + Function: removeHandler + + Response command used to remove an event handler from an element. + + Parameters: + + sTarget - (string): The id of the element. + sEvent - (string): The name of the event. + sHandler - (string): The javascript function that is called when the + event is fired. + + Returns: + + object : The object. + */ + public function removeHandler($sTarget,$sEvent,$sHandler) + { + return $this->addCommand( + array( + 'cmd'=>'rh', + 'id'=>$sTarget, + 'prop'=>$sEvent + ), + $sHandler); + } + + /* + Function: setFunction + + Response command used to construct a javascript function on the browser. + + Parameters: + + sFunction - (string): The name of the function to construct. + sArgs - (string): Comma separated list of parameter names. + sScript - (string): The javascript code that will become the body of the + function. + + Returns: + + object : The object. + */ + public function setFunction($sFunction, $sArgs, $sScript) + { + return $this->addCommand( + array( + 'cmd'=>'sf', + 'func'=>$sFunction, + 'prop'=>$sArgs + ), + $sScript + ); + } + + /* + Function: wrapFunction + + Response command used to construct a wrapper function around + and existing javascript function on the browser. + + Parameters: + + sFunction - (string): The name of the existing function to wrap. + sArgs - (string): The comma separated list of parameters for the function. + aScripts - (array): An array of javascript code snippets that will + be used to build the body of the function. The first piece of code + specified in the array will occur before the call to the original + function, the second will occur after the original function is called. + sReturnValueVariable - (string): The name of the variable that will + retain the return value from the call to the original function. + + Returns: + + object : The object. + */ + public function wrapFunction($sFunction, $sArgs, $aScripts, $sReturnValueVariable) + { + return $this->addCommand( + array( + 'cmd'=>'wpf', + 'func'=>$sFunction, + 'prop'=>$sArgs, + 'type'=>$sReturnValueVariable + ), + $aScripts + ); + } + + /* + Function: includeScript + + Response command used to load a javascript file on the browser. + + Parameters: + + sFileName - (string): The relative or fully qualified URI of the + javascript file. + + sType - (string): Determines the script type . Defaults to 'text/javascript'. + + + Returns: + + object : The object. + */ + public function includeScript($sFileName, $sType = null, $sId = null) + { + $command = array('cmd' => 'in'); + + if (false === (null === $sType)) + $command['type'] = $sType; + + if (false === (null === $sId)) + $command['elm_id'] = $sId; + + return $this->addCommand( + $command, + $sFileName + ); + } + + /* + Function: includeScriptOnce + + Response command used to include a javascript file on the browser + if it has not already been loaded. + + Parameters: + + sFileName - (string): The relative for fully qualified URI of the + javascript file. + + sType - (string): Determines the script type . Defaults to 'text/javascript'. + + Returns: + + object : The object. + */ + public function includeScriptOnce($sFileName, $sType = null, $sId = null) + { + $command = array('cmd' => 'ino'); + + if (false === (null === $sType)) + $command['type'] = $sType; + + if (false === (null === $sId)) + $command['elm_id'] = $sId; + + return $this->addCommand( + $command, + $sFileName + ); + } + + /* + Function: removeScript + + Response command used to remove a SCRIPT reference to a javascript + file on the browser. Optionally, you can call a javascript function + just prior to the file being unloaded (for cleanup). + + Parameters: + + sFileName - (string): The relative or fully qualified URI of the + javascript file. + sUnload - (string): Name of a javascript function to call prior + to unlaoding the file. + + Returns: + + object : The object. + */ + public function removeScript($sFileName, $sUnload = '') { + $this->addCommand( + array( + 'cmd'=>'rjs', + 'unld'=>$sUnload + ), + $sFileName + ); + return $this; + } + + /* + Function: includeCSS + + Response command used to include a LINK reference to + the specified CSS file on the browser. This will cause the + browser to load and apply the style sheet. + + Parameters: + + sFileName - (string): The relative or fully qualified URI of + the css file. + + sMedia - (string): Determines the media type of the CSS file. Defaults to 'screen'. + + Returns: + + object : The object. + */ + public function includeCSS($sFileName, $sMedia = null) + { + $command = array('cmd' => 'css'); + + if (false === (null === $sMedia)) + $command['media'] = $sMedia; + + return $this->addCommand( + $command, + $sFileName + ); + } + + /* + Function: removeCSS + + Response command used to remove a LINK reference to + a CSS file on the browser. This causes the browser to + unload the style sheet, effectively removing the style + changes it caused. + + Parameters: + + sFileName - (string): The relative or fully qualified URI + of the css file. + + Returns: + + object : The object. + */ + public function removeCSS($sFileName, $sMedia = null) + { + $command = array('cmd'=>'rcss'); + + if (false === (null === $sMedia)) + $command['media'] = $sMedia; + + return $this->addCommand( + $command, + $sFileName + ); + } + + /* + Function: waitForCSS + + Response command instructing xajax to pause while the CSS + files are loaded. The browser is not typically a multi-threading + application, with regards to javascript code. Therefore, the + CSS files included or removed with includeCSS> and + removeCSS> respectively, will not be loaded or + removed until the browser regains control from the script. This + command returns control back to the browser and pauses the execution + of the response until the CSS files, included previously, are + loaded. + + Parameters: + + iTimeout - (integer): The number of 1/10ths of a second to pause + before timing out and continuing with the execution of the + response commands. + + Returns: + + object : The object. + */ + public function waitForCSS($iTimeout = 600) { + $sData = ""; + $this->addCommand( + array( + 'cmd'=>'wcss', + 'prop'=>$iTimeout + ), + $sData + ); + return $this; + } + + /* + Function: waitFor + + Response command instructing xajax to delay execution of the response + commands until a specified condition is met. Note, this returns control + to the browser, so that other script operations can execute. xajax + will continue to monitor the specified condition and, when it evaulates + to true, will continue processing response commands. + + Parameters: + + script - (string): A piece of javascript code that evaulates to true + or false. + tenths - (integer): The number of 1/10ths of a second to wait before + timing out and continuing with the execution of the response + commands. + + Returns: + + object : The object. + */ + public function waitFor($script, $tenths) { + return $this->addCommand( + array( + 'cmd'=>'wf', + 'prop'=>$tenths + ), + $script + ); + } + + /* + Function: sleep + + Response command which instructs xajax to pause execution + of the response commands, returning control to the browser + so it can perform other commands asynchronously. After + the specified delay, xajax will continue execution of the + response commands. + + Parameters: + + tenths - (integer): The number of 1/10ths of a second to + sleep. + + Returns: + + object : The object. + */ + public function sleep($tenths) { + $this->addCommand( + array( + 'cmd'=>'s', + 'prop'=>$tenths + ), + '' + ); + return $this; + } + + public function domStartResponse() + { + $this->script('xjxElm = []'); + } + + public function domCreateElement($variable, $tag) + { + return $this->addCommand( + array( + 'cmd' => 'DCE', + 'tgt' => $variable + ), + $tag + ); + } + + public function domSetAttribute($variable, $key, $value) + { + return $this->addCommand( + array( + 'cmd' => 'DSA', + 'tgt' => $variable, + 'key' => $key + ), + $value + ); + } + + public function domRemoveChildren($parent, $skip=null, $remove=null) + { + $command = array( + 'cmd' => 'DRC' + ); + + if ($skip != null) + $command['skip'] = $skip; + + if ($remove != null) + $command['remove'] = $remove; + + return $this->addCommand( + $command, + $parent + ); + } + + public function domAppendChild($parent, $variable) + { + return $this->addCommand( + array( + 'cmd' => 'DAC', + 'par' => $parent + ), + $variable + ); + } + + public function domInsertBefore($target, $variable) + { + return $this->addCommand( + array( + 'cmd' => 'DIB', + 'tgt' => $target + ), + $variable + ); + } + + public function domInsertAfter($target, $variable) + { + return $this->addCommand( + array( + 'cmd' => 'DIA', + 'tgt' => $target + ), + $variable + ); + } + + public function domAppendText($parent, $text) + { + return $this->addCommand( + array( + 'cmd' => 'DAT', + 'par' => $parent + ), + $text + ); + } + + public function domEndResponse() + { + $this->script('xjxElm = []'); + } + + /* + Function: setReturnValue + + Stores a value that will be passed back as part of the response. + When making synchronous requests, the calling javascript can + obtain this value immediately as the return value of the + function. + + Parameters: + + value - (mixed): Any value. + + Returns: + + object : The object. + */ + public function setReturnValue($value) { + + + $this->returnValue = 'JSON' == $this->sResponseType ? $value : $this->_encodeArray($value) ; + return $this; + } + + /* + Function: getContentType + + Returns the current content type that will be used for the + response packet. (typically: "text/xml") + + Returns: + + string : The content type. + */ + public function getContentType() + { + return $this->sContentType; + } + + public function setContentType($sContentType) + { + $this->sContentType = $sContentType ; + } + + /* + Function: getOutput + */ + public function getOutput() + { + ob_start(); + if ('text/xml' == $this->getContentType() ) { + $this->_printHeader_XML(); + $this->_printResponse_XML(); + } elseif ('application/json' == $this->getContentType() ) { + $this->_printResponse_JSON(); + + } else { + //todo: trigger Error + }; + return ob_get_clean(); + } + + /* + Function: printOutput + + Prints the output, generated from the commands added to the response, + that will be sent to the browser. + + Returns: + + string : The textual representation of the response commands. + */ + public function printOutput() + { + $this->_sendHeaders(); + if ('text/xml' == $this->getContentType() ) { + $this->_printHeader_XML(); + $this->_printResponse_XML(); + } elseif ('application/json' == $this->getContentType() ) { + $this->_printResponse_JSON(); + + } else { + //todo: trigger Error + } + } + + /* + Function: _sendHeaders + + Used internally to generate the response headers. + */ + public function _sendHeaders() + { + $objArgumentManager = xajaxArgumentManager::getInstance(); + if (XAJAX_METHOD_GET == $objArgumentManager->getRequestMethod()) + { + header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); + } + + $sCharacterSet = ''; + if ($this->sCharacterEncoding && 0 < strlen(trim($this->sCharacterEncoding))) { + $sCharacterSet = '; charset="' . trim($this->sCharacterEncoding) . '"'; + } + + $sContentType = $this->getContentType(); + + header('content-type: ' . $sContentType . ' ' . $sCharacterSet); + } + + /* + Function: getCommandCount + + Returns: + + integer : The number of commands in the response. + */ + public function getCommandCount() + { + return count($this->aCommands); + } + + /* + Function: appendResponse + + Merges the response commands from the specified + object with the response commands in this object. + + Parameters: + + mCommands - (object): object. + bBefore - (boolean): Add the new commands to the beginning + of the list. + + */ + public function appendResponse($mCommands, $bBefore=false) + { + if ( $mCommands instanceof xajaxResponse ) { + $this->returnValue = $mCommands->returnValue; + + if ($bBefore) { + $this->aCommands = array_merge($mCommands->aCommands, $this->aCommands); + } + else { + $this->aCommands = array_merge($this->aCommands, $mCommands->aCommands); + } + } + else if (is_array($mCommands)) { + if ($bBefore) { + $this->aCommands = array_merge($mCommands, $this->aCommands); + } + else { + $this->aCommands = array_merge($this->aCommands, $mCommands); + } + } + else { + //SkipDebug + if (!empty($mCommands)) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:LCERR:01') + , E_USER_ERROR + ); + } + //EndSkipDebug + } + } + + /* + Function: addPluginCommand + + Adds a response command that is generated by a plugin. + + Parameters: + + objPlugin - (object): A reference to a plugin object. + aAttributes - (array): Array containing the attributes for this + response command. + mData - (mixed): The data to be sent with this command. + + Returns: + + object : The object. + */ + public function addPluginCommand($objPlugin, $aAttributes, $mData) + { + $aAttributes['plg'] = $objPlugin->getName(); + return $this->addCommand($aAttributes, $mData); + } + + /* + Function: addCommand + + Add a response command to the array of commands that will + be sent to the browser. + + Parameters: + + aAttributes - (array): Associative array of attributes that + will describe the command. + mData - (mixed): The data to be associated with this command. + + Returns: + + object : The command. + */ + public function addCommand($aAttributes, $mData) + { + if ('text/xml' == $this->getContentType()) $mData = $this->_encodeArray($mData);; + + /* merge commands if possible */ + if ( in_array($aAttributes['cmd'],array('js','ap') ) ) + { + if ($aLastCommand = array_pop($this->aCommands)) + { + if ($aLastCommand['cmd'] == $aAttributes['cmd']) + { + if ('js' == $aLastCommand['cmd']) + { + $mData = $aLastCommand['data'].'; '.$mData; + } + elseif('ap' == $aLastCommand['cmd'] && $aLastCommand['id'] == $aAttributes['id'] && $aLastCommand['prop'] == $aAttributes['prop']) + { + $mData = $aLastCommand['data'].' '.$mData; + } + else + { + $this->aCommands[] = $aLastCommand; + } + } else { + $this->aCommands[] = $aLastCommand; + } + } + } + $aAttributes['data'] = $mData; + $this->aCommands[] = $aAttributes; + + return $this; + } + + + private function _printResponse_JSON() + { + $response = array(); + + if (null !== $this->returnValue) + $response['xjxrv'] = $this->returnValue; + + $response['xjxobj'] = array(); + + foreach(array_keys($this->aCommands) as $sKey) + $response['xjxobj'][] = $this->aCommands[$sKey]; + + print json_encode($response); + } + + /* + Function: _printHeader_XML + + Used internally to print XML start tag. + */ + private function _printHeader_XML() + { + echo '<'; + echo '?'; + echo 'xml version="1.0"'; + + $sEncoding = trim($this->sCharacterEncoding); + if ($this->sCharacterEncoding && 0 < strlen($sEncoding)) { + echo ' encoding="'; + echo $sEncoding; + echo '"'; + } + + echo ' ?'; + echo '>'; + } + + /* + Function: _printResponse_XML + + Used internally to generate the command output. + */ + public function _printResponse_XML() + { + echo '<'; + echo 'xjx>'; + + if (null !== $this->returnValue) + { + echo '<'; + echo 'xjxrv>'; + + $this->_printArray_XML($this->returnValue); + + echo '<'; + echo '/xjxrv>'; + } + + foreach(array_keys($this->aCommands) as $sKey) + $this->_printCommand_XML($this->aCommands[$sKey]); + + echo '<'; + echo '/xjx>'; + } + + /* + Function: _printCommand_XML + + Prints an XML representation of the command. + + Parameters: + + aAttributes - (array): Associative array of attributes for this + command. + */ + private function _printCommand_XML($aAttributes) + { + echo '<'; + echo 'cmd'; + + $mData = ''; + + foreach (array_keys($aAttributes) as $sKey) { + if ($sKey) { + if ('data' != $sKey) { + echo ' '; + echo $sKey; + echo '="'; + echo $aAttributes[$sKey]; + echo '"'; + } else + $mData = $aAttributes[$sKey]; + } + } + + echo '>'; + + $this->_printArray_XML($mData); + + echo '<'; + echo '/cmd>'; + } + + /* + Function: _printArray_XML + + Prints an XML representation of a php array suitable + for inclusion in the response to the browser. Arrays + sent via this method will be converted into a javascript + array on the browser. + + Parameters: + + mArray - (array): Array to be converted. + */ + private function _printArray_XML($mArray) { + if ('object' == gettype($mArray)) + $mArray = get_object_vars($mArray); + + if (false == is_array($mArray)) { + $this->_printEscapedString_XML($mArray); + return; + } + + echo '<'; + echo 'xjxobj>'; + + foreach (array_keys($mArray) as $sKey) { + if (is_array($mArray[$sKey])) { + echo '<'; + echo 'e>'; + + foreach (array_keys($mArray[$sKey]) as $sInnerKey) { + //SkipDebug + if (htmlspecialchars($sInnerKey, ENT_COMPAT, 'UTF-8') != $sInnerKey) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:AKERR:01') + , E_USER_ERROR + ); + } + //EndSkipDebug + + if ('k' == $sInnerKey || 'v' == $sInnerKey) { + echo '<'; + echo $sInnerKey; + echo '>'; + $this->_printArray_XML($mArray[$sKey][$sInnerKey]); + echo '<'; + echo '/'; + echo $sInnerKey; + echo '>'; + } else { + //SkipDebug + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:IEAERR:01') + , E_USER_ERROR + ); + //EndSkipDebug + } + } + + echo '<'; + echo '/e>'; + } else { + //SkipDebug + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:NEAERR:01') + , E_USER_ERROR + ); + //EndSkipDebug + } + } + + echo '<'; + echo '/xjxobj>'; + } + + /* + Function: _printEscapedString_XML + + Escape the specified data if necessary, so special characters in the + command data does not interfere with the structure of the response. + + This could be overridden to allow for transport encodings other than + XML. + + Parameters: + + sData - (string): The data to be escaped. + + Returns: + + string : The escaped data. + */ + private function _printEscapedString_XML($sData) + { + if (is_null($sData) || false == isset($sData)) { + echo '*'; + return; + } + + if ($this->bOutputEntities) { + //SkipDebug + if (false === function_exists('mb_convert_encoding')) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:MBEERR:01') + , E_USER_NOTICE + ); + } + //EndSkipDebug + + echo call_user_func_array( + 'mb_convert_encoding', + array($sData, 'HTML-ENTITIES', $this->sCharacterEncoding) + ); + return; + } + + $nCDATA = 0; + + $bNoOpenCDATA = (false === strpos($sData, '<'.'![CDATA[')); + if ($bNoOpenCDATA) { + $bNoCloseCDATA = (false === strpos($sData, ']]>')); + if ($bNoCloseCDATA) { + $bSpecialChars = (htmlspecialchars($sData, ENT_COMPAT, 'UTF-8') != $sData); + if ($bSpecialChars) + $nCDATA = 1; + } else + $nCDATA = 2; + } else + $nCDATA = 2; + + if (0 < $nCDATA) { + echo '<'; + echo '![CDATA['; + + // PHP defines numeric values as integer or float (double and real are aliases of float) + if (is_string($sData)) { + echo 'S'; + } else if (is_int($sData) || is_float($sData)) { + echo 'N'; + } else if (is_bool($sData)) { + echo 'B'; + } + + if (1 < $nCDATA) { + $aSegments = explode('<'.'![CDATA[', $sData); + $aOutput = array(); + $nOutput = 0; + foreach (array_keys($aSegments) as $keySegment) { + $aFragments = explode(']]>', $aSegments[$keySegment]); + $aStack = array(); + $nStack = 0; + foreach (array_keys($aFragments) as $keyFragment) { + if (0 < $nStack) + array_push($aStack, ']]]]><', '![CDATA[>', $aFragments[$keyFragment]); + else + $aStack[] = $aFragments[$keyFragment]; + ++$nStack; + } + if (0 < $nOutput) + array_push($aOutput, '<', '![]]><', '![CDATA[CDATA[', implode('', $aStack)); + else + $aOutput[] = implode('', $aStack); + ++$nOutput; + } + echo implode('', $aOutput); + } else + echo $sData; + + echo ']]>'; + } else { + if (is_string($sData)) { + echo 'S'; + } else if (is_int($sData) || is_float($sData)) { + echo 'N'; + } else if (is_bool($sData)) { + echo 'B'; + } + echo $sData; + } + } + + /* + Function: _encodeArray + + Recursively serializes a data structure in an array so that it can + be sent to the browser. This can be thought of as the opposite of + _parseObjXml>. + + Parameters: + + mData - (mixed): The data to be evaluated. + + Returns: + + mixed : The object constructed from the data. + */ + private function _encodeArray($mData) { + if ('object' === gettype($mData)) + $mData = get_object_vars($mData); + + if (false === is_array($mData)) + return $mData; + + $aData = array(); + foreach (array_keys($mData) as $sKey) + $aData[] = array( + // key does not need to be encoded + 'k'=>$sKey, + 'v'=>$this->_encodeArray($mData[$sKey]) + ); + return $aData; + } + +}// end class xajaxResponse + +class xajaxCustomResponse +{ + protected $sOutput; + protected $sContentType; + + protected $sCharacterEncoding; + protected $bOutputEntities; + + function __construct($sContentType) + { + $this->sOutput = ''; + $this->sContentType = $sContentType; + + $objResponseManager = xajaxResponseManager::getInstance(); + + $this->sCharacterEncoding = $objResponseManager->getCharacterEncoding(); + $this->bOutputEntities = $objResponseManager->getOutputEntities(); + } + + public function setCharacterEncoding($sCharacterEncoding) + { + $this->sCharacterEncoding = $sCharacterEncoding; + } + + public function setOutputEntities($bOutputEntities) + { + $this->bOutputEntities = $bOutputEntities; + } + + public function clear() + { + $this->sOutput = ''; + } + + public function append($sOutput) + { + $this->sOutput .= $sOutput; + } + + public function appendResponse($objResponse) + { + //SkipDebug + if (false == ($objResponse instanceof xajaxCustomResponse )) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:MXRTERR') + , E_USER_ERROR + ); + } + + if ($objResponse->getContentType() != $this->getContentType()) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:MXCTERR') + , E_USER_ERROR + ); + } + + if ($objResponse->getCharacterEncoding() != $this->getCharacterEncoding()) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:MXCEERR') + , E_USER_ERROR + ); + } + + if ($objResponse->getOutputEntities() != $this->getOutputEntities()) { + $objLanguageManager = xajaxLanguageManager::getInstance(); + trigger_error( + $objLanguageManager->getText('XJXRSP:MXOEERR') + , E_USER_ERROR + ); + } + //EndSkipDebug + + $this->sOutput .= $objResponse->getOutput(); + } + + public function getContentType() + { + return $this->sContentType; + } + + public function getCharacterEncoding() + { + return $this->sCharacterEncoding; + } + + public function getOutputEntities() + { + return $this->bOutputEntities; + } + + public function getOutput() + { + return $this->sOutput; + } + + public function printOutput() + { + $sContentType = $this->sContentType; + $sCharacterSet = $this->sCharacterEncoding; + + header("content-type: {$sContentType}; charset={$sCharacterSet}"); + + echo $this->sOutput; + } +} diff --git a/www/include/xajax/xajax_core/xajaxResponseManager.inc.php b/www/include/xajax/xajax_core/xajaxResponseManager.inc.php new file mode 100644 index 00000000..a8877704 --- /dev/null +++ b/www/include/xajax/xajax_core/xajaxResponseManager.inc.php @@ -0,0 +1,262 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxResponseManager.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajaxResponseManager + + This class stores and tracks the response that will be returned after + processing a request. The response manager represents a single point + of contact for working with objects as well as + objects. +*/ +final class xajaxResponseManager +{ + /* + Object: objResponse + + The current response object that will be sent back to the browser + once the request processing phase is complete. + */ + private $objResponse; + + /* + String: sCharacterEncoding + */ + private $sCharacterEncoding; + + /* + Boolean: bOutputEntities + */ + private $bOutputEntities; + + /* + Array: aDebugMessages + */ + private $aDebugMessages; + + /* + Function: xajaxResponseManager + + Construct and initialize the one and only xajaxResponseManager object. + */ + private function __construct() + { + $this->objResponse = NULL; + $this->aDebugMessages = array(); + } + + /* + Function: getInstance + + Implementation of the singleton pattern: provide a single instance of the + to all who request it. + */ + public static function &getInstance() + { + static $obj; + if (!$obj) { + $obj = new xajaxResponseManager(); + } + return $obj; + } + + /* + Function: configure + + Called by the xajax object when configuration options are set in the main script. Option + values are passed to each of the main xajax components and stored locally as needed. The + will track the characterEncoding and outputEntities settings. + + Parameters: + $sName - (string): Setting name + $mValue - (mixed): Value + */ + public function configure($sName, $mValue) + { + if ('characterEncoding' == $sName) + { + $this->sCharacterEncoding = $mValue; + + if (isset($this->objResponse)) + $this->objResponse->setCharacterEncoding($this->sCharacterEncoding); + } + else if ('contentType' == $sName) + { + if (isset($this->objResponse)) + $this->objResponse->setContentType($mValue); + } + else if ('outputEntities' == $sName) + { + if (true === $mValue || false === $mValue) + { + $this->bOutputEntities = $mValue; + + if (isset($this->objResponse)) + $this->objResponse->setOutputEntities($this->bOutputEntities); + } + } + $this->aSettings[$sName] = $mValue; + + } + + + + /* + Function: getConfiguration + + Get the current value of a configuration setting that was previously set + via configure> or configureMany> + + Parameters: + + $sName - (string): The name of the configuration setting + + Returns: + + $mValue : (mixed): The value of the setting if set, null otherwise. + */ + + public function getConfiguration($sName) + { + if (isset($this->aSettings[$sName])) + return $this->aSettings[$sName]; + return NULL; + } + + /* + Function: clear + + Clear the current response. A new response will need to be appended + before the request processing is complete. + */ + public function clear() + { + $this->objResponse = NULL; + } + + /* + Function: append + + Used, primarily internally, to append one response object onto the end of another. You can + append one xajaxResponse to the end of another, or append a xajaxCustomResponse onto the end of + another xajaxCustomResponse. However, you cannot append a standard response object onto the end + of a custom response and likewise, you cannot append a custom response onto the end of a standard + response. + + Parameters: + + $mResponse - (object): The new response object to be added to the current response object. + + If no prior response has been appended, this response becomes the main response object to which other + response objects will be appended. + */ + public function append($mResponse) + { + if ( $mResponse instanceof xajaxResponse ) { + if (NULL == $this->objResponse) { + $this->objResponse = $mResponse; + } else if ( $this->objResponse instanceof xajaxResponse ) { + if ($this->objResponse != $mResponse) + $this->objResponse->appendResponse($mResponse); + } else { + $objLanguageManager = xajaxLanguageManager::getInstance(); + $this->debug( + $objLanguageManager->getText('XJXRM:MXRTERR') + . get_class($this->objResponse) + . ')' + ); + } + } else if ( $mResponse instanceof xajaxCustomResponse ) { + if (NULL == $this->objResponse) { + $this->objResponse = $mResponse; + } else if ( $this->objResponse instanceof xajaxCustomResponse ) { + if ($this->objResponse != $mResponse) + $this->objResponse->appendResponse($mResponse); + } else { + $objLanguageManager = xajaxLanguageManager::getInstance(); + $this->debug( + $objLanguageManager->getText('XJXRM:MXRTERR') + . get_class($this->objResponse) + . ')' + ); + } + } else { + $objLanguageManager = xajaxLanguageManager::getInstance(); + $this->debug($objLanguageManager->getText('XJXRM:IRERR')); + } + } + + /* + Function: debug + + Appends a debug message on the end of the debug message queue. Debug messages + will be sent to the client with the normal response (if the response object supports + the sending of debug messages, see: ) + + Parameters: + + $sMessage - (string): The text of the debug message to be sent. + */ + public function debug($sMessage) + { + $this->aDebugMessages[] = $sMessage; + } + + /* + Function: send + + Prints the response object to the output stream, thus sending the response to the client. + */ + public function send() + { + if (NULL != $this->objResponse) { + foreach ($this->aDebugMessages as $sMessage) + $this->objResponse->debug($sMessage); + $this->aDebugMessages = array(); + $this->objResponse->printOutput(); + } + } + + /* + Function: getCharacterEncoding + + Called automatically by new response objects as they are constructed to obtain the + current character encoding setting. As the character encoding is changed, the + will automatically notify the current response object since it would have been constructed + prior to the setting change, see . + */ + public function getCharacterEncoding() + { + return $this->sCharacterEncoding; + } + + /* + Function: getOutputEntities + + Called automatically by new response objects as they are constructed to obtain the + current output entities setting. As the output entities setting is changed, the + will automatically notify the current response object since it would + have been constructed prior to the setting change, see . + */ + public function getOutputEntities() + { + return $this->bOutputEntities; + } +} \ No newline at end of file diff --git a/www/include/xajax/xajax_core/xajax_lang_de.inc.php b/www/include/xajax/xajax_core/xajax_lang_de.inc.php new file mode 100644 index 00000000..3d7774e3 --- /dev/null +++ b/www/include/xajax/xajax_core/xajax_lang_de.inc.php @@ -0,0 +1,88 @@ + for a detailed description, copyright + and license information. + + Translations provided by: (Thank you!) + - mic + - q_no +*/ + +/* + @package xajax + @version $Id: xajax_lang_de.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +//SkipAIO + +$objLanguageManager = xajaxLanguageManager::getInstance(); +$objLanguageManager->register('de', array( + 'LOGHDR:01' => '** xajax Fehler Protokoll - ', + 'LOGHDR:02' => " **\n", + 'LOGHDR:03' => "\n\n\n", + 'LOGERR:01' => "** Protokolliere Fehler **\n\nxajax konnte den Fehler nicht in die Protokolldatei schreiben:\n", + 'LOGMSG:01' => "** PHP Fehlermeldungen: **", + 'CMPRSJS:RDERR:01' => 'Die unkomprimierte JavaScript-Datei konnte nicht gefunden werden im Verzeichnis: ', + 'CMPRSJS:RDERR:02' => '. Fehler ', + 'CMPRSJS:WTERR:01' => 'Die komprimierte xajax JavaScript-Datei konnte nicht in das Verzeichnis ', + 'CMPRSJS:WTERR:02' => ' geschrieben werden. Fehler ', + 'CMPRSPHP:WTERR:01' => 'Die komprimierte xajax Datei ', + 'CMPRSPHP:WTERR:02' => ' konnte nicht geschrieben werden. Fehler ', + 'CMPRSAIO:WTERR:01' => 'Die komprimierte xajax Datei ', + 'CMPRSAIO:WTERR:02' => '/xajaxAIO.inc.php konnte nicht geschrieben werden. Fehler ', + 'DTCTURI:01' => 'xajax Fehler: xajax konnte die Request URI nicht automatisch identifizieren.', + 'DTCTURI:02' => 'Bitte setzen sie die Request URI explizit wenn sie die xajax Klasse instanziieren.', + 'ARGMGR:ERR:01' => 'Fehlerhaftes Objekt erhalten: ', + 'ARGMGR:ERR:02' => ' <==> ', + 'ARGMGR:ERR:03' => 'Die erhaltenen xajax Daten konnte nicht aus UTF8 konvertiert werden.', + 'XJXCTL:IAERR:01' => 'Ungültiges Attribut [', + 'XJXCTL:IAERR:02' => '] für Element [', + 'XJXCTL:IAERR:03' => '].', + 'XJXCTL:IRERR:01' => 'Ungültiges Request-Objekt übergeben an xajaxControl::setEvent', + 'XJXCTL:IEERR:01' => 'Ungültiges Attribut (event name) [', + 'XJXCTL:IEERR:02' => '] für Element [', + 'XJXCTL:IEERR:03' => '].', + 'XJXCTL:MAERR:01' => 'Erforderliches Attribut fehlt [', + 'XJXCTL:MAERR:02' => '] für Element [', + 'XJXCTL:MAERR:03' => '].', + 'XJXCTL:IETERR:01' => "Ungültiges End-Tag; Sollte 'forbidden' oder 'optional' sein.\n", + 'XJXCTL:ICERR:01' => "Ungültige Klasse für html control angegeben.; Sollte %inline, %block oder %flow sein.\n", + 'XJXCTL:ICLERR:01' => 'Ungültige Klasse (control) an addChild übergeben; Sollte abgeleitet sein von xajaxControl.', + 'XJXCTL:ICLERR:02' => 'Ungültige Klasse (control) an addChild übergeben [', + 'XJXCTL:ICLERR:03' => '] für Element [', + 'XJXCTL:ICLERR:04' => "].\n", + 'XJXCTL:ICHERR:01' => 'Ungültiger Parameter übergeben für xajaxControl::addChildren; Array aus xajaxControl Objekten erwartet.', + 'XJXCTL:MRAERR:01' => 'Erforderliches Attribut fehlt [', + 'XJXCTL:MRAERR:02' => '] für Element [', + 'XJXCTL:MRAERR:03' => '].', + 'XJXPLG:GNERR:01' => 'Response plugin sollte die Funktion getName überschreiben.', + 'XJXPLG:PERR:01' => 'Response plugin sollte die process Funktion überschreiben.', + 'XJXPM:IPLGERR:01' => 'Versuch ungültiges Plugin zu registrieren: : ', + 'XJXPM:IPLGERR:02' => ' Ableitung von xajaxRequestPlugin oder xajaxResponsePlugin erwartet.', + 'XJXPM:MRMERR:01' => 'Konnte die Registrierungsmethode nicht finden für: : ', + 'XJXRSP:EDERR:01' => 'Die Angabe der Zeichensatzkodierung in der xajaxResponse ist veraltet. Die neue Funktion lautet: $xajax->configure("characterEncoding", ...);', + 'XJXRSP:MPERR:01' => 'Ungültiger oder fehlender Pluginname festgestellt im Aufruf von xajaxResponse::plugin', + 'XJXRSP:CPERR:01' => "Der Parameter \$sType in addCreate ist veraltet. Die neue Funktion lautet addCreateInput()", + 'XJXRSP:LCERR:01' => "Das xajax response Objeckt konnte die Befehler nich verarbeiten, da kein gültiges Array übergeben wurde.", + 'XJXRSP:AKERR:01' => 'Ungültiger Tag-Name im Array.', + 'XJXRSP:IEAERR:01' => 'Ungeeignet kodiertes Array.', + 'XJXRSP:NEAERR:01' => 'Nicht kodiertes Array festgestellt.', + 'XJXRSP:MBEERR:01' => 'Die Ausgabe vonn xajax response konnte nicht in htmlentities umgewandelt werden, da die Funktion mb_convert_encoding nicht verfügbar ist.', + 'XJXRSP:MXRTERR' => 'Fehler: Kann keine verschiedenen Typen in einer einzelnen Antwort verarbeiten.', + 'XJXRSP:MXCTERR' => 'Fehler: Kann keine verschiedenen Content-Types in einer einzelnen Antwort verarbeiten.', + 'XJXRSP:MXCEERR' => 'Fehler: Kann keine verschiedenen Zeichensatzkodierungen in einer einzelnen Antwort verarbeiten.', + 'XJXRSP:MXOEERR' => 'Fehler: Kann keine output entities (true/false) in ener einzelnen Antwort verarbeiten.', + 'XJXRM:IRERR' => 'Ungültige Antwort erhalten während der Ausführung der Anfrage.', + 'XJXRM:MXRTERR' => 'Fehler: Kann kkeine verschiedenen reponse types benutzen während der Ausführung einer Anfrage: ' + )); + +//EndSkipAIO \ No newline at end of file diff --git a/www/include/xajax/xajax_core/xajax_lang_nl.inc.php b/www/include/xajax/xajax_core/xajax_lang_nl.inc.php new file mode 100644 index 00000000..72ebc99d --- /dev/null +++ b/www/include/xajax/xajax_core/xajax_lang_nl.inc.php @@ -0,0 +1,79 @@ + for a detailed description, copyright + and license information. + + Translations provided by: (Thank you!) + - Jeffrey +*/ + +//SkipAIO + +$objLanguageManager = xajaxLanguageManager::getInstance(); +$objLanguageManager->register('nl', array( + 'LOGHDR:01' => '** xajax Foutmelding logboek - ', + 'LOGHDR:02' => " **\n", + 'LOGHDR:03' => "\n\n\n", + 'LOGERR:01' => "** Logboek fouten **\n\nxajax was niet in staat om te schrijven naar het logboek:\n", + 'LOGMSG:01' => "** PHP Foutmeldingen: **", + 'CMPRSJS:RDERR:01' => 'Het xajax ongecomprimeerde Javascript bestand kon niet worden gevonden in de: ', + 'CMPRSJS:RDERR:02' => '. map. ', + 'CMPRSJS:WTERR:01' => 'Het xajax gecomprimeerde Javascript bestand kon niet worden geschreven in de: ', + 'CMPRSJS:WTERR:02' => ' map. Fout ', + 'CMPRSPHP:WTERR:01' => 'Naar het xajax gecomprimeerde bestand ', + 'CMPRSPHP:WTERR:02' => ' kon niet worden geschreven. Fout ', + 'CMPRSAIO:WTERR:01' => 'Naar het xajax gecomprimeerde bestand ', + 'CMPRSAIO:WTERR:02' => '/xajaxAIO.inc.php kon niet worden geschreven. Fout ', + 'DTCTURI:01' => 'xajax Fout: xajax kon de Request URI niet automatisch identificeren.', + 'DTCTURI:02' => 'Alstublieft, specificeer de Request URI expliciet bij het initiëren van het xajax object.', + 'ARGMGR:ERR:01' => 'Misvormd object argument ontvangen: ', + 'ARGMGR:ERR:02' => ' <==> ', + 'ARGMGR:ERR:03' => 'De binnenkomende xajax data kon niet wordt geconverteerd van UTF-8.', + 'XJXCTL:IAERR:01' => 'Ongeldig attribuut [', + 'XJXCTL:IAERR:02' => '] voor element [', + 'XJXCTL:IAERR:03' => '].', + 'XJXCTL:IRERR:01' => 'Ongeldige object aanvraag doorgegeven aan xajaxControl::setEvent', + 'XJXCTL:IEERR:01' => 'Ongeldig attribuut (event name) [', + 'XJXCTL:IEERR:02' => '] voor element [', + 'XJXCTL:IEERR:03' => '].', + 'XJXCTL:MAERR:01' => 'Ontbrekend attribuut [', + 'XJXCTL:MAERR:02' => '] voor element [', + 'XJXCTL:MAERR:03' => '].', + 'XJXCTL:IETERR:01' => "Ongeldige eind-tag; zou 'forbidden' of 'optional' moeten zijn..\n", + 'XJXCTL:ICERR:01' => "Ongeldige klasse gespecificeerd voor html control.; zou %inline, %block of %flow moeten zijn.\n", + 'XJXCTL:ICLERR:01' => 'Ongeldige (control) doorgegeven aan addChild; Zou moeten worden afgeleid van xajaxControl.', + 'XJXCTL:ICLERR:02' => 'Ongeldige (control) doorgegeven aan addChild [', + 'XJXCTL:ICLERR:03' => '] voor element [', + 'XJXCTL:ICLERR:04' => "].\n", + 'XJXCTL:ICHERR:01' => 'Ongeldige parameter doorgegeven aan xajaxControl::addChildren; Array moet bestaan uit xajaxControl objecten.', + 'XJXCTL:MRAERR:01' => 'Ontbrekend attribuut [', + 'XJXCTL:MRAERR:02' => '] voor element [', + 'XJXCTL:MRAERR:03' => '].', + 'XJXPLG:GNERR:01' => 'Retourneer plugin zou de getName functie moeten overschrijven.', + 'XJXPLG:PERR:01' => 'Retourneer plugin zou de proces functie moeten overschrijven.', + 'XJXPM:IPLGERR:01' => 'Poging om ongeldige plugin te registreren: : ', + 'XJXPM:IPLGERR:02' => ' afleiding moet komen van xajaxRequestPlugin of xajaxResponsePlugin.', + 'XJXPM:MRMERR:01' => 'Localisatie van registratie methode faalde voor het volgende: : ', + 'XJXRSP:EDERR:01' => 'Doorgeven van karakter decodering naar de xajaxResponse constructie is verouderd. De nieuwe functie luidt: $xajax->configure("characterEncoding", ...);', + 'XJXRSP:MPERR:01' => 'Ongeldige of ontbrekende plugin naam gedetecteerd in een aanvraag naar xajaxResponse::plugin', + 'XJXRSP:CPERR:01' => "De parameter \$sType in addCreate is verouderd.. De nieuwe functie luidt addCreateInput()", + 'XJXRSP:LCERR:01' => "Het xajax antwoord object kon de commando's niet laden, gezien de meegegeven data geen geldige array is.", + 'XJXRSP:AKERR:01' => 'Ongeldige ge-encodeerde tag naam in array', + 'XJXRSP:IEAERR:01' => 'Ungeeignet kodiertes Array.', + 'XJXRSP:NEAERR:01' => 'Niet gecodeerde array gedetecteerd.', + 'XJXRSP:MBEERR:01' => 'De xajax output kon niet worden geconverteerd naar HTML entities, gezien mb_convert_encoding niet beschikbaar is.', + 'XJXRSP:MXRTERR' => 'Fout: Kann keine verschiedenen Typen in einer einzelnen Antwort verarbeiten.', + 'XJXRSP:MXCTERR' => 'Fout: Kan geen meerdere typen verwisselen in een enkele teruggave.', + 'XJXRSP:MXCEERR' => 'Fout: Kan geen meerdere karakter decoderingen verwerken in een enkele teruggave.', + 'XJXRSP:MXOEERR' => 'Fout: kan geen output entities (true/false) in een enkele teruggave verwerken.', + 'XJXRM:IRERR' => 'Een ongeldig antwoord is geretourneerd tijdens het verwerken van deze aanvraag.', + 'XJXRM:MXRTERR' => 'Fout: Kan geen meerdere typen verwisselen tijdens het verwerken van een enkele aanvraag: ' + )); + +//EndSkipAIO \ No newline at end of file diff --git a/www/include/xajax/xajax_js/JSON.js b/www/include/xajax/xajax_js/JSON.js new file mode 100644 index 00000000..a2c7769f --- /dev/null +++ b/www/include/xajax/xajax_js/JSON.js @@ -0,0 +1,29 @@ + +if(!this.JSON){this.JSON={};} +(function(){function f(n){return n<10?'0'+n:n;} +if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+ +f(this.getUTCMonth()+1)+'-'+ +f(this.getUTCDate())+'T'+ +f(this.getUTCHours())+':'+ +f(this.getUTCMinutes())+':'+ +f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};} +var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';} +function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);} +if(typeof rep==='function'){value=rep.call(holder,key,value);} +switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';} +gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i 1&&arguments[1]==true) +submitDisabledElements=true;var prefix='';if(arguments.length > 2) +prefix=arguments[2];if('string'==typeof parent) +parent=xajax.$(parent);var aFormValues={};if(parent) +if(parent.childNodes) +xajax.tools._getFormValues(aFormValues,parent.childNodes,submitDisabledElements,prefix);return aFormValues;} +xajax.tools._getFormValues=function(aFormValues,children,submitDisabledElements,prefix){var iLen=children.length;for(var i=0;i < iLen;++i){var child=children[i];if(('undefined'!=typeof child.childNodes)&&(child.type!='select-one')&&(child.type!='select-multiple')) +xajax.tools._getFormValues(aFormValues,child.childNodes,submitDisabledElements,prefix);xajax.tools._getFormValue(aFormValues,child,submitDisabledElements,prefix);} +} +xajax.tools._getFormValue=function(aFormValues,child,submitDisabledElements,prefix){if(!child.name) +return;if('PARAM'==child.tagName)return;if(child.disabled) +if(true==child.disabled) +if(false==submitDisabledElements) +return;if(prefix!=child.name.substring(0,prefix.length)) +return;if(child.type) +if(child.type=='radio'||child.type=='checkbox') +if(false==child.checked) +return;var name=child.name;var values=[];if('select-multiple'==child.type){var jLen=child.length;for(var j=0;j < jLen;++j){var option=child.options[j];if(true==option.selected) +values.push(option.value);} +}else{values=child.value;} +var keyBegin=name.indexOf('[');if(0 <=keyBegin){var n=name;var k=n.substr(0,n.indexOf('['));var a=n.substr(n.indexOf('['));if(typeof aFormValues[k]=='undefined') +aFormValues[k]={};var p=aFormValues;while(a.length!=0){var sa=a.substr(0,a.indexOf(']')+1);var lk=k;var lp=p;a=a.substr(a.indexOf(']')+1);p=p[k];k=sa.substr(1,sa.length-2);if(k==''){if('select-multiple'==child.type){k=lk;p=lp;}else{k=p.length;} +} +if(typeof k=='undefined'){k=0;for(var i in lp[lk])k++;} +if(typeof p[k]=='undefined'){p[k]={};} +} +p[k]=values;}else{aFormValues[name]=values;} +} +xajax.tools.stripOnPrefix=function(sEventName){sEventName=sEventName.toLowerCase();if(0==sEventName.indexOf('on')) +sEventName=sEventName.replace(/on/,'');return sEventName;} +xajax.tools.addOnPrefix=function(sEventName){sEventName=sEventName.toLowerCase();if(0!=sEventName.indexOf('on')) +sEventName='on'+sEventName;return sEventName;} +xajax.tools.xml={};xajax.tools.xml.parseAttributes=function(child,obj){var iLen=child.attributes.length;for(var i=0;i < iLen;++i){var attr=child.attributes[i];obj[attr.name]=attr.value;} +} +xajax.tools.xml.parseChildren=function(child,obj){obj.data='';if(0 < child.childNodes.length){if(1 < child.childNodes.length){var grandChild=child.firstChild;do{if('#cdata-section'==grandChild.nodeName||'#text'==grandChild.nodeName){obj.data+=grandChild.data;} +}while(grandChild=grandChild.nextSibling);}else{var grandChild=child.firstChild;if('xjxobj'==grandChild.nodeName){obj.data=xajax.tools._nodeToObject(grandChild);return;}else if('#cdata-section'==grandChild.nodeName||'#text'==grandChild.nodeName){obj.data=grandChild.data;} +} +}else if('undefined'!=typeof child.data){obj.data=child.data;} +obj.data=xajax.tools._enforceDataType(obj.data);} +xajax.tools.xml.processFragment=function(xmlNode,seq,oRet,oRequest){var xx=xajax;var xt=xx.tools;while(xmlNode){if('cmd'==xmlNode.nodeName){var obj={};obj.fullName='*unknown*';obj.sequence=seq;obj.request=oRequest;obj.context=oRequest.context;xt.xml.parseAttributes(xmlNode,obj);xt.xml.parseChildren(xmlNode,obj);xt.queue.push(xx.response,obj);}else if('xjxrv'==xmlNode.nodeName){oRet=xt._nodeToObject(xmlNode.firstChild);}else if('debugmsg'==xmlNode.nodeName){}else +throw{code:10004,data:xmlNode.nodeName} +++seq;xmlNode=xmlNode.nextSibling;} +return oRet;} +xajax.tools.queue={} +xajax.tools.queue.create=function(size){return{start:0, +size:size, +end:0, +commands:[], +timeout:null +} +} +xajax.tools.queue.retry=function(obj,count){var retries=obj.retries;if(retries){--retries;if(1 > retries) +return false;}else retries=count;obj.retries=retries;return true;} +xajax.tools.queue.rewind=function(theQ){if(0 < theQ.start) +--theQ.start;else +theQ.start=theQ.size;} +xajax.tools.queue.setWakeup=function(theQ,when){if(null!=theQ.timeout){clearTimeout(theQ.timeout);theQ.timeout=null;} +theQ.timout=setTimeout(function(){xajax.tools.queue.process(theQ);},when);} +xajax.tools.queue.process=function(theQ){if(null!=theQ.timeout){clearTimeout(theQ.timeout);theQ.timeout=null;} +var obj=xajax.tools.queue.pop(theQ);while(null!=obj){try{if(false==xajax.executeCommand(obj)) +return false;}catch(e){} +delete obj;obj=xajax.tools.queue.pop(theQ);} +return true;} +xajax.tools.queue.push=function(theQ,obj){var next=theQ.end+1;if(next > theQ.size) +next=0;if(next!=theQ.start){theQ.commands[theQ.end]=obj;theQ.end=next;}else +throw{code:10003} +} +xajax.tools.queue.pushFront=function(theQ,obj){xajax.tools.queue.rewind(theQ);theQ.commands[theQ.start]=obj;} +xajax.tools.queue.pop=function(theQ){var next=theQ.start;if(next==theQ.end) +return null;next++;if(next > theQ.size) +next=0;var obj=theQ.commands[theQ.start];delete theQ.commands[theQ.start];theQ.start=next;return obj;} +xajax.responseProcessor={};xajax.tools.json={} +xajax.tools.json.processFragment=function(nodes,seq,oRet,oRequest){var xx=xajax;var xt=xx.tools;for(nodeName in nodes){if('xjxobj'==nodeName){for(a in nodes[nodeName]){if(parseInt(a)!=a)continue;var obj=nodes[nodeName][a];obj.fullName='*unknown*';obj.sequence=seq;obj.request=oRequest;obj.context=oRequest.context;xt.queue.push(xx.response,obj);++seq;} +}else if('xjxrv'==nodeName){oRet=nodes[nodeName];}else if('debugmsg'==nodeName){txt=nodes[nodeName];}else +throw{code:10004,data:obj.fullName} +} +return oRet;} +xajax.responseProcessor.json=function(oRequest){var xx=xajax;var xt=xx.tools;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;var oRet=oRequest.returnValue;if(xt.in_array(xx.responseSuccessCodes,oRequest.request.status)){xcb.execute([gcb,lcb],'onSuccess',oRequest);var seq=0;if(oRequest.request.responseText){try{var responseJSON=eval('('+oRequest.request.responseText+')');}catch(ex){throw(ex);} +if(('object'==typeof responseJSON)&&('object'==typeof responseJSON.xjxobj)){oRequest.status.onProcessing();oRet=xt.json.processFragment(responseJSON,seq,oRet,oRequest);}else{} +} +var obj={};obj.fullName='Response Complete';obj.sequence=seq;obj.request=oRequest;obj.context=oRequest.context;obj.cmd='rcmplt';xt.queue.push(xx.response,obj);if(null==xx.response.timeout) +xt.queue.process(xx.response);}else if(xt.in_array(xx.responseRedirectCodes,oRequest.request.status)){xcb.execute([gcb,lcb],'onRedirect',oRequest);window.location=oRequest.request.getResponseHeader('location');xx.completeResponse(oRequest);}else if(xt.in_array(xx.responseErrorsForAlert,oRequest.request.status)){xcb.execute([gcb,lcb],'onFailure',oRequest);xx.completeResponse(oRequest);} +return oRet;} +xajax.responseProcessor.xml=function(oRequest){var xx=xajax;var xt=xx.tools;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;var oRet=oRequest.returnValue;if(xt.in_array(xx.responseSuccessCodes,oRequest.request.status)){xcb.execute([gcb,lcb],'onSuccess',oRequest);var seq=0;if(oRequest.request.responseXML){var responseXML=oRequest.request.responseXML;if(responseXML.documentElement){oRequest.status.onProcessing();var child=responseXML.documentElement.firstChild;oRet=xt.xml.processFragment(child,seq,oRet,oRequest);} +} +var obj={};obj.fullName='Response Complete';obj.sequence=seq;obj.request=oRequest;obj.context=oRequest.context;obj.cmd='rcmplt';xt.queue.push(xx.response,obj);if(null==xx.response.timeout) +xt.queue.process(xx.response);}else if(xt.in_array(xx.responseRedirectCodes,oRequest.request.status)){xcb.execute([gcb,lcb],'onRedirect',oRequest);window.location=oRequest.request.getResponseHeader('location');xx.completeResponse(oRequest);}else if(xt.in_array(xx.responseErrorsForAlert,oRequest.request.status)){xcb.execute([gcb,lcb],'onFailure',oRequest);xx.completeResponse(oRequest);} +return oRet;} +xajax.js={} +xajax.js.includeScriptOnce=function(command){command.fullName='includeScriptOnce';var fileName=command.data;var oDoc=xajax.config.baseDocument;var loadedScripts=oDoc.getElementsByTagName('script');var iLen=loadedScripts.length;for(var i=0;i < iLen;++i){var script=loadedScripts[i];if(script.src){if(0 <=script.src.indexOf(fileName)) +return true;} +} +return xajax.js.includeScript(command);} +xajax.js.includeScript=function(command){command.fullName='includeScript';var oDoc=xajax.config.baseDocument;var objHead=oDoc.getElementsByTagName('head');var objScript=oDoc.createElement('script');objScript.src=command.data;if('undefined'==typeof command.type)objScript.type='text/javascript';else objScript.type=command.type;if('undefined'!=typeof command.type)objScript.setAttribute('id',command.elm_id);objHead[0].appendChild(objScript);return true;} +xajax.js.removeScript=function(command){command.fullName='removeScript';var fileName=command.data;var unload=command.unld;var oDoc=xajax.config.baseDocument;var loadedScripts=oDoc.getElementsByTagName('script');var iLen=loadedScripts.length;for(var i=0;i < iLen;++i){var script=loadedScripts[i];if(script.src){if(0 <=script.src.indexOf(fileName)){if('undefined'!=typeof unload){var args={};args.data=unload;args.context=window;xajax.js.execute(args);} +var parent=script.parentNode;parent.removeChild(script);} +} +} +return true;} +xajax.js.sleep=function(command){command.fullName='sleep';if(xajax.tools.queue.retry(command,command.prop)){xajax.tools.queue.setWakeup(xajax.response,100);return false;} +return true;} +xajax.js.confirmCommands=function(command){command.fullName='confirmCommands';var msg=command.data;var numberOfCommands=command.id;if(false==confirm(msg)){while(0 < numberOfCommands){xajax.tools.queue.pop(xajax.response);--numberOfCommands;} +} +return true;} +xajax.js.execute=function(args){args.fullName='execute Javascript';var returnValue=true;args.context=args.context ? args.context:{};args.context.xajaxDelegateCall=function(){eval(args.data);};args.context.xajaxDelegateCall();return returnValue;} +xajax.js.waitFor=function(args){args.fullName='waitFor';var bResult=false;var cmdToEval='bResult = (';cmdToEval+=args.data;cmdToEval+=');';try{args.context.xajaxDelegateCall=function(){eval(cmdToEval);} +args.context.xajaxDelegateCall();}catch(e){} +if(false==bResult){if(xajax.tools.queue.retry(args,args.prop)){xajax.tools.queue.setWakeup(xajax.response,100);return false;} +} +return true;} +xajax.js.call=function(args){args.fullName='call js function';var parameters=args.data;var scr=new Array();scr.push(args.func);scr.push('(');if('undefined'!=typeof parameters){if('object'==typeof parameters){var iLen=parameters.length;if(0 < iLen){scr.push('parameters[0]');for(var i=1;i < iLen;++i) +scr.push(', parameters['+i+']');} +} +} +scr.push(');');args.context.xajaxDelegateCall=function(){eval(scr.join(''));} +args.context.xajaxDelegateCall();return true;} +xajax.js.setFunction=function(args){args.fullName='setFunction';var code=new Array();code.push(args.func);code.push(' = function(');if('object'==typeof args.prop){var separator='';for(var m in args.prop){code.push(separator);code.push(args.prop[m]);separator=',';} +}else code.push(args.prop);code.push(') { ');code.push(args.data);code.push(' }');args.context.xajaxDelegateCall=function(){eval(code.join(''));} +args.context.xajaxDelegateCall();return true;} +xajax.js.wrapFunction=function(args){args.fullName='wrapFunction';var code=new Array();code.push(args.func);code.push(' = xajax.js.makeWrapper(');code.push(args.func);code.push(', args.prop, args.data, args.type, args.context);');args.context.xajaxDelegateCall=function(){eval(code.join(''));} +args.context.xajaxDelegateCall();return true;} +xajax.js.makeWrapper=function(origFun,args,codeBlocks,returnVariable,context){var originalCall='';if(0 < returnVariable.length){originalCall+=returnVariable;originalCall+=' = ';} +var originalCall='origFun(';originalCall+=args;originalCall+='); ';var code='wrapper = function(';code+=args;code+=') { ';if(0 < returnVariable.length){code+=' var ';code+=returnVariable;code+=' = null;';} +var separator='';var bLen=codeBlocks.length;for(var b=0;b < bLen;++b){code+=separator;code+=codeBlocks[b];separator=originalCall;} +if(0 < returnVariable.length){code+=' return ';code+=returnVariable;code+=';';} +code+=' } ';var wrapper=null;context.xajaxDelegateCall=function(){eval(code);} +context.xajaxDelegateCall();return wrapper;} +xajax.dom={} +xajax.dom.assign=function(element,property,data){if('string'==typeof element) +element=xajax.$(element);switch(property){case 'innerHTML': +element.innerHTML=data;break;case 'outerHTML': +if('undefined'==typeof element.outerHTML){var r=xajax.config.baseDocument.createRange();r.setStartBefore(element);var df=r.createContextualFragment(data);element.parentNode.replaceChild(df,element);}else element.outerHTML=data;break;default: +if(xajax.tools.willChange(element,property,data)) +eval('element.'+property+' = data;');break;} +return true;} +xajax.dom.append=function(element,property,data){if('string'==typeof element) +element=xajax.$(element);eval('element.'+property+' += data;');return true;} +xajax.dom.prepend=function(element,property,data){if('string'==typeof element) +element=xajax.$(element);eval('element.'+property+' = data + element.'+property);return true;} +xajax.dom.replace=function(element,sAttribute,aData){var sSearch=aData['s'];var sReplace=aData['r'];if(sAttribute=='innerHTML') +sSearch=xajax.tools.getBrowserHTML(sSearch);if('string'==typeof element) +element=xajax.$(element);eval('var txt = element.'+sAttribute);var bFunction=false;if('function'==typeof txt){txt=txt.join('');bFunction=true;} +var start=txt.indexOf(sSearch);if(start >-1){var newTxt=[];while(start >-1){var end=start+sSearch.length;newTxt.push(txt.substr(0,start));newTxt.push(sReplace);txt=txt.substr(end,txt.length-end);start=txt.indexOf(sSearch);} +newTxt.push(txt);newTxt=newTxt.join('');if(bFunction){eval('element.'+sAttribute+'=newTxt;');}else if(xajax.tools.willChange(element,sAttribute,newTxt)){eval('element.'+sAttribute+'=newTxt;');} +} +return true;} +xajax.dom.remove=function(element){if('string'==typeof element) +element=xajax.$(element);if(element&&element.parentNode&&element.parentNode.removeChild) +element.parentNode.removeChild(element);return true;} +xajax.dom.create=function(objParent,sTag,sId){if('string'==typeof objParent) +objParent=xajax.$(objParent);var target=xajax.config.baseDocument.createElement(sTag);target.setAttribute('id',sId);if(objParent) +objParent.appendChild(target);return true;} +xajax.dom.insert=function(objSibling,sTag,sId){if('string'==typeof objSibling) +objSibling=xajax.$(objSibling);var target=xajax.config.baseDocument.createElement(sTag);target.setAttribute('id',sId);objSibling.parentNode.insertBefore(target,objSibling);return true;} +xajax.dom.insertAfter=function(objSibling,sTag,sId){if('string'==typeof objSibling) +objSibling=xajax.$(objSibling);var target=xajax.config.baseDocument.createElement(sTag);target.setAttribute('id',sId);objSibling.parentNode.insertBefore(target,objSibling.nextSibling);return true;} +xajax.dom.contextAssign=function(args){args.fullName='context assign';var code=[];code.push('this.');code.push(args.prop);code.push(' = data;');code=code.join('');args.context.xajaxDelegateCall=function(data){eval(code);} +args.context.xajaxDelegateCall(args.data);return true;} +xajax.dom.contextAppend=function(args){args.fullName='context append';var code=[];code.push('this.');code.push(args.prop);code.push(' += data;');code=code.join('');args.context.xajaxDelegateCall=function(data){eval(code);} +args.context.xajaxDelegateCall(args.data);return true;} +xajax.dom.contextPrepend=function(args){args.fullName='context prepend';var code=[];code.push('this.');code.push(args.prop);code.push(' = data + this.');code.push(args.prop);code.push(';');code=code.join('');args.context.xajaxDelegateCall=function(data){eval(code);} +args.context.xajaxDelegateCall(args.data);return true;} +xajax.domResponse={} +xajax.domResponse.startResponse=function(args){xjxElm=[];} +xajax.domResponse.createElement=function(args){eval( +[ args.tgt,' = document.createElement(args.data)' ] +.join('') +);} +xajax.domResponse.setAttribute=function(args){args.context.xajaxDelegateCall=function(){eval( +[ args.tgt,'.setAttribute(args.key, args.data)' ] +.join('') +);} +args.context.xajaxDelegateCall();} +xajax.domResponse.appendChild=function(args){args.context.xajaxDelegateCall=function(){eval( +[ args.par,'.appendChild(',args.data,')' ] +.join('') +);} +args.context.xajaxDelegateCall();} +xajax.domResponse.insertBefore=function(args){args.context.xajaxDelegateCall=function(){eval( +[ args.tgt,'.parentNode.insertBefore(',args.data,', ',args.tgt,')' ] +.join('') +);} +args.context.xajaxDelegateCall();} +xajax.domResponse.insertAfter=function(args){args.context.xajaxDelegateCall=function(){eval( +[ args.tgt,'parentNode.insertBefore(',args.data,', ',args.tgt,'.nextSibling)' ] +.join('') +);} +args.context.xajaxDelegateCall();} +xajax.domResponse.appendText=function(args){args.context.xajaxDelegateCall=function(){eval( +[ args.par,'.appendChild(document.createTextNode(args.data))' ] +.join('') +);} +args.context.xajaxDelegateCall();} +xajax.domResponse.removeChildren=function(args){var skip=args.skip||0;var remove=args.remove||-1;var element=null;args.context.xajaxDelegateCall=function(){eval([ 'element = ',args.data ].join(''));} +args.context.xajaxDelegateCall();var children=element.childNodes;for(var i in children){if(isNaN(i)==false&&children[i].nodeType==1){if(skip > 0)skip=skip-1;else if(remove!=0){if(remove > 0) +remove=remove-1;element.removeChild(children[i]);} +} +} +} +xajax.domResponse.endResponse=function(args){xjxElm=[];} +xajax.css={} +xajax.css.add=function(fileName,media){var oDoc=xajax.config.baseDocument;var oHeads=oDoc.getElementsByTagName('head');var oHead=oHeads[0];var oLinks=oHead.getElementsByTagName('link');var found=false;var iLen=oLinks.length;for(var i=0;i < iLen&&false==found;++i) +if(0 <=oLinks[i].href.indexOf(fileName)&&oLinks[i].media==media) +found=true;if(false==found){var oCSS=oDoc.createElement('link');oCSS.rel='stylesheet';oCSS.type='text/css';oCSS.href=fileName;oCSS.media=media;oHead.appendChild(oCSS);} +return true;} +xajax.css.remove=function(fileName,media){var oDoc=xajax.config.baseDocument;var oHeads=oDoc.getElementsByTagName('head');var oHead=oHeads[0];var oLinks=oHead.getElementsByTagName('link');var i=0;while(i < oLinks.length) +if(0 <=oLinks[i].href.indexOf(fileName)&&oLinks[i].media==media) +oHead.removeChild(oLinks[i]);else++i;return true;} +xajax.css.waitForCSS=function(args){var oDocSS=xajax.config.baseDocument.styleSheets;var ssEnabled=[];var iLen=oDocSS.length;for(var i=0;i < iLen;++i){ssEnabled[i]=0;try{ssEnabled[i]=oDocSS[i].cssRules.length;}catch(e){try{ssEnabled[i]=oDocSS[i].rules.length;}catch(e){} +} +} +var ssLoaded=true;var iLen=ssEnabled.length;for(var i=0;i < iLen;++i) +if(0==ssEnabled[i]) +ssLoaded=false;if(false==ssLoaded){if(xajax.tools.queue.retry(args,args.prop)){xajax.tools.queue.setWakeup(xajax.response,10);return false;} +} +return true;} +xajax.forms={} +xajax.forms.getInput=function(type,name,id){if('undefined'==typeof window.addEventListener){xajax.forms.getInput=function(type,name,id){return xajax.config.baseDocument.createElement('');} +}else{xajax.forms.getInput=function(type,name,id){var oDoc=xajax.config.baseDocument;var Obj=oDoc.createElement('input');Obj.setAttribute('type',type);Obj.setAttribute('name',name);Obj.setAttribute('id',id);return Obj;} +} +return xajax.forms.getInput(type,name,id);} +xajax.forms.createInput=function(command){command.fullName='createInput';var objParent=command.id;var sType=command.type;var sName=command.data;var sId=command.prop;if('string'==typeof objParent) +objParent=xajax.$(objParent);var target=xajax.forms.getInput(sType,sName,sId);if(objParent&&target){objParent.appendChild(target);} +return true;} +xajax.forms.insertInput=function(command){command.fullName='insertInput';var objSibling=command.id;var sType=command.type;var sName=command.data;var sId=command.prop;if('string'==typeof objSibling) +objSibling=xajax.$(objSibling);var target=xajax.forms.getInput(sType,sName,sId);if(target&&objSibling&&objSibling.parentNode) +objSibling.parentNode.insertBefore(target,objSibling);return true;} +xajax.forms.insertInputAfter=function(command){command.fullName='insertInputAfter';var objSibling=command.id;var sType=command.type;var sName=command.data;var sId=command.prop;if('string'==typeof objSibling) +objSibling=xajax.$(objSibling);var target=xajax.forms.getInput(sType,sName,sId);if(target&&objSibling&&objSibling.parentNode) +objSibling.parentNode.insertBefore(target,objSibling.nextSibling);return true;} +xajax.events={} +xajax.events.setEvent=function(command){command.fullName='addEvent';var element=command.id;var sEvent=command.prop;var code=command.data;if('string'==typeof element) +element=xajax.$(element);sEvent=xajax.tools.addOnPrefix(sEvent);code=xajax.tools.doubleQuotes(code);eval('element.'+sEvent+' = function() { '+code+'; }');return true;} +xajax.events.addHandler=function(element,sEvent,fun){if(window.addEventListener){xajax.events.addHandler=function(command){command.fullName='addHandler';var element=command.id;var sEvent=command.prop;var fun=command.data;if('string'==typeof element) +element=xajax.$(element);sEvent=xajax.tools.stripOnPrefix(sEvent);eval('element.addEventListener("'+sEvent+'", '+fun+', false);');return true;} +}else{xajax.events.addHandler=function(command){command.fullName='addHandler';var element=command.id;var sEvent=command.prop;var fun=command.data;if('string'==typeof element) +element=xajax.$(element);sEvent=xajax.tools.addOnPrefix(sEvent);eval('element.attachEvent("'+sEvent+'", '+fun+', false);');return true;} +} +return xajax.events.addHandler(element,sEvent,fun);} +xajax.events.removeHandler=function(element,sEvent,fun){if(window.removeEventListener){xajax.events.removeHandler=function(command){command.fullName='removeHandler';var element=command.id;var sEvent=command.prop;var fun=command.data;if('string'==typeof element) +element=xajax.$(element);sEvent=xajax.tools.stripOnPrefix(sEvent);eval('element.removeEventListener("'+sEvent+'", '+fun+', false);');return true;} +}else{xajax.events.removeHandler=function(command){command.fullName='removeHandler';var element=command.id;var sEvent=command.prop;var fun=command.data;if('string'==typeof element) +element=xajax.$(element);sEvent=xajax.tools.addOnPrefix(sEvent);eval('element.detachEvent("'+sEvent+'", '+fun+', false);');return true;} +} +return xajax.events.removeHandler(element,sEvent,fun);} +xajax.callback={} +xajax.callback.create=function(){var xx=xajax;var xc=xx.config;var xcb=xx.callback;var oCB={} +oCB.timers={};oCB.timers.onResponseDelay=xcb.setupTimer( +(arguments.length > 0) +? arguments[0] +:xc.defaultResponseDelayTime);oCB.timers.onExpiration=xcb.setupTimer( +(arguments.length > 1) +? arguments[1] +:xc.defaultExpirationTime);oCB.onRequest=null;oCB.onResponseDelay=null;oCB.onExpiration=null;oCB.beforeResponseProcessing=null;oCB.onFailure=null;oCB.onRedirect=null;oCB.onSuccess=null;oCB.onComplete=null;return oCB;} +xajax.callback.setupTimer=function(iDelay){return{timer:null,delay:iDelay};} +xajax.callback.clearTimer=function(oCallback,sFunction){if('undefined'!=typeof oCallback.timers){if('undefined'!=typeof oCallback.timers[sFunction]){clearTimeout(oCallback.timers[sFunction].timer);} +}else if('object'==typeof oCallback){var iLen=oCallback.length;for(var i=0;i < iLen;++i) +xajax.callback.clearTimer(oCallback[i],sFunction);} +} +xajax.callback.execute=function(oCallback,sFunction,args){if('undefined'!=typeof oCallback[sFunction]){var func=oCallback[sFunction];if('function'==typeof func){if('undefined'!=typeof oCallback.timers[sFunction]){oCallback.timers[sFunction].timer=setTimeout(function(){func(args);},oCallback.timers[sFunction].delay);} +else{func(args);} +} +}else if('object'==typeof oCallback){var iLen=oCallback.length;for(var i=0;i < iLen;++i) +xajax.callback.execute(oCallback[i],sFunction,args);} +} +xajax.callback.global=xajax.callback.create();xajax.response=xajax.tools.queue.create(xajax.config.responseQueueSize);xajax.responseSuccessCodes=['0','200'];xajax.responseErrorsForAlert=['400','401','402','403','404','500','501','502','503'];xajax.responseRedirectCodes=['301','302','307'];if('undefined'==typeof xajax.command) +xajax.command={};xajax.command.create=function(sequence,request,context){var newCmd={};newCmd.cmd='*';newCmd.fullName='* unknown command name *';newCmd.sequence=sequence;newCmd.request=request;newCmd.context=context;return newCmd;} +if('undefined'==typeof xajax.command.handler) +xajax.command.handler={};if('undefined'==typeof xajax.command.handler.handlers) +xajax.command.handler.handlers=[];xajax.command.handler.register=function(shortName,func){xajax.command.handler.handlers[shortName]=func;} +xajax.command.handler.unregister=function(shortName){var func=xajax.command.handler.handlers[shortName];delete xajax.command.handler.handlers[shortName];return func;} +xajax.command.handler.isRegistered=function(command){var shortName=command.cmd;if(xajax.command.handler.handlers[shortName]) +return true;return false;} +xajax.command.handler.call=function(command){var shortName=command.cmd;return xajax.command.handler.handlers[shortName](command);} +xajax.command.handler.register('rcmplt',function(args){xajax.completeResponse(args.request);return true;});xajax.command.handler.register('css',function(args){args.fullName='includeCSS';if('undefined'==typeof args.media) +args.media='screen';return xajax.css.add(args.data,args.media);});xajax.command.handler.register('rcss',function(args){args.fullName='removeCSS';if('undefined'==typeof args.media) +args.media='screen';return xajax.css.remove(args.data,args.media);});xajax.command.handler.register('wcss',function(args){args.fullName='waitForCSS';return xajax.css.waitForCSS(args);});xajax.command.handler.register('as',function(args){args.fullName='assign/clear';try{return xajax.dom.assign(args.target,args.prop,args.data);}catch(e){} +return true;});xajax.command.handler.register('ap',function(args){args.fullName='append';return xajax.dom.append(args.target,args.prop,args.data);});xajax.command.handler.register('pp',function(args){args.fullName='prepend';return xajax.dom.prepend(args.target,args.prop,args.data);});xajax.command.handler.register('rp',function(args){args.fullName='replace';return xajax.dom.replace(args.id,args.prop,args.data);});xajax.command.handler.register('rm',function(args){args.fullName='remove';return xajax.dom.remove(args.id);});xajax.command.handler.register('ce',function(args){args.fullName='create';return xajax.dom.create(args.id,args.data,args.prop);});xajax.command.handler.register('ie',function(args){args.fullName='insert';return xajax.dom.insert(args.id,args.data,args.prop);});xajax.command.handler.register('ia',function(args){args.fullName='insertAfter';return xajax.dom.insertAfter(args.id,args.data,args.prop);});xajax.command.handler.register('DSR',xajax.domResponse.startResponse);xajax.command.handler.register('DCE',xajax.domResponse.createElement);xajax.command.handler.register('DSA',xajax.domResponse.setAttribute);xajax.command.handler.register('DAC',xajax.domResponse.appendChild);xajax.command.handler.register('DIB',xajax.domResponse.insertBefore);xajax.command.handler.register('DIA',xajax.domResponse.insertAfter);xajax.command.handler.register('DAT',xajax.domResponse.appendText);xajax.command.handler.register('DRC',xajax.domResponse.removeChildren);xajax.command.handler.register('DER',xajax.domResponse.endResponse);xajax.command.handler.register('c:as',xajax.dom.contextAssign);xajax.command.handler.register('c:ap',xajax.dom.contextAppend);xajax.command.handler.register('c:pp',xajax.dom.contextPrepend);xajax.command.handler.register('s',xajax.js.sleep);xajax.command.handler.register('ino',xajax.js.includeScriptOnce);xajax.command.handler.register('in',xajax.js.includeScript);xajax.command.handler.register('rjs',xajax.js.removeScript);xajax.command.handler.register('wf',xajax.js.waitFor);xajax.command.handler.register('js',xajax.js.execute);xajax.command.handler.register('jc',xajax.js.call);xajax.command.handler.register('sf',xajax.js.setFunction);xajax.command.handler.register('wpf',xajax.js.wrapFunction);xajax.command.handler.register('al',function(args){args.fullName='alert';alert(args.data);return true;});xajax.command.handler.register('cc',xajax.js.confirmCommands);xajax.command.handler.register('ci',xajax.forms.createInput);xajax.command.handler.register('ii',xajax.forms.insertInput);xajax.command.handler.register('iia',xajax.forms.insertInputAfter);xajax.command.handler.register('ev',xajax.events.setEvent);xajax.command.handler.register('ah',xajax.events.addHandler);xajax.command.handler.register('rh',xajax.events.removeHandler);xajax.command.handler.register('dbg',function(args){args.fullName='debug message';return true;});xajax.initializeRequest=function(oRequest){var xx=xajax;var xc=xx.config;oRequest.append=function(opt,def){if('undefined'!=typeof this[opt]){for(var itmName in def) +if('undefined'==typeof this[opt][itmName]) +this[opt][itmName]=def[itmName];}else this[opt]=def;} +oRequest.append('commonHeaders',xc.commonHeaders);oRequest.append('postHeaders',xc.postHeaders);oRequest.append('getHeaders',xc.getHeaders);oRequest.set=function(option,defaultValue){if('undefined'==typeof this[option]) +this[option]=defaultValue;} +oRequest.set('statusMessages',xc.statusMessages);oRequest.set('waitCursor',xc.waitCursor);oRequest.set('mode',xc.defaultMode);oRequest.set('method',xc.defaultMethod);oRequest.set('URI',xc.requestURI);oRequest.set('httpVersion',xc.defaultHttpVersion);oRequest.set('contentType',xc.defaultContentType);oRequest.set('retry',xc.defaultRetry);oRequest.set('returnValue',xc.defaultReturnValue);oRequest.set('maxObjectDepth',xc.maxObjectDepth);oRequest.set('maxObjectSize',xc.maxObjectSize);oRequest.set('context',window);var xcb=xx.callback;var gcb=xcb.global;var lcb=xcb.create();lcb.take=function(frm,opt){if('undefined'!=typeof frm[opt]){lcb[opt]=frm[opt];lcb.hasEvents=true;} +delete frm[opt];} +lcb.take(oRequest,'onRequest');lcb.take(oRequest,'onResponseDelay');lcb.take(oRequest,'onExpiration');lcb.take(oRequest,'beforeResponseProcessing');lcb.take(oRequest,'onFailure');lcb.take(oRequest,'onRedirect');lcb.take(oRequest,'onSuccess');lcb.take(oRequest,'onComplete');if('undefined'!=typeof oRequest.callback){if(lcb.hasEvents) +oRequest.callback=[oRequest.callback,lcb];}else +oRequest.callback=lcb;oRequest.status=(oRequest.statusMessages) +? xc.status.update() +:xc.status.dontUpdate();oRequest.cursor=(oRequest.waitCursor) +? xc.cursor.update() +:xc.cursor.dontUpdate();oRequest.method=oRequest.method.toUpperCase();if('GET'!=oRequest.method) +oRequest.method='POST';oRequest.requestRetry=oRequest.retry;oRequest.append('postHeaders',{'content-type':oRequest.contentType +});delete oRequest['append'];delete oRequest['set'];delete oRequest['take'];if('undefined'==typeof oRequest.URI) +throw{code:10005} +} +xajax.processParameters=function(oRequest){var xx=xajax;var xt=xx.tools;var rd=[];var separator='';for(var sCommand in oRequest.functionName){if('constructor'!=sCommand){rd.push(separator);rd.push(sCommand);rd.push('=');rd.push(encodeURIComponent(oRequest.functionName[sCommand]));separator='&';} +} +var dNow=new Date();rd.push('&xjxr=');rd.push(dNow.getTime());delete dNow;if(oRequest.parameters){var i=0;var iLen=oRequest.parameters.length;while(i < iLen){var oVal=oRequest.parameters[i];if('object'==typeof oVal&&null!=oVal){try{oVal=JSON.stringify(oVal);}catch(e){oVal='';} +rd.push('&xjxargs[]=');oVal=encodeURIComponent(oVal);rd.push(oVal);++i;}else{rd.push('&xjxargs[]=');if('undefined'==typeof oVal||null==oVal){rd.push('*');}else{var sType=typeof oVal;if('string'==sType) +rd.push('S');else if('boolean'==sType) +rd.push('B');else if('number'==sType) +rd.push('N');oVal=encodeURIComponent(oVal);rd.push(oVal);} +++i;} +} +} +oRequest.requestURI=oRequest.URI;if('GET'==oRequest.method){oRequest.requestURI+=oRequest.requestURI.indexOf('?')==-1 ? '?':'&';oRequest.requestURI+=rd.join('');rd=[];} +oRequest.requestData=rd.join('');} +xajax.prepareRequest=function(oRequest){var xx=xajax;var xt=xx.tools;oRequest.request=xt.getRequestObject();oRequest.setRequestHeaders=function(headers){if('object'==typeof headers){for(var optionName in headers) +this.request.setRequestHeader(optionName,headers[optionName]);} +} +oRequest.setCommonRequestHeaders=function(){this.setRequestHeaders(this.commonHeaders);if(this.challengeResponse) +this.request.setRequestHeader('challenge-response',this.challengeResponse);} +oRequest.setPostRequestHeaders=function(){this.setRequestHeaders(this.postHeaders);} +oRequest.setGetRequestHeaders=function(){this.setRequestHeaders(this.getHeaders);} +if('asynchronous'==oRequest.mode){oRequest.request.onreadystatechange=function(){if(oRequest.request.readyState!=4) +return;xajax.responseReceived(oRequest);} +oRequest.finishRequest=function(){return this.returnValue;} +}else{oRequest.finishRequest=function(){return xajax.responseReceived(oRequest);} +} +if('undefined'!=typeof oRequest.userName&&'undefined'!=typeof oRequest.password){oRequest.open=function(){this.request.open( +this.method, +this.requestURI, +'asynchronous'==this.mode, +oRequest.userName, +oRequest.password);} +}else{oRequest.open=function(){this.request.open( +this.method, +this.requestURI, +'asynchronous'==this.mode);} +} +if('POST'==oRequest.method){oRequest.applyRequestHeaders=function(){this.setCommonRequestHeaders();try{this.setPostRequestHeaders();}catch(e){this.method='GET';this.requestURI+=this.requestURI.indexOf('?')==-1 ? '?':'&';this.requestURI+=this.requestData;this.requestData='';if(0==this.requestRetry)this.requestRetry=1;throw e;} +} +}else{oRequest.applyRequestHeaders=function(){this.setCommonRequestHeaders();this.setGetRequestHeaders();} +} +} +xajax.request=function(){var numArgs=arguments.length;if(0==numArgs) +return false;var oRequest={} +if(1 < numArgs) +oRequest=arguments[1];oRequest.functionName=arguments[0];var xx=xajax;xx.initializeRequest(oRequest);xx.processParameters(oRequest);while(0 < oRequest.requestRetry){try{--oRequest.requestRetry;xx.prepareRequest(oRequest);return xx.submitRequest(oRequest);}catch(e){xajax.callback.execute( +[xajax.callback.global,oRequest.callback], +'onFailure', +oRequest +);if(0==oRequest.requestRetry) +throw e;} +} +} +xajax.submitRequest=function(oRequest){oRequest.status.onRequest();var xcb=xajax.callback;var gcb=xcb.global;var lcb=oRequest.callback;xcb.execute([gcb,lcb],'onResponseDelay',oRequest);xcb.execute([gcb,lcb],'onExpiration',oRequest);xcb.execute([gcb,lcb],'onRequest',oRequest);oRequest.open();oRequest.applyRequestHeaders();oRequest.cursor.onWaiting();oRequest.status.onWaiting();xajax._internalSend(oRequest);return oRequest.finishRequest();} +xajax._internalSend=function(oRequest){oRequest.request.send(oRequest.requestData);} +xajax.abortRequest=function(oRequest){oRequest.aborted=true;oRequest.request.abort();xajax.completeResponse(oRequest);} +xajax.responseReceived=function(oRequest){var xx=xajax;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;if(oRequest.aborted) +return;xcb.clearTimer([gcb,lcb],'onExpiration');xcb.clearTimer([gcb,lcb],'onResponseDelay');xcb.execute([gcb,lcb],'beforeResponseProcessing',oRequest);var challenge=oRequest.request.getResponseHeader('challenge');if(challenge){oRequest.challengeResponse=challenge;xx.prepareRequest(oRequest);return xx.submitRequest(oRequest);} +var fProc=xx.getResponseProcessor(oRequest);if('undefined'==typeof fProc){xcb.execute([gcb,lcb],'onFailure',oRequest);xx.completeResponse(oRequest);return;} +return fProc(oRequest);} +xajax.getResponseProcessor=function(oRequest){var fProc;if('undefined'==typeof oRequest.responseProcessor){var cTyp=oRequest.request.getResponseHeader('content-type');if(cTyp){if(0 <=cTyp.indexOf('text/xml')){fProc=xajax.responseProcessor.xml;}else if(0 <=cTyp.indexOf('application/json')){fProc=xajax.responseProcessor.json;} +} +}else fProc=oRequest.responseProcessor;return fProc;} +xajax.executeCommand=function(command){if(xajax.command.handler.isRegistered(command)){if(command.id) +command.target=xajax.$(command.id);if(false==xajax.command.handler.call(command)){xajax.tools.queue.pushFront(xajax.response,command);return false;} +} +return true;} +xajax.completeResponse=function(oRequest){xajax.callback.execute( +[xajax.callback.global,oRequest.callback], +'onComplete', +oRequest +);oRequest.cursor.onComplete();oRequest.status.onComplete();delete oRequest['functionName'];delete oRequest['requestURI'];delete oRequest['requestData'];delete oRequest['requestRetry'];delete oRequest['request'];delete oRequest['set'];delete oRequest['open'];delete oRequest['setRequestHeaders'];delete oRequest['setCommonRequestHeaders'];delete oRequest['setPostRequestHeaders'];delete oRequest['setGetRequestHeaders'];delete oRequest['applyRequestHeaders'];delete oRequest['finishRequest'];delete oRequest['status'];delete oRequest['cursor'];delete oRequest['challengeResponse'];} +xajax.$=xajax.tools.$;xajax.getFormValues=xajax.tools.getFormValues;xajax.isLoaded=true;xjx={} +xjx.$=xajax.tools.$;xjx.getFormValues=xajax.tools.getFormValues;xjx.request=xajax.request;if('undefined'==typeof JSON)xajax.js.includeScript({data:xajax.config.JavaScriptURI+'xajax_js/JSON.js'}); \ No newline at end of file diff --git a/www/include/xajax/xajax_js/xajax_core_uncompressed.js b/www/include/xajax/xajax_js/xajax_core_uncompressed.js new file mode 100644 index 00000000..91cc6919 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_core_uncompressed.js @@ -0,0 +1,3739 @@ +/* + File: xajax_core.js + + This file contains the definition of the main xajax javascript core. + + This is the client side code which runs on the web browser or similar + web enabled application. Include this in the HEAD of each page for + which you wish to use xajax. + + Title: xajax core javascript library + + Please see for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajax_core_uncompressed.js 327 2007-02-28 16:55:26Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajax.config + + This class contains all the default configuration settings. These + are application level settings; however, they can be overridden + by including a xajax.config definition prior to including the + file, or by specifying the appropriate configuration + options on a per call basis. +*/ +if ('undefined' == typeof xajax) + xajax = {}; + +if ('undefined' == typeof xajax.config) + xajax.config = {}; + +/* + Function: xajax.config.setDefault + + This function will set a default configuration option if it is + not already set. + + Parameters: + option - (string): + The name of the option that will be set. + + defaultValue - (unknown): + The value to use if a value was not already set. +*/ +xajax.config.setDefault = function(option, defaultValue) { + if ('undefined' == typeof xajax.config[option]) + xajax.config[option] = defaultValue; +} + +/* + Object: commonHeaders + + An array of header entries where the array key is the header + option name and the associated value is the value that will + set when the request object is initialized. + + These headers will be set for both POST and GET requests. +*/ +xajax.config.setDefault('commonHeaders', { + 'If-Modified-Since': 'Sat, 1 Jan 2000 00:00:00 GMT' + }); + +/* + Object: postHeaders + + An array of header entries where the array key is the header + option name and the associated value is the value that will + set when the request object is initialized. +*/ +xajax.config.setDefault('postHeaders', {}); + +/* + Object: getHeaders + + An array of header entries where the array key is the header + option name and the associated value is the value that will + set when the request object is initialized. +*/ +xajax.config.setDefault('getHeaders', {}); + +/* + Boolean: waitCursor + + true - xajax should display a wait cursor when making a request + false - xajax should not show a wait cursor during a request +*/ +xajax.config.setDefault('waitCursor', false); + +/* + Boolean: statusMessages + + true - xajax should update the status bar during a request + false - xajax should not display the status of the request +*/ +xajax.config.setDefault('statusMessages', false); + +/* + Object: baseDocument + + The base document that will be used throughout the code for + locating elements by ID. +*/ +xajax.config.setDefault('baseDocument', document); + +/* + String: requestURI + + The URI that requests will be sent to. +*/ +xajax.config.setDefault('requestURI', xajax.config.baseDocument.URL); + +/* + String: defaultMode + + The request mode. + + 'asynchronous' - The request will immediately return, the + response will be processed when (and if) it is received. + + 'synchronous' - The request will block, waiting for the + response. This option allows the server to return + a value directly to the caller. +*/ +xajax.config.setDefault('defaultMode', 'asynchronous'); + +/* + String: defaultHttpVersion + + The Hyper Text Transport Protocol version designated in the + header of the request. +*/ +xajax.config.setDefault('defaultHttpVersion', 'HTTP/1.1'); + +/* + String: defaultContentType + + The content type designated in the header of the request. +*/ +xajax.config.setDefault('defaultContentType', 'application/x-www-form-urlencoded'); + +/* + Integer: defaultResponseDelayTime + + The delay time, in milliseconds, associated with the + event. +*/ +xajax.config.setDefault('defaultResponseDelayTime', 1000); + +/* + Integer: defaultExpirationTime + + The amount of time to wait, in milliseconds, before a request + is considered expired. This is used to trigger the + to form a URL. +*/ +xajax.config.setDefault('defaultMethod', 'POST'); // W3C: Method is case sensitive + +/* + Integer: defaultRetry + + The number of times a request should be retried + if it expires. +*/ +xajax.config.setDefault('defaultRetry', 5); + +/* + Object: defaultReturnValue + + The value returned by when in asynchronous + mode, or when a syncrhonous call does not specify the + return value. +*/ +xajax.config.setDefault('defaultReturnValue', false); + +/* + Integer: maxObjectDepth + + The maximum depth of recursion allowed when serializing + objects to be sent to the server in a request. +*/ +xajax.config.setDefault('maxObjectDepth', 20); + +/* + Integer: maxObjectSize + + The maximum number of members allowed when serializing + objects to be sent to the server in a request. +*/ +xajax.config.setDefault('maxObjectSize', 2000); + +xajax.config.setDefault('responseQueueSize', 1000); + +/* + Class: xajax.config.status + + Provides support for updating the browser's status bar during + the request process. By splitting the status bar functionality + into an object, the xajax developer has the opportunity to + customize the status bar messages prior to sending xajax requests. +*/ +xajax.config.status = { + /* + Function: update + + Constructs and returns a set of event handlers that will be + called by the xajax framework to set the status bar messages. + */ + update: function() { + return { + onRequest: function() { + window.status = 'Sending Request...'; + }, + onWaiting: function() { + window.status = 'Waiting for Response...'; + }, + onProcessing: function() { + window.status = 'Processing...'; + }, + onComplete: function() { + window.status = 'Done.'; + } + } + }, + /* + Function: dontUpdate + + Constructs and returns a set of event handlers that will be + called by the xajax framework where status bar updates + would normally occur. + */ + dontUpdate: function() { + return { + onRequest: function() {}, + onWaiting: function() {}, + onProcessing: function() {}, + onComplete: function() {} + } + } +} + +/* + Class: xajax.config.cursor + + Provides the base functionality for updating the browser's cursor + during requests. By splitting this functionalityh into an object + of it's own, xajax developers can now customize the functionality + prior to submitting requests. +*/ +xajax.config.cursor = { + /* + Function: update + + Constructs and returns a set of event handlers that will be + called by the xajax framework to effect the status of the + cursor during requests. + */ + update: function() { + return { + onWaiting: function() { + if (xajax.config.baseDocument.body) + xajax.config.baseDocument.body.style.cursor = 'wait'; + }, + onComplete: function() { + xajax.config.baseDocument.body.style.cursor = 'auto'; + } + } + }, + /* + Function: dontUpdate + + Constructs and returns a set of event handlers that will + be called by the xajax framework where cursor status changes + would typically be made during the handling of requests. + */ + dontUpdate: function() { + return { + onWaiting: function() {}, + onComplete: function() {} + } + } +} + +/* + Class: xajax.tools + + This contains utility functions which are used throughout + the xajax core. +*/ +xajax.tools = {} + +/* + Function: xajax.tools.$ + + Shorthand for finding a uniquely named element within + the document. + + Parameters: + sId - (string): + The unique name of the element (specified by the + ID attribute), not to be confused with the name + attribute on form elements. + + Returns: + + object - The element found or null. + + Note: + This function uses the + which allows to operate on the main window + document as well as documents from contained + iframes and child windows. + + See also: + and +*/ +xajax.tools.$ = function(sId) { + if (!sId) + return null; + //sId not an string so return it maybe its an object. + if(typeof sId != 'string') + return sId; + + var oDoc = xajax.config.baseDocument; + + var obj = oDoc.getElementById(sId); + if (obj) + return obj; + + if (oDoc.all) + return oDoc.all[sId]; + + return obj; +} + +/* + Function xajax.tools.in_array + + Looks for a value within the specified array and, if found, + returns true; otherwise it returns false. + + Parameters: + array - (object): + The array to be searched. + + valueToCheck - (object): + The value to search for. + + Returns: + + true : The value is one of the values contained in the + array. + + false : The value was not found in the specified array. +*/ +xajax.tools.in_array = function(array, valueToCheck) { + var i = 0; + var l = array.length; + while (i < l) { + if (array[i] == valueToCheck) + return true; + ++i; + } + return false; +} + +/* + Function: xajax.tools.doubleQuotes + + Replace all occurances of the single quote character with a double + quote character. + + Parameters: + + haystack - The source string to be scanned. + + Returns: false on error + + string - A new string with the modifications applied. +*/ +xajax.tools.doubleQuotes = function(haystack) { + if(typeof haystack == 'undefined') return false; + return haystack.replace(new RegExp("'", 'g'), '"'); +} + +/* + Function: xajax.tools.singleQuotes + + Replace all occurances of the double quote character with a single + quote character. + + haystack - The source string to be scanned. + + Returns: + + string - A new string with the modification applied. +*/ +/* +xajax.tools.singleQuotes = function(haystack) { + return haystack.replace(new RegExp('"', 'g'), "'"); +} +*/ + +/* + Function: xajax.tools._escape + + Determine if the specified value contains special characters and + create a CDATA section so the value can be safely transmitted. + + Parameters: + + data - (string or other): + The source string value to be evaluated or an object of unknown + type. + + Returns: + + string - The string value, escaped if necessary or the object provided + if it is not a string. + + Note: + When the specified object is NOT a string, the value is returned + as is. +*/ +/* +xajax.tools._escape = function(data) { + if ('undefined' == typeof data) + return data; + // 'object' is handled elsewhere, + // 'string' handled below, + // 'number' will be returned here + // 'boolean' will be returned here + if ('string' != typeof data) + return data; + + var needCDATA = false; + + if (encodeURIComponent(data) != data) { + needCDATA = true; + + var segments = data.split(''); + var fragLen = fragments.length; + segment = ''; + for (var j = 0; j < fragLen; ++j) { + if (0 != j) + segment += ']]]]>'; + segment += fragments[j]; + } + if (0 != i) + data.push(''; + + return data; +} +*/ + +/* + Function: xajax.tools._objectToXML + + Convert a javascript object or array into XML suitable for + transmission to the server. + + Parameters: + + obj - The object or array to convert. + + guard - An object used to track the level of recursion + when encoding javascript objects. When an object + contains a reference to it's parent and the parent + contains a reference to the child, an infinite + recursion will cause some browsers to crash. + + Returns: + + string - the xml representation of the object or array. + + See also: + + and +*/ + +/* +xajax.tools._objectToXML = function(obj, guard) { + var aXml = []; + aXml.push(''); + for (var key in obj) { + ++guard.size; + if (guard.maxSize < guard.size) + return aXml.join(''); + if ('undefined' != typeof obj[key]) { + if ('constructor' == key) + continue; + if ('function' == typeof obj[key]) + continue; + aXml.push(''); + var val = xajax.tools._escape(key); + aXml.push(val); + aXml.push(''); + if ('object' == typeof obj[key]) { + ++guard.depth; + if (guard.maxDepth > guard.depth) { + try { + aXml.push(xajax.tools._objectToXML(obj[key], guard)); + } catch (e) { + // do nothing, if the debug module is installed + // it will catch the exception and handle it + } + } + --guard.depth; + } else { + var val = xajax.tools._escape(obj[key]); + if ('undefined' == typeof val || null == val) { + aXml.push('*'); + } else { + var sType = typeof val; + if ('string' == sType) + aXml.push('S'); + else if ('boolean' == sType) + aXml.push('B'); + else if ('number' == sType) + aXml.push('N'); + aXml.push(val); + } + } + + aXml.push(''); + } + } + aXml.push(''); + + return aXml.join(''); +} +*/ + +/* + Function: xajax.tools._enforceDataType + + Ensure that the javascript variable created is of the correct data type. + + Parameters: + value (string) + + Returns: + + (unknown) - The value provided converted to the correct data type. +*/ +xajax.tools._enforceDataType = function(value) { + value = new String(value); + var type = value.substr(0, 1); + value = value.substr(1); + + if ('*' == type) + value = null; + else if ('N' == type) + value = value - 0; + else if ('B' == type) + value = !!value; +// else if ('S' == type) +// value = new String(value); + + return value; +} + +/* + Function: xajax.tools._nodeToObject + + Deserialize a javascript object from an XML node. + + Parameters: + + node - A node, likely from the xml returned by the server. + + Returns: + + object - The object extracted from the xml node. +*/ +xajax.tools._nodeToObject = function(node) { + if (null == node) + return ''; + + if ('undefined' != typeof node.nodeName) { + if ('#cdata-section' == node.nodeName || '#text' == node.nodeName) { + var data = ''; + do if (node.data) data += node.data; while (node = node.nextSibling); + return xajax.tools._enforceDataType(data); + } else if ('xjxobj' == node.nodeName) { + var key = null; + var value = null; + var data = new Array; + var child = node.firstChild; + while (child) { + if ('e' == child.nodeName) { + var grandChild = child.firstChild; + while (grandChild) { + if ('k' == grandChild.nodeName) + // Don't support objects here, only number, string, etc... + key = xajax.tools._enforceDataType(grandChild.firstChild.data); + else ('v' == grandChild.nodeName) + // Value might be object, string, number, boolean... even null or undefined + value = xajax.tools._nodeToObject(grandChild.firstChild); + grandChild = grandChild.nextSibling; + } + // Allow the value to be null or undefined (or a value) + if (null != key) { // && null != value) { + data[key] = value; + key = value = null; + } + } + child = child.nextSibling; + } + return data; + } + } + + throw { code: 10001, data: node.nodeName }; +} + +/* + Function: xajax.tools.getRequestObject + + Construct an XMLHttpRequest object dependent on the capabilities + of the browser. + + Returns: + + object - Javascript XHR object. +*/ +xajax.tools.getRequestObject = function() { + if ('undefined' != typeof XMLHttpRequest) { + xajax.tools.getRequestObject = function() { + return new XMLHttpRequest(); + } + } else if ('undefined' != typeof ActiveXObject) { + xajax.tools.getRequestObject = function() { + try { + return new ActiveXObject('Msxml2.XMLHTTP.4.0'); + } catch (e) { + xajax.tools.getRequestObject = function() { + try { + return new ActiveXObject('Msxml2.XMLHTTP'); + } catch (e2) { + xajax.tools.getRequestObject = function() { + return new ActiveXObject('Microsoft.XMLHTTP'); + } + return xajax.tools.getRequestObject(); + } + } + return xajax.tools.getRequestObject(); + } + } + } else if (window.createRequest) { + xajax.tools.getRequestObject = function() { + return window.createRequest(); + } + } else { + xajax.tools.getRequestObject = function() { + throw { code: 10002 }; + } + } + + // this would seem to cause an infinite loop, however, the function should + // be reassigned by now and therefore, it will not loop. + return xajax.tools.getRequestObject(); +} + +/* + Function: xajax.tools.getBrowserHTML + + Insert the specified string of HTML into the document, then + extract it. This gives the browser the ability to validate + the code and to apply any transformations it deems appropriate. + + Parameters: + + sValue - (string): + A block of html code or text to be inserted into the + browser's document. + + Returns: + + The (potentially modified) html code or text. +*/ +xajax.tools.getBrowserHTML = function(sValue) { + var oDoc = xajax.config.baseDocument; + if (!oDoc.body) + return ''; + + var elWorkspace = xajax.$('xajax_temp_workspace'); + if (!elWorkspace) + { + elWorkspace = oDoc.createElement('div'); + elWorkspace.setAttribute('id', 'xajax_temp_workspace'); + elWorkspace.style.display = 'none'; + elWorkspace.style.visibility = 'hidden'; + oDoc.body.appendChild(elWorkspace); + } + elWorkspace.innerHTML = sValue; + var browserHTML = elWorkspace.innerHTML; + elWorkspace.innerHTML = ''; + + return browserHTML; +} + +/* + Function: xajax.tools.willChange + + Tests to see if the specified data is the same as the current + value of the element's attribute. + + Parameters: + element - (string or object): + The element or it's unique name (specified by the ID attribute) + + attribute - (string): + The name of the attribute. + + newData - (string): + The value to be compared with the current value of the specified + element. + + Returns: + + true - The specified value differs from the current attribute value. + false - The specified value is the same as the current value. +*/ +xajax.tools.willChange = function(element, attribute, newData) { + if ('string' == typeof element) + element = xajax.$(element); + if (element) { + var oldData; + eval('oldData=element.'+attribute); + return (newData != oldData); + } + + return false; +} + +/* + Function: xajax.tools.getFormValues + + Build an associative array of form elements and their values from + the specified form. + + Parameters: + + element - (string): The unique name (id) of the form to be processed. + disabled - (boolean, optional): Include form elements which are currently disabled. + prefix - (string, optional): A prefix used for selecting form elements. + + Returns: + + An associative array of form element id and value. +*/ +xajax.tools.getFormValues = function(parent) { + var submitDisabledElements = false; + if (arguments.length > 1 && arguments[1] == true) + submitDisabledElements = true; + + var prefix = ''; + if(arguments.length > 2) + prefix = arguments[2]; + + if ('string' == typeof parent) + parent = xajax.$(parent); + + var aFormValues = {}; + +// JW: Removing these tests so that form values can be retrieved from a specified +// container element like a DIV, regardless of whether they exist in a form or not. +// +// if (parent.tagName) +// if ('FORM' == parent.tagName.toUpperCase()) + if (parent) + if (parent.childNodes) + xajax.tools._getFormValues(aFormValues, parent.childNodes, submitDisabledElements, prefix); + + return aFormValues; +} + +/* + Function: xajax.tools._getFormValues + + Used internally by to recursively get the value + of form elements. This function will extract all form element values + regardless of the depth of the element within the form. +*/ +xajax.tools._getFormValues = function(aFormValues, children, submitDisabledElements, prefix) +{ + var iLen = children.length; + for (var i = 0; i < iLen; ++i) { + var child = children[i]; + if (('undefined' != typeof child.childNodes) && (child.type != 'select-one') && (child.type != 'select-multiple')) + xajax.tools._getFormValues(aFormValues, child.childNodes, submitDisabledElements, prefix); + xajax.tools._getFormValue(aFormValues, child, submitDisabledElements, prefix); + } +} + +/* + Function: xajax.tools._getFormValue + + Used internally by to extract a single form value. + This will detect the type of element (radio, checkbox, multi-select) and + add it's value(s) to the form values array. + + Modified version for multidimensional arrays +*/ +xajax.tools._getFormValue = function(aFormValues, child, submitDisabledElements, prefix) +{ + if (!child.name) + return; + + if ('PARAM' == child.tagName) return; + + if (child.disabled) + if (true == child.disabled) + if (false == submitDisabledElements) + return; + + if (prefix != child.name.substring(0, prefix.length)) + return; + + if (child.type) + if (child.type == 'radio' || child.type == 'checkbox') + if (false == child.checked) + return; + + var name = child.name; + + var values = []; + + if ('select-multiple' == child.type) { + var jLen = child.length; + for (var j = 0; j < jLen; ++j) { + var option = child.options[j]; + if (true == option.selected) + values.push(option.value); + } + } else { + values = child.value; + } + + var keyBegin = name.indexOf('['); + /* exists name/object before the Bracket?*/ + if (0 <= keyBegin) { + var n = name; + var k = n.substr(0, n.indexOf('[')); + var a = n.substr(n.indexOf('[')); + if (typeof aFormValues[k] == 'undefined') + aFormValues[k] = {}; + var p = aFormValues; // pointer reset + while (a.length != 0) { + var sa = a.substr(0, a.indexOf(']')+1); + + var lk = k; //save last key + var lp = p; //save last pointer + + a = a.substr(a.indexOf(']')+1); + p = p[k]; + k = sa.substr(1, sa.length-2); + if (k == '') { + if ('select-multiple' == child.type) { + k = lk; //restore last key + p = lp; + } else { + k = p.length; + } + } + if (typeof k == 'undefined') + { + /*check against the global aFormValues Stack wich is the next(last) usable index */ + k=0; + for (var i in lp[lk]) k++; + } + if (typeof p[k] == 'undefined'){ + + p[k] ={}; + } + } + p[k] = values; + } else { + aFormValues[name] = values; + } +} + + +/* + Function: xajax.tools.stripOnPrefix + + Detect, and if found, remove the prefix 'on' from the specified + string. This is used while working with event handlers. + + Parameters: + + sEventName - (string): The string to be modified. + + Returns: + + string - The modified string. +*/ +xajax.tools.stripOnPrefix = function(sEventName) { + sEventName = sEventName.toLowerCase(); + if (0 == sEventName.indexOf('on')) + sEventName = sEventName.replace(/on/,''); + + return sEventName; +} + +/* + Function: xajax.tools.addOnPrefix + + Detect, and add if not found, the prefix 'on' from the specified + string. This is used while working with event handlers. + + Parameters: + + sEventName - (string): The string to be modified. + + Returns: + + string - The modified string. +*/ +xajax.tools.addOnPrefix = function(sEventName) { + sEventName = sEventName.toLowerCase(); + if (0 != sEventName.indexOf('on')) + sEventName = 'on' + sEventName; + + return sEventName; +} + + + +/* + Class: xajax.tools.xml + + An object that contains utility function for processing + xml response packets. +*/ +xajax.tools.xml = {}; + +/* + Function: xajax.tools.xml.parseAttributes + + Take the parameters passed in the command of the XML response + and convert them to parameters of the args object. This will + serve as the command object which will be stored in the + response command queue. + + Parameters: + + child - (object): The xml child node which contains the + attributes for the current response command. + + obj - (object): The current response command that will have the + attributes applied. +*/ +xajax.tools.xml.parseAttributes = function(child, obj) { + var iLen = child.attributes.length; + for (var i = 0; i < iLen; ++i) { + var attr = child.attributes[i]; + obj[attr.name] = attr.value; + } +} + +/* + Function: xajax.tools.xml.parseChildren + + Parses the child nodes of the command of the response XML. Generally, + the child nodes contain the data element of the command; this member + may be an object, which will be deserialized by + + Parameters: + + child - (object): The xml node that contains the child (data) for + the current response command object. + + obj - (object): The response command object. +*/ +xajax.tools.xml.parseChildren = function(child, obj) { + obj.data = ''; + if (0 < child.childNodes.length) { + if (1 < child.childNodes.length) { + var grandChild = child.firstChild; + do { + if ('#cdata-section' == grandChild.nodeName || '#text' == grandChild.nodeName) { + obj.data += grandChild.data; + } + } while (grandChild = grandChild.nextSibling); + } else { + var grandChild = child.firstChild; + if ('xjxobj' == grandChild.nodeName) { + obj.data = xajax.tools._nodeToObject(grandChild); + return; + } else if ('#cdata-section' == grandChild.nodeName || '#text' == grandChild.nodeName) { + obj.data = grandChild.data; + } + } + } else if ('undefined' != typeof child.data) { + obj.data = child.data; + } + + obj.data = xajax.tools._enforceDataType(obj.data); +} + +/* + Function: xajax.tools.xml.processFragment + + Parameters: + + xmlNode - (object): The first xml node in the xml fragment. + seq - (number): A counter used to keep track of the sequence + of this command in the response. + oRet - (object): A variable that is used to return the request + "return value" for use with synchronous requests. +*/ +xajax.tools.xml.processFragment = function(xmlNode, seq, oRet, oRequest) { + var xx = xajax; + var xt = xx.tools; + while (xmlNode) { + if ('cmd' == xmlNode.nodeName) { + var obj = {}; + obj.fullName = '*unknown*'; + obj.sequence = seq; + obj.request = oRequest; + obj.context = oRequest.context; + + xt.xml.parseAttributes(xmlNode, obj); + xt.xml.parseChildren(xmlNode, obj); + + xt.queue.push(xx.response, obj); + } else if ('xjxrv' == xmlNode.nodeName) { + oRet = xt._nodeToObject(xmlNode.firstChild); + } else if ('debugmsg' == xmlNode.nodeName) { + // txt = xt._nodeToObject(xmlNode.firstChild); + } else + throw { code: 10004, data: xmlNode.nodeName } + + ++seq; + xmlNode = xmlNode.nextSibling; + } + return oRet; +} + +/* + Class: xajax.tools.queue + + This contains the code and variables for building, populating + and processing First In Last Out (FILO) buffers. +*/ +xajax.tools.queue = {} + +/* + Function: create + + Construct and return a new queue object. + + Parameters: + + size - (integer): + The number of entries the queue will be able to hold. +*/ +xajax.tools.queue.create = function(size) { + return { + start: 0, + size: size, + end: 0, + commands: [], + timeout: null + } +} + +/* + Function: xajax.tools.queue.retry + + Maintains a retry counter for the given object. + + Parameters: + + obj - (object): + The object to track the retry count for. + + count - (integer): + The number of times the operation should be attempted + before a failure is indicated. + + Returns: + + true - The object has not exhausted all the retries. + false - The object has exhausted the retry count specified. +*/ +xajax.tools.queue.retry = function(obj, count) { + var retries = obj.retries; + if (retries) { + --retries; + if (1 > retries) + return false; + } else retries = count; + obj.retries = retries; + return true; +} + +/* + Function: xajax.tools.queue.rewind + + Rewind the buffer head pointer, effectively reinserting the + last retrieved object into the buffer. + + Parameters: + + theQ - (object): + The queue to be rewound. +*/ +xajax.tools.queue.rewind = function(theQ) { + if (0 < theQ.start) + --theQ.start; + else + theQ.start = theQ.size; +} + +/* + Function: xajax.tools.queue.setWakeup + + Set or reset a timeout that is used to restart processing + of the queue. This allows the queue to asynchronously wait + for an event to occur (giving the browser time to process + pending events, like loading files) + + Parameters: + + theQ - (object): + The queue to process upon timeout. + + when - (integer): + The number of milliseconds to wait before starting/ + restarting the processing of the queue. +*/ +xajax.tools.queue.setWakeup = function(theQ, when) { + if (null != theQ.timeout) { + clearTimeout(theQ.timeout); + theQ.timeout = null; + } + theQ.timout = setTimeout(function() { xajax.tools.queue.process(theQ); }, when); +} + +/* + Function: xajax.tools.queue.process + + While entries exist in the queue, pull and entry out and + process it's command. When a command returns false, the + processing is halted. + + Parameters: + + theQ - (object): The queue object to process. This should + have been crated by calling . + + Returns: + + true - The queue was fully processed and is now empty. + false - The queue processing was halted before the + queue was fully processed. + + Note: + + - Use or call this function to + cause the queue processing to continue. + + - This will clear the associated timeout, this function is not + designed to be reentrant. + + - When an exception is caught, do nothing; if the debug module + is installed, it will catch the exception and handle it. +*/ +xajax.tools.queue.process = function(theQ) { + if (null != theQ.timeout) { + clearTimeout(theQ.timeout); + theQ.timeout = null; + } + var obj = xajax.tools.queue.pop(theQ); + while (null != obj) { + try { + if (false == xajax.executeCommand(obj)) + return false; + } catch (e) { + } + delete obj; + + obj = xajax.tools.queue.pop(theQ); + } + return true; +} + +/* + Function: xajax.tools.queue.push + + Push a new object into the tail of the buffer maintained by the + specified queue object. + + Parameters: + + theQ - (object): + The queue in which you would like the object stored. + + obj - (object): + The object you would like stored in the queue. +*/ +xajax.tools.queue.push = function(theQ, obj) { + var next = theQ.end + 1; + if (next > theQ.size) + next = 0; + if (next != theQ.start) { + theQ.commands[theQ.end] = obj; + theQ.end = next; + } else + throw { code: 10003 } +} + +/* + Function: xajax.tools.queue.pushFront + + Push a new object into the head of the buffer maintained by + the specified queue object. This effectively pushes an object + to the front of the queue... it will be processed first. + + Parameters: + + theQ - (object): + The queue in which you would like the object stored. + + obj - (object): + The object you would like stored in the queue. +*/ +xajax.tools.queue.pushFront = function(theQ, obj) { + xajax.tools.queue.rewind(theQ); + theQ.commands[theQ.start] = obj; +} + +/* + Function: xajax.tools.queue.pop + + Attempt to pop an object off the head of the queue. + + Parameters: + + theQ - (object): + The queue object you would like to modify. + + Returns: + + object - The object that was at the head of the queue or + null if the queue was empty. +*/ +xajax.tools.queue.pop = function(theQ) { + var next = theQ.start; + if (next == theQ.end) + return null; + next++; + if (next > theQ.size) + next = 0; + var obj = theQ.commands[theQ.start]; + delete theQ.commands[theQ.start]; + theQ.start = next; + return obj; +} + +/* + Class: xajax.responseProcessor +*/ +xajax.responseProcessor = {}; + +/* + Function: xajax.responseProcessor.json + + Parse the JSON response into a series of commands. The commands + are constructed by calling and + . + + Parameters: + + oRequest - (object): The request context object. +*/ + + +xajax.tools.json = {} + +xajax.tools.json.processFragment = function(nodes, seq, oRet, oRequest) { + var xx = xajax; + var xt = xx.tools; + for (nodeName in nodes) { + if ('xjxobj' == nodeName) { + for (a in nodes[nodeName]) + { + + /* + prevents from using not numbered indexes of 'xjxobj' + nodes[nodeName][a]= "0" is an valid xajax response stack item + nodes[nodeName][a]= "pop" is an method from somewhere but not from xjxobj + */ + if( parseInt(a) !=a) continue; + + var obj = nodes[nodeName][a]; + + obj.fullName = '*unknown*'; + obj.sequence = seq; + obj.request = oRequest; + obj.context = oRequest.context; + xt.queue.push(xx.response, obj); + ++seq; + + } + } else if ('xjxrv' == nodeName) { + oRet = nodes[nodeName]; + } else if ('debugmsg' == nodeName) { + txt = nodes[nodeName]; + } else + throw { code: 10004, data: obj.fullName} + } + return oRet; +} + +xajax.responseProcessor.json = function (oRequest) { + + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + + var oRet = oRequest.returnValue; + + if (xt.in_array(xx.responseSuccessCodes, oRequest.request.status)) { + xcb.execute([gcb, lcb], 'onSuccess', oRequest); + var seq = 0; + if (oRequest.request.responseText) { + try { + var responseJSON = eval('('+oRequest.request.responseText+')'); + } catch (ex) { + throw(ex); + } + if ( ('object' == typeof responseJSON) && ('object' == typeof responseJSON.xjxobj) ) { + oRequest.status.onProcessing(); + oRet = xt.json.processFragment(responseJSON, seq, oRet, oRequest); + } else { + } + } + var obj = {}; + obj.fullName = 'Response Complete'; + obj.sequence = seq; + obj.request = oRequest; + obj.context = oRequest.context; + obj.cmd = 'rcmplt'; + xt.queue.push(xx.response, obj); + + // do not re-start the queue if a timeout is set + if (null == xx.response.timeout) + xt.queue.process(xx.response); + } else if (xt.in_array(xx.responseRedirectCodes, oRequest.request.status)) { + xcb.execute([gcb, lcb], 'onRedirect', oRequest); + window.location = oRequest.request.getResponseHeader('location'); + xx.completeResponse(oRequest); + } else if (xt.in_array(xx.responseErrorsForAlert, oRequest.request.status)) { + xcb.execute([gcb, lcb], 'onFailure', oRequest); + xx.completeResponse(oRequest); + } + + return oRet; + + +} + +/* + Function: xajax.responseProcessor.xml + + Parse the response XML into a series of commands. The commands + are constructed by calling and + . + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax.responseProcessor.xml = function(oRequest) { + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + + var oRet = oRequest.returnValue; + + if (xt.in_array(xx.responseSuccessCodes, oRequest.request.status)) { + xcb.execute([gcb, lcb], 'onSuccess', oRequest); + var seq = 0; + if (oRequest.request.responseXML) { + var responseXML = oRequest.request.responseXML; + if (responseXML.documentElement) { + oRequest.status.onProcessing(); + + var child = responseXML.documentElement.firstChild; + oRet = xt.xml.processFragment(child, seq, oRet, oRequest); + } + } + var obj = {}; + obj.fullName = 'Response Complete'; + obj.sequence = seq; + obj.request = oRequest; + obj.context = oRequest.context; + obj.cmd = 'rcmplt'; + xt.queue.push(xx.response, obj); + + // do not re-start the queue if a timeout is set + if (null == xx.response.timeout) + xt.queue.process(xx.response); + } else if (xt.in_array(xx.responseRedirectCodes, oRequest.request.status)) { + xcb.execute([gcb, lcb], 'onRedirect', oRequest); + window.location = oRequest.request.getResponseHeader('location'); + xx.completeResponse(oRequest); + } else if (xt.in_array(xx.responseErrorsForAlert, oRequest.request.status)) { + xcb.execute([gcb, lcb], 'onFailure', oRequest); + xx.completeResponse(oRequest); + } + + return oRet; +} + +/* + Class: xajax.js + + Contains the functions for javascript file and function + manipulation. +*/ +xajax.js = {} + +/* + Function: xajax.js.includeScriptOnce + + Add a reference to the specified script file if one does not + already exist in the HEAD of the current document. + + This will effecitvely cause the script file to be loaded in + the browser. + + Parameters: + + fileName - (string): The URI of the file. + + Returns: + + true - The reference exists or was added. +*/ +xajax.js.includeScriptOnce = function(command) { + command.fullName = 'includeScriptOnce'; + var fileName = command.data; + // Check for existing script tag for this file. + var oDoc = xajax.config.baseDocument; + var loadedScripts = oDoc.getElementsByTagName('script'); + var iLen = loadedScripts.length; + for (var i = 0; i < iLen; ++i) { + var script = loadedScripts[i]; + if (script.src) { + if (0 <= script.src.indexOf(fileName)) + return true; + } + } + return xajax.js.includeScript(command); +} + +/* + Function: xajax.js.includeScript + + Adds a SCRIPT tag referencing the specified file. This + effectively causes the script to be loaded in the browser. + + Parameters: + + command (object) - Xajax response object + + Returns: + + true - The reference was added. +*/ +xajax.js.includeScript = function(command) { + command.fullName = 'includeScript'; + var oDoc = xajax.config.baseDocument; + var objHead = oDoc.getElementsByTagName('head'); + var objScript = oDoc.createElement('script'); + objScript.src = command.data; + if ('undefined' == typeof command.type) objScript.type = 'text/javascript'; + else objScript.type = command.type; + if ('undefined' != typeof command.type) objScript.setAttribute('id', command.elm_id); + objHead[0].appendChild(objScript); + return true; +} + +/* + Function: xajax.js.removeScript + + Locates a SCRIPT tag in the HEAD of the document which references + the specified file and removes it. + + Parameters: + + command (object) - Xajax response object + + Returns: + + true - The script was not found or was removed. +*/ +xajax.js.removeScript = function(command) { + command.fullName = 'removeScript'; + var fileName = command.data; + var unload = command.unld; + var oDoc = xajax.config.baseDocument; + var loadedScripts = oDoc.getElementsByTagName('script'); + var iLen = loadedScripts.length; + for (var i = 0; i < iLen; ++i) { + var script = loadedScripts[i]; + if (script.src) { + if (0 <= script.src.indexOf(fileName)) { + if ('undefined' != typeof unload) { + var args = {}; + args.data = unload; + args.context = window; + xajax.js.execute(args); + } + var parent = script.parentNode; + parent.removeChild(script); + } + } + } + return true; +} + +/* + Function: xajax.js.sleep + + Causes the processing of items in the queue to be delayed + for the specified amount of time. This is an asynchronous + operation, therefore, other operations will be given an + opportunity to execute during this delay. + + Parameters: + + args - (object): The response command containing the following + parameters. + - args.prop: The number of 10ths of a second to sleep. + + Returns: + + true - The sleep operation completed. + false - The sleep time has not yet expired, continue sleeping. +*/ +xajax.js.sleep = function(command) { + command.fullName = 'sleep'; + // inject a delay in the queue processing + // handle retry counter + if (xajax.tools.queue.retry(command, command.prop)) { + xajax.tools.queue.setWakeup(xajax.response, 100); + return false; + } + // wake up, continue processing queue + return true; +} + +/* + Function: xajax.js.confirmCommands + + Prompt the user with the specified text, if the user responds by clicking + cancel, then skip the specified number of commands in the response command + queue. If the user clicks Ok, the command processing resumes normal + operation. + + Parameters: + + command (object) - xajax response object + + Returns: + + true - The operation completed successfully. +*/ +xajax.js.confirmCommands = function(command) { + command.fullName = 'confirmCommands'; + var msg = command.data; + var numberOfCommands = command.id; + if (false == confirm(msg)) { + while (0 < numberOfCommands) { + xajax.tools.queue.pop(xajax.response); + --numberOfCommands; + } + } + return true; +} + +/* + Function: xajax.js.execute + + Execute the specified string of javascript code, using the current + script context. + + Parameters: + + args - The response command object containing the following: + - args.data: (string): The javascript to be evaluated. + - args.context: (object): The javascript object that to be + referenced as 'this' in the script. + + Returns: + + unknown - A value set by the script using 'returnValue = ' + true - If the script does not set a returnValue. +*/ +xajax.js.execute = function(args) { + args.fullName = 'execute Javascript'; + var returnValue = true; + args.context = args.context ? args.context : {}; + args.context.xajaxDelegateCall = function() { + eval(args.data); + }; + args.context.xajaxDelegateCall(); + return returnValue; +} + +/* + Function: xajax.js.waitFor + + Test for the specified condition, using the current script + context; if the result is false, sleep for 1/10th of a + second and try again. + + Parameters: + + args - The response command object containing the following: + + - args.data: (string): The javascript to evaluate. + - args.prop: (integer): The number of 1/10ths of a + second to wait before giving up. + - args.context: (object): The current script context object + which is accessable in the javascript being evaulated + via the 'this' keyword. + + Returns: + + false - The condition evaulates to false and the sleep time + has not expired. + true - The condition evaluates to true or the sleep time has + expired. +*/ +xajax.js.waitFor = function(args) { + args.fullName = 'waitFor'; + + var bResult = false; + var cmdToEval = 'bResult = ('; + cmdToEval += args.data; + cmdToEval += ');'; + try { + args.context.xajaxDelegateCall = function() { + eval(cmdToEval); + } + args.context.xajaxDelegateCall(); + } catch (e) { + } + if (false == bResult) { + // inject a delay in the queue processing + // handle retry counter + if (xajax.tools.queue.retry(args, args.prop)) { + xajax.tools.queue.setWakeup(xajax.response, 100); + return false; + } + // give up, continue processing queue + } + return true; +} + +/* + Function: xajax.js.call + + Call a javascript function with a series of parameters using + the current script context. + + Parameters: + + args - The response command object containing the following: + - args.data: (array): The parameters to pass to the function. + - args.func: (string): The name of the function to call. + - args.context: (object): The current script context object + which is accessable in the function name via the 'this' + keyword. + + Returns: + + true - The call completed successfully. +*/ +xajax.js.call = function(args) { + args.fullName = 'call js function'; + + var parameters = args.data; + + var scr = new Array(); + scr.push(args.func); + scr.push('('); + if ('undefined' != typeof parameters) { + if ('object' == typeof parameters) { + var iLen = parameters.length; + if (0 < iLen) { + scr.push('parameters[0]'); + for (var i = 1; i < iLen; ++i) + scr.push(', parameters[' + i + ']'); + } + } + } + scr.push(');'); + args.context.xajaxDelegateCall = function() { + eval(scr.join('')); + } + args.context.xajaxDelegateCall(); + return true; +} + +/* + Function: xajax.js.setFunction + + Constructs the specified function using the specified javascript + as the body of the function. + + Parameters: + + args - The response command object which contains the following: + + - args.func: (string): The name of the function to construct. + - args.data: (string): The script that will be the function body. + - args.context: (object): The current script context object + which is accessable in the script name via the 'this' keyword. + + Returns: + + true - The function was constructed successfully. +*/ +xajax.js.setFunction = function(args) { + args.fullName = 'setFunction'; + + var code = new Array(); + code.push(args.func); + code.push(' = function('); + if ('object' == typeof args.prop) { + var separator = ''; + for (var m in args.prop) { + code.push(separator); + code.push(args.prop[m]); + separator = ','; + } + } else code.push(args.prop); + code.push(') { '); + code.push(args.data); + code.push(' }'); + args.context.xajaxDelegateCall = function() { + eval(code.join('')); + } + args.context.xajaxDelegateCall(); + return true; +} + +/* + Function: xajax.js.wrapFunction + + Construct a javascript function which will call the original function with + the same name, potentially executing code before and after the call to the + original function. + + Parameters: + + args - (object): The response command object which will contain + the following: + + - args.func: (string): The name of the function to be wrapped. + - args.prop: (string): List of parameters used when calling the function. + - args.data: (array): The portions of code to be called before, after + or even between calls to the original function. + - args.context: (object): The current script context object which is + accessable in the function name and body via the 'this' keyword. + + Returns: + + true - The wrapper function was constructed successfully. +*/ +xajax.js.wrapFunction = function(args) { + args.fullName = 'wrapFunction'; + + var code = new Array(); + code.push(args.func); + code.push(' = xajax.js.makeWrapper('); + code.push(args.func); + code.push(', args.prop, args.data, args.type, args.context);'); + args.context.xajaxDelegateCall = function() { + eval(code.join('')); + } + args.context.xajaxDelegateCall(); + return true; +} + +/* + Function: xajax.js.makeWrapper + + + Helper function used in the wrapping of an existing javascript function. + + Parameters: + + origFun - (string): The name of the original function. + args - (string): The list of parameters used when calling the function. + codeBlocks - (array): Array of strings of javascript code to be executed + before, after and perhaps between calls to the original function. + returnVariable - (string): The name of the variable used to retain the + return value from the call to the original function. + context - (object): The current script context object which is accessable + in the function name and body via the 'this' keyword. + + Returns: + + object - The complete wrapper function. +*/ +xajax.js.makeWrapper = function(origFun, args, codeBlocks, returnVariable, context) { + var originalCall = ''; + if (0 < returnVariable.length) { + originalCall += returnVariable; + originalCall += ' = '; + } + var originalCall = 'origFun('; + originalCall += args; + originalCall += '); '; + + var code = 'wrapper = function('; + code += args; + code += ') { '; + + if (0 < returnVariable.length) { + code += ' var '; + code += returnVariable; + code += ' = null;'; + } + var separator = ''; + var bLen = codeBlocks.length; + for (var b = 0; b < bLen; ++b) { + code += separator; + code += codeBlocks[b]; + separator = originalCall; + } + if (0 < returnVariable.length) { + code += ' return '; + code += returnVariable; + code += ';'; + } + code += ' } '; + + var wrapper = null; + context.xajaxDelegateCall = function() { + eval(code); + } + context.xajaxDelegateCall(); + return wrapper; +} + +/* + Class: xajax.dom +*/ +xajax.dom = {} + +/* + Function: xajax.dom.assign + + Assign an element's attribute to the specified value. + + Parameters: + + element - (object): The HTML element to effect. + property - (string): The name of the attribute to set. + data - (string): The new value to be applied. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.assign = function(element, property, data) { + if ('string' == typeof element) + element = xajax.$(element); + + switch (property) { + case 'innerHTML': + element.innerHTML = data; + break; + case 'outerHTML': + if ('undefined' == typeof element.outerHTML) { + var r = xajax.config.baseDocument.createRange(); + r.setStartBefore(element); + var df = r.createContextualFragment(data); + element.parentNode.replaceChild(df, element); + } else element.outerHTML = data; + break; + default: + if (xajax.tools.willChange(element, property, data)) + eval('element.' + property + ' = data;'); + break; + } + return true; +} + +/* + Function: xajax.dom.append + + Append the specified value to an element's attribute. + + Parameters: + + element - (object): The HTML element to effect. + property - (string): The name of the attribute to append to. + data - (string): The new value to be appended. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.append = function(element, property, data) { + if ('string' == typeof element) + element = xajax.$(element); + + eval('element.' + property + ' += data;'); + return true; +} + +/* + Function: xajax.dom.prepend + + Prepend the specified value to an element's attribute. + + Parameters: + + element - (object): The HTML element to effect. + property - (string): The name of the attribute. + data - (string): The new value to be prepended. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.prepend = function(element, property, data) { + if ('string' == typeof element) + element = xajax.$(element); + + eval('element.' + property + ' = data + element.' + property); + return true; +} + +/* + Function: xajax.dom.replace + + Search and replace the specified text. + + Parameters: + + element - (string or object): The name of, or the element itself which is + to be modified. + sAttribute - (string): The name of the attribute to be set. + aData - (array): The search text and replacement text. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.replace = function(element, sAttribute, aData) { + var sSearch = aData['s']; + var sReplace = aData['r']; + + if (sAttribute == 'innerHTML') + sSearch = xajax.tools.getBrowserHTML(sSearch); + + if ('string' == typeof element) + element = xajax.$(element); + + eval('var txt = element.' + sAttribute); + + var bFunction = false; + if ('function' == typeof txt) { + txt = txt.join(''); + bFunction = true; + } + + var start = txt.indexOf(sSearch); + if (start > -1) { + var newTxt = []; + while (start > -1) { + var end = start + sSearch.length; + newTxt.push(txt.substr(0, start)); + newTxt.push(sReplace); + txt = txt.substr(end, txt.length - end); + start = txt.indexOf(sSearch); + } + newTxt.push(txt); + newTxt = newTxt.join(''); + + if (bFunction) { + eval('element.' + sAttribute + '=newTxt;'); + } else if (xajax.tools.willChange(element, sAttribute, newTxt)) { + eval('element.' + sAttribute + '=newTxt;'); + } + } + return true; +} + +/* + Function: xajax.dom.remove + + Delete an element. + + Parameters: + + element - (string or object): The name of, or the element itself which + will be deleted. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.remove = function(element) { + if ('string' == typeof element) + element = xajax.$(element); + + if (element && element.parentNode && element.parentNode.removeChild) + element.parentNode.removeChild(element); + + return true; +} + +/* + Function: xajax.dom.create + + Create a new element and append it to the specified parent element. + + Parameters: + + objParent - (string or object): The name of, or the element itself + which will contain the new element. + sTag - (string): The tag name for the new element. + sId - (string): The value to be assigned to the id attribute of + the new element. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.create = function(objParent, sTag, sId) { + if ('string' == typeof objParent) + objParent = xajax.$(objParent); + var target = xajax.config.baseDocument.createElement(sTag); + target.setAttribute('id', sId); + if (objParent) + objParent.appendChild(target); + return true; +} + +/* + Function: xajax.dom.insert + + Insert a new element before the specified element. + + Parameters: + + objSibling - (string or object): The name of, or the element itself + that will be used as the reference point for insertion. + sTag - (string): The tag name for the new element. + sId - (string): The value that will be assigned to the new element's + id attribute. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.insert = function(objSibling, sTag, sId) { + if ('string' == typeof objSibling) + objSibling = xajax.$(objSibling); + var target = xajax.config.baseDocument.createElement(sTag); + target.setAttribute('id', sId); + objSibling.parentNode.insertBefore(target, objSibling); + return true; +} + +/* + Function: xajax.dom.insertAfter + + Insert a new element after the specified element. + + Parameters: + + objSibling - (string or object): The name of, or the element itself + that will be used as the reference point for insertion. + sTag - (string): The tag name for the new element. + sId - (string): The value that will be assigned to the new element's + id attribute. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.insertAfter = function(objSibling, sTag, sId) { + if ('string' == typeof objSibling) + objSibling = xajax.$(objSibling); + var target = xajax.config.baseDocument.createElement(sTag); + target.setAttribute('id', sId); + objSibling.parentNode.insertBefore(target, objSibling.nextSibling); + return true; +} + +/* + Function: xajax.dom.contextAssign + + Assign a value to a named member of the current script context object. + + Parameters: + + args - (object): The response command object which will contain the + following: + + - args.prop: (string): The name of the member to assign. + - args.data: (string or object): The value to assign to the member. + - args.context: (object): The current script context object which + is accessable via the 'this' keyword. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.contextAssign = function(args) { + args.fullName = 'context assign'; + + var code = []; + code.push('this.'); + code.push(args.prop); + code.push(' = data;'); + code = code.join(''); + args.context.xajaxDelegateCall = function(data) { + eval(code); + } + args.context.xajaxDelegateCall(args.data); + return true; +} + +/* + Function: xajax.dom.contextAppend + + Appends a value to a named member of the current script context object. + + Parameters: + + args - (object): The response command object which will contain the + following: + + - args.prop: (string): The name of the member to append to. + - args.data: (string or object): The value to append to the member. + - args.context: (object): The current script context object which + is accessable via the 'this' keyword. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.contextAppend = function(args) { + args.fullName = 'context append'; + + var code = []; + code.push('this.'); + code.push(args.prop); + code.push(' += data;'); + code = code.join(''); + args.context.xajaxDelegateCall = function(data) { + eval(code); + } + args.context.xajaxDelegateCall(args.data); + return true; +} + +/* + Function: xajax.dom.contextPrepend + + Prepend a value to a named member of the current script context object. + + Parameters: + + args - (object): The response command object which will contain the + following: + + - args.prop: (string): The name of the member to prepend to. + - args.data: (string or object): The value to prepend to the member. + - args.context: (object): The current script context object which + is accessable via the 'this' keyword. + + Returns: + + true - The operation completed successfully. +*/ +xajax.dom.contextPrepend = function(args) { + args.fullName = 'context prepend'; + + var code = []; + code.push('this.'); + code.push(args.prop); + code.push(' = data + this.'); + code.push(args.prop); + code.push(';'); + code = code.join(''); + args.context.xajaxDelegateCall = function(data) { + eval(code); + } + args.context.xajaxDelegateCall(args.data); + return true; +} + + +/* + Class: xajax.domResponse +*/ +xajax.domResponse = {} + +xajax.domResponse.startResponse = function(args) { + xjxElm = []; +} + +xajax.domResponse.createElement = function(args) { + eval( + [ args.tgt, ' = document.createElement(args.data)' ] + .join('') + ); +} + +xajax.domResponse.setAttribute = function(args) { + args.context.xajaxDelegateCall = function() { + eval( + [ args.tgt, '.setAttribute(args.key, args.data)' ] + .join('') + ); + } + args.context.xajaxDelegateCall(); +} + +xajax.domResponse.appendChild = function(args) { + args.context.xajaxDelegateCall = function() { + eval( + [ args.par, '.appendChild(', args.data, ')' ] + .join('') + ); + } + args.context.xajaxDelegateCall(); +} + +xajax.domResponse.insertBefore = function(args) { + args.context.xajaxDelegateCall = function() { + eval( + [ args.tgt, '.parentNode.insertBefore(', args.data, ', ', args.tgt, ')' ] + .join('') + ); + } + args.context.xajaxDelegateCall(); +} + +xajax.domResponse.insertAfter = function(args) { + args.context.xajaxDelegateCall = function() { + eval( + [ args.tgt, 'parentNode.insertBefore(', args.data, ', ', args.tgt, '.nextSibling)' ] + .join('') + ); + } + args.context.xajaxDelegateCall(); +} + +xajax.domResponse.appendText = function(args) { + args.context.xajaxDelegateCall = function() { + eval( + [ args.par, '.appendChild(document.createTextNode(args.data))' ] + .join('') + ); + } + args.context.xajaxDelegateCall(); +} + +xajax.domResponse.removeChildren = function(args) { + var skip = args.skip || 0; + var remove = args.remove || -1; + var element = null; + args.context.xajaxDelegateCall = function() { + eval( [ 'element = ', args.data ].join( '' ) ); + } + args.context.xajaxDelegateCall(); + var children = element.childNodes; + for (var i in children) { + if (isNaN(i) == false && children[i].nodeType == 1) { + if (skip > 0) skip = skip - 1; + else if (remove != 0) { + if (remove > 0) + remove = remove - 1; + element.removeChild(children[i]); + } + } + } +} + +xajax.domResponse.endResponse = function(args) { + xjxElm = []; +} + + +/* + Class: xajax.css +*/ +xajax.css = {} + +/* + Function: xajax.css.add + + Add a LINK reference to the specified .css file if it does not + already exist in the HEAD of the current document. + + Parameters: + + filename - (string): The URI of the .css file to reference. + + media - (string): The media type of the css file (print/screen/handheld,..) + + Returns: + + true - The operation completed successfully. +*/ +xajax.css.add = function(fileName, media) { + var oDoc = xajax.config.baseDocument; + var oHeads = oDoc.getElementsByTagName('head'); + var oHead = oHeads[0]; + var oLinks = oHead.getElementsByTagName('link'); + + var found = false; + var iLen = oLinks.length; + for (var i = 0; i < iLen && false == found; ++i) + if (0 <= oLinks[i].href.indexOf(fileName) && oLinks[i].media == media) + found = true; + + if (false == found) { + var oCSS = oDoc.createElement('link'); + oCSS.rel = 'stylesheet'; + oCSS.type = 'text/css'; + oCSS.href = fileName; + oCSS.media = media; + oHead.appendChild(oCSS); + } + + return true; +} + +/* + Function: xajax.css.remove + + Locate and remove a LINK reference from the current document's + HEAD. + + Parameters: + + filename - (string): The URI of the .css file. + + Returns: + + true - The operation completed successfully. +*/ +xajax.css.remove = function(fileName, media) { + var oDoc = xajax.config.baseDocument; + var oHeads = oDoc.getElementsByTagName('head'); + var oHead = oHeads[0]; + var oLinks = oHead.getElementsByTagName('link'); + + var i = 0; + while (i < oLinks.length) + if (0 <= oLinks[i].href.indexOf(fileName) && oLinks[i].media == media) + oHead.removeChild(oLinks[i]); + else ++i; + + return true; +} + +/* + Function: xajax.css.waitForCSS + + Attempt to detect when all .css files have been loaded once + they are referenced by a LINK tag in the HEAD of the current + document. + + Parameters: + + args - (object): The response command object which will contain + the following: + + - args.prop - (integer): The number of 1/10ths of a second + to wait before giving up. + + Returns: + + true - The .css files appear to be loaded. + false - The .css files do not appear to be loaded and the timeout + has not expired. +*/ +xajax.css.waitForCSS = function(args) { + var oDocSS = xajax.config.baseDocument.styleSheets; + var ssEnabled = []; + var iLen = oDocSS.length; + for (var i = 0; i < iLen; ++i) { + ssEnabled[i] = 0; + try { + ssEnabled[i] = oDocSS[i].cssRules.length; + } catch (e) { + try { + ssEnabled[i] = oDocSS[i].rules.length; + } catch (e) { + } + } + } + + var ssLoaded = true; + var iLen = ssEnabled.length; + for (var i = 0; i < iLen; ++i) + if (0 == ssEnabled[i]) + ssLoaded = false; + + if (false == ssLoaded) { + // inject a delay in the queue processing + // handle retry counter + if (xajax.tools.queue.retry(args, args.prop)) { + xajax.tools.queue.setWakeup(xajax.response, 10); + return false; + } + // give up, continue processing queue + } + return true; +} + + +/* + Class: xajax.forms +*/ +xajax.forms = {} + +/* + Function: xajax.forms.getInput + + Create and return a form input element with the specified parameters. + + Parameters: + + type - (string): The type of input element desired. + name - (string): The value to be assigned to the name attribute. + id - (string): The value to be assigned to the id attribute. + + Returns: + + object - The new input element. +*/ +xajax.forms.getInput = function(type, name, id) { + if ('undefined' == typeof window.addEventListener) { + xajax.forms.getInput = function(type, name, id) { + return xajax.config.baseDocument.createElement(''); + } + } else { + xajax.forms.getInput = function(type, name, id) { + var oDoc = xajax.config.baseDocument; + var Obj = oDoc.createElement('input'); + Obj.setAttribute('type', type); + Obj.setAttribute('name', name); + Obj.setAttribute('id', id); + return Obj; + } + } + return xajax.forms.getInput(type, name, id); +} + +/* + Function: xajax.forms.createInput + + Create a new input element under the specified parent. + + Parameters: + + objParent - (string or object): The name of, or the element itself + that will be used as the reference for the insertion. + sType - (string): The value to be assigned to the type attribute. + sName - (string): The value to be assigned to the name attribute. + sId - (string): The value to be assigned to the id attribute. + + Returns: + + true - The operation completed successfully. +*/ +xajax.forms.createInput = function(command) { + command.fullName = 'createInput'; + var objParent = command.id; + + var sType = command.type; + var sName = command.data; + var sId = command.prop; + if ('string' == typeof objParent) + objParent = xajax.$(objParent); + var target = xajax.forms.getInput(sType, sName, sId); + if (objParent && target) + { + objParent.appendChild(target); + } + return true; +} + +/* + Function: xajax.forms.insertInput + + Insert a new input element before the specified element. + + Parameters: + + objSibling - (string or object): The name of, or the element itself + that will be used as the reference for the insertion. + sType - (string): The value to be assigned to the type attribute. + sName - (string): The value to be assigned to the name attribute. + sId - (string): The value to be assigned to the id attribute. + + Returns: + + true - The operation completed successfully. +*/ +xajax.forms.insertInput = function(command) { + command.fullName = 'insertInput'; + var objSibling = command.id; + var sType = command.type; + var sName = command.data; + var sId = command.prop; + if ('string' == typeof objSibling) + objSibling = xajax.$(objSibling); + var target = xajax.forms.getInput(sType, sName, sId); + if (target && objSibling && objSibling.parentNode) + objSibling.parentNode.insertBefore(target, objSibling); + return true; +} + +/* + Function: xajax.forms.insertInputAfter + + Insert a new input element after the specified element. + + Parameters: + + objSibling - (string or object): The name of, or the element itself + that will be used as the reference for the insertion. + sType - (string): The value to be assigned to the type attribute. + sName - (string): The value to be assigned to the name attribute. + sId - (string): The value to be assigned to the id attribute. + + Returns: + + true - The operation completed successfully. +*/ +xajax.forms.insertInputAfter = function(command) { + command.fullName = 'insertInputAfter'; + var objSibling = command.id; + var sType = command.type; + var sName = command.data; + var sId = command.prop; + if ('string' == typeof objSibling) + objSibling = xajax.$(objSibling); + var target = xajax.forms.getInput(sType, sName, sId); + if (target && objSibling && objSibling.parentNode) + objSibling.parentNode.insertBefore(target, objSibling.nextSibling); + return true; +} + +/* + Class: xajax.events +*/ +xajax.events = {} + +/* + Function: xajax.events.setEvent + + Set an event handler. + + Parameters: + + command - (object): Response command object. + - id: Element ID + - prop: Event + - data: Code + + Returns: + + true - The operation completed successfully. +*/ +xajax.events.setEvent = function(command) { + command.fullName = 'setEvent'; + var element = command.id; + var sEvent = command.prop; + var code = command.data; + //force to get the element + element = xajax.$(element); + sEvent = xajax.tools.addOnPrefix(sEvent); + code = xajax.tools.doubleQuotes(code); + eval('element.' + sEvent + ' = function(e) { ' + code + '; }'); + return true; +} + +/* + Function: xajax.events.addHandler + + Add an event handler to the specified element. + + Parameters: + + element - (string or object): The name of, or the element itself + which will have the event handler assigned. + sEvent - (string): The name of the event. + fun - (string): The function to be called. + + Returns: + + true - The operation completed successfully. +*/ +xajax.events.addHandler = function(element, sEvent, fun) { + if (window.addEventListener) { + xajax.events.addHandler = function(command) { + command.fullName = 'addHandler'; + var element = command.id; + var sEvent = command.prop; + var fun = command.data; + if ('string' == typeof element) + element = xajax.$(element); + sEvent = xajax.tools.stripOnPrefix(sEvent); + eval('element.addEventListener("' + sEvent + '", ' + fun + ', false);'); + return true; + } + } else { + xajax.events.addHandler = function(command) { + command.fullName = 'addHandler'; + var element = command.id; + var sEvent = command.prop; + var fun = command.data; + if ('string' == typeof element) + element = xajax.$(element); + sEvent = xajax.tools.addOnPrefix(sEvent); + eval('element.attachEvent("' + sEvent + '", ' + fun + ', false);'); + return true; + } + } + return xajax.events.addHandler(element, sEvent, fun); +} + +/* + Function: xajax.events.removeHandler + + Remove an event handler from an element. + + Parameters: + + element - (string or object): The name of, or the element itself which + will have the event handler removed. + event - (string): The name of the event for which this handler is + associated. + fun - The function to be removed. + + Returns: + + true - The operation completed successfully. +*/ +xajax.events.removeHandler = function(element, sEvent, fun) { + if (window.removeEventListener) { + xajax.events.removeHandler = function(command) { + command.fullName = 'removeHandler'; + var element = command.id; + var sEvent = command.prop; + var fun = command.data; + if ('string' == typeof element) + element = xajax.$(element); + sEvent = xajax.tools.stripOnPrefix(sEvent); + eval('element.removeEventListener("' + sEvent + '", ' + fun + ', false);'); + return true; + } + } else { + xajax.events.removeHandler = function(command) { + command.fullName = 'removeHandler'; + var element = command.id; + var sEvent = command.prop; + var fun = command.data; + if ('string' == typeof element) + element = xajax.$(element); + sEvent = xajax.tools.addOnPrefix(sEvent); + eval('element.detachEvent("' + sEvent + '", ' + fun + ', false);'); + return true; + } + } + return xajax.events.removeHandler(element, sEvent, fun); +} + +/* + Class: xajax.callback +*/ +xajax.callback = {} + +/* + Function: xajax.callback.create + + Create a blank callback object. Two optional arguments let you + set the delay time for the onResponseDelay and onExpiration events. + + Returns: + + object - The callback object. +*/ +xajax.callback.create = function() { + var xx = xajax; + var xc = xx.config; + var xcb = xx.callback; + + var oCB = {} + oCB.timers = {}; + + oCB.timers.onResponseDelay = xcb.setupTimer( + (arguments.length > 0) + ? arguments[0] + : xc.defaultResponseDelayTime); + + oCB.timers.onExpiration = xcb.setupTimer( + (arguments.length > 1) + ? arguments[1] + : xc.defaultExpirationTime); + + oCB.onRequest = null; + oCB.onResponseDelay = null; + oCB.onExpiration = null; + oCB.beforeResponseProcessing = null; + oCB.onFailure = null; + oCB.onRedirect = null; + oCB.onSuccess = null; + oCB.onComplete = null; + + return oCB; +} + +/* + Function: xajax.callback.setupTimer + + Create a timer to fire an event in the future. This will + be used fire the onRequestDelay and onExpiration events. + + Parameters: + + iDelay - (integer): The amount of time in milliseconds to delay. + + Returns: + + object - A callback timer object. +*/ +xajax.callback.setupTimer = function(iDelay) +{ + return { timer: null, delay: iDelay }; +} + +/* + Function: xajax.callback.clearTimer + + Clear a callback timer for the specified function. + + Parameters: + + oCallback - (object): The callback object (or objects) that + contain the specified function timer to be cleared. + sFunction - (string): The name of the function associated + with the timer to be cleared. +*/ +xajax.callback.clearTimer = function(oCallback, sFunction) +{ + if ('undefined' != typeof oCallback.timers) { + if ('undefined' != typeof oCallback.timers[sFunction]) { + clearTimeout(oCallback.timers[sFunction].timer); + } + } else if ('object' == typeof oCallback) { + var iLen = oCallback.length; + for (var i = 0; i < iLen; ++i) + xajax.callback.clearTimer(oCallback[i], sFunction); + } +} + +/* + Function: xajax.callback.execute + + Execute a callback event. + + Parameters: + + oCallback - (object): The callback object (or objects) which + contain the event handlers to be executed. + sFunction - (string): The name of the event to be triggered. + args - (object): The request object for this request. +*/ +xajax.callback.execute = function(oCallback, sFunction, args) { + if ('undefined' != typeof oCallback[sFunction]) { + var func = oCallback[sFunction]; + if ('function' == typeof func) { + if ('undefined' != typeof oCallback.timers[sFunction]) { + oCallback.timers[sFunction].timer = setTimeout(function() { + func(args); + }, oCallback.timers[sFunction].delay); + } + else { + func(args); + } + } + } else if ('object' == typeof oCallback) { + var iLen = oCallback.length; + for (var i = 0; i < iLen; ++i) + xajax.callback.execute(oCallback[i], sFunction, args); + } +} + +/* + Class: xajax.callback.global + + The global callback object which is active for every request. +*/ +xajax.callback.global = xajax.callback.create(); + +/* + Class: xajax +*/ + +/* + Object: xajax.response + + The response queue that holds response commands, once received + from the server, until they are processed. +*/ +xajax.response = xajax.tools.queue.create(xajax.config.responseQueueSize); + +/* + Object: responseSuccessCodes + + This array contains a list of codes which will be returned from the + server upon successful completion of the server portion of the + request. + + These values should match those specified in the HTTP standard. +*/ +xajax.responseSuccessCodes = ['0', '200']; + +// 10.4.1 400 Bad Request +// 10.4.2 401 Unauthorized +// 10.4.3 402 Payment Required +// 10.4.4 403 Forbidden +// 10.4.5 404 Not Found +// 10.4.6 405 Method Not Allowed +// 10.4.7 406 Not Acceptable +// 10.4.8 407 Proxy Authentication Required +// 10.4.9 408 Request Timeout +// 10.4.10 409 Conflict +// 10.4.11 410 Gone +// 10.4.12 411 Length Required +// 10.4.13 412 Precondition Failed +// 10.4.14 413 Request Entity Too Large +// 10.4.15 414 Request-URI Too Long +// 10.4.16 415 Unsupported Media Type +// 10.4.17 416 Requested Range Not Satisfiable +// 10.4.18 417 Expectation Failed +// 10.5 Server Error 5xx +// 10.5.1 500 Internal Server Error +// 10.5.2 501 Not Implemented +// 10.5.3 502 Bad Gateway +// 10.5.4 503 Service Unavailable +// 10.5.5 504 Gateway Timeout +// 10.5.6 505 HTTP Version Not Supported + +/* + Object: responseErrorsForAlert + + This array contains a list of status codes returned by + the server to indicate that the request failed for some + reason. +*/ +xajax.responseErrorsForAlert = ['400','401','402','403','404','500','501','502','503']; + +// 10.3.1 300 Multiple Choices +// 10.3.2 301 Moved Permanently +// 10.3.3 302 Found +// 10.3.4 303 See Other +// 10.3.5 304 Not Modified +// 10.3.6 305 Use Proxy +// 10.3.7 306 (Unused) +// 10.3.8 307 Temporary Redirect + +/* + Object: responseRedirectCodes + + An array of status codes returned from the server to + indicate a request for redirect to another URL. + + Typically, this is used by the server to send the browser + to another URL. This does not typically indicate that + the xajax request should be sent to another URL. +*/ +xajax.responseRedirectCodes = ['301','302','307']; + +/* + Class: xajax.command + + The object that manages commands and command handlers. +*/ +if ('undefined' == typeof xajax.command) + xajax.command = {}; + +/* + Function: xajax.command.create + + Creates a new command (object) that will be populated with + command parameters and eventually passed to the command handler. +*/ +xajax.command.create = function(sequence, request, context) { + var newCmd = {}; + newCmd.cmd = '*'; + newCmd.fullName = '* unknown command name *'; + newCmd.sequence = sequence; + newCmd.request = request; + newCmd.context = context; + return newCmd; +} + +/* + Class: xajax.command.handler + + The object that manages command handlers. +*/ +if ('undefined' == typeof xajax.command.handler) + xajax.command.handler = {}; + +/* + Object: handlers + + An array that is used internally in the xajax.command.handler object + to keep track of command handlers that have been registered. +*/ +if ('undefined' == typeof xajax.command.handler.handlers) + xajax.command.handler.handlers = []; + +/* + Function: xajax.command.handler.register + + Registers a new command handler. +*/ +xajax.command.handler.register = function(shortName, func) { + xajax.command.handler.handlers[shortName] = func; +} + +/* + Function: xajax.command.handler.unregister + + Unregisters and returns a command handler. + + Parameters: + shortName - (string): The name of the command handler. + + Returns: + func - (function): The unregistered function. +*/ +xajax.command.handler.unregister = function(shortName) { + var func = xajax.command.handler.handlers[shortName]; + delete xajax.command.handler.handlers[shortName]; + return func; +} + +/* + Function: xajax.command.handler.isRegistered + + + Parameters: + command - (object): + - cmd: The Name of the function. + + Returns: + + boolean - (true or false): depending on whether a command handler has + been created for the specified command (object). + +*/ +xajax.command.handler.isRegistered = function(command) { + var shortName = command.cmd; + if (xajax.command.handler.handlers[shortName]) + return true; + return false; +} + +/* + Function: xajax.command.handler.call + + Calls the registered command handler for the specified command + (you should always check isRegistered before calling this function) + + Parameters: + command - (object): + - cmd: The Name of the function. + + Returns: + true - (boolean) : +*/ +xajax.command.handler.call = function(command) { + var shortName = command.cmd; + return xajax.command.handler.handlers[shortName](command); +} + +xajax.command.handler.register('rcmplt', function(args) { + xajax.completeResponse(args.request); + return true; +}); + +xajax.command.handler.register('css', function(args) { + args.fullName = 'includeCSS'; + if ('undefined' == typeof args.media) + args.media = 'screen'; + return xajax.css.add(args.data, args.media); +}); +xajax.command.handler.register('rcss', function(args) { + args.fullName = 'removeCSS'; + if ('undefined' == typeof args.media) + args.media = 'screen'; + return xajax.css.remove(args.data, args.media); +}); +xajax.command.handler.register('wcss', function(args) { + args.fullName = 'waitForCSS'; + return xajax.css.waitForCSS(args); +}); + +xajax.command.handler.register('as', function(args) { + args.fullName = 'assign/clear'; + try { + return xajax.dom.assign(args.target, args.prop, args.data); + } catch (e) { + // do nothing, if the debug module is installed it will + // catch and handle the exception + } + return true; +}); +xajax.command.handler.register('ap', function(args) { + args.fullName = 'append'; + return xajax.dom.append(args.target, args.prop, args.data); +}); +xajax.command.handler.register('pp', function(args) { + args.fullName = 'prepend'; + return xajax.dom.prepend(args.target, args.prop, args.data); +}); +xajax.command.handler.register('rp', function(args) { + args.fullName = 'replace'; + return xajax.dom.replace(args.id, args.prop, args.data); +}); +xajax.command.handler.register('rm', function(args) { + args.fullName = 'remove'; + return xajax.dom.remove(args.id); +}); +xajax.command.handler.register('ce', function(args) { + args.fullName = 'create'; + return xajax.dom.create(args.id, args.data, args.prop); +}); +xajax.command.handler.register('ie', function(args) { + args.fullName = 'insert'; + return xajax.dom.insert(args.id, args.data, args.prop); +}); +xajax.command.handler.register('ia', function(args) { + args.fullName = 'insertAfter'; + return xajax.dom.insertAfter(args.id, args.data, args.prop); +}); + +xajax.command.handler.register('DSR', xajax.domResponse.startResponse); +xajax.command.handler.register('DCE', xajax.domResponse.createElement); +xajax.command.handler.register('DSA', xajax.domResponse.setAttribute); +xajax.command.handler.register('DAC', xajax.domResponse.appendChild); +xajax.command.handler.register('DIB', xajax.domResponse.insertBefore); +xajax.command.handler.register('DIA', xajax.domResponse.insertAfter); +xajax.command.handler.register('DAT', xajax.domResponse.appendText); +xajax.command.handler.register('DRC', xajax.domResponse.removeChildren); +xajax.command.handler.register('DER', xajax.domResponse.endResponse); + +xajax.command.handler.register('c:as', xajax.dom.contextAssign); +xajax.command.handler.register('c:ap', xajax.dom.contextAppend); +xajax.command.handler.register('c:pp', xajax.dom.contextPrepend); + +xajax.command.handler.register('s', xajax.js.sleep); +xajax.command.handler.register('ino', xajax.js.includeScriptOnce); +xajax.command.handler.register('in', xajax.js.includeScript); +xajax.command.handler.register('rjs', xajax.js.removeScript); +xajax.command.handler.register('wf', xajax.js.waitFor); +xajax.command.handler.register('js', xajax.js.execute); +xajax.command.handler.register('jc', xajax.js.call); +xajax.command.handler.register('sf', xajax.js.setFunction); +xajax.command.handler.register('wpf', xajax.js.wrapFunction); +xajax.command.handler.register('al', function(args) { + args.fullName = 'alert'; + alert(args.data); + return true; +}); +xajax.command.handler.register('cc', xajax.js.confirmCommands); + +xajax.command.handler.register('ci', xajax.forms.createInput); +xajax.command.handler.register('ii', xajax.forms.insertInput); +xajax.command.handler.register('iia', xajax.forms.insertInputAfter); + +xajax.command.handler.register('ev', xajax.events.setEvent); + +xajax.command.handler.register('ah', xajax.events.addHandler); +xajax.command.handler.register('rh', xajax.events.removeHandler); + +xajax.command.handler.register('dbg', function(args) { + args.fullName = 'debug message'; + return true; +}); + +/* + Function: xajax.initializeRequest + + Initialize a request object, populating default settings, where + call specific settings are not already provided. + + Parameters: + + oRequest - (object): An object that specifies call specific settings + that will, in addition, be used to store all request related + values. This includes temporary values used internally by xajax. +*/ +xajax.initializeRequest = function(oRequest) { + var xx = xajax; + var xc = xx.config; + + oRequest.append = function(opt, def) { + if ('undefined' != typeof this[opt]) { + for (var itmName in def) + if ('undefined' == typeof this[opt][itmName]) + this[opt][itmName] = def[itmName]; + } else this[opt] = def; + } + + oRequest.append('commonHeaders', xc.commonHeaders); + oRequest.append('postHeaders', xc.postHeaders); + oRequest.append('getHeaders', xc.getHeaders); + + oRequest.set = function(option, defaultValue) { + if ('undefined' == typeof this[option]) + this[option] = defaultValue; + } + + oRequest.set('statusMessages', xc.statusMessages); + oRequest.set('waitCursor', xc.waitCursor); + oRequest.set('mode', xc.defaultMode); + oRequest.set('method', xc.defaultMethod); + oRequest.set('URI', xc.requestURI); + oRequest.set('httpVersion', xc.defaultHttpVersion); + oRequest.set('contentType', xc.defaultContentType); + oRequest.set('retry', xc.defaultRetry); + oRequest.set('returnValue', xc.defaultReturnValue); + oRequest.set('maxObjectDepth', xc.maxObjectDepth); + oRequest.set('maxObjectSize', xc.maxObjectSize); + oRequest.set('context', window); + + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = xcb.create(); + + lcb.take = function(frm, opt) { + if ('undefined' != typeof frm[opt]) { + lcb[opt] = frm[opt]; + lcb.hasEvents = true; + } + delete frm[opt]; + } + + lcb.take(oRequest, 'onRequest'); + lcb.take(oRequest, 'onResponseDelay'); + lcb.take(oRequest, 'onExpiration'); + lcb.take(oRequest, 'beforeResponseProcessing'); + lcb.take(oRequest, 'onFailure'); + lcb.take(oRequest, 'onRedirect'); + lcb.take(oRequest, 'onSuccess'); + lcb.take(oRequest, 'onComplete'); + + if ('undefined' != typeof oRequest.callback) { + if (lcb.hasEvents) + oRequest.callback = [oRequest.callback, lcb]; + } else + oRequest.callback = lcb; + + oRequest.status = (oRequest.statusMessages) + ? xc.status.update() + : xc.status.dontUpdate(); + + oRequest.cursor = (oRequest.waitCursor) + ? xc.cursor.update() + : xc.cursor.dontUpdate(); + + oRequest.method = oRequest.method.toUpperCase(); + if ('GET' != oRequest.method) + oRequest.method = 'POST'; // W3C: Method is case sensitive + + oRequest.requestRetry = oRequest.retry; + + oRequest.append('postHeaders', { + 'content-type': oRequest.contentType + }); + + delete oRequest['append']; + delete oRequest['set']; + delete oRequest['take']; + + if ('undefined' == typeof oRequest.URI) + throw { code: 10005 } +} + +/* + Function: xajax.processParameters + + Processes request specific parameters and generates the temporary + variables needed by xajax to initiate and process the request. + + Parameters: + + oRequest - A request object, created initially by a call to + + + Note: + This is called once per request; upon a request failure, this + will not be called for additional retries. +*/ +xajax.processParameters = function(oRequest) { + var xx = xajax; + var xt = xx.tools; + + var rd = []; + + var separator = ''; + for (var sCommand in oRequest.functionName) { + if ('constructor' != sCommand) { + rd.push(separator); + rd.push(sCommand); + rd.push('='); + rd.push(encodeURIComponent(oRequest.functionName[sCommand])); + separator = '&'; + } + } + var dNow = new Date(); + rd.push('&xjxr='); + rd.push(dNow.getTime()); + delete dNow; + + if (oRequest.parameters) { + var i = 0; + var iLen = oRequest.parameters.length; + while (i < iLen) { + var oVal = oRequest.parameters[i]; + if ('object' == typeof oVal && null != oVal) { + try { +// var oGuard = {}; +// oGuard.depth = 0; +// oGuard.maxDepth = oRequest.maxObjectDepth; +// oGuard.size = 0; +// oGuard.maxSize = oRequest.maxObjectSize; + //oVal = xt._objectToXML(oVal, oGuard); + oVal = JSON.stringify(oVal); + } catch (e) { + oVal = ''; + // do nothing, if the debug module is installed + // it will catch the exception and handle it + } + rd.push('&xjxargs[]='); + oVal = encodeURIComponent(oVal); + rd.push(oVal); + ++i; + } else { + rd.push('&xjxargs[]='); + + if ('undefined' == typeof oVal || null == oVal) { + rd.push('*'); + } else { + var sType = typeof oVal; + if ('string' == sType) + rd.push('S'); + else if ('boolean' == sType) + rd.push('B'); + else if ('number' == sType) + rd.push('N'); + oVal = encodeURIComponent(oVal); + rd.push(oVal); + } + ++i; + } + } + } + + oRequest.requestURI = oRequest.URI; + + if ('GET' == oRequest.method) { + oRequest.requestURI += oRequest.requestURI.indexOf('?')== -1 ? '?' : '&'; + oRequest.requestURI += rd.join(''); + rd = []; + } + + oRequest.requestData = rd.join(''); +} + +/* + Function: xajax.prepareRequest + + Prepares the XMLHttpRequest object for this xajax request. + + Parameters: + + oRequest - (object): An object created by a call to + which already contains the necessary parameters and temporary variables + needed to initiate and process a xajax request. + + Note: + This is called each time a request object is being prepared for a + call to the server. If the request is retried, the request must be + prepared again. +*/ +xajax.prepareRequest = function(oRequest) { + var xx = xajax; + var xt = xx.tools; + + oRequest.request = xt.getRequestObject(); + + oRequest.setRequestHeaders = function(headers) { + if ('object' == typeof headers) { + for (var optionName in headers) + this.request.setRequestHeader(optionName, headers[optionName]); + } + } + oRequest.setCommonRequestHeaders = function() { + this.setRequestHeaders(this.commonHeaders); + if (this.challengeResponse) + this.request.setRequestHeader('challenge-response', this.challengeResponse); + } + oRequest.setPostRequestHeaders = function() { + this.setRequestHeaders(this.postHeaders); + } + oRequest.setGetRequestHeaders = function() { + this.setRequestHeaders(this.getHeaders); + } + + if ('asynchronous' == oRequest.mode) { + // references inside this function should be expanded + // IOW, don't use shorthand references like xx for xajax + oRequest.request.onreadystatechange = function() { + if (oRequest.request.readyState != 4) + return; + xajax.responseReceived(oRequest); + } + oRequest.finishRequest = function() { + return this.returnValue; + } + } else { + oRequest.finishRequest = function() { + return xajax.responseReceived(oRequest); + } + } + + if ('undefined' != typeof oRequest.userName && 'undefined' != typeof oRequest.password) { + oRequest.open = function() { + this.request.open( + this.method, + this.requestURI, + 'asynchronous' == this.mode, + oRequest.userName, + oRequest.password); + } + } else { + oRequest.open = function() { + this.request.open( + this.method, + this.requestURI, + 'asynchronous' == this.mode); + } + } + + if ('POST' == oRequest.method) { // W3C: Method is case sensitive + oRequest.applyRequestHeaders = function() { + this.setCommonRequestHeaders(); + try { + this.setPostRequestHeaders(); + } catch (e) { + this.method = 'GET'; + this.requestURI += this.requestURI.indexOf('?')== -1 ? '?' : '&'; + this.requestURI += this.requestData; + this.requestData = ''; + if (0 == this.requestRetry) this.requestRetry = 1; + throw e; + } + } + } else { + oRequest.applyRequestHeaders = function() { + this.setCommonRequestHeaders(); + this.setGetRequestHeaders(); + } + } +} + +/* + Function: xajax.request + + Initiates a request to the server. + + Parameters: + + functionName - (object): An object containing the name of the function to execute + on the server. The standard request is: {xjxfun:'function_name'} + + oRequest - (object, optional): A request object which + may contain call specific parameters. This object will be + used by xajax to store all the request parameters as well + as temporary variables needed during the processing of the + request. + +*/ +xajax.request = function() { + var numArgs = arguments.length; + if (0 == numArgs) + return false; + + var oRequest = {} + if (1 < numArgs) + oRequest = arguments[1]; + + oRequest.functionName = arguments[0]; + + var xx = xajax; + + xx.initializeRequest(oRequest); + xx.processParameters(oRequest); + while (0 < oRequest.requestRetry) { + try { + --oRequest.requestRetry; + xx.prepareRequest(oRequest); + return xx.submitRequest(oRequest); + } catch (e) { + xajax.callback.execute( + [xajax.callback.global, oRequest.callback], + 'onFailure', + oRequest + ); + if (0 == oRequest.requestRetry) + throw e; + } + } +} + +/* + Function: xajax.submitRequest + + Create a request object and submit the request using the specified + request type; all request parameters should be finalized by this + point. Upon failure of a POST, this function will fall back to a + GET request. + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax.submitRequest = function(oRequest) { + oRequest.status.onRequest(); + + var xcb = xajax.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + + xcb.execute([gcb, lcb], 'onResponseDelay', oRequest); + xcb.execute([gcb, lcb], 'onExpiration', oRequest); + xcb.execute([gcb, lcb], 'onRequest', oRequest); + + oRequest.open(); + oRequest.applyRequestHeaders(); + + oRequest.cursor.onWaiting(); + oRequest.status.onWaiting(); + + xajax._internalSend(oRequest); + + // synchronous mode causes response to be processed immediately here + return oRequest.finishRequest(); +} + +/* + Function: xajax._internalSend + + This function is used internally by xajax to initiate a request to the + server. + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax._internalSend = function(oRequest) { + // this may block if synchronous mode is selected + oRequest.request.send(oRequest.requestData); +} + +/* + Function: xajax.abortRequest + + Abort the request. + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax.abortRequest = function(oRequest) +{ + oRequest.aborted = true; + oRequest.request.abort(); + xajax.completeResponse(oRequest); +} + +/* + Function: xajax.responseReceived + + Process the response. + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax.responseReceived = function(oRequest) { + var xx = xajax; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + // sometimes the responseReceived gets called when the + // request is aborted + if (oRequest.aborted) + return; + + xcb.clearTimer([gcb, lcb], 'onExpiration'); + xcb.clearTimer([gcb, lcb], 'onResponseDelay'); + + xcb.execute([gcb, lcb], 'beforeResponseProcessing', oRequest); + + var challenge = oRequest.request.getResponseHeader('challenge'); + if (challenge) { + oRequest.challengeResponse = challenge; + xx.prepareRequest(oRequest); + return xx.submitRequest(oRequest); + } + + var fProc = xx.getResponseProcessor(oRequest); + if ('undefined' == typeof fProc) { + xcb.execute([gcb, lcb], 'onFailure', oRequest); + xx.completeResponse(oRequest); + return; + } + + return fProc(oRequest); +} + +/* + Function: xajax.getResponseProcessor + + This function attempts to determine, based on the content type of the + reponse, what processor should be used for handling the response data. + + The default xajax response will be text/xml which will invoke the + xajax xml response processor. Other response processors may be added + in the future. The user can specify their own response processor on + a call by call basis. + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax.getResponseProcessor = function(oRequest) { + var fProc; + + if ('undefined' == typeof oRequest.responseProcessor) { + var cTyp = oRequest.request.getResponseHeader('content-type'); + if (cTyp) { + if (0 <= cTyp.indexOf('text/xml')) { + fProc = xajax.responseProcessor.xml; + } else if (0 <= cTyp.indexOf('application/json')) { + fProc = xajax.responseProcessor.json; + } + } + } else fProc = oRequest.responseProcessor; + + return fProc; +} + +/* + Function: xajax.executeCommand + + Perform a lookup on the command specified by the response command + object passed in the first parameter. If the command exists, the + function checks to see if the command references a DOM object by + ID; if so, the object is located within the DOM and added to the + command data. The command handler is then called. + + If the command handler returns true, it is assumed that the command + completed successfully. If the command handler returns false, then the + command is considered pending; xajax enters a wait state. It is up + to the command handler to set an interval, timeout or event handler + which will restart the xajax response processing. + + Parameters: + + obj - (object): The response command to be executed. + + Returns: + + true - The command completed successfully. + false - The command signalled that it needs to pause processing. +*/ +xajax.executeCommand = function(command) { + if (xajax.command.handler.isRegistered(command)) { + // it is important to grab the element here as the previous command + // might have just created the element + if (command.id) + command.target = xajax.$(command.id); + // process the command + if (false == xajax.command.handler.call(command)) { + xajax.tools.queue.pushFront(xajax.response, command); + return false; + } + } + return true; +} + +/* + Function: xajax.completeResponse + + Called by the response command queue processor when all commands have + been processed. + + Parameters: + + oRequest - (object): The request context object. +*/ +xajax.completeResponse = function(oRequest) { + xajax.callback.execute( + [xajax.callback.global, oRequest.callback], + 'onComplete', + oRequest + ); + oRequest.cursor.onComplete(); + oRequest.status.onComplete(); + // clean up -- these items are restored when the request is initiated + delete oRequest['functionName']; + delete oRequest['requestURI']; + delete oRequest['requestData']; + delete oRequest['requestRetry']; + delete oRequest['request']; + delete oRequest['set']; + delete oRequest['open']; + delete oRequest['setRequestHeaders']; + delete oRequest['setCommonRequestHeaders']; + delete oRequest['setPostRequestHeaders']; + delete oRequest['setGetRequestHeaders']; + delete oRequest['applyRequestHeaders']; + delete oRequest['finishRequest']; + delete oRequest['status']; + delete oRequest['cursor']; + delete oRequest['challengeResponse']; +} + +/* + Function: xajax.$ + + Shortcut to . +*/ +xajax.$ = xajax.tools.$; + +/* + Function: xajax.getFormValues + + Shortcut to . +*/ +xajax.getFormValues = xajax.tools.getFormValues; + +/* + Boolean: xajax.isLoaded + + true - xajax module is loaded. +*/ +xajax.isLoaded = true; + + +/* + Class: xjx + + Contains shortcut's to frequently used functions. +*/ +xjx = {} + +/* + Function: xjx.$ + + Shortcut to . +*/ +xjx.$ = xajax.tools.$; + +/* + Function: xjx.getFormValues + + Shortcut to . +*/ +xjx.getFormValues = xajax.tools.getFormValues; + + +xjx.request = xajax.request; + +if ('undefined' == typeof JSON) xajax.js.includeScript({data:xajax.config.JavaScriptURI+'xajax_js/JSON.js'}); \ No newline at end of file diff --git a/www/include/xajax/xajax_js/xajax_debug.js b/www/include/xajax/xajax_js/xajax_debug.js new file mode 100644 index 00000000..678c4b71 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_debug.js @@ -0,0 +1,883 @@ +/* + File: xajax_debug.js + + This optional file contains the debugging module for use with xajax. If + you include this module after the standard module, you + will receive debugging messages, including errors, that occur during + the processing of your xajax requests. + + Title: xajax debugging module + + Please see for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajax_debug_uncompressed.js 327 2007-02-28 16:55:26Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +try +{ + /* + Class: xajax.debug + + This object contains the variables and functions used to display process state + messages and to trap error conditions and report them to the user via + a secondary browser window or alert messages as necessary. + */ + if ('undefined' == typeof xajax) + throw { name: 'SequenceError', message: 'Error: xajax core was not detected, debug module disabled.' } + + if ('undefined' == typeof xajax.debug) + xajax.debug = {} + + /* + String: xajax.debug.workId + + Stores a 'unique' identifier for this session so that an existing debugging + window can be detected, else one will be created. + */ + xajax.debug.workId = 'xajaxWork'+ new Date().getTime(); + + /* + String: xajax.debug.windowSource + + The default URL that is given to the debugging window upon creation. + */ + xajax.debug.windowSource = 'about:blank'; + + /* + String: xajax.debug.windowID + + A 'unique' name used to identify the debugging window that is attached + to this xajax session. + */ + xajax.debug.windowID = 'xajax_debug_'+xajax.debug.workId; + + /* + String: windowStyle + + The parameters that will be used to create the debugging window. + */ + if ('undefined' == typeof xajax.debug.windowStyle) + xajax.debug.windowStyle = + 'width=800,' + + 'height=600,' + + 'scrollbars=yes,' + + 'resizable=yes,' + + 'status=yes'; + + /* + String: windowTemplate + + The HTML template and CSS style information used to populate the + debugging window upon creation. + */ + if ('undefined' == typeof xajax.debug.windowTemplate) + xajax.debug.windowTemplate = + '' + + '' + + 'xajax debug output' + + '' + + '' + + '

xajax debug output

' + + '
' + + ''; + + /* + Object: window + + A reference to the debugging window, once constructed, where messages will + be displayed throughout the request process. This is constructed internally + as needed. + */ + + /* + Array: xajax.debug.text + */ + xajax.debug.text = []; + xajax.debug.text[100] = 'WARNING: '; + xajax.debug.text[101] = 'ERROR: '; + xajax.debug.text[102] = 'XAJAX DEBUG MESSAGE:\n'; + xajax.debug.text[103] = '...\n[LONG RESPONSE]\n...'; + xajax.debug.text[104] = 'SENDING REQUEST'; + xajax.debug.text[105] = 'SENT ['; + xajax.debug.text[106] = ' bytes]'; + xajax.debug.text[107] = 'CALLING: '; + xajax.debug.text[108] = 'URI: '; + xajax.debug.text[109] = 'INITIALIZING REQUEST'; + xajax.debug.text[110] = 'PROCESSING PARAMETERS ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'NO PARAMETERS TO PROCESS'; + xajax.debug.text[113] = 'PREPARING REQUEST'; + xajax.debug.text[114] = 'STARTING XAJAX CALL (deprecated: use xajax.request instead)'; + xajax.debug.text[115] = 'STARTING XAJAX REQUEST'; + xajax.debug.text[116] = 'No response processor is available to process the response from the server.\n'; + xajax.debug.text[117] = '.\nCheck for error messages from the server.'; + xajax.debug.text[118] = 'RECEIVED [status: '; + xajax.debug.text[119] = ', size: '; + xajax.debug.text[120] = ' bytes, time: '; + xajax.debug.text[121] = 'ms]:\n'; + xajax.debug.text[122] = 'The server returned the following HTTP status: '; + xajax.debug.text[123] = '\nRECEIVED:\n'; + xajax.debug.text[124] = 'The server returned a redirect to:
'; + xajax.debug.text[125] = 'DONE ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'INITIALIZING REQUEST OBJECT'; + + /* + Array: xajax.debug.exceptions + */ + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Invalid response XML: The response contains an unknown tag: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: XMLHttpRequest is not available, xajax is disabled.'; + xajax.debug.exceptions[10003] = 'Queue overflow: Cannot push object onto queue because it is full.'; + xajax.debug.exceptions[10004] = 'Invalid response XML: The response contains an unexpected tag or text: {data}.'; + xajax.debug.exceptions[10005] = 'Invalid request URI: Invalid or missing URI; autodetection failed; please specify a one explicitly.'; + xajax.debug.exceptions[10006] = 'Invalid response command: Malformed response command received.'; + xajax.debug.exceptions[10007] = 'Invalid response command: Command [{data}] is not a known command.'; + xajax.debug.exceptions[10008] = 'Element with ID [{data}] not found in the document.'; + xajax.debug.exceptions[10009] = 'Invalid request: Missing function name parameter.'; + xajax.debug.exceptions[10010] = 'Invalid request: Missing function object parameter.'; + + /* + Function: xajax.debug.getExceptionText + + Parameters: + e - (object): Exception + */ + xajax.debug.getExceptionText = function(e) { + if ('undefined' != typeof e.code) { + if ('undefined' != typeof xajax.debug.exceptions[e.code]) { + var msg = xajax.debug.exceptions[e.code]; + if ('undefined' != typeof e.data) { + msg.replace('{data}', e.data); + } + return msg; + } + } else if ('undefined' != typeof e.name) { + var msg = e.name; + if ('undefined' != typeof e.message) { + msg += ': '; + msg += e.message; + } + return msg; + } + return 'An unknown error has occurred.'; + } + + /* + Function: xajax.debug.writeMessage + + Output a debug message to the debug window if available or send to an + alert box. If the debug window has not been created, attempt to + create it. + + Parameters: + + text - (string): The text to output. + + prefix - (string): The prefix to use; this is prepended onto the + message; it should indicate the type of message (warning, error) + + cls - (stirng): The className that will be applied to the message; + invoking a style from the CSS provided in + . Should be one of the following: + - warningText + - errorText + */ + xajax.debug.writeMessage = function(text, prefix, cls) { + try { + var xd = xajax.debug; + if ('undefined' == typeof xd.window || true == xd.window.closed) { + xd.window = window.open(xd.windowSource, xd.windowID, xd.windowStyle); + if ("about:blank" == xd.windowSource) + xd.window.document.write(xd.windowTemplate); + } + var xdw = xd.window; + var xdwd = xdw.document; + if ('undefined' == typeof prefix) + prefix = ''; + if ('undefined' == typeof cls) + cls = 'debugText'; + + text = xajax.debug.prepareDebugText(text); + + var debugTag = xdwd.getElementById('debugTag'); + var debugEntry = xdwd.createElement('div'); + var debugDate = xdwd.createElement('span'); + var debugText = xdwd.createElement('pre'); + + debugDate.innerHTML = new Date().toString(); + debugText.innerHTML = prefix + text; + + debugEntry.appendChild(debugDate); + debugEntry.appendChild(debugText); + debugTag.insertBefore(debugEntry, debugTag.firstChild); + // don't allow 'style' issues to hinder the debug output + try { + debugEntry.className = 'debugEntry'; + debugDate.className = 'debugDate'; + debugText.className = cls; + } catch (e) { + } + } catch (e) { + if (text.length > 1000) text = text.substr(0,1000) + xajax.debug.text[102]; + alert(xajax.debug.text[102] + text); + } + } + + /* + Function: xajax.debug.prepareDebugText + + Convert special characters to their HTML equivellents so they + will show up in the . + + Parameters: + text - (string): Debug text + */ + xajax.debug.prepareDebugText = function(text) { + try { + text = text.replace(/&/g, '&') + .replace(//g, '>') + .replace(/\n/g, '
'); + return text; + } catch (e) { + xajax.debug.stringReplace = function(haystack, needle, newNeedle) { + var segments = haystack.split(needle); + haystack = ''; + for (var i = 0; i < segments.length; ++i) { + if (0 != i) + haystack += newNeedle; + haystack += segments[i]; + } + return haystack; + } + xajax.debug.prepareDebugText = function(text) { + text = xajax.debug.stringReplace(text, '&', '&'); + text = xajax.debug.stringReplace(text, '<', '<'); + text = xajax.debug.stringReplace(text, '>', '>'); + text = xajax.debug.stringReplace(text, '\n', '
'); + return text; + } + xajax.debug.prepareDebugText(text); + } + } + + /* + Function: xajax.debug.executeCommand + + Catch any exceptions that are thrown by a response command handler + and display a message in the debugger. + + This is a wrapper function which surrounds the standard + function. + */ + xajax.debug.executeCommand = xajax.executeCommand; + xajax.executeCommand = function(args) { + try { + if ('undefined' == typeof args.cmd) + throw { code: 10006 }; + if (false == xajax.command.handler.isRegistered(args)) + throw { code: 10007, data: args.cmd }; + return xajax.debug.executeCommand(args); + } catch(e) { + var msg = 'ExecuteCommand ('; + if ('undefined' != typeof args.sequence) { + msg += '#'; + msg += args.sequence; + msg += ', '; + } + if ('undefined' != typeof args.cmdFullName) { + msg += '"'; + msg += args.cmdFullName; + msg += '"'; + } + msg += '):\n'; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + return true; + } + + /* + Function: xajax.parseAttributes + + Catch any exception thrown during the parsing of response + command attributes and display an appropriate debug message. + + This is a wrapper around the standard + function. + + Parameters: + child - (object): Childnode + obj - (object): Object + + */ + xajax.debug.parseAttributes = xajax.parseAttributes; + xajax.parseAttributes = function(child, obj) { + try { + xajax.debug.parseAttributes(child, obj); + } catch(e) { + var msg = 'ParseAttributes:\n'; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + } + + xajax.debug.commandHandler = xajax.command.handler.unregister('dbg'); + xajax.command.handler.register('dbg', function(args) { + args.cmdFullName = 'debug message'; + xajax.debug.writeMessage(args.data, xajax.debug.text[100], 'warningText'); + return xajax.debug.commandHandler(args); + }); + + + /* + Function: xajax.tools.$ + + Catch any exceptions thrown while attempting to locate an + HTML element by it's unique name. + + This is a wrapper around the standard function. + + Parameters: + sId - (string): Element ID or name + + */ + xajax.debug.$ = xajax.tools.$; + xajax.tools.$ = function(sId) { + try { + var returnValue = xajax.debug.$(sId); + if ('object' != typeof returnValue) + throw { code: 10008 }; + } + catch (e) { + var msg = '$:'; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[100], 'warningText'); + } + return returnValue; + } + + /* + Function: xajax.tools._objectToXML + + Generate a message indicating that a javascript object is + being converted to xml. Indicate the max depth and size. Then + display the size of the object upon completion. Catch any + exceptions thrown during the conversion process. + + This is a wrapper around the standard + function. + + Parameters: + obj - (object): + guard - (object): + + */ + xajax.debug._objectToXML = xajax.tools._objectToXML; + xajax.tools._objectToXML = function(obj, guard) { + try { + if (0 == guard.size) { + var msg = 'OBJECT TO XML: maxDepth = '; + msg += guard.maxDepth; + msg += ', maxSize = '; + msg += guard.maxSize; + xajax.debug.writeMessage(msg); + } + var r = xajax.debug._objectToXML(obj, guard); + if (0 == guard.depth) { + var msg = 'OBJECT TO XML: size = '; + msg += guard.size; + xajax.debug.writeMessage(msg); + } + return r; + } catch(e) { + var msg = 'ObjectToXML: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + return ''; + } + + /* + Function: xajax._internalSend + + Generate a message indicating that the xajax request is + about the be sent to the server. + + This is a wrapper around the standard + function. + */ + xajax.debug._internalSend = xajax._internalSend; + xajax._internalSend = function(oRequest) { + try { + xajax.debug.writeMessage(xajax.debug.text[104]); + xajax.debug.writeMessage( + xajax.debug.text[105] + + oRequest.requestData.length + + xajax.debug.text[106] + ); + oRequest.beginDate = new Date(); + xajax.debug._internalSend(oRequest); + } catch (e) { + var msg = 'InternalSend: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.submitRequest + + Generate a message indicating that a request is ready to be + submitted; providing the URL and the function being invoked. + + Catch any exceptions thrown and display a message. + + This is a wrapper around the standard + function. + */ + xajax.debug.submitRequest = xajax.submitRequest; + xajax.submitRequest = function(oRequest) { + var msg = oRequest.method; + msg += ': '; + text = decodeURIComponent(oRequest.requestData); + text = text.replace(new RegExp('&xjx', 'g'), '\n&xjx'); + text = text.replace(new RegExp('', 'g'), '\n'); + text = text.replace(new RegExp('', 'g'), '\n'); + text = text.replace(new RegExp('', 'g'), '\n\n'); + msg += text; + xajax.debug.writeMessage(msg); + msg = xajax.debug.text[107]; + var separator = '\n'; + for (var mbr in oRequest.functionName) { + msg += separator; + msg += mbr; + msg += ': '; + msg += oRequest.functionName[mbr]; + separator = '\n'; + } + msg += separator; + msg += xajax.debug.text[108]; + msg += separator; + msg += oRequest.URI; + xajax.debug.writeMessage(msg); + + try { + return xajax.debug.submitRequest(oRequest); + } catch (e) { + xajax.debug.writeMessage(e.message); + if (0 < oRequest.retry) + throw e; + } + } + + /* + Function: xajax.initializeRequest + + Generate a message indicating that the request object is + being initialized. + + This is a wrapper around the standard + function. + */ + xajax.debug.initializeRequest = xajax.initializeRequest; + xajax.initializeRequest = function(oRequest) { + try { + var msg = xajax.debug.text[109]; + xajax.debug.writeMessage(msg); + return xajax.debug.initializeRequest(oRequest); + } catch (e) { + var msg = 'InitializeRequest: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.processParameters + + Generate a message indicating that the request object is + being populated with the parameters provided. + + This is a wrapper around the standard + function. + */ + xajax.debug.processParameters = xajax.processParameters; + xajax.processParameters = function(oRequest) { + try { + if ('undefined' != typeof oRequest.parameters) { + var msg = xajax.debug.text[110]; + msg += oRequest.parameters.length; + msg += xajax.debug.text[111]; + xajax.debug.writeMessage(msg); + } else { + var msg = xajax.debug.text[112]; + xajax.debug.writeMessage(msg); + } + return xajax.debug.processParameters(oRequest); + } catch (e) { + var msg = 'ProcessParameters: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.prepareRequest + + Generate a message indicating that the request is being + prepared. This may occur more than once for a request + if it errors and a retry is attempted. + + This is a wrapper around the standard + */ + xajax.debug.prepareRequest = xajax.prepareRequest; + xajax.prepareRequest = function(oRequest) { + try { + var msg = xajax.debug.text[113]; + xajax.debug.writeMessage(msg); + return xajax.debug.prepareRequest(oRequest); + } catch (e) { + var msg = 'PrepareRequest: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.call + + Validates that a function name was provided, generates a message + indicating that a xajax call is starting and sets a flag in the + request object indicating that debugging is enabled for this call. + + This is a wrapper around the standard function. + */ + xajax.debug.call = xajax.call; + xajax.call = function() { + try { + xajax.debug.writeMessage(xajax.debug.text[114]); + + var numArgs = arguments.length; + + if (0 == numArgs) + throw { code: 10009 }; + + var functionName = arguments[0]; + var oOptions = {} + if (1 < numArgs) + oOptions = arguments[1]; + + oOptions.debugging = true; + + return xajax.debug.call(functionName, oOptions); + } catch (e) { + var msg = 'Call: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.request + + Validates that a function name was provided, generates a message + indicating that a xajax request is starting and sets a flag in the + request object indicating that debugging is enabled for this request. + + This is a wrapper around the standard function. + */ + xajax.debug.request = xajax.request; + xajax.request = function() { + try { + xajax.debug.writeMessage(xajax.debug.text[115]); + + var numArgs = arguments.length; + + if (0 == numArgs) + throw { code: 10010 }; + + var oFunction = arguments[0]; + var oOptions = {} + if (1 < numArgs) + oOptions = arguments[1]; + + oOptions.debugging = true; + + return xajax.debug.request(oFunction, oOptions); + } catch (e) { + var msg = 'Request: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.getResponseProcessor + + Generate an error message when no reponse processor is available + to process the type of response returned from the server. + + This is a wrapper around the standard + function. + */ + xajax.debug.getResponseProcessor = xajax.getResponseProcessor; + xajax.getResponseProcessor = function(oRequest) { + try { + var fProc = xajax.debug.getResponseProcessor(oRequest); + + if ('undefined' == typeof fProc) { + var msg = xajax.debug.text[116]; + try { + var contentType = oRequest.request.getResponseHeader('content-type'); + msg += "Content-Type: "; + msg += contentType; + if ('text/html' == contentType) { + msg += xajax.debug.text[117]; + } + } catch (e) { + } + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + + return fProc; + } catch (e) { + var msg = 'GetResponseProcessor: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.responseReceived + + Generate a message indicating that a response has been received + from the server; provide some statistical data regarding the + response and the response time. + + Catch any exceptions that are thrown during the processing of + the response and generate a message. + + This is a wrapper around the standard + function. + */ + xajax.debug.responseReceived = xajax.responseReceived; + xajax.responseReceived = function(oRequest) { + var xx = xajax; + var xt = xx.tools; + var xd = xx.debug; + + var oRet; + + try { + var status = oRequest.request.status; + if (xt.in_array(xx.responseSuccessCodes, status)) { + var packet = oRequest.request.responseText; + packet = packet.replace(new RegExp('', 'g'), '\n'); + packet = packet.replace(new RegExp('', 'g'), '\n'); + packet = packet.replace(new RegExp('', 'g'), '\n'); + packet = packet.replace(new RegExp('', 'g'), '\n\n'); + packet = packet.replace(new RegExp('', 'g'), '\n'); + oRequest.midDate = new Date(); + var msg = xajax.debug.text[118]; + msg += oRequest.request.status; + msg += xajax.debug.text[119]; + msg += packet.length; + msg += xajax.debug.text[120]; + msg += (oRequest.midDate - oRequest.beginDate); + msg += xajax.debug.text[121]; + msg += packet; + xd.writeMessage(msg); + } else if (xt.in_array(xx.responseErrorsForAlert, status)) { + var msg = xajax.debug.text[122]; + msg += status; + msg += xajax.debug.text[123]; + msg += oRequest.request.responseText; + xd.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } else if (xt.in_array(xx.responseRedirectCodes, status)) { + var msg = xajax.debug.text[124]; + msg += oRequest.request.getResponseHeader('location'); + xd.writeMessage(msg); + } + oRet = xd.responseReceived(oRequest); + } catch (e) { + var msg = 'ResponseReceived: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xd.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + + return oRet; + } + + /* + Function: xajax.completeResponse + + Generate a message indicating that the request has completed + and provide some statistics regarding the request and response. + + This is a wrapper around the standard + function. + */ + xajax.debug.completeResponse = xajax.completeResponse; + xajax.completeResponse = function(oRequest) { + try { + var returnValue = xajax.debug.completeResponse(oRequest); + oRequest.endDate = new Date(); + var msg = xajax.debug.text[125]; + msg += (oRequest.endDate - oRequest.beginDate); + msg += xajax.debug.text[126]; + xajax.debug.writeMessage(msg); + return returnValue; + } catch (e) { + var msg = 'CompleteResponse: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.tools.getRequestObject + + Generate a message indicating that the request object is + being initialized. + + Catch any exceptions that are thrown during the process or + initializing a new request object. + + This is a wrapper around the standard + function. + */ + xajax.debug.getRequestObject = xajax.tools.getRequestObject; + xajax.tools.getRequestObject = function() { + try { + xajax.debug.writeMessage(xajax.debug.text[127]); + return xajax.debug.getRequestObject(); + } catch (e) { + var msg = 'GetRequestObject: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.dom.assign + + Catch any exceptions thrown during the assignment and + display an error message. + + This is a wrapper around the standard + function. + */ + if (xajax.dom.assign) { + xajax.debug.assign = xajax.dom.assign; + xajax.dom.assign = function(element, property, data) { + try { + return xajax.debug.assign(element, property, data); + } catch (e) { + var msg = 'xajax.dom.assign: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + msg += 'Eval: element.'; + msg += property; + msg += ' = data;\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + return true; + } + } + + /* + Function: xajax.tools.queue.retry + */ + if (xajax.tools) { + if (xajax.tools.queue) { + if (xajax.tools.queue.retry) { + if ('undefined' == typeof xajax.debug.tools) + xajax.debug.tools = {}; + if ('undefined' == typeof xajax.debug.tools.queue) + xajax.debug.tools.queue = {}; + xajax.debug.tools.queue.retry = xajax.tools.queue.retry; + xajax.tools.queue.retry = function(obj, count) { + if (xajax.debug.tools.queue.retry(obj, count)) + return true; + // no 'exceeded' message for sleep command + if (obj.cmd && 's' == obj.cmd) + return false; + xajax.debug.writeMessage('Retry count exceeded.'); + return false; + } + } + } + } + + /* + Boolean: xajax.debug.isLoaded + + true - indicates that the debugging module is loaded + */ + xajax.debug.isLoaded = true; + + /* + Section: Redefine shortcuts. + + Must redefine these shortcuts so they point to the new debug (wrapper) versions: + - + - + - + + Must redefine these shortcuts as well: + - + - + */ + xjx = {} + + xjx.$ = xajax.tools.$; + xjx.getFormValues = xajax.tools.getFormValues; + xjx.call = xajax.call; + xjx.request = xajax.request; + + xajax.$ = xajax.tools.$; + xajax.getFormValues = xajax.tools.getFormValues; +} catch (e) { + alert(e.name + ': ' + e.message); +} diff --git a/www/include/xajax/xajax_js/xajax_debug_uncompressed.js b/www/include/xajax/xajax_js/xajax_debug_uncompressed.js new file mode 100644 index 00000000..a5decc63 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_debug_uncompressed.js @@ -0,0 +1,883 @@ +/* + File: xajax_debug.js + + This optional file contains the debugging module for use with xajax. If + you include this module after the standard module, you + will receive debugging messages, including errors, that occur during + the processing of your xajax requests. + + Title: xajax debugging module + + Please see for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajax_debug_uncompressed.js 327 2007-02-28 16:55:26Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2009 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +try +{ + /* + Class: xajax.debug + + This object contains the variables and functions used to display process state + messages and to trap error conditions and report them to the user via + a secondary browser window or alert messages as necessary. + */ + if ('undefined' == typeof xajax) + throw { name: 'SequenceError', message: 'Error: xajax core was not detected, debug module disabled.' } + + if ('undefined' == typeof xajax.debug) + xajax.debug = {} + + /* + String: xajax.debug.workId + + Stores a 'unique' identifier for this session so that an existing debugging + window can be detected, else one will be created. + */ + xajax.debug.workId = 'xajaxWork'+ new Date().getTime(); + + /* + String: xajax.debug.windowSource + + The default URL that is given to the debugging window upon creation. + */ + xajax.debug.windowSource = 'about:blank'; + + /* + String: xajax.debug.windowID + + A 'unique' name used to identify the debugging window that is attached + to this xajax session. + */ + xajax.debug.windowID = 'xajax_debug_'+xajax.debug.workId; + + /* + String: windowStyle + + The parameters that will be used to create the debugging window. + */ + if ('undefined' == typeof xajax.debug.windowStyle) + xajax.debug.windowStyle = + 'width=800,' + + 'height=600,' + + 'scrollbars=yes,' + + 'resizable=yes,' + + 'status=yes'; + + /* + String: windowTemplate + + The HTML template and CSS style information used to populate the + debugging window upon creation. + */ + if ('undefined' == typeof xajax.debug.windowTemplate) + xajax.debug.windowTemplate = + '' + + '' + + 'xajax debug output' + + '' + + '' + + '

xajax debug output

' + + '
' + + ''; + + /* + Object: window + + A reference to the debugging window, once constructed, where messages will + be displayed throughout the request process. This is constructed internally + as needed. + */ + + /* + Array: xajax.debug.text + */ + xajax.debug.text = []; + xajax.debug.text[100] = 'WARNING: '; + xajax.debug.text[101] = 'ERROR: '; + xajax.debug.text[102] = 'XAJAX DEBUG MESSAGE:\n'; + xajax.debug.text[103] = '...\n[LONG RESPONSE]\n...'; + xajax.debug.text[104] = 'SENDING REQUEST'; + xajax.debug.text[105] = 'SENT ['; + xajax.debug.text[106] = ' bytes]'; + xajax.debug.text[107] = 'CALLING: '; + xajax.debug.text[108] = 'URI: '; + xajax.debug.text[109] = 'INITIALIZING REQUEST'; + xajax.debug.text[110] = 'PROCESSING PARAMETERS ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'NO PARAMETERS TO PROCESS'; + xajax.debug.text[113] = 'PREPARING REQUEST'; + xajax.debug.text[114] = 'STARTING XAJAX CALL (deprecated: use xajax.request instead)'; + xajax.debug.text[115] = 'STARTING XAJAX REQUEST'; + xajax.debug.text[116] = 'No response processor is available to process the response from the server.\n'; + xajax.debug.text[117] = '.\nCheck for error messages from the server.'; + xajax.debug.text[118] = 'RECEIVED [status: '; + xajax.debug.text[119] = ', size: '; + xajax.debug.text[120] = ' bytes, time: '; + xajax.debug.text[121] = 'ms]:\n'; + xajax.debug.text[122] = 'The server returned the following HTTP status: '; + xajax.debug.text[123] = '\nRECEIVED:\n'; + xajax.debug.text[124] = 'The server returned a redirect to:
'; + xajax.debug.text[125] = 'DONE ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'INITIALIZING REQUEST OBJECT'; + + /* + Array: xajax.debug.exceptions + */ + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Invalid response XML: The response contains an unknown tag: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: XMLHttpRequest is not available, xajax is disabled.'; + xajax.debug.exceptions[10003] = 'Queue overflow: Cannot push object onto queue because it is full.'; + xajax.debug.exceptions[10004] = 'Invalid response XML: The response contains an unexpected tag or text: {data}.'; + xajax.debug.exceptions[10005] = 'Invalid request URI: Invalid or missing URI; autodetection failed; please specify a one explicitly.'; + xajax.debug.exceptions[10006] = 'Invalid response command: Malformed response command received.'; + xajax.debug.exceptions[10007] = 'Invalid response command: Command [{data}] is not a known command.'; + xajax.debug.exceptions[10008] = 'Element with ID [{data}] not found in the document.'; + xajax.debug.exceptions[10009] = 'Invalid request: Missing function name parameter.'; + xajax.debug.exceptions[10010] = 'Invalid request: Missing function object parameter.'; + + /* + Function: xajax.debug.getExceptionText + + Parameters: + e - (object): Exception + */ + xajax.debug.getExceptionText = function(e) { + if ('undefined' != typeof e.code) { + if ('undefined' != typeof xajax.debug.exceptions[e.code]) { + var msg = xajax.debug.exceptions[e.code]; + if ('undefined' != typeof e.data) { + msg.replace('{data}', e.data); + } + return msg; + } + } else if ('undefined' != typeof e.name) { + var msg = e.name; + if ('undefined' != typeof e.message) { + msg += ': '; + msg += e.message; + } + return msg; + } + return 'An unknown error has occurred.'; + } + + /* + Function: xajax.debug.writeMessage + + Output a debug message to the debug window if available or send to an + alert box. If the debug window has not been created, attempt to + create it. + + Parameters: + + text - (string): The text to output. + + prefix - (string): The prefix to use; this is prepended onto the + message; it should indicate the type of message (warning, error) + + cls - (stirng): The className that will be applied to the message; + invoking a style from the CSS provided in + . Should be one of the following: + - warningText + - errorText + */ + xajax.debug.writeMessage = function(text, prefix, cls) { + try { + var xd = xajax.debug; + if ('undefined' == typeof xd.window || true == xd.window.closed) { + xd.window = window.open(xd.windowSource, xd.windowID, xd.windowStyle); + if ("about:blank" == xd.windowSource) + xd.window.document.write(xd.windowTemplate); + } + var xdw = xd.window; + var xdwd = xdw.document; + if ('undefined' == typeof prefix) + prefix = ''; + if ('undefined' == typeof cls) + cls = 'debugText'; + + text = xajax.debug.prepareDebugText(text); + + var debugTag = xdwd.getElementById('debugTag'); + var debugEntry = xdwd.createElement('div'); + var debugDate = xdwd.createElement('span'); + var debugText = xdwd.createElement('pre'); + + debugDate.innerHTML = new Date().toString(); + debugText.innerHTML = prefix + text; + + debugEntry.appendChild(debugDate); + debugEntry.appendChild(debugText); + debugTag.insertBefore(debugEntry, debugTag.firstChild); + // don't allow 'style' issues to hinder the debug output + try { + debugEntry.className = 'debugEntry'; + debugDate.className = 'debugDate'; + debugText.className = cls; + } catch (e) { + } + } catch (e) { + if (text.length > 1000) text = text.substr(0,1000) + xajax.debug.text[102]; + alert(xajax.debug.text[102] + text); + } + } + + /* + Function: xajax.debug.prepareDebugText + + Convert special characters to their HTML equivellents so they + will show up in the . + + Parameters: + text - (string): Debug text + */ + xajax.debug.prepareDebugText = function(text) { + try { + text = text.replace(/&/g, '&') + .replace(//g, '>') + .replace(/\n/g, '
'); + return text; + } catch (e) { + xajax.debug.stringReplace = function(haystack, needle, newNeedle) { + var segments = haystack.split(needle); + haystack = ''; + for (var i = 0; i < segments.length; ++i) { + if (0 != i) + haystack += newNeedle; + haystack += segments[i]; + } + return haystack; + } + xajax.debug.prepareDebugText = function(text) { + text = xajax.debug.stringReplace(text, '&', '&'); + text = xajax.debug.stringReplace(text, '<', '<'); + text = xajax.debug.stringReplace(text, '>', '>'); + text = xajax.debug.stringReplace(text, '\n', '
'); + return text; + } + xajax.debug.prepareDebugText(text); + } + } + + /* + Function: xajax.debug.executeCommand + + Catch any exceptions that are thrown by a response command handler + and display a message in the debugger. + + This is a wrapper function which surrounds the standard + function. + */ + xajax.debug.executeCommand = xajax.executeCommand; + xajax.executeCommand = function(args) { + try { + if ('undefined' == typeof args.cmd) + throw { code: 10006 }; + if (false == xajax.command.handler.isRegistered(args)) + throw { code: 10007, data: args.cmd }; + return xajax.debug.executeCommand(args); + } catch(e) { + var msg = 'ExecuteCommand ('; + if ('undefined' != typeof args.sequence) { + msg += '#'; + msg += args.sequence; + msg += ', '; + } + if ('undefined' != typeof args.cmdFullName) { + msg += '"'; + msg += args.cmdFullName; + msg += '"'; + } + msg += '):\n'; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + return true; + } + + /* + Function: xajax.parseAttributes + + Catch any exception thrown during the parsing of response + command attributes and display an appropriate debug message. + + This is a wrapper around the standard + function. + + Parameters: + child - (object): Childnode + obj - (object): Object + + */ + xajax.debug.parseAttributes = xajax.parseAttributes; + xajax.parseAttributes = function(child, obj) { + try { + xajax.debug.parseAttributes(child, obj); + } catch(e) { + var msg = 'ParseAttributes:\n'; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + } + + xajax.debug.commandHandler = xajax.command.handler.unregister('dbg'); + xajax.command.handler.register('dbg', function(args) { + args.cmdFullName = 'debug message'; + xajax.debug.writeMessage(args.data, xajax.debug.text[100], 'warningText'); + return xajax.debug.commandHandler(args); + }); + + + /* + Function: xajax.tools.$ + + Catch any exceptions thrown while attempting to locate an + HTML element by it's unique name. + + This is a wrapper around the standard function. + + Parameters: + sId - (string): Element ID or name + + */ + xajax.debug.$ = xajax.tools.$; + xajax.tools.$ = function(sId) { + try { + var returnValue = xajax.debug.$(sId); + if ('object' != typeof returnValue) + throw { code: 10008 }; + } + catch (e) { + var msg = '$:'; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[100], 'warningText'); + } + return returnValue; + } + + /* + Function: xajax.tools._objectToXML + + Generate a message indicating that a javascript object is + being converted to xml. Indicate the max depth and size. Then + display the size of the object upon completion. Catch any + exceptions thrown during the conversion process. + + This is a wrapper around the standard + function. + + Parameters: + obj - (object): + guard - (object): + + */ + xajax.debug._objectToXML = xajax.tools._objectToXML; + xajax.tools._objectToXML = function(obj, guard) { + try { + if (0 == guard.size) { + var msg = 'OBJECT TO XML: maxDepth = '; + msg += guard.maxDepth; + msg += ', maxSize = '; + msg += guard.maxSize; + xajax.debug.writeMessage(msg); + } + var r = xajax.debug._objectToXML(obj, guard); + if (0 == guard.depth) { + var msg = 'OBJECT TO XML: size = '; + msg += guard.size; + xajax.debug.writeMessage(msg); + } + return r; + } catch(e) { + var msg = 'ObjectToXML: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + return ''; + } + + /* + Function: xajax._internalSend + + Generate a message indicating that the xajax request is + about the be sent to the server. + + This is a wrapper around the standard + function. + */ + xajax.debug._internalSend = xajax._internalSend; + xajax._internalSend = function(oRequest) { + try { + xajax.debug.writeMessage(xajax.debug.text[104]); + xajax.debug.writeMessage( + xajax.debug.text[105] + + oRequest.requestData.length + + xajax.debug.text[106] + ); + oRequest.beginDate = new Date(); + xajax.debug._internalSend(oRequest); + } catch (e) { + var msg = 'InternalSend: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.submitRequest + + Generate a message indicating that a request is ready to be + submitted; providing the URL and the function being invoked. + + Catch any exceptions thrown and display a message. + + This is a wrapper around the standard + function. + */ + xajax.debug.submitRequest = xajax.submitRequest; + xajax.submitRequest = function(oRequest) { + var msg = oRequest.method; + msg += ': '; + text = decodeURIComponent(oRequest.requestData); + text = text.replace(new RegExp('&xjx', 'g'), '\n&xjx'); + text = text.replace(new RegExp('', 'g'), '\n'); + text = text.replace(new RegExp('', 'g'), '\n'); + text = text.replace(new RegExp('', 'g'), '\n\n'); + msg += text; + xajax.debug.writeMessage(msg); + msg = xajax.debug.text[107]; + var separator = '\n'; + for (var mbr in oRequest.functionName) { + msg += separator; + msg += mbr; + msg += ': '; + msg += oRequest.functionName[mbr]; + separator = '\n'; + } + msg += separator; + msg += xajax.debug.text[108]; + msg += separator; + msg += oRequest.URI; + xajax.debug.writeMessage(msg); + + try { + return xajax.debug.submitRequest(oRequest); + } catch (e) { + xajax.debug.writeMessage(e.message); + if (0 < oRequest.retry) + throw e; + } + } + + /* + Function: xajax.initializeRequest + + Generate a message indicating that the request object is + being initialized. + + This is a wrapper around the standard + function. + */ + xajax.debug.initializeRequest = xajax.initializeRequest; + xajax.initializeRequest = function(oRequest) { + try { + var msg = xajax.debug.text[109]; + xajax.debug.writeMessage(msg); + return xajax.debug.initializeRequest(oRequest); + } catch (e) { + var msg = 'InitializeRequest: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.processParameters + + Generate a message indicating that the request object is + being populated with the parameters provided. + + This is a wrapper around the standard + function. + */ + xajax.debug.processParameters = xajax.processParameters; + xajax.processParameters = function(oRequest) { + try { + if ('undefined' != typeof oRequest.parameters) { + var msg = xajax.debug.text[110]; + msg += oRequest.parameters.length; + msg += xajax.debug.text[111]; + xajax.debug.writeMessage(msg); + } else { + var msg = xajax.debug.text[112]; + xajax.debug.writeMessage(msg); + } + return xajax.debug.processParameters(oRequest); + } catch (e) { + var msg = 'ProcessParameters: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.prepareRequest + + Generate a message indicating that the request is being + prepared. This may occur more than once for a request + if it errors and a retry is attempted. + + This is a wrapper around the standard + */ + xajax.debug.prepareRequest = xajax.prepareRequest; + xajax.prepareRequest = function(oRequest) { + try { + var msg = xajax.debug.text[113]; + xajax.debug.writeMessage(msg); + return xajax.debug.prepareRequest(oRequest); + } catch (e) { + var msg = 'PrepareRequest: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.call + + Validates that a function name was provided, generates a message + indicating that a xajax call is starting and sets a flag in the + request object indicating that debugging is enabled for this call. + + This is a wrapper around the standard function. + */ + xajax.debug.call = xajax.call; + xajax.call = function() { + try { + xajax.debug.writeMessage(xajax.debug.text[114]); + + var numArgs = arguments.length; + + if (0 == numArgs) + throw { code: 10009 }; + + var functionName = arguments[0]; + var oOptions = {} + if (1 < numArgs) + oOptions = arguments[1]; + + oOptions.debugging = true; + + return xajax.debug.call(functionName, oOptions); + } catch (e) { + var msg = 'Call: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.request + + Validates that a function name was provided, generates a message + indicating that a xajax request is starting and sets a flag in the + request object indicating that debugging is enabled for this request. + + This is a wrapper around the standard function. + */ + xajax.debug.request = xajax.request; + xajax.request = function() { + try { + xajax.debug.writeMessage(xajax.debug.text[115]); + + var numArgs = arguments.length; + + if (0 == numArgs) + throw { code: 10010 }; + + var oFunction = arguments[0]; + var oOptions = {} + if (1 < numArgs) + oOptions = arguments[1]; + + oOptions.debugging = true; + + return xajax.debug.request(oFunction, oOptions); + } catch (e) { + var msg = 'Request: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.getResponseProcessor + + Generate an error message when no reponse processor is available + to process the type of response returned from the server. + + This is a wrapper around the standard + function. + */ + xajax.debug.getResponseProcessor = xajax.getResponseProcessor; + xajax.getResponseProcessor = function(oRequest) { + try { + var fProc = xajax.debug.getResponseProcessor(oRequest); + + if ('undefined' == typeof fProc) { + var msg = xajax.debug.text[116]; + try { + var contentType = oRequest.request.getResponseHeader('content-type'); + msg += "Content-Type: "; + msg += contentType; + if ('text/html' == contentType) { + msg += xajax.debug.text[117]; + } + } catch (e) { + } + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + + return fProc; + } catch (e) { + var msg = 'GetResponseProcessor: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.responseReceived + + Generate a message indicating that a response has been received + from the server; provide some statistical data regarding the + response and the response time. + + Catch any exceptions that are thrown during the processing of + the response and generate a message. + + This is a wrapper around the standard + function. + */ + xajax.debug.responseReceived = xajax.responseReceived; + xajax.responseReceived = function(oRequest) { + var xx = xajax; + var xt = xx.tools; + var xd = xx.debug; + + var oRet; + + try { + var status = oRequest.request.status; + if (xt.in_array(xx.responseSuccessCodes, status)) { + var packet = oRequest.request.responseText; + packet = packet.replace(new RegExp('', 'g'), '\n'); + packet = packet.replace(new RegExp('', 'g'), '\n'); + packet = packet.replace(new RegExp('', 'g'), '\n'); + packet = packet.replace(new RegExp('', 'g'), '\n\n'); + packet = packet.replace(new RegExp('', 'g'), '\n'); + oRequest.midDate = new Date(); + var msg = xajax.debug.text[118]; + msg += oRequest.request.status; + msg += xajax.debug.text[119]; + msg += packet.length; + msg += xajax.debug.text[120]; + msg += (oRequest.midDate - oRequest.beginDate); + msg += xajax.debug.text[121]; + msg += packet; + xd.writeMessage(msg); + } else if (xt.in_array(xx.responseErrorsForAlert, status)) { + var msg = xajax.debug.text[122]; + msg += status; + msg += xajax.debug.text[123]; + msg += oRequest.request.responseText; + xd.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } else if (xt.in_array(xx.responseRedirectCodes, status)) { + var msg = xajax.debug.text[124]; + msg += oRequest.request.getResponseHeader('location'); + xd.writeMessage(msg); + } + oRet = xd.responseReceived(oRequest); + } catch (e) { + var msg = 'ResponseReceived: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xd.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + + return oRet; + } + + /* + Function: xajax.completeResponse + + Generate a message indicating that the request has completed + and provide some statistics regarding the request and response. + + This is a wrapper around the standard + function. + */ + xajax.debug.completeResponse = xajax.completeResponse; + xajax.completeResponse = function(oRequest) { + try { + var returnValue = xajax.debug.completeResponse(oRequest); + oRequest.endDate = new Date(); + var msg = xajax.debug.text[125]; + msg += (oRequest.endDate - oRequest.beginDate); + msg += xajax.debug.text[126]; + xajax.debug.writeMessage(msg); + return returnValue; + } catch (e) { + var msg = 'CompleteResponse: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.tools.getRequestObject + + Generate a message indicating that the request object is + being initialized. + + Catch any exceptions that are thrown during the process or + initializing a new request object. + + This is a wrapper around the standard + function. + */ + xajax.debug.getRequestObject = xajax.tools.getRequestObject; + xajax.tools.getRequestObject = function() { + try { + xajax.debug.writeMessage(xajax.debug.text[127]); + return xajax.debug.getRequestObject(); + } catch (e) { + var msg = 'GetRequestObject: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + throw e; + } + } + + /* + Function: xajax.dom.assign + + Catch any exceptions thrown during the assignment and + display an error message. + + This is a wrapper around the standard + function. + */ + if (xajax.dom.assign) { + xajax.debug.assign = xajax.dom.assign; + xajax.dom.assign = function(element, property, data) { + try { + return xajax.debug.assign(element, property, data); + } catch (e) { + var msg = 'xajax.dom.assign: '; + msg += xajax.debug.getExceptionText(e); + msg += '\n'; + msg += 'Eval: element.'; + msg += property; + msg += ' = data;\n'; + xajax.debug.writeMessage(msg, xajax.debug.text[101], 'errorText'); + } + return true; + } + } + + /* + Function: xajax.tools.queue.retry + */ + if (xajax.tools) { + if (xajax.tools.queue) { + if (xajax.tools.queue.retry) { + if ('undefined' == typeof xajax.debug.tools) + xajax.debug.tools = {}; + if ('undefined' == typeof xajax.debug.tools.queue) + xajax.debug.tools.queue = {}; + xajax.debug.tools.queue.retry = xajax.tools.queue.retry; + xajax.tools.queue.retry = function(obj, count) { + if (xajax.debug.tools.queue.retry(obj, count)) + return true; + // no 'exceeded' message for sleep command + if (obj.cmd && 's' == obj.cmd) + return false; + xajax.debug.writeMessage('Retry count exceeded.'); + return false; + } + } + } + } + + /* + Boolean: xajax.debug.isLoaded + + true - indicates that the debugging module is loaded + */ + xajax.debug.isLoaded = true; + + /* + Section: Redefine shortcuts. + + Must redefine these shortcuts so they point to the new debug (wrapper) versions: + - + - + - + + Must redefine these shortcuts as well: + - + - + */ + xjx = {} + + xjx.$ = xajax.tools.$; + xjx.getFormValues = xajax.tools.getFormValues; + xjx.call = xajax.call; + xjx.request = xajax.request; + + xajax.$ = xajax.tools.$; + xajax.getFormValues = xajax.tools.getFormValues; +} catch (e) { + alert(e.name + ': ' + e.message); +} diff --git a/www/include/xajax/xajax_js/xajax_lang_bg.js b/www/include/xajax/xajax_js/xajax_lang_bg.js new file mode 100644 index 00000000..abb957c2 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_bg.js @@ -0,0 +1,10 @@ + +if('undefined'!=typeof xajax.debug){xajax.debug.text=[];xajax.debug.text[100]='ПРЕДУПРЕЖДЕÐИЕ: ';xajax.debug.text[101]='ГРЕШКÐ: ';xajax.debug.text[102]='XAJAX ДЕБЪГ СЪОБЩЕÐИЕ:\n';xajax.debug.text[103]='...\n[ДЪЛЪГ ОТГОВОР]\n...';xajax.debug.text[104]='ИЗПРÐЩÐÐЕ ÐРЗÐЯВКИ';xajax.debug.text[105]='ИЗПРÐТЕÐИ [';xajax.debug.text[106]=' байта]';xajax.debug.text[107]='ИЗВИКВÐÐЕ: ';xajax.debug.text[108]='ÐдреÑ: ';xajax.debug.text[109]='ИÐИЦИÐЛИЗИРÐÐЕ ÐРЗÐЯВКÐТÐ';xajax.debug.text[110]='ОБРÐБОТВÐÐЕ ÐРПÐРÐМЕТРИТЕ [';xajax.debug.text[111]=']';xajax.debug.text[112]='ÐЯМРПÐРÐМЕТРИ ЗРОБРÐБОТВÐÐЕ';xajax.debug.text[113]='ПОДГОТВЯВÐÐЕ ÐРЗÐЯВКÐТÐ';xajax.debug.text[114]='СТÐРТИРÐÐЕ ÐÐ XAJAX ПОВИКВÐÐЕТО (оÑтарÑло: вмеÑто това използвай xajax.request)';xajax.debug.text[115]='СТÐРТИРÐÐЕ ÐÐ XAJAX ЗÐЯВКÐТÐ';xajax.debug.text[116]='ÐÑма региÑтрирани функции, които да обработÑÑ‚ заÑвката ви на Ñървъра!\n';xajax.debug.text[117]='.\nПровери за ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð·Ð° грешки на Ñървъра.';xajax.debug.text[118]='ПОЛУЧЕÐИ [ÑтатуÑ: ';xajax.debug.text[119]=', размер: ';xajax.debug.text[120]=' байта, време: ';xajax.debug.text[121]='мÑек]:\n';xajax.debug.text[122]='Сървъра върна ÑÐ»ÐµÐ´Ð½Ð¸Ñ HTTP ÑтатуÑ: ';xajax.debug.text[123]='\nПОЛУЧЕÐИ:\n';xajax.debug.text[124]='Сървъра върна пренаÑочване към:
';xajax.debug.text[125]='ГОТОВО [';xajax.debug.text[126]='мÑек]';xajax.debug.text[127]='ИÐИЦИÐЛИЗИРÐÐЕ ÐРОБЕКТРÐРЗÐЯВКÐТÐ';xajax.debug.exceptions=[];xajax.debug.exceptions[10001]='Ðевалиден XML отговор: Отговора Ñъдържа непознат таг: {data}.';xajax.debug.exceptions[10002]='GetRequestObject: ÐÑма XMLHttpRequest, xajax е изключен.';xajax.debug.exceptions[10003]='Препълване на опашката: Обекта не може да бъде Ñложен на опашката, защото Ñ‚Ñ Ðµ пълна.';xajax.debug.exceptions[10004]='Ðевалиден XML отговор: Отговора Ñъдържа неочакван таг или текÑÑ‚: {data}.';xajax.debug.exceptions[10005]='Ðевалиден адреÑ: Ðевалиден или липÑващ адреÑ; автоматичното откриване неуÑпешнп; please specify a one explicitly.';xajax.debug.exceptions[10006]='Ðевалидна команда в отговора: Получена беше невалидна команда като отговор.';xajax.debug.exceptions[10007]='Ðевалидна команда в отговора: Командата [{data}] е непозната.';xajax.debug.exceptions[10008]='Елемент Ñ ID [{data}] не беше намерен в документа.';xajax.debug.exceptions[10009]='Ðевалидна заÑвка: Параметъра Ñ Ð¸Ð¼ÐµÑ‚Ð¾ на функциÑта липÑва.';xajax.debug.exceptions[10010]='Ðевалидна заÑвка: ЛипÑва обекта на функциÑта.';} +if('undefined'!=typeof xajax.config){if('undefined'!=typeof xajax.config.status){xajax.config.status.update=function(){return{onRequest:function(){window.status='Изпращане на заÑвка...';}, +onWaiting:function(){window.status='Изчакване на отговор...';}, +onProcessing:function(){window.status='Изпълнение...';}, +onComplete:function(){window.status='Готово.';} +} +} +} +} diff --git a/www/include/xajax/xajax_js/xajax_lang_bg_uncompressed.js b/www/include/xajax/xajax_js/xajax_lang_bg_uncompressed.js new file mode 100644 index 00000000..9adefd34 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_bg_uncompressed.js @@ -0,0 +1,81 @@ +/** + * translation for: xajax v.x.x + * @version: 1.0.0 + * @author: mic + * @copyright xajax project + * @license GNU/GPL + * @package xajax x.x.x + * @since v.x.x.x + * save as UTF-8 + */ + +if ('undefined' != typeof xajax.debug) { + /* + Array: text + */ + xajax.debug.text = []; + xajax.debug.text[100] = 'ПРЕДУПРЕЖДЕÐИЕ: '; + xajax.debug.text[101] = 'ГРЕШКÐ: '; + xajax.debug.text[102] = 'XAJAX ДЕБЪГ СЪОБЩЕÐИЕ:\n'; + xajax.debug.text[103] = '...\n[ДЪЛЪГ ОТГОВОР]\n...'; + xajax.debug.text[104] = 'ИЗПРÐЩÐÐЕ ÐРЗÐЯВКИ'; + xajax.debug.text[105] = 'ИЗПРÐТЕÐИ ['; + xajax.debug.text[106] = ' байта]'; + xajax.debug.text[107] = 'ИЗВИКВÐÐЕ: '; + xajax.debug.text[108] = 'ÐдреÑ: '; + xajax.debug.text[109] = 'ИÐИЦИÐЛИЗИРÐÐЕ ÐРЗÐЯВКÐТÐ'; + xajax.debug.text[110] = 'ОБРÐБОТВÐÐЕ ÐРПÐРÐМЕТРИТЕ ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'ÐЯМРПÐРÐМЕТРИ ЗРОБРÐБОТВÐÐЕ'; + xajax.debug.text[113] = 'ПОДГОТВЯВÐÐЕ ÐРЗÐЯВКÐТÐ'; + xajax.debug.text[114] = 'СТÐРТИРÐÐЕ ÐÐ XAJAX ПОВИКВÐÐЕТО (оÑтарÑло: вмеÑто това използвай xajax.request)'; + xajax.debug.text[115] = 'СТÐРТИРÐÐЕ ÐÐ XAJAX ЗÐЯВКÐТÐ'; + xajax.debug.text[116] = 'ÐÑма региÑтрирани функции, които да обработÑÑ‚ заÑвката ви на Ñървъра!\n'; + xajax.debug.text[117] = '.\nПровери за ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð·Ð° грешки на Ñървъра.'; + xajax.debug.text[118] = 'ПОЛУЧЕÐИ [ÑтатуÑ: '; + xajax.debug.text[119] = ', размер: '; + xajax.debug.text[120] = ' байта, време: '; + xajax.debug.text[121] = 'мÑек]:\n'; + xajax.debug.text[122] = 'Сървъра върна ÑÐ»ÐµÐ´Ð½Ð¸Ñ HTTP ÑтатуÑ: '; + xajax.debug.text[123] = '\nПОЛУЧЕÐИ:\n'; + xajax.debug.text[124] = 'Сървъра върна пренаÑочване към:
'; + xajax.debug.text[125] = 'ГОТОВО ['; + xajax.debug.text[126] = 'мÑек]'; + xajax.debug.text[127] = 'ИÐИЦИÐЛИЗИРÐÐЕ ÐРОБЕКТРÐРЗÐЯВКÐТÐ'; + + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Ðевалиден XML отговор: Отговора Ñъдържа непознат таг: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: ÐÑма XMLHttpRequest, xajax е изключен.'; + xajax.debug.exceptions[10003] = 'Препълване на опашката: Обекта не може да бъде Ñложен на опашката, защото Ñ‚Ñ Ðµ пълна.'; + xajax.debug.exceptions[10004] = 'Ðевалиден XML отговор: Отговора Ñъдържа неочакван таг или текÑÑ‚: {data}.'; + xajax.debug.exceptions[10005] = 'Ðевалиден адреÑ: Ðевалиден или липÑващ адреÑ; автоматичното откриване неуÑпешнп; please specify a one explicitly.'; + xajax.debug.exceptions[10006] = 'Ðевалидна команда в отговора: Получена беше невалидна команда като отговор.'; + xajax.debug.exceptions[10007] = 'Ðевалидна команда в отговора: Командата [{data}] е непозната.'; + xajax.debug.exceptions[10008] = 'Елемент Ñ ID [{data}] не беше намерен в документа.'; + xajax.debug.exceptions[10009] = 'Ðевалидна заÑвка: Параметъра Ñ Ð¸Ð¼ÐµÑ‚Ð¾ на функциÑта липÑва.'; + xajax.debug.exceptions[10010] = 'Ðевалидна заÑвка: ЛипÑва обекта на функциÑта.'; +} + +if ('undefined' != typeof xajax.config) { + if ('undefined' != typeof xajax.config.status) { + /* + Object: update + */ + xajax.config.status.update = function() { + return { + onRequest: function() { + window.status = 'Изпращане на заÑвка...'; + }, + onWaiting: function() { + window.status = 'Изчакване на отговор...'; + }, + onProcessing: function() { + window.status = 'Изпълнение...'; + }, + onComplete: function() { + window.status = 'Готово.'; + } + } + } + } +} \ No newline at end of file diff --git a/www/include/xajax/xajax_js/xajax_lang_de.js b/www/include/xajax/xajax_js/xajax_lang_de.js new file mode 100644 index 00000000..c2253269 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_de.js @@ -0,0 +1,9 @@ +if('undefined'!=typeof xajax.debug){xajax.debug.text=[];xajax.debug.text[100]='WARNUNG: ';xajax.debug.text[101]='FEHLER: ';xajax.debug.text[102]='XAJAX FEHLERSUCHE NACHRICHT:\n';xajax.debug.text[103]='...\n[UMGFANGREICHE ANTWORT]\n...';xajax.debug.text[104]='SENDE ANFRAGE';xajax.debug.text[105]='GESENDET [';xajax.debug.text[106]=' bytes]';xajax.debug.text[107]='STARTE AUFRUF: ';xajax.debug.text[108]='URI: ';xajax.debug.text[109]='BEGINNE ANFRAGE';xajax.debug.text[110]='PARAMETER IN BEARBEITUNG [';xajax.debug.text[111]=']';xajax.debug.text[112]='KEINE PARAMETER ZU VERARBEITEN';xajax.debug.text[113]='BEREITE REQUEST VOR';xajax.debug.text[114]='BEGINNE XAJAX CALL (veraltet: verwendet stattdessen xajax.request)';xajax.debug.text[115]='BEGINNE XAJAX ANFRAGE';xajax.debug.text[116]='Die vom Server erhaltenen Daten konnten nicht verarbeitet werden.\n';xajax.debug.text[117]='.\nPrüfe auf Fehlermeldungen des Servers.';xajax.debug.text[118]='ERHALTEN [status: ';xajax.debug.text[119]=', Größe: ';xajax.debug.text[120]=' bytes, Zeit: ';xajax.debug.text[121]='ms]:\n';xajax.debug.text[122]='Der Server hat folgenden HTTP-Status zurück gesendet: ';xajax.debug.text[123]='\nERHALTEN:\n';xajax.debug.text[124]='Der Server lieferte einen Redirect nach:
';xajax.debug.text[125]='ABGESCHLOSSEN [';xajax.debug.text[126]='ms]';xajax.debug.text[127]='INITIALISIERE REQUEST OBJEKT';xajax.debug.exceptions=[];xajax.debug.exceptions[10001]='Ungültige XML-Antwort: die Antwort enthält ein ungültiges Tag: {data}.';xajax.debug.exceptions[10002]='GetRequestObject: XMLHttpRequest ist nicht verfügbar, XajaX ist nicht verfügbar.';xajax.debug.exceptions[10003]='Warteschleife-Überlauf: kann Objekt nicht an Warteschleife übergeben da diese voll ist.';xajax.debug.exceptions[10004]='Ungültige XML-Antwort: die Antwort enthält einen unerwarteten Tag oder Text: {data}.';xajax.debug.exceptions[10005]='Ungültige Request-URI: Ungültige oder Fehlende URI; Autoerkennung fehlgeschlagen; bitte nur eine einzige URI angeben.';xajax.debug.exceptions[10006]='Ungültiges Antwort-Befehl: Unvollständiges Objekt zurück erhalten.';xajax.debug.exceptions[10007]='Ungültiges Antwort-Befehl: Befehl [{data}] ist nicht bekannt.';xajax.debug.exceptions[10008]='Es konnte kein Element mit der ID [{data}] konnte im Dokument gefunden werden.';xajax.debug.exceptions[10009]='Ungültige Anfrage: Fehlender Funktionsparameter - name.';xajax.debug.exceptions[10010]='Ungültige Anfrage: Fehlender Funktionsparameter - object.';} +if('undefined'!=typeof xajax.config){if('undefined'!=typeof xajax.config.status){xajax.config.status.update=function(){return{onRequest:function(){window.status='Sende Anfrage...';}, +onWaiting:function(){window.status='Warten auf Antwort...';}, +onProcessing:function(){window.status='Verarbeitung...';}, +onComplete:function(){window.status='Fertig.';} +} +} +} +} diff --git a/www/include/xajax/xajax_js/xajax_lang_de_uncompressed.js b/www/include/xajax/xajax_js/xajax_lang_de_uncompressed.js new file mode 100644 index 00000000..c396c379 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_de_uncompressed.js @@ -0,0 +1,84 @@ +/** + * translation for: xajax v.x.x + * @version: 1.0.0 + * @author: mic + * @copyright xajax project + * @license GNU/GPL + * @package xajax x.x.x + * @since v.x.x.x + * save as UTF-8 + */ + +if ('undefined' != typeof xajax.debug) { + /* + Array: text + */ + xajax.debug.text = []; + xajax.debug.text[100] = 'WARNUNG: '; + xajax.debug.text[101] = 'FEHLER: '; + xajax.debug.text[102] = 'XAJAX FEHLERSUCHE NACHRICHT:\n'; + xajax.debug.text[103] = '...\n[UMGFANGREICHE ANTWORT]\n...'; + xajax.debug.text[104] = 'SENDE ANFRAGE'; + xajax.debug.text[105] = 'GESENDET ['; + xajax.debug.text[106] = ' bytes]'; + xajax.debug.text[107] = 'STARTE AUFRUF: '; + xajax.debug.text[108] = 'URI: '; + xajax.debug.text[109] = 'BEGINNE ANFRAGE'; + xajax.debug.text[110] = 'PARAMETER IN BEARBEITUNG ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'KEINE PARAMETER ZU VERARBEITEN'; + xajax.debug.text[113] = 'BEREITE REQUEST VOR'; + xajax.debug.text[114] = 'BEGINNE XAJAX CALL (veraltet: verwendet stattdessen xajax.request)'; + xajax.debug.text[115] = 'BEGINNE XAJAX ANFRAGE'; + xajax.debug.text[116] = 'Die vom Server erhaltenen Daten konnten nicht verarbeitet werden.\n'; + xajax.debug.text[117] = '.\nPrüfe auf Fehlermeldungen des Servers.'; + xajax.debug.text[118] = 'ERHALTEN [status: '; + xajax.debug.text[119] = ', Größe: '; + xajax.debug.text[120] = ' bytes, Zeit: '; + xajax.debug.text[121] = 'ms]:\n'; + xajax.debug.text[122] = 'Der Server hat folgenden HTTP-Status zurück gesendet: '; + xajax.debug.text[123] = '\nERHALTEN:\n'; + xajax.debug.text[124] = 'Der Server lieferte einen Redirect nach:
'; + xajax.debug.text[125] = 'ABGESCHLOSSEN ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'INITIALISIERE REQUEST OBJEKT'; + + /* + Array: exceptions + */ + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Ungültige XML-Antwort: die Antwort enthält ein ungültiges Tag: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: XMLHttpRequest ist nicht verfügbar, XajaX ist nicht verfügbar.'; + xajax.debug.exceptions[10003] = 'Warteschleife-Ãœberlauf: kann Objekt nicht an Warteschleife übergeben da diese voll ist.'; + xajax.debug.exceptions[10004] = 'Ungültige XML-Antwort: die Antwort enthält einen unerwarteten Tag oder Text: {data}.'; + xajax.debug.exceptions[10005] = 'Ungültige Request-URI: Ungültige oder Fehlende URI; Autoerkennung fehlgeschlagen; bitte nur eine einzige URI angeben.'; + xajax.debug.exceptions[10006] = 'Ungültiges Antwort-Befehl: Unvollständiges Objekt zurück erhalten.'; + xajax.debug.exceptions[10007] = 'Ungültiges Antwort-Befehl: Befehl [{data}] ist nicht bekannt.'; + xajax.debug.exceptions[10008] = 'Es konnte kein Element mit der ID [{data}] konnte im Dokument gefunden werden.'; + xajax.debug.exceptions[10009] = 'Ungültige Anfrage: Fehlender Funktionsparameter - name.'; + xajax.debug.exceptions[10010] = 'Ungültige Anfrage: Fehlender Funktionsparameter - object.'; +} + +if ('undefined' != typeof xajax.config) { + if ('undefined' != typeof xajax.config.status) { + /* + Object: update + */ + xajax.config.status.update = function() { + return { + onRequest: function() { + window.status = 'Sende Anfrage...'; + }, + onWaiting: function() { + window.status = 'Warten auf Antwort...'; + }, + onProcessing: function() { + window.status = 'Verarbeitung...'; + }, + onComplete: function() { + window.status = 'Fertig.'; + } + } + } + } +} diff --git a/www/include/xajax/xajax_js/xajax_lang_es.js b/www/include/xajax/xajax_js/xajax_lang_es.js new file mode 100644 index 00000000..ed1862a7 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_es.js @@ -0,0 +1,10 @@ + +if('undefined'!=typeof xajax.debug){xajax.debug.text=[];xajax.debug.text[100]='ALERTA: ';xajax.debug.text[101]='ERROR: ';xajax.debug.text[102]='MENSAJE XAJAX DEBUG:\n';xajax.debug.text[103]='...\n[RESPUESTA LARGA]\n...';xajax.debug.text[104]='ENVIANDO PETICION';xajax.debug.text[105]='ENVIADO [';xajax.debug.text[106]=' bytes]';xajax.debug.text[107]='LLAMADA: ';xajax.debug.text[108]='URI: ';xajax.debug.text[109]='INICIALIZANDO PETICION';xajax.debug.text[110]='PROCESANDO PARAMETROS [';xajax.debug.text[111]=']';xajax.debug.text[112]='NO HAY PARAMETROS A PROCESAR';xajax.debug.text[113]='PREPARANDO PETICION';xajax.debug.text[114]='INICIANDO XAJAX CALL (En desuso: use xajax.request)';xajax.debug.text[115]='INICIANDO XAJAX REQUEST';xajax.debug.text[116]='Ningún procesador de respuesta esta disponible para tratar la respuesta del servidor.\n';xajax.debug.text[117]='.\nRevisa mensajes de error del servidor.';xajax.debug.text[118]='RECIBIDO [status: ';xajax.debug.text[119]=', size: ';xajax.debug.text[120]=' bytes, time: ';xajax.debug.text[121]='ms]:\n';xajax.debug.text[122]='El servidor retorno el siguiente estado HTTP: ';xajax.debug.text[123]='\nRECIBIDO:\n';xajax.debug.text[124]='El servidor retorno una redireccion a:
';xajax.debug.text[125]='HECHO [';xajax.debug.text[126]='ms]';xajax.debug.text[127]='INICIALIZANDO PETICION OBJETO';xajax.debug.exceptions=[];xajax.debug.exceptions[10001]='Invalid response XML: La respuesta contiene una etiqueta desconocida: {data}.';xajax.debug.exceptions[10002]='GetRequestObject: XMLHttpRequest no disponible, xajax esta deshabilitado.';xajax.debug.exceptions[10003]='Queue overflow: No se puede colocar objeto en cola porque esta llena.';xajax.debug.exceptions[10004]='Invalid response XML: La respuesta contiene una etiqueta o texto inesperado: {data}.';xajax.debug.exceptions[10005]='Invalid request URI: URI invalida o perdida; autodeteccion fallida; por favor especifica una explicitamente.';xajax.debug.exceptions[10006]='Invalid response command: Orden de respuesta mal formado recibido.';xajax.debug.exceptions[10007]='Invalid response command: Comando [{data}] no es un comando conocido.';xajax.debug.exceptions[10008]='Elemento con ID [{data}] no encontrado en el documento.';xajax.debug.exceptions[10009]='Invalid request: Nombre parametro de funcion perdido.';xajax.debug.exceptions[10010]='Invalid request: Objeto parametro de funcion perdido.';} +if('undefined'!=typeof xajax.config){if('undefined'!=typeof xajax.config.status){xajax.config.status.update=function(){return{onRequest:function(){window.status='Enviando Peticion...';}, +onWaiting:function(){window.status='Esperando Respuesta...';}, +onProcessing:function(){window.status='Procesando...';}, +onComplete:function(){window.status='Hecho.';} +} +} +} +} diff --git a/www/include/xajax/xajax_js/xajax_lang_es_uncompressed.js b/www/include/xajax/xajax_js/xajax_lang_es_uncompressed.js new file mode 100644 index 00000000..96b17a40 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_es_uncompressed.js @@ -0,0 +1,81 @@ +/** + * translation for: xajax v.x.x + * @version: 1.0.0 + * @author: mic + * @copyright xajax project + * @license GNU/GPL + * @package xajax x.x.x + * @since v.x.x.x + * save as UTF-8 + */ + +if ('undefined' != typeof xajax.debug) { + /* + Array: text + */ + xajax.debug.text = []; + xajax.debug.text[100] = 'ALERTA: '; + xajax.debug.text[101] = 'ERROR: '; + xajax.debug.text[102] = 'MENSAJE DE DEPURACION XAJAX:\n'; + xajax.debug.text[103] = '...\n[RESPUESTA LARGA]\n...'; + xajax.debug.text[104] = 'ENVIANDO PETICION'; + xajax.debug.text[105] = 'ENVIADO ['; + xajax.debug.text[106] = ' bytes]'; + xajax.debug.text[107] = 'LLAMADA: '; + xajax.debug.text[108] = 'URI: '; + xajax.debug.text[109] = 'INICIALIZANDO PETICION'; + xajax.debug.text[110] = 'PROCESANDO PARAMETROS ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'NO HAY PARAMETROS QUE PROCESAR'; + xajax.debug.text[113] = 'PREPARANDO PETICION'; + xajax.debug.text[114] = 'INICIANDO LLAMADA XAJAX (En desuso: use xajax.request)'; + xajax.debug.text[115] = 'INICIANDO PETICION XAJAX'; + xajax.debug.text[116] = 'Ningun procesador de respuesta esta disponible para tratar la respuesta del servidor.\n'; + xajax.debug.text[117] = '.\nRevisa mensajes de error del servidor.'; + xajax.debug.text[118] = 'RECIBIDO [status: '; + xajax.debug.text[119] = ', tamaño: '; + xajax.debug.text[120] = ' bytes, tiempo: '; + xajax.debug.text[121] = 'ms]:\n'; + xajax.debug.text[122] = 'El servidor retorno el siguiente estado HTTP: '; + xajax.debug.text[123] = '\nRECIBIDO:\n'; + xajax.debug.text[124] = 'El servidor retorno una redireccion a:
'; + xajax.debug.text[125] = 'HECHO ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'INICIALIZANDO PETICION DEL OBJETO'; + + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Respuesta XML invalida: La respuesta contiene una etiqueta desconocida: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: XMLHttpRequest no disponible, xajax esta deshabilitado.'; + xajax.debug.exceptions[10003] = 'Queue overflow: No se puede colocar objeto en cola porque esta llena.'; + xajax.debug.exceptions[10004] = 'Respuesta XML invalida: La respuesta contiene una etiqueta o texto inesperado: {data}.'; + xajax.debug.exceptions[10005] = 'Solicitud URI invalida: URI invalida o perdida; autodeteccion fallida; por favor especifica una explicitamente.'; + xajax.debug.exceptions[10006] = 'Comando de respuesta invalido: Orden de respuesta mal formado recibido.'; + xajax.debug.exceptions[10007] = 'Comando de respuesta invalido: Comando [{data}] no es un comando conocido.'; + xajax.debug.exceptions[10008] = 'Elemento con ID [{data}] no encontrado en el documento.'; + xajax.debug.exceptions[10009] = 'Respuesta invalida: Nombre parametro de funcion perdido.'; + xajax.debug.exceptions[10010] = 'Respuesta invalida: Objeto parametro de funcion perdido.'; +} + +if ('undefined' != typeof xajax.config) { + if ('undefined' != typeof xajax.config.status) { + /* + Object: update + */ + xajax.config.status.update = function() { + return { + onRequest: function() { + window.status = 'Enviando Peticion...'; + }, + onWaiting: function() { + window.status = 'Esperando Respuesta...'; + }, + onProcessing: function() { + window.status = 'Procesando...'; + }, + onComplete: function() { + window.status = 'Hecho.'; + } + } + } + } +} diff --git a/www/include/xajax/xajax_js/xajax_lang_fr.js b/www/include/xajax/xajax_js/xajax_lang_fr.js new file mode 100644 index 00000000..a246abef --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_fr.js @@ -0,0 +1,8 @@ +xajax.debug.text=[];xajax.debug.text[100]='ATTENTION : ';xajax.debug.text[101]='ERREUR : ';xajax.debug.text[102]='MESSAGE DE DEBUG XAJAX :\n';xajax.debug.text[103]='...\n[RÉPONSE LONGUE]\n...';xajax.debug.text[104]='ENVOI DE LA REQUÊTE';xajax.debug.text[105]='ENVOYÉ [';xajax.debug.text[106]=' octets]';xajax.debug.text[107]='APPEL : ';xajax.debug.text[108]='URI : ';xajax.debug.text[109]='INITIALISATION DE LA REQUÊTE';xajax.debug.text[110]='TRAITEMENT DES PARAMÈTRES [';xajax.debug.text[111]=']';xajax.debug.text[112]='AUCUN PARAMÈTRE À TRAITER';xajax.debug.text[113]='PRÉPARATION DE LA REQUÊTE';xajax.debug.text[114]='DÉBUT DE L\'APPEL XAJAX (déprécié: utilisez plutôt xajax.request)';xajax.debug.text[115]='DÉBUT DE LA REQUÊTE';xajax.debug.text[116]='Aucun traitement disponible pour traiter la réponse du serveur.\n';xajax.debug.text[117]='.\nVérifie s\'il existe des messages d\'erreur du serveur.';xajax.debug.text[118]='REÇUS [statut : ';xajax.debug.text[119]=', taille: ';xajax.debug.text[120]=' octets, temps: ';xajax.debug.text[121]='ms] :\n';xajax.debug.text[122]='Le serveur a retourné la statut HTTP suivant : ';xajax.debug.text[123]='\nREÇUS :\n';xajax.debug.text[124]='Le serveur a indiqué une redirection vers :
';xajax.debug.text[125]='FAIT [';xajax.debug.text[126]='ms]';xajax.debug.text[127]='INITIALISATION DE L\'OBJET REQUÊTE';xajax.debug.exceptions=[];xajax.debug.exceptions[10001]='Réponse XML non valide : La réponse contient une balise inconnue : {data}.';xajax.debug.exceptions[10002]='GetRequestObject : XMLHttpRequest n\'est pas disponible, xajax est désactivé.';xajax.debug.exceptions[10003]='File pleine : Ne peut ajouter un objet à la file car elle est pleine.';xajax.debug.exceptions[10004]='Réponse XML non valide : La réponse contient une balise ou un texte inattendu : {data}.';xajax.debug.exceptions[10005]='URI de la requête non valide : URI non valide ou manquante; auto-détection échouée; veuillez en spécifier une explicitement.';xajax.debug.exceptions[10006]='Réponse de commande invalide : Commande de réponse reçue mal formée.';xajax.debug.exceptions[10007]='Réponse de commande invalide : Commande [{data}] est inconnue.';xajax.debug.exceptions[10008]='L\'élément d\'ID [{data}] est introuvable dans le document.';xajax.debug.exceptions[10009]='Requête invalide : Aucun nom de fonction indiqué en paramètre.';xajax.debug.exceptions[10010]='Requête invalide : Aucun objet indiqué en paramètre pour la fonction.';if('undefined'!=typeof xajax.config){if('undefined'!=typeof xajax.config.status){xajax.config.status.update=function(){return{onRequest:function(){window.status='Envoi de la requête...';}, +onWaiting:function(){window.status='Attente de la réponse...';}, +onProcessing:function(){window.status='En cours de traitement...';}, +onComplete:function(){window.status='Fait.';} +} +} +} +} diff --git a/www/include/xajax/xajax_js/xajax_lang_fr_uncompressed.js b/www/include/xajax/xajax_js/xajax_lang_fr_uncompressed.js new file mode 100644 index 00000000..a9d488bd --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_fr_uncompressed.js @@ -0,0 +1,65 @@ + xajax.debug.text = []; + xajax.debug.text[100] = 'ATTENTION : '; + xajax.debug.text[101] = 'ERREUR : '; + xajax.debug.text[102] = 'MESSAGE DE DEBUG XAJAX :\n'; + xajax.debug.text[103] = '...\n[R�PONSE LONGUE]\n...'; + xajax.debug.text[104] = 'ENVOI DE LA REQU�TE'; + xajax.debug.text[105] = 'ENVOY� ['; + xajax.debug.text[106] = ' octets]'; + xajax.debug.text[107] = 'APPEL : '; + xajax.debug.text[108] = 'URI : '; + xajax.debug.text[109] = 'INITIALISATION DE LA REQU�TE'; + xajax.debug.text[110] = 'TRAITEMENT DES PARAM�TRES ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'AUCUN PARAM�TRE � TRAITER'; + xajax.debug.text[113] = 'PR�PARATION DE LA REQU�TE'; + xajax.debug.text[114] = 'D�BUT DE L\'APPEL XAJAX (d�pr�ci�: utilisez plut�t xajax.request)'; + xajax.debug.text[115] = 'D�BUT DE LA REQU�TE'; + xajax.debug.text[116] = 'Aucun traitement disponible pour traiter la r�ponse du serveur.\n'; + xajax.debug.text[117] = '.\nV�rifie s\'il existe des messages d\'erreur du serveur.'; + xajax.debug.text[118] = 'RE�US [statut : '; + xajax.debug.text[119] = ', taille: '; + xajax.debug.text[120] = ' octets, temps: '; + xajax.debug.text[121] = 'ms] :\n'; + xajax.debug.text[122] = 'Le serveur a retourn� la statut HTTP suivant : '; + xajax.debug.text[123] = '\nRE�US :\n'; + xajax.debug.text[124] = 'Le serveur a indiqu� une redirection vers :
'; + xajax.debug.text[125] = 'FAIT ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'INITIALISATION DE L\'OBJET REQU�TE'; + + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'R�ponse XML non valide : La r�ponse contient une balise inconnue : {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject : XMLHttpRequest n\'est pas disponible, xajax est d�sactiv�.'; + xajax.debug.exceptions[10003] = 'File pleine : Ne peut ajouter un objet � la file car elle est pleine.'; + xajax.debug.exceptions[10004] = 'R�ponse XML non valide : La r�ponse contient une balise ou un texte inattendu : {data}.'; + xajax.debug.exceptions[10005] = 'URI de la requ�te non valide : URI non valide ou manquante; auto-d�tection �chou�e; veuillez en sp�cifier une explicitement.'; + xajax.debug.exceptions[10006] = 'R�ponse de commande invalide : Commande de r�ponse re�ue mal form�e.'; + xajax.debug.exceptions[10007] = 'R�ponse de commande invalide : Commande [{data}] est inconnue.'; + xajax.debug.exceptions[10008] = 'L\'�l�ment d\'ID [{data}] est introuvable dans le document.'; + xajax.debug.exceptions[10009] = 'Requ�te invalide : Aucun nom de fonction indiqu� en param�tre.'; + xajax.debug.exceptions[10010] = 'Requ�te invalide : Aucun objet indiqu� en param�tre pour la fonction.'; + + if ('undefined' != typeof xajax.config) { + if ('undefined' != typeof xajax.config.status) { + /* + Object: mise � jour + */ + xajax.config.status.update = function() { + return { + onRequest: function() { + window.status = 'Envoi de la requ�te...'; + }, + onWaiting: function() { + window.status = 'Attente de la r�ponse...'; + }, + onProcessing: function() { + window.status = 'En cours de traitement...'; + }, + onComplete: function() { + window.status = 'Fait.'; + } + } + } + } + } \ No newline at end of file diff --git a/www/include/xajax/xajax_js/xajax_lang_nl.js b/www/include/xajax/xajax_js/xajax_lang_nl.js new file mode 100644 index 00000000..9b529cf1 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_nl.js @@ -0,0 +1,9 @@ +if('undefined'!=typeof xajax.debug){xajax.debug.text=[];xajax.debug.text[100]='FOUTMELDING: ';xajax.debug.text[101]='FOUT: ';xajax.debug.text[102]='XAJAX FOUTMELDINGS BERICHT:\n';xajax.debug.text[103]='...\n[LANG ANTWOORD]\n...';xajax.debug.text[104]='VERZENDING AANVRAAG';xajax.debug.text[105]='VERZONDEN [';xajax.debug.text[106]=' bytes]';xajax.debug.text[107]='AANROEPING: ';xajax.debug.text[108]='URI: ';xajax.debug.text[109]='INITIALISATIE AANVRAAG';xajax.debug.text[110]='VERWERKING PARAMETERS [';xajax.debug.text[111]=']';xajax.debug.text[112]='GEEN PARAMETERS OM TE VERWERKEN';xajax.debug.text[113]='VOORBEREIDING AANVRAAG';xajax.debug.text[114]='BEGIN XAJAX AANVRAAG (verouderd: gebruik xajax.request)';xajax.debug.text[115]='BEGIN XAJAX AANVRAAG';xajax.debug.text[116]='Er is geen verwerkingsbestand gespecificeerd om de aanvraag te verwerken.\n';xajax.debug.text[117]='.\nBekijk foutmeldingen van de server.';xajax.debug.text[118]='ONTVANGEN [status: ';xajax.debug.text[119]=', omvang: ';xajax.debug.text[120]=' bytes, Zeit: ';xajax.debug.text[121]='ms]:\n';xajax.debug.text[122]='De server retourneert de volgende HTTP-status: ';xajax.debug.text[123]='\nONTVANGEN:\n';xajax.debug.text[124]='De server retourneert een doorverwijzing naar:
';xajax.debug.text[125]='KLAAR [';xajax.debug.text[126]='ms]';xajax.debug.text[127]='INITIALISATIE OBJECT AANVRAAG';xajax.debug.exceptions=[];xajax.debug.exceptions[10001]='Ongeldig XML-antwoord: het antwoord bevat een onbekende tag: {data}.';xajax.debug.exceptions[10002]='GetRequestObject: XMLHttpRequest is niet beschikbaar, XajaX is uitgeschakeld.';xajax.debug.exceptions[10003]='Wachtrij limiet overschreden: kan het object niet in de wachtrij plaatsen, omdat die vol is.';xajax.debug.exceptions[10004]='Ongeldig XML-antwoord: het antwoord bevat een onverwachte tag of tekst: {data}.';xajax.debug.exceptions[10005]='Ongeldige Request-URI: Ongeldige of ontbrekende URI; automatische detectie faalt; specificeer een URI expliciet.';xajax.debug.exceptions[10006]='Ongeldig antwoord bevel: misvormd antwoord bevel ontvangen.';xajax.debug.exceptions[10007]='Ongeldig antwoord bevel: Bevel [{data}] is niet bekend.';xajax.debug.exceptions[10008]='Element met het ID [{data}] kon niet in het document worden gevonden.';xajax.debug.exceptions[10009]='Ongeldige aanvraag: Missende functie parameter - naam.';xajax.debug.exceptions[10010]='Ongeldige aanvraag: Missende functie parameter - object.';} +if('undefined'!=typeof xajax.config){if('undefined'!=typeof xajax.config.status){xajax.config.status.update=function(){return{onRequest:function(){window.status="Verzenden aanvraag...";}, +onWaiting:function(){window.status="Wachten op antwoord...";}, +onProcessing:function(){window.status="Verwerking...";}, +onComplete:function(){window.status="Afgesloten.";} +} +} +} +} diff --git a/www/include/xajax/xajax_js/xajax_lang_nl_uncompressed.js b/www/include/xajax/xajax_js/xajax_lang_nl_uncompressed.js new file mode 100644 index 00000000..22fc154a --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_nl_uncompressed.js @@ -0,0 +1,84 @@ +/** + * translation for: xajax v.x.x + * @version: 1.0.0 + * @author: jeffrey + * @copyright xajax project + * @license GNU/GPL + * @package xajax x.x.x + * @since v.x.x.x + * save as UTF-8 + */ + +if ('undefined' != typeof xajax.debug) { + /* + Array: text + */ + xajax.debug.text = []; + xajax.debug.text[100] = 'FOUTMELDING: '; + xajax.debug.text[101] = 'FOUT: '; + xajax.debug.text[102] = 'XAJAX FOUTMELDINGS BERICHT:\n'; + xajax.debug.text[103] = '...\n[LANG ANTWOORD]\n...'; + xajax.debug.text[104] = 'VERZENDING AANVRAAG'; + xajax.debug.text[105] = 'VERZONDEN ['; + xajax.debug.text[106] = ' bytes]'; + xajax.debug.text[107] = 'AANROEPING: '; + xajax.debug.text[108] = 'URI: '; + xajax.debug.text[109] = 'INITIALISATIE AANVRAAG'; + xajax.debug.text[110] = 'VERWERKING PARAMETERS ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'GEEN PARAMETERS OM TE VERWERKEN'; + xajax.debug.text[113] = 'VOORBEREIDING AANVRAAG'; + xajax.debug.text[114] = 'BEGIN XAJAX AANVRAAG (verouderd: gebruik xajax.request)'; + xajax.debug.text[115] = 'BEGIN XAJAX AANVRAAG'; + xajax.debug.text[116] = 'Er is geen verwerkingsbestand gespecificeerd om de aanvraag te verwerken.\n'; + xajax.debug.text[117] = '.\nBekijk foutmeldingen van de server.'; + xajax.debug.text[118] = 'ONTVANGEN [status: '; + xajax.debug.text[119] = ', omvang: '; + xajax.debug.text[120] = ' bytes, Zeit: '; + xajax.debug.text[121] = 'ms]:\n'; + xajax.debug.text[122] = 'De server retourneert de volgende HTTP-status: '; + xajax.debug.text[123] = '\nONTVANGEN:\n'; + xajax.debug.text[124] = 'De server retourneert een doorverwijzing naar:
'; + xajax.debug.text[125] = 'KLAAR ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'INITIALISATIE OBJECT AANVRAAG'; + + /* + Array: exceptions + */ + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Ongeldig XML-antwoord: het antwoord bevat een onbekende tag: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: XMLHttpRequest is niet beschikbaar, XajaX is uitgeschakeld.'; + xajax.debug.exceptions[10003] = 'Wachtrij limiet overschreden: kan het object niet in de wachtrij plaatsen, omdat die vol is.'; + xajax.debug.exceptions[10004] = 'Ongeldig XML-antwoord: het antwoord bevat een onverwachte tag of tekst: {data}.'; + xajax.debug.exceptions[10005] = 'Ongeldige Request-URI: Ongeldige of ontbrekende URI; automatische detectie faalt; specificeer een URI expliciet.'; + xajax.debug.exceptions[10006] = 'Ongeldig antwoord bevel: misvormd antwoord bevel ontvangen.'; + xajax.debug.exceptions[10007] = 'Ongeldig antwoord bevel: Bevel [{data}] is niet bekend.'; + xajax.debug.exceptions[10008] = 'Element met het ID [{data}] kon niet in het document worden gevonden.'; + xajax.debug.exceptions[10009] = 'Ongeldige aanvraag: Missende functie parameter - naam.'; + xajax.debug.exceptions[10010] = 'Ongeldige aanvraag: Missende functie parameter - object.'; +} + +if ('undefined' != typeof xajax.config) { + if ('undefined' != typeof xajax.config.status) { + /* + Object: update + */ + xajax.config.status.update = function() { + return { + onRequest: function() { + window.status = "Verzenden aanvraag..."; + }, + onWaiting: function() { + window.status = "Wachten op antwoord..."; + }, + onProcessing: function() { + window.status = "Verwerking..."; + }, + onComplete: function() { + window.status = "Afgesloten."; + } + } + } + } +} diff --git a/www/include/xajax/xajax_js/xajax_lang_tr.js b/www/include/xajax/xajax_js/xajax_lang_tr.js new file mode 100644 index 00000000..ed22aa01 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_tr.js @@ -0,0 +1,10 @@ + +if('undefined'!=typeof xajax.debug){xajax.debug.text=[];xajax.debug.text[100]='IKAZ: ';xajax.debug.text[101]='HATA: ';xajax.debug.text[102]='XAJAX DEBUG (HATA AYIKLAMASI) MESAJI:\n';xajax.debug.text[103]='...\n[UZUN YANIT]\n...';xajax.debug.text[104]='ISTEK GÖNDERILIYOR';xajax.debug.text[105]='GÖNDERILDI [';xajax.debug.text[106]=' byte]';xajax.debug.text[107]='ÇAGIRILIYOR: ';xajax.debug.text[108]='URI: ';xajax.debug.text[109]='ISTEK BASLATILIYOR';xajax.debug.text[110]='PARAMETRELER ISLENIYOR [';xajax.debug.text[111]=']';xajax.debug.text[112]='ISLENECEK PARAMETRE YOK';xajax.debug.text[113]='ISTEK HAZIRLANIYOR';xajax.debug.text[114]='XAJAX ÇAGRISI BASLATILIYOR (kullanimi tavsiye edilmiyor: yerine xajax.request kullanin)';xajax.debug.text[115]='XAJAX ISTEGI BASLATILIYOR';xajax.debug.text[116]='Sunucudan gelen cevabi isleyecek cevap islemcisi yok.\n';xajax.debug.text[117]='.\nSunucudan gelen hata mesajlarini kontrol edin.';xajax.debug.text[118]='ALINDI [durum: ';xajax.debug.text[119]=', boyut: ';xajax.debug.text[120]=' byte, süre: ';xajax.debug.text[121]='ms]:\n';xajax.debug.text[122]='Sunucu asagidaki HTTP durumunu gönderdi: ';xajax.debug.text[123]='\nALINDI:\n';xajax.debug.text[124]='Sunucu su adrese yönlendirme istegi gönderdi :
';xajax.debug.text[125]='TAMAMLANDI [';xajax.debug.text[126]='ms]';xajax.debug.text[127]='ISTEK NESNESI BASLATILIYOR';xajax.debug.exceptions=[];xajax.debug.exceptions[10001]='Geçersiz XML cevabi: Cevap bilinmeyen bir etiket tasiyor: {data}.';xajax.debug.exceptions[10002]='GetRequestObject: XMLHttpRequest hazir degil, xajax nesnesi etkisizlestirildi.';xajax.debug.exceptions[10003]='Islem kuyrugu fazla yüklendi: Kuyruk dolu oldugu için nesne kuyruga eklenemiyor.';xajax.debug.exceptions[10004]='Geçersiz XML cevabi: Cevap bilinmeyen bir etiket veya metin tasiyor: {data}.';xajax.debug.exceptions[10005]='Geçersiz istek URI: Geçersiz veya kayip URI; otomatik tespit yapilamadi; lütfen açikça bir tane belirleyiniz.';xajax.debug.exceptions[10006]='Geçersiz cevap komutu: Bozulmus cevap komutu alindi.';xajax.debug.exceptions[10007]='Geçersiz cevap komutu: [{data}] komutu bilinmiyor.';xajax.debug.exceptions[10008]='[{data}] ID li element dosya içinde bulunamadi.';xajax.debug.exceptions[10009]='Geçersiz istek: Fonksiyon isim parametresi eksik.';xajax.debug.exceptions[10010]='Geçersiz istek: Fonksiyon nesne parametresi eksik.';} +if('undefined'!=typeof xajax.config){if('undefined'!=typeof xajax.config.status){xajax.config.status.update=function(){return{onRequest:function(){window.status='İstek Gönderiliyor...';}, +onWaiting:function(){window.status='Cevap Bekleniyor...';}, +onProcessing:function(){window.status='İşlem Devam Ediyor...';}, +onComplete:function(){window.status='Tamamlandı.';} +} +} +} +} diff --git a/www/include/xajax/xajax_js/xajax_lang_tr_uncompressed.js b/www/include/xajax/xajax_js/xajax_lang_tr_uncompressed.js new file mode 100644 index 00000000..1bcc0263 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_lang_tr_uncompressed.js @@ -0,0 +1,82 @@ +/** + * translation for: xajax v.x.x + * @version: 1.0.0 + * @author: mic + * @copyright xajax project + * @license GNU/GPL + * @package xajax x.x.x + * @since v.x.x.x + * save as UTF-8 + */ + +if ('undefined' != typeof xajax.debug) { + + xajax.debug.text = []; + xajax.debug.text[100] = 'IKAZ: '; + xajax.debug.text[101] = 'HATA: '; + xajax.debug.text[102] = 'XAJAX DEBUG (HATA AYIKLAMASI) MESAJI:\n'; + xajax.debug.text[103] = '...\n[UZUN YANIT]\n...'; + xajax.debug.text[104] = 'ISTEK GÖNDERILIYOR'; + xajax.debug.text[105] = 'GÖNDERILDI ['; + xajax.debug.text[106] = ' byte]'; + xajax.debug.text[107] = 'ÇAGIRILIYOR: '; + xajax.debug.text[108] = 'URI: '; + xajax.debug.text[109] = 'ISTEK BASLATILIYOR'; + xajax.debug.text[110] = 'PARAMETRELER ISLENIYOR ['; + xajax.debug.text[111] = ']'; + xajax.debug.text[112] = 'ISLENECEK PARAMETRE YOK'; + xajax.debug.text[113] = 'ISTEK HAZIRLANIYOR'; + xajax.debug.text[114] = 'XAJAX ÇAGRISI BASLATILIYOR (kullanimi tavsiye edilmiyor: yerine xajax.request kullanin)'; + xajax.debug.text[115] = 'XAJAX ISTEGI BASLATILIYOR'; + xajax.debug.text[116] = 'Sunucudan gelen cevabi isleyecek cevap islemcisi yok.\n'; + xajax.debug.text[117] = '.\nSunucudan gelen hata mesajlarini kontrol edin.'; + xajax.debug.text[118] = 'ALINDI [durum: '; + xajax.debug.text[119] = ', boyut: '; + xajax.debug.text[120] = ' byte, süre: '; + xajax.debug.text[121] = 'ms]:\n'; + xajax.debug.text[122] = 'Sunucu asagidaki HTTP durumunu gönderdi: '; + xajax.debug.text[123] = '\nALINDI:\n'; + xajax.debug.text[124] = 'Sunucu su adrese yönlendirme istegi gönderdi :
'; + xajax.debug.text[125] = 'TAMAMLANDI ['; + xajax.debug.text[126] = 'ms]'; + xajax.debug.text[127] = 'ISTEK NESNESI BASLATILIYOR'; + + /* + Array: exceptions + */ + xajax.debug.exceptions = []; + xajax.debug.exceptions[10001] = 'Geçersiz XML cevabi: Cevap bilinmeyen bir etiket tasiyor: {data}.'; + xajax.debug.exceptions[10002] = 'GetRequestObject: XMLHttpRequest hazir degil, xajax nesnesi etkisizlestirildi.'; + xajax.debug.exceptions[10003] = 'Islem kuyrugu fazla yüklendi: Kuyruk dolu oldugu için nesne kuyruga eklenemiyor.'; + xajax.debug.exceptions[10004] = 'Geçersiz XML cevabi: Cevap bilinmeyen bir etiket veya metin tasiyor: {data}.'; + xajax.debug.exceptions[10005] = 'Geçersiz istek URI: Geçersiz veya kayip URI; otomatik tespit yapilamadi; lütfen açikça bir tane belirleyiniz.'; + xajax.debug.exceptions[10006] = 'Geçersiz cevap komutu: Bozulmus cevap komutu alindi.'; + xajax.debug.exceptions[10007] = 'Geçersiz cevap komutu: [{data}] komutu bilinmiyor.'; + xajax.debug.exceptions[10008] = '[{data}] ID li element dosya içinde bulunamadi.'; + xajax.debug.exceptions[10009] = 'Geçersiz istek: Fonksiyon isim parametresi eksik.'; + xajax.debug.exceptions[10010] = 'Geçersiz istek: Fonksiyon nesne parametresi eksik.'; +} + +if ('undefined' != typeof xajax.config) { + if ('undefined' != typeof xajax.config.status) { + /* + Object: update + */ + xajax.config.status.update = function() { + return { + onRequest: function() { + window.status = 'İstek Gönderiliyor...'; + }, + onWaiting: function() { + window.status = 'Cevap Bekleniyor...'; + }, + onProcessing: function() { + window.status = 'İşlem Devam Ediyor...'; + }, + onComplete: function() { + window.status = 'Tamamlandı.'; + } + } + } + } +} diff --git a/www/include/xajax/xajax_js/xajax_verbose.js b/www/include/xajax/xajax_js/xajax_verbose.js new file mode 100644 index 00000000..d3c457a3 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_verbose.js @@ -0,0 +1,18 @@ + +try{if('undefined'==typeof xajax) +throw{name:'SequenceError',message:'Error: xajax core was not detected, verbose module disabled.'} +if('undefined'==typeof xajax.debug) +throw{name:'SequenceError',message:'Error: xajax debugger was not detected, verbose module disabled.'} +xajax.debug.verbose={} +xajax.debug.verbose.expandObject=function(obj){var rec=true;if(1 < arguments.length) +rec=arguments[1];if('function'==typeof(obj)){return '[Function]';}else if('object'==typeof(obj)){if(true==rec){var t=' { ';var separator='';for(var m in obj){t+=separator;t+=m;t+=': ';try{t+=xajax.debug.verbose.expandObject(obj[m],false);}catch(e){t+='[n/a]';} +separator=', ';} +t+=' } ';return t;}else return '[Object]';}else return '"'+obj+'"';} +xajax.debug.verbose.makeFunction=function(obj,name){return function(){var fun=name;fun+='(';var separator='';var pLen=arguments.length;for(var p=0;p < pLen;++p){fun+=separator;fun+=xajax.debug.verbose.expandObject(arguments[p]);separator=',';} +fun+=');';var msg='--> ';msg+=fun;xajax.debug.writeMessage(msg);var returnValue=true;var code='returnValue = obj(';separator='';for(var p=0;p < pLen;++p){code+=separator;code+='arguments['+p+']';separator=',';} +code+=');';eval(code);msg='<-- ';msg+=fun;msg+=' returns ';msg+=xajax.debug.verbose.expandObject(returnValue);xajax.debug.writeMessage(msg);return returnValue;} +} +xajax.debug.verbose.hook=function(x,base){for(var m in x){if('function'==typeof(x[m])){x[m]=xajax.debug.verbose.makeFunction(x[m],base+m);} +} +} +xajax.debug.verbose.hook(xajax,'xajax.');xajax.debug.verbose.hook(xajax.callback,'xajax.callback.');xajax.debug.verbose.hook(xajax.css,'xajax.css.');xajax.debug.verbose.hook(xajax.dom,'xajax.dom.');xajax.debug.verbose.hook(xajax.events,'xajax.events.');xajax.debug.verbose.hook(xajax.forms,'xajax.forms.');xajax.debug.verbose.hook(xajax.js,'xajax.js.');xajax.debug.verbose.hook(xajax.tools,'xajax.tools.');xajax.debug.verbose.hook(xajax.tools.queue,'xajax.tools.queue.');xajax.debug.verbose.hook(xajax.command,'xajax.command.');xajax.debug.verbose.hook(xajax.command.handler,'xajax.command.handler.');xajax.debug.verbose.isLoaded=true;}catch(e){alert(e.name+': '+e.message);} diff --git a/www/include/xajax/xajax_js/xajax_verbose_uncompressed.js b/www/include/xajax/xajax_js/xajax_verbose_uncompressed.js new file mode 100644 index 00000000..a3d82ad9 --- /dev/null +++ b/www/include/xajax/xajax_js/xajax_verbose_uncompressed.js @@ -0,0 +1,176 @@ +/* + File: xajax_verbose.js + + The xajax verbose debugging module. This is an optional module, include in + your project with care. :) + + Title: xajax verbose debugging module + + Please see for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajax_verbose_uncompressed 327 2007-02-28 16:55:26Z calltoconstruct $ + @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson + @copyright Copyright (c) 2008-2009 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +try { + if ('undefined' == typeof xajax) + throw { name: 'SequenceError', message: 'Error: xajax core was not detected, verbose module disabled.' } + if ('undefined' == typeof xajax.debug) + throw { name: 'SequenceError', message: 'Error: xajax debugger was not detected, verbose module disabled.' } + + /* + Class: xajax.debug.verbose + + Provide a high level of detail which can be used to debug hard to find + problems. + */ + xajax.debug.verbose = {} + + /* + Function: xajax.debug.verbose.expandObject + + Generate a debug message expanding all the first level + members found therein. + + + Parameters: + + obj - (object): The object to be enumerated. + + Returns: + + string - The textual representation of all the first + level members. + */ + xajax.debug.verbose.expandObject = function(obj) { + var rec = true; + if (1 < arguments.length) + rec = arguments[1]; + if ('function' == typeof (obj)) { + return '[Function]'; + } else if ('object' == typeof (obj)) { + if (true == rec) { + var t = ' { '; + var separator = ''; + for (var m in obj) { + t += separator; + t += m; + t += ': '; + try { + t += xajax.debug.verbose.expandObject(obj[m], false); + } catch (e) { + t += '[n/a]'; + } + separator = ', '; + } + t += ' } '; + return t; + } else return '[Object]'; + } else return '"' + obj + '"'; + } + + /* + Function: xajax.debug.verbose.makeFunction + + Generate a wrapper function around the specified function. + + Parameters: + + obj - (object): The object that contains the function to be + wrapped. + name - (string): The name of the function to be wrapped. + + Returns: + + function - The wrapper function. + */ + xajax.debug.verbose.makeFunction = function(obj, name) { + return function() { + var fun = name; + fun += '('; + + var separator = ''; + var pLen = arguments.length; + for (var p = 0; p < pLen; ++p) { + fun += separator; + fun += xajax.debug.verbose.expandObject(arguments[p]); + separator = ','; + } + + fun += ');'; + + var msg = '--> '; + msg += fun; + + xajax.debug.writeMessage(msg); + + var returnValue = true; + var code = 'returnValue = obj('; + separator = ''; + for (var p = 0; p < pLen; ++p) { + code += separator; + code += 'arguments[' + p + ']'; + separator = ','; + } + code += ');'; + + eval(code); + + msg = '<-- '; + msg += fun; + msg += ' returns '; + msg += xajax.debug.verbose.expandObject(returnValue); + + xajax.debug.writeMessage(msg); + + return returnValue; + } + } + + /* + Function: xajax.debug.verbose.hook + + Generate a wrapper function around each of the functions + contained within the specified object. + + Parameters: + + x - (object): The object to be scanned. + base - (string): The base reference to be prepended to the + generated wrapper functions. + */ + xajax.debug.verbose.hook = function(x, base) { + for (var m in x) { + if ('function' == typeof (x[m])) { + x[m] = xajax.debug.verbose.makeFunction(x[m], base + m); + } + } + } + + xajax.debug.verbose.hook(xajax, 'xajax.'); + xajax.debug.verbose.hook(xajax.callback, 'xajax.callback.'); + xajax.debug.verbose.hook(xajax.css, 'xajax.css.'); + xajax.debug.verbose.hook(xajax.dom, 'xajax.dom.'); + xajax.debug.verbose.hook(xajax.events, 'xajax.events.'); + xajax.debug.verbose.hook(xajax.forms, 'xajax.forms.'); + xajax.debug.verbose.hook(xajax.js, 'xajax.js.'); + xajax.debug.verbose.hook(xajax.tools, 'xajax.tools.'); + xajax.debug.verbose.hook(xajax.tools.queue, 'xajax.tools.queue.'); + xajax.debug.verbose.hook(xajax.command, 'xajax.command.'); + xajax.debug.verbose.hook(xajax.command.handler, 'xajax.command.handler.'); + + /* + Boolean: isLoaded + + true - indicates that the verbose debugging module is loaded. + */ + xajax.debug.verbose.isLoaded = true; +} catch (e) { + alert(e.name + ': ' + e.message); +} diff --git a/www/include/xajax/xajax_plugins/response/comet/comet.inc.php b/www/include/xajax/xajax_plugins/response/comet/comet.inc.php new file mode 100644 index 00000000..41395427 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/comet/comet.inc.php @@ -0,0 +1,296 @@ +sJavascriptURI>. + */ + var $bInlineScript; + + + var $fTimeOut; + /* + Function: clsTableUpdater + + Constructs and initializes an instance of the table updater class. + */ + function clsCometStreaming() + { + $this->sDefer = ''; + $this->sJavascriptURI = ''; + $this->bInlineScript = false; + } + /* + Function: configure + + Receives configuration settings set by or user script calls to + configure>. + + sName - (string): The name of the configuration option being set. + mValue - (mixed): The value being associated with the configuration option. + */ + function configure($sName, $mValue) + { + if ('scriptDeferral' == $sName) { + if (true === $mValue || false === $mValue) { + if ($mValue) $this->sDefer = 'defer '; + else $this->sDefer = ''; + } + } else if ('javascript URI' == $sName) { + $this->sJavascriptURI = $mValue; + } else if ('inlineScript' == $sName) { + if (true === $mValue || false === $mValue) + $this->bInlineScript = $mValue; + } else if ('cometsleeptimout' == strtolower($sName) ) { + if ( is_numeric($mValue) ) + $this->fTimeOut = $mValue; + } + } + + /* + Function: generateClientScript + + Called by the during the script generation phase. + + */ + function generateClientScript() + { + if ($this->bInlineScript) + { + echo "\n\n"; + } else { + echo "\n\n"; + } + } + + +} + +class xajaxCometResponse extends xajaxResponse +{ + var $bHeaderSent = false; + var $fTimeOut=1; + + + /* + Function: xajaxCometResponse + + calls parent function xajaxResponse(); + */ + + function xajaxCometResponse($fTimeOut=false) + { + + if ( false != $fTimeOut ) $this->fTimeOut=$fTimeOut; + + parent::__construct(); + + + } + + /* + Function: printOutput + + override the original printOutput function. It's no longer needed since the output is already sent. + */ + + function printOutput() + { + $this->flush(); + if ( "HTML5DRAFT" == $_REQUEST['xjxstreaming']) { + + $response = ""; + $response .= "Event: xjxendstream\n"; + $response .= "data: done\n"; + $response .= "\n"; + print $response; + + } + } + + /* + Function: flush_XHR + + Flushes the command queue for comet browsers. + */ + + function flush_XHR() + { + + if (!$this->bHeaderSent) + { + $this->_sendHeaders(); + $this->bHeaderSent=true; + } + + ob_start(); + $this->_printResponse_XML(); + $c = ob_get_contents(); + ob_get_clean(); + $c = str_replace(chr(1)," ",$c); + $c = str_replace(chr(2)," ",$c); + $c = str_replace(chr(31)," ",$c); + $c = str_replace(""," ",$c); + if ($c == "") return false; + print $c; + ob_flush(); + flush(); + $this->sleep( $this->fTimeOut ); + } + + + /* + Function: flush_activeX + + Flushes the command queue for ActiveX browsers. + */ + + function flush_activeX() + { + ob_start(); + $this->_printResponse_XML(); + $c = ob_get_contents(); + ob_end_clean(); + + $c = ''.$c; + $c = str_replace('"','\"',$c); + $c = str_replace("\n",'\n',$c); + $c = str_replace("\r",'\r',$c); + + $response = ""; + $response .= ""; + + + print $response; + ob_flush(); + flush(); + $this->sleep( $this->fTimeOut-0.1 ); + } + + /* + Function: flush_HTML5DRAFT + + Flushes the command queue for HTML5DRAFT browsers. + */ + + function flush_HTML5DRAFT() + { + + + if (!$this->bHeaderSent) + { + header("Content-Type: application/x-dom-event-stream"); + $this->bHeaderSent=1; + } + + ob_start(); + $this->_printResponse_XML(); + $c = ob_get_contents(); + ob_end_clean(); + $c = str_replace("\n",'\n',$c); + $c = str_replace("\r",'\r',$c); + $response = ""; + $response .= "Event: xjxstream\n"; + $response .= "data: $c\n"; + $response .= "\n"; + print $response; + ob_flush(); + flush(); + $this->sleep( $this->fTimeOut ); + + } + + + /* + Function: flush + + Determines which browser is wating for a response and calls the according flush function. + */ + function flush() + { + if (0 == count($this->aCommands)) return false; + if ("xhr" == $_SERVER['HTTP_STREAMING']) + { + $this->flush_XHR(); + } + elseif ( "HTML5DRAFT" == $_REQUEST['xjxstreaming']) + { + $this->flush_HTML5DRAFT(); + } + else + { + $this->flush_activeX(); + } + $this->aCommands=array(); + } + + /* + Function: sleep + + Very accurate sleep function. + */ + function sleep($seconds) + { + usleep(floor($seconds*1000000)); + } + +} + +$objPluginManager =& xajaxPluginManager::getInstance(); +$objPluginManager->registerPlugin(new clsCometStreaming()); diff --git a/www/include/xajax/xajax_plugins/response/comet/comet.js b/www/include/xajax/xajax_plugins/response/comet/comet.js new file mode 100644 index 00000000..616d88d4 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/comet/comet.js @@ -0,0 +1,102 @@ + +try{if(undefined==xajax.ext) +xajax.ext={};} +catch(e){} +try{if(undefined==xajax.ext.comet) +xajax.ext.comet={};} +catch(e){alert("Could not create xajax.ext.comet namespace");} +xjxEc=xajax.ext.comet;xjxEc.detectSupport=function(){var agt=navigator.userAgent.toLowerCase();if(agt.indexOf("opera")!=-1) +return 'Opera';if(agt.indexOf("staroffice")!=-1) +return 'Star Office';if(agt.indexOf("webtv")!=-1) +return 'WebTV';if(agt.indexOf("beonex")!=-1) +return 'Beonex';if(agt.indexOf("chimera")!=-1) +return 'Chimera';if(agt.indexOf("netpositive")!=-1) +return 'NetPositive';if(agt.indexOf("phoenix")!=-1) +return 'Phoenix';if(agt.indexOf("firefox")!=-1) +return 'Firefox';if(agt.indexOf("safari")!=-1) +return 'Safari';if(agt.indexOf("skipstone")!=-1) +return 'SkipStone';if(agt.indexOf("msie")!=-1) +return 'Internet Explorer';if(agt.indexOf("netscape")!=-1) +return 'Netscape';if(agt.indexOf("mozilla/5.0")!=-1) +return 'Mozilla';if(agt.indexOf('\/')!=-1){if(agt.substr(0,agt.indexOf('\/'))!='mozilla'){return navigator.userAgent.substr(0,agt.indexOf('\/'));} +else +return 'Netscape';} +else if(agt.indexOf(' ')!=-1) +return navigator.userAgent.substr(0,agt.indexOf(' '));else +return navigator.userAgent;return false;} +xjxEc.prepareRequestXHR=function(oRequest){if(true==oRequest.comet){var xx=xajax;var xt=xx.tools;oRequest.request=xt.getRequestObject();oRequest.setRequestHeaders=function(headers){if('object'==typeof headers){for(var optionName in headers) +this.request.setRequestHeader(optionName,headers[optionName]);} +} +oRequest.setCommonRequestHeaders=function(){this.setRequestHeaders(this.commonHeaders);} +oRequest.setPostRequestHeaders=function(){this.setRequestHeaders(this.postHeaders);} +oRequest.setGetRequestHeaders=function(){this.setRequestHeaders(this.getHeaders);} +oRequest.applyRequestHeaders=function(){} +oRequest.setCommonRequestHeaders=function(){this.request.setRequestHeader('If-Modified-Since','Sat, 1 Jan 2000 00:00:00 GMT');this.request.setRequestHeader('streaming','xhr');if(typeof(oRequest.header)=="object"){for(a in oRequest.header) +this.request.setRequestHeader(a,oRequest.header[a]);} +} +oRequest.comet={};oRequest.comet.LastPosition=0;oRequest.comet.inProgress=false;var pollLatestResponse=function(){console.log('pollLatestResponse');xjxEc.responseProcessor.XHR(oRequest);} +oRequest.pollTimer=setInterval(pollLatestResponse,300);oRequest.request.onreadystatechange=function(){if(oRequest.request.readyState < 3){console.log('readyState < 3');return;} +if(oRequest.request.readyState==4){console.log('readyState == 4');clearInterval(oRequest.pollTimer);xjxEc.responseProcessor.XHR(oRequest);xajax.completeResponse(oRequest);return;} +} +oRequest.finishRequest=function(){return this.returnValue;} +if('undefined'!=typeof oRequest.userName&&'undefined'!=typeof oRequest.password){oRequest.open=function(){this.request.open(this.method,this.requestURI,true,oRequest.userName,oRequest.password);} +} +else{oRequest.open=function(){this.request.open(this.method,this.requestURI,true);} +} +if('POST'==oRequest.method){oRequest.applyRequestHeaders=function(){this.setCommonRequestHeaders();try{this.setPostRequestHeaders();} +catch(e){this.method='GET';this.requestURI+=this.requestURI.indexOf('?')==-1 ? '?':'&';this.requestURI+=this.requestData;this.requestData='';if(0==this.requestRetry) +this.requestRetry=1;throw e;} +} +} +else{oRequest.applyRequestHeaders=function(){this.setCommonRequestHeaders();this.setGetRequestHeaders();} +} +return;} +return xjxEc.prepareRequest(oRequest);} +xjxEc.connect_htmlfile=function(url,callback,oRequest){try{xjxEc.transferDoc=new ActiveXObject("htmlfile");xjxEc.transferDoc.open();xjxEc.transferDoc.write("");xjxEc.transferDoc.write("");xjxEc.transferDoc.write("");xjxEc.transferDoc.close();xjxEc.ifrDiv=xjxEc.transferDoc.createElement("div");xjxEc.transferDoc.body.appendChild(xjxEc.ifrDiv);xjxEc.ifrDiv.innerHTML="";xjxEc.transferDoc.callback=function(response){callback(response,oRequest);};} +catch(ex){} +} +xjxEc.prepareRequestActiveX=function(oRequest){if(true==oRequest.comet){var xx=xajax;var xt=xx.tools;oRequest.requestURI+=oRequest.requestURI.indexOf('?')==-1 ? '?':'&';oRequest.requestURI+=oRequest.requestData;oRequest.requestData='';try{xjxEc.connect_htmlfile(oRequest.requestURI,xjxEc.responseProcessor.ActiveX,oRequest);if(0 < oRequest.requestRetry) +oRequest.requestRetry=0;} +catch(ex){} +return;} +return xjxEc.prepareRequest(oRequest);} +xjxEc.prepareRequestHTMLDRAFT=function(oRequest){if(true==oRequest.comet){var xx=xajax;var xt=xx.tools;oRequest.requestURI+=oRequest.requestURI.indexOf('?')==-1 ? '?':'&';oRequest.requestURI+=oRequest.requestData;oRequest.requestURI+="&xjxstreaming=HTML5DRAFT";oRequest.inProgress=false;try{var uri=oRequest.requestURI;var es=document.createElement("event-source");es.setAttribute("src",uri);es.setAttribute("width",200);es.setAttribute("height",200);es.style.display="block";callback=function(event){xjxEc.responseProcessor.HTMLDRAFT(event.data,oRequest);};remove=function(){es.removeEventListener("xjxstream",callback,false);es.removeEventListener("xjxendstream",remove,false);} +es.addEventListener("xjxstream",callback,false);es.addEventListener("xjxendstream",remove,false);document.body.appendChild(es);if(0 < oRequest.requestRetry) +oRequest.requestRetry=0;} +catch(ex){} +return;} +return xjxEc.prepareRequest(oRequest);} +xajax.debug={};xajax.debug.prepareDebugText=function(text){try{text=text.replace(/&/g,'&').replace(//g,'>').replace(/\n/g,'
');return text;} +catch(e){xajax.debug.stringReplace=function(haystack,needle,newNeedle){var segments=haystack.split(needle);haystack='';for(var i=0;i < segments.length;++i){if(0!=i) +haystack+=newNeedle;haystack+=segments[i];} +return haystack;} +xajax.debug.prepareDebugText=function(text){text=xajax.debug.stringReplace(text,'&','&');text=xajax.debug.stringReplace(text,'<','<');text=xajax.debug.stringReplace(text,'>','>');text=xajax.debug.stringReplace(text,'\n','
');return text;} +xajax.debug.prepareDebugText(text);} +} +xjxEc.responseProcessor={} +xjxEc.responseProcessor.XHR=function(oRequest){var xx=xajax;var xt=xx.tools;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;var oRet=oRequest.returnValue;if(""==oRequest.request.responseText) +return;var allMessages=oRequest.request.responseText;if(true===oRequest.comet.inProgress)return;oRequest.comet.inProgress=true;do{var unprocessed=allMessages.substring(oRequest.comet.LastPosition);var messageXMLEndIndex=unprocessed.indexOf("");if(messageXMLEndIndex!=-1){var endOfFirstMessageIndex=messageXMLEndIndex+("").length;var anUpdate=unprocessed.substring(0,endOfFirstMessageIndex);var cmd=(new DOMParser()).parseFromString(anUpdate,"text/xml");try{var seq=0;var child=cmd.documentElement.firstChild;xt.xml.processFragment(child,seq,oRet,oRequest);} +catch(ex){} +xt.queue.process(xx.response);oRequest.comet.LastPosition+=endOfFirstMessageIndex;} +}while(messageXMLEndIndex!=-1);oRequest.comet.inProgress=false;return oRet;} +xjxEc.responseProcessor.ActiveX=function(response,oRequest){response.replace('\"','"');var xx=xajax;var xt=xx.tools;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;var oRet=oRequest.returnValue;if(response){var cmd=(new DOMParser()).parseFromString(response,"text/xml");var seq=0;var child=cmd.documentElement.firstChild;xt.xml.processFragment(child,seq,oRequest);if(null==xx.response.timeout) +xt.queue.process(xx.response);} +return oRet;} +xjxEc.responseProcessor.HTMLDRAFT=function(response,oRequest){var xx=xajax;var xt=xx.tools;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;var oRet=oRequest.returnValue;if(oRequest.inProgress)return;if(response&&oRequest.lastResponse!==response){oRequest.inProgress=true;var cmd=(new DOMParser()).parseFromString(response,"text/xml");var seq=0;var child=cmd.documentElement.firstChild;xt.xml.processFragment(child,seq,oRequest);if(null==xx.response.timeout) +xt.queue.process(xx.response);oRequest.inProgress=false;oRequest.lastResponse=response +} +return oRet;} +xjxEc.submitRequestActiveX=function(oRequest){if(true==oRequest.comet) +return;xjxEc.submitRequest(oRequest);} +xjxEc.prepareRequest=xajax.prepareRequest;xjxEc.stream_support=xjxEc.detectSupport();switch(xjxEc.stream_support){case "Internet Explorer": +xajax.prepareRequest=xjxEc.prepareRequestActiveX;xjxEc.submitRequest=xajax.submitRequest;xajax.submitRequest=xjxEc.submitRequestActiveX;break;case "Firefox": +case "Safari": +xajax.prepareRequest=xjxEc.prepareRequestXHR;break;case "Opera": +xajax.prepareRequest=xjxEc.prepareRequestHTMLDRAFT;xjxEc.submitRequest=xajax.submitRequest;xajax.submitRequest=xjxEc.submitRequestActiveX;break;default: +alert("Xajax.Ext.Comet: Your browser does not support comet streaming or is not yet supported by this plugin!");} +if(typeof DOMParser=="undefined"){DOMParser=function(){} +DOMParser.prototype.parseFromString=function(str,contentType){if(typeof ActiveXObject!="undefined"){var d=new ActiveXObject("Microsoft.XMLDOM");d.loadXML(str);return d;} +else if(typeof XMLHttpRequest!="undefined"){var req=new XMLHttpRequest;req.open("GET","data:"+(contentType||"application/xml")+";charset=utf-8,"+encodeURIComponent(str),false);if(req.overrideMimeType){req.overrideMimeType(contentType);} +req.send(null);return req.responseXML;} +} +} diff --git a/www/include/xajax/xajax_plugins/response/comet/comet_uncompressed.js b/www/include/xajax/xajax_plugins/response/comet/comet_uncompressed.js new file mode 100644 index 00000000..4738e29f --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/comet/comet_uncompressed.js @@ -0,0 +1,624 @@ +/* + File: comet.js + + Title: Comet plugin for xajax + +*/ + +/* + @package comet plugin + @version $Id: + @copyright Copyright (c) 2007 by Steffen Konerow (IE) + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajax.ext.comet + + This class contains all functions for using comet streaming with xajax. + +*/ + +try +{ + if (undefined == xajax.ext) + xajax.ext = { + }; +} +catch (e) +{ +} + +try +{ + if (undefined == xajax.ext.comet) + xajax.ext.comet = { + }; +} +catch (e) +{ + alert("Could not create xajax.ext.comet namespace"); +} + +// create Shorthand for xajax.ext.comet +xjxEc = xajax.ext.comet; + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: detectSupport + + Detects browser for using fallback methods instead of multipart XHR responses. +*/ +xjxEc.detectSupport = function() +{ + var agt = navigator.userAgent.toLowerCase(); + + if (agt.indexOf("opera") != -1) + return 'Opera'; + + if (agt.indexOf("staroffice") != -1) + return 'Star Office'; + + if (agt.indexOf("webtv") != -1) + return 'WebTV'; + + if (agt.indexOf("beonex") != -1) + return 'Beonex'; + + if (agt.indexOf("chimera") != -1) + return 'Chimera'; + + if (agt.indexOf("netpositive") != -1) + return 'NetPositive'; + + if (agt.indexOf("phoenix") != -1) + return 'Phoenix'; + + if (agt.indexOf("firefox") != -1) + return 'Firefox'; + + if (agt.indexOf("safari") != -1) + return 'Safari'; + + if (agt.indexOf("skipstone") != -1) + return 'SkipStone'; + + if (agt.indexOf("msie") != -1) + return 'Internet Explorer'; + + if (agt.indexOf("netscape") != -1) + return 'Netscape'; + + if (agt.indexOf("mozilla/5.0") != -1) + return 'Mozilla'; + + if (agt.indexOf('\/') != -1) + { + if (agt.substr(0, agt.indexOf('\/')) != 'mozilla') + { + return navigator.userAgent.substr(0, agt.indexOf('\/')); + } + else + return 'Netscape'; + } + else if (agt.indexOf(' ') != -1) + return navigator.userAgent.substr(0, agt.indexOf(' ')); + else + return navigator.userAgent; + + // if (navigator.appVersion.indexOf("MSIE")!=-1) + // { + // var version,temp; + // temp=navigator.appVersion.split("MSIE") + // version=parseFloat(temp[1]) + // if (version>=5.5) return "MSIE"; + // } + // if ( "undefined" != typeof window.opera ) + // { + // return "OPERA"; + // } + // if ( "undefined" != typeof window.Iterator ) + // { + // return "FF2"; + // } + + return false; +} + + +// ------------------------------------------------------------------------------------------------------------------------------------- + +/* + Function: prepareRequestXHR + + Prepares the XMLHttpRequest object for this xajax request in FF/Safari browsers. + +*/ + +xjxEc.prepareRequestXHR = function (oRequest) +{ + if (true == oRequest.comet) + { + var xx = xajax; + var xt = xx.tools; + oRequest.request = xt.getRequestObject(); + + oRequest.setRequestHeaders = function(headers) + { + if ('object' == typeof headers) + { + for (var optionName in headers) + this.request.setRequestHeader(optionName, headers[optionName]); + } + } + oRequest.setCommonRequestHeaders = function() + { + this.setRequestHeaders(this.commonHeaders); + } + oRequest.setPostRequestHeaders = function() + { + this.setRequestHeaders(this.postHeaders); + } + oRequest.setGetRequestHeaders = function() + { + this.setRequestHeaders(this.getHeaders); + } + + oRequest.applyRequestHeaders = function() + { + } + + oRequest.setCommonRequestHeaders = function() + { + this.request.setRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'); + this.request.setRequestHeader('streaming', 'xhr'); + + if (typeof (oRequest.header) == "object") + { + for (a in oRequest.header) + this.request.setRequestHeader(a, oRequest.header[a]); + } + } + oRequest.comet = { + }; + + oRequest.comet.LastPosition = 0; + oRequest.comet.inProgress = false; + var pollLatestResponse = function() + { + + console.log('pollLatestResponse'); + xjxEc.responseProcessor.XHR(oRequest); + } + oRequest.pollTimer = setInterval(pollLatestResponse, 300); + oRequest.request.onreadystatechange = function() + { + if (oRequest.request.readyState < 3) + { + console.log('readyState < 3'); + return; + } + if (oRequest.request.readyState == 4) + { + console.log('readyState == 4'); + clearInterval(oRequest.pollTimer); + xjxEc.responseProcessor.XHR(oRequest); + //xajax.responseReceived(oRequest); + xajax.completeResponse(oRequest); + return; + } + } + oRequest.finishRequest = function() + { + return this.returnValue; + } + + if ('undefined' != typeof oRequest.userName && 'undefined' != typeof oRequest.password) + { + oRequest.open = function() + { + this.request.open(this.method, this.requestURI, true, oRequest.userName, oRequest.password); + } + } + else + { + oRequest.open = function() + { + this.request.open(this.method, this.requestURI, true); + } + } + + if ('POST' == oRequest.method) + { // W3C: Method is case sensitive + oRequest.applyRequestHeaders = function() + { + this.setCommonRequestHeaders(); + + try + { + this.setPostRequestHeaders(); + } + catch (e) + { + this.method = 'GET'; + this.requestURI += this.requestURI.indexOf('?') == -1 ? '?' : '&'; + this.requestURI += this.requestData; + this.requestData = ''; + + if (0 == this.requestRetry) + this.requestRetry = 1; + throw e; + } + } + } + else + { + oRequest.applyRequestHeaders = function() + { + this.setCommonRequestHeaders(); + this.setGetRequestHeaders(); + } + } + return; + } + return xjxEc.prepareRequest(oRequest); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: connect_htmlfile + + Create a hidden iframe for IE + +*/ +xjxEc.connect_htmlfile = function (url, callback, oRequest) +{ + try + { + xjxEc.transferDoc = new ActiveXObject("htmlfile"); + xjxEc.transferDoc.open(); + xjxEc.transferDoc.write(""); + xjxEc.transferDoc.write(""); + xjxEc.transferDoc.write(""); + xjxEc.transferDoc.close(); + xjxEc.ifrDiv = xjxEc.transferDoc.createElement("div"); + xjxEc.transferDoc.body.appendChild(xjxEc.ifrDiv); + xjxEc.ifrDiv.innerHTML = ""; + xjxEc.transferDoc.callback = function (response) + { + callback(response, oRequest); + }; + } + catch (ex) + { + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------- + +/* + Function: prepareRequestActiveX + + Prepares the Iframe for streaming with active X + +*/ + +xjxEc.prepareRequestActiveX = function(oRequest) +{ + if (true == oRequest.comet) + { + var xx = xajax; + var xt = xx.tools; + oRequest.requestURI += oRequest.requestURI.indexOf('?') == -1 ? '?' : '&'; + oRequest.requestURI += oRequest.requestData; + oRequest.requestData = ''; + + try + { + xjxEc.connect_htmlfile(oRequest.requestURI, xjxEc.responseProcessor.ActiveX, oRequest); + + if (0 < oRequest.requestRetry) + oRequest.requestRetry = 0; + } + catch (ex) + { + } + return; + } + return xjxEc.prepareRequest(oRequest); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- + +/* + Function: prepareRequestHTMLDRAFT + + Prepares streaming with HTML 5 Draft + +*/ + +xjxEc.prepareRequestHTMLDRAFT = function(oRequest) +{ + if (true == oRequest.comet) + { + var xx = xajax; + var xt = xx.tools; + oRequest.requestURI += oRequest.requestURI.indexOf('?') == -1 ? '?' : '&'; + oRequest.requestURI += oRequest.requestData; + oRequest.requestURI += "&xjxstreaming=HTML5DRAFT"; + oRequest.inProgress = false; + + try + { + var uri = oRequest.requestURI; + var es = document.createElement("event-source"); + es.setAttribute("src", uri); + es.setAttribute("width", 200); + es.setAttribute("height", 200); + es.style.display = "block"; + callback = function(event) + { + xjxEc.responseProcessor.HTMLDRAFT(event.data, oRequest); + }; + remove = function() + { + es.removeEventListener("xjxstream", callback, false); + es.removeEventListener("xjxendstream", remove, false); + //document.body.removeChild(es); + } + + es.addEventListener("xjxstream", callback, false); + es.addEventListener("xjxendstream", remove, false); + document.body.appendChild(es); + + if (0 < oRequest.requestRetry) + oRequest.requestRetry = 0; + } + catch (ex) + { + } + return; + } + return xjxEc.prepareRequest(oRequest); +} +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: responseProcessor.XHR + + Processes the streaming response for FF/Safari + +*/ +xajax.debug = { +}; + +xajax.debug.prepareDebugText = function(text) +{ + try + { + text = text.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '
'); + return text; + } + catch (e) + { + xajax.debug.stringReplace = function(haystack, needle, newNeedle) + { + var segments = haystack.split(needle); + haystack = ''; + + for (var i = 0; i < segments.length; ++i) + { + if (0 != i) + haystack += newNeedle; + haystack += segments[i]; + } + return haystack; + } + xajax.debug.prepareDebugText = function(text) + { + text = xajax.debug.stringReplace(text, '&', '&'); + text = xajax.debug.stringReplace(text, '<', '<'); + text = xajax.debug.stringReplace(text, '>', '>'); + text = xajax.debug.stringReplace(text, '\n', '
'); + return text; + } + xajax.debug.prepareDebugText(text); + } +} +xjxEc.responseProcessor = { +} + +xjxEc.responseProcessor.XHR = function(oRequest) +{ + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + var oRet = oRequest.returnValue; + + if ("" == oRequest.request.responseText) + return; + var allMessages = oRequest.request.responseText; + if (true === oRequest.comet.inProgress) return; + oRequest.comet.inProgress = true; + do + { + var unprocessed = allMessages.substring(oRequest.comet.LastPosition); + var messageXMLEndIndex = unprocessed.indexOf(""); + + if (messageXMLEndIndex != -1) + { + var endOfFirstMessageIndex = messageXMLEndIndex + ("").length; + var anUpdate = unprocessed.substring(0, endOfFirstMessageIndex); + + var cmd = (new DOMParser()).parseFromString(anUpdate, "text/xml"); + + try + { + var seq = 0; + var child = cmd.documentElement.firstChild; + xt.xml.processFragment(child, seq, oRet, oRequest); + } + catch (ex) + { + } + xt.queue.process(xx.response); + oRequest.comet.LastPosition += endOfFirstMessageIndex; + } + } while (messageXMLEndIndex != -1); + + oRequest.comet.inProgress = false; + return oRet; +} +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: responseProcessor.ActiveX + + Processes the streaming response for IE + +*/ + +xjxEc.responseProcessor.ActiveX = function(response, oRequest) +{ + response.replace('\"', '"'); + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + var oRet = oRequest.returnValue; + + if (response) + { + var cmd = (new DOMParser()).parseFromString(response, "text/xml"); + var seq = 0; + var child = cmd.documentElement.firstChild; + xt.xml.processFragment(child, seq, oRequest); + + if (null == xx.response.timeout) + xt.queue.process(xx.response); + } + return oRet; +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: responseProcessor.HTMLDRAFT + + Processes the streaming response for HTML 5 Draft Browsers (Opera 9+) + +*/ + +xjxEc.responseProcessor.HTMLDRAFT = function(response, oRequest) +{ + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + var oRet = oRequest.returnValue; + if (oRequest.inProgress) return; + if (response && oRequest.lastResponse !== response) + { + oRequest.inProgress = true; + var cmd = (new DOMParser()).parseFromString(response, "text/xml"); + var seq = 0; + var child = cmd.documentElement.firstChild; + xt.xml.processFragment(child, seq, oRequest); + + if (null == xx.response.timeout) + xt.queue.process(xx.response); + oRequest.inProgress=false; + oRequest.lastResponse = response + } + return oRet; +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + Function: submitRequestActiveX + + Supresses the xajax.submitRequest() function call for IE in streaming calls. + +*/ + +xjxEc.submitRequestActiveX = function(oRequest) +{ + if (true == oRequest.comet) + return; + + xjxEc.submitRequest(oRequest); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + variable setup. Detects IE and replaces the according functions + +*/ + +xjxEc.prepareRequest = xajax.prepareRequest; + +xjxEc.stream_support = xjxEc.detectSupport(); + +switch (xjxEc.stream_support) +{ + case "Internet Explorer": + xajax.prepareRequest = xjxEc.prepareRequestActiveX; + xjxEc.submitRequest = xajax.submitRequest; + xajax.submitRequest = xjxEc.submitRequestActiveX; + break; + + case "Firefox": + case "Safari": + xajax.prepareRequest = xjxEc.prepareRequestXHR; + break; + + case "Opera": + xajax.prepareRequest = xjxEc.prepareRequestHTMLDRAFT; + xjxEc.submitRequest = xajax.submitRequest; + xajax.submitRequest = xjxEc.submitRequestActiveX; + break; + + default: + alert("Xajax.Ext.Comet: Your browser does not support comet streaming or is not yet supported by this plugin!"); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + Function: DOMParser + + Prototype DomParser for IE/Opera + +*/ +if (typeof DOMParser == "undefined") +{ + DOMParser = function () + { + } + + DOMParser.prototype.parseFromString = function (str, contentType) + { + if (typeof ActiveXObject != "undefined") + { + var d = new ActiveXObject("Microsoft.XMLDOM"); + d.loadXML(str); + return d; + } + else if (typeof XMLHttpRequest != "undefined") + { + var req = new XMLHttpRequest; + req.open("GET", "data:" + (contentType || "application/xml") + ";charset=utf-8," + encodeURIComponent(str), false); + + if (req.overrideMimeType) + { + req.overrideMimeType(contentType); + } + req.send(null); + return req.responseXML; + } + } +} +// ------------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/www/include/xajax/xajax_plugins/response/comet/comet_uncompressed.js.bak b/www/include/xajax/xajax_plugins/response/comet/comet_uncompressed.js.bak new file mode 100644 index 00000000..ad261065 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/comet/comet_uncompressed.js.bak @@ -0,0 +1,622 @@ +/* + File: comet.js + + Title: Comet plugin for xajax + +*/ + +/* + @package comet plugin + @version $Id: + @copyright Copyright (c) 2007 by Steffen Konerow (IE) + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajax.ext.comet + + This class contains all functions for using comet streaming with xajax. + +*/ + +try +{ + if (undefined == xajax.ext) + xajax.ext = { + }; +} +catch (e) +{ +} + +try +{ + if (undefined == xajax.ext.comet) + xajax.ext.comet = { + }; +} +catch (e) +{ + alert("Could not create xajax.ext.comet namespace"); +} + +// create Shorthand for xajax.ext.comet +xjxEc = xajax.ext.comet; + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: detectSupport + + Detects browser for using fallback methods instead of multipart XHR responses. +*/ +xjxEc.detectSupport = function() +{ + var agt = navigator.userAgent.toLowerCase(); + + if (agt.indexOf("opera") != -1) + return 'Opera'; + + if (agt.indexOf("staroffice") != -1) + return 'Star Office'; + + if (agt.indexOf("webtv") != -1) + return 'WebTV'; + + if (agt.indexOf("beonex") != -1) + return 'Beonex'; + + if (agt.indexOf("chimera") != -1) + return 'Chimera'; + + if (agt.indexOf("netpositive") != -1) + return 'NetPositive'; + + if (agt.indexOf("phoenix") != -1) + return 'Phoenix'; + + if (agt.indexOf("firefox") != -1) + return 'Firefox'; + + if (agt.indexOf("safari") != -1) + return 'Safari'; + + if (agt.indexOf("skipstone") != -1) + return 'SkipStone'; + + if (agt.indexOf("msie") != -1) + return 'Internet Explorer'; + + if (agt.indexOf("netscape") != -1) + return 'Netscape'; + + if (agt.indexOf("mozilla/5.0") != -1) + return 'Mozilla'; + + if (agt.indexOf('\/') != -1) + { + if (agt.substr(0, agt.indexOf('\/')) != 'mozilla') + { + return navigator.userAgent.substr(0, agt.indexOf('\/')); + } + else + return 'Netscape'; + } + else if (agt.indexOf(' ') != -1) + return navigator.userAgent.substr(0, agt.indexOf(' ')); + else + return navigator.userAgent; + + // if (navigator.appVersion.indexOf("MSIE")!=-1) + // { + // var version,temp; + // temp=navigator.appVersion.split("MSIE") + // version=parseFloat(temp[1]) + // if (version>=5.5) return "MSIE"; + // } + // if ( "undefined" != typeof window.opera ) + // { + // return "OPERA"; + // } + // if ( "undefined" != typeof window.Iterator ) + // { + // return "FF2"; + // } + + return false; +} + + +// ------------------------------------------------------------------------------------------------------------------------------------- + +/* + Function: prepareRequestXHR + + Prepares the XMLHttpRequest object for this xajax request in FF/Safari browsers. + +*/ + +xjxEc.prepareRequestXHR = function (oRequest) +{ + if (true == oRequest.comet) + { + var xx = xajax; + var xt = xx.tools; + oRequest.request = xt.getRequestObject(); + + oRequest.setRequestHeaders = function(headers) + { + if ('object' == typeof headers) + { + for (var optionName in headers) + this.request.setRequestHeader(optionName, headers[optionName]); + } + } + oRequest.setCommonRequestHeaders = function() + { + this.setRequestHeaders(this.commonHeaders); + } + oRequest.setPostRequestHeaders = function() + { + this.setRequestHeaders(this.postHeaders); + } + oRequest.setGetRequestHeaders = function() + { + this.setRequestHeaders(this.getHeaders); + } + + oRequest.applyRequestHeaders = function() + { + } + + oRequest.setCommonRequestHeaders = function() + { + this.request.setRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'); + this.request.setRequestHeader('streaming', 'xhr'); + + if (typeof (oRequest.header) == "object") + { + for (a in oRequest.header) + this.request.setRequestHeader(a, oRequest.header[a]); + } + } + oRequest.comet = { + }; + + oRequest.comet.LastPosition = 0; + oRequest.comet.inProgress = false; + var pollLatestResponse = function() + { + xjxEc.responseProcessor.XHR(oRequest); + } + oRequest.pollTimer = setInterval(pollLatestResponse, 300); + oRequest.request.onreadystatechange = function() + { + if (oRequest.request.readyState < 3) + { + console.log('readyState < 3'); + return; + } + if (oRequest.request.readyState == 4) + { + console.log('readyState == 4'); + clearInterval(oRequest.pollTimer); + xjxEc.responseProcessor.XHR(oRequest); + //xajax.responseReceived(oRequest); + xajax.completeResponse(oRequest); + return; + } + } + oRequest.finishRequest = function() + { + return this.returnValue; + } + + if ('undefined' != typeof oRequest.userName && 'undefined' != typeof oRequest.password) + { + oRequest.open = function() + { + this.request.open(this.method, this.requestURI, true, oRequest.userName, oRequest.password); + } + } + else + { + oRequest.open = function() + { + this.request.open(this.method, this.requestURI, true); + } + } + + if ('POST' == oRequest.method) + { // W3C: Method is case sensitive + oRequest.applyRequestHeaders = function() + { + this.setCommonRequestHeaders(); + + try + { + this.setPostRequestHeaders(); + } + catch (e) + { + this.method = 'GET'; + this.requestURI += this.requestURI.indexOf('?') == -1 ? '?' : '&'; + this.requestURI += this.requestData; + this.requestData = ''; + + if (0 == this.requestRetry) + this.requestRetry = 1; + throw e; + } + } + } + else + { + oRequest.applyRequestHeaders = function() + { + this.setCommonRequestHeaders(); + this.setGetRequestHeaders(); + } + } + return; + } + return xjxEc.prepareRequest(oRequest); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: connect_htmlfile + + Create a hidden iframe for IE + +*/ +xjxEc.connect_htmlfile = function (url, callback, oRequest) +{ + try + { + xjxEc.transferDoc = new ActiveXObject("htmlfile"); + xjxEc.transferDoc.open(); + xjxEc.transferDoc.write(""); + xjxEc.transferDoc.write(""); + xjxEc.transferDoc.write(""); + xjxEc.transferDoc.close(); + xjxEc.ifrDiv = xjxEc.transferDoc.createElement("div"); + xjxEc.transferDoc.body.appendChild(xjxEc.ifrDiv); + xjxEc.ifrDiv.innerHTML = ""; + xjxEc.transferDoc.callback = function (response) + { + callback(response, oRequest); + }; + } + catch (ex) + { + } +} + +// ------------------------------------------------------------------------------------------------------------------------------------- + +/* + Function: prepareRequestActiveX + + Prepares the Iframe for streaming with active X + +*/ + +xjxEc.prepareRequestActiveX = function(oRequest) +{ + if (true == oRequest.comet) + { + var xx = xajax; + var xt = xx.tools; + oRequest.requestURI += oRequest.requestURI.indexOf('?') == -1 ? '?' : '&'; + oRequest.requestURI += oRequest.requestData; + oRequest.requestData = ''; + + try + { + xjxEc.connect_htmlfile(oRequest.requestURI, xjxEc.responseProcessor.ActiveX, oRequest); + + if (0 < oRequest.requestRetry) + oRequest.requestRetry = 0; + } + catch (ex) + { + } + return; + } + return xjxEc.prepareRequest(oRequest); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- + +/* + Function: prepareRequestHTMLDRAFT + + Prepares streaming with HTML 5 Draft + +*/ + +xjxEc.prepareRequestHTMLDRAFT = function(oRequest) +{ + if (true == oRequest.comet) + { + var xx = xajax; + var xt = xx.tools; + oRequest.requestURI += oRequest.requestURI.indexOf('?') == -1 ? '?' : '&'; + oRequest.requestURI += oRequest.requestData; + oRequest.requestURI += "&xjxstreaming=HTML5DRAFT"; + oRequest.inProgress = false; + + try + { + var uri = oRequest.requestURI; + var es = document.createElement("event-source"); + es.setAttribute("src", uri); + es.setAttribute("width", 200); + es.setAttribute("height", 200); + es.style.display = "block"; + callback = function(event) + { + xjxEc.responseProcessor.HTMLDRAFT(event.data, oRequest); + }; + remove = function() + { + es.removeEventListener("xjxstream", callback, false); + es.removeEventListener("xjxendstream", remove, false); + //document.body.removeChild(es); + } + + es.addEventListener("xjxstream", callback, false); + es.addEventListener("xjxendstream", remove, false); + document.body.appendChild(es); + + if (0 < oRequest.requestRetry) + oRequest.requestRetry = 0; + } + catch (ex) + { + } + return; + } + return xjxEc.prepareRequest(oRequest); +} +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: responseProcessor.XHR + + Processes the streaming response for FF/Safari + +*/ +xajax.debug = { +}; + +xajax.debug.prepareDebugText = function(text) +{ + try + { + text = text.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '
'); + return text; + } + catch (e) + { + xajax.debug.stringReplace = function(haystack, needle, newNeedle) + { + var segments = haystack.split(needle); + haystack = ''; + + for (var i = 0; i < segments.length; ++i) + { + if (0 != i) + haystack += newNeedle; + haystack += segments[i]; + } + return haystack; + } + xajax.debug.prepareDebugText = function(text) + { + text = xajax.debug.stringReplace(text, '&', '&'); + text = xajax.debug.stringReplace(text, '<', '<'); + text = xajax.debug.stringReplace(text, '>', '>'); + text = xajax.debug.stringReplace(text, '\n', '
'); + return text; + } + xajax.debug.prepareDebugText(text); + } +} +xjxEc.responseProcessor = { +} + +xjxEc.responseProcessor.XHR = function(oRequest) +{ + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + var oRet = oRequest.returnValue; + + if ("" == oRequest.request.responseText) + return; + var allMessages = oRequest.request.responseText; + if (true === oRequest.comet.inProgress) return; + oRequest.comet.inProgress = true; + do + { + var unprocessed = allMessages.substring(oRequest.comet.LastPosition); + var messageXMLEndIndex = unprocessed.indexOf(""); + + if (messageXMLEndIndex != -1) + { + var endOfFirstMessageIndex = messageXMLEndIndex + ("").length; + var anUpdate = unprocessed.substring(0, endOfFirstMessageIndex); + + var cmd = (new DOMParser()).parseFromString(anUpdate, "text/xml"); + + try + { + var seq = 0; + var child = cmd.documentElement.firstChild; + xt.xml.processFragment(child, seq, oRet, oRequest); + } + catch (ex) + { + } + xt.queue.process(xx.response); + oRequest.comet.LastPosition += endOfFirstMessageIndex; + } + } while (messageXMLEndIndex != -1); + + oRequest.comet.inProgress = false; + return oRet; +} +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: responseProcessor.ActiveX + + Processes the streaming response for IE + +*/ + +xjxEc.responseProcessor.ActiveX = function(response, oRequest) +{ + response.replace('\"', '"'); + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + var oRet = oRequest.returnValue; + + if (response) + { + var cmd = (new DOMParser()).parseFromString(response, "text/xml"); + var seq = 0; + var child = cmd.documentElement.firstChild; + xt.xml.processFragment(child, seq, oRequest); + + if (null == xx.response.timeout) + xt.queue.process(xx.response); + } + return oRet; +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + Function: responseProcessor.HTMLDRAFT + + Processes the streaming response for HTML 5 Draft Browsers (Opera 9+) + +*/ + +xjxEc.responseProcessor.HTMLDRAFT = function(response, oRequest) +{ + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + var oRet = oRequest.returnValue; + if (oRequest.inProgress) return; + if (response && oRequest.lastResponse !== response) + { + oRequest.inProgress = true; + var cmd = (new DOMParser()).parseFromString(response, "text/xml"); + var seq = 0; + var child = cmd.documentElement.firstChild; + xt.xml.processFragment(child, seq, oRequest); + + if (null == xx.response.timeout) + xt.queue.process(xx.response); + oRequest.inProgress=false; + oRequest.lastResponse = response + } + return oRet; +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + Function: submitRequestActiveX + + Supresses the xajax.submitRequest() function call for IE in streaming calls. + +*/ + +xjxEc.submitRequestActiveX = function(oRequest) +{ + if (true == oRequest.comet) + return; + + xjxEc.submitRequest(oRequest); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + variable setup. Detects IE and replaces the according functions + +*/ + +xjxEc.prepareRequest = xajax.prepareRequest; + +xjxEc.stream_support = xjxEc.detectSupport(); + +switch (xjxEc.stream_support) +{ + case "Internet Explorer": + xajax.prepareRequest = xjxEc.prepareRequestActiveX; + xjxEc.submitRequest = xajax.submitRequest; + xajax.submitRequest = xjxEc.submitRequestActiveX; + break; + + case "Firefox": + case "Safari": + xajax.prepareRequest = xjxEc.prepareRequestXHR; + break; + + case "Opera": + xajax.prepareRequest = xjxEc.prepareRequestHTMLDRAFT; + xjxEc.submitRequest = xajax.submitRequest; + xajax.submitRequest = xjxEc.submitRequestActiveX; + break; + + default: + alert("Xajax.Ext.Comet: Your browser does not support comet streaming or is not yet supported by this plugin!"); +} + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + Function: DOMParser + + Prototype DomParser for IE/Opera + +*/ +if (typeof DOMParser == "undefined") +{ + DOMParser = function () + { + } + + DOMParser.prototype.parseFromString = function (str, contentType) + { + if (typeof ActiveXObject != "undefined") + { + var d = new ActiveXObject("Microsoft.XMLDOM"); + d.loadXML(str); + return d; + } + else if (typeof XMLHttpRequest != "undefined") + { + var req = new XMLHttpRequest; + req.open("GET", "data:" + (contentType || "application/xml") + ";charset=utf-8," + encodeURIComponent(str), false); + + if (req.overrideMimeType) + { + req.overrideMimeType(contentType); + } + req.send(null); + return req.responseXML; + } + } +} +// ------------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/www/include/xajax/xajax_plugins/response/comet/xajaxCometFunction.inc.php b/www/include/xajax/xajax_plugins/response/comet/xajaxCometFunction.inc.php new file mode 100644 index 00000000..d5fb4ba9 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/comet/xajaxCometFunction.inc.php @@ -0,0 +1,232 @@ + for a detailed description, copyright + and license information. +*/ + +/* + @package xajax + @version $Id: xajaxCometFunction.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $ + @copyright Copyright (c) 2005-2006 by Jared White & J. Max Wilson + @license http://www.xajaxproject.org/bsd_license.txt BSD License +*/ + +/* + Class: xajaxCometFunction + + Construct instances of this class to define functions that will be registered + with the request processor. This class defines the parameters that + are needed for the definition of a xajax enabled function. While you can + still specify functions by name during registration, it is advised that you + convert to using this class when you wish to register external functions or + to specify call options as well. +*/ +class xajaxCometFunction +{ + /* + String: sAlias + + An alias to use for this function. This is useful when you want + to call the same xajax enabled function with a different set of + call options from what was already registered. + */ + var $sAlias; + + /* + Object: uf + + A string or array which defines the function to be registered. + */ + var $uf; + + /* + String: sInclude + + The path and file name of the include file that contains the function. + */ + var $sInclude; + + /* + Array: aConfiguration + + An associative array containing call options that will be sent to the + browser curing client script generation. + */ + var $aConfiguration; + + /* + Function: xajaxCometFunction + + Constructs and initializes the object. + + $uf - (mixed): A function specification in one of the following formats: + + - a three element array: + (string) Alternate function name: when a method of a class has the same + name as another function in the system, you can provide an alias to + help avoid collisions. + (object or class name) Class: the name of the class or an instance of + the object which contains the function to be called. + (string) Method: the name of the method that will be called. + - a two element array: + (object or class name) Class: the name of the class or an instance of + the object which contains the function to be called. + (string) Method: the name of the method that will be called. + - a string: + the name of the function that is available at global scope (not in a + class. + $sInclude - (string, optional): The path and file name of the include file + that contains the class or function to be called. + + $aConfiguration - (array, optional): An associative array of call options + that will be used when sending the request from the client. + + Examples: + + $myFunction = array('alias', 'myClass', 'myMethod'); + $myFunction = array('alias', &$myObject, 'myMethod'); + $myFunction = array('myClass', 'myMethod'); + $myFunction = array(&$myObject, 'myMethod'); + $myFunction = 'myFunction'; + + $myUserFunction = new xajaxCometFunction($myFunction, 'myFile.inc.php', array( + 'method' => 'get', + 'mode' => 'synchronous' + )); + + $xajax->register(XAJAX_FUNCTION, $myUserFunction); + */ + function xajaxCometFunction($uf, $sInclude=NULL, $aConfiguration=array()) + { + $this->sAlias = ''; + $this->uf =& $uf; + $this->sInclude = $sInclude; + $this->aConfiguration = array(); + foreach ($aConfiguration as $sKey => $sValue) + $this->configure($sKey, $sValue); + + if (is_array($this->uf) && 2 < count($this->uf)) + { + $this->sAlias = $this->uf[0]; + $this->uf = array_slice($this->uf, 1); + } + +//SkipDebug + if (is_array($this->uf) && 2 != count($this->uf)) + trigger_error( + 'Invalid function declaration for xajaxCometFunction.', + E_USER_ERROR + ); +//EndSkipDebug + } + + /* + Function: getName + + Get the name of the function being referenced. + + Returns: + + string - the name of the function contained within this object. + */ + function getName() + { + // Do not use sAlias here! + if (is_array($this->uf)) + return $this->uf[1]; + return $this->uf; + } + + /* + Function: configure + + Call this to set call options for this instance. + */ + function configure($sName, $sValue) + { + if ('alias' == $sName) + $this->sAlias = $sValue; + else + $this->aConfiguration[$sName] = $sValue; + } + + /* + Function: generateRequest + + Constructs and returns a object which is capable + of generating the javascript call to invoke this xajax enabled + function. + */ + function generateRequest($sXajaxPrefix) + { + $sAlias = $this->getName(); + if (0 < strlen($this->sAlias)) + $sAlias = $this->sAlias; + return new xajaxRequest("{$sXajaxPrefix}{$sAlias}"); + } + + /* + Function: generateClientScript + + Called by the that is referencing this function + reference during the client script generation phase. This function + will generate the javascript function stub that is sent to the + browser on initial page load. + */ + function generateClientScript($sXajaxPrefix) + { + $sFunction = $this->getName(); + $sAlias = $sFunction; + if (0 < strlen($this->sAlias)) + $sAlias = $this->sAlias; + echo "{$sXajaxPrefix}{$sAlias} = function() { "; + echo "return xajax.request( "; + echo "{ xjxcomet: '{$sFunction}' }, "; + echo "{ parameters: arguments, mode:'comet'"; + + $sSeparator = ", "; + foreach ($this->aConfiguration as $sKey => $sValue) + echo "{$sSeparator}{$sKey}: {$sValue}"; + + echo " } ); "; + echo "};\n"; + } + + /* + Function: call + + Called by the that references this function during the + request processing phase. This function will call the specified + function, including an external file if needed and passing along + the specified arguments. + */ + function call($aArgs=array()) + { + $objResponseManager =& xajaxResponseManager::getInstance(); + + if (NULL != $this->sInclude) + { + ob_start(); + require_once $this->sInclude; + $sOutput = ob_get_clean(); + +//SkipDebug + if (0 < strlen($sOutput)) + { + $sOutput = 'From include file: ' . $this->sInclude . ' => ' . $sOutput; + $objResponseManager->debug($sOutput); + } +//EndSkipDebug + } + + $mFunction = $this->uf; + $objResponseManager->append(call_user_func_array($mFunction, $aArgs)); + } +} +?> diff --git a/www/include/xajax/xajax_plugins/response/googleMap.inc.php b/www/include/xajax/xajax_plugins/response/googleMap.inc.php new file mode 100644 index 00000000..7ebb2d0d --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/googleMap.inc.php @@ -0,0 +1,18 @@ +sJavascriptURI='';$this->bInlineScript=true;} +function configure($sName,$mValue){if('javascript URI'==$sName){$this->sJavascriptURI=$mValue;}else if('inlineScript'==$sName){if(true===$mValue||false===$mValue) +$this->bInlineScript=$mValue;} +} +function generateClientScript(){echo "\n\n";echo "\n\n";} +function getName(){return get_class($this);} +function setGoogleSiteKey($sKey){$this->sGoogleSiteKey=$sKey;} +function create($sMap,$sParentId){$command=array('n'=>'gm:cr','t'=>$sParentId);$this->addCommand($command,$sMap);} +function zoom($sMap,$nZoom){$command=array('n'=>'gm:zm','t'=>$sMap);$this->addCommand($command,$nZoom);} +function setMarker($sMap,$nLat,$nLon,$sText){$this->addCommand( +array('n'=>'gm:sm','t'=>$sMap), +array($nLat,$nLon,$sText) +);} +function moveTo($sMap,$nLat,$nLon){$command=array('n'=>'et_ar','t'=>$parent);if(null!=$position) +$command['p']=$position;$this->addCommand($command,$row);} +} +$objPluginManager=&xajaxPluginManager::getInstance();$objPluginManager->registerPlugin(new clsGoogleMap()); \ No newline at end of file diff --git a/www/include/xajax/xajax_plugins/response/swfupload/swfupload.inc.php b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.inc.php new file mode 100644 index 00000000..f780a2b7 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.inc.php @@ -0,0 +1,158 @@ +sDefer = ''; + $this->sJavascriptURI = ''; + $this->bInlineScript = false; + } + //-------------------------------------------------------------------------------------------------------------------------------- + + function getName() + { + return get_class( $this ); + } + + //-------------------------------------------------------------------------------------------------------------------------------- + public function configure( $sName, $mValue ) + { + switch ( $sName ) + { + case 'scriptDeferral': + if ( true === $mValue || false === $mValue ) + { + if ( $mValue ) + $this->sDefer = 'defer '; + else + $this->sDefer = ''; + } + break; + + case 'javascript URI': + $this->sJavascriptURI = $mValue; + break; + + case 'inlineScript': + if ( true === $mValue || false === $mValue ) + $this->bInlineScript = $mValue; + break; + + case 'SWFupload_FadeTimeOut': + if ( is_numeric( $mValue ) ) + $this->SWFupload_FadeTimeOut = $mValue; + break; + } + } + + function generateHash() + { + return ('SWFuploadPlugin'); + } + + + //-------------------------------------------------------------------------------------------------------------------------------- + + public function generateClientScript() + { + echo "if (undefined == xajax.ext) xajax.ext = {};\n"; + echo "xajax.ext.SWFupload = {};"; + echo "xajax.ext.SWFupload.config = {};\n"; + echo "xajax.ext.SWFupload.config.javascript_URI='".$this->sJavascriptURI."xajax_plugins/response/swfupload/';\n"; + echo "xajax.ext.SWFupload.config.FadeTimeOut = '".$this->SWFupload_FadeTimeOut."';\n"; + + include( dirname( __FILE__ ).'/swfupload.js' ); + include( dirname( __FILE__ ).'/swfupload.xajax.js' ); + } + + //-------------------------------------------------------------------------------------------------------------------------------- + + function transForm( $id, $config, $multi = false ) + { + $command = array + ( + 'cmd' => 'SWFup_tfo', + 'id' => $id + ); + + $this->addCommand( $command, array + ( + "config" => $config, + "multi" => $multi + )); + } + + //-------------------------------------------------------------------------------------------------------------------------------- + + function transField( $id, $config, $multi = false ) + { + $command = array + ( + 'cmd' => 'SWFup_tfi', + 'id' => $id + ); + + $this->addCommand( $command, array + ( + "config" => $config, + "multi" => $multi + )); + } + //-------------------------------------------------------------------------------------------------------------------------------- + + function destroyField( $id ) + { + $command = array + ( + 'cmd' => 'SWFup_dfi', + 'id' => $id + ); + + $this->addCommand( $command, array ()); + } + //-------------------------------------------------------------------------------------------------------------------------------- + + function destroyForm( $id ) + { + $command = array + ( + 'cmd' => 'SWFup_dfo', + 'id' => $id + ); + + $this->addCommand( $command, array ()); + } +//-------------------------------------------------------------------------------------------------------------------------------- + + +} + +$objPluginManager = &xajaxPluginManager::getInstance(); +$objPluginManager->registerPlugin( new clsSwfUpload(), 100 ); +?> \ No newline at end of file diff --git a/www/include/xajax/xajax_plugins/response/swfupload/swfupload.js b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.js new file mode 100644 index 00000000..ae813554 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.js @@ -0,0 +1,151 @@ + +var SWFUpload;if(SWFUpload==undefined){SWFUpload=function(settings){this.initSWFUpload(settings);};} +SWFUpload.prototype.initSWFUpload=function(settings){try{this.customSettings={};this.settings=settings;this.eventQueue=[];this.movieName="SWFUpload_"+SWFUpload.movieCount++;this.movieElement=null;SWFUpload.instances[this.movieName]=this;this.initSettings();this.loadFlash();this.displayDebugInfo();}catch(ex){delete SWFUpload.instances[this.movieName];throw ex;} +};SWFUpload.instances={};SWFUpload.movieCount=0;SWFUpload.version="2.2.0 Beta 3";SWFUpload.QUEUE_ERROR={QUEUE_LIMIT_EXCEEDED:-100, +FILE_EXCEEDS_SIZE_LIMIT:-110, +ZERO_BYTE_FILE:-120, +INVALID_FILETYPE:-130 +};SWFUpload.UPLOAD_ERROR={HTTP_ERROR:-200, +MISSING_UPLOAD_URL:-210, +IO_ERROR:-220, +SECURITY_ERROR:-230, +UPLOAD_LIMIT_EXCEEDED:-240, +UPLOAD_FAILED:-250, +SPECIFIED_FILE_ID_NOT_FOUND:-260, +FILE_VALIDATION_FAILED:-270, +FILE_CANCELLED:-280, +UPLOAD_STOPPED:-290 +};SWFUpload.FILE_STATUS={QUEUED:-1, +IN_PROGRESS:-2, +ERROR:-3, +COMPLETE:-4, +CANCELLED:-5 +};SWFUpload.BUTTON_ACTION={SELECT_FILE:-100, +SELECT_FILES:-110, +START_UPLOAD:-120 +};SWFUpload.CURSOR={ARROW:-1, +HAND:-2 +};SWFUpload.WINDOW_MODE={WINDOW:"window", +TRANSPARENT:"transparent", +OPAQUE:"opaque" +};SWFUpload.prototype.initSettings=function(){this.ensureDefault=function(settingName,defaultValue){this.settings[settingName]=(this.settings[settingName]==undefined)? defaultValue:this.settings[settingName];};this.ensureDefault("upload_url","");this.ensureDefault("file_post_name","Filedata");this.ensureDefault("post_params",{});this.ensureDefault("use_query_string",false);this.ensureDefault("requeue_on_error",false);this.ensureDefault("http_success",[]);this.ensureDefault("file_types","*.*");this.ensureDefault("file_types_description","All Files");this.ensureDefault("file_size_limit",0);this.ensureDefault("file_upload_limit",0);this.ensureDefault("file_queue_limit",0);this.ensureDefault("flash_url","swfupload.swf");this.ensureDefault("prevent_swf_caching",true);this.ensureDefault("button_image_url","");this.ensureDefault("button_width",1);this.ensureDefault("button_height",1);this.ensureDefault("button_text","");this.ensureDefault("button_text_style","color: #000000; font-size: 16pt;");this.ensureDefault("button_text_top_padding",0);this.ensureDefault("button_text_left_padding",0);this.ensureDefault("button_action",SWFUpload.BUTTON_ACTION.SELECT_FILES);this.ensureDefault("button_disabled",false);this.ensureDefault("button_placeholder_id",null);this.ensureDefault("button_cursor",SWFUpload.CURSOR.ARROW);this.ensureDefault("button_window_mode",SWFUpload.WINDOW_MODE.WINDOW);this.ensureDefault("debug",false);this.settings.debug_enabled=this.settings.debug;this.settings.return_upload_start_handler=this.returnUploadStart;this.ensureDefault("swfupload_loaded_handler",null);this.ensureDefault("file_dialog_start_handler",null);this.ensureDefault("file_queued_handler",null);this.ensureDefault("file_queue_error_handler",null);this.ensureDefault("file_dialog_complete_handler",null);this.ensureDefault("upload_start_handler",null);this.ensureDefault("upload_progress_handler",null);this.ensureDefault("upload_error_handler",null);this.ensureDefault("upload_success_handler",null);this.ensureDefault("upload_complete_handler",null);this.ensureDefault("debug_handler",this.debugMessage);this.ensureDefault("custom_settings",{});this.customSettings=this.settings.custom_settings;if(this.settings.prevent_swf_caching){this.settings.flash_url=this.settings.flash_url+"?swfuploadrnd="+Math.floor(Math.random()*999999999);} +delete this.ensureDefault;};SWFUpload.prototype.loadFlash=function(){if(this.settings.button_placeholder_id!==""){this.replaceWithFlash();}else{this.appendFlash();} +};SWFUpload.prototype.appendFlash=function(){var targetElement,container;if(document.getElementById(this.movieName)!==null){throw "ID "+this.movieName+" is already in use. The Flash Object could not be added";} +targetElement=document.getElementsByTagName("body")[0];if(targetElement==undefined){throw "Could not find the 'body' element.";} +container=document.createElement("div");container.style.width="1px";container.style.height="1px";container.style.overflow="hidden";targetElement.appendChild(container);container.innerHTML=this.getFlashHTML();if(window[this.movieName]==undefined){window[this.movieName]=this.getMovieElement();} +};SWFUpload.prototype.replaceWithFlash=function(){var targetElement,tempParent;if(document.getElementById(this.movieName)!==null){throw "ID "+this.movieName+" is already in use. The Flash Object could not be added";} +targetElement=document.getElementById(this.settings.button_placeholder_id);if(targetElement==undefined){throw "Could not find the placeholder element.";} +tempParent=document.createElement("div");tempParent.innerHTML=this.getFlashHTML();targetElement.parentNode.replaceChild(tempParent.firstChild,targetElement);if(window[this.movieName]==undefined){window[this.movieName]=this.getMovieElement();} +};SWFUpload.prototype.getFlashHTML=function(){return ['', +'', +'', +'', +'', +'', +'', +''].join("");};SWFUpload.prototype.getFlashVars=function(){var paramString=this.buildParamString();var httpSuccessString=this.settings.http_success.join(",");return ["movieName=",encodeURIComponent(this.movieName), +"&uploadURL=",encodeURIComponent(this.settings.upload_url), +"&useQueryString=",encodeURIComponent(this.settings.use_query_string), +"&requeueOnError=",encodeURIComponent(this.settings.requeue_on_error), +"&httpSuccess=",encodeURIComponent(httpSuccessString), +"&params=",encodeURIComponent(paramString), +"&filePostName=",encodeURIComponent(this.settings.file_post_name), +"&fileTypes=",encodeURIComponent(this.settings.file_types), +"&fileTypesDescription=",encodeURIComponent(this.settings.file_types_description), +"&fileSizeLimit=",encodeURIComponent(this.settings.file_size_limit), +"&fileUploadLimit=",encodeURIComponent(this.settings.file_upload_limit), +"&fileQueueLimit=",encodeURIComponent(this.settings.file_queue_limit), +"&debugEnabled=",encodeURIComponent(this.settings.debug_enabled), +"&buttonImageURL=",encodeURIComponent(this.settings.button_image_url), +"&buttonWidth=",encodeURIComponent(this.settings.button_width), +"&buttonHeight=",encodeURIComponent(this.settings.button_height), +"&buttonText=",encodeURIComponent(this.settings.button_text), +"&buttonTextTopPadding=",encodeURIComponent(this.settings.button_text_top_padding), +"&buttonTextLeftPadding=",encodeURIComponent(this.settings.button_text_left_padding), +"&buttonTextStyle=",encodeURIComponent(this.settings.button_text_style), +"&buttonAction=",encodeURIComponent(this.settings.button_action), +"&buttonDisabled=",encodeURIComponent(this.settings.button_disabled), +"&buttonCursor=",encodeURIComponent(this.settings.button_cursor) +].join("");};SWFUpload.prototype.getMovieElement=function(){if(this.movieElement==undefined){this.movieElement=document.getElementById(this.movieName);} +if(this.movieElement===null){throw "Could not find Flash element";} +return this.movieElement;};SWFUpload.prototype.buildParamString=function(){var postParams=this.settings.post_params;var paramStringPairs=[];if(typeof(postParams)==="object"){for(var name in postParams){if(postParams.hasOwnProperty(name)){paramStringPairs.push(encodeURIComponent(name.toString())+"="+encodeURIComponent(postParams[name].toString()));} +} +} +return paramStringPairs.join("&");};SWFUpload.prototype.destroy=function(){try{this.cancelUpload(null,false);;var movieElement=null;movieElement=this.getMovieElement();if(movieElement){for(var i in movieElement){try{if(typeof(movieElement[i])==="function"){movieElement[i]=null;} +}catch(ex1){} +} +try{movieElement.parentNode.removeChild(movieElement);}catch(ex){} +} +window[this.movieName]=null;SWFUpload.instances[this.movieName]=null;delete SWFUpload.instances[this.movieName];this.movieElement=null;this.settings=null;this.customSettings=null;this.eventQueue=null;this.movieName=null;return true;}catch(ex1){alert(ex);return false;} +};SWFUpload.prototype.displayDebugInfo=function(){this.debug( +[ +"---SWFUpload Instance Info---\n", +"Version: ",SWFUpload.version,"\n", +"Movie Name: ",this.movieName,"\n", +"Settings:\n", +"\t","upload_url: ",this.settings.upload_url,"\n", +"\t","flash_url: ",this.settings.flash_url,"\n", +"\t","use_query_string: ",this.settings.use_query_string.toString(),"\n", +"\t","requeue_on_error: ",this.settings.requeue_on_error.toString(),"\n", +"\t","http_success: ",this.settings.http_success.join(", "),"\n", +"\t","file_post_name: ",this.settings.file_post_name,"\n", +"\t","post_params: ",this.settings.post_params.toString(),"\n", +"\t","file_types: ",this.settings.file_types,"\n", +"\t","file_types_description: ",this.settings.file_types_description,"\n", +"\t","file_size_limit: ",this.settings.file_size_limit,"\n", +"\t","file_upload_limit: ",this.settings.file_upload_limit,"\n", +"\t","file_queue_limit: ",this.settings.file_queue_limit,"\n", +"\t","debug: ",this.settings.debug.toString(),"\n", +"\t","prevent_swf_caching: ",this.settings.prevent_swf_caching.toString(),"\n", +"\t","button_placeholder_id: ",this.settings.button_placeholder_id.toString(),"\n", +"\t","button_image_url: ",this.settings.button_image_url.toString(),"\n", +"\t","button_width: ",this.settings.button_width.toString(),"\n", +"\t","button_height: ",this.settings.button_height.toString(),"\n", +"\t","button_text: ",this.settings.button_text.toString(),"\n", +"\t","button_text_style: ",this.settings.button_text_style.toString(),"\n", +"\t","button_text_top_padding: ",this.settings.button_text_top_padding.toString(),"\n", +"\t","button_text_left_padding: ",this.settings.button_text_left_padding.toString(),"\n", +"\t","button_action: ",this.settings.button_action.toString(),"\n", +"\t","button_disabled: ",this.settings.button_disabled.toString(),"\n", +"\t","custom_settings: ",this.settings.custom_settings.toString(),"\n", +"Event Handlers:\n", +"\t","swfupload_loaded_handler assigned: ",(typeof this.settings.swfupload_loaded_handler==="function").toString(),"\n", +"\t","file_dialog_start_handler assigned: ",(typeof this.settings.file_dialog_start_handler==="function").toString(),"\n", +"\t","file_queued_handler assigned: ",(typeof this.settings.file_queued_handler==="function").toString(),"\n", +"\t","file_queue_error_handler assigned: ",(typeof this.settings.file_queue_error_handler==="function").toString(),"\n", +"\t","upload_start_handler assigned: ",(typeof this.settings.upload_start_handler==="function").toString(),"\n", +"\t","upload_progress_handler assigned: ",(typeof this.settings.upload_progress_handler==="function").toString(),"\n", +"\t","upload_error_handler assigned: ",(typeof this.settings.upload_error_handler==="function").toString(),"\n", +"\t","upload_success_handler assigned: ",(typeof this.settings.upload_success_handler==="function").toString(),"\n", +"\t","upload_complete_handler assigned: ",(typeof this.settings.upload_complete_handler==="function").toString(),"\n", +"\t","debug_handler assigned: ",(typeof this.settings.debug_handler==="function").toString(),"\n" +].join("") +);};SWFUpload.prototype.addSetting=function(name,value,default_value){if(value==undefined){return(this.settings[name]=default_value);}else{return(this.settings[name]=value);} +};SWFUpload.prototype.getSetting=function(name){if(this.settings[name]!=undefined){return this.settings[name];} +return "";};SWFUpload.prototype.callFlash=function(functionName,argumentArray){argumentArray=argumentArray||[];var movieElement=this.getMovieElement();var returnValue,returnString;try{returnString=movieElement.CallFunction(''+__flash__argumentsToXML(argumentArray,0)+'');returnValue=eval(returnString);}catch(ex){throw "Call to "+functionName+" failed";} +if(returnValue!=undefined&&typeof returnValue.post==="object"){returnValue=this.unescapeFilePostParams(returnValue);} +return returnValue;};SWFUpload.prototype.selectFile=function(){this.callFlash("SelectFile");};SWFUpload.prototype.selectFiles=function(){this.callFlash("SelectFiles");};SWFUpload.prototype.startUpload=function(fileID){this.callFlash("StartUpload",[fileID]);};SWFUpload.prototype.cancelUpload=function(fileID,triggerErrorEvent){if(triggerErrorEvent!==false){triggerErrorEvent=true;} +this.callFlash("CancelUpload",[fileID,triggerErrorEvent]);};SWFUpload.prototype.stopUpload=function(){this.callFlash("StopUpload");};SWFUpload.prototype.getStats=function(){return this.callFlash("GetStats");};SWFUpload.prototype.setStats=function(statsObject){this.callFlash("SetStats",[statsObject]);};SWFUpload.prototype.getFile=function(fileID){if(typeof(fileID)==="number"){return this.callFlash("GetFileByIndex",[fileID]);}else{return this.callFlash("GetFile",[fileID]);} +};SWFUpload.prototype.addFileParam=function(fileID,name,value){return this.callFlash("AddFileParam",[fileID,name,value]);};SWFUpload.prototype.removeFileParam=function(fileID,name){this.callFlash("RemoveFileParam",[fileID,name]);};SWFUpload.prototype.setUploadURL=function(url){this.settings.upload_url=url.toString();this.callFlash("SetUploadURL",[url]);};SWFUpload.prototype.setPostParams=function(paramsObject){this.settings.post_params=paramsObject;this.callFlash("SetPostParams",[paramsObject]);};SWFUpload.prototype.addPostParam=function(name,value){this.settings.post_params[name]=value;this.callFlash("SetPostParams",[this.settings.post_params]);};SWFUpload.prototype.removePostParam=function(name){delete this.settings.post_params[name];this.callFlash("SetPostParams",[this.settings.post_params]);};SWFUpload.prototype.setFileTypes=function(types,description){this.settings.file_types=types;this.settings.file_types_description=description;this.callFlash("SetFileTypes",[types,description]);};SWFUpload.prototype.setFileSizeLimit=function(fileSizeLimit){this.settings.file_size_limit=fileSizeLimit;this.callFlash("SetFileSizeLimit",[fileSizeLimit]);};SWFUpload.prototype.setFileUploadLimit=function(fileUploadLimit){this.settings.file_upload_limit=fileUploadLimit;this.callFlash("SetFileUploadLimit",[fileUploadLimit]);};SWFUpload.prototype.setFileQueueLimit=function(fileQueueLimit){this.settings.file_queue_limit=fileQueueLimit;this.callFlash("SetFileQueueLimit",[fileQueueLimit]);};SWFUpload.prototype.setFilePostName=function(filePostName){this.settings.file_post_name=filePostName;this.callFlash("SetFilePostName",[filePostName]);};SWFUpload.prototype.setUseQueryString=function(useQueryString){this.settings.use_query_string=useQueryString;this.callFlash("SetUseQueryString",[useQueryString]);};SWFUpload.prototype.setRequeueOnError=function(requeueOnError){this.settings.requeue_on_error=requeueOnError;this.callFlash("SetRequeueOnError",[requeueOnError]);};SWFUpload.prototype.setHTTPSuccess=function(http_status_codes){if(typeof http_status_codes==="string"){http_status_codes=http_status_codes.replace(" ","").split(",");} +this.settings.http_success=http_status_codes;this.callFlash("SetHTTPSuccess",[http_status_codes]);};SWFUpload.prototype.setDebugEnabled=function(debugEnabled){this.settings.debug_enabled=debugEnabled;this.callFlash("SetDebugEnabled",[debugEnabled]);};SWFUpload.prototype.setButtonImageURL=function(buttonImageURL){if(buttonImageURL==undefined){buttonImageURL="";} +this.settings.button_image_url=buttonImageURL;this.callFlash("SetButtonImageURL",[buttonImageURL]);};SWFUpload.prototype.setButtonDimensions=function(width,height){this.settings.button_width=width;this.settings.button_height=height;var movie=this.getMovieElement();if(movie!=undefined){movie.style.width=width+"px";movie.style.height=height+"px";} +this.callFlash("SetButtonDimensions",[width,height]);};SWFUpload.prototype.setButtonText=function(html){this.settings.button_text=html;this.callFlash("SetButtonText",[html]);};SWFUpload.prototype.setButtonTextPadding=function(left,top){this.settings.button_text_top_padding=top;this.settings.button_text_left_padding=left;this.callFlash("SetButtonTextPadding",[left,top]);};SWFUpload.prototype.setButtonTextStyle=function(css){this.settings.button_text_style=css;this.callFlash("SetButtonTextStyle",[css]);};SWFUpload.prototype.setButtonDisabled=function(isDisabled){this.settings.button_disabled=isDisabled;this.callFlash("SetButtonDisabled",[isDisabled]);};SWFUpload.prototype.setButtonAction=function(buttonAction){this.settings.button_action=buttonAction;this.callFlash("SetButtonAction",[buttonAction]);};SWFUpload.prototype.setButtonCursor=function(cursor){this.settings.button_cursor=cursor;this.callFlash("SetButtonCursor",[cursor]);};SWFUpload.prototype.queueEvent=function(handlerName,argumentArray){if(argumentArray==undefined){argumentArray=[];}else if(!(argumentArray instanceof Array)){argumentArray=[argumentArray];} +var self=this;if(typeof this.settings[handlerName]==="function"){this.eventQueue.push(function(){this.settings[handlerName].apply(this,argumentArray);});setTimeout(function(){self.executeNextEvent();},0);}else if(this.settings[handlerName]!==null){throw "Event handler "+handlerName+" is unknown or is not a function";} +};SWFUpload.prototype.executeNextEvent=function(){var f=this.eventQueue ? this.eventQueue.shift():null;if(typeof(f)==="function"){f.apply(this);} +};SWFUpload.prototype.unescapeFilePostParams=function(file){var reg=/[$]([0-9a-f]{4})/i;var unescapedPost={};var uk;if(file!=undefined){for(var k in file.post){if(file.post.hasOwnProperty(k)){uk=k;var match;while((match=reg.exec(uk))!==null){uk=uk.replace(match[0],String.fromCharCode(parseInt("0x"+match[1],16)));} +unescapedPost[uk]=file.post[k];} +} +file.post=unescapedPost;} +return file;};SWFUpload.prototype.flashReady=function(){var movieElement=this.getMovieElement();if(typeof(movieElement.CallFunction)==="unknown"){this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");for(var key in movieElement){try{if(typeof(movieElement[key])==="function"){movieElement[key]=null;} +}catch(ex){} +} +} +this.queueEvent("swfupload_loaded_handler");};SWFUpload.prototype.fileDialogStart=function(){this.queueEvent("file_dialog_start_handler");};SWFUpload.prototype.fileQueued=function(file){file=this.unescapeFilePostParams(file);this.queueEvent("file_queued_handler",file);};SWFUpload.prototype.fileQueueError=function(file,errorCode,message){file=this.unescapeFilePostParams(file);this.queueEvent("file_queue_error_handler",[file,errorCode,message]);};SWFUpload.prototype.fileDialogComplete=function(numFilesSelected,numFilesQueued){this.queueEvent("file_dialog_complete_handler",[numFilesSelected,numFilesQueued]);};SWFUpload.prototype.uploadStart=function(file){file=this.unescapeFilePostParams(file);this.queueEvent("return_upload_start_handler",file);};SWFUpload.prototype.returnUploadStart=function(file){var returnValue;if(typeof this.settings.upload_start_handler==="function"){file=this.unescapeFilePostParams(file);returnValue=this.settings.upload_start_handler.call(this,file);}else if(this.settings.upload_start_handler!=undefined){throw "upload_start_handler must be a function";} +if(returnValue===undefined){returnValue=true;} +returnValue=!!returnValue;this.callFlash("ReturnUploadStart",[returnValue]);};SWFUpload.prototype.uploadProgress=function(file,bytesComplete,bytesTotal){file=this.unescapeFilePostParams(file);this.queueEvent("upload_progress_handler",[file,bytesComplete,bytesTotal]);};SWFUpload.prototype.uploadError=function(file,errorCode,message){file=this.unescapeFilePostParams(file);this.queueEvent("upload_error_handler",[file,errorCode,message]);};SWFUpload.prototype.uploadSuccess=function(file,serverData){file=this.unescapeFilePostParams(file);this.queueEvent("upload_success_handler",[file,serverData]);};SWFUpload.prototype.uploadComplete=function(file){file=this.unescapeFilePostParams(file);this.queueEvent("upload_complete_handler",file);};SWFUpload.prototype.debug=function(message){this.queueEvent("debug_handler",message);};SWFUpload.prototype.debugMessage=function(message){if(this.settings.debug){var exceptionMessage,exceptionValues=[];if(typeof message==="object"&&typeof message.name==="string"&&typeof message.message==="string"){for(var key in message){if(message.hasOwnProperty(key)){exceptionValues.push(key+": "+message[key]);} +} +exceptionMessage=exceptionValues.join("\n")||"";exceptionValues=exceptionMessage.split("\n");exceptionMessage="EXCEPTION: "+exceptionValues.join("\nEXCEPTION: ");SWFUpload.Console.writeLine(exceptionMessage);}else{SWFUpload.Console.writeLine(message);} +} +};SWFUpload.Console={};SWFUpload.Console.writeLine=function(message){var console,documentForm;try{console=document.getElementById("SWFUpload_Console");if(!console){documentForm=document.createElement("form");document.getElementsByTagName("body")[0].appendChild(documentForm);console=document.createElement("textarea");console.id="SWFUpload_Console";console.style.fontFamily="monospace";console.setAttribute("wrap","off");console.wrap="off";console.style.overflow="auto";console.style.width="700px";console.style.height="350px";console.style.margin="5px";documentForm.appendChild(console);} +console.value+=message+"\n";console.scrollTop=console.scrollHeight-console.clientHeight;}catch(ex){alert("Exception: "+ex.name+" Message: "+ex.message);} +}; \ No newline at end of file diff --git a/www/include/xajax/xajax_plugins/response/swfupload/swfupload.swf b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.swf new file mode 100644 index 00000000..6ac3b812 Binary files /dev/null and b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.swf differ diff --git a/www/include/xajax/xajax_plugins/response/swfupload/swfupload.xajax.js b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.xajax.js new file mode 100644 index 00000000..1da7d103 --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/swfupload/swfupload.xajax.js @@ -0,0 +1,112 @@ + +xajax.ext.SWFupload.swf=null;xajax.ext.SWFupload.forms={};xajax.ext.SWFupload.fields={};xajax.ext.SWFupload.queues={};xajax.ext.SWFupload.tools={};xajax.ext.SWFupload.settings={flash_url:xajax.ext.SWFupload.config.javascript_URI+"swfupload.swf", +file_size_limit:"0", +file_types:"*.*", +file_types_description:"All Files", +file_upload_limit:0, +file_queue_limit:0, +file_queue_error_handler:xajax.ext.SWFupload.tools.fileQueueError, +debug:false, +button_image_url:"img/button_500x22.gif", +button_width:270, +button_height:22, +button_action:SWFUpload.BUTTON_ACTION.SELECT_FILES, +button_window_mode:SWFUpload.WINDOW_MODE.TRANSPARENT, +button_placeholder_id:'', +button_text:'Select Files...', +button_text_style:".btnText { font-size: 10; font-weight: bold; font-family: MS Shell Dlg; }", +button_text_top_padding:3, +button_text_left_padding:100, +post_params:{} +} +if('undefined'==typeof xajax.ext.SWFupload.lang){xajax.ext.SWFupload.lang={};xajax.ext.SWFupload.lang.browseFiles='Browse Files';xajax.ext.SWFupload.lang.browseFile='Browse File';} +xajax.ext.SWFupload.configure=function(config){if("object"==typeof config)return xajax.ext.SWFupload.tools.mergeObj(this.settings,config);return this.settings;} +xajax.ext.SWFupload.addQueue=function(child,parent,config,multiple){var id=xajax.ext.SWFupload.tools.getId();this.queues[id]=new xajax.ext.SWFupload.tools.fileQueue(id,child,parent,config,multiple);return id;} +xajax.ext.SWFupload.applyConfig=function(oQueue){var conf=oQueue.getConfig();var swf=xajax.ext.SWFupload.getInstance();if('undefined'!=typeof conf.file_types) +swf.setFileTypes(conf.file_types,conf.file_types_description);if('undefined'!=typeof conf.file_size_limit) +swf.setFileSizeLimit(conf.file_size_limit);if('object'==typeof conf.post_params){for(a in conf.post_params) +swf.addPostParam(a,conf.post_params[a]);} +swf.settings.file_queued_handler=function(oFile){oQueue.addFile(oFile)};;swf.settings.file_queue_error_handler=oQueue.fileQueueError;} +xajax.ext.SWFupload.selectFile=function(oQueue){this.applyConfig(oQueue);if(oQueue.getConfig().file_queue_limit > 0&&oQueue.getConfig().file_queue_limit <=oQueue.queued)return;xajax.ext.SWFupload.getInstance().selectFile();} +xajax.ext.SWFupload.selectFiles=function(oQueue){this.applyConfig(oQueue);if(oQueue.getConfig().file_queue_limit > 0&&oQueue.getConfig().file_queue_limit <=oQueue.queued)return;xajax.ext.SWFupload.getInstance().selectFiles();} +xajax.ext.SWFupload.getInstance=function(){if(null==this.swf)this.swf=new SWFUpload(this.settings);return this.swf;} +xajax.ext.SWFupload.removeFile=function(QueueId,FileId,finished){this.queues[QueueId].removeFile(FileId,finished);} +xajax.ext.SWFupload.request={};xajax.ext.SWFupload.request.getFileFromQueue=function(oRequest){var instances={};var queued=0;if("string"==typeof oRequest.SWFform){if('object'!=typeof xajax.ext.SWFupload.forms[oRequest.SWFform]){return false;} +for(a in xajax.ext.SWFupload.forms[oRequest.SWFform]){var field=xajax.ext.SWFupload.forms[oRequest.SWFform][a];if(0 < xajax.ext.SWFupload.queues[field].queued){oRequest.currentFile=xajax.ext.SWFupload.queues[field].getFile();oRequest.swf=xajax.ext.SWFupload.queues[field].getSWF();return true;};} +}else if("string"==typeof oRequest.SWFfield){if('string'!=typeof xajax.ext.SWFupload.fields[oRequest.SWFfield]){return false;} +var qId=xajax.ext.SWFupload.fields[oRequest.SWFfield];if(0 < xajax.ext.SWFupload.queues[qId].queued){oRequest.currentFile=xajax.ext.SWFupload.queues[qId].getFile();oRequest.swf=xajax.ext.SWFupload.queues[qId].getSWF();return true;};}else{for(var a in xajax.ext.SWFupload.queues){if(0 < xajax.ext.SWFupload.queues[a].queued){oRequest.currentFile=xajax.ext.SWFupload.queues[a].getFile();oRequest.swf=xajax.ext.SWFupload.queues[a].getSWF();return true;};} +} +return false;} +xajax.ext.SWFupload.request.processParameters=function(oRequest){if("SWFupload"==oRequest.mode){oRequest.currentFile=false;xajax.ext.SWFupload.request.getFileFromQueue(oRequest);if(oRequest.currentFile)oRequest.method='GET';} +return xajax.ext.SWFupload.bak.processParameters(oRequest);} +xajax.ext.SWFupload.request.prepareRequest=function(oRequest){if("SWFupload"==oRequest.mode&&false!=oRequest.currentFile)return;return xajax.ext.SWFupload.bak.prepareRequest(oRequest);} +xajax.ext.SWFupload.request.submitRequest=function(oRequest){if("SWFupload"==oRequest.mode&&false!=oRequest.currentFile){if(oRequest.requestURI){oRequest.bak_requestURI=oRequest.requestURI;}else if(oRequest.bak_requestURI){oRequest.requestURI=oRequest.bak_requestURI;} +var swf=oRequest.swf;var fileQueue=xajax.ext.SWFupload.queues[oRequest.currentFile.QueueId];swf.customSettings.currentFile=oRequest.currentFile;swf.setFilePostName(swf.customSettings.currentFile.name);swf.customSettings.oRequest=oRequest;swf.setUploadURL(oRequest.requestURI);swf.settings.upload_success_handler=function(oFile,response){var xx=xajax;var xt=xx.tools;var xcb=xx.callback;var gcb=xcb.global;var lcb=oRequest.callback;var oRet=oRequest.returnValue;var FileId=swf.customSettings.currentFile;if('function'==typeof this.old_upload_success_handler)this.old_upload_success_handler(oFile);xcb.execute([gcb,lcb],'onSuccess',oRequest);var seq=0;if(response){var responseXML=(new DOMParser()).parseFromString(response,"text/xml");if(responseXML.documentElement){oRequest.status.onProcessing();var child=responseXML.documentElement.firstChild;oRet=xt.xml.processFragment(child,seq,oRet,oRequest);} +} +var obj={};obj.fullName='Response Complete';obj.sequence=seq;obj.request=oRequest;obj.context=oRequest.context;obj.cmd='rcmplt';xt.queue.push(xx.response,obj);if(null==xx.response.timeout) +xt.queue.process(xx.response);} +swf.settings.upload_complete_handler=function(oFile){var qFile=this.customSettings.currentFile;xajax.ext.SWFupload.removeFile(qFile.QueueId,qFile.id,true);if(!xajax.ext.SWFupload.request.getFileFromQueue(oRequest)){if('function'==typeof oRequest.onUploadComplete)oRequest.onUploadComplete();return;} +xajax.ext.SWFupload.request.submitRequest(oRequest);} +swf.settings.upload_start_handler=function(oFile){if('function'==typeof this.old_upload_start_handler)this.old_upload_start_handler(oFile);oRequest.startTime=new Date();} +swf.settings.upload_progress_handler=function(oFile,bytesLoaded,bytesTotal){upload={};upload.received=bytesLoaded;upload.total=bytesTotal;upload.state="uploading";var reqTime=new Date();upload.lastbytes=oRequest.lastbytes;upload.now=reqTime.getTime()/1000;upload.start=oRequest.startTime.getTime()/1000;var step=upload.received/(upload.total/100);var progressbar=xajax.$('SWFup_progress_'+oFile.id);var w=Math.round(220*step/100);progressbar.style.width=w+'px';var progress=xajax.$("swf_queued_filesize_"+oFile.id);var elapsed=upload.now-upload.start;var rate=xajax.ext.SWFupload.tools.formatBytes(upload.received/elapsed).toString()+'/s';progress.innerHTML=""+rate+" "+xajax.ext.SWFupload.tools.formatBytes(upload.received)+"/"+xajax.ext.SWFupload.tools.formatBytes(upload.total);oRequest.lastbytes=upload.received;} +swf.settings.upload_error_handler=function(file,errorCode,message){if(-280==errorCode)return;if(file==null){fileName='';}else{fileName=file.name;} +alert("Error Code: "+errorCode+", File name: "+fileName+", Message: "+message);};swf.startUpload(swf.customSettings.currentFile.id);return;} +return xajax.ext.SWFupload.bak.submitRequest(oRequest);} +xajax.ext.SWFupload.tools.queueFile=function(oFile,name,QueueId,QueueContainer){this.id=oFile.id;this.name=name;this.QueueId=QueueId;var container=document.createElement('div');container.id="SWFup_"+this.id;container.className="swf_queued_file";this.elm=container;var remove=document.createElement('div');remove.className="swf_queued_file_remove";remove.innerHTML=" ";var id=this.id;var QueueId=this.QueueId;remove.onclick=function(){xajax.ext.SWFupload.removeFile(QueueId,id);} +container.appendChild(remove);var label=document.createElement('div');label.className="swf_queued_filename";label.innerHTML=oFile.name;container.appendChild(label);var progress_container=document.createElement('div');progress_container.className="swf_queued_file_progress_container";container.appendChild(progress_container);var progress=document.createElement('div');progress.className="swf_queued_file_progress_bar";progress.style.width='1px';progress.id='SWFup_progress_'+oFile.id;progress_container.appendChild(progress);var fSize=document.createElement('div');fSize.className="swf_queued_filesize";fSize.id="swf_queued_filesize_"+this.id;fSize.innerHTML=xajax.ext.SWFupload.tools.formatBytes(oFile.size);container.appendChild(fSize);var fClear=document.createElement('div');fClear.style.clear='both';container.appendChild(fClear);QueueContainer.appendChild(container);this.container=container;this.oFile=oFile;this.destroy=function(){QueueContainer.removeChild(container);} +return;} +xajax.ext.SWFupload.tools.fileQueue=function(id,child,parent,config,multiple){this.id=id;var config='object'==typeof config ? xajax.ext.SWFupload.tools.mergeObj(xajax.ext.SWFupload.settings,config):xajax.ext.SWFupload.settings;this.queued=0;this.files={};this.queue=null;this.getConfig=function(){return config;} +var tmpName=child.name;var container=document.createElement('div');container.id='SWFbuttonContainer_'+tmpName;container.className='swf_browse_button';parent.appendChild(container);var container2=document.createElement('div');container2.id='SWFbutton_'+tmpName;container.appendChild(container2);parent.removeChild(child);var oQueue=this;if(true===multiple){config.button_action=SWFUpload.BUTTON_ACTION.SELECT_FILES;}else{config.button_action=SWFUpload.BUTTON_ACTION.SELECT_FILE;} +var QueueContainer=document.createElement('div');QueueContainer.id='SWFqueue_'+this.id;QueueContainer.className='swf_queue_container';parent.appendChild(QueueContainer);config.button_placeholder_id=container2.id;var foo=this;var fieldname=child.name;this.addFile=function(oFile){foo.files[oFile.id]=new xajax.ext.SWFupload.tools.queueFile(oFile,fieldname,foo.id,QueueContainer);foo.queued++;if(foo.queued==config.file_queue_limit)foo.swf.setButtonDisabled(true);} +this.getFile=function(FileId){if("undefined"!=typeof FileId)return foo.files[FileId];for(a in foo.files)return foo.files[a];return false;} +this.purge=function(d){var a=d.attributes,i,l,n;if(a){l=a.length;for(i=0;i < l;i+=1){n=a[i].name;if(typeof d[n]==='function'){d[n]=null;} +} +} +a=d.childNodes;if(a){l=a.length;for(i=0;i < l;i+=1){this.purge(d.childNodes[i]);} +} +} +this.removeFile=function(FileId,finished){foo.swf.cancelUpload(FileId);foo.queued--;if(foo.queued <=config.file_queue_limit)foo.swf.setButtonDisabled(false);var filediv=xajax.$("SWFup_"+foo.files[FileId].id);filediv.className=true===finished ? 'swf_queued_file_finished':'swf_queued_file_removed';setTimeout(function(){xajax.ext.SWFupload.tools.FadeOut(filediv,100);},xajax.ext.SWFupload.config.FadeTimeOut);foo.files[FileId]=null;delete foo.files[FileId];} +this.destroy=function(){this.swf.destroy();delete(this.swf);for(a in foo.files){foo.files[a].destroy();delete(foo.files[a]);} +foo.queued=0;delete(foo);} +this.fileQueueError=function(swf,code,msg){if(-110==code){msg="Die gewählte Datei ist zu groß!";alert(msg);} +} +this.getSWF=function(){return this.swf;} +config.file_queued_handler=this.addFile;config.file_queue_error_handler=this.fileQueueError;this.swf=new SWFUpload(config);} +xajax.ext.SWFupload.tools._parseFields=function(children,parent,config,multiple){var result={};var iLen=children.length;for(var i=0;i < iLen;++i){var child=children[i];if('undefined'!=typeof child.childNodes) +var res2=xajax.ext.SWFupload.tools._parseFields(child.childNodes,child,config,multiple);result=xajax.ext.SWFupload.tools.mergeObj(result,res2);if(child.name){if('file'==child.type){result[child.name]=xajax.ext.SWFupload.addQueue(child,parent,config,multiple);} +} +} +return result;} +xajax.ext.SWFupload.tools.transForm=function(form_id,config,multiple){var oForm=xajax.$(form_id);if(oForm) +if(oForm.childNodes){var fields=xajax.ext.SWFupload.tools._parseFields(oForm.childNodes,oForm,config,multiple);xajax.ext.SWFupload.forms[form_id]=fields;} +return;} +xajax.ext.SWFupload.tools.transField=function(field_id,config,multiple){try{var oField=xajax.$(field_id);if('undefined'!=typeof oField)return xajax.ext.SWFupload.fields[field_id]=xajax.ext.SWFupload.addQueue(oField,oField.parentNode,config,multiple);}catch(ex){} +return;} +xajax.ext.SWFupload.tools.destroyForm=function(form_id){if("undefined"==typeof xajax.ext.SWFupload.forms[form_id])return;for(a in xajax.ext.SWFupload.forms[form_id]){var key=xajax.ext.SWFupload.forms[form_id][a];xajax.ext.SWFupload.queues[key].destroy();delete xajax.ext.SWFupload.queues[key];} +delete xajax.ext.SWFupload.forms[form_id];return;} +xajax.ext.SWFupload.tools.destroyField=function(field_id){if("undefined"==typeof xajax.ext.SWFupload.fields[field_id])return;var key=xajax.ext.SWFupload.fields[field_id];xajax.ext.SWFupload.queues[key].destroy();delete(xajax.ext.SWFupload.queues[key]);delete xajax.ext.SWFupload.fields[field_id];return true;} +xajax.ext.SWFupload.tools.FadeOut=function(elm,opacity){var reduceOpacityBy=15;var rate=40;if(opacity > 0){opacity-=reduceOpacityBy;if(opacity < 0){opacity=0;} +if(elm.filters){try{elm.filters.item("DXImageTransform.Microsoft.Alpha").opacity=opacity;}catch(e){elm.style.filter="progid:DXImageTransform.Microsoft.Alpha(opacity="+opacity+")";} +}else{elm.style.opacity=opacity/100;} +} +if(opacity > 0){var oSelf=this;setTimeout(function(){xajax.ext.SWFupload.tools.FadeOut(elm,opacity);},rate);}else{var parent=elm.parentNode;parent.removeChild(elm);} +} +xajax.ext.SWFupload.tools.formatBytes=function(bytes){var ret={};if(bytes/1204 < 1024){return(Math.round(bytes/1024*100)/100).toString()+" kB";}else{return(Math.round(bytes/1024/1024*100)/100).toString()+" MB";} +return ret;} +xajax.ext.SWFupload.tools.mergeObj=function(){if('object'!=typeof arguments)return;var res={};var len=arguments.length;for(var i=0;iSelect Files...', + button_text_style:".btnText { font-size: 10; font-weight: bold; font-family: MS Shell Dlg; }", + button_text_top_padding:3, + button_text_left_padding:100, + post_params:{} +} + +if ('undefined' == typeof xajax.ext.SWFupload.lang) { + xajax.ext.SWFupload.lang = {}; + xajax.ext.SWFupload.lang.browseFiles = 'Browse Files'; + xajax.ext.SWFupload.lang.browseFile = 'Browse File'; +} + + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.init + arguments: config [object] + + Creates the SWFupload instance + */ + +xajax.ext.SWFupload.configure = function (config) { + if ("object" == typeof config) return xajax.ext.SWFupload.tools.mergeObj(this.settings, config); + + return this.settings; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.addQueue + arguments: child [object], parent [object], config [objeect ,multiple [bool] + + Creates a new a new file queue and stores the reference in this.queues + */ +xajax.ext.SWFupload.addQueue = function (child, parent, config, multiple) { + var id = xajax.ext.SWFupload.tools.getId(); + this.queues[id] = new xajax.ext.SWFupload.tools.fileQueue(id, child, parent, config, multiple); + + return id; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.applyConfig + arguments: oQueue [object] + + Applies the queue's config on the SWFupload instance + */ +xajax.ext.SWFupload.applyConfig = function (oQueue) { + + var conf = oQueue.getConfig(); + var swf = xajax.ext.SWFupload.getInstance(); + + if ('undefined' != typeof conf.file_types) + swf.setFileTypes(conf.file_types, conf.file_types_description); + + if ('undefined' != typeof conf.file_size_limit) + swf.setFileSizeLimit(conf.file_size_limit); + + if ('object' == typeof conf.post_params) { + for (a in conf.post_params) + swf.addPostParam(a, conf.post_params[a]); + } + + swf.settings.file_queued_handler = function (oFile) { + oQueue.addFile(oFile) + }; + ; + swf.settings.file_queue_error_handler = oQueue.fileQueueError; +} +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.selectFile + arguments: oQueue [object] + + Onclick handler for selecting file + */ + +xajax.ext.SWFupload.selectFile = function (oQueue) { + this.applyConfig(oQueue); + + if (oQueue.getConfig().file_queue_limit > 0 && oQueue.getConfig().file_queue_limit <= oQueue.queued) return; + + xajax.ext.SWFupload.getInstance().selectFile(); +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.selectFiles + arguments: oQueue [object] + + Onclick handler for selecting files + */ + +xajax.ext.SWFupload.selectFiles = function (oQueue) { + this.applyConfig(oQueue); + if (oQueue.getConfig().file_queue_limit > 0 && oQueue.getConfig().file_queue_limit <= oQueue.queued) return; + xajax.ext.SWFupload.getInstance().selectFiles(); +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.getInstance + arguments: + + Return the SWFupload instance. If there's no instance available it creates a new one with default settings. + */ + +xajax.ext.SWFupload.getInstance = function () { + if (null == this.swf) this.swf = new SWFUpload(this.settings); + + return this.swf; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.removeFile + arguments: QueueId [integer] , FileId [integer] + + Removes the file (FileID) from queue (QueueId) + */ + +xajax.ext.SWFupload.removeFile = function (QueueId, FileId, finished) { + this.queues[QueueId].removeFile(FileId, finished); +} + + +/* ------------------------------------------------------------------------------------------------------------------------ */ + +xajax.ext.SWFupload.request = {}; + + +/* + function: xajax.ext.SWFupload.request.getFileFromQueue + arguments: oRequest [object] + + Returns the first file from first available queue. + Returns false if no files were selected + */ + +xajax.ext.SWFupload.request.getFileFromQueue = function (oRequest) { + + + var instances = {}; + var queued = 0; + if ("string" == typeof oRequest.SWFform) { + + + if ('object' != typeof xajax.ext.SWFupload.forms[oRequest.SWFform]) { + return false; + } + for (a in xajax.ext.SWFupload.forms[oRequest.SWFform]) { + var field = xajax.ext.SWFupload.forms[oRequest.SWFform][a]; + if (0 < xajax.ext.SWFupload.queues[field].queued) { + oRequest.currentFile = xajax.ext.SWFupload.queues[field].getFile(); + oRequest.swf = xajax.ext.SWFupload.queues[field].getSWF(); + return true; + } + ; + } + } else if ("string" == typeof oRequest.SWFfield) { + if ('string' != typeof xajax.ext.SWFupload.fields[oRequest.SWFfield]) { + return false; + } + + var qId = xajax.ext.SWFupload.fields[oRequest.SWFfield]; + if (0 < xajax.ext.SWFupload.queues[qId].queued) { + oRequest.currentFile = xajax.ext.SWFupload.queues[qId].getFile(); + oRequest.swf = xajax.ext.SWFupload.queues[qId].getSWF(); + return true; + } + ; + } else { + + for (var a in xajax.ext.SWFupload.queues) { + if (0 < xajax.ext.SWFupload.queues[a].queued) { + oRequest.currentFile = xajax.ext.SWFupload.queues[a].getFile(); + oRequest.swf = xajax.ext.SWFupload.queues[a].getSWF(); + return true; + } + ; + } + } + + return false; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.request. xajax.ext.SWFupload.request.processParameters = function(oRequest) + + arguments: oRequest [object] + + Processes the parameters + */ + +xajax.ext.SWFupload.request.processParameters = function (oRequest) { + if ("SWFupload" == oRequest.mode) { + oRequest.currentFile = false; + xajax.ext.SWFupload.request.getFileFromQueue(oRequest); + if (oRequest.currentFile) oRequest.method = 'GET'; + } + return xajax.ext.SWFupload.bak.processParameters(oRequest); +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.request. xajax.ext.SWFupload.request.prepareRequest = function(oRequest) + + arguments: oRequest [object] + + doesn't to anything at all when there's a file selected for upload + */ + +xajax.ext.SWFupload.request.prepareRequest = function (oRequest) { + if ("SWFupload" == oRequest.mode && false != oRequest.currentFile) return; + return xajax.ext.SWFupload.bak.prepareRequest(oRequest); +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.request. xajax.ext.SWFupload.request.submitRequest = function(oRequest) + + arguments: oRequest [object] + + Submits the request either via SWFupload or XHR + */ + +xajax.ext.SWFupload.request.submitRequest = function (oRequest) { + if ("SWFupload" == oRequest.mode && false != oRequest.currentFile) { + + if (oRequest.requestURI) { + //backup requestURI, otherwise xajax.responseReceived() is going to delete our url + oRequest.bak_requestURI = oRequest.requestURI; + } else if (oRequest.bak_requestURI) { + oRequest.requestURI = oRequest.bak_requestURI; + } + + var swf = oRequest.swf; + + var fileQueue = xajax.ext.SWFupload.queues[oRequest.currentFile.QueueId]; + + swf.customSettings.currentFile = oRequest.currentFile; + swf.setFilePostName(swf.customSettings.currentFile.name); + + swf.customSettings.oRequest = oRequest; + swf.setUploadURL(oRequest.requestURI); + + swf.settings.upload_success_handler = function (oFile, response) { + var xx = xajax; + var xt = xx.tools; + var xcb = xx.callback; + var gcb = xcb.global; + var lcb = oRequest.callback; + + var oRet = oRequest.returnValue; + var isXML = '<' == response.substr(0,1) ? true : false; + + + var FileId = swf.customSettings.currentFile; + if ('function' == typeof this.old_upload_success_handler) this.old_upload_success_handler(oFile); + xcb.execute([gcb, lcb], 'onSuccess', oRequest); + + var seq = 0; + if (isXML) + { + if (response) { + var responseXML = (new DOMParser()).parseFromString(response, "text/xml"); + if (responseXML.documentElement) { + oRequest.status.onProcessing(); + + var child = responseXML.documentElement.firstChild; + oRet = xt.xml.processFragment(child, seq, oRet, oRequest); + } + } + + } + else { + if (response) { + try { + var responseJSON = eval('('+response+')'); + } catch (ex) { + throw(ex); + } + if ( ('object' == typeof responseJSON) && ('object' == typeof responseJSON.xjxobj) ) { + oRequest.status.onProcessing(); + oRet = xt.json.processFragment(responseJSON, seq, oRet, oRequest); + } else { + } + } + } + + + + var obj = {}; + obj.fullName = 'Response Complete'; + obj.sequence = seq; + obj.request = oRequest; + obj.context = oRequest.context; + obj.cmd = 'rcmplt'; + xt.queue.push(xx.response, obj); + + // do not re-start the queue if a timeout is set + if (null == xx.response.timeout) + xt.queue.process(xx.response); + } + + swf.settings.upload_complete_handler = function (oFile) { + + var qFile = this.customSettings.currentFile; + xajax.ext.SWFupload.removeFile(qFile.QueueId, qFile.id, true); + + if (!xajax.ext.SWFupload.request.getFileFromQueue(oRequest)) { + if ('function' == typeof oRequest.onUploadComplete) oRequest.onUploadComplete(); + return; + } + + xajax.ext.SWFupload.request.submitRequest(oRequest); + } + + + swf.settings.upload_start_handler = function (oFile) { + if ('function' == typeof this.old_upload_start_handler) this.old_upload_start_handler(oFile); + oRequest.startTime = new Date(); + + } + swf.settings.upload_progress_handler = function (oFile, bytesLoaded, bytesTotal) { + + upload = {}; + upload.received = bytesLoaded; + upload.total = bytesTotal; + upload.state = "uploading"; + var reqTime = new Date(); + + upload.lastbytes = oRequest.lastbytes; + upload.now = reqTime.getTime() / 1000; + upload.start = oRequest.startTime.getTime() / 1000; + + var step = upload.received / (upload.total / 100); + var progressbar = xajax.$('SWFup_progress_' + oFile.id); + var w = Math.round(220 * step / 100); + progressbar.style.width = w + 'px'; + + var progress = xajax.$("swf_queued_filesize_" + oFile.id); + var elapsed = upload.now - upload.start; + var rate = xajax.ext.SWFupload.tools.formatBytes(upload.received / elapsed).toString() + '/s'; + progress.innerHTML = "" + rate + " " + xajax.ext.SWFupload.tools.formatBytes(upload.received) + "/" + xajax.ext.SWFupload.tools.formatBytes(upload.total); + oRequest.lastbytes = upload.received; + + } + + swf.settings.upload_error_handler = function (file, errorCode, message) { + // Skipe error when a file is removed from queue (abort) + if (-280 == errorCode) return; + if (file == null) { + fileName = ''; + } else { + fileName = file.name; + } + + alert("Error Code: " + errorCode + ", File name: " + fileName + ", Message: " + message); + }; + swf.startUpload(swf.customSettings.currentFile.id); + return; + } + return xajax.ext.SWFupload.bak.submitRequest(oRequest); +} + + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools.queueFile + arguments: oFile,QueueId,QueueContainer + + */ +xajax.ext.SWFupload.tools.queueFile = function (oFile, name, QueueId, QueueContainer) { + + this.id = oFile.id; + this.name = name; + this.QueueId = QueueId; + + var container = document.createElement('div'); + container.id = "SWFup_" + this.id; + container.className = "swf_queued_file"; + + this.elm = container; + + var remove = document.createElement('div'); + remove.className = "swf_queued_file_remove"; + remove.innerHTML = " "; + + var id = this.id; + var QueueId = this.QueueId; + remove.onclick = function () { + xajax.ext.SWFupload.removeFile(QueueId, id); + } + container.appendChild(remove); + + var label = document.createElement('div'); + label.className = "swf_queued_filename"; + label.innerHTML = oFile.name; + container.appendChild(label); + + var progress_container = document.createElement('div'); + progress_container.className = "swf_queued_file_progress_container"; + container.appendChild(progress_container); + + + var progress = document.createElement('div'); + progress.className = "swf_queued_file_progress_bar"; + progress.style.width = '1px'; + progress.id = 'SWFup_progress_' + oFile.id; + progress_container.appendChild(progress); + + + var fSize = document.createElement('div'); + fSize.className = "swf_queued_filesize"; + fSize.id = "swf_queued_filesize_" + this.id; + fSize.innerHTML = xajax.ext.SWFupload.tools.formatBytes(oFile.size); + container.appendChild(fSize); + + var fClear = document.createElement('div'); + fClear.style.clear = 'both'; + container.appendChild(fClear); + QueueContainer.appendChild(container); + + this.container = container; + this.oFile = oFile; + + this.destroy = function () { + QueueContainer.removeChild(container); + } + + return; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools.fileQueue + arguments: id [integer],child [object], parent [object], multiple [bool] + + parses the form for fields + */ + +xajax.ext.SWFupload.tools.fileQueue = function (id, child, parent, config, multiple) { + + + this.id = id; + var config = 'object' == typeof config ? xajax.ext.SWFupload.tools.mergeObj(xajax.ext.SWFupload.settings, config) : xajax.ext.SWFupload.settings; + this.queued = 0; + this.files = {}; + this.queue = null; + + this.getConfig = function () { + return config; + } + + var tmpName = child.name; + var container = document.createElement('div'); + container.id = 'SWFbuttonContainer_' + tmpName; + container.className = 'swf_browse_button'; + parent.appendChild(container); + + + var container2 = document.createElement('div'); + container2.id = 'SWFbutton_' + tmpName; + container.appendChild(container2); + + parent.removeChild(child); + + var oQueue = this; + if (true === multiple) { + config.button_action = SWFUpload.BUTTON_ACTION.SELECT_FILES; + } else { + config.button_action = SWFUpload.BUTTON_ACTION.SELECT_FILE; + + } + + var QueueContainer = document.createElement('div'); + QueueContainer.id = 'SWFqueue_' + this.id; + QueueContainer.className = 'swf_queue_container'; + parent.appendChild(QueueContainer); + + config.button_placeholder_id = container2.id; + + var foo = this; + + var fieldname = child.name; + this.addFile = function (oFile) { + foo.files[oFile.id] = new xajax.ext.SWFupload.tools.queueFile(oFile, fieldname, foo.id, QueueContainer); + foo.queued++; + if (foo.queued == config.file_queue_limit) foo.swf.setButtonDisabled(true); + } + + this.getFile = function (FileId) { + if ("undefined" != typeof FileId) return foo.files[FileId]; + for (a in foo.files) return foo.files[a]; + return false; + } + + this.purge = function (d) { + var a = d.attributes, i, l, n; + if (a) { + l = a.length; + for (i = 0; i < l; i += 1) { + n = a[i].name; + if (typeof d[n] === 'function') { + d[n] = null; + } + } + } + a = d.childNodes; + if (a) { + l = a.length; + for (i = 0; i < l; i += 1) { + this.purge(d.childNodes[i]); + } + } + } + + this.removeFile = function (FileId, finished) { + + foo.swf.cancelUpload(FileId); + + foo.queued--; + if (foo.queued <= config.file_queue_limit) foo.swf.setButtonDisabled(false); + var filediv = xajax.$("SWFup_" + foo.files[FileId].id); + filediv.className = true === finished ? 'swf_queued_file_finished' : 'swf_queued_file_removed'; + setTimeout(function () { + xajax.ext.SWFupload.tools.FadeOut(filediv, 100); + }, xajax.ext.SWFupload.config.FadeTimeOut); + + foo.files[FileId] = null; + delete foo.files[FileId]; + } + this.destroy = function () { + + this.swf.destroy(); + delete(this.swf); + for (a in foo.files) { + foo.files[a].destroy(); + delete (foo.files[a]); + } + foo.queued = 0; + delete(foo); + } + this.fileQueueError = function (swf, code, msg) { + if (-110 == code) { + msg = "Die gewählte Datei ist zu groß!"; + alert(msg); + } + } + + this.getSWF = function () { + return this.swf; + + } + + config.file_queued_handler = this.addFile; + config.file_queue_error_handler = this.fileQueueError; + + this.swf = new SWFUpload(config); + +} +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools._parseFields + arguments: children [array],parent [object], config [object], multiple [bool] + + parses the form for fields + */ + + +xajax.ext.SWFupload.tools._parseFields = function (children, parent, config, multiple) { + var result = {}; + var iLen = children.length; + for (var i = 0; i < iLen; ++i) { + var child = children[i]; + if ('undefined' != typeof child.childNodes) + var res2 = xajax.ext.SWFupload.tools._parseFields(child.childNodes, child, config, multiple); + result = xajax.ext.SWFupload.tools.mergeObj(result, res2); + if (child.name) { + if ('file' == child.type) { + result[child.name] = xajax.ext.SWFupload.addQueue(child, parent, config, multiple); + } + } + } + return result; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools.transForm + arguments: form_id [integer] ,config [object] ,multiple [bool] + + transforms the all fields of the given form into fileQueue instances + */ + +xajax.ext.SWFupload.tools.transForm = function (form_id, config, multiple) { + var oForm = xajax.$(form_id); + if (oForm) + if (oForm.childNodes) { + var fields = xajax.ext.SWFupload.tools._parseFields(oForm.childNodes, oForm, config, multiple); + xajax.ext.SWFupload.forms[form_id] = fields; + } + return; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ + +/* + function: xajax.ext.SWFupload.tools.transField + arguments: field_id [integer] ,config [object] ,multiple [bool] + + transforms the given field into a fileQueue instance + */ + +xajax.ext.SWFupload.tools.transField = function (field_id, config, multiple) { + try { + var oField = xajax.$(field_id); + if ('undefined' != typeof oField) return xajax.ext.SWFupload.fields[field_id] = xajax.ext.SWFupload.addQueue(oField, oField.parentNode, config, multiple); + + } catch (ex) { + } + return; +} + + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools.destroyForm + arguments: form_id [integer] + + destroys the given form + */ + +xajax.ext.SWFupload.tools.destroyForm = function (form_id) { + if ("undefined" == typeof xajax.ext.SWFupload.forms[form_id]) return; + for (a in xajax.ext.SWFupload.forms[form_id]) { + var key = xajax.ext.SWFupload.forms[form_id][a]; + xajax.ext.SWFupload.queues[key].destroy(); + delete xajax.ext.SWFupload.queues[key]; + } + delete xajax.ext.SWFupload.forms[form_id]; + return; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools.destroyField + arguments: field_id [integer] + + destroys the given field + */ + +xajax.ext.SWFupload.tools.destroyField = function (field_id) { + if ("undefined" == typeof xajax.ext.SWFupload.fields[field_id]) return; + var key = xajax.ext.SWFupload.fields[field_id]; + xajax.ext.SWFupload.queues[key].destroy(); + delete(xajax.ext.SWFupload.queues[key]); + delete xajax.ext.SWFupload.fields[field_id]; + + return true; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ + +/* + function: xajax.ext.SWFupload.tools.FadeOut + arguments: elm [object], opacity [integer] + + fades a div + */ + +xajax.ext.SWFupload.tools.FadeOut = function (elm, opacity) { + var reduceOpacityBy = 15; + var rate = 40; + if (opacity > 0) { + opacity -= reduceOpacityBy; + if (opacity < 0) { + opacity = 0; + } + + if (elm.filters) { + try { + elm.filters.item("DXImageTransform.Microsoft.Alpha").opacity = opacity; + } catch (e) { + // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. + elm.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + opacity + ")"; + } + } else { + elm.style.opacity = opacity / 100; + } + } + + if (opacity > 0) { + var oSelf = this; + setTimeout(function () { + xajax.ext.SWFupload.tools.FadeOut(elm, opacity); + }, rate); + } else { + var parent = elm.parentNode; + parent.removeChild(elm); + } +} + + +/* ------------------------------------------------------------------------------------------------------------------------ */ + +/* + function: xajax.ext.SWFupload.tools.formatBytes + arguments: bytes [integer] + + returns string with formatted size (kB / MB) + */ + +xajax.ext.SWFupload.tools.formatBytes = function (bytes) { + + var ret = {}; + if (bytes / 1204 < 1024) { + return (Math.round(bytes / 1024 * 100) / 100).toString() + " kB"; + } else { + return (Math.round(bytes / 1024 / 1024 * 100) / 100).toString() + " MB"; + } + return ret; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ + +/* + function: xajax.ext.SWFupload.tools.mergeObj + arguments: n objects + + Merges all objects and returns a single object. + Newrt keys override existing keys. + + */ + +xajax.ext.SWFupload.tools.mergeObj = function () { + if ('object' != typeof arguments) return; + + var res = {}; + var len = arguments.length; + for (var i = 0; i < len; i++) { + var obj = arguments[i]; + for (a in obj) { + res[a] = obj[a]; + } + } + return res; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.ext.SWFupload.tools.getId + arguments: + + returns a 'unique' (rand) id + */ + +xajax.ext.SWFupload.tools.getId = function () { + var pid_str = ""; + for (i = 0; i <= 3; i++) { + var pid = 0; + pid = Math.random(); + while (Math.ceil(pid).toString().length < 8) { + pid *= 10; + } + pid = Math.ceil(pid).toString(); + pid_str = pid_str + pid.toString(); + } + return pid_str; +} + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.command.handler.register('SWFup_dfi') + arguments: object + + xajax response command for ext.SWFupload.tools.destroyField + */ +xajax.command.handler.register('SWFup_dfi', function (args) { + args.cmdFullName = 'ext.SWFupload.tools.destroyField'; + xajax.ext.SWFupload.tools.destroyField(args.id); + return true; +}); + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.command.handler.register('SWFup_dfo') + arguments: object + + xajax response command for ext.SWFupload.tools.destroyForm + */ + +xajax.command.handler.register('SWFup_dfo', function (args) { + args.cmdFullName = 'ext.SWFupload.tools.destroyForm'; + xajax.ext.SWFupload.tools.destroyForm(args.id); + return true; +}); + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.command.handler.register('SWFup_tfi'I + arguments: object + + xajax response command for ext.SWFupload.tools.transField + */ + +xajax.command.handler.register('SWFup_tfi', function (args) { + args.cmdFullName = 'ext.SWFupload.tools.transField'; + +// if ("string" == typeof args.data.config.upload_complete_handler) { +// try { +// eval("var foo = "+args.data.config.upload_complete_handler); +// args.data.config.upload_complete_handler = foo; +// } catch(ex) {delete(args.data.config.upload_complete_handler);} +// } + + if ("string" == typeof args.data.config.upload_success_handler) { + try { + eval("var foo = " + args.data.config.upload_success_handler); + args.data.config.upload_success_handler = foo; + } catch (ex) { + delete(args.data.config.upload_success_handler); + } + } + + xajax.ext.SWFupload.tools.transField(args.id, args.data.config, args.data.multi); + return true; +}); + +/* ------------------------------------------------------------------------------------------------------------------------ */ +/* + function: xajax.command.handler.register('SWFup_tfo'] + arguments: object + + xajax response command for ext.SWFupload.tools.transForm + */ +xajax.command.handler.register('SWFup_tfo', function (args) { + try { + args.cmdFullName = 'ext.SWFupload.tools.transForm'; +// if ("string" == typeof args.data.config.upload_complete_handler) +// { +// try { +// eval("var foo = "+args.data.config.upload_complete_handler); +// args.data.config.upload_complete_handler = foo; +// } catch(ex) {delete(args.data.config.upload_complete_handler);} +// } + + if ("string" == typeof args.data.config.upload_success_handler) { + try { + eval("var foo = " + args.data.config.upload_success_handler); + args.data.config.upload_success_handler = foo; + } catch (ex) { + delete(args.data.config.upload_success_handler); + } + } + xajax.ext.SWFupload.tools.transForm(args.id, args.data.config, args.data.multi); + + } catch (ex) { + + } + + + return true; + + +}); +/* ------------------------------------------------------------------------------------------------------------------------ */ + + +xajax.ext.SWFupload.bak = {}; +xajax.ext.SWFupload.bak.prepareRequest = xajax.prepareRequest; +xajax.ext.SWFupload.bak.submitRequest = xajax.submitRequest; +xajax.ext.SWFupload.bak.responseProcessor = xajax.responseProcessor; +xajax.ext.SWFupload.bak.processParameters = xajax.processParameters; + +xajax.prepareRequest = xajax.ext.SWFupload.request.prepareRequest; +xajax.submitRequest = xajax.ext.SWFupload.request.submitRequest; +xajax.processParameters = xajax.ext.SWFupload.request.processParameters; + + +/* ------------------------------------------------------------------------------------------------------------------------ */ + + +// ------------------------------------------------------------------------------------------------------------------------------------- +/* + + Function: DOMParser + + Prototype DomParser for IE/Opera + + */ +if (typeof DOMParser == "undefined") { + DOMParser = function () { + } + + DOMParser.prototype.parseFromString = function (str, contentType) { + if (typeof ActiveXObject != "undefined") { + var d = new ActiveXObject("Microsoft.XMLDOM"); + d.loadXML(str); + return d; + } else if (typeof XMLHttpRequest != "undefined") { + var req = new XMLHttpRequest; + req.open("GET", "data:" + (contentType || "application/xml") + + ";charset=utf-8," + encodeURIComponent(str), false); + if (req.overrideMimeType) { + req.overrideMimeType(contentType); + } + req.send(null); + return req.responseXML; + } + } +} diff --git a/www/include/xajax/xajax_plugins/response/swfupload/swfupload_uncompressed.js b/www/include/xajax/xajax_plugins/response/swfupload/swfupload_uncompressed.js new file mode 100644 index 00000000..97fd999b --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/swfupload/swfupload_uncompressed.js @@ -0,0 +1,946 @@ +/** + * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + * + * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + * + * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + */ + + +/* ******************* */ +/* Constructor & Init */ +/* ******************* */ +var SWFUpload; + +if (SWFUpload == undefined) { + SWFUpload = function (settings) { + this.initSWFUpload(settings); + }; +} + +SWFUpload.prototype.initSWFUpload = function (settings) { + try { + this.customSettings = {}; // A container where developers can place their own settings associated with this instance. + this.settings = settings; + this.eventQueue = []; + this.movieName = "SWFUpload_" + SWFUpload.movieCount++; + this.movieElement = null; + + + // Setup global control tracking + SWFUpload.instances[this.movieName] = this; + + // Load the settings. Load the Flash movie. + this.initSettings(); + this.loadFlash(); + this.displayDebugInfo(); + } catch (ex) { + delete SWFUpload.instances[this.movieName]; + throw ex; + } +}; + +/* *************** */ +/* Static Members */ +/* *************** */ +SWFUpload.instances = {}; +SWFUpload.movieCount = 0; +SWFUpload.version = "2.2.0 Beta 3"; +SWFUpload.QUEUE_ERROR = { + QUEUE_LIMIT_EXCEEDED : -100, + FILE_EXCEEDS_SIZE_LIMIT : -110, + ZERO_BYTE_FILE : -120, + INVALID_FILETYPE : -130 +}; +SWFUpload.UPLOAD_ERROR = { + HTTP_ERROR : -200, + MISSING_UPLOAD_URL : -210, + IO_ERROR : -220, + SECURITY_ERROR : -230, + UPLOAD_LIMIT_EXCEEDED : -240, + UPLOAD_FAILED : -250, + SPECIFIED_FILE_ID_NOT_FOUND : -260, + FILE_VALIDATION_FAILED : -270, + FILE_CANCELLED : -280, + UPLOAD_STOPPED : -290 +}; +SWFUpload.FILE_STATUS = { + QUEUED : -1, + IN_PROGRESS : -2, + ERROR : -3, + COMPLETE : -4, + CANCELLED : -5 +}; +SWFUpload.BUTTON_ACTION = { + SELECT_FILE : -100, + SELECT_FILES : -110, + START_UPLOAD : -120 +}; +SWFUpload.CURSOR = { + ARROW : -1, + HAND : -2 +}; +SWFUpload.WINDOW_MODE = { + WINDOW : "window", + TRANSPARENT : "transparent", + OPAQUE : "opaque" +}; + +/* ******************** */ +/* Instance Members */ +/* ******************** */ + +// Private: initSettings ensures that all the +// settings are set, getting a default value if one was not assigned. +SWFUpload.prototype.initSettings = function () { + this.ensureDefault = function (settingName, defaultValue) { + this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName]; + }; + + // Upload backend settings + this.ensureDefault("upload_url", ""); + this.ensureDefault("file_post_name", "Filedata"); + this.ensureDefault("post_params", {}); + this.ensureDefault("use_query_string", false); + this.ensureDefault("requeue_on_error", false); + this.ensureDefault("http_success", []); + + // File Settings + this.ensureDefault("file_types", "*.*"); + this.ensureDefault("file_types_description", "All Files"); + this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited" + this.ensureDefault("file_upload_limit", 0); + this.ensureDefault("file_queue_limit", 0); + + // Flash Settings + this.ensureDefault("flash_url", "swfupload.swf"); + this.ensureDefault("prevent_swf_caching", true); + + // Button Settings + this.ensureDefault("button_image_url", ""); + this.ensureDefault("button_width", 1); + this.ensureDefault("button_height", 1); + this.ensureDefault("button_text", ""); + this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;"); + this.ensureDefault("button_text_top_padding", 0); + this.ensureDefault("button_text_left_padding", 0); + this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES); + this.ensureDefault("button_disabled", false); + this.ensureDefault("button_placeholder_id", null); + this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW); + this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW); + + // Debug Settings + this.ensureDefault("debug", false); + this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API + + // Event Handlers + this.settings.return_upload_start_handler = this.returnUploadStart; + this.ensureDefault("swfupload_loaded_handler", null); + this.ensureDefault("file_dialog_start_handler", null); + this.ensureDefault("file_queued_handler", null); + this.ensureDefault("file_queue_error_handler", null); + this.ensureDefault("file_dialog_complete_handler", null); + + this.ensureDefault("upload_start_handler", null); + this.ensureDefault("upload_progress_handler", null); + this.ensureDefault("upload_error_handler", null); + this.ensureDefault("upload_success_handler", null); + this.ensureDefault("upload_complete_handler", null); + + this.ensureDefault("debug_handler", this.debugMessage); + + this.ensureDefault("custom_settings", {}); + + // Other settings + this.customSettings = this.settings.custom_settings; + + // Update the flash url if needed + if (this.settings.prevent_swf_caching) { + this.settings.flash_url = this.settings.flash_url + "?swfuploadrnd=" + Math.floor(Math.random() * 999999999); + } + + delete this.ensureDefault; +}; + +SWFUpload.prototype.loadFlash = function () { + if (this.settings.button_placeholder_id !== "") { + this.replaceWithFlash(); + } else { + this.appendFlash(); + } +}; + +// Private: appendFlash gets the HTML tag for the Flash +// It then appends the flash to the body +SWFUpload.prototype.appendFlash = function () { + var targetElement, container; + + // Make sure an element with the ID we are going to use doesn't already exist + if (document.getElementById(this.movieName) !== null) { + throw "ID " + this.movieName + " is already in use. The Flash Object could not be added"; + } + + // Get the body tag where we will be adding the flash movie + targetElement = document.getElementsByTagName("body")[0]; + + if (targetElement == undefined) { + throw "Could not find the 'body' element."; + } + + // Append the container and load the flash + container = document.createElement("div"); + container.style.width = "1px"; + container.style.height = "1px"; + container.style.overflow = "hidden"; + + targetElement.appendChild(container); + container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers) + + // Fix IE Flash/Form bug + if (window[this.movieName] == undefined) { + window[this.movieName] = this.getMovieElement(); + } + + +}; + +// Private: replaceWithFlash replaces the button_placeholder element with the flash movie. +SWFUpload.prototype.replaceWithFlash = function () { + var targetElement, tempParent; + + // Make sure an element with the ID we are going to use doesn't already exist + if (document.getElementById(this.movieName) !== null) { + throw "ID " + this.movieName + " is already in use. The Flash Object could not be added"; + } + + // Get the element where we will be placing the flash movie + targetElement = document.getElementById(this.settings.button_placeholder_id); + + if (targetElement == undefined) { + throw "Could not find the placeholder element."; + } + + // Append the container and load the flash + tempParent = document.createElement("div"); + tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers) + targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement); + + // Fix IE Flash/Form bug + if (window[this.movieName] == undefined) { + window[this.movieName] = this.getMovieElement(); + } + +}; + +// Private: getFlashHTML generates the object tag needed to embed the flash in to the document +SWFUpload.prototype.getFlashHTML = function () { + // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay + return ['', + '', + '', + '', + '', + '', + '', + ''].join(""); +}; + +// Private: getFlashVars builds the parameter string that will be passed +// to flash in the flashvars param. +SWFUpload.prototype.getFlashVars = function () { + // Build a string from the post param object + var paramString = this.buildParamString(); + var httpSuccessString = this.settings.http_success.join(","); + + // Build the parameter string + return ["movieName=", encodeURIComponent(this.movieName), + "&uploadURL=", encodeURIComponent(this.settings.upload_url), + "&useQueryString=", encodeURIComponent(this.settings.use_query_string), + "&requeueOnError=", encodeURIComponent(this.settings.requeue_on_error), + "&httpSuccess=", encodeURIComponent(httpSuccessString), + "&params=", encodeURIComponent(paramString), + "&filePostName=", encodeURIComponent(this.settings.file_post_name), + "&fileTypes=", encodeURIComponent(this.settings.file_types), + "&fileTypesDescription=", encodeURIComponent(this.settings.file_types_description), + "&fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit), + "&fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit), + "&fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit), + "&debugEnabled=", encodeURIComponent(this.settings.debug_enabled), + "&buttonImageURL=", encodeURIComponent(this.settings.button_image_url), + "&buttonWidth=", encodeURIComponent(this.settings.button_width), + "&buttonHeight=", encodeURIComponent(this.settings.button_height), + "&buttonText=", encodeURIComponent(this.settings.button_text), + "&buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding), + "&buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding), + "&buttonTextStyle=", encodeURIComponent(this.settings.button_text_style), + "&buttonAction=", encodeURIComponent(this.settings.button_action), + "&buttonDisabled=", encodeURIComponent(this.settings.button_disabled), + "&buttonCursor=", encodeURIComponent(this.settings.button_cursor) + ].join(""); +}; + +// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload +// The element is cached after the first lookup +SWFUpload.prototype.getMovieElement = function () { + if (this.movieElement == undefined) { + this.movieElement = document.getElementById(this.movieName); + } + + if (this.movieElement === null) { + throw "Could not find Flash element"; + } + + return this.movieElement; +}; + +// Private: buildParamString takes the name/value pairs in the post_params setting object +// and joins them up in to a string formatted "name=value&name=value" +SWFUpload.prototype.buildParamString = function () { + var postParams = this.settings.post_params; + var paramStringPairs = []; + + if (typeof(postParams) === "object") { + for (var name in postParams) { + if (postParams.hasOwnProperty(name)) { + paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString())); + } + } + } + + return paramStringPairs.join("&"); +}; + +// Public: Used to remove a SWFUpload instance from the page. This method strives to remove +// all references to the SWF, and other objects so memory is properly freed. +// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state. +// Credits: Major improvements provided by steffen +SWFUpload.prototype.destroy = function () { + try { + // Make sure Flash is done before we try to remove it + this.cancelUpload(null, false); +; + // Remove the SWFUpload DOM nodes + var movieElement = null; + movieElement = this.getMovieElement(); + + if (movieElement) { + // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround) + for (var i in movieElement) { + try { + if (typeof(movieElement[i]) === "function") { + movieElement[i] = null; + } + } catch (ex1) {} + } + + // Remove the Movie Element from the page + try { + movieElement.parentNode.removeChild(movieElement); + } catch (ex) {} + } + + + // Remove IE form fix reference + window[this.movieName] = null; + + // Destroy other references + SWFUpload.instances[this.movieName] = null; + delete SWFUpload.instances[this.movieName]; + + this.movieElement = null; + this.settings = null; + this.customSettings = null; + this.eventQueue = null; + this.movieName = null; + + + return true; + } catch (ex1) { + alert(ex); + return false; + } +}; + +// Public: displayDebugInfo prints out settings and configuration +// information about this SWFUpload instance. +// This function (and any references to it) can be deleted when placing +// SWFUpload in production. +SWFUpload.prototype.displayDebugInfo = function () { + this.debug( + [ + "---SWFUpload Instance Info---\n", + "Version: ", SWFUpload.version, "\n", + "Movie Name: ", this.movieName, "\n", + "Settings:\n", + "\t", "upload_url: ", this.settings.upload_url, "\n", + "\t", "flash_url: ", this.settings.flash_url, "\n", + "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n", + "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n", + "\t", "http_success: ", this.settings.http_success.join(", "), "\n", + "\t", "file_post_name: ", this.settings.file_post_name, "\n", + "\t", "post_params: ", this.settings.post_params.toString(), "\n", + "\t", "file_types: ", this.settings.file_types, "\n", + "\t", "file_types_description: ", this.settings.file_types_description, "\n", + "\t", "file_size_limit: ", this.settings.file_size_limit, "\n", + "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n", + "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n", + "\t", "debug: ", this.settings.debug.toString(), "\n", + + "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n", + + "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n", + "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n", + "\t", "button_width: ", this.settings.button_width.toString(), "\n", + "\t", "button_height: ", this.settings.button_height.toString(), "\n", + "\t", "button_text: ", this.settings.button_text.toString(), "\n", + "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n", + "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n", + "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n", + "\t", "button_action: ", this.settings.button_action.toString(), "\n", + "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n", + + "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n", + "Event Handlers:\n", + "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n", + "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n", + "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n", + "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n", + "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n", + "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n", + "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n", + "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n", + "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n", + "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n" + ].join("") + ); +}; + +/* Note: addSetting and getSetting are no longer used by SWFUpload but are included + the maintain v2 API compatibility +*/ +// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used. +SWFUpload.prototype.addSetting = function (name, value, default_value) { + if (value == undefined) { + return (this.settings[name] = default_value); + } else { + return (this.settings[name] = value); + } +}; + +// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found. +SWFUpload.prototype.getSetting = function (name) { + if (this.settings[name] != undefined) { + return this.settings[name]; + } + + return ""; +}; + + + +// Private: callFlash handles function calls made to the Flash element. +// Calls are made with a setTimeout for some functions to work around +// bugs in the ExternalInterface library. +SWFUpload.prototype.callFlash = function (functionName, argumentArray) { + argumentArray = argumentArray || []; + + var movieElement = this.getMovieElement(); + var returnValue, returnString; + + // Flash's method if calling ExternalInterface methods (code adapted from MooTools). + try { + returnString = movieElement.CallFunction('' + __flash__argumentsToXML(argumentArray, 0) + ''); + returnValue = eval(returnString); + } catch (ex) { + throw "Call to " + functionName + " failed"; + } + + // Unescape file post param values + if (returnValue != undefined && typeof returnValue.post === "object") { + returnValue = this.unescapeFilePostParams(returnValue); + } + + return returnValue; +}; + + +/* ***************************** + -- Flash control methods -- + Your UI should use these + to operate SWFUpload + ***************************** */ + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFile causes a File Selection Dialog window to appear. This +// dialog only allows 1 file to be selected. +SWFUpload.prototype.selectFile = function () { + this.callFlash("SelectFile"); +}; + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFiles causes a File Selection Dialog window to appear/ This +// dialog allows the user to select any number of files +// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names. +// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around +// for this bug. +SWFUpload.prototype.selectFiles = function () { + this.callFlash("SelectFiles"); +}; + + +// Public: startUpload starts uploading the first file in the queue unless +// the optional parameter 'fileID' specifies the ID +SWFUpload.prototype.startUpload = function (fileID) { + this.callFlash("StartUpload", [fileID]); +}; + +// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index. +// If you do not specify a fileID the current uploading file or first file in the queue is cancelled. +// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter. +SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) { + if (triggerErrorEvent !== false) { + triggerErrorEvent = true; + } + this.callFlash("CancelUpload", [fileID, triggerErrorEvent]); +}; + +// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue. +// If nothing is currently uploading then nothing happens. +SWFUpload.prototype.stopUpload = function () { + this.callFlash("StopUpload"); +}; + +/* ************************ + * Settings methods + * These methods change the SWFUpload settings. + * SWFUpload settings should not be changed directly on the settings object + * since many of the settings need to be passed to Flash in order to take + * effect. + * *********************** */ + +// Public: getStats gets the file statistics object. +SWFUpload.prototype.getStats = function () { + return this.callFlash("GetStats"); +}; + +// Public: setStats changes the SWFUpload statistics. You shouldn't need to +// change the statistics but you can. Changing the statistics does not +// affect SWFUpload accept for the successful_uploads count which is used +// by the upload_limit setting to determine how many files the user may upload. +SWFUpload.prototype.setStats = function (statsObject) { + this.callFlash("SetStats", [statsObject]); +}; + +// Public: getFile retrieves a File object by ID or Index. If the file is +// not found then 'null' is returned. +SWFUpload.prototype.getFile = function (fileID) { + if (typeof(fileID) === "number") { + return this.callFlash("GetFileByIndex", [fileID]); + } else { + return this.callFlash("GetFile", [fileID]); + } +}; + +// Public: addFileParam sets a name/value pair that will be posted with the +// file specified by the Files ID. If the name already exists then the +// exiting value will be overwritten. +SWFUpload.prototype.addFileParam = function (fileID, name, value) { + return this.callFlash("AddFileParam", [fileID, name, value]); +}; + +// Public: removeFileParam removes a previously set (by addFileParam) name/value +// pair from the specified file. +SWFUpload.prototype.removeFileParam = function (fileID, name) { + this.callFlash("RemoveFileParam", [fileID, name]); +}; + +// Public: setUploadUrl changes the upload_url setting. +SWFUpload.prototype.setUploadURL = function (url) { + this.settings.upload_url = url.toString(); + this.callFlash("SetUploadURL", [url]); +}; + +// Public: setPostParams changes the post_params setting +SWFUpload.prototype.setPostParams = function (paramsObject) { + this.settings.post_params = paramsObject; + this.callFlash("SetPostParams", [paramsObject]); +}; + +// Public: addPostParam adds post name/value pair. Each name can have only one value. +SWFUpload.prototype.addPostParam = function (name, value) { + this.settings.post_params[name] = value; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: removePostParam deletes post name/value pair. +SWFUpload.prototype.removePostParam = function (name) { + delete this.settings.post_params[name]; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: setFileTypes changes the file_types setting and the file_types_description setting +SWFUpload.prototype.setFileTypes = function (types, description) { + this.settings.file_types = types; + this.settings.file_types_description = description; + this.callFlash("SetFileTypes", [types, description]); +}; + +// Public: setFileSizeLimit changes the file_size_limit setting +SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) { + this.settings.file_size_limit = fileSizeLimit; + this.callFlash("SetFileSizeLimit", [fileSizeLimit]); +}; + +// Public: setFileUploadLimit changes the file_upload_limit setting +SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) { + this.settings.file_upload_limit = fileUploadLimit; + this.callFlash("SetFileUploadLimit", [fileUploadLimit]); +}; + +// Public: setFileQueueLimit changes the file_queue_limit setting +SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) { + this.settings.file_queue_limit = fileQueueLimit; + this.callFlash("SetFileQueueLimit", [fileQueueLimit]); +}; + +// Public: setFilePostName changes the file_post_name setting +SWFUpload.prototype.setFilePostName = function (filePostName) { + this.settings.file_post_name = filePostName; + this.callFlash("SetFilePostName", [filePostName]); +}; + +// Public: setUseQueryString changes the use_query_string setting +SWFUpload.prototype.setUseQueryString = function (useQueryString) { + this.settings.use_query_string = useQueryString; + this.callFlash("SetUseQueryString", [useQueryString]); +}; + +// Public: setRequeueOnError changes the requeue_on_error setting +SWFUpload.prototype.setRequeueOnError = function (requeueOnError) { + this.settings.requeue_on_error = requeueOnError; + this.callFlash("SetRequeueOnError", [requeueOnError]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) { + if (typeof http_status_codes === "string") { + http_status_codes = http_status_codes.replace(" ", "").split(","); + } + + this.settings.http_success = http_status_codes; + this.callFlash("SetHTTPSuccess", [http_status_codes]); +}; + + +// Public: setDebugEnabled changes the debug_enabled setting +SWFUpload.prototype.setDebugEnabled = function (debugEnabled) { + this.settings.debug_enabled = debugEnabled; + this.callFlash("SetDebugEnabled", [debugEnabled]); +}; + +// Public: setButtonImageURL loads a button image sprite +SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) { + if (buttonImageURL == undefined) { + buttonImageURL = ""; + } + + this.settings.button_image_url = buttonImageURL; + this.callFlash("SetButtonImageURL", [buttonImageURL]); +}; + +// Public: setButtonDimensions resizes the Flash Movie and button +SWFUpload.prototype.setButtonDimensions = function (width, height) { + this.settings.button_width = width; + this.settings.button_height = height; + + var movie = this.getMovieElement(); + if (movie != undefined) { + movie.style.width = width + "px"; + movie.style.height = height + "px"; + } + + this.callFlash("SetButtonDimensions", [width, height]); +}; +// Public: setButtonText Changes the text overlaid on the button +SWFUpload.prototype.setButtonText = function (html) { + this.settings.button_text = html; + this.callFlash("SetButtonText", [html]); +}; +// Public: setButtonTextPadding changes the top and left padding of the text overlay +SWFUpload.prototype.setButtonTextPadding = function (left, top) { + this.settings.button_text_top_padding = top; + this.settings.button_text_left_padding = left; + this.callFlash("SetButtonTextPadding", [left, top]); +}; + +// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button +SWFUpload.prototype.setButtonTextStyle = function (css) { + this.settings.button_text_style = css; + this.callFlash("SetButtonTextStyle", [css]); +}; +// Public: setButtonDisabled disables/enables the button +SWFUpload.prototype.setButtonDisabled = function (isDisabled) { + this.settings.button_disabled = isDisabled; + this.callFlash("SetButtonDisabled", [isDisabled]); +}; +// Public: setButtonAction sets the action that occurs when the button is clicked +SWFUpload.prototype.setButtonAction = function (buttonAction) { + this.settings.button_action = buttonAction; + this.callFlash("SetButtonAction", [buttonAction]); +}; + +// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button +SWFUpload.prototype.setButtonCursor = function (cursor) { + this.settings.button_cursor = cursor; + this.callFlash("SetButtonCursor", [cursor]); +}; + +/* ******************************* + Flash Event Interfaces + These functions are used by Flash to trigger the various + events. + + All these functions a Private. + + Because the ExternalInterface library is buggy the event calls + are added to a queue and the queue then executed by a setTimeout. + This ensures that events are executed in a determinate order and that + the ExternalInterface bugs are avoided. +******************************* */ + +SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + if (argumentArray == undefined) { + argumentArray = []; + } else if (!(argumentArray instanceof Array)) { + argumentArray = [argumentArray]; + } + + var self = this; + if (typeof this.settings[handlerName] === "function") { + // Queue the event + this.eventQueue.push(function () { + this.settings[handlerName].apply(this, argumentArray); + }); + + // Execute the next queued event + setTimeout(function () { + self.executeNextEvent(); + }, 0); + + } else if (this.settings[handlerName] !== null) { + throw "Event handler " + handlerName + " is unknown or is not a function"; + } +}; + +// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout +// we must queue them in order to garentee that they are executed in order. +SWFUpload.prototype.executeNextEvent = function () { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + var f = this.eventQueue ? this.eventQueue.shift() : null; + if (typeof(f) === "function") { + f.apply(this); + } +}; + +// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have +// properties that contain characters that are not valid for JavaScript identifiers. To work around this +// the Flash Component escapes the parameter names and we must unescape again before passing them along. +SWFUpload.prototype.unescapeFilePostParams = function (file) { + var reg = /[$]([0-9a-f]{4})/i; + var unescapedPost = {}; + var uk; + + if (file != undefined) { + for (var k in file.post) { + if (file.post.hasOwnProperty(k)) { + uk = k; + var match; + while ((match = reg.exec(uk)) !== null) { + uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16))); + } + unescapedPost[uk] = file.post[k]; + } + } + + file.post = unescapedPost; + } + + return file; +}; + +SWFUpload.prototype.flashReady = function () { + // Check that the movie element is loaded correctly with its ExternalInterface methods defined + var movieElement = this.getMovieElement(); + + // Pro-actively unhook all the Flash functions + if (typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)"); + for (var key in movieElement) { + try { + if (typeof(movieElement[key]) === "function") { + movieElement[key] = null; + } + } catch (ex) { + } + } + } + + this.queueEvent("swfupload_loaded_handler"); +}; + + +/* This is a chance to do something before the browse window opens */ +SWFUpload.prototype.fileDialogStart = function () { + this.queueEvent("file_dialog_start_handler"); +}; + + +/* Called when a file is successfully added to the queue. */ +SWFUpload.prototype.fileQueued = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queued_handler", file); +}; + + +/* Handle errors that occur when an attempt to queue a file fails. */ +SWFUpload.prototype.fileQueueError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queue_error_handler", [file, errorCode, message]); +}; + +/* Called after the file dialog has closed and the selected files have been queued. + You could call startUpload here if you want the queued files to begin uploading immediately. */ +SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) { + this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]); +}; + +SWFUpload.prototype.uploadStart = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("return_upload_start_handler", file); +}; + +SWFUpload.prototype.returnUploadStart = function (file) { + var returnValue; + if (typeof this.settings.upload_start_handler === "function") { + file = this.unescapeFilePostParams(file); + returnValue = this.settings.upload_start_handler.call(this, file); + } else if (this.settings.upload_start_handler != undefined) { + throw "upload_start_handler must be a function"; + } + + // Convert undefined to true so if nothing is returned from the upload_start_handler it is + // interpretted as 'true'. + if (returnValue === undefined) { + returnValue = true; + } + + returnValue = !!returnValue; + + this.callFlash("ReturnUploadStart", [returnValue]); +}; + + + +SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]); +}; + +SWFUpload.prototype.uploadError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_error_handler", [file, errorCode, message]); +}; + +SWFUpload.prototype.uploadSuccess = function (file, serverData) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_success_handler", [file, serverData]); +}; + +SWFUpload.prototype.uploadComplete = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_complete_handler", file); +}; + +/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the + internal debug console. You can override this event and have messages written where you want. */ +SWFUpload.prototype.debug = function (message) { + this.queueEvent("debug_handler", message); +}; + + +/* ********************************** + Debug Console + The debug console is a self contained, in page location + for debug message to be sent. The Debug Console adds + itself to the body if necessary. + + The console is automatically scrolled as messages appear. + + If you are using your own debug handler or when you deploy to production and + have debug disabled you can remove these functions to reduce the file size + and complexity. +********************************** */ + +// Private: debugMessage is the default debug_handler. If you want to print debug messages +// call the debug() function. When overriding the function your own function should +// check to see if the debug setting is true before outputting debug information. +SWFUpload.prototype.debugMessage = function (message) { + if (this.settings.debug) { + var exceptionMessage, exceptionValues = []; + + // Check for an exception object and print it nicely + if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") { + for (var key in message) { + if (message.hasOwnProperty(key)) { + exceptionValues.push(key + ": " + message[key]); + } + } + exceptionMessage = exceptionValues.join("\n") || ""; + exceptionValues = exceptionMessage.split("\n"); + exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: "); + SWFUpload.Console.writeLine(exceptionMessage); + } else { + SWFUpload.Console.writeLine(message); + } + } +}; + +SWFUpload.Console = {}; +SWFUpload.Console.writeLine = function (message) { + var console, documentForm; + + try { + console = document.getElementById("SWFUpload_Console"); + + if (!console) { + documentForm = document.createElement("form"); + document.getElementsByTagName("body")[0].appendChild(documentForm); + + console = document.createElement("textarea"); + console.id = "SWFUpload_Console"; + console.style.fontFamily = "monospace"; + console.setAttribute("wrap", "off"); + console.wrap = "off"; + console.style.overflow = "auto"; + console.style.width = "700px"; + console.style.height = "350px"; + console.style.margin = "5px"; + documentForm.appendChild(console); + } + + console.value += message + "\n"; + + console.scrollTop = console.scrollHeight - console.clientHeight; + } catch (ex) { + alert("Exception: " + ex.name + " Message: " + ex.message); + } +}; diff --git a/www/include/xajax/xajax_plugins/response/tableUpdater.inc.php b/www/include/xajax/xajax_plugins/response/tableUpdater.inc.php new file mode 100644 index 00000000..de4ea39e --- /dev/null +++ b/www/include/xajax/xajax_plugins/response/tableUpdater.inc.php @@ -0,0 +1,112 @@ +sDefer='';$this->sJavascriptURI='';$this->bInlineScript=true;} +function configure($sName,$mValue){if('scriptDeferral'==$sName){if(true===$mValue||false===$mValue){if($mValue)$this->sDefer='defer ';else $this->sDefer='';} +}else if('javascript URI'==$sName){$this->sJavascriptURI=$mValue;}else if('inlineScript'==$sName){if(true===$mValue||false===$mValue) +$this->bInlineScript=$mValue;} +} +function generateClientScript(){if($this->bInlineScript){echo "\n\n";}else{echo "\n\n"; - return $html; - } - - /** - * Returns a string containing a Javascript include of the xajax.js file - * along with a check to see if the file loaded after six seconds - * (typically called internally by xajax from get/printJavascript). - * - * @param string the relative address of the folder where xajax has been - * installed. For instance, if your PHP file is - * "http://www.myserver.com/myfolder/mypage.php" - * and xajax was installed in - * "http://www.myserver.com/anotherfolder", then $sJsURI - * should be set to "../anotherfolder". Defaults to assuming - * xajax is in the same folder as your PHP file. - * @param string the relative folder/file pair of the xajax Javascript - * engine located within the xajax installation folder. - * Defaults to xajax_js/xajax.js. - * @return string - */ - function getJavascriptInclude($sJsURI="", $sJsFile=NULL) - { - if ($sJsFile == NULL) $sJsFile = "xajax_js/xajax.js"; - - if ($sJsURI != "" && substr($sJsURI, -1) != "/") $sJsURI .= "/"; - - $html = "\t\n"; - $html .= "\t\n"; - return $html; - } - - /** - * This method can be used to create a new xajax.js file out of the - * xajax_uncompressed.js file (which will only happen if xajax.js doesn't - * already exist on the filesystem). - * - * @param string an optional argument containing the full server file path - * of xajax.js. - */ - function autoCompressJavascript($sJsFullFilename=NULL) - { - $sJsFile = "xajax_js/xajax.js"; - - if ($sJsFullFilename) { - $realJsFile = $sJsFullFilename; - } - else { - $realPath = realpath(dirname(__FILE__)); - $realJsFile = $realPath . "/". $sJsFile; - } - - // Create a compressed file if necessary - if (!file_exists($realJsFile)) { - $srcFile = str_replace(".js", "_uncompressed.js", $realJsFile); - if (!file_exists($srcFile)) { - trigger_error("The xajax uncompressed Javascript file could not be found in the " . dirname($realJsFile) . " folder. Error ", E_USER_ERROR); - } - require(dirname(__FILE__)."/xajaxCompress.php"); - $javaScript = implode('', file($srcFile)); - $compressedScript = xajaxCompressJavascript($javaScript); - $fH = @fopen($realJsFile, "w"); - if (!$fH) { - trigger_error("The xajax compressed javascript file could not be written in the " . dirname($realJsFile) . " folder. Error ", E_USER_ERROR); - } - else { - fwrite($fH, $compressedScript); - fclose($fH); - } - } - } - - /** - * Returns the current URL based upon the SERVER vars. - * - * @access private - * @return string - */ - function _detectURI() { - $aURL = array(); - - // Try to get the request URL - if (!empty($_SERVER['REQUEST_URI'])) { - $aURL = parse_url($_SERVER['REQUEST_URI']); - } - - // Fill in the empty values - if (empty($aURL['scheme'])) { - if (!empty($_SERVER['HTTP_SCHEME'])) { - $aURL['scheme'] = $_SERVER['HTTP_SCHEME']; - } else { - $aURL['scheme'] = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http'; - } - } - - if (empty($aURL['host'])) { - if (!empty($_SERVER['HTTP_HOST'])) { - if (strpos($_SERVER['HTTP_HOST'], ':') > 0) { - list($aURL['host'], $aURL['port']) = explode(':', $_SERVER['HTTP_HOST']); - } else { - $aURL['host'] = $_SERVER['HTTP_HOST']; - } - } else if (!empty($_SERVER['SERVER_NAME'])) { - $aURL['host'] = $_SERVER['SERVER_NAME']; - } else { - print "xajax Error: xajax failed to automatically identify your Request URI."; - print "Please set the Request URI explicitly when you instantiate the xajax object."; - exit(); - } - } - - if (empty($aURL['port']) && !empty($_SERVER['SERVER_PORT'])) { - $aURL['port'] = $_SERVER['SERVER_PORT']; - } - - if (empty($aURL['path'])) { - if (!empty($_SERVER['PATH_INFO'])) { - $sPath = parse_url($_SERVER['PATH_INFO']); - } else { - $sPath = parse_url($_SERVER['PHP_SELF']); - } - $aURL['path'] = $sPath['path']; - unset($sPath); - } - - if (!empty($aURL['query'])) { - $aURL['query'] = '?'.$aURL['query']; - } - - // Build the URL: Start with scheme, user and pass - $sURL = $aURL['scheme'].'://'; - if (!empty($aURL['user'])) { - $sURL.= $aURL['user']; - if (!empty($aURL['pass'])) { - $sURL.= ':'.$aURL['pass']; - } - $sURL.= '@'; - } - - // Add the host - $sURL.= $aURL['host']; - - // Add the port if needed - if (!empty($aURL['port']) && (($aURL['scheme'] == 'http' && $aURL['port'] != 80) || ($aURL['scheme'] == 'https' && $aURL['port'] != 443))) { - $sURL.= ':'.$aURL['port']; - } - - // Add the path and the query string - $sURL.= $aURL['path'].@$aURL['query']; - - // Clean up - unset($aURL); - return $sURL; - } - - /** - * Returns true if the function name is associated with an object callback, - * false if not. - * - * @param string the name of the function - * @access private - * @return boolean - */ - function _isObjectCallback($sFunction) - { - if (array_key_exists($sFunction, $this->aObjects)) return true; - return false; - } - - /** - * Returns true if the function or object callback can be called, false if - * not. - * - * @param string the name of the function - * @access private - * @return boolean - */ - function _isFunctionCallable($sFunction) - { - if ($this->_isObjectCallback($sFunction)) { - if (is_object($this->aObjects[$sFunction][0])) { - return method_exists($this->aObjects[$sFunction][0], $this->aObjects[$sFunction][1]); - } - else { - return is_callable($this->aObjects[$sFunction]); - } - } - else { - return function_exists($sFunction); - } - } - - /** - * Calls the function, class method, or object method with the supplied - * arguments. - * - * @param string the name of the function - * @param array arguments to pass to the function - * @access private - * @return mixed the output of the called function or method - */ - function _callFunction($sFunction, $aArgs) - { - if ($this->_isObjectCallback($sFunction)) { - $mReturn = call_user_func_array($this->aObjects[$sFunction], $aArgs); - } - else { - $mReturn = call_user_func_array($sFunction, $aArgs); - } - return $mReturn; - } - - /** - * Generates the Javascript wrapper for the specified PHP function. - * - * @param string the name of the function - * @param mixed the request type - * @access private - * @return string - */ - function _wrap($sFunction,$sRequestType=XAJAX_POST) - { - $js = "function ".$this->sWrapperPrefix."$sFunction(){return xajax.call(\"$sFunction\", arguments, ".$sRequestType.");}\n"; - return $js; - } - - /** - * Takes a string containing xajax xjxobj XML or xjxquery XML and builds an - * array representation of it to pass as an argument to the PHP function - * being called. - * - * @param string the root tag of the XML - * @param string XML to convert - * @access private - * @return array - */ - function _xmlToArray($rootTag, $sXml) - { - $aArray = array(); - $sXml = str_replace("<$rootTag>","<$rootTag>|~|",$sXml); - $sXml = str_replace("","|~|",$sXml); - $sXml = str_replace("","|~|",$sXml); - $sXml = str_replace("","|~|",$sXml); - $sXml = str_replace("","|~|",$sXml); - $sXml = str_replace("","|~||~|",$sXml); - $sXml = str_replace("","|~|",$sXml); - $sXml = str_replace("","|~||~|",$sXml); - $sXml = str_replace("","|~|",$sXml); - $sXml = str_replace("","|~||~|",$sXml); - - $this->aObjArray = explode("|~|",$sXml); - - $this->iPos = 0; - $aArray = $this->_parseObjXml($rootTag); - - return $aArray; - } - - /** - * A recursive function that generates an array from the contents of - * $this->aObjArray. - * - * @param string the root tag of the XML - * @access private - * @return array - */ - function _parseObjXml($rootTag) - { - $aArray = array(); - - if ($rootTag == "xjxobj") - { - while(!stristr($this->aObjArray[$this->iPos],"")) - { - $this->iPos++; - if(stristr($this->aObjArray[$this->iPos],"")) - { - $key = ""; - $value = null; - - $this->iPos++; - while(!stristr($this->aObjArray[$this->iPos],"")) - { - if(stristr($this->aObjArray[$this->iPos],"")) - { - $this->iPos++; - while(!stristr($this->aObjArray[$this->iPos],"")) - { - $key .= $this->aObjArray[$this->iPos]; - $this->iPos++; - } - } - if(stristr($this->aObjArray[$this->iPos],"")) - { - $this->iPos++; - while(!stristr($this->aObjArray[$this->iPos],"")) - { - if(stristr($this->aObjArray[$this->iPos],"")) - { - $value = $this->_parseObjXml("xjxobj"); - $this->iPos++; - } - else - { - $value .= $this->aObjArray[$this->iPos]; - if ($this->bDecodeUTF8Input) - { - $value = $this->_decodeUTF8Data($value); - } - } - $this->iPos++; - } - } - $this->iPos++; - } - - $aArray[$key]=$value; - } - } - } - - if ($rootTag == "xjxquery") - { - $sQuery = ""; - $this->iPos++; - while(!stristr($this->aObjArray[$this->iPos],"")) - { - if (stristr($this->aObjArray[$this->iPos],"") || stristr($this->aObjArray[$this->iPos],"")) - { - $this->iPos++; - continue; - } - $sQuery .= $this->aObjArray[$this->iPos]; - $this->iPos++; - } - - parse_str($sQuery, $aArray); - if ($this->bDecodeUTF8Input) - { - foreach($aArray as $key => $value) - { - $aArray[$key] = $this->_decodeUTF8Data($value); - } - } - // If magic quotes is on, then we need to strip the slashes from the - // array values because of the parse_str pass which adds slashes - if (get_magic_quotes_gpc() == 1) { - $newArray = array(); - foreach ($aArray as $sKey => $sValue) { - if (is_string($sValue)) - $newArray[$sKey] = stripslashes($sValue); - else - $newArray[$sKey] = $sValue; - } - $aArray = $newArray; - } - } - - return $aArray; - } - - /** - * Decodes string data from UTF-8 to the current xajax encoding. - * - * @param string data to convert - * @access private - * @return string converted data - */ - function _decodeUTF8Data($sData) - { - $sValue = $sData; - if ($this->bDecodeUTF8Input) - { - $sFuncToUse = NULL; - - if (function_exists('iconv')) - { - $sFuncToUse = "iconv"; - } - else if (function_exists('mb_convert_encoding')) - { - $sFuncToUse = "mb_convert_encoding"; - } - else if ($this->sEncoding == "ISO-8859-1") - { - $sFuncToUse = "utf8_decode"; - } - else - { - trigger_error("The incoming xajax data could not be converted from UTF-8", E_USER_NOTICE); - } - - if ($sFuncToUse) - { - if (is_string($sValue)) - { - if ($sFuncToUse == "iconv") - { - $sValue = iconv("UTF-8", $this->sEncoding.'//TRANSLIT', $sValue); - } - else if ($sFuncToUse == "mb_convert_encoding") - { - $sValue = mb_convert_encoding($sValue, $this->sEncoding, "UTF-8"); - } - else - { - $sValue = utf8_decode($sValue); - } - } - } - } - return $sValue; - } - -}// end class xajax - -/** - * This function is registered with PHP's set_error_handler() function if - * the xajax error handling system is turned on. - */ -function xajaxErrorHandler($errno, $errstr, $errfile, $errline) -{ - $errorReporting = error_reporting(); - if (($errno & $errorReporting) == 0) return; - - if ($errno == E_NOTICE) { - $errTypeStr = "NOTICE"; - } - else if ($errno == E_WARNING) { - $errTypeStr = "WARNING"; - } - else if ($errno == E_USER_NOTICE) { - $errTypeStr = "USER NOTICE"; - } - else if ($errno == E_USER_WARNING) { - $errTypeStr = "USER WARNING"; - } - else if ($errno == E_USER_ERROR) { - $errTypeStr = "USER FATAL ERROR"; - } - else if ($errno == E_STRICT) { - return; - } - else { - $errTypeStr = "UNKNOWN: $errno"; - } - $GLOBALS['xajaxErrorHandlerText'] .= "\n----\n[$errTypeStr] $errstr\nerror in line $errline of file $errfile"; -} - -?> \ No newline at end of file diff --git a/www/include/xajax_0.2.4/xajaxResponse.inc.php b/www/include/xajax_0.2.4/xajaxResponse.inc.php deleted file mode 100644 index 1c0aeb60..00000000 --- a/www/include/xajax_0.2.4/xajaxResponse.inc.php +++ /dev/null @@ -1,580 +0,0 @@ - - *
  • Assign - sets the specified attribute of an element in your page
  • - *
  • Append - appends data to the end of the specified attribute of an - * element in your page
  • - *
  • Prepend - prepends data to the beginning of the specified attribute of - * an element in your page
  • - *
  • Replace - searches for and replaces data in the specified attribute of - * an element in your page
  • - *
  • Script - runs the supplied JavaScript code
  • - *
  • Alert - shows an alert box with the supplied message text
  • - * - * - * Note: elements are identified by their HTML id, so if you don't see - * your browser HTML display changing from the request, make sure you're using - * the right id names in your response. - * - * @package xajax - */ -class xajaxResponse -{ - /**#@+ - * @access protected - */ - /** - * @var string internal XML storage - */ - var $xml; - /** - * @var string the encoding type to use - */ - var $sEncoding; - /** - * @var boolean if special characters in the XML should be converted to - * entities - */ - var $bOutputEntities; - - /**#@-*/ - - /** - * The constructor's main job is to set the character encoding for the - * response. - * - * Note: to change the character encoding for all of the - * responses, set the XAJAX_DEFAULT_ENCODING constant before you - * instantiate xajax. - * - * @param string contains the character encoding string to use - * @param boolean lets you set if you want special characters in the output - * converted to HTML entities - * - */ - function xajaxResponse($sEncoding=XAJAX_DEFAULT_CHAR_ENCODING, $bOutputEntities=false) - { - $this->setCharEncoding($sEncoding); - $this->bOutputEntities = $bOutputEntities; - } - - /** - * Sets the character encoding for the response based on $sEncoding, which - * is a string containing the character encoding to use. You don't need to - * use this method normally, since the character encoding for the response - * gets set automatically based on the XAJAX_DEFAULT_CHAR_ENCODING - * constant. - * - * @param string - */ - function setCharEncoding($sEncoding) - { - $this->sEncoding = $sEncoding; - } - - /** - * Tells the response object to convert special characters to HTML entities - * automatically (only works if the mb_string extension is available). - */ - function outputEntitiesOn() - { - $this->bOutputEntities = true; - } - - /** - * Tells the response object to output special characters intact. (default - * behavior) - */ - function outputEntitiesOff() - { - $this->bOutputEntities = false; - } - - /** - * Adds a confirm commands command message to the XML response. - * - * Usage: $objResponse->addConfirmCommands(1, "Do you want to preview the new data?"); - * - * @param integer the number of commands to skip if the user presses - * Cancel in the browsers's confirm dialog - * @param string the message to show in the browser's confirm dialog - */ - function addConfirmCommands($iCmdNumber, $sMessage) - { - $this->xml .= $this->_cmdXML(array("n"=>"cc","t"=>$iCmdNumber),$sMessage); - } - - /** - * Adds an assign command message to the XML response. - * - * Usage: $objResponse->addAssign("contentDiv", "innerHTML", "Some Text"); - * - * @param string contains the id of an HTML element - * @param string the part of the element you wish to modify ("innerHTML", - * "value", etc.) - * @param string the data you want to set the attribute to - */ - function addAssign($sTarget,$sAttribute,$sData) - { - $this->xml .= $this->_cmdXML(array("n"=>"as","t"=>$sTarget,"p"=>$sAttribute),$sData); - } - - /** - * Adds an append command message to the XML response. - * - * Usage: $objResponse->addAppend("contentDiv", "innerHTML", "Some New Text"); - * - * @param string contains the id of an HTML element - * @param string the part of the element you wish to modify ("innerHTML", - * "value", etc.) - * @param string the data you want to append to the end of the attribute - */ - function addAppend($sTarget,$sAttribute,$sData) - { - $this->xml .= $this->_cmdXML(array("n"=>"ap","t"=>$sTarget,"p"=>$sAttribute),$sData); - } - - /** - * Adds an prepend command message to the XML response. - * - * Usage: $objResponse->addPrepend("contentDiv", "innerHTML", "Some Starting Text"); - * - * @param string contains the id of an HTML element - * @param string the part of the element you wish to modify ("innerHTML", - * "value", etc.) - * @param string the data you want to prepend to the beginning of the - * attribute - */ - function addPrepend($sTarget,$sAttribute,$sData) - { - $this->xml .= $this->_cmdXML(array("n"=>"pp","t"=>$sTarget,"p"=>$sAttribute),$sData); - } - - /** - * Adds a replace command message to the XML response. - * - * Usage: $objResponse->addReplace("contentDiv", "innerHTML", "text", "text"); - * - * @param string contains the id of an HTML element - * @param string the part of the element you wish to modify ("innerHTML", - * "value", etc.) - * @param string the string to search for - * @param string the string to replace the search string when found in the - * attribute - */ - function addReplace($sTarget,$sAttribute,$sSearch,$sData) - { - $sDta = ""; - $this->xml .= $this->_cmdXML(array("n"=>"rp","t"=>$sTarget,"p"=>$sAttribute),$sDta); - } - - /** - * Adds a clear command message to the XML response. - * - * Usage: $objResponse->addClear("contentDiv", "innerHTML"); - * - * @param string contains the id of an HTML element - * @param string the part of the element you wish to clear ("innerHTML", - * "value", etc.) - */ - function addClear($sTarget,$sAttribute) - { - $this->addAssign($sTarget,$sAttribute,''); - } - - /** - * Adds an alert command message to the XML response. - * - * Usage: $objResponse->addAlert("This is important information"); - * - * @param string the text to be displayed in the Javascript alert box - */ - function addAlert($sMsg) - { - $this->xml .= $this->_cmdXML(array("n"=>"al"),$sMsg); - } - - /** - * Uses the addScript() method to add a Javascript redirect to another URL. - * - * Usage: $objResponse->addRedirect("http://www.xajaxproject.org"); - * - * @param string the URL to redirect the client browser to - */ - function addRedirect($sURL) - { - //we need to parse the query part so that the values are rawurlencode()'ed - //can't just use parse_url() cos we could be dealing with a relative URL which - // parse_url() can't deal with. - $queryStart = strpos($sURL, '?', strrpos($sURL, '/')); - if ($queryStart !== FALSE) - { - $queryStart++; - $queryEnd = strpos($sURL, '#', $queryStart); - if ($queryEnd === FALSE) - $queryEnd = strlen($sURL); - $queryPart = substr($sURL, $queryStart, $queryEnd-$queryStart); - parse_str($queryPart, $queryParts); - $newQueryPart = ""; - foreach($queryParts as $key => $value) - { - $newQueryPart .= rawurlencode($key).'='.rawurlencode($value).ini_get('arg_separator.output'); - } - $sURL = str_replace($queryPart, $newQueryPart, $sURL); - } - $this->addScript('window.location = "'.$sURL.'";'); - } - - /** - * Adds a Javascript command message to the XML response. - * - * Usage: $objResponse->addScript("var x = prompt('get some text');"); - * - * @param string contains Javascript code to be executed - */ - function addScript($sJS) - { - $this->xml .= $this->_cmdXML(array("n"=>"js"),$sJS); - } - - /** - * Adds a Javascript function call command message to the XML response. - * - * Usage: $objResponse->addScriptCall("myJSFunction", "arg 1", "arg 2", 12345); - * - * @param string $sFunc the name of a Javascript function - * @param mixed $args,... optional arguments to pass to the Javascript function - */ - function addScriptCall() { - $arguments = func_get_args(); - $sFunc = array_shift($arguments); - $sData = $this->_buildObjXml($arguments); - $this->xml .= $this->_cmdXML(array("n"=>"jc","t"=>$sFunc),$sData); - } - - /** - * Adds a remove element command message to the XML response. - * - * Usage: $objResponse->addRemove("Div2"); - * - * @param string contains the id of an HTML element to be removed - */ - function addRemove($sTarget) - { - $this->xml .= $this->_cmdXML(array("n"=>"rm","t"=>$sTarget),''); - } - - /** - * Adds a create element command message to the XML response. - * - * Usage: $objResponse->addCreate("parentDiv", "h3", "myid"); - * - * @param string contains the id of an HTML element to to which the new - * element will be appended. - * @param string the tag to be added - * @param string the id to be assigned to the new element - * @param string deprecated, use the addCreateInput() method instead - */ - function addCreate($sParent, $sTag, $sId, $sType="") - { - if ($sType) - { - trigger_error("The \$sType parameter of addCreate has been deprecated. Use the addCreateInput() method instead.", E_USER_WARNING); - return; - } - $this->xml .= $this->_cmdXML(array("n"=>"ce","t"=>$sParent,"p"=>$sId),$sTag); - } - - /** - * Adds a insert element command message to the XML response. - * - * Usage: $objResponse->addInsert("childDiv", "h3", "myid"); - * - * @param string contains the id of the child before which the new element - * will be inserted - * @param string the tag to be added - * @param string the id to be assigned to the new element - */ - function addInsert($sBefore, $sTag, $sId) - { - $this->xml .= $this->_cmdXML(array("n"=>"ie","t"=>$sBefore,"p"=>$sId),$sTag); - } - - /** - * Adds a insert element command message to the XML response. - * - * Usage: $objResponse->addInsertAfter("childDiv", "h3", "myid"); - * - * @param string contains the id of the child after which the new element - * will be inserted - * @param string the tag to be added - * @param string the id to be assigned to the new element - */ - function addInsertAfter($sAfter, $sTag, $sId) - { - $this->xml .= $this->_cmdXML(array("n"=>"ia","t"=>$sAfter,"p"=>$sId),$sTag); - } - - /** - * Adds a create input command message to the XML response. - * - * Usage: $objResponse->addCreateInput("form1", "text", "username", "input1"); - * - * @param string contains the id of an HTML element to which the new input - * will be appended - * @param string the type of input to be created (text, radio, checkbox, - * etc.) - * @param string the name to be assigned to the new input and the variable - * name when it is submitted - * @param string the id to be assigned to the new input - */ - function addCreateInput($sParent, $sType, $sName, $sId) - { - $this->xml .= $this->_cmdXML(array("n"=>"ci","t"=>$sParent,"p"=>$sId,"c"=>$sType),$sName); - } - - /** - * Adds an insert input command message to the XML response. - * - * Usage: $objResponse->addInsertInput("input5", "text", "username", "input1"); - * - * @param string contains the id of the child before which the new element - * will be inserted - * @param string the type of input to be created (text, radio, checkbox, - * etc.) - * @param string the name to be assigned to the new input and the variable - * name when it is submitted - * @param string the id to be assigned to the new input - */ - function addInsertInput($sBefore, $sType, $sName, $sId) - { - $this->xml .= $this->_cmdXML(array("n"=>"ii","t"=>$sBefore,"p"=>$sId,"c"=>$sType),$sName); - } - - /** - * Adds an insert input command message to the XML response. - * - * Usage: $objResponse->addInsertInputAfter("input7", "text", "email", "input2"); - * - * @param string contains the id of the child after which the new element - * will be inserted - * @param string the type of input to be created (text, radio, checkbox, - * etc.) - * @param string the name to be assigned to the new input and the variable - * name when it is submitted - * @param string the id to be assigned to the new input - */ - function addInsertInputAfter($sAfter, $sType, $sName, $sId) - { - $this->xml .= $this->_cmdXML(array("n"=>"iia","t"=>$sAfter,"p"=>$sId,"c"=>$sType),$sName); - } - - /** - * Adds an event command message to the XML response. - * - * Usage: $objResponse->addEvent("contentDiv", "onclick", "alert(\'Hello World\');"); - * - * @param string contains the id of an HTML element - * @param string the event you wish to set ("onclick", "onmouseover", etc.) - * @param string the Javascript string you want the event to invoke - */ - function addEvent($sTarget,$sEvent,$sScript) - { - $this->xml .= $this->_cmdXML(array("n"=>"ev","t"=>$sTarget,"p"=>$sEvent),$sScript); - } - - /** - * Adds a handler command message to the XML response. - * - * Usage: $objResponse->addHandler("contentDiv", "onclick", "content_click"); - * - * @param string contains the id of an HTML element - * @param string the event you wish to set ("onclick", "onmouseover", etc.) - * @param string the name of a Javascript function that will handle the - * event. Multiple handlers can be added for the same event - */ - function addHandler($sTarget,$sEvent,$sHandler) - { - $this->xml .= $this->_cmdXML(array("n"=>"ah","t"=>$sTarget,"p"=>$sEvent),$sHandler); - } - - /** - * Adds a remove handler command message to the XML response. - * - * Usage: $objResponse->addRemoveHandler("contentDiv", "onclick", "content_click"); - * - * @param string contains the id of an HTML element - * @param string the event you wish to remove ("onclick", "onmouseover", - * etc.) - * @param string the name of a Javascript handler function that you want to - * remove - */ - function addRemoveHandler($sTarget,$sEvent,$sHandler) - { - $this->xml .= $this->_cmdXML(array("n"=>"rh","t"=>$sTarget,"p"=>$sEvent),$sHandler); - } - - /** - * Adds an include script command message to the XML response. - * - * Usage: $objResponse->addIncludeScript("functions.js"); - * - * @param string URL of the Javascript file to include - */ - function addIncludeScript($sFileName) - { - $this->xml .= $this->_cmdXML(array("n"=>"in"),$sFileName); - } - - /** - * Returns the XML to be returned from your function to the xajax processor - * on your page. Since xajax 0.2, you can also return an xajaxResponse - * object from your function directly, and xajax will automatically request - * the XML using this method call. - * - * Usage: return $objResponse->getXML(); - * - * @return string response XML data - */ - function getXML() - { - $sXML = "sEncoding && strlen(trim($this->sEncoding)) > 0) - $sXML .= " encoding=\"".$this->sEncoding."\""; - $sXML .= " ?".">" . $this->xml . ""; - - return $sXML; - } - - /** - * Adds the commands of the provided response XML output to this response - * object - * - * Usage: - * $r1 = $objResponse1->getXML(); - * $objResponse2->loadXML($r1); - * return $objResponse2->getXML(); - * - * @param string the response XML (returned from a getXML() method) to add - * to the end of this response object - */ - function loadXML($mXML) - { - if (is_a($mXML, "xajaxResponse")) { - $mXML = $mXML->getXML(); - } - $sNewXML = ""; - $iStartPos = strpos($mXML, "") + 5; - $sNewXML = substr($mXML, $iStartPos); - $iEndPos = strpos($sNewXML, ""); - $sNewXML = substr($sNewXML, 0, $iEndPos); - $this->xml .= $sNewXML; - } - - /** - * Generates XML from command data - * - * @access private - * @param array associative array of attributes - * @param string data - * @return string XML command - */ - function _cmdXML($aAttributes, $sData) - { - if ($this->bOutputEntities) { - if (function_exists('mb_convert_encoding')) { - $sData = call_user_func_array('mb_convert_encoding', array(&$sData, 'HTML-ENTITIES', $this->sEncoding)); - } - else { - trigger_error("The xajax XML response output could not be converted to HTML entities because the mb_convert_encoding function is not available", E_USER_NOTICE); - } - } - $xml = " $sValue) - $xml .= " $sAttribute=\"$sValue\""; - if ($sData !== null && !stristr($sData,'"; - else if ($sData !== null) - $xml .= ">$sData"; - else - $xml .= ">"; - - return $xml; - } - - /** - * Recursively serializes a data structure in XML so it can be sent to - * the client. It could be thought of as the opposite of - * {@link xajax::_parseObjXml()}. - * - * @access private - * @param mixed data structure to serialize to XML - * @return string serialized XML - */ - function _buildObjXml($var) { - if (gettype($var) == "object") $var = get_object_vars($var); - if (!is_array($var)) { - return ""; - } - else { - $data = ""; - foreach ($var as $key => $value) { - $data .= ""; - $data .= "" . htmlspecialchars($key) . ""; - $data .= "" . $this->_buildObjXml($value) . ""; - $data .= ""; - } - $data .= ""; - return $data; - } - } - -}// end class xajaxResponse -?> diff --git a/www/include/xajax_0.2.4/xajax_js/xajax.js b/www/include/xajax_0.2.4/xajax_js/xajax.js deleted file mode 100644 index 0dca8f52..00000000 --- a/www/include/xajax_0.2.4/xajax_js/xajax.js +++ /dev/null @@ -1,172 +0,0 @@ -/* xajax Javascript library :: version 0.2.4 */ -Array.prototype.containsValue=function(valueToCheck){for(var i=0;i 1000)text=text.substr(0,1000)+"...\n[long response]\n...";try{if(this.debugWindow==undefined||this.debugWindow.closed==true){this.debugWindow=window.open('about:blank','xajax-debug','width=800,height=600,scrollbars=1,resizable,status');this.debugWindow.document.write('Xajax debug output

    Xajax debug output

    ');} -text=text.replace(/&/g,"&") -text=text.replace(//g,">") -debugTag=this.debugWindow.document.getElementById('debugTag');debugTag.innerHTML=(''+(new Date()).toString()+': '+text+'
    ')+debugTag.innerHTML;}catch(e){alert("Xajax Debug:\n "+text);} -};this.workId='xajaxWork'+new Date().getTime();this.depth=0;this.responseErrorsForAlert=["400","401","402","403","404","500","501","502","503"];this.getRequestObject=function(){if(xajaxDebug)this.DebugMessage("Initializing Request Object..");var req=null;if(typeof XMLHttpRequest!="undefined") -req=new XMLHttpRequest();if(!req&&typeof ActiveXObject!="undefined"){try{req=new ActiveXObject("Msxml2.XMLHTTP");} -catch(e){try{req=new ActiveXObject("Microsoft.XMLHTTP");} -catch(e2){try{req=new ActiveXObject("Msxml2.XMLHTTP.4.0");} -catch(e3){req=null;} -} -} -} -if(!req&&window.createRequest) -req=window.createRequest();if(!req)this.DebugMessage("Request Object Instantiation failed.");return req;} -this.$=function(sId){if(!sId){return null;} -var returnObj=document.getElementById(sId);if(!returnObj&&document.all){returnObj=document.all[sId];} -if(xajaxDebug&&!returnObj&&sId!=this.workId){this.DebugMessage("Element with the id \""+sId+"\" not found.");} -return returnObj;} -this.include=function(sFileName){var objHead=document.getElementsByTagName('head');var objScript=document.createElement('script');objScript.type='text/javascript';objScript.src=sFileName;objHead[0].appendChild(objScript);} -this.stripOnPrefix=function(sEventName){sEventName=sEventName.toLowerCase();if(sEventName.indexOf('on')==0){sEventName=sEventName.replace(/on/,'');} -return sEventName;} -this.addOnPrefix=function(sEventName){sEventName=sEventName.toLowerCase();if(sEventName.indexOf('on')!=0){sEventName='on'+sEventName;} -return sEventName;} -this.addHandler=function(sElementId,sEvent,sFunctionName){if(window.addEventListener){sEvent=this.stripOnPrefix(sEvent);eval("this.$('"+sElementId+"').addEventListener('"+sEvent+"',"+sFunctionName+",false);");} -else{sAltEvent=this.addOnPrefix(sEvent);eval("this.$('"+sElementId+"').attachEvent('"+sAltEvent+"',"+sFunctionName+",false);");} -} -this.removeHandler=function(sElementId,sEvent,sFunctionName){if(window.addEventListener){sEvent=this.stripOnPrefix(sEvent);eval("this.$('"+sElementId+"').removeEventListener('"+sEvent+"',"+sFunctionName+",false);");} -else{sAltEvent=this.addOnPrefix(sEvent);eval("this.$('"+sElementId+"').detachEvent('"+sAltEvent+"',"+sFunctionName+",false);");} -} -this.create=function(sParentId,sTag,sId){var objParent=this.$(sParentId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);if(objParent) -objParent.appendChild(objElement);} -this.insert=function(sBeforeId,sTag,sId){var objSibling=this.$(sBeforeId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);objSibling.parentNode.insertBefore(objElement,objSibling);} -this.insertAfter=function(sAfterId,sTag,sId){var objSibling=this.$(sAfterId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);objSibling.parentNode.insertBefore(objElement,objSibling.nextSibling);} -this.getInput=function(sType,sName,sId){var Obj;if(!window.addEventListener){Obj=document.createElement('');} -else{Obj=document.createElement('input');Obj.setAttribute('type',sType);Obj.setAttribute('name',sName);Obj.setAttribute('id',sId);} -return Obj;} -this.createInput=function(sParentId,sType,sName,sId){var objParent=this.$(sParentId);var objElement=this.getInput(sType,sName,sId);if(objParent&&objElement) -objParent.appendChild(objElement);} -this.insertInput=function(sBeforeId,sType,sName,sId){var objSibling=this.$(sBeforeId);var objElement=this.getInput(sType,sName,sId);if(objElement&&objSibling&&objSibling.parentNode) -objSibling.parentNode.insertBefore(objElement,objSibling);} -this.insertInputAfter=function(sAfterId,sType,sName,sId){var objSibling=this.$(sAfterId);var objElement=this.getInput(sType,sName,sId);if(objElement&&objSibling&&objSibling.parentNode){objSibling.parentNode.insertBefore(objElement,objSibling.nextSibling);} -} -this.remove=function(sId){objElement=this.$(sId);if(objElement&&objElement.parentNode&&objElement.parentNode.removeChild){objElement.parentNode.removeChild(objElement);} -} -this.replace=function(sId,sAttribute,sSearch,sReplace){var bFunction=false;if(sAttribute=="innerHTML") -sSearch=this.getBrowserHTML(sSearch);eval("var txt=this.$('"+sId+"')."+sAttribute);if(typeof txt=="function"){txt=txt.toString();bFunction=true;} -if(txt.indexOf(sSearch)>-1){var newTxt='';while(txt.indexOf(sSearch)>-1){x=txt.indexOf(sSearch)+sSearch.length+1;newTxt+=txt.substr(0,x).replace(sSearch,sReplace);txt=txt.substr(x,txt.length-x);} -newTxt+=txt;if(bFunction){eval('this.$("'+sId+'").'+sAttribute+'=newTxt;');} -else if(this.willChange(sId,sAttribute,newTxt)){eval('this.$("'+sId+'").'+sAttribute+'=newTxt;');} -} -} -this.getFormValues=function(frm){var objForm;var submitDisabledElements=false;if(arguments.length > 1&&arguments[1]==true) -submitDisabledElements=true;var prefix="";if(arguments.length > 2) -prefix=arguments[2];if(typeof(frm)=="string") -objForm=this.$(frm);else -objForm=frm;var sXml="";if(objForm&&objForm.tagName=='FORM'){var formElements=objForm.elements;for(var i=0;i < formElements.length;i++){if(!formElements[i].name) -continue;if(formElements[i].name.substring(0,prefix.length)!=prefix) -continue;if(formElements[i].type&&(formElements[i].type=='radio'||formElements[i].type=='checkbox')&&formElements[i].checked==false) -continue;if(formElements[i].disabled&&formElements[i].disabled==true&&submitDisabledElements==false) -continue;var name=formElements[i].name;if(name){if(sXml!='') -sXml+='&';if(formElements[i].type=='select-multiple'){for(var j=0;j < formElements[i].length;j++){if(formElements[i].options[j].selected==true) -sXml+=name+"="+encodeURIComponent(formElements[i].options[j].value)+"&";} -} -else{sXml+=name+"="+encodeURIComponent(formElements[i].value);} -} -} -} -sXml+="";return sXml;} -this.objectToXML=function(obj){var sXml="";for(i in obj){try{if(i=='constructor') -continue;if(obj[i]&&typeof(obj[i])=='function') -continue;var key=i;var value=obj[i];if(value&&typeof(value)=="object"&&this.depth <=50){this.depth++;value=this.objectToXML(value);this.depth--;} -sXml+=""+key+""+value+"";} -catch(e){if(xajaxDebug)this.DebugMessage(e.name+": "+e.message);} -} -sXml+="";return sXml;} -this._nodeToObject=function(node){if(node.nodeName=='#cdata-section'){var data="";for(var j=0;j"+document.getElementsByTagName("HTML")[0].innerHTML+"";} -this.processResponse=function(xml){clearTimeout(loadingTimeout);this.doneLoadingFunction();if(xajaxStatusMessages==true)window.status='Processing...';var tmpXajax=null;xml=xml.documentElement;if(xml==null) -return;var skipCommands=0;for(var i=0;i 0){skipCommands--;continue;} -if(xml.childNodes[i].nodeName=="cmd"){var cmd;var id;var property;var data;var search;var type;var before;var objElement=null;for(var j=0;j 1&&xml.childNodes[i].firstChild.nodeName=="#cdata-section"){data="";for(var j=0;j 1){for(var j=0;j 1&&xml.childNodes[i].childNodes[j].firstChild.nodeName=="#cdata-section"){var internalData="";for(var k=0;k 1000) text = text.substr(0,1000)+"...\n[long response]\n..."; - try { - if (this.debugWindow == undefined || this.debugWindow.closed == true) { - this.debugWindow = window.open('about:blank', 'xajax-debug', 'width=800,height=600,scrollbars=1,resizable,status'); - this.debugWindow.document.write('Xajax debug output

    Xajax debug output

    '); - } - text = text.replace(/&/g, "&") - text = text.replace(//g, ">") - debugTag = this.debugWindow.document.getElementById('debugTag'); - debugTag.innerHTML = (''+(new Date()).toString()+': ' + text + '
    ') + debugTag.innerHTML; - } catch (e) { - alert("Xajax Debug:\n " + text); - } - }; - - this.workId = 'xajaxWork'+ new Date().getTime(); - this.depth = 0; - this.responseErrorsForAlert = ["400","401","402","403","404","500","501","502","503"]; - - //Get the XMLHttpRequest Object - this.getRequestObject = function() - { - if (xajaxDebug) this.DebugMessage("Initializing Request Object.."); - var req = null; - if (typeof XMLHttpRequest != "undefined") - req = new XMLHttpRequest(); - if (!req && typeof ActiveXObject != "undefined") - { - try - { - req=new ActiveXObject("Msxml2.XMLHTTP"); - } - catch (e) - { - try - { - req=new ActiveXObject("Microsoft.XMLHTTP"); - } - catch (e2) - { - try { - req=new ActiveXObject("Msxml2.XMLHTTP.4.0"); - } - catch (e3) - { - req=null; - } - } - } - } - if(!req && window.createRequest) - req = window.createRequest(); - - if (!req) this.DebugMessage("Request Object Instantiation failed."); - - return req; - } - - // xajax.$() is shorthand for document.getElementById() - this.$ = function(sId) - { - if (!sId) { - return null; - } - var returnObj = document.getElementById(sId); - if (!returnObj && document.all) { - returnObj = document.all[sId]; - } - if (xajaxDebug && !returnObj && sId != this.workId) { - this.DebugMessage("Element with the id \"" + sId + "\" not found."); - } - return returnObj; - } - - // xajax.include(sFileName) dynamically includes an external javascript file - this.include = function(sFileName) - { - var objHead = document.getElementsByTagName('head'); - var objScript = document.createElement('script'); - objScript.type = 'text/javascript'; - objScript.src = sFileName; - objHead[0].appendChild(objScript); - } - - this.stripOnPrefix = function(sEventName) - { - sEventName = sEventName.toLowerCase(); - if (sEventName.indexOf('on') == 0) - { - sEventName = sEventName.replace(/on/,''); - } - - return sEventName; - } - - this.addOnPrefix = function(sEventName) - { - sEventName = sEventName.toLowerCase(); - if (sEventName.indexOf('on') != 0) - { - sEventName = 'on' + sEventName; - } - - return sEventName; - } - - // xajax.addHandler adds an event handler to an element - this.addHandler = function(sElementId, sEvent, sFunctionName) - { - if (window.addEventListener) - { - sEvent = this.stripOnPrefix(sEvent); - eval("this.$('"+sElementId+"').addEventListener('"+sEvent+"',"+sFunctionName+",false);"); - } - else - { - sAltEvent = this.addOnPrefix(sEvent); - eval("this.$('"+sElementId+"').attachEvent('"+sAltEvent+"',"+sFunctionName+",false);"); - } - } - - // xajax.removeHandler removes an event handler from an element - this.removeHandler = function(sElementId, sEvent, sFunctionName) - { - if (window.addEventListener) - { - sEvent = this.stripOnPrefix(sEvent); - eval("this.$('"+sElementId+"').removeEventListener('"+sEvent+"',"+sFunctionName+",false);"); - } - else - { - sAltEvent = this.addOnPrefix(sEvent); - eval("this.$('"+sElementId+"').detachEvent('"+sAltEvent+"',"+sFunctionName+",false);"); - } - } - - // xajax.create creates a new child node under a parent - this.create = function(sParentId, sTag, sId) - { - var objParent = this.$(sParentId); - objElement = document.createElement(sTag); - objElement.setAttribute('id',sId); - if (objParent) - objParent.appendChild(objElement); - } - - // xajax.insert inserts a new node before another node - this.insert = function(sBeforeId, sTag, sId) - { - var objSibling = this.$(sBeforeId); - objElement = document.createElement(sTag); - objElement.setAttribute('id',sId); - objSibling.parentNode.insertBefore(objElement, objSibling); - } - - // xajax.insertAfter inserts a new node after another node - this.insertAfter = function(sAfterId, sTag, sId) - { - var objSibling = this.$(sAfterId); - objElement = document.createElement(sTag); - objElement.setAttribute('id',sId); - objSibling.parentNode.insertBefore(objElement, objSibling.nextSibling); - } - - this.getInput = function(sType, sName, sId) - { - var Obj; - if (!window.addEventListener) - { - Obj = document.createElement(''); - } - else - { - Obj = document.createElement('input'); - Obj.setAttribute('type',sType); - Obj.setAttribute('name',sName); - Obj.setAttribute('id',sId); - } - return Obj; - } - - // xajax.createInput creates a new input node under a parent - this.createInput = function(sParentId, sType, sName, sId) - { - var objParent = this.$(sParentId); - var objElement = this.getInput(sType, sName, sId); - if (objParent && objElement) - objParent.appendChild(objElement); - } - - // xajax.insertInput creates a new input node before another node - this.insertInput = function(sBeforeId, sType, sName, sId) - { - var objSibling = this.$(sBeforeId); - var objElement = this.getInput(sType, sName, sId); - if (objElement && objSibling && objSibling.parentNode) - objSibling.parentNode.insertBefore(objElement, objSibling); - } - - // xajax.insertInputAfter creates a new input node after another node - this.insertInputAfter = function(sAfterId, sType, sName, sId) - { - var objSibling = this.$(sAfterId); - var objElement = this.getInput(sType, sName, sId); - if (objElement && objSibling && objSibling.parentNode) { - objSibling.parentNode.insertBefore(objElement, objSibling.nextSibling); - } - } - - // xajax.remove deletes an element - this.remove = function(sId) - { - objElement = this.$(sId); - if (objElement && objElement.parentNode && objElement.parentNode.removeChild) - { - objElement.parentNode.removeChild(objElement); - } - } - - //xajax.replace searches for text in an attribute of an element and replaces it - //with a different text - this.replace = function(sId,sAttribute,sSearch,sReplace) - { - var bFunction = false; - - if (sAttribute == "innerHTML") - sSearch = this.getBrowserHTML(sSearch); - - eval("var txt=this.$('"+sId+"')."+sAttribute); - if (typeof txt == "function") - { - txt = txt.toString(); - bFunction = true; - } - if (txt.indexOf(sSearch)>-1) - { - var newTxt = ''; - while (txt.indexOf(sSearch) > -1) - { - x = txt.indexOf(sSearch)+sSearch.length+1; - newTxt += txt.substr(0,x).replace(sSearch,sReplace); - txt = txt.substr(x,txt.length-x); - } - newTxt += txt; - if (bFunction) - { - eval('this.$("'+sId+'").'+sAttribute+'=newTxt;'); - } - else if (this.willChange(sId,sAttribute,newTxt)) - { - eval('this.$("'+sId+'").'+sAttribute+'=newTxt;'); - } - } - } - - // xajax.getFormValues() builds a query string XML message from the elements of a form object - // * The first argument is the id of the form - // * The second argument (optional) can be set to true if you want to submit disabled elements - // * The third argument (optional) allows you to specify a string prefix that a form element - // name must contain if you want that element to be submitted - this.getFormValues = function(frm) - { - var objForm; - var submitDisabledElements = false; - if (arguments.length > 1 && arguments[1] == true) - submitDisabledElements = true; - var prefix=""; - if(arguments.length > 2) - prefix = arguments[2]; - - if (typeof(frm) == "string") - objForm = this.$(frm); - else - objForm = frm; - var sXml = ""; - if (objForm && objForm.tagName == 'FORM') - { - var formElements = objForm.elements; - for( var i=0; i < formElements.length; i++) - { - if (!formElements[i].name) - continue; - if (formElements[i].name.substring(0, prefix.length) != prefix) - continue; - if (formElements[i].type && (formElements[i].type == 'radio' || formElements[i].type == 'checkbox') && formElements[i].checked == false) - continue; - if (formElements[i].disabled && formElements[i].disabled == true && submitDisabledElements == false) - continue; - var name = formElements[i].name; - if (name) - { - if (sXml != '') - sXml += '&'; - if(formElements[i].type=='select-multiple') - { - for (var j = 0; j < formElements[i].length; j++) - { - if (formElements[i].options[j].selected == true) - sXml += name+"="+encodeURIComponent(formElements[i].options[j].value)+"&"; - } - } - else - { - sXml += name+"="+encodeURIComponent(formElements[i].value); - } - } - } - } - - sXml +=""; - - return sXml; - } - - // Generates an XML message that xajax can understand from a javascript object - this.objectToXML = function(obj) - { - var sXml = ""; - for (i in obj) - { - try - { - if (i == 'constructor') - continue; - if (obj[i] && typeof(obj[i]) == 'function') - continue; - - var key = i; - var value = obj[i]; - if (value && typeof(value)=="object" && this.depth <= 50) - { - this.depth++; - value = this.objectToXML(value); - this.depth--; - } - - sXml += ""+key+""+value+""; - - } - catch(e) - { - if (xajaxDebug) this.DebugMessage(e.name+": "+e.message); - } - } - sXml += ""; - - return sXml; - } - - // unserializes data structure from xajaxResponse::_buildObjXml() - this._nodeToObject = function(node) { - // parentNode here is weird, have to tune - if (node.nodeName == '#cdata-section') { - var data = ""; - for (var j=0; j"+document.getElementsByTagName("HTML")[0].innerHTML+""; - } - - //Process XML xajaxResponses returned from the request - this.processResponse = function(xml) - { - clearTimeout(loadingTimeout); - this.doneLoadingFunction(); - if (xajaxStatusMessages == true) window.status = 'Processing...'; - var tmpXajax = null; - xml = xml.documentElement; - if (xml == null) - return; - - var skipCommands = 0; - for (var i=0; i 0) { - skipCommands--; - continue; - } - if (xml.childNodes[i].nodeName == "cmd") - { - var cmd; - var id; - var property; - var data; - var search; - var type; - var before; - var objElement = null; - - for (var j=0; j 1 && xml.childNodes[i].firstChild.nodeName == "#cdata-section") - { - data = ""; - for (var j=0; j 1) - { - for (var j=0; j 1 && xml.childNodes[i].childNodes[j].firstChild.nodeName == "#cdata-section") - { - var internalData = ""; - for (var k=0; kregisterFunction("window_save_position"); - -// for when and if I switch to xajax 0.5.x -//$xajax->register(XAJAX_FUNCTION,"window_save_position"); +$xajax->register(XAJAX_FUNCTION,"window_save_position"); @@ -43,19 +40,19 @@ function window_save_position($element, $x, $y) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$element or !$x or !$y) { return($response->getXML()); } - + if (!$element or !$x or !$y) { return $response; } + // Search the DB if ($x > 0 and $y > 0 and $x < 3000 and $y < 3000) { $_SESSION['window_position']["{$element}_x"] = $x; $_SESSION['window_position']["{$element}_y"] = $y; } - - return($response->getXML()); + + return $response; } -?> \ No newline at end of file +?> diff --git a/www/include/xajax_setup.inc.php b/www/include/xajax_setup.inc.php index 943373cd..45ece90f 100644 --- a/www/include/xajax_setup.inc.php +++ b/www/include/xajax_setup.inc.php @@ -1,40 +1,23 @@ configure('deferScriptGeneration', false); +$xajax->configure('javascript URI', "${baseURL}/include/xajax/"); - -// Load various modules +// Load various modules // (registering several functions with xajax and loading additional js into the page) require_once("{$include}/xajax_drag/drag.inc.php"); $conf['html_headers'] .= '' . "\n"; @@ -62,8 +45,8 @@ -// Process xajax requests -$xajax->$xajaxProcReq(); +// Process xajax requests +$xajax->processRequest(); // Include the xajax javascript in our html headers @@ -196,33 +179,33 @@ function get_page_links($page=1, $per_page=1, $total=1, $window_name='', $form_i ////////////////////////////////////////////////////////////////////////////// // Function: // change_page (string $window_name, int $page) -// +// // Description: // This function changes the "page" a person is viewing by setting the // new page value in a hidden input field and then instructing the // browser to do an xajax callback to the display_list() function. -// +// // $form NEEDS form_id => id && page => page number ////////////////////////////////////////////////////////////////////////////// function ws_change_page($window_name, $form) { global $conf, $self; - + // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); $js = ''; - + // Basically we're going to update the value of the input field called "page" // in the "filter" form. Then we just have the browser do an xajax callback to // update the list being displayed. $js .= "el('{$form['form_id']}_page').value = '{$form['page']}';"; $js .= "xajax_window_submit('{$window_name}', xajax.getFormValues('{$form['form_id']}'), 'display_list');"; - + // Send an XML response to the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -238,14 +221,14 @@ function ws_change_page($window_name, $form) { function get_text_suggestions($q="", $table="", $field="", $max_results=10) { global $conf, $self, $onadb; $results = array(); - + // Don't return anything if we didn't get anything if (!$q or ($max_results < 1) or !$table or !$field) { return($results); } - + $where = "{$field} LIKE " . $onadb->qstr($q); $order = "{$field} ASC"; - + // Search the db for results list ($status, $rows, $records) = db_get_records( $onadb, @@ -254,14 +237,14 @@ function get_text_suggestions($q="", $table="", $field="", $max_results=10) { $order, $max_results ); - + // If the query didn't work return the error message if ($status) { $results[] = "Internal Error: {$self['error']}"; } - + foreach ($records as $record) { $results[] = $record[$field]; } - + // Return the records return($results); } @@ -281,17 +264,17 @@ function get_username_suggestions($q, $max_results=10) { ////////////////////////////////////////////////////////////////////////////// function suggest_username($q, $el_input, $el_suggest) { global $conf; - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$q or !$el_input or !$el_suggest) { return($response->getXML()); } + if (!$q or !$el_input or !$el_suggest) { return $response; } $js = ""; - + // Search the DB $results = get_username_suggestions($q); $results = array_merge($results, get_username_suggestions('%'.$q, $conf['suggest_max_results'] - count($results))); $results = array_unique($results); - + // Build the javascript to return $js .= "suggestions = Array("; $comma = ""; @@ -301,11 +284,11 @@ function suggest_username($q, $el_input, $el_suggest) { if (!$comma) { $comma = ", "; } } $js .= ");"; - + // Tell the browser to execute the javascript in $js by sending an XML response $js .= "suggest_display('{$el_input}', '{$el_suggest}');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } function suggest_tse_username($q, $el_input, $el_suggest) { return(suggest_username($q, $el_input, $el_suggest)); diff --git a/www/include/xajax_suggest/suggest.inc.php b/www/include/xajax_suggest/suggest.inc.php index 5c028014..4071a844 100755 --- a/www/include/xajax_suggest/suggest.inc.php +++ b/www/include/xajax_suggest/suggest.inc.php @@ -1,16 +1,6 @@ registerFunction("suggest"); - -// for when and if I switch to xajax 0.5.x -//$xajax->register(XAJAX_FUNCTION,"suggest"); - - - +$xajax->register(XAJAX_FUNCTION,"suggest"); ////////////////////////////////////////////////////////////////////////////// // Xajax Server @@ -24,29 +14,25 @@ //
    // // ## Now in PHP you'd create a function called "suggest_test()" -// +// // $type = suggest type // $q = query string // $el_input = input element id // $el_suggest = suggest element id -// +// ////////////////////////////////////////////////////////////////////////////// function suggest($type, $q, $el_input, $el_suggest) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$type or !$q or !$el_input or !$el_suggest) { return($response->getXML()); } - + if (!$type or !$q or !$el_input or !$el_suggest) { return $response; } + // Make sure the requested function is defined $function = 'suggest_' . $type; if (function_exists($function)) { return($function($q, $el_input, $el_suggest)); } - - return($response->getXML()); -} - - - + return $response; +} -?> \ No newline at end of file +?> diff --git a/www/include/xajax_webwin/webwin.inc.php b/www/include/xajax_webwin/webwin.inc.php index e8db9d36..c15f6e48 100755 --- a/www/include/xajax_webwin/webwin.inc.php +++ b/www/include/xajax_webwin/webwin.inc.php @@ -22,18 +22,8 @@ $color['window_tab_inactive_bg'] = '#FFFFFF'; $color['window_content_bg'] = '#F2F2F2'; - -// These are the functions we'll be exposing via Xajax -// xajax 0.2.x format -$xajax->registerFunction("window_open"); -$xajax->registerFunction("window_submit"); - -// for when and if I switch to xajax 0.5.x -//$xajax->register(XAJAX_FUNCTION,"window_submit"); -//$xajax->register(XAJAX_FUNCTION,"window_open"); - - - +$xajax->register(XAJAX_FUNCTION,"window_submit"); +$xajax->register(XAJAX_FUNCTION,"window_open"); ////////////////////////////////////////////////////////////////////////////// // Xajax Server @@ -59,7 +49,7 @@ function window_open($window_name, $window=array()) { // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if (!$window_name) { return($response->getXML()); } + if (!$window_name) { return $response; } // Variables that might be used in building HTML :: FIXME this is site specific! global $font_family, $color, $style, $images; @@ -69,7 +59,7 @@ function window_open($window_name, $window=array()) { if ($file) { require_once($file); } // Setup a header and footer for the new window - if (!$window['header']) { + if (!isset($window['header'])) { $window['header'] = << @@ -82,7 +72,7 @@ function window_open($window_name, $window=array()) {
    EOL; } - if (!$window['footer']) { + if (!isset($window['footer'])) { $window['footer'] = <<
    @@ -190,7 +190,7 @@ function(ev) { - + @@ -257,7 +257,7 @@ function(ev) { ////////////////////////////////////////////////////////////////////////////// // Function: ws_more_host_options() -// +// // Description: // Displays additional drop-downs in the advanced search form. ////////////////////////////////////////////////////////////////////////////// @@ -274,8 +274,8 @@ function ws_more_host_options($window_name, $form='') { $custom_attribute_type_list .= "\n"; unset($records, $ca); } - - + + // Build device model list list($status, $rows, $records) = db_get_records($onadb, 'models', 'id >= 1'); $models = array(); @@ -290,8 +290,8 @@ function ws_more_host_options($window_name, $form='') { $device_model_list .= "\n"; } unset($models, $model); - - + + // Build device type list list($status, $rows, $records) = db_get_records($onadb, 'roles', 'id >= 1', 'name'); $device_role_list = '\n'; @@ -299,8 +299,8 @@ function ws_more_host_options($window_name, $form='') { foreach ($records as $record) { $device_role_list .= "\n"; } - - + + // Build device manufacturer list list($status, $rows, $records) = db_get_records($onadb, 'manufacturers', 'ID >= 1', 'name'); $device_manufacturer_list = '\n'; @@ -308,8 +308,8 @@ function ws_more_host_options($window_name, $form='') { foreach ($records as $record) { $device_manufacturer_list .= "\n"; } - - + + // Build the new HTML $html = << @@ -360,15 +360,15 @@ function ws_more_host_options($window_name, $form='') { EOL; - + $js = "el('more_options_link').style.display = 'none';"; - + // Insert the new html $response = new xajaxResponse(); - $response->addAssign("more_host_options", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); - + $response->assign("more_host_options", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; + } diff --git a/www/winc/app_config_type_edit.inc.php b/www/winc/app_config_type_edit.inc.php index 37326785..988969de 100644 --- a/www/winc/app_config_type_edit.inc.php +++ b/www/winc/app_config_type_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('config_type_name').focus(); EOL; // If we got a manufacturer, load it for display @@ -59,7 +60,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -68,6 +69,7 @@ function ws_editor($window_name, $form='') {
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -142,8 +144,8 @@ function ws_save($window_name, $form='') { if(trim($form['config_type_name']) == "") { $self['error'] = "ERROR => Blank names not allowed."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } // check for an existing entry like this @@ -151,8 +153,8 @@ function ws_save($window_name, $form='') { if ($rows) { $self['error'] = "ERROR => The name you are trying to use already exists."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } // If you get a numeric in $form, update the record @@ -170,7 +172,7 @@ function ws_save($window_name, $form='') { if ($status or !$rows) { $self['error'] = "ERROR => config_type_edit update ws_save() failed: " . $self['error']; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); + $response->script("alert('{$self['error']}');"); } else { // Get the record after updating (logging) @@ -220,10 +222,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_config_type_list.inc.php b/www/winc/app_config_type_list.inc.php index d2a5adcf..25696141 100644 --- a/www/winc/app_config_type_list.inc.php +++ b/www/winc/app_config_type_list.inc.php @@ -38,17 +38,10 @@ - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -253,10 +244,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_configuration_type_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_configuration_type_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -277,8 +267,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -290,8 +280,8 @@ function ws_delete($window_name, $form='') { 'configuration_types', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Configuration type id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Configuration type id {$form} does not exist');"); + return $response; } // Get a list of device models that use this manufacturer @@ -327,8 +317,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -336,4 +326,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_custom_attribute_type_edit.inc.php b/www/winc/app_custom_attribute_type_edit.inc.php index 75cce1b7..600b9dcf 100644 --- a/www/winc/app_custom_attribute_type_edit.inc.php +++ b/www/winc/app_custom_attribute_type_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('cust_attrib_type_name').focus(); EOL; // If we got type, load it for display @@ -59,7 +60,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -68,6 +69,7 @@ function ws_editor($window_name, $form='') {
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -186,8 +188,8 @@ function ws_save($window_name, $form='') { if($form['cust_attrib_type_name'] == "") { $self['error'] = "ERROR => Blank names not allowed."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } @@ -210,7 +212,7 @@ function ws_save($window_name, $form='') { if ($status or !$rows) { $self['error'] = "ERROR => cust_attrib_type edit update ws_save() failed: " . $self['error']; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); + $response->script("alert('{$self['error']}');"); } else { // Get the manufacturer record after updating (logging) @@ -264,10 +266,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_custom_attribute_type_list.inc.php b/www/winc/app_custom_attribute_type_list.inc.php index 105f6402..a711f585 100644 --- a/www/winc/app_custom_attribute_type_list.inc.php +++ b/www/winc/app_custom_attribute_type_list.inc.php @@ -38,17 +38,10 @@ - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -246,10 +237,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_custom_attribute_type_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_custom_attribute_type_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -270,8 +260,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -283,8 +273,8 @@ function ws_delete($window_name, $form='') { 'custom_attribute_types', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Custom attribute type id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Custom attribute type id {$form} does not exist');"); + return $response; } // Get a list of device models that use this manufacturer @@ -320,8 +310,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -329,4 +319,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_device_model_edit.inc.php b/www/winc/app_device_model_edit.inc.php index 23287f74..2ae30b35 100644 --- a/www/winc/app_device_model_edit.inc.php +++ b/www/winc/app_device_model_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -71,7 +71,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -164,8 +164,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -253,10 +253,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_device_model_list.inc.php b/www/winc/app_device_model_list.inc.php index 3ac6bcb6..af914513 100644 --- a/www/winc/app_device_model_list.inc.php +++ b/www/winc/app_device_model_list.inc.php @@ -39,17 +39,10 @@
    - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -251,10 +242,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_device_model_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_device_model_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -275,8 +265,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -286,8 +276,8 @@ function ws_delete($window_name, $form='') { // Load the record to make sure it exists list($status, $rows, $device_model) = db_get_record($onadb, 'models', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Device model id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Device model id {$form} does not exist');"); + return $response; } // Get a list of device_types that use this device model @@ -317,8 +307,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -326,4 +316,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_device_role_edit.inc.php b/www/winc/app_device_role_edit.inc.php index 72157de5..d1808fcb 100644 --- a/www/winc/app_device_role_edit.inc.php +++ b/www/winc/app_device_role_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('role_name').focus(); EOL; // If we got a class type, load it for display @@ -61,7 +62,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -70,6 +71,7 @@ function ws_editor($window_name, $form='') {
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -139,13 +141,13 @@ function ws_save($window_name, $form='') { // Strip whitespace // FIXME: (PK) What about SQL injection attacks? This is a user-entered string... $form['role_name'] = trim($form['role_name']); - + // Don't insert a string of all white space! if(trim($form['role_name']) == "") { $self['error'] = "ERROR => Blank names not allowed."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } @@ -168,7 +170,7 @@ function ws_save($window_name, $form='') { else { // Get the record after updating (logging) list($status, $rows, $new_role) = ona_get_role_record(array('id' => $form['id'])); - + // Return the success notice $self['error'] = "INFO => Role UPDATED:{$new_role['id']}: {$new_role['name']}"; printmsg($self['error'], 0); @@ -213,10 +215,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_device_role_list.inc.php b/www/winc/app_device_role_list.inc.php index d71c4915..78b2dcd5 100644 --- a/www/winc/app_device_role_list.inc.php +++ b/www/winc/app_device_role_list.inc.php @@ -39,17 +39,10 @@ - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -161,11 +152,11 @@ function ws_display_list($window_name, $form) { if ($offset == 0) { $offset = -1; } // Get list of elements - list($status, $rows, $records) = db_get_records($onadb, - 'roles', - $where, - 'name', - $conf['search_results_per_page'], + list($status, $rows, $records) = db_get_records($onadb, + 'roles', + $where, + 'name', + $conf['search_results_per_page'], $offset); // If we got less than serach_results_per_page, add the current offset to it @@ -176,10 +167,10 @@ function ws_display_list($window_name, $form) { // If there were more than $conf['search_results_per_page'] find out how many records there really are else if ($rows >= $conf['search_results_per_page']) { - list ($status, $rows, $tmp) = db_get_records($onadb, - 'roles', - $where, - '', + list ($status, $rows, $tmp) = db_get_records($onadb, + 'roles', + $where, + '', 0); } $count = $rows; @@ -247,10 +238,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_role_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_role_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -271,8 +261,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -280,19 +270,19 @@ function ws_delete($window_name, $form='') { $js = ''; // Load the record to make sure it exists - list($status, $rows, $role) = db_get_record($onadb, - 'roles', + list($status, $rows, $role) = db_get_record($onadb, + 'roles', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Role id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Role id {$form} does not exist');"); + return $response; } // Get a list of device models that use this role - list($status, $rows, $devicemodels) = db_get_records($onadb, - 'models', - array('role_id' => $form), - '', + list($status, $rows, $devicemodels) = db_get_records($onadb, + 'models', + array('role_id' => $form), + '', 0); // Check that there are no parent records using this type @@ -301,8 +291,8 @@ function ws_delete($window_name, $form='') { } else { // Delete the record - list($status, $rows) = db_delete_records($onadb, - 'roles', + list($status, $rows) = db_delete_records($onadb, + 'roles', array('id' => $role['id'])); if ($status or !$rows) { @@ -321,8 +311,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -330,4 +320,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_device_type_edit.inc.php b/www/winc/app_device_type_edit.inc.php index 6334bb56..bc7391c6 100644 --- a/www/winc/app_device_type_edit.inc.php +++ b/www/winc/app_device_type_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -80,7 +80,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -151,8 +151,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -217,10 +217,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_device_type_list.inc.php b/www/winc/app_device_type_list.inc.php index ab92d9b8..e16436a8 100644 --- a/www/winc/app_device_type_list.inc.php +++ b/www/winc/app_device_type_list.inc.php @@ -39,17 +39,10 @@
    - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -153,6 +144,7 @@ function ws_display_list($window_name, $form) { EOL; + // TODO: filter does not yet work right $where = 'id > 0'; if (is_array($form) and $form['filter']) { $where = 'TODO LIKE ' . $onadb->qstr('%'.$form['filter'].'%'); @@ -254,10 +246,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_device_type_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_device_type_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -278,8 +269,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -289,8 +280,8 @@ function ws_delete($window_name, $form='') { // Load the record to make sure it exists list($status, $rows, $device_type) = db_get_record($onadb, 'device_types', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Device type id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Device type id {$form} does not exist');"); + return $response; } // Get a list of devices that use this device type @@ -320,8 +311,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -329,4 +320,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_dhcp_failover_list.inc.php b/www/winc/app_dhcp_failover_list.inc.php index b94f3d15..0485aa77 100644 --- a/www/winc/app_dhcp_failover_list.inc.php +++ b/www/winc/app_dhcp_failover_list.inc.php @@ -41,17 +41,10 @@
    - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -159,7 +150,7 @@ function ws_display_list($window_name, $form) { EOL; - // Filter currently broken.. need host-> server lookup code here + // TODO: Filter currently broken.. need host-> server lookup code here $where = 'id > 0'; if (is_array($form) and $form['filter']) { $where = 'primary_server_id LIKE ' . $onadb->qstr('%'.$form['filter'].'%'); @@ -258,10 +249,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_dhcp_failover_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_dhcp_failover_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -272,4 +262,4 @@ class="act" -?> \ No newline at end of file +?> diff --git a/www/winc/app_dhcp_option_edit.inc.php b/www/winc/app_dhcp_option_edit.inc.php index 8326de79..993ee122 100644 --- a/www/winc/app_dhcp_option_edit.inc.php +++ b/www/winc/app_dhcp_option_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('display_name').focus(); EOL; // If we got an option, load it for display @@ -73,7 +74,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -82,6 +83,7 @@ function ws_editor($window_name, $form='') { - + - +
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -253,6 +255,7 @@ function ws_save($window_name, $form='') { 'display_name' => $form['display_name'], 'type' => $form['type'], 'number' => $form['number'], + 'sys_default' => 0, 'name' => $form['name']) ); if ($status or !$rows) { @@ -276,8 +279,8 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/app_dhcp_option_list.inc.php b/www/winc/app_dhcp_option_list.inc.php index f5d73ae2..6b2a99fc 100644 --- a/www/winc/app_dhcp_option_list.inc.php +++ b/www/winc/app_dhcp_option_list.inc.php @@ -39,17 +39,10 @@ - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -275,10 +266,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_dhcp_option_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_dhcp_option_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -299,8 +289,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -310,8 +300,8 @@ function ws_delete($window_name, $form='') { // Load the record to make sure it exists list($status, $rows, $dhcp_option) = db_get_record($onadb, 'dhcp_options', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: DHCP option ID {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: DHCP option ID {$form} does not exist');"); + return $response; } // Get a list of device models that use this dhcp option @@ -342,8 +332,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -351,4 +341,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_dhcp_servers_list.inc.php b/www/winc/app_dhcp_servers_list.inc.php index 6d3c4f0f..02c59bdf 100644 --- a/www/winc/app_dhcp_servers_list.inc.php +++ b/www/winc/app_dhcp_servers_list.inc.php @@ -1,6 +1,6 @@ DHCP Servers
    - + -
    Filter
    -
    - +
    {$conf['loading_icon']} @@ -96,16 +86,15 @@ class="filter" el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Put a help icon in the title bar */ el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Setup the quick filter */ - el('{$form_id}_filter_overlay').style.left = (el('{$form_id}_filter_overlay').offsetWidth + 10) + 'px'; {$form_id}_last_search = ''; - + /* Tell the browser to load/display the list */ xajax_window_submit('{$submit_window}', xajax.getFormValues('{$form_id}'), 'display_list'); EOL; @@ -125,14 +114,7 @@ class="filter" function ws_display_list($window_name, $form) { global $conf, $self, $mysql, $onadb; global $font_family, $color, $style, $images; - - // Check permissions -// if (!auth('advanced')) { -// $response = new xajaxResponse(); -// $response->addScript("alert('Permission denied!');"); -// return($response->getXML()); -// } - + // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); @@ -143,22 +125,22 @@ function ws_display_list($window_name, $form) { // Find out what page we're on $page = 1; if ($form['page'] and is_numeric($form['page'])) { $page = $form['page']; } - - + + $html = << - + - + EOL; - + $where = 'id in (select host_id from dhcp_server_subnets group by host_id)'; if (is_array($form) and $form['filter']) { //$where = 'name like ' . $onadb->qstr('%'.$form['filter'].'%'); @@ -166,10 +148,10 @@ function ws_display_list($window_name, $form) { // Offset for SQL query $offset = ($conf['search_results_per_page'] * ($page - 1)); if ($offset == 0) { $offset = -1; } - + // Get list of elements list($status, $rows, $records) = db_get_records($onadb, 'hosts', $where, '', $conf['search_results_per_page'], $offset); - + //$records = array_unique(array_slice($dnsservers,1,1)); // If we got less than search_results_per_page, add the current offset to it @@ -177,14 +159,14 @@ function ws_display_list($window_name, $form) { if ($rows > 0 and $rows < $conf['search_results_per_page']) { $rows += ($conf['search_results_per_page'] * ($page - 1)); } - + // If there were more than $conf['search_results_per_page'] find out how many records there really are else if ($rows >= $conf['search_results_per_page']) { list ($status, $rows, $tmp) = db_get_records($onadb, 'hosts', $where, '', 0); } $count = $rows; - - + + // Loop through and display foreach ($records as $record) { @@ -215,7 +197,7 @@ class="act" - +
    Server name Subnet count  
    {$usage_rows} EOL; } - + $html .= << - + EOL; - - + + // Build page links if there are any $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); - - + + // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_domain_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_domain_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -270,4 +251,4 @@ class="act" -?> \ No newline at end of file +?> diff --git a/www/winc/app_dns_view_edit.inc.php b/www/winc/app_dns_view_edit.inc.php index cc32aa20..977da235 100644 --- a/www/winc/app_dns_view_edit.inc.php +++ b/www/winc/app_dns_view_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('dns_view_name').focus(); EOL; // If an array in a string was provided, build the array and store it in $form @@ -60,7 +61,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -69,6 +70,7 @@ function ws_editor($window_name, $form='') { - + - +
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -162,8 +164,8 @@ function ws_save($window_name, $form='') { if(trim($form['dns_view_name']) == "") { $self['error'] = "ERROR => Blank names not allowed."; printmsg($self['error'], 1); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } @@ -180,8 +182,8 @@ function ws_save($window_name, $form='') { if ($rows) { $self['error'] = "ERROR => The name you are trying to use already exists."; printmsg($self['error'], 1); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } $SET['name'] = strtoupper($form['dns_view_name']); } @@ -191,7 +193,7 @@ function ws_save($window_name, $form='') { if ($status or !$rows) { $self['error'] = "ERROR => dns_view_edit update ws_save() failed: " . $self['error']; printmsg($self['error'], 1); - $response->addScript("alert('{$self['error']}');"); + $response->script("alert('{$self['error']}');"); } else { // Get the record after updating (logging) @@ -213,8 +215,8 @@ function ws_save($window_name, $form='') { if ($rows) { $self['error'] = "ERROR => The name you are trying to use already exists."; printmsg($self['error'], 1); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } $id = ona_get_next_id('dns_views'); @@ -252,10 +254,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_dns_view_list.inc.php b/www/winc/app_dns_view_list.inc.php index 4d5199f4..060b273e 100644 --- a/www/winc/app_dns_view_list.inc.php +++ b/www/winc/app_dns_view_list.inc.php @@ -38,17 +38,10 @@ - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -271,10 +262,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_dns_view_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_dns_view_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -295,8 +285,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -305,8 +295,8 @@ function ws_delete($window_name, $form='') { // Don't allow them to delete the default if ($form == 0) { - $response->addScript("alert('You are not allowed to delete the default DNS view.');"); - return($response->getXML()); + $response->script("alert('You are not allowed to delete the default DNS view.');"); + return $response; } // Load the record to make sure it exists @@ -314,8 +304,8 @@ function ws_delete($window_name, $form='') { 'dns_views', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: DNS view id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: DNS view id {$form} does not exist');"); + return $response; } // Get a list of device models that use this manufacturer @@ -351,8 +341,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -360,4 +350,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_domain_list.inc.php b/www/winc/app_domain_list.inc.php index 6f6c87bc..8898cc05 100644 --- a/www/winc/app_domain_list.inc.php +++ b/www/winc/app_domain_list.inc.php @@ -1,6 +1,6 @@ Domains
    - + -
    Filter
    -
    - +
    {$conf['loading_icon']} @@ -96,16 +86,15 @@ class="filter" el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Put a help icon in the title bar */ el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Setup the quick filter */ - el('{$form_id}_filter_overlay').style.left = (el('{$form_id}_filter_overlay').offsetWidth + 10) + 'px'; {$form_id}_last_search = ''; - + /* Tell the browser to load/display the list */ xajax_window_submit('{$submit_window}', xajax.getFormValues('{$form_id}'), 'display_list'); EOL; @@ -121,18 +110,11 @@ class="filter" -// This function displays a list (all?) network types +// This function displays a list (all?) network types function ws_display_list($window_name, $form) { global $conf, $self, $mysql, $onadb; global $font_family, $color, $style, $images; - - // Check permissions -// if (!auth('advanced')) { -// $response = new xajaxResponse(); -// $response->addScript("alert('Permission denied!');"); -// return($response->getXML()); -// } - + // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); @@ -143,13 +125,13 @@ function ws_display_list($window_name, $form) { // Find out what page we're on $page = 1; if ($form['page'] and is_numeric($form['page'])) { $page = $form['page']; } - - + + $html = << - + @@ -157,9 +139,9 @@ function ws_display_list($window_name, $form) { - + EOL; - + $where = 'ID > 0'; if (is_array($form) and $form['filter']) { $where = 'name like ' . $onadb->qstr('%'.$form['filter'].'%'); @@ -167,23 +149,23 @@ function ws_display_list($window_name, $form) { // Offset for SQL query $offset = ($conf['search_results_per_page'] * ($page - 1)); if ($offset == 0) { $offset = -1; } - + // Get list of elements list($status, $rows, $records) = db_get_records($onadb, 'domains', $where, 'name', $conf['search_results_per_page'], $offset); - + // If we got less than search_results_per_page, add the current offset to it // so that if we're on the last page $rows still has the right number in it. if ($rows > 0 and $rows < $conf['search_results_per_page']) { $rows += ($conf['search_results_per_page'] * ($page - 1)); } - + // If there were more than $conf['search_results_per_page'] find out how many records there really are else if ($rows >= $conf['search_results_per_page']) { list ($status, $rows, $tmp) = db_get_records($onadb, 'domains', $where, '', 0); } $count = $rows; - - + + // Loop through and display foreach ($records as $record) { @@ -192,14 +174,14 @@ function ws_display_list($window_name, $form) { $parent['name'] = ona_build_domain_name($parent['id']); } $record['parent_domain_name'] = $parent['name']; - + // Need to remove this variable, otherwise, if the current record does not have a parent // the previous parent domain name will be displayed unset($parent['name']); // make the name an fqdn $record['name'] = ona_build_domain_name($record['id']); - + // Escape data for display in html foreach(array_keys($record) as $key) { $record[$key] = htmlentities($record[$key], ENT_QUOTES, $conf['php_charset']); @@ -239,7 +221,7 @@ class="act" - + EOL; } - + $html .= << - +
    Add DNS domain 
    EOL; - - + + // Build page links if there are any $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); - - + + // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_domain_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_domain_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -311,4 +292,4 @@ class="act" -?> \ No newline at end of file +?> diff --git a/www/winc/app_domain_servers_list.inc.php b/www/winc/app_domain_servers_list.inc.php index ced4c0f0..0249aa7a 100644 --- a/www/winc/app_domain_servers_list.inc.php +++ b/www/winc/app_domain_servers_list.inc.php @@ -1,6 +1,6 @@ Domain Servers - +
    - +
    Domain nameRecords in domain  
    {$usage_rows} - +
    - + -
    Filter
    -
    - +
    {$conf['loading_icon']} @@ -96,16 +88,15 @@ class="filter" el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Put a help icon in the title bar */ el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Setup the quick filter */ - el('{$form_id}_filter_overlay').style.left = (el('{$form_id}_filter_overlay').offsetWidth + 10) + 'px'; {$form_id}_last_search = ''; - + /* Tell the browser to load/display the list */ xajax_window_submit('{$submit_window}', xajax.getFormValues('{$form_id}'), 'display_list'); EOL; @@ -121,18 +112,11 @@ class="filter" -// This function displays a list (all?) network types +// This function displays a list (all?) network types function ws_display_list($window_name, $form) { global $conf, $self, $mysql, $onadb; global $font_family, $color, $style, $images; - - // Check permissions -// if (!auth('advanced')) { -// $response = new xajaxResponse(); -// $response->addScript("alert('Permission denied!');"); -// return($response->getXML()); -// } - + // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); @@ -143,22 +127,23 @@ function ws_display_list($window_name, $form) { // Find out what page we're on $page = 1; if ($form['page'] and is_numeric($form['page'])) { $page = $form['page']; } - - + + $html = << - + - + EOL; - + + // TODO: filter does not yet work $where = 'id in (select host_id from dns_server_domains group by host_id)'; if (is_array($form) and $form['filter']) { //$where = 'name like ' . $onadb->qstr('%'.$form['filter'].'%'); @@ -166,10 +151,10 @@ function ws_display_list($window_name, $form) { // Offset for SQL query $offset = ($conf['search_results_per_page'] * ($page - 1)); if ($offset == 0) { $offset = -1; } - + // Get list of elements list($status, $rows, $records) = db_get_records($onadb, 'hosts', $where, '', $conf['search_results_per_page'], $offset); - + //$records = array_unique(array_slice($dnsservers,1,1)); // If we got less than search_results_per_page, add the current offset to it @@ -177,14 +162,14 @@ function ws_display_list($window_name, $form) { if ($rows > 0 and $rows < $conf['search_results_per_page']) { $rows += ($conf['search_results_per_page'] * ($page - 1)); } - + // If there were more than $conf['search_results_per_page'] find out how many records there really are else if ($rows >= $conf['search_results_per_page']) { list ($status, $rows, $tmp) = db_get_records($onadb, 'hosts', $where, '', 0); } $count = $rows; - - + + // Loop through and display foreach ($records as $record) { @@ -215,7 +200,7 @@ class="act" - +
    Server name Domain count  
    {$usage_rows} EOL; } - + $html .= << - + EOL; - - + + // Build page links if there are any $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); - - + + // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_domain_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_domain_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -281,4 +265,4 @@ class="act" -?> \ No newline at end of file +?> diff --git a/www/winc/app_full_list.inc.php b/www/winc/app_full_list.inc.php index 471bf35b..36695c31 100644 --- a/www/winc/app_full_list.inc.php +++ b/www/winc/app_full_list.inc.php @@ -60,7 +60,7 @@ function ws_display($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; - + /* Put a help icon in the title bar */ el('{$window_name}_title_r').innerHTML = ' ' + @@ -79,33 +79,33 @@ function ws_display($window_name, $form='') { if(array_key_exists('ip',$form) && array_key_exists('ip_thru',$form) ) { // Set the window title: $window['subtitle'] = "Range: {$form['ip']} to {$form['ip_thru']}"; - + // Define javascript to run after the window is created $window['js'] .= <<{$form['ip']},ip_thru=>{$form['ip_thru']},form_id=>{$form_id},content_id=>{$content_id}', 'display_list'); - + EOL; - + } if(array_key_exists('subnet_id',$form)) { list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $form['subnet_id'])); - + // Set the window title: $window['subtitle'] = "Subnet: {$subnet['name']}"; - + // Define javascript to run after the window is created $window['js'] .= <<{$form['subnet_id']},form_id=>{$form_id},content_id=>{$content_id}', 'display_list'); - + EOL; - - } + + } $window['html'] .= <<
    - + @@ -120,7 +120,7 @@ function ws_display($window_name, $form='') {
    {$conf['loading_icon']}
    - + EOL; @@ -130,7 +130,7 @@ function ws_display($window_name, $form='') { ////////////////////////////////////////////////////////////////////////////// // Function: ws_display_list() -// +// // Description: // Displays A list of hosts based on search criteria. // Input: An array from xajaxGetFormValues() from a quick filter form. @@ -140,27 +140,27 @@ function ws_display_list($window_name, $form='') { global $images, $color, $style; $html = ''; $js = ''; - + // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); - + // Find the "tab" we're on $tab = $_SESSION['ona'][$form['form_id']]['tab']; - + // Build js to refresh this list $refresh = "xajax_window_submit('{$window_name}', xajax.getFormValues('{$form['form_id']}'), 'display_list');"; - - + + // Search results go in here $results = array(); $count = 0; - - + + // NETWORK ID if (is_numeric($form['subnet_id'])) { - + } - + // Do the SQL Query list ($status, $count, $results) = db_get_records( @@ -177,7 +177,7 @@ function ws_display_list($window_name, $form='') { foreach($results as $record) { $iplist["{$record['ip_addr']}"]='used'; } - + list($status, $rows, $subnet) = ona_find_subnet($form['subnet_id']); // Create a few variables that will be handy later @@ -196,14 +196,14 @@ function ws_display_list($window_name, $form='') { foreach ($pools as $pool) for ($ip = $pool['ip_addr_start']; $ip <= $pool['ip_addr_end']; $ip++) $iplist["{$ip}"] = 'pool-'.$pool['id']; - + // // *** BUILD HTML LIST *** // $html .= <<
    - + @@ -249,7 +249,7 @@ class="act" class="act" onClick="xajax_window_submit('edit_interface', 'ip_addr=>{$currip_txt}', 'editor');" >Add interface to an existing host  - + EOL; // If the current ip is one allocated on this subnet lets do some stuff @@ -267,7 +267,7 @@ class="act" class="act" onClick="xajax_window_submit('edit_dhcp_pool', 'subnet=>{$subnet['id']},id=>{$poolid}', 'editor');" >  - + - + EOL; // Print color info for any matching blocks @@ -437,8 +437,8 @@ class="domain" $html .= << EOL; - - + + $js .= <<addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/app_group_edit.inc.php b/www/winc/app_group_edit.inc.php index 0e33f79e..59bdff70 100644 --- a/www/winc/app_group_edit.inc.php +++ b/www/winc/app_group_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('user_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } $window['js'] .= <<' + el('{$window_name}_title_r').innerHTML; + el('group_name').focus(); EOL; // Set a few parameters for the "results" window we're about to create @@ -44,7 +45,7 @@ function ws_editor($window_name, $form='') { // If we got a group ID, load it for display if (is_string($form) and $form) { - list($status, $rows, $record) = db_get_record($onadb, 'groups', array('id' => $form)); + list($status, $rows, $record) = db_get_record($onadb, 'auth_groups', array('id' => $form)); } // Build some html for selecting the groups the group is in @@ -57,7 +58,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - +
    B
    @@ -66,6 +67,7 @@ function ws_editor($window_name, $form='') {
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -149,13 +151,13 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['name']) { $js .= "alert('Error! All fields are required!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } if (!preg_match('/^[A-Za-z0-9.\-_ ]+$/', $form['name'])) { $js .= "alert('Invalid group name! Valid characters: A-Z 0-9 .-_ and space');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } //MP: zero out the level for now @@ -166,7 +168,7 @@ function ws_save($window_name, $form='') { if (!$form['id']) { list ($status, $rows) = db_insert_record( $onadb, - 'groups', + 'auth_groups', array( 'name' => $form['name'], 'description' => $form['description'], @@ -187,16 +189,16 @@ function ws_save($window_name, $form='') { // Update an existing record? else { - list($status, $rows, $record) = db_get_record($onadb, 'groups', array('id' => $form['id'])); + list($status, $rows, $record) = db_get_record($onadb, 'auth_groups', array('id' => $form['id'])); if ($rows != 1 or $record['id'] != $form['id']) { $js .= "alert('Error! The record requested could not be loaded from the database!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } list ($status, $rows) = db_update_record( $onadb, - 'groups', + 'auth_groups', array( 'id' => $form['id'], ), @@ -211,7 +213,7 @@ function ws_save($window_name, $form='') { printmsg($self['error'], 0); } else { - list($status, $rows, $new_record) = db_get_record($onadb, 'groups', array('id' => $form['id'])); + list($status, $rows, $new_record) = db_get_record($onadb, 'auth_groups', array('id' => $form['id'])); // Return the success notice $self['error'] = "INFO => Group UPDATED:{$record['id']}: {$record['name']}"; @@ -243,9 +245,9 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_group_list.inc.php b/www/winc/app_group_list.inc.php index 4d7b09c3..edfd5316 100644 --- a/www/winc/app_group_list.inc.php +++ b/www/winc/app_group_list.inc.php @@ -28,7 +28,7 @@ // Load some html into $window['html'] $form_id = "{$window_name}_filter_form"; -$tab = 'groups'; +$tab = 'auth_groups'; $submit_window = $window_name; $content_id = "{$window_name}_list"; $window['html'] .= << - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the group supplied an array in a string, build the array and store it in $form @@ -163,7 +154,7 @@ function ws_display_list($window_name, $form) { if ($offset == 0) { $offset = -1; } // Get our groups - list($status, $rows, $records) = db_get_records($onadb, 'groups', $where, 'name', $conf['search_results_per_page'], $offset); + list($status, $rows, $records) = db_get_records($onadb, 'auth_groups', $where, 'name', $conf['search_results_per_page'], $offset); // If we got less than serach_results_per_page, add the current offset to it // so that if we're on the last page $rows still has the right number in it. @@ -173,7 +164,7 @@ function ws_display_list($window_name, $form) { // If there were more than $conf['search_results_per_page'] find out how many records there really are else if ($rows >= $conf['search_results_per_page']) { - list ($status, $rows, $tmp) = db_get_records($onadb, 'groups', $where, '', 0); + list ($status, $rows, $tmp) = db_get_records($onadb, 'auth_groups', $where, '', 0); } $count = $rows; @@ -249,10 +240,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_groups_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_groups_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -273,8 +263,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('user_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -282,10 +272,10 @@ function ws_delete($window_name, $form='') { $js = ''; // Load the group record to make sure it exists - list($status, $rows, $group) = db_get_record($onadb, 'groups', array('id' => $form)); + list($status, $rows, $group) = db_get_record($onadb, 'auth_groups', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Group ID {$form} doesnt exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Group ID {$form} doesnt exist');"); + return $response; } // Delete the group assignments that reference our group id @@ -299,7 +289,7 @@ function ws_delete($window_name, $form='') { } while ($rows >= 1); // Delete the group's record - list($status, $rows) = db_delete_records($onadb, 'groups', array('id' => $group['id'])); + list($status, $rows) = db_delete_records($onadb, 'auth_groups', array('id' => $group['id'])); if ($status or !$rows) { // If the module returned an error code display a popup warning @@ -316,8 +306,8 @@ function ws_delete($window_name, $form='') { // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -325,4 +315,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_keyboard_shortcuts.inc.php b/www/winc/app_keyboard_shortcuts.inc.php new file mode 100644 index 00000000..1ffc3ba1 --- /dev/null +++ b/www/winc/app_keyboard_shortcuts.inc.php @@ -0,0 +1,79 @@ +' + + el('{$window_name}_title_r').innerHTML; + + /* Put a help icon in the title bar */ + el('{$window_name}_title_r').innerHTML = + ' ' + + el('{$window_name}_title_r').innerHTML; + +EOL; + +global $conf; + +$window['html'] .= << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Jumping +
    g then s: Focus the quicksearch box
    g then c: Open IP Calculator
    g then h: Open main Home screen
    g then l: Open login popup
     
    + Advanced search Tab +
    s then b: Block search tab
    s then v: Vlan Campus search tab
    s then s: Subnet search tab
    s then h: Host search tab
    s then d: DNS domain search tab
     
    + Add New +
    a then h: Add new Host
    a then i: Add new Interface
    a then s: Add new Subnet
    a then d: Add new DNS record
    a then D: Add new DNS domain
    a then v: Add new Vlan
    a then V: Add new Vlan Campus
    a then b: Add new Block
    a then l: Add new Location
    + + + +EOL; + + + + +?> diff --git a/www/winc/app_location_list.inc.php b/www/winc/app_location_list.inc.php index a5d2a1ee..a9fb0949 100644 --- a/www/winc/app_location_list.inc.php +++ b/www/winc/app_location_list.inc.php @@ -41,17 +41,10 @@
    - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -242,12 +233,12 @@ class="act"   Add new location  EOL; @@ -260,10 +251,10 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_locations_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_locations_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + $response->script($js); + return $response; } @@ -284,8 +275,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('location_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -305,7 +296,7 @@ function ws_delete($window_name, $form='') { // Delete the record list($status, $output) = run_module('location_del', array('reference' => $form['id'], 'commit' => 'Y')); - + // If the module returned an error code display a popup warning if ($status != 0) { $js .= "alert('Delete failed:" . trim($self['error']) . ");"; @@ -321,8 +312,8 @@ function ws_delete($window_name, $form='') { } // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -330,4 +321,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_manufacturer_edit.inc.php b/www/winc/app_manufacturer_edit.inc.php index 87085b40..c670f125 100644 --- a/www/winc/app_manufacturer_edit.inc.php +++ b/www/winc/app_manufacturer_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('manufacturer_name').focus(); EOL; // If we got a manufacturer, load it for display @@ -59,7 +60,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -68,6 +69,7 @@ function ws_editor($window_name, $form='') {
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); $js = ''; @@ -137,13 +139,13 @@ function ws_save($window_name, $form='') { // Strip whitespace // FIXME: (PK) What about SQL injection attacks? This is a user-entered string... $form['manufacturer_name'] = trim($form['manufacturer_name']); - + // Don't insert a string of all white space! if(trim($form['manufacturer_name']) == "") { $self['error'] = "ERROR => Blank names not allowed."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } @@ -162,12 +164,12 @@ function ws_save($window_name, $form='') { if ($status or !$rows) { $self['error'] = "ERROR => manufacturer_edit update ws_save() failed: " . $self['error']; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); + $response->script("alert('{$self['error']}');"); } else { // Get the manufacturer record after updating (logging) list($status, $rows, $new_manufacturer) = ona_get_manufacturer_record(array('id' => $form['id'])); - + // Return the success notice $self['error'] = "INFO => Manufacturer UPDATED:{$new_manufacturer['id']}: {$new_manufacturer['name']}"; printmsg($self['error'], 0); @@ -186,9 +188,9 @@ function ws_save($window_name, $form='') { } else { printmsg("DEBUG => id for new manufacturer record: $id", 3); - list($status, $rows) = db_insert_record($onadb, - "manufacturers", - array('id' => $id, + list($status, $rows) = db_insert_record($onadb, + "manufacturers", + array('id' => $id, 'name' => trim($form['manufacturer_name']))); if ($status or !$rows) { @@ -198,10 +200,10 @@ function ws_save($window_name, $form='') { else { $self['error'] = "INFO => Manufacturer ADDED: {$form['manufacturer_name']} "; printmsg($self['error'], 0); - } + } } } - + // If the module returned an error code display a popup warning if ($status or !$rows) { $js .= "alert(\"Save failed. ". trim($self['error']) . " (Hint: Does the name you're trying to insert already exist?)\");"; @@ -212,10 +214,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_manufacturer_list.inc.php b/www/winc/app_manufacturer_list.inc.php index bb5f2470..f5004ce2 100644 --- a/www/winc/app_manufacturer_list.inc.php +++ b/www/winc/app_manufacturer_list.inc.php @@ -38,17 +38,10 @@ - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -228,12 +219,12 @@ class="act"   Add manufacturer  EOL; @@ -246,10 +237,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_manufacturer_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_manufacturer_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -270,8 +260,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -283,8 +273,8 @@ function ws_delete($window_name, $form='') { 'manufacturers', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Manufacturer id {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Manufacturer id {$form} does not exist');"); + return $response; } // Get a list of device models that use this manufacturer @@ -320,8 +310,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -329,4 +319,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_permission_editor.inc.php b/www/winc/app_permission_editor.inc.php index 1d7b235f..1fe7789b 100644 --- a/www/winc/app_permission_editor.inc.php +++ b/www/winc/app_permission_editor.inc.php @@ -21,8 +21,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('user_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -49,7 +49,7 @@ function ws_editor($window_name, $form='') { // If we got a group ID, load it and it's permissions if ($form['group_id']) { - list($status, $rows, $group) = db_get_record($onadb, 'groups', array('id' => $form['group_id'])); + list($status, $rows, $group) = db_get_record($onadb, 'auth_groups', array('id' => $form['group_id'])); list($status, $rows, $perms) = db_get_records($onadb, 'permission_assignments', array('group_id' => $group['id'])); $form['type'] = 'group_id'; $form['id'] = $group['id']; @@ -74,7 +74,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -145,8 +145,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('user_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -194,10 +194,10 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_plugin_list.inc.php b/www/winc/app_plugin_list.inc.php index 22bde317..68ab0773 100644 --- a/www/winc/app_plugin_list.inc.php +++ b/www/winc/app_plugin_list.inc.php @@ -40,17 +40,10 @@
    - + -
    Name
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the group supplied an array in a string, build the array and store it in $form @@ -302,10 +293,10 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_plugins_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_plugins_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + $response->script($js); + return $response; } @@ -331,8 +322,8 @@ function ws_toggleenable($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -361,8 +352,8 @@ function ws_toggleenable($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/app_report_list.inc.php b/www/winc/app_report_list.inc.php index 3bf5b89e..4d410103 100644 --- a/www/winc/app_report_list.inc.php +++ b/www/winc/app_report_list.inc.php @@ -40,17 +40,10 @@
    - + -
    Name
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the group supplied an array in a string, build the array and store it in $form @@ -233,14 +224,13 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_reports_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_reports_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_subnet_type_edit.inc.php b/www/winc/app_subnet_type_edit.inc.php index 2985ec78..2bd72f6b 100644 --- a/www/winc/app_subnet_type_edit.inc.php +++ b/www/winc/app_subnet_type_edit.inc.php @@ -5,7 +5,7 @@ ////////////////////////////////////////////////////////////////////////////// // Function: // Display Edit Form -// +// // Description: // Displays a form for creating/editing subnet types. // If a subnet type id is found in $form it is used to display an existing @@ -15,46 +15,47 @@ function ws_editor($window_name, $form='') { global $conf, $self, $onadb; global $font_family, $color, $style, $images; - + // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - + // Set a few parameters for the "results" window we're about to create $window = array( 'title' => 'Subnet Type Editor', 'html' => '', 'js' => '', ); - + $window['js'] .= <<' + el('{$window_name}_title_r').innerHTML; - + /* Put a help icon in the title bar */ el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('subnet_type_name').focus(); EOL; - + // If we got a subnet type, load it for display if (is_numeric($form)) { list($status, $rows, $record) = db_get_record($onadb, 'subnet_types', array('id' => $form)); } - + // Escape data for display in html foreach(array_keys((array)$record) as $key) { $record[$key] = htmlentities($record[$key], ENT_QUOTES, $conf['php_charset']); } - + // Load some html into $window['html'] $window['html'] .= << - + @@ -62,34 +63,35 @@ function ws_editor($window_name, $form='') { Display Name - + - + - + - + @@ -104,7 +106,7 @@ class="edit" > - + - +
    -
    Short Name -
    Notes
      @@ -119,16 +121,16 @@ class="edit" >
    - + EOL; - - + + // Lets build a window and display the results return(window_open($window_name, $window)); - + } @@ -146,33 +148,33 @@ class="edit" ////////////////////////////////////////////////////////////////////////////// function ws_save($window_name, $form='') { global $conf, $self, $onadb; - + // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); $js = ''; - + // Validate Input if ($form['short_name'] == '' or $form['display_name'] == '' ) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all fields to continue!');"); + return $response; } - + // BUSINESS RULE: Force short_name to be console friendly (a-z,-, & _ only) $form['short_name'] = strtolower($form['short_name']); if (!preg_match('/^[\w-_]+$/', $form['short_name'])) { - $response->addScript("alert('Invalid short name! Please use only script-friendly characters: a-z - _ (no spaces)');"); - return($response->getXML()); + $response->script("alert('Invalid short name! Please use only script-friendly characters: a-z - _ (no spaces)');"); + return $response; } - + // If you get a numeric in $form, update the record if (is_numeric($form['id'])) { list($status, $rows) = db_update_record( @@ -191,7 +193,7 @@ function ws_save($window_name, $form='') { $id = ona_get_next_id('subnet_types'); list($status, $rows) = db_insert_record($onadb, 'subnet_types', array('id' => $id, 'display_name' => $form['display_name'], 'short_name' => $form['short_name'], 'notes' => $form['notes'])); } - + // If the module returned an error code display a popup warning if ($status) { $js .= "alert('Save failed. ". trim($self['error']) . " (Hint: All fields are required!)');"; @@ -200,12 +202,12 @@ function ws_save($window_name, $form='') { $js .= "removeElement('{$window_name}');"; $js .= "xajax_window_submit('app_subnet_type_list', xajax.getFormValues('app_subnet_type_list_filter_form'), 'display_list');"; } - + // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_subnet_type_list.inc.php b/www/winc/app_subnet_type_list.inc.php index 49ea02e7..12723a3a 100644 --- a/www/winc/app_subnet_type_list.inc.php +++ b/www/winc/app_subnet_type_list.inc.php @@ -39,17 +39,10 @@
    -
    + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -253,10 +244,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_subnet_type_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_subnet_type_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -277,8 +267,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -288,8 +278,8 @@ function ws_delete($window_name, $form='') { // Load the record to make sure it exists list($status, $rows, $subnet_type) = db_get_record($onadb, 'subnet_types', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: Subnet type ID {$form} doesnt exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: Subnet type ID {$form} doesnt exist');"); + return $response; } // Get a list of subnets that use this subnet type @@ -313,8 +303,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -322,4 +312,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_sysconf_edit.inc.php b/www/winc/app_sysconf_edit.inc.php index bd2d0841..b9818acb 100644 --- a/www/winc/app_sysconf_edit.inc.php +++ b/www/winc/app_sysconf_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,7 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + el('conf_name').focus(); EOL; // If we got a class type, load it for display @@ -65,7 +66,7 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + @@ -80,6 +81,7 @@ function ws_editor($window_name, $form='') {
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -189,8 +191,8 @@ function ws_save($window_name, $form='') { if(trim($form['name']) == "") { $self['error'] = "ERROR => Blank names not allowed."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } @@ -204,8 +206,8 @@ function ws_save($window_name, $form='') { if ($original_sysconf['editable'] == 0) { $self['error'] = "ERROR => This system config entry is not editable."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } if($form['value'] !== $original_sysconf['value'] or $form['description'] !== $original_sysconf['description']) { @@ -232,8 +234,8 @@ function ws_save($window_name, $form='') { } else { $self['error'] = "INFO => You have not made a change to the value or description."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } } // If you get nothing in $form, create a new record @@ -243,8 +245,8 @@ function ws_save($window_name, $form='') { if ($rows) { $self['error'] = "ERROR => The name you are trying to use already exists."; printmsg($self['error'], 0); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } list($status, $rows) = db_insert_record($onadb, @@ -276,8 +278,8 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/app_sysconf_list.inc.php b/www/winc/app_sysconf_list.inc.php index d8f4b737..44cfe8c8 100644 --- a/www/winc/app_sysconf_list.inc.php +++ b/www/winc/app_sysconf_list.inc.php @@ -15,6 +15,7 @@ // // +global $images,$conf; // Check permissions if (!auth('advanced')) { @@ -30,7 +31,7 @@ $tab = 'sysconf'; $submit_window = $window_name; $content_id = "{$window_name}_list"; -$window['html'] .= << @@ -39,17 +40,10 @@
    - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -270,10 +262,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_sysconf_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_sysconf_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -294,8 +285,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -307,8 +298,8 @@ function ws_delete($window_name, $form='') { 'sys_config', array('name' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: sys_config entry {$form} does not exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: sys_config entry {$form} does not exist');"); + return $response; } // Delete the record @@ -332,8 +323,8 @@ function ws_delete($window_name, $form='') { $js .= "xajax_window_submit('$window_name', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -341,4 +332,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/app_user_edit.inc.php b/www/winc/app_user_edit.inc.php index c723dde6..827c296c 100644 --- a/www/winc/app_user_edit.inc.php +++ b/www/winc/app_user_edit.inc.php @@ -19,8 +19,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('user_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Set a few parameters for the "results" window we're about to create @@ -40,6 +40,8 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML = ' ' + el('{$window_name}_title_r').innerHTML; + + el('username').focus(); EOL; // If we got a user ID, load it for display @@ -53,12 +55,12 @@ function ws_editor($window_name, $form='') { $user_groups = array(); list($status, $rows, $records) = db_get_records($onadb, 'group_assignments', array('user_id' => $user['id'])); foreach ($records as $record) { - list($status, $rows, $g) = db_get_record($onadb, 'groups', array('id' => $record['group_id'])); + list($status, $rows, $g) = db_get_record($onadb, 'auth_groups', array('id' => $record['group_id'])); $user_groups[$g['name']] = $g['id']; } // Get all the groups from the database - list($status, $rows, $allgroups) = db_get_records($onadb, 'groups', 'id > 0'); + list($status, $rows, $allgroups) = db_get_records($onadb, 'auth_groups', 'id > 0'); $group_check_list = ""; foreach ($allgroups as $group) { @@ -76,8 +78,15 @@ function ws_editor($window_name, $form='') { $window['html'] .= << - + +EOL; + if ($overwrite == 'yes') { + $window['html'] .= << +EOL; + } + + $window['html'] .= << @@ -86,6 +95,7 @@ function ws_editor($window_name, $form='') { - @@ -124,7 +121,7 @@
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -180,13 +190,13 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['username']) { $js .= "alert('Error! All fields are required!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } if (!preg_match('/^[A-Za-z0-9.\-_]+$/', $form['username'])) { $js .= "alert('Invalid username! Valid characters: A-Z 0-9 .-_');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } // Create a new record? @@ -197,6 +207,7 @@ function ws_save($window_name, $form='') { array( 'username' => $form['username'], 'password' => $form['password'], + 'ctime' => date('Y-m-j G:i:s',time()), ) ); if ($status or !$rows) { @@ -215,8 +226,8 @@ function ws_save($window_name, $form='') { list($status, $rows, $user) = db_get_record($onadb, 'users', array('id' => $form['user_id'])); if ($rows != 1 or $user['id'] != $form['user_id']) { $js .= "alert('Error! The record requested could not be loaded from the database!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } list ($status, $rows) = db_update_record( @@ -258,8 +269,8 @@ function ws_save($window_name, $form='') { if ($status or $rows != 1) { $js .= "alert('Save failed: " . trim($self['error']) . "');"; // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -270,7 +281,7 @@ function ws_save($window_name, $form='') { // Get a list of every group - list($status, $rows, $groups) = db_get_records($onadb, 'groups', 'id > 0'); + list($status, $rows, $groups) = db_get_records($onadb, 'auth_groups', 'id > 0'); // Loop through each group foreach ($groups as $group) { @@ -279,7 +290,7 @@ function ws_save($window_name, $form='') { $exit_status += $status; // If the user is supposed to be assigned to this group, make sure she is. - if (array_key_exists($group['name'], $form['groups'])) { + if (isset($form['groups']) and array_key_exists($group['name'], $form['groups'])) { if ($status == 0 and $rows == 0) { list($status, $rows) = db_insert_record($onadb, 'group_assignments', array('user_id' => $user['id'], 'group_id' => $group['id'])); $log_msg .= $more . "group_add[" . $group['name'] . "]"; @@ -314,11 +325,11 @@ function ws_save($window_name, $form='') { } // Return some javascript to the browser - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/app_user_info.inc.php b/www/winc/app_user_info.inc.php index 2a10ce97..61221b4b 100644 --- a/www/winc/app_user_info.inc.php +++ b/www/winc/app_user_info.inc.php @@ -47,9 +47,6 @@
    {$output['ona_username']}
    -
    -
    - + -
    Filter
    addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -245,10 +236,9 @@ class="act" // Insert the new table into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_users_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_users_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -269,8 +259,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('user_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -280,8 +270,8 @@ function ws_delete($window_name, $form='') { // Load the user record to make sure it exists list($status, $rows, $user) = db_get_record($onadb, 'users', array('id' => $form)); if ($status or !$rows) { - $response->addScript("alert('Delete failed: User ID {$form} doesnt exist');"); - return($response->getXML()); + $response->script("alert('Delete failed: User ID {$form} doesnt exist');"); + return $response; } // Delete the user's group assignments @@ -311,8 +301,8 @@ function ws_delete($window_name, $form='') { } // Send an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/display_block.inc.php b/www/winc/display_block.inc.php index cf795944..8f4c2e63 100644 --- a/www/winc/display_block.inc.php +++ b/www/winc/display_block.inc.php @@ -25,8 +25,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Block doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title @@ -148,7 +148,6 @@ class="act" // SMALL SUBNET MAP // Get the numeric IP address of our subnet (we replace the last quad with a .0) - $ip_subnet = ip_mangle($record['ip_addr_start'], 'numeric'); if (is_ipv4($ip_subnet)) { @@ -255,20 +254,12 @@ class="act"
    - + -
    Name
    addIncludeScript('include/js/bignumber.js'); - $response->addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js . $portal_js); } - return($response->getXML()); + $response->includeScript('include/js/bignumber.js'); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js . $portal_js); } + return $response; } diff --git a/www/winc/display_block_map.inc.php b/www/winc/display_block_map.inc.php index b4665f0b..2587dd66 100644 --- a/www/winc/display_block_map.inc.php +++ b/www/winc/display_block_map.inc.php @@ -108,10 +108,10 @@ class="act" // Instantiate the xajaxResponse object $response = new xajaxResponse(); // GDO need to use Big Int JS - $response->addIncludeScript('include/js/bignumber.js'); - $response->addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->includeScript('include/js/bignumber.js'); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_config_text.inc.php b/www/winc/display_config_text.inc.php index bb82580d..ee19cd7a 100644 --- a/www/winc/display_config_text.inc.php +++ b/www/winc/display_config_text.inc.php @@ -29,8 +29,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    You don't have access to this page
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -47,14 +47,10 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Host doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } - // Get configurations info - list($status, $rows, $configs) = db_get_records($onadb,'configurations',array('host_id' => $host['id']),'ctime DESC'); - - // Update History Title (and tell the browser to re-draw the history div) $history = array_pop($_SESSION['ona']['work_space']['history']); $js .= "xajax_window_submit('work_space', ' ', 'rewrite_history');"; @@ -148,8 +144,6 @@ class="act" - - // Config archive LIST $tab = 'configs'; $submit_window = "list_{$tab}"; @@ -173,14 +167,6 @@ class="act" -
    {$form['host_id']}, old_id=>' + OLD.value + ',new_id=>' + NEW.value + '\', \'display\')'); "> + + @@ -241,7 +234,6 @@ class="button" EOL; $js .= <<addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } - -//MP: TODO this delete stuff should be in configuration.inc.php module!!!!!! - - ////////////////////////////////////////////////////////////////////////////// -// Function: ws_delete_config() +// Function: +// Delete Form // // Description: -// Deletes a single config text record +// Deletes a config record. $form should be an array with a 'host_id' +// key defined and optionally a 'js' key with javascript to have the +// browser run after a successful delete. ////////////////////////////////////////////////////////////////////////////// -function ws_delete_config($window_name, $form='') { - global $conf, $self, $onadb; - global $images, $color, $style; - - // If the user supplied an array in a string, build the array and store it in $form - $form = parse_options_string($form); - - // Load the config text record - list($status, $rows, $config) = ona_get_config_record(array('id' => $form['config_id'])); - if (!$config['id']) { - array_pop($_SESSION['ona']['work_space']['history']); - $html .= "
    Configuration text record doesn't exist!
    "; - $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); - } - - // Load the asscoiated host record - list($status, $rows, $host) = ona_find_host($config['host_id']); - if (!$host['id']) { - array_pop($_SESSION['ona']['work_space']['history']); - $html .= "
    Host doesn't exist!
    "; - $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); - } +function ws_delete($window_name, $form='') { + global $include, $conf, $self, $onadb; // Check permissions - if (! (auth('host_config_admin') and authlvl($host['lvl'])) ) { - $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); - } - - // Delete the config text - - // FIXME, this should probably use a module, but there isn't one! - - list($status, $rows) = db_delete_records($onadb, 'configurations', array('id' => $config['id'])); - if ($status or !$rows) { + if (!auth('host_config_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Delete failed!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } + // If an array in a string was provided, build the array and store it in $form + $form = parse_options_string($form); - // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if ($form['js']) { $response->addScript($form['js']); } - return($response->getXML()); -} - - - - - - - - - + $js = ''; + // Run the module + list($status, $output) = run_module('config_del', array('host' => $form['host'], 'type' => $form['type'], 'commit' => $form['commit'])); + // If commit was N, display the confirmation dialog box + if (!$form['commit']) { + $build_commit_html = 1; + $commit_function = 'delete'; + include(window_find_include('module_results')); + return(window_open("{$window_name}_results", $window)); + } + // If the module returned an error code display a popup warning + if ($status) + $js .= "alert('Delete failed. " . preg_replace('/[\s\']+/', ' ', $output) . "');"; + else if ($form['js']) + $js .= $form['js']; // usually js will refresh the window we got called from + // Return an XML response + $response->script($js); + return $response; +} ////////////////////////////////////////////////////////////////////////////// -// Function: ws_delete_configs() +// Function: +// Delete All Form // // Description: -// Deletes all the config records for a particular host and type +// Deletes all config records. $form should be an array with a 'host_id' +// key defined and optionally a 'js' key with javascript to have the +// browser run after a successful delete. ////////////////////////////////////////////////////////////////////////////// -function ws_delete_configs($window_name, $form='') { - global $conf, $self, $onadb; - global $images, $color, $style; - - // If the user supplied an array in a string, build the array and store it in $form - $form = parse_options_string($form); - - // Load the host record - list($status, $rows, $host) = ona_find_host($form['host_id']); - if (!$host['id']) { - array_pop($_SESSION['ona']['work_space']['history']); - $html .= "
    Host doesn't exist!
    "; - $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); - } +function ws_delete_all($window_name, $form='') { + global $include, $conf, $self, $onadb; // Check permissions - if (! (auth('host_config_admin') and authlvl($host['lvl'])) ) { + if (!auth('host_config_admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - // Load the config type - list($status, $rows, $type) = ona_get_config_type_record(array('id' => $form['type_id'])); - if ($status or !$rows) { - $response = new xajaxResponse(); - $response->addScript("alert('ERROR => Invalid config type!');"); - return($response->getXML()); - } - - - // Delete the config text records that match - // FIXME, this should probably use a module, but there isn't one! - list($status, $rows) = db_delete_records($onadb, 'configurations', array('host_id' => $host['id'], 'configuration_type_id' => $type['id'])); - if ($status or !$rows) { - $response = new xajaxResponse(); - $response->addScript("alert('Delete failed!');"); - return($response->getXML()); - } + // If an array in a string was provided, build the array and store it in $form + $form = parse_options_string($form); - // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - if ($form['js']) { $response->addScript($form['js']); } - return($response->getXML()); -} - - - - - - + $js = ''; + // Run the module + list($status, $output) = run_module('config_del_all', array('host' => $form['host'], 'commit' => $form['commit'])); + // If commit was N, display the confirmation dialog box + if (!$form['commit']) { + $build_commit_html = 1; + $commit_function = 'delete'; + include(window_find_include('module_results')); + return(window_open("{$window_name}_results", $window)); + } + // If the module returned an error code display a popup warning + if ($status) + $js .= "alert('Delete failed. " . preg_replace('/[\s\']+/', ' ', $output) . "');"; + else if ($form['js']) + $js .= $form['js']; // usually js will refresh the window we got called from + // Basically hard code the refresh if you have deleted all the configs + $js .= "xajax_window_submit('work_space', 'xajax_window_submit(\'display_host\', \'host_id=>{$form['host']}\', \'display\')');"; + // Return an XML response + $response->script($js); + return $response; +} diff --git a/www/winc/display_device.inc.php b/www/winc/display_device.inc.php index 436a5c76..ce3980b4 100644 --- a/www/winc/display_device.inc.php +++ b/www/winc/display_device.inc.php @@ -28,8 +28,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Device doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title (and tell the browser to re-draw the history div) @@ -193,19 +193,11 @@ function ws_display($window_name, $form='') {
    - + -
    Name
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_dhcp_server.inc.php b/www/winc/display_dhcp_server.inc.php index 600e2e30..cc391336 100644 --- a/www/winc/display_dhcp_server.inc.php +++ b/www/winc/display_dhcp_server.inc.php @@ -24,8 +24,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Server doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Pick up host information @@ -199,18 +199,11 @@ class="act"
    - + -
    Filter
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; @@ -345,9 +336,9 @@ function ws_display_config($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("confoutput", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("confoutput", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_domain.inc.php b/www/winc/display_domain.inc.php index 6ca8e8e7..fbf8f592 100644 --- a/www/winc/display_domain.inc.php +++ b/www/winc/display_domain.inc.php @@ -13,7 +13,7 @@ function ws_display($window_name, $form='') { global $images, $color, $style; $html = ''; $js = ''; - //$debug_val = 3; // used in the auth() calls to suppress logging + $debug_val = 3; // used in the auth() calls to suppress logging // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); @@ -24,8 +24,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Domain doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title @@ -41,7 +41,7 @@ function ws_display($window_name, $form='') { $refresh = "xajax_window_submit('work_space', '{$refresh}');"; // Get associated info - if ($record['parent_id']) { + if (isset($record['parent_id'])) { list($status, $rows, $parent_domain) = ona_get_domain_record(array('id' => $record['parent_id'])); $parent_domain['name'] = ona_build_domain_name($parent_domain['id']); } else { @@ -334,14 +334,14 @@ class="linkact" - // HOST LIST + // LIST $tab = 'records'; $submit_window = "list_{$tab}"; $form_id = "{$submit_window}_filter_form"; $_SESSION['ona'][$form_id]['tab'] = $tab; $content_id = "{$window_name}_{$submit_window}"; $html .= << +
    @@ -354,19 +354,11 @@ class="linkact"
    EOL; $html .= << + - -
    Filter
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -517,9 +507,9 @@ function ws_display_config($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("confoutput", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("confoutput", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_domain_server.inc.php b/www/winc/display_domain_server.inc.php index 50312371..3ac10225 100644 --- a/www/winc/display_domain_server.inc.php +++ b/www/winc/display_domain_server.inc.php @@ -24,8 +24,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Server doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Pick up host information @@ -136,18 +136,11 @@ class="nav"
    - + -
    Filter
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -316,9 +307,9 @@ function ws_display_config($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("confoutput", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("confoutput", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -327,4 +318,4 @@ function ws_display_config($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/display_host.inc.php b/www/winc/display_host.inc.php index b0b30f1d..624436da 100644 --- a/www/winc/display_host.inc.php +++ b/www/winc/display_host.inc.php @@ -28,8 +28,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Host doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title (and tell the browser to re-draw the history div) @@ -71,7 +71,7 @@ function ws_display($window_name, $form='') { list($status, $rows, $manufacturer) = ona_get_manufacturer_record(array('id' => $model['manufacturer_id'])); $record['devicefull'] = "{$manufacturer['name']}, {$model['name']} ({$role['name']})"; $record['device'] = str_replace('Unknown', '?', $record['devicefull']); - $record['location_id'] = $device['location_id']; + $record['location_id'] = $device['location_id']; // Device serial number and/or asset tag $record['serial_number'] = $device['serial_number']; @@ -155,7 +155,7 @@ function ws_display($window_name, $form='') { $_SESSION['ona'][$form_id]['tab'] = $tab; $content_id = "{$window_name}_{$submit_window}"; $html .= << +
    @@ -166,19 +166,11 @@ function ws_display($window_name, $form='') {
    - + -
    Name
    - + -
    Full IP
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_interface.inc.php b/www/winc/display_interface.inc.php index 8d85e068..07173204 100644 --- a/www/winc/display_interface.inc.php +++ b/www/winc/display_interface.inc.php @@ -29,8 +29,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Interface doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title (and tell the browser to re-draw the history div) @@ -191,18 +191,11 @@ class="act"
    - + -
    Filter
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_ona_db_logs.inc.php b/www/winc/display_ona_db_logs.inc.php index 6727fbc4..e3f75548 100644 --- a/www/winc/display_ona_db_logs.inc.php +++ b/www/winc/display_ona_db_logs.inc.php @@ -106,19 +106,11 @@ function ws_display($window_name, $form='') {
    - + -
    Username
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_report.inc.php b/www/winc/display_report.inc.php index 78eefef8..5d83a115 100644 --- a/www/winc/display_report.inc.php +++ b/www/winc/display_report.inc.php @@ -32,8 +32,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    The report {$form['report']} doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title @@ -69,10 +69,10 @@ function ws_display($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - if ($rpt_js) { $response->addScript($rpt_js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + if ($rpt_js) { $response->script($rpt_js); } + return $response; } @@ -102,9 +102,9 @@ function ws_run_report($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("report_content", "innerHTML", $report_output); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("report_content", "innerHTML", $report_output); + if ($js) { $response->script($js); } + return $response; } @@ -119,4 +119,4 @@ function ws_run_report($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/display_subnet.inc.php b/www/winc/display_subnet.inc.php index 50161ade..82945943 100644 --- a/www/winc/display_subnet.inc.php +++ b/www/winc/display_subnet.inc.php @@ -31,8 +31,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    Subnet doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title @@ -146,19 +146,11 @@ function ws_display($window_name, $form='') {
    - + -
    Name
    - + -
    Filter
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_vlan.inc.php b/www/winc/display_vlan.inc.php index 04f46729..6aae0321 100644 --- a/www/winc/display_vlan.inc.php +++ b/www/winc/display_vlan.inc.php @@ -24,8 +24,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    VLAN doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Get campus info @@ -174,19 +174,11 @@ class="nav"
    - + -
    Name
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/display_vlan_campus.inc.php b/www/winc/display_vlan_campus.inc.php index d0c36be5..2b24ff03 100644 --- a/www/winc/display_vlan_campus.inc.php +++ b/www/winc/display_vlan_campus.inc.php @@ -28,8 +28,8 @@ function ws_display($window_name, $form='') { array_pop($_SESSION['ona']['work_space']['history']); $html .= "
    VLAN campus doesn't exist!
    "; $response = new xajaxResponse(); - $response->addAssign("work_space_content", "innerHTML", $html); - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + return $response; } // Update History Title (and tell the browser to re-draw the history div) @@ -174,19 +174,11 @@ class="act"
    - + -
    Vlan Name
    addAssign("work_space_content", "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("work_space_content", "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/edit_block.inc.php b/www/winc/edit_block.inc.php index d3f82edb..b6827292 100644 --- a/www/winc/edit_block.inc.php +++ b/www/winc/edit_block.inc.php @@ -18,12 +18,15 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } + // If an array in a string was provided, build the array and store it in $form + $form = parse_options_string($form); + // Load an existing host record (and associated info) if $form is a host_id - if (is_numeric($form['block_id'])) { + if (isset($form['block_id'])) { list($status, $rows, $block) = ona_get_block_record(array('id' => $form['block_id'])); $block['ip_addr_start'] = ip_mangle($block['ip_addr_start'], 'dotted'); $block['ip_addr_end'] = ip_mangle($block['ip_addr_end'], 'dotted'); @@ -58,7 +61,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - + @@ -143,12 +146,11 @@ class="edit" @@ -176,8 +178,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('advanced')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -186,8 +188,8 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['name'] or !$form['start'] or !$form['end']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Decide if we're editing or adding @@ -218,8 +220,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -239,8 +241,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -261,8 +263,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_custom_attribute.inc.php b/www/winc/edit_custom_attribute.inc.php index 96bac7ff..a48301f3 100644 --- a/www/winc/edit_custom_attribute.inc.php +++ b/www/winc/edit_custom_attribute.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('custom_attribute_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -68,8 +68,8 @@ function ws_editor($window_name, $form='') { $ca_type_list = ''; foreach ($catypes as $record) { $selected = ""; - if ($record['id'] == $ca['custom_attribute_type_id']) { $selected = "SELECTED=\"selected\""; } - if ($record['id']) {$ca_type_list .= "\n";} + if (isset($record['id']) == $ca['custom_attribute_type_id']) { $selected = "SELECTED=\"selected\""; } + if (isset($record['id'])) {$ca_type_list .= "\n";} } // Javascript to run after the window is built @@ -85,6 +85,8 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML; el('{$window_name}_form').onsubmit = function() { return false; }; + + el('type').focus(); EOL; @@ -92,7 +94,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - + @@ -150,12 +152,11 @@ class="edit" @@ -197,8 +198,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('custom_attribute_add')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -207,8 +208,8 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['type'] and !$form['value']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Validate the host is valid @@ -236,8 +237,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -261,8 +262,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('custom_attribute_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -286,8 +287,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_dhcp_failover_group.inc.php b/www/winc/edit_dhcp_failover_group.inc.php index 3dfd6fa2..11dcc97f 100644 --- a/www/winc/edit_dhcp_failover_group.inc.php +++ b/www/winc/edit_dhcp_failover_group.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -82,13 +82,14 @@ function ws_editor($window_name, $form='') { el('{$window_name}_edit_form').onsubmit = function() { return false; }; + el('failover_pri_hostname').focus(); EOL; // Define the window's inner html $window['html'] = << - +
    - + >Save
    - + >Save
    @@ -255,12 +256,11 @@ class="edit" @@ -288,8 +288,8 @@ function ws_save($window_name, $form='') { // Check permissions (there is no interface_add, it's merged with host_add) if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -297,9 +297,9 @@ function ws_save($window_name, $form='') { $js = ''; // Validate input - if ($form['pri_server'] == '') { - $response->addScript("alert('Please complete all the fields to continue!');"); - return($response->getXML()); + if ($form['pri_server'] == '' or $form['sec_server'] == '' ) { + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Decide if we're editing or adding @@ -331,8 +331,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -356,8 +356,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -377,8 +377,8 @@ function ws_delete($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_dhcp_option_entry.inc.php b/www/winc/edit_dhcp_option_entry.inc.php index fe1739d5..b25012fa 100644 --- a/www/winc/edit_dhcp_option_entry.inc.php +++ b/www/winc/edit_dhcp_option_entry.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -81,8 +81,8 @@ function ws_editor($window_name, $form='') { $dhcpoptions['dhcp_options'] = htmlentities($dhcpoptions['display_name']); foreach ($dhcpoptions as $record) { $selected = ""; - if ($record['id'] == $dhcp_entry['dhcp_option_id']) { $selected = "SELECTED=\"selected\""; } - if ($record['id']) {$dhcp_option_list .= "\n";} + if (isset($record['id']) == $dhcp_entry['dhcp_option_id']) { $selected = "SELECTED=\"selected\""; } + if (isset($record['id'])) {$dhcp_option_list .= "\n";} } // Javascript to run after the window is built @@ -98,6 +98,8 @@ function ws_editor($window_name, $form='') { el('{$window_name}_title_r').innerHTML; el('{$window_name}_form').onsubmit = function() { return false; }; + + el('option').focus(); EOL; @@ -105,7 +107,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - + @@ -165,12 +167,11 @@ class="edit" @@ -212,8 +213,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -222,8 +223,8 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['type'] and $form['value'] == '') { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Validate the host is valid @@ -251,8 +252,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -276,8 +277,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -298,8 +299,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_dhcp_pool.inc.php b/www/winc/edit_dhcp_pool.inc.php index 4e31f0d0..779b015a 100644 --- a/www/winc/edit_dhcp_pool.inc.php +++ b/www/winc/edit_dhcp_pool.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -115,6 +115,7 @@ function(ev) { ); }; + el('start').focus(); EOL; @@ -123,7 +124,7 @@ function(ev) { $window['html'] = << - + @@ -176,6 +177,7 @@ class="nav" @@ -324,8 +325,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -334,8 +335,8 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['start'] and !$form['end']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } list($status, $rows, $subnet) = ona_find_subnet($form['subnet_id']); @@ -345,8 +346,8 @@ function ws_save($window_name, $form='') { // check the ips are part of the subnet you are on if (($start_dec < $subnet['ip_addr'] or $start_dec > $net_end) or ($end_dec < $subnet['ip_addr'] or $end_dec > $net_end)) { - $response->addScript("alert('Save failed: ERROR => The pool range you specified is not part of the subnet: {$subnet['name']}!');"); - return($response->getXML()); + $response->script("alert('Save failed: ERROR => The pool range you specified is not part of the subnet: {$subnet['name']}!');"); + return $response; } @@ -378,8 +379,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -403,8 +404,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -425,8 +426,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_dhcp_server.inc.php b/www/winc/edit_dhcp_server.inc.php index 2c44486e..795f77cc 100644 --- a/www/winc/edit_dhcp_server.inc.php +++ b/www/winc/edit_dhcp_server.inc.php @@ -28,8 +28,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -80,7 +80,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - +
    - + >Save
    - + >Save
    - + >Save
    @@ -135,12 +135,11 @@ class="edit" @@ -182,8 +181,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -195,15 +194,15 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['subnet']) { - $response->addScript("alert('Please select a subnet to continue!');"); - return($response->getXML()); + $response->script("alert('Please select a subnet to continue!');"); + return $response; } // Validate subnet is valid list($status, $rows, $subnet) = ona_get_subnet_record(array('name' => $form['subnet'])); if ($status or !$rows) { - $response->addScript("alert('Invalid subnet!');"); - return($response->getXML()); + $response->script("alert('Invalid subnet!');"); + return $response; } // Decide if we're editing or adding @@ -223,8 +222,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -247,8 +246,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -269,8 +268,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_domain.inc.php b/www/winc/edit_domain.inc.php index 5607b6e0..9bdaabbf 100644 --- a/www/winc/edit_domain.inc.php +++ b/www/winc/edit_domain.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -80,7 +80,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - + @@ -247,12 +247,11 @@ class="edit" @@ -280,8 +279,8 @@ function ws_save($window_name, $form='') { // Check permissions (there is no interface_add, it's merged with host_add) if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -290,8 +289,8 @@ function ws_save($window_name, $form='') { // Validate input if ($form['name'] == '') { - $response->addScript("alert('Please complete the domain name field to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete the domain name field to continue!');"); + return $response; } //MP: FIXME: It would be nice to disallow "." in the name.. this would force us to create .com .org .net etc domains. @@ -338,8 +337,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -363,8 +362,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -384,8 +383,8 @@ function ws_delete($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_domain_server.inc.php b/www/winc/edit_domain_server.inc.php index a926c8ee..0de0b200 100644 --- a/www/winc/edit_domain_server.inc.php +++ b/www/winc/edit_domain_server.inc.php @@ -28,8 +28,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -69,6 +69,7 @@ function ws_editor($window_name, $form='') { suggest_setup('domain_server_name', 'suggest_domain_server_name'); suggest_setup('domain_server_edit', 'suggest_domain_server_edit'); + el('domain_server_name').focus(); EOL; @@ -76,7 +77,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - +
    - + >Save
    - + >Save
    @@ -142,12 +143,11 @@ class="edit" @@ -189,8 +189,8 @@ function ws_save($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -201,9 +201,17 @@ function ws_save($window_name, $form='') { $js = ''; // Validate input + if ($form['server'] == '' or + $form['domain'] == '' or + $form['role'] == '' + ) { + $response->script("alert('Please complete all required fields to continue!');"); + return $response; + } + if (!$form['domain']) { - $response->addScript("alert('Please select a domain to continue!');"); - return($response->getXML()); + $response->script("alert('Please select a domain to continue!');"); + return $response; } @@ -224,8 +232,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -248,8 +256,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -270,8 +278,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_host.inc.php b/www/winc/edit_host.inc.php index d8e9f7fd..3c1a08bf 100644 --- a/www/winc/edit_host.inc.php +++ b/www/winc/edit_host.inc.php @@ -28,8 +28,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (! (auth('host_modify') or auth('host_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -179,7 +179,7 @@ function(ev) { $window['html'] = << - + @@ -471,12 +471,11 @@ class="edit" @@ -507,8 +506,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('host_modify') or auth('host_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -519,8 +518,8 @@ function ws_save($window_name, $form='') { /* Interface input: required only if adding a host */ ($form['host'] == '.' and $form['set_ip'] == '') ) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Since we're adding two records (host and an interface) @@ -530,21 +529,15 @@ function ws_save($window_name, $form='') { // Validate the "set_host" name is valid $form['set_host'] = sanitize_hostname(trim($form['set_host'])); if (!$form['set_host']) { - $response->addScript("alert('Invalid hostname!');"); - return($response->getXML()); + $response->script("alert('Invalid hostname!');"); + return $response; } - // Validate domain is valid -// list($status, $rows, $domain) = ona_find_domain($form['set_domain'],0); -// if ($status or !$rows) { -// $response->addScript("alert('Invalid domain!');"); -// return($response->getXML()); -// } // Make sure the IP address specified is valid if ($form['host'] != '.' and $form['set_ip']) { $form['set_ip'] = ip_mangle($form['set_ip'], 'dotted'); if ($form['set_ip'] == -1) { - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } } @@ -565,8 +558,8 @@ function ws_save($window_name, $form='') { if (!auth('host_add')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Device options @@ -607,8 +600,8 @@ function ws_save($window_name, $form='') { if (!$ptrdomain['id']) { printmsg("ERROR => This operation tried to create a PTR record that is the first in this IP address space. You must first create at least the following DNS domain: {$octets[$octcount]}.in-addr.arpa",3); $self['error'] = "ERROR => This operation tried to create a PTR record that is the first in this IP address space.
    You must first create at least the following DNS domain: {$octets[$octcount]}.in-addr.arpa.
    You could also create domains at deeper level reverse zones if desired.
    We have opened the add domain dialog for you."; - $response->addScript("alert('{$self['error']}');xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[$octcount]}{$arpa}', 'editor');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[$octcount]}{$arpa}', 'editor');"); + return $response; } } @@ -639,8 +632,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -664,8 +657,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('host_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -693,8 +686,8 @@ function ws_delete($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_interface.inc.php b/www/winc/edit_interface.inc.php index de6b7de1..26b67f4b 100644 --- a/www/winc/edit_interface.inc.php +++ b/www/winc/edit_interface.inc.php @@ -28,8 +28,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('interface_modify')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -83,9 +83,9 @@ function ws_editor($window_name, $form='') { $selected = ''; $dnsviews['name'] = htmlentities($dnsviews['name']); // If this entry matches the record you are editing, set it to selected - if ($dns_record['id'] and $entry['id'] == $dns_record['dns_view_id']) { + if (isset($dns_record['id']) and $entry['id'] == $dns_record['dns_view_id']) { $selected = "SELECTED=\"selected\""; - } elseif (!$dns_record['id'] and $entry['id'] == 0) { + } elseif (!isset($dns_record['id']) and $entry['id'] == 0) { // Otherwise use the default record if we are adding a new entry $selected = "SELECTED=\"selected\""; } @@ -147,7 +147,7 @@ function(ev) { $window['html'] = << - + EOL; if($host['fqdn']) { @@ -258,6 +258,13 @@ class="edit" alt="Allow duplicate MAC addresses" type="checkbox" > Allow duplicate MAC addresses +
    + Auto generate MAC addresses @@ -361,12 +368,11 @@ class="edit"
    @@ -399,8 +405,8 @@ function ws_save($window_name, $form='') { // Check permissions (there is no interface_add, it's merged with host_add) if (! (auth('interface_modify') and auth('host_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form $form = parse_options_string($form); @@ -410,8 +416,8 @@ function ws_save($window_name, $form='') { // Validate input if ($form['set_ip'] == '') { - $response->addScript("alert('Please complete the IP address field to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete the IP address field to continue!');"); + return $response; } // set_create_a and set_create_ptr should both be set! if (!$form['set_addptr']) $form['set_addptr'] = 'N'; @@ -424,6 +430,7 @@ function ws_save($window_name, $form='') { $module = 'interface_add'; $form['ip'] = $form['set_ip']; unset($form['set_ip']); $form['mac'] = $form['set_mac']; unset($form['set_mac']); + $form['laa'] = $form['set_laa']; unset($form['set_laa']); $form['name'] = $form['set_name']; unset($form['set_name']); $form['description'] = $form['set_description']; unset($form['set_description']); $form['addptr'] = $form['set_addptr']; unset($form['set_addptr']); @@ -435,7 +442,7 @@ function ws_save($window_name, $form='') { // Do a pre check of the ptr domain so we can prompt the user properly if ($module == 'interface_add') { - + $ipflip = ip_mangle($form['ip'],'flip'); $octets = explode(".",$ipflip); //GD: ipv6 IPs must be reversed in .ip6.arpa @@ -451,8 +458,8 @@ function ws_save($window_name, $form='') { if (!$ptrdomain['id']) { printmsg("ERROR => You must first create at least the following DNS domain: {$octets[$octcount]}{$arpa}",3); $self['error'] = "ERROR => You must first create at least the following DNS domain: {$octets[$octcount]}{$arpa}. You could also create domains for class B or class C level reverse zones. Click OK to open add domain dialog"; - $response->addScript("alert('{$self['error']}');xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[$octcount]}{$arpa}', 'editor');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[$octcount]}{$arpa}', 'editor');"); + return $response; } } @@ -480,8 +487,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -505,8 +512,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('interface_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -534,8 +541,8 @@ function ws_delete($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_location.inc.php b/www/winc/edit_location.inc.php index fb0bdb33..a1fb7c1a 100644 --- a/www/winc/edit_location.inc.php +++ b/www/winc/edit_location.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('location_add')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -61,7 +61,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - +
    - + >Save
    - + >Save
    - + >Save
    @@ -156,12 +156,11 @@ function ws_editor($window_name, $form='') { @@ -189,8 +188,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('location_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -202,8 +201,8 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['reference'] or !$form['name']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } @@ -239,8 +238,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_record.inc.php b/www/winc/edit_record.inc.php index 38a9ff31..08d4acf4 100644 --- a/www/winc/edit_record.inc.php +++ b/www/winc/edit_record.inc.php @@ -30,8 +30,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (! (auth('dns_record_modify') and auth('dns_record_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -158,9 +158,9 @@ function ws_editor($window_name, $form='') { $selected = ''; $dnsviews['name'] = htmlentities($dnsviews['name']); // If this entry matches the record you are editing, set it to selected - if ($dns_record['id'] and $entry['id'] == $dns_record['dns_view_id']) { + if (isset($dns_record['id']) and $entry['id'] == $dns_record['dns_view_id']) { $selected = "SELECTED=\"selected\""; - } elseif (!$dns_record['id'] and $entry['id'] == 0) { + } elseif (!isset($dns_record['id']) and $entry['id'] == 0) { // Otherwise use the default record if we are adding a new entry $selected = "SELECTED=\"selected\""; } @@ -192,7 +192,7 @@ function ws_editor($window_name, $form='') { $window['html'] = << - + @@ -358,13 +358,13 @@ class="edit" - @@ -679,26 +678,27 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('dns_record_modify') and auth('dns_record_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object $response = new xajaxResponse(); $js = ''; - + // we need to do a little validation here to make sure things + // have a good chance of working! // Validate input -// if ($form['set_domain'] == '' or -// $form['set_type'] == '' -// ) { -// $response->addScript("alert('Please complete all fields to continue!');"); -// return($response->getXML()); -// } + if ($form['set_name'] == '' or + $form['set_type'] == '' or + $form['set_ip'] == '' or + $form['set_domain'] == '' + ) { + $response->script("alert('Please complete all required fields to continue!');"); + return $response; + } - // we need to do a little validation here to make sure things - // have a good chance of working! // If the name we were passed has a leading . in it then remove the dot. $form['set_name'] = preg_replace("/^\./", '', trim($form['set_name'])); @@ -708,8 +708,8 @@ function ws_save($window_name, $form='') { if ($form['set_name'] and ($form['set_type'] != 'NS')) { $form['set_name'] = sanitize_hostname($form['set_name']); if (!$form['set_name']) { - $response->addScript("alert('Invalid hostname!');"); - return($response->getXML()); + $response->script("alert('Invalid hostname!');"); + return $response; } } @@ -717,8 +717,8 @@ function ws_save($window_name, $form='') { if ($form['set_name'] != '.' and $form['set_ip']) { $form['set_ip'] = ip_mangle($form['set_ip'], 'dotted'); if ($form['set_ip'] == -1) { - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } } @@ -789,8 +789,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -814,8 +814,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('dns_record_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -843,8 +843,8 @@ function ws_delete($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -865,8 +865,8 @@ function ws_makeprimary($window_name, $form='') { // Check permissions if (!auth('dns_record_modify')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -891,8 +891,8 @@ function ws_makeprimary($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -915,8 +915,8 @@ function ws_enablerecord($window_name, $form='') { // Check permissions if (!auth('dns_record_modify')) { $response = new xajaxResponse(); - $response->addScript("alert('Failed to enable record: Permission denied!');"); - return($response->getXML()); + $response->script("alert('Failed to enable record: Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -942,8 +942,8 @@ function ws_enablerecord($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_subnet.inc.php b/www/winc/edit_subnet.inc.php index afaa653e..c5854538 100644 --- a/www/winc/edit_subnet.inc.php +++ b/www/winc/edit_subnet.inc.php @@ -18,41 +18,47 @@ function ws_editor($window_name, $form='') { // Check permissions if (! (auth('subnet_modify') and auth('subnet_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); + // If $form is a number, it's an record ID- so we transform $form into an array if (is_numeric($form)) $form = array('subnet_id' => $form); $subnet = array(); + $vlan = array(); // Load an existing record (and associated info) if $form is an id - if (is_numeric($form['subnet_id'])) { + if (!empty($form['subnet_id'])) { + if (is_numeric($form['subnet_id'])) { list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $form['subnet_id'])); if ($rows) { - if (strlen($subnet['ip_addr']) > 11) { - $subnet['ip_mask'] = '/'.ip_mangle($subnet['ip_mask'], 'cidr'); - } else { - $subnet['ip_mask'] = ip_mangle($subnet['ip_mask'], 'dotted'); - } - $subnet['ip_addr'] = ip_mangle($subnet['ip_addr'], 'dotted'); - - // Vlan Record - list($status, $rows, $vlan) = ona_get_vlan_record(array('id' => $subnet['vlan_id'])); - $subnet['vlan_desc'] = $vlan['vlan_campus_name'] . ' / ' . $vlan['name']; + if (strlen($subnet['ip_addr']) > 11) { + $subnet['ip_mask'] = '/'.ip_mangle($subnet['ip_mask'], 'cidr'); + } + else { + $subnet['ip_mask'] = ip_mangle($subnet['ip_mask'], 'dotted'); + } + $subnet['ip_addr'] = ip_mangle($subnet['ip_addr'], 'dotted'); + + // Vlan Record + list($status, $rows, $vlan) = ona_get_vlan_record(array('id' => $subnet['vlan_id'])); + $subnet['vlan_desc'] = $vlan['vlan_campus_name'] . ' / ' . $vlan['name']; } - } - // If there is no subnet id in the form but we are passing in data, clean it up - else { + } + // If there is no subnet id in the form but we are passing in data, clean it up + else { if (strlen($form['ip_addr']) > 1) $subnet['ip_addr'] = ip_mangle($form['ip_addr'], 'dotted'); if (strlen($form['ip_mask']) > 1) $subnet['ip_mask'] = ip_mangle($form['ip_mask'], 'dotted'); if (strlen($form['name']) > 1) $subnet['name'] = $form['name']; + } } - if (!$subnet['vlan_id']) $subnet['vlan_desc'] = 'None'; + if (empty($subnet['vlan_id'])) $subnet['vlan_desc'] = 'None'; + if (empty($subnet['subnet_type_id'])) $subnet['subnet_type_id'] = 0; // Escape data for display in html @@ -60,21 +66,17 @@ function ws_editor($window_name, $form='') { // Set the window title: $window['title'] = "Add Subnet"; - if ($subnet['id']) $window['title'] = "Edit Subnet"; - + if (isset($subnet['id'])) $window['title'] = "Edit Subnet"; // Build subnet type list list($status, $rows, $subnettypes) = db_get_records($onadb, 'subnet_types', 'id > 0', 'display_name'); $subnet_type_list = '\n'; - $subnettypes['subnet_type_name'] = htmlentities($subnettypes['display_name']); foreach ($subnettypes as $record) { $selected = ""; - if ($record['id'] == $subnet['subnet_type_id']) { $selected = "SELECTED=\"selected\""; } - if ($record['id']) {$subnet_type_list .= "\n";} + if (isset($record['id']) == $subnet['subnet_type_id']) { $selected = "SELECTED=\"selected\""; } + if (isset($record['id'])) {$subnet_type_list .= "\n";} } - - // Javascript to run after the window is built $window['js'] = << - +
    - + >Save
    + Begin EOL; - if ((strtotime($dns_record['ebegin']) < time()) && (strtotime($dns_record['ebegin']) > 1)) { + if ((strtotime($dns_record['ebegin']) > time()) && (strtotime($dns_record['ebegin']) < strtotime('2038-01-10 00:00:00'))) { $window['html'] .= << - + >Save
    @@ -254,12 +256,11 @@ class="edit" @@ -290,8 +291,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('subnet_modify') and auth('subnet_add')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -304,22 +305,22 @@ function ws_save($window_name, $form='') { $form['set_ip'] == '' or $form['set_netmask'] == '' ) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Make sure the IP address specified is valid $form['set_ip'] = ip_mangle($form['set_ip'], 'dotted'); if ($form['set_ip'] == -1) { - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } // Make sure the netmask specified is valid $form['set_netmask'] = ip_mangle($form['set_netmask'], 'cidr'); if ($form['set_netmask'] == -1) { $self['error'] = preg_replace('/IP address/i', 'netmask', $self['error']); - $response->addScript("alert('{$self['error']}');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');"); + return $response; } // Before we go on, we must alert the user if this new subnet would require a new PTR zone. @@ -329,8 +330,8 @@ function ws_save($window_name, $form='') { // list($status, $rows, $ptrdomain) = ona_find_domain($ipflip.".in-addr.arpa"); // if (!$ptrdomain['id']) { // $self['error'] = "ERROR => This subnet is the first in the {$octets[3]}.0.0.0 class A range. You must first create at least the following DNS domain: {$octets[3]}.in-addr.arpa\\n\\nSelect OK to create new DNS domain now."; -// $response->addScript("var doit=confirm('{$self['error']}');if (doit == true) {xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[3]}.in-addr.arpa', 'editor');} else {removeElement('{$window_name}');}"); -// return($response->getXML()); +// $response->script("var doit=confirm('{$self['error']}');if (doit == true) {xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[3]}.in-addr.arpa', 'editor');} else {removeElement('{$window_name}');}"); +// return $response; // } @@ -350,7 +351,7 @@ function ws_save($window_name, $form='') { $form['netmask'] = $form['set_netmask']; unset($form['set_netmask']); $form['vlan'] = $form['set_vlan']; unset($form['set_vlan']); } - + // Run the module to ADD or MODIFY the SUBNET. list($status, $output) = run_module('subnet_'.$module, $form); @@ -364,15 +365,15 @@ function ws_save($window_name, $form='') { $js .= "el('statusinfo_{$window_name}').innerHTML = 'Previously added: {$form['name']}';"; else $js .= "removeElement('{$window_name}');"; - + // If there is "refresh" javascript, send it to the browser to execute // MP: FIXME.. there is an issue that if you add a new subnet, then imidiately modify its IP the JS refresh uses the old ip and fails. find out why if ($form['js']) $js .= $form['js']; } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -396,8 +397,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('subnet_del')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -425,8 +426,8 @@ function ws_delete($window_name, $form='') { $js .= $form['js']; // usually js will refresh the window we got called from // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_tag.inc.php b/www/winc/edit_tag.inc.php index b22c5911..2c81ac74 100644 --- a/www/winc/edit_tag.inc.php +++ b/www/winc/edit_tag.inc.php @@ -14,8 +14,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('host_add') or auth('subnet_add'))) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -39,8 +39,8 @@ function ws_save($window_name, $form='') { $js .= "xajax_window_submit('tooltips', 'type => {$form['type']}, reference => {$form['reference']}, updateid => {$form['updateid']}', 'tag_html');"; // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -58,8 +58,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (! (auth('host_del') or auth('subnet_del'))) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -80,8 +80,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_vlan.inc.php b/www/winc/edit_vlan.inc.php index 7bd0be33..c6f15967 100644 --- a/www/winc/edit_vlan.inc.php +++ b/www/winc/edit_vlan.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('vlan_add')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -63,13 +63,14 @@ function ws_editor($window_name, $form='') { suggest_setup('vlan_edit', 'suggest_vlan_edit'); el('{$window_name}_edit_form').onsubmit = function() { return false; }; + el('vlan_edit').focus(); EOL; // Define the window's inner html $window['html'] = << - + @@ -166,12 +167,11 @@ class="edit" @@ -199,8 +199,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('advanced')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -209,14 +209,14 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['campus'] or !$form['name'] or !$form['number']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all required fields to continue!');"); + return $response; } // Validate zone is valid list($status, $rows, $campus) = ona_get_vlan_campus_record(array('name' => $form['campus'])); if ($status or !$rows) { - $response->addScript("alert('Invalid VLAN campus!');"); - return($response->getXML()); + $response->script("alert('Invalid VLAN campus!');"); + return $response; } // Decide if we're editing or adding @@ -251,8 +251,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -275,8 +275,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -297,8 +297,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/edit_vlan_campus.inc.php b/www/winc/edit_vlan_campus.inc.php index 72ae7375..b0ed2461 100644 --- a/www/winc/edit_vlan_campus.inc.php +++ b/www/winc/edit_vlan_campus.inc.php @@ -18,8 +18,8 @@ function ws_editor($window_name, $form='') { // Check permissions if (!auth('vlan_add')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If the user supplied an array in a string, build the array and store it in $form @@ -54,13 +54,14 @@ function ws_editor($window_name, $form='') { ' ' + el('{$window_name}_title_r').innerHTML; + el('campus_name').focus(); EOL; // Define the window's inner html $window['html'] = << - +
    - + >Save
    - + >Save
    @@ -77,6 +78,7 @@ function ws_editor($window_name, $form='') { @@ -126,8 +127,8 @@ function ws_save($window_name, $form='') { // Check permissions if (! (auth('advanced')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -136,8 +137,8 @@ function ws_save($window_name, $form='') { // Validate input if (!$form['name']) { - $response->addScript("alert('Please provide a campus name to continue!');"); - return($response->getXML()); + $response->script("alert('Please provide a campus name to continue!');"); + return $response; } // Decide if we're editing or adding @@ -169,8 +170,8 @@ function ws_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -194,8 +195,8 @@ function ws_delete($window_name, $form='') { // Check permissions if (!auth('advanced')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // If an array in a string was provided, build the array and store it in $form @@ -216,8 +217,8 @@ function ws_delete($window_name, $form='') { } // Return an XML response - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } diff --git a/www/winc/ipcalcgui.inc.php b/www/winc/ipcalcgui.inc.php index 9cfbc212..6b69976f 100644 --- a/www/winc/ipcalcgui.inc.php +++ b/www/winc/ipcalcgui.inc.php @@ -64,8 +64,8 @@ function ws_ipcalcgui_submit($window_name, $form='') { $response = new xajaxResponse(); - $response->addAssign('ipcalc_data', "innerHTML", $text); - return($response->getXML()); + $response->assign('ipcalc_data', "innerHTML", $text); + return $response; } @@ -75,4 +75,4 @@ function ws_ipcalcgui_submit($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/list_blocks.inc.php b/www/winc/list_blocks.inc.php index 07e0614c..a95f0129 100644 --- a/www/winc/list_blocks.inc.php +++ b/www/winc/list_blocks.inc.php @@ -209,7 +209,7 @@ class="act" $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); // If there was only 1 result, and we're about to display results in the "Search Results" window, display it. - if ($count == 1 and $form['content_id'] == 'search_results_list' and $form['filter'] == '') + if ($count == 1 and $form['content_id'] == 'search_results_list' and $form['filter'] == '' and $form['one_go'] != 'n') $js .= $primary_object_js; @@ -217,10 +217,10 @@ class="act" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_configs.inc.php b/www/winc/list_configs.inc.php index 79721b66..1a3be9d2 100644 --- a/www/winc/list_configs.inc.php +++ b/www/winc/list_configs.inc.php @@ -159,10 +159,13 @@ function ws_display_list($window_name, $form='') { {$confsize}
    - + >Save
    - +
    + + + + + +
    EOL; if (auth('host_config_admin',$debug_val)) { @@ -183,7 +186,7 @@ class="act" class="nav" onClick="var doit=confirm('Are you sure you want to delete this config record?'); if (doit == true) - xajax_window_submit('display_config_text', xajax.getFormValues('{$form['form_id']}_list_configs_{$record['id']}'), 'delete_config');" + xajax_window_submit('display_config_text', xajax.getFormValues('{$form['form_id']}_list_configs_{$record['id']}'), 'delete');" >Delete config  EOL; @@ -210,10 +213,10 @@ class="nav" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_dhcp_server.inc.php b/www/winc/list_dhcp_server.inc.php index 36c0a49e..150cbc06 100644 --- a/www/winc/list_dhcp_server.inc.php +++ b/www/winc/list_dhcp_server.inc.php @@ -234,10 +234,10 @@ class="act" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -248,4 +248,4 @@ class="act" -?> \ No newline at end of file +?> diff --git a/www/winc/list_domain_server.inc.php b/www/winc/list_domain_server.inc.php index 06b40f27..c04b588a 100644 --- a/www/winc/list_domain_server.inc.php +++ b/www/winc/list_domain_server.inc.php @@ -58,7 +58,7 @@ function ws_display_list($window_name, $form='') { // Do the SQL Query $filter = ''; if ($form['filter']) { - $filter = $and . 'name LIKE ' . $oracle->qstr('%'.$form['filter'].'%'); + $filter = $and . 'name LIKE ' . $onadb->qstr('%'.$form['filter'].'%'); } @@ -183,10 +183,10 @@ class="act" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_hosts.inc.php b/www/winc/list_hosts.inc.php index cf37c7f1..5b53c6f5 100644 --- a/www/winc/list_hosts.inc.php +++ b/www/winc/list_hosts.inc.php @@ -14,6 +14,7 @@ function ws_display_list($window_name, $form='') { global $images, $color, $style; $html = ''; $js = ''; + $debug_val = 3; // If the user supplied an array in a string, transform it into an array $form = parse_options_string($form); @@ -129,12 +130,14 @@ function ws_display_list($window_name, $form='') { list($status, $rows, $record) = ona_find_domain($form['domain']); if ($record['id']) { $withdomain = "AND b.domain_id = {$record['id']}"; + } else { + // last resort, try it as a partial name with wildcard + $withdomain = "AND b.domain_id in (select id from domains where name like '{$form['domain']}%')"; } // Now find what the host part of $search is $hostname = trim($form['hostname']); } - // MP: Doing the many select IN statements was too slow.. I did this kludge: // 1. get a list of all the interfaces // 2. loop through the array and build a list of comma delimited host_ids to use in the final select @@ -150,6 +153,10 @@ function ws_display_list($window_name, $form='') { list($status, $rows, $r) = ona_find_host($form['hostname']); if ($rows) $hostids .= ','.$r['id']; + // Lets try and find the host id for just the record that matches the dotted host portion + list($status, $rows, $r) = db_get_record($onadb, 'interfaces a, dns b', "a.id = b.interface_id and b.name LIKE '{$form['hostname']}.{$form['domain']}%'"); + if ($rows) $hostids .= ','.$r['host_id']; + // MP: this is the old, slow query for reference. // // TODO: MP this seems to be kinda slow (gee I wonder why).. look into speeding things up somehow. @@ -613,7 +620,7 @@ class="nav" >  EOL; - if (auth('host_modify')) { + if (auth('host_modify',$debug_val)) { $html .= <<addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_interfaces.inc.php b/www/winc/list_interfaces.inc.php index 8c3ba495..8ad4f932 100644 --- a/www/winc/list_interfaces.inc.php +++ b/www/winc/list_interfaces.inc.php @@ -58,10 +58,12 @@ function ws_display_list($window_name, $form='') { // Do the SQL Query $filter = ''; +/* disable filter here since it does not actual work properly if ($form['filter']) { $form['filter'] = ip_mangle($form['filter']); $filter = $and . ' ip_addr LIKE ' . $onadb->qstr('%'.$form['filter'].'%'); } +*/ list ($status, $rows, $results) = db_get_records( $onadb, @@ -113,6 +115,12 @@ function ws_display_list($window_name, $form='') { foreach($results as $record) { // Get additional info about each host record // + // crappy filter outside the query itself + if (isset($form['filter'])) { + $iptext = ip_mangle($record['ip_addr'], 'dotted'); + if (!preg_match("/{$form['filter']}/",$iptext)) continue; + } + // Check if this interface has an external NAT unset($extnatint, $extnatdisplay, $extnatdisplay, $extnatsubdisplay); if ($record['nat_interface_id'] > 0) { @@ -306,10 +314,10 @@ class="act" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_ona_db_logs.inc.php b/www/winc/list_ona_db_logs.inc.php index fa779764..7d684c6a 100644 --- a/www/winc/list_ona_db_logs.inc.php +++ b/www/winc/list_ona_db_logs.inc.php @@ -171,10 +171,10 @@ function ws_display_list($window_name, $form='') { // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_records.inc.php b/www/winc/list_records.inc.php index 9f4d646d..137264be 100644 --- a/www/winc/list_records.inc.php +++ b/www/winc/list_records.inc.php @@ -142,6 +142,8 @@ function ws_display_list($window_name, $form='') { + // default some arrays + $host = array(); // display a nice message when we dont find all the records @@ -162,7 +164,7 @@ function ws_display_list($window_name, $form='') { // Do the SQL Query $filter = ''; - if ($form['filter']) { + if (isset($form['filter'])) { // Host names should always be lower case $form['filter'] = strtolower($form['filter']); $filter = ' AND name LIKE ' . $onadb->qstr('%'.$form['filter'].'%'); @@ -285,6 +287,11 @@ function ws_display_list($window_name, $form='') { $record = $results[$i-1]; + // crappy filter outside the query itself + if (isset($form['filter'])) { + if (!preg_match("/{$form['filter']}/",$record['name'])) continue; + } + // if the interface is the primary_dns_id for the host then mark it $primary_record = ' '; if ($host['primary_dns_id'] == $record['id']) { @@ -469,7 +476,7 @@ class="domain" // If it is in the future, print the time if (strtotime($record['ebegin']) > time()) $ebegin = '' . date($conf['date_format'],strtotime($record['ebegin'])) . ''; // If it is 0 then show as disabled - if (strtotime($record['ebegin']) < 0) { + if (strtotime($record['ebegin']) > strtotime('2038-01-10 00:00:00')) { $ebegin = <<addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_subnets.inc.php b/www/winc/list_subnets.inc.php index 823147dd..64016a67 100644 --- a/www/winc/list_subnets.inc.php +++ b/www/winc/list_subnets.inc.php @@ -301,16 +301,16 @@ class="act" $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); // If there was only 1 result, and we're about to display results in the "Search Results" window, display it. - if ($count == 1 and $form['content_id'] == 'search_results_list' and $form['filter'] == '') + if ($count == 1 and $form['content_id'] == 'search_results_list' and $form['filter'] == '' and $form['one_go'] != 'n') $js .= $primary_object_js; // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_vlan_campus.inc.php b/www/winc/list_vlan_campus.inc.php index 23d81240..79c9b71d 100644 --- a/www/winc/list_vlan_campus.inc.php +++ b/www/winc/list_vlan_campus.inc.php @@ -191,7 +191,7 @@ class="act" $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); // If there was only 1 result, and we're about to display results in the "Search Results" window, display it. - if ($count == 1 and $form['content_id'] == 'search_results_list' and $form['filter'] == '') + if ($count == 1 and $form['content_id'] == 'search_results_list' and $form['filter'] == '' and $form['one_go'] != 'n') $js .= $primary_object_js; @@ -199,10 +199,10 @@ class="act" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/list_vlans.inc.php b/www/winc/list_vlans.inc.php index ad18c887..0c6b248c 100644 --- a/www/winc/list_vlans.inc.php +++ b/www/winc/list_vlans.inc.php @@ -186,10 +186,10 @@ class="act" // Insert the new html into the content div specified // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign("{$form['form_id']}_{$tab}_count", "innerHTML", "({$count})"); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/menu_control.inc.php b/www/winc/menu_control.inc.php index 71a11884..e90d98a1 100644 --- a/www/winc/menu_control.inc.php +++ b/www/winc/menu_control.inc.php @@ -58,11 +58,11 @@ function ws_menu_control_submit($window_name, $ws) { $response = new xajaxResponse(); - $response->addAssign('menu_bar_top', "innerHTML", $html); - $response->addScript($js); + $response->assign('menu_bar_top', "innerHTML", $html); + $response->script($js); // used to let menus pass in javascript - $response->addScript($tmpjs); - return($response->getXML()); + $response->script($tmpjs); + return $response; } @@ -83,7 +83,7 @@ function ws_menu($window_name, $form='') { // If an array in a string was provided, build the array and store it in $form $form = parse_options_string($form); - printmsg("DEBUG => Displaying tooltip: {$form['tooltip']}", 4); + if (isset($form['tooltip'])) printmsg("DEBUG => Displaying tooltip: {$form['tooltip']}", 4); $menuname = 'get_html_'.$form['menu_name']; @@ -96,12 +96,12 @@ function ws_menu($window_name, $form='') { // 4. Unhide it $response = new xajaxResponse(); if ($html) { - $response->addScript("el('{$form['id']}').style.visibility = 'hidden';"); - $response->addAssign($form['id'], "innerHTML", $html); - $response->addScript("wwTT_position('{$form['id']}'); el('{$form['id']}').style.visibility = 'visible';"); + $response->script("el('{$form['id']}').style.visibility = 'hidden';"); + $response->assign($form['id'], "innerHTML", $html); + $response->script("wwTT_position('{$form['id']}'); el('{$form['id']}').style.visibility = 'visible';"); } - if ($js) { $response->addScript($js); } - return($response->getXML()); + if ($js) { $response->script($js); } + return $response; } @@ -369,7 +369,7 @@ function get_html_menu_button_edit() {
     Add Subnet
    @@ -381,7 +381,7 @@ function get_html_menu_button_edit() {
     Add Host
    @@ -417,7 +417,7 @@ function get_html_menu_button_edit() {
     Add VLAN campus
    @@ -429,7 +429,7 @@ function get_html_menu_button_edit() {
     Add VLAN
    @@ -441,7 +441,7 @@ function get_html_menu_button_edit() {
     Add Block
    @@ -453,7 +453,7 @@ function get_html_menu_button_edit() {
     Add Location
    diff --git a/www/winc/module_results.inc.php b/www/winc/module_results.inc.php index 6bff6db4..620a7614 100644 --- a/www/winc/module_results.inc.php +++ b/www/winc/module_results.inc.php @@ -3,10 +3,10 @@ // This is not really a window at all. // It is intended to be "included" by other code to build the html // to display the output from a module it just ran. -// +// // The following variables must be pre-defined before including this file: // $output The textual output from the module you just ran -// +// // The following are optional variables must both be deifned to enable the "commit" checkbox: // $build_commit_html = 1 | 0 Wether this code should build a commit checkbox and submit button. // We use this for almost every "delete" module. @@ -14,7 +14,7 @@ // the submit button is pressed. // FYI, if you use the "commit" functionality, the created window MUST be called "{$window_name}_results" // for the Cancel button to work properly. -// +// global $color, $style; diff --git a/www/winc/process_alerts.inc.php b/www/winc/process_alerts.inc.php index 902cb9f4..4b420f2f 100644 --- a/www/winc/process_alerts.inc.php +++ b/www/winc/process_alerts.inc.php @@ -35,8 +35,8 @@ function ws_process_alerts_submit($window_name, $form='') { $response = new xajaxResponse(); - if ($js) { $response->addScript($js); } - return($response->getXML()); + if ($js) { $response->script($js); } + return $response; } @@ -46,4 +46,4 @@ function ws_process_alerts_submit($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/search_results.inc.php b/www/winc/search_results.inc.php index 826c2f8f..adffac8d 100644 --- a/www/winc/search_results.inc.php +++ b/www/winc/search_results.inc.php @@ -46,8 +46,36 @@ function ws_search_results_submit($window_name, $form='') { } } + + // ugg, setting empty form values that dont exist so warns dont show up + // This was an attempt at cleaning up warns, not sure if there will be other impacts + // for now I supress warns at the index.php. This could just go away. leaving for refrence. + if (!array_key_exists('blockname',$form)) $form['blockname']=''; + if (!array_key_exists('campusname',$form)) $form['campusname']=''; + if (!array_key_exists('hostname',$form)) $form['hostname']=''; + if (!array_key_exists('domain',$form)) $form['domain']=''; + if (!array_key_exists('mac',$form)) $form['mac']=''; + if (!array_key_exists('ip',$form)) $form['ip']=''; + if (!array_key_exists('tag_host',$form)) $form['tag_host']=''; + if (!array_key_exists('tag_net',$form)) $form['tag_net']=''; + if (!array_key_exists('ip_thru',$form)) $form['ip_thru']=''; + if (!array_key_exists('notes',$form)) $form['notes']=''; + if (!array_key_exists('location',$form)) $form['location']=''; + if (!array_key_exists('custom_attribute_type',$form)) $form['custom_attribute_type']=''; + if (!array_key_exists('custom_attribute_type_net',$form)) $form['custom_attribute_type_net']=''; + if (!array_key_exists('ca_value',$form)) $form['ca_value']=''; + if (!array_key_exists('ca_value_net',$form)) $form['ca_value_net']=''; + if (!array_key_exists('model',$form)) $form['model']=''; + if (!array_key_exists('role',$form)) $form['role']=''; + if (!array_key_exists('manufacturer',$form)) $form['manufacturer']=''; + if (!array_key_exists('vlandesc',$form)) $form['vlandesc']=''; + if (!array_key_exists('subnetname',$form)) $form['subnetname']=''; + if (!array_key_exists('ip_subnet',$form)) $form['ip_subnet']=''; + if (!array_key_exists('ip_subnet_thru',$form)) $form['ip_subnet_thru']=''; + // keep wildcard checkbox value - if ($form['nowildcard']) $wildchecked = 'checked="yes"'; + $wildchecked = ''; + if (array_key_exists('nowildcard',$form)) $wildchecked = 'checked="yes"'; // Load some html into $window['html'] $form_id = "{$window_name}_filter_form"; @@ -95,18 +123,11 @@ function ws_search_results_submit($window_name, $form='') {
    -
    + -
    Filter
    - + @@ -164,7 +184,7 @@ class="filter" - + @@ -194,7 +214,7 @@ class="filter" - + @@ -344,7 +364,7 @@ class="filter" - + @@ -445,7 +465,7 @@ class="filter" - + @@ -590,7 +610,6 @@ class="filter" el('{$window_name}_title_r').innerHTML; /* Setup the quick filter */ - el('{$form_id}_filter_overlay').style.left = (el('{$form_id}_filter_overlay').offsetWidth + 10) + 'px'; {$form_id}_last_search = ''; /* Save the new tab and make it look active */ @@ -718,6 +737,15 @@ function quick_search($q) { return( array('subnets', array('subnet_id' => $record['id']) ) ); } + // If there is a dot in what is typed. split that out and check the right hand side for domains first + // then use any found domainid in the search + if (strpos($q,'.') !== false) { + // Split the query into host and domain portions + list($q,$dom) = explode('.', $q, 2); + printmsg("DEBUG => quick_search() found a dot in the name, trying hostname = {$q} and domain = {$dom}" ,3); + return( array('hosts', array('hostname' => $q, 'domain' => $dom, 'nowildcard' => 'yes') ) ); + } + // Well, I guess we'll assume $q is a hostname/alias search printmsg("DEBUG => quick_search() found no subnet or host match. Returning hostname = {$q}" ,3); return( array('hosts', array('hostname' => $q) ) ); @@ -776,12 +804,12 @@ function qsearch_command($q) { if ($js) { $js .= "el('qsearch').value = ''; el('suggest_qsearch').style.display = 'none';"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } else { - $response->addScript("alert('Invalid command!');"); - return($response->getXML()); + $response->script("alert('Invalid command!');"); + return $response; } } @@ -840,9 +868,6 @@ function ws_change_tab($window_name, $form, $display_list=1, $return_text=0) { // Put the cursor in the first field $js .= "_el = el('{$tab}_field1'); if (_el) el('{$tab}_field1').focus();"; - // Hide/show the filter overlay - $js .= "el('{$form_id}_filter_overlay').style.display = (el('{$form_id}_filter').value == '') ? 'inline' : 'none';"; - // Tell the browser to ask for a new list of data if ($display_list) { $js .= "xajax_window_submit('list_{$tab}', xajax.getFormValues('{$form_id}'), 'display_list');"; @@ -854,9 +879,9 @@ function ws_change_tab($window_name, $form, $display_list=1, $return_text=0) { } // Send an XML response to the window - $response->addAssign($_SESSION['ona'][$form_id]['content_id'], 'innerHTML', $conf['loading_icon']); - $response->addScript($js); - return($response->getXML()); + $response->assign($_SESSION['ona'][$form_id]['content_id'], 'innerHTML', $conf['loading_icon']); + $response->script($js); + return $response; } diff --git a/www/winc/search_results_qf.inc.php b/www/winc/search_results_qf.inc.php index 23b91925..92c9ce00 100644 --- a/www/winc/search_results_qf.inc.php +++ b/www/winc/search_results_qf.inc.php @@ -170,9 +170,9 @@ function ws_subnet($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -225,8 +225,8 @@ function ws_free_ip($window_name, $form='') { if ($status or !$rows) { // Send a javascript popup error $response = new xajaxResponse(); - $response->addScript("alert('ERROR => Invalid subnet selected!');"); - return($response->getXML()); + $response->script("alert('ERROR => Invalid subnet selected!');"); + return $response; } // Get a list of interfaces on the selected subnet @@ -335,9 +335,9 @@ function ws_free_ip($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -510,9 +510,9 @@ function ws_location($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } @@ -563,8 +563,8 @@ function ws_vlan($window_name, $form='') { if ($status or !$rows) { // Send a javascript popup error $response = new xajaxResponse(); - $response->addScript("alert('ERROR => Invalid VLAN campus!');"); - return($response->getXML()); + $response->script("alert('ERROR => Invalid VLAN campus!');"); + return $response; } @@ -636,9 +636,9 @@ function ws_vlan($window_name, $form='') { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign($form['content_id'], "innerHTML", $html); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->assign($form['content_id'], "innerHTML", $html); + if ($js) { $response->script($js); } + return $response; } diff --git a/www/winc/tooltips.inc.php b/www/winc/tooltips.inc.php index 98d1833d..31b5b48f 100644 --- a/www/winc/tooltips.inc.php +++ b/www/winc/tooltips.inc.php @@ -111,11 +111,11 @@ function ws_tooltips_submit($window_name, $form='') { // 3. Reposition it // 4. Unhide it $response = new xajaxResponse(); - $response->addScript("el('{$form['id']}').style.visibility = 'hidden';"); - $response->addAssign($form['id'], "innerHTML", $html); - $response->addScript("wwTT_position('{$form['id']}'); el('{$form['id']}').style.visibility = 'visible';"); - if ($js) { $response->addScript($js); } - return($response->getXML()); + $response->script("el('{$form['id']}').style.visibility = 'hidden';"); + $response->assign($form['id'], "innerHTML", $html); + $response->script("wwTT_position('{$form['id']}'); el('{$form['id']}').style.visibility = 'visible';"); + if ($js) { $response->script($js); } + return $response; } @@ -131,7 +131,7 @@ function tagsort($a, $b) { // Update HTML list of tags for specified type // the tag lists will have 5 items per line // The output will be placed in the innerHTML of the 'updateid' dom element -// +// // Form needs to have, type, reference, updateid /////////////////////////////////////// function ws_tag_html($window_name, $form='') { @@ -173,10 +173,10 @@ class="tagdel" } $response = new xajaxResponse(); - $response->addAssign($form['updateid'], "innerHTML", $html); + $response->assign($form['updateid'], "innerHTML", $html); // set extra width in the table so the delete button looks better - $response->addScript("tagTdWidth=el('tagname_{$tag['name']}{$tag['id']}').parentNode.parentNode.offsetWidth+8;el('tagname_{$tag['name']}{$tag['id']}').parentNode.parentNode.setAttribute('style','width:'+tagTdWidth+'px');"); - return($response->getXML()); + $response->script("tagTdWidth=el('tagname_{$tag['name']}{$tag['id']}').parentNode.parentNode.offsetWidth+8;el('tagname_{$tag['name']}{$tag['id']}').parentNode.parentNode.setAttribute('style','width:'+tagTdWidth+'px');"); + return $response; } @@ -309,7 +309,7 @@ function get_sys_alert_html($form) { $html .= << - + @@ -385,8 +385,8 @@ function ws_switch_context($window_name, $form='') { } $response = new xajaxResponse(); - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -422,7 +422,7 @@ function get_loginform_html($form) { $html .= << - + @@ -506,8 +506,8 @@ function ws_logingo($window_name, $form='') { } $response = new xajaxResponse(); - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -833,7 +833,7 @@ function quick_subnet_search($form) { $html .= << - + @@ -936,6 +936,7 @@ function quick_location_search($form) { $js .= << - + @@ -970,7 +971,7 @@ function quick_location_search($form) { Reference @@ -1075,7 +1076,7 @@ function quick_tag_add($form) { $html .= << - + @@ -1150,7 +1151,7 @@ function quick_vlan_search($form) { $html .= << - + @@ -1201,6 +1202,7 @@ function quick_vlan_search($form) { // Javascript to run after the window is built $js = << - + @@ -1335,7 +1337,7 @@ function quick_free_ip_search($form) { EOL; if ($form['text_value'] != "") { - $js .= "xajax_window_submit('search_results_qf', xajax.getFormValues('quick_free_ip_search_form'), 'subnet');"; + $js .= "xajax_window_submit('search_results_qf', xajax.getFormValues('quick_free_ip_search_form'), 'subnet');el('subnet_qf').focus();"; } return(array($html, $js)); } @@ -1396,7 +1398,7 @@ function quick_pool_server_search($form) { $html .= << - + @@ -1607,7 +1609,7 @@ class="nav" $html .= << @@ -56,6 +51,4 @@ } // END CONFIG ARCHIVE LIST - - -?> \ No newline at end of file +?> diff --git a/www/workspace_plugins/builtin/desktop_firsttasks/main.inc.php b/www/workspace_plugins/builtin/desktop_firsttasks/main.inc.php index dba5c8b2..2cbcd136 100644 --- a/www/workspace_plugins/builtin/desktop_firsttasks/main.inc.php +++ b/www/workspace_plugins/builtin/desktop_firsttasks/main.inc.php @@ -19,29 +19,29 @@ try one of these tasks:
      Add a DNS domain 
      Add a new subnet 
      Add a new host 
    - +
    - + @@ -1693,7 +1695,7 @@ function quick_interface_share($form) { $html .= << -
    + @@ -1772,8 +1774,8 @@ function ws_interface_share_save($window_name, $form='') { // Check permissions if (! (auth('interface_del')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -1782,8 +1784,8 @@ function ws_interface_share_save($window_name, $form='') { // Validate input if (!$form['host'] and !$form['ip']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all fields to continue!');"); + return $response; } // Decide if we're editing or adding @@ -1801,8 +1803,8 @@ function ws_interface_share_save($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -1823,8 +1825,8 @@ function ws_interface_share_del($window_name, $form='') { // Check permissions if (! (auth('interface_del')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -1833,8 +1835,8 @@ function ws_interface_share_del($window_name, $form='') { // Validate input if (!$form['host'] and !$form['ip']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all fields to continue!');"); + return $response; } // Decide if we're editing or adding @@ -1852,8 +1854,8 @@ function ws_interface_share_del($window_name, $form='') { } // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -2002,7 +2004,7 @@ function quick_interface_nat($form) { $html .= << - + @@ -2071,8 +2073,8 @@ function ws_interface_nat_save($window_name, $form='') { // Check permissions if (! (auth('interface_modify')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } $form = parse_options_string($form); @@ -2085,8 +2087,8 @@ function ws_interface_nat_save($window_name, $form='') { // Validate input if (!$form['ip'] and !$form['natip']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all fields to continue!');"); + return $response; } // Decide if we're deleting or adding @@ -2101,8 +2103,8 @@ function ws_interface_nat_save($window_name, $form='') { if (!$ptrdomain['id']) { printmsg("ERROR => This operation tried to create a PTR record that is the first in the {$octets[3]}.0.0.0 class A range. You must first create at least the following DNS domain: {$octets[3]}.in-addr.arpa",3); $self['error'] = "ERROR => This operation tried to create a PTR record that is the first in the {$octets[3]}.0.0.0 class A range. You must first create at least the following DNS domain: {$octets[3]}.in-addr.arpa. You could also create domains for class B or class C level reverse zones. Click OK to open add domain dialog"; - $response->addScript("alert('{$self['error']}');xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[3]}.in-addr.arpa', 'editor');"); - return($response->getXML()); + $response->script("alert('{$self['error']}');xajax_window_submit('edit_domain', 'newptrdomainname=>{$octets[3]}.in-addr.arpa', 'editor');"); + return $response; } } @@ -2119,8 +2121,8 @@ function ws_interface_nat_save($window_name, $form='') { // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -2164,7 +2166,7 @@ function quick_interface_move($form) { $html .= << - + @@ -2235,8 +2237,8 @@ function ws_interface_move_save($window_name, $form='') { // Check permissions if (! (auth('advanced')) ) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } // Instantiate the xajaxResponse object @@ -2247,8 +2249,8 @@ function ws_interface_move_save($window_name, $form='') { // Validate input if (!$form['host'] and !$form['ip']) { - $response->addScript("alert('Please complete all fields to continue!');"); - return($response->getXML()); + $response->script("alert('Please complete all fields to continue!');"); + return $response; } list($status, $total_interfaces, $ints) = db_get_records($onadb, 'interfaces', array('host_id' => $form['orig_host']), '', 0); @@ -2285,8 +2287,8 @@ function ws_interface_move_save($window_name, $form='') { // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -2409,7 +2411,7 @@ function get_switchport_template_select($form) { $html .= << - + diff --git a/www/winc/user_edit.inc.php b/www/winc/user_edit.inc.php index 92d0dbea..3d418d64 100644 --- a/www/winc/user_edit.inc.php +++ b/www/winc/user_edit.inc.php @@ -4,7 +4,7 @@ ////////////////////////////////////////////////////////////////////////////// // Function: // Display Edit Form -// +// // Description: // Displays a form for creating/editing a record. // If a record id is found in $form it is used to display an existing @@ -14,15 +14,15 @@ function ws_editor($window_name, $form='') { global $conf, $self, $mysql; global $color, $style, $images; - + // Make sure they have permission if (!auth('admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - - + + // If we got a record ID, load it for display $admin_checked = ''; if (is_string($form) and is_numeric($form)) { @@ -33,97 +33,97 @@ function ws_editor($window_name, $form='') { $admin_checked = 'CHECKED'; } } - - + + // Set a few parameters for the "results" window we're about to create $window = array( 'title' => 'Employee Editor', 'html' => '', 'js' => '', ); - - + + // Escape data for display in html foreach(array_keys($record) as $key) { $record[$key] = htmlentities($record[$key], ENT_QUOTES, $conf['php_charset']); } - + // Load some html into $window['html'] $window['html'] .= <<
    - + - + - + - + - + - + - +
    First Name -
    Last Name -
    Username -
    Password -
    Admin -
      @@ -139,22 +139,22 @@ class="edit" -
    - + EOL; - + // Lets build a window and display the results return(window_open($window_name, $window)); - + } @@ -166,58 +166,58 @@ class="edit" ////////////////////////////////////////////////////////////////////////////// // Function: // Save Form -// +// // Description: // Creates/updates a record with the info from the submitted form. ////////////////////////////////////////////////////////////////////////////// function ws_save($window_name, $form='') { global $conf, $self, $mysql; - + // Make sure they have permission if (!auth('admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - + // Don't allow this in the demo account! if ($_SESSION['auth']['client']['url'] == 'demo') { $response = new xajaxResponse(); - $response->addScript("alert('Feature disabled in this demo!');"); - return($response->getXML()); + $response->script("alert('Feature disabled in this demo!');"); + return $response; } - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); $js = ''; - + // Make sure they're logged in - if (!loggedIn()) { return($response->getXML()); } - + if (!loggedIn()) { return $response; } + // Validate input if (!$form['fname'] or !$form['lname'] or !$form['username']) { $js .= "alert('Error! First name, last name, and username are required fields!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } if (!$form['id'] and !$form['passwd']) { $js .= "alert('Error! A password is required to create a new employee!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } - + // Usernames are stored in lower case $form['username'] = strtolower($form['username']); - + // md5sum the password if there is one if ($form['passwd']) { $form['passwd'] = md5($form['passwd']); } - + // Create a new record? if (!$form['id']) { list ($status, $rows) = db_insert_record( - $mysql, + $mysql, 'users', array( 'client_id' => $_SESSION['auth']['client']['id'], @@ -232,21 +232,21 @@ function ws_save($window_name, $form='') { ); printmsg("NOTICE => Added new user: {$form['username']} client url: {$_SESSION['auth']['client']['url']}", 0); } - + // Update an existing record? else { list($status, $rows, $record) = db_get_record($mysql, 'users', array('id' => $form['id'], 'client_id' => $_SESSION['auth']['client']['id'])); if ($rows != 1 or $record['id'] != $form['id']) { $js .= "alert('Error! The record requested could not be loaded from the database!');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } if (strlen($form['passwd']) < 32) { $form['passwd'] = $record['passwd']; } - + list ($status, $rows) = db_update_record( - $mysql, + $mysql, 'users', array( 'id' => $form['id'], @@ -260,21 +260,21 @@ function ws_save($window_name, $form='') { 'active' => 1 ) ); - + printmsg("NOTICE => Updated user: {$form['username']} client url: {$_SESSION['auth']['client']['url']}", 0); } - + // If the module returned an error code display a popup warning if ($status) { printmsg("ERROR => User add/edit failed! {$self['error']}", 0); $js .= "alert('Save failed. Contact the webmaster if this problem persists.');"; - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } - + $js .= "removeElement('{$window_name}');"; $js .= "xajax_window_submit('user_list', xajax.getFormValues('user_list_filter_form'), 'display_list');"; - + // Handle the "admin" flag list($status, $rows, $user) = db_get_record($mysql, 'users', array('username' => $form['username'], 'client_id' => $_SESSION['auth']['client']['id'], 'active' => 1)); list($status, $rows, $perm) = db_get_record($mysql, 'permissions', array('name' => 'admin')); @@ -286,19 +286,19 @@ function ws_save($window_name, $form='') { else if (!$form['admin'] and $acl['id'] and $user['id'] and $perm['id'] and ($_SESSION['auth']['user']['id'] != $user['id']) ) { // Take the permission away, UNLESS THEY ARE TRYING TO MODIFY THEIR OWN ACCOUNT! list($status, $rows) = db_delete_record($mysql, 'acl', array('user_id' => $user['id'], 'perm_id' => $perm['id'])); - + } else if ($_SESSION['auth']['user']['id'] == $user['id']) { // IF they did try to remove their own admin status, give them a popup and tell them they can't do that. $js .= "alert('WARNING => You can\\'t change your own admin status!');"; } - + // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } -?> \ No newline at end of file +?> diff --git a/www/winc/user_list.inc.php b/www/winc/user_list.inc.php index 01114628..e6848fbe 100644 --- a/www/winc/user_list.inc.php +++ b/www/winc/user_list.inc.php @@ -1,5 +1,5 @@
    - + - + - +
    Employees
    @@ -49,14 +49,14 @@ cursor: text;" onClick="this.style.display = 'none'; el('{$form_id}_filter').focus();" >Filter -
    - +
    {$conf['loading_icon']}
    - +
    EOL; @@ -87,7 +87,7 @@ class="filter" /* Setup the quick filter */ el('{$form_id}_filter_overlay').style.left = (el('{$form_id}_filter_overlay').offsetWidth + 10) + 'px'; {$form_id}_last_search = ''; - + /* Tell the browser to load/display the list */ xajax_window_submit('{$submit_window}', xajax.getFormValues('{$form_id}'), 'display_list'); EOL; @@ -102,53 +102,53 @@ class="filter" function ws_display_list($window_name, $form) { global $conf, $self, $mysql; global $font_family, $color, $style, $images; - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); - + // Make sure they're logged in - if (!loggedIn()) { return($response->getXML()); } - + if (!loggedIn()) { return $response; } + // If the user supplied an array in a string, build the array and store it in $form $form = parse_options_string($form); - + // Find out what page we're on $page = 1; if ($form['page'] and is_numeric($form['page'])) { $page = $form['page']; } - + printmsg("INFO => Displaying user list page: {$page} client url: {$_SESSION['auth']['client']['url']}", 0); - + // Calculate the SQL query offset (based on the page being displayed) $offset = ($conf['search_results_per_page'] * ($page - 1)); if ($offset == 0) { $offset = -1; } - - + + $where = "`client_id` = {$_SESSION['auth']['client']['id']} AND `active` = 1"; if (is_array($form) and $form['filter']) { $where .= ' AND `username` LIKE ' . $mysql->qstr('%'.$form['filter'].'%'); } - + // Get our employees list($status, $rows, $records) = db_get_records($mysql, 'users', $where, 'username', $conf['search_results_per_page'], $offset); - + // If we got less than serach_results_per_page, add the current offset to it // so that if we're on the last page $rows still has the right number in it. if ($rows > 0 and $rows < $conf['search_results_per_page']) { $rows += ($conf['search_results_per_page'] * ($page - 1)); } - + // If there were more than $conf['search_results_per_page'] find out how many records there really are else if ($rows >= $conf['search_results_per_page']) { list ($status, $rows, $tmp) = db_get_records($mysql, 'users', $where, '', 0); } $count = $rows; - + // Add a table header $html = << - + @@ -157,55 +157,55 @@ function ws_display_list($window_name, $form) { - + EOL; - + // Loop through and display the records foreach ($records as $record) { - + list ($status, $rows, $client) = db_get_record($mysql, 'clients', array('id' => $record['client_id'])); $record['company_name'] = $client['company_name']; - + // Escape data for display in html - foreach(array_keys($record) as $key) { + foreach(array_keys($record) as $key) { $record[$key] = htmlentities($record[$key], ENT_QUOTES, $conf['php_charset']); } - + // If the user is an admin, set some extra html $admin_html = ""; if (empty($perm)) list($status, $rows, $perm) = db_get_record($mysql, 'permissions', array('name' => 'admin')); list($status, $rows, $acl) = db_get_record($mysql, 'acl', array('user_id' => $record['id'], 'perm_id' => $perm['id'])); if ($acl['id']) $admin_html = ""; - - + + $html .= << - + - + - + - + - + - + EOL; } - + $html .= << @@ -226,27 +226,26 @@ class="act" class="act" onClick="xajax_window_submit('user_edit', ' ', 'editor');" >  - + Add new employee  - +
    UsernameAdmin  
    {$record['username']}  {$record['fname']} {$record['lname']}  {$record['company_name']}  {$admin_html}    - +  
    EOL; - - + + // Build page links if there are any $html .= get_page_links($page, $conf['search_results_per_page'], $count, $window_name, $form['form_id']); - - + + // Insert the new table into the window - $response->addAssign("{$form['form_id']}_employees_count", "innerHTML", "({$count})"); - $response->addAssign("{$form['content_id']}", "innerHTML", $html); - // $response->addScript($js); - return($response->getXML()); + $response->assign("{$form['form_id']}_employees_count", "innerHTML", "({$count})"); + $response->assign("{$form['content_id']}", "innerHTML", $html); + return $response; } @@ -256,44 +255,44 @@ class="act" ////////////////////////////////////////////////////////////////////////////// // Function: delete() -// +// // Description: // Deletes a record. ////////////////////////////////////////////////////////////////////////////// function ws_delete($window_name, $form='') { global $conf, $self, $mysql; - + // Make sure they have permission if (!auth('admin')) { $response = new xajaxResponse(); - $response->addScript("alert('Permission denied!');"); - return($response->getXML()); + $response->script("alert('Permission denied!');"); + return $response; } - + // Don't allow this in the demo account! if ($_SESSION['auth']['client']['url'] == 'demo') { $response = new xajaxResponse(); - $response->addScript("alert('Feature disabled in this demo!');"); - return($response->getXML()); + $response->script("alert('Feature disabled in this demo!');"); + return $response; } - + // Don't allow a user to delete their own account! if ($_SESSION['auth']['user']['id'] == $form) { $response = new xajaxResponse(); - $response->addScript("alert('Sorry, but you can\\'t delete your own admin account!');"); - return($response->getXML()); + $response->script("alert('Sorry, but you can\\'t delete your own admin account!');"); + return $response; } - + // Instantiate the xajaxResponse object $response = new xajaxResponse(); $js = ''; - - + + // Set the user to inactive (which will make them "dissapear" for all practical purposes) printmsg("NOTICE => Deleting (disabling) user: {$form} client url: {$_SESSION['auth']['client']['url']}", 0); list($status, $rows) = db_update_record($mysql, 'users', array('client_id' => $_SESSION['auth']['client']['id'], 'id' => $form), array('active' => 0)); - + // If the module returned an error code display a popup warning if ($status != 0 or $rows != 1) { $js .= "alert('Delete failed');"; @@ -302,10 +301,10 @@ function ws_delete($window_name, $form='') { // Refresh the current list of templates.. it's changed! $js .= "xajax_window_submit('{$window_name}', xajax.getFormValues('{$window_name}_filter_form'), 'display_list');"; } - + // Insert the new table into the window - $response->addScript($js); - return($response->getXML()); + $response->script($js); + return $response; } @@ -318,4 +317,4 @@ function ws_delete($window_name, $form='') { -?> \ No newline at end of file +?> diff --git a/www/winc/work_space.inc.php b/www/winc/work_space.inc.php index eb5a80ac..79a2221e 100644 --- a/www/winc/work_space.inc.php +++ b/www/winc/work_space.inc.php @@ -153,7 +153,7 @@ function ws_work_space_submit($window_name, $javascript='') { // This also updates the work space window's title. ////////////////////////////////////////////////////////////////////////////// function ws_rewrite_history($window_name, $null='', $return_html=0) { - global $conf, $self, $color, $style, $images; + global $conf, $self, $color, $style, $images, $year; $html = $js = ''; @@ -190,10 +190,10 @@ function ws_rewrite_history($window_name, $null='', $return_html=0) { // Insert the new html into the window // Instantiate the xajaxResponse object $response = new xajaxResponse(); - $response->addAssign("trace_history", "innerHTML", $html); - $response->addAssign("work_space_title_r", "innerHTML", $new_buttons); - $response->addAssign("work_space_title", "innerHTML", $new_title); - return($response->getXML()); + $response->assign("trace_history", "innerHTML", $html); + $response->assign("work_space_title_r", "innerHTML", $new_buttons); + $response->assign("work_space_title", "innerHTML", $new_title); + return $response; } diff --git a/www/workspace_plugins/builtin/config_archives/main.inc.php b/www/workspace_plugins/builtin/config_archives/main.inc.php index b57ad894..74f2d436 100644 --- a/www/workspace_plugins/builtin/config_archives/main.inc.php +++ b/www/workspace_plugins/builtin/config_archives/main.inc.php @@ -1,9 +1,5 @@ $record['id'], 'configuration_type_id' => $type['id']), '', 0); if ($rows) { // Select the first config record of the specified type and host - list($status, $rows, $config) = ona_get_config_record(array('host_id' => $record['id'],'configuration_type_id' => $type['id'])); + list($status, $rows_conf, $config) = db_get_records($onadb, 'configurations', array('host_id' => $record['id'], 'configuration_type_id' => $type['id']), 'ctime DESC', 1); // Escape data for display in html foreach(array_keys($type) as $key) { $type[$key] = htmlentities($type[$key], ENT_QUOTES); } @@ -30,7 +25,7 @@ style="cursor: pointer;" onMouseOver="this.className='row-highlight';" onMouseOut="this.className='row-normal';" - onClick="xajax_window_submit('work_space', 'xajax_window_submit(\'display_config_text\', \'host_id=>{$record['id']},type_id=>{$type['id']},displayconf=>{$config['id']}\', \'display\')');" + onClick="xajax_window_submit('work_space', 'xajax_window_submit(\'display_config_text\', \'host_id=>{$record['id']},type_id=>{$type['id']},displayconf=>{$config[0]['id']}\', \'display\')');" >
    {$type['name']} ({$rows})