├── BASH ├── LetsencryptGlesysHook │ ├── README.md │ ├── config │ ├── glesys-dns-01-hook.sh │ └── glesys-dns-01-lbl-hook.sh ├── LocalCPUCoresUpgradeDowngrade │ ├── README.md │ └── cpumonitor.sh ├── LocalMemUpgrade │ ├── README.md │ └── upgrademem.bash ├── LocalMemoryUpgradeDowngrade │ ├── README.md │ └── memmonitor.sh ├── RemoteMemUpgrade │ ├── README.md │ └── memupgrade.bash └── RoundRobinLoadBalancer │ ├── README.md │ └── balancer.bash ├── LICENSE ├── PHP ├── DNSZone │ ├── README.md │ ├── example.com.txt │ └── php_glesys_zone_import.php ├── InvoiceRSS │ ├── README.md │ └── rss.php ├── MiniControlpanel │ ├── APIClient.php │ ├── README.md │ ├── full_example.php │ └── mini_example.php └── api_classes │ ├── README.txt │ ├── docs │ ├── glesys_domain.txt │ └── glesys_email.txt │ ├── glesys_api.php │ ├── glesys_domain.php │ ├── glesys_email.php │ └── idna_convert.php ├── Python └── ConkyServerStatus │ ├── README.md │ ├── conky.png │ ├── conkyserverstatus.py │ └── glesys.conf ├── README.md └── Ruby ├── CreateDestroyList ├── GlesysAPI.rb └── README.md ├── README.md ├── domain ├── README.md └── domain.rb └── glesys.rb /BASH/LetsencryptGlesysHook/README.md: -------------------------------------------------------------------------------- 1 | # letsencrypt-glesys-hook (DNS-01 and the GleSYS API). 2 | How to set up letsencrypt via DNS (glesys-dns01) Works for wildcard 3 | 4 | ## Dependencies 5 | - dehydrated (apt-get install dehydrated) 6 | - curl 7 | - xmlstarlet (apt-get install curl xmlstarlet) 8 | - GleSYS API credentials (DOMAIN permissions for list, add, remove records) 9 | (in case you want to upload the cert to load-balancer you will need permissions to the LB too) 10 | 11 | ## Instructions 12 | 13 | - Create an API key for the GleSYS API in the control panel as described above 14 | - echo "export USER=CL12345" > /etc/ssl/private/.glesys-credentials 15 | - echo "export KEY=KEY_GOES_HERE" >> /etc/ssl/private/.glesys-credentials 16 | - echo "export LOADBALANSERID=lb1234567" >> /etc/ssl/private/.glesys-credentials (in case you use load-balancer) 17 | - chmod 600 /etc/ssl/private/.glesys-credentials 18 | - cd /etc/dehydrated 19 | - wget https://raw.githubusercontent.com/glesys/api-docs/master/BASH/LetsencryptGlesysHook/glesys-dns-01-hook.sh 20 | - wget https://raw.githubusercontent.com/glesys/api-docs/master/BASH/LetsencryptGlesysHook/glesys-dns-01-lbl-hook.sh 21 | - wget https://raw.githubusercontent.com/lukas2511/dehydrated/master/dehydrated 22 | - wget -q https://raw.githubusercontent.com/glesys/api-docs/master/BASH/LetsencryptGlesysHook/config -O /etc/dehydrated/config 23 | - chmod 700 /etc/dehydrated/glesys-dns-01-hook.sh /etc/dehydrated/glesys-dns-01-lbl-hook.sh /etc/dehydrated/dehydrated 24 | - edit your /etc/dehydrated/config to include the hook you want to use 25 | * glesys-dns-01-hook.sh # if you don't have a load-balancer # Active by default 26 | * glesys-dns-01-lbl-hook.sh # to be upload the cert direct to the load-balancer 27 | - echo "example.com *.example.com" > /etc/dehydrated/domains.txt # your domain here! 28 | - ./dehydrated --register --accept-terms 29 | - ./dehydrated -c 30 | -------------------------------------------------------------------------------- /BASH/LetsencryptGlesysHook/config: -------------------------------------------------------------------------------- 1 | CONFIG_D=/etc/dehydrated/conf.d 2 | BASEDIR=/etc/ssl/private 3 | WELLKNOWN="${BASEDIR}/acme-challenges" 4 | DOMAINS_TXT="/etc/dehydrated/domains.txt" 5 | CHALLENGETYPE="dns-01" 6 | HOOK="/etc/dehydrated/glesys-dns-01-hook.sh" 7 | #HOOK="/etc/dehydrated/glesys-dns-01-lbl-hook.sh" 8 | CONTACT_EMAIL=user@example.com 9 | CHAIN="yes" 10 | CA="https://acme-v02.api.letsencrypt.org/directory" 11 | #CA="https://acme-staging-v02.api.letsencrypt.org/directory" 12 | -------------------------------------------------------------------------------- /BASH/LetsencryptGlesysHook/glesys-dns-01-hook.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # An improved hook script for dehydrated and GleSYS API. 4 | # 5 | # Contributions by 6 | # * kiranos: https://github.com/kiranos/ 7 | # * marcusmansson: https://gitlab.com/marcusmansson/glesys-dns01 8 | # * abed19919: https://github.com/abdulaziz-alahmad/ 9 | # 10 | # Dependencies 11 | # ============ 12 | # - curl and xmlstarlet (debian: apt-get install curl xmlstarlet) 13 | # - GleSYS API credentials (DOMAIN permissions for list, add, remove records) 14 | # 15 | # Prerequisites 16 | # ============= 17 | # Read README.md 18 | # 19 | # echo "export USER=CL12345" > /etc/ssl/private/.glesys-credentials 20 | # echo "export KEY=KEY_GOES_HERE" >> /etc/ssl/private/.glesys-credentials 21 | # chmod 600 /etc/ssl/private/.glesys-credentials 22 | # 23 | # IMPORTANT 24 | # ========= 25 | # Edit your dehydrated config and set CHAIN="yes", otherwise wildcard urls 26 | # will not work if you create a combo cert for both domain.tld and *.domain.tld. 27 | # 28 | # CHAIN="yes" 29 | # 30 | # 31 | set -e 32 | set -o pipefail 33 | umask 077 34 | HOOK=$1 35 | TIME=$(date) 36 | LOGFILE=/var/log/glesys-dns-01.log 37 | VERBOSE= 38 | 39 | _cleanup () { 40 | rm -f /tmp/api-log.xml 41 | } 42 | trap _cleanup EXIT 43 | 44 | # Tail logfile in background (if interactive) 45 | if [[ $VERBOSE ]] && test -t 0; then 46 | tail --pid $$ -f $LOGFILE & 47 | fi 48 | 49 | # Check required bins. 50 | hash xmlstarlet 51 | hash curl 52 | 53 | # Load GleSYS Credentials. 54 | source /etc/ssl/private/.glesys-credentials 55 | 56 | # Parse all domain challenges from argument list. 57 | domains=(); 58 | _parse_domains () { 59 | shift; 60 | while (( "$#" )); do 61 | read -r FQDN _ CHALLENGE _ <<< "$@" 62 | shift 3 63 | # convert fqdn to array and get the last two slices 64 | x=(${FQDN//./ }) 65 | x="${x[@]: -2:2}" 66 | DOMAIN=${x// /.} 67 | domains+=("$DOMAIN $FQDN $CHALLENGE") 68 | done 69 | } 70 | 71 | _start_log () { 72 | echo $TIME: "$@" 73 | echo $TIME: $(declare -p domains) 74 | } >> $LOGFILE 75 | 76 | _validate_response () { 77 | # Check if API call got status 200 (OK). 78 | STATUSCODE=$(xmlstarlet sel -t -v "/response/status/code" /tmp/api-log.xml) 79 | 80 | if [[ $STATUSCODE -ne 200 ]]; then 81 | ERRORCODE=$(xmlstarlet sel -t -v "/response/status/text" /tmp/api-log.xml) 82 | echo "Error in $0: $ERRORCODE" 83 | exit 1 84 | fi 85 | } 86 | 87 | request_failure() { 88 | local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}" HEADERS="${4}" 89 | 90 | # This hook is called when an HTTP request fails (e.g., when the ACME 91 | # server is busy, returns an error, etc). It will be called upon any 92 | # response code that does not start with '2'. Useful to alert admins 93 | # about problems with requests. 94 | # 95 | # Parameters: 96 | # - STATUSCODE 97 | # The HTML status code that originated the error. 98 | # - REASON 99 | # The specified reason for the error. 100 | # - REQTYPE 101 | # The kind of request that was made (GET, POST...) 102 | # - HEADERS 103 | # HTTP headers returned by the CA 104 | 105 | # Simple example: Send mail to root 106 | # printf "Subject: HTTP request failed failed!\n\nA http request failed with status ${STATUSCODE}!" | sendmail root 107 | } 108 | 109 | deploy_challenge () { 110 | _parse_domains $@ 111 | 112 | # Create TXT records for all ACME challenges. 113 | for domain in "${domains[@]}"; do 114 | read DOMAIN FQDN CHALLENGE <<< "$domain" 115 | glesys_api addrecord domainname=$DOMAIN \ 116 | host=_acme-challenge.$FQDN. type=TXT ttl=600 data=$CHALLENGE 117 | done 118 | 119 | # Wait for settings to apply on the endpoint. 120 | echo "Wait for settings to apply on the endpoint. 20sec" 121 | sleep 20 122 | } 123 | 124 | clean_challenge () { 125 | _parse_domains $@ 126 | local lastdomain="" 127 | 128 | # For all hosts: 129 | for domain in "${domains[@]}"; do 130 | read DOMAIN FQDN CHALLENGE <<< "$domain" 131 | [[ $DOMAIN = $lastdomain ]] && continue 132 | lastdomain=$DOMAIN 133 | 134 | # API call to retrieve list of records for the domain. 135 | glesys_api listrecords domainname=$DOMAIN 136 | 137 | acme_records=$(xmlstarlet sel -t \ 138 | -m "//host[contains(., '_acme-challenge')]/.." \ 139 | -v "concat(recordid, ' ')" \ 140 | -n /tmp/api-log.xml) 141 | 142 | # Remove TXT records created by this script. 143 | for id in $acme_records; do 144 | glesys_api deleterecord recordid=$id 145 | done 146 | done 147 | } 148 | 149 | sync_cert() { 150 | local KEYFILE="${1}" CERTFILE="${2}" FULLCHAINFILE="${3}" CHAINFILE="${4}" REQUESTFILE="${5}" 151 | 152 | # This hook is called after the certificates have been created but before 153 | # they are symlinked. This allows you to sync the files to disk to prevent 154 | # creating a symlink to empty files on unexpected system crashes. 155 | # 156 | # This hook is not intended to be used for further processing of certificate 157 | # files, see deploy_cert for that. 158 | # 159 | # Parameters: 160 | # - KEYFILE 161 | # The path of the file containing the private key. 162 | # - CERTFILE 163 | # The path of the file containing the signed certificate. 164 | # - FULLCHAINFILE 165 | # The path of the file containing the full certificate chain. 166 | # - CHAINFILE 167 | # The path of the file containing the intermediate certificate(s). 168 | # - REQUESTFILE 169 | # The path of the file containing the certificate signing request. 170 | 171 | # Simple example: sync the files before symlinking them 172 | # sync "${KEYFILE}" "${CERTFILE} "${FULLCHAINFILE}" "${CHAINFILE}" "${REQUESTFILE}" 173 | } 174 | 175 | deploy_cert () { 176 | local DOMAIN="${2}" KEYFILE="${3}" CERTFILE="${4}" FULLCHAINFILE="${5}" CHAINFILE="${6}" TIMESTAMP="${4}" 177 | echo "DOMAIN: $DOMAIN" 178 | echo "CERTFILE: $CERTFILE" 179 | echo "KEYFILE: $KEYFILE" 180 | echo "CHAINFILE: $CHAINFILE" 181 | echo "FULLCHAINFILE: $FULLCHAINFILE" 182 | 183 | # Add you script here to be run after the certificate is created/renewed 184 | echo "You should restart or reload the service that handel the SSL certs" 185 | # 186 | # Uncomment what matches servers setup. 187 | # 188 | # Apache2 189 | #/etc/init.d/apache2 restart 190 | # 191 | # Nginx 192 | #/etc/init.d/nginx restart 193 | # 194 | # HaProxy 195 | #cat $5 > /etc/haproxy/ssl/$2.pem 196 | #cat $3 >> /etc/haproxy/ssl/$2.pem 197 | #chmod 600 /etc/haproxy/ssl/$2.pem 198 | #/etc/init.d/haproxy reload 199 | # 200 | # Postfix 201 | #/etc/init.d/postfix reload 202 | # 203 | ##################################################################### 204 | } 205 | 206 | invalid_challenge() { 207 | local DOMAIN="${1}" RESPONSE="${2}" 208 | 209 | # This hook is called if the challenge response has failed, so domain 210 | # owners can be aware and act accordingly. 211 | # 212 | # Parameters: 213 | # - DOMAIN 214 | # The primary domain name, i.e. the certificate common 215 | # name (CN). 216 | # - RESPONSE 217 | # The response that the verification server returned 218 | # Simple example: Send mail to root 219 | # printf "Subject: Validation of ${DOMAIN} failed!\n\nOh noez!" | sendmail root 220 | } 221 | 222 | exit_hook () { 223 | # - You might want to restart your web server here or 224 | # - Truncate log file, since no errors occured 225 | # Uncomment the next line if you want to remove the logfile at this point 226 | # rm $LOGFILE 227 | : 228 | } 229 | 230 | # Prefix all words using first argument as prefix. 231 | _prefix () { 232 | local prefix=$1; shift 233 | printf "%s" "${@/#/$prefix}" 234 | } 235 | 236 | # API query parts. 237 | CURL="curl -sS -X POST -k --basic" 238 | API_ENDPOINT="--url https://api.glesys.com/domain" 239 | glesys_api () { 240 | local METHOD=$1; shift 241 | 242 | # Add --data-urlencode to all arguments. 243 | local PARAMS=$(_prefix " --data-urlencode " $@) 244 | 245 | # Log query. 246 | echo "\n$TIME: $CURL $API_ENDPOINT/$METHOD/ $PARAMS" 247 | 248 | # Perform actual query in a safe manner. 249 | $CURL $API_ENDPOINT/$METHOD/ $PARAMS -K- <<< "-u $USER:$KEY" | tee /tmp/api-log.xml 250 | 251 | # Make sure it succeeded. 252 | _validate_response 253 | } >> $LOGFILE 254 | 255 | _start_log $@ 256 | 257 | # Run hook (if defined). 258 | declare -f $HOOK > /dev/null && $HOOK $@ 259 | exit 0 260 | -------------------------------------------------------------------------------- /BASH/LetsencryptGlesysHook/glesys-dns-01-lbl-hook.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # An improved hook script for dehydrated and GleSYS API. 4 | # 5 | # Contributions by 6 | # * kiranos: https://github.com/kiranos/ 7 | # * marcusmansson: https://gitlab.com/marcusmansson/glesys-dns01 8 | # * abed19919: https://github.com/abdulaziz-alahmad/ 9 | # 10 | # Dependencies 11 | # ============ 12 | # - curl and xmlstarlet (debian: apt-get install curl xmlstarlet) 13 | # - GleSYS API credentials (DOMAIN permissions for list, add, remove records) 14 | # 15 | # Prerequisites 16 | # ============= 17 | # Read README.md 18 | # 19 | # echo "export USER=CL12345" > /etc/ssl/private/.glesys-credentials 20 | # echo "export KEY=KEY_GOES_HERE" >> /etc/ssl/private/.glesys-credentials 21 | # echo "export LOADBALANSERID=lb1234567" >> /etc/ssl/private/.glesys-credentials 22 | # chmod 600 /etc/ssl/private/.glesys-credentials 23 | # 24 | # IMPORTANT 25 | # ========= 26 | # Edit your dehydrated config and set CHAIN="yes", otherwise wildcard urls 27 | # will not work if you create a combo cert for both domain.tld and *.domain.tld. 28 | # 29 | # CHAIN="yes" 30 | # 31 | # 32 | set -e 33 | set -o pipefail 34 | umask 077 35 | HOOK=$1 36 | TIME=$(date) 37 | LOGFILE=/var/log/glesys-dns-lb-01.log 38 | VERBOSE= 39 | 40 | _cleanup () { 41 | rm -f /tmp/api-log.xml 42 | } 43 | trap _cleanup EXIT 44 | 45 | # Tail logfile in background (if interactive) 46 | if [[ $VERBOSE ]] && test -t 0; then 47 | tail --pid $$ -f $LOGFILE & 48 | fi 49 | 50 | # Check required bins. 51 | hash xmlstarlet 52 | hash curl 53 | 54 | # Load GleSYS Credentials. 55 | source /etc/ssl/private/.glesys-credentials 56 | 57 | # Parse all domain challenges from argument list. 58 | domains=(); 59 | _parse_domains () { 60 | shift; 61 | while (( "$#" )); do 62 | read -r FQDN _ CHALLENGE _ <<< "$@" 63 | shift 3 64 | # convert fqdn to array and get the last two slices 65 | x=(${FQDN//./ }) 66 | x="${x[@]: -2:2}" 67 | DOMAIN=${x// /.} 68 | domains+=("$DOMAIN $FQDN $CHALLENGE") 69 | done 70 | } 71 | 72 | _start_log () { 73 | echo $TIME: "$@" 74 | echo $TIME: $(declare -p domains) 75 | } >> $LOGFILE 76 | 77 | _validate_response () { 78 | # Check if API call got status 200 (OK). 79 | STATUSCODE=$(xmlstarlet sel -t -v "/response/status/code" /tmp/api-log.xml) 80 | 81 | if [[ $STATUSCODE -ne 200 ]]; then 82 | ERRORCODE=$(xmlstarlet sel -t -v "/response/status/text" /tmp/api-log.xml) 83 | echo "Error in $0: $ERRORCODE" 84 | exit 1 85 | fi 86 | } 87 | 88 | request_failure() { 89 | local STATUSCODE="${1}" REASON="${2}" REQTYPE="${3}" HEADERS="${4}" 90 | # This hook is called when an HTTP request fails (e.g., when the ACME 91 | # server is busy, returns an error, etc). It will be called upon any 92 | # response code that does not start with '2'. Useful to alert admins 93 | # about problems with requests. 94 | # 95 | # Parameters: 96 | # - STATUSCODE 97 | # The HTML status code that originated the error. 98 | # - REASON 99 | # The specified reason for the error. 100 | # - REQTYPE 101 | # The kind of request that was made (GET, POST...) 102 | # - HEADERS 103 | # HTTP headers returned by the CA 104 | # Simple example: Send mail to root 105 | # printf "Subject: HTTP request failed failed!\n\nA http request failed with status ${STATUSCODE}!" | sendmail root 106 | } 107 | 108 | deploy_challenge () { 109 | _parse_domains $@ 110 | 111 | # Create TXT records for all ACME challenges. 112 | for domain in "${domains[@]}"; do 113 | read DOMAIN FQDN CHALLENGE <<< "$domain" 114 | glesys_api addrecord domainname=$DOMAIN \ 115 | host=_acme-challenge.$FQDN. type=TXT ttl=600 data=$CHALLENGE 116 | done 117 | 118 | # Wait for settings to apply on the endpoint. 119 | echo "Wait for settings to apply on the endpoint. 20sec" 120 | sleep 20 121 | } 122 | 123 | clean_challenge () { 124 | _parse_domains $@ 125 | local lastdomain="" 126 | 127 | # For all hosts: 128 | for domain in "${domains[@]}"; do 129 | read DOMAIN FQDN CHALLENGE <<< "$domain" 130 | [[ $DOMAIN = $lastdomain ]] && continue 131 | lastdomain=$DOMAIN 132 | 133 | # API call to retrieve list of records for the domain. 134 | glesys_api listrecords domainname=$DOMAIN 135 | 136 | acme_records=$(xmlstarlet sel -t \ 137 | -m "//host[contains(., '_acme-challenge')]/.." \ 138 | -v "concat(recordid, ' ')" \ 139 | -n /tmp/api-log.xml) 140 | 141 | # Remove TXT records created by this script. 142 | for id in $acme_records; do 143 | glesys_api deleterecord recordid=$id 144 | done 145 | done 146 | } 147 | 148 | function validate_xml { 149 | #Check if API call got status 200 (OK) 150 | STATUSCODE=`xmlstarlet sel -t -v "/response/status/code" /tmp/api-log.xml` 151 | if [ "$STATUSCODE" -ne 200 ]; then 152 | ERRORCODE=`xmlstarlet sel -t -v "/response/status/text" /tmp/api-log.xml` 153 | echo "Error: $ERRORCODE" 154 | exit 1 155 | fi 156 | } 157 | 158 | deploy_cert () { 159 | 160 | #Create single PEM 161 | cat $5 > /etc/ssl/private/certs/$2/$2.pem 162 | cat $3 >> /etc/ssl/private/certs/$2/$2.pem 163 | chmod 600 /etc/ssl/private/certs/$2/$2.pem 164 | date=`date +"%F"` 165 | 166 | #upload cert 167 | cert="/etc/ssl/private/certs/$2/$2.pem" 168 | curl -s -X POST --data-urlencode loadbalancerid="$LOADBALANSERID" --data-urlencode certificatename="letsencrypt-$date" --data-urlencode certificate="`base64 -i $cert |tr -d '\012'`" -k --basic -u $USER:$KEY https://api.glesys.com/loadbalancer/addcertificate/ > /tmp/api-log.xml 169 | validate_xml 170 | 171 | #Get name of frontend which is listening on 443 172 | curl -s -X POST --data-urlencode loadbalancerid="$LOADBALANSERID" -k --basic -u $USER:$KEY https://api.glesys.com/loadbalancer/details/ > /tmp/api-log.xml 173 | validate_xml 174 | frontend=`xmlstarlet sel -t -v "/response/loadbalancer/frontends/item[port=443]/name" /tmp/api-log.xml` 175 | 176 | #change cert on frontend 177 | curl -s -X POST --data-urlencode loadbalancerid="$LOADBALANSERID" --data-urlencode frontendname="$frontend" --data-urlencode sslcertificate="letsencrypt-$date" -k --basic -u $USER:$KEY https://api.glesys.com/loadbalancer/editfrontend/ > /tmp/api-log.xml 178 | validate_xml 179 | } 180 | 181 | unchanged_cert () { 182 | 183 | echo "Certificate for domain $2 is still valid - no action taken" 184 | 185 | } 186 | 187 | 188 | exit_hook () { 189 | # - You might want to restart your web server here or 190 | # - Truncate log file, since no errors occured 191 | # Uncomment the next line if you want to remove the logfile at this point 192 | # rm $LOGFILE 193 | : 194 | } 195 | 196 | # Prefix all words using first argument as prefix. 197 | _prefix () { 198 | local prefix=$1; shift 199 | printf "%s" "${@/#/$prefix}" 200 | } 201 | 202 | 203 | 204 | 205 | 206 | # API query parts. 207 | CURL="curl -sS -X POST -k --basic" 208 | API_ENDPOINT="--url https://api.glesys.com/domain" 209 | glesys_api () { 210 | local METHOD=$1; shift 211 | 212 | # Add --data-urlencode to all arguments. 213 | local PARAMS=$(_prefix " --data-urlencode " $@) 214 | 215 | # Log query. 216 | echo "\n$TIME: $CURL $API_ENDPOINT/$METHOD/ $PARAMS" 217 | 218 | # Perform actual query in a safe manner. 219 | $CURL $API_ENDPOINT/$METHOD/ $PARAMS -K- <<< "-u $USER:$KEY" | tee /tmp/api-log.xml 220 | 221 | # Make sure it succeeded. 222 | _validate_response 223 | } >> $LOGFILE 224 | 225 | _start_log $@ 226 | 227 | # Run hook (if defined). 228 | declare -f $HOOK > /dev/null && $HOOK $@ 229 | exit 0 230 | -------------------------------------------------------------------------------- /BASH/LocalCPUCoresUpgradeDowngrade/README.md: -------------------------------------------------------------------------------- 1 | #Add/Remove CPU Cores on a virtual server using GleSYS API 2 | 3 | Author: [Jasper Metselaar](/formmailer) 4 | 5 | This BASH-script will add or remove CPU cores for a Glesys virtual server using the API. 6 | 7 | The script will add a CPU core automatically when the CPU load has been 1.0 or more per core during the past 15 minutes. 8 | 9 | A core will be removed when the CPU usage drops. (below the number of cores minus 1.0.) 10 | 11 | You will be notified by mail when cores have been added or removed. 12 | 13 | This script should be run as a cron-job (typically every 5 to ten minutes) to upgrade and downgrade a server depending on 14 | the current needs. 15 | -------------------------------------------------------------------------------- /BASH/LocalCPUCoresUpgradeDowngrade/cpumonitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CORES=$(grep 'model name' /proc/cpuinfo | wc -l) 4 | LOAD=$(uptime | grep "load average" | awk '{print $NF}' | sed 's/[\.,].*//g') 5 | if [ $LOAD -ge $CORES ]; then 6 | NEWCORES=$((CORES+1)); 7 | /usr/bin/curl -X POST -d serverid=vz1234567\&cpucores=$NEWCORES -k --basic -u cl12345:[api-key] https://api.glesys.com/server/edit/ 8 | ( 9 | echo -e "Adding a core. Server has now $NEWCORES cores.\n" 10 | uptime 11 | ) | mail -s "High CPU on server $HOSTNAME: average load > $CORES - CPU report" user@mail.com 12 | fi 13 | 14 | if [ $LOAD -lt $CORES ] && [ $CORES -gt 1 ]; then 15 | NEWCORES=$((CORES-1)); 16 | /usr/bin/curl -X POST -d serverid=vz1234567\&cpucores=$NEWCORES -k --basic -u cl12345:[api-key] https://api.glesys.com/server/edit/ 17 | ( 18 | echo -e "Removing a core. Server has now $NEWCORES cores.\n" 19 | uptime 20 | ) | mail -s "Server $HOSTNAME has to many cores: average load < $CORES - CPU report" user@mail.com 21 | fi 22 | -------------------------------------------------------------------------------- /BASH/LocalMemUpgrade/README.md: -------------------------------------------------------------------------------- 1 | #Upgrade memory on local server 2 | 3 | Author: [Emil Andersson](/emil-nasso) 4 | 5 | This simple scripts checks if the server has used more than 90% of its memory. If it has, it upgrades to 2048mb memory. 6 | 7 | There are alot of possible improvements that should probably be added to this script before being used in production but it serves good as an example. One problem is that is probably wont be able to run if the server has 100% used memory. 8 | 9 | 10 | -------------------------------------------------------------------------------- /BASH/LocalMemUpgrade/upgrademem.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TOTAL=`free | grep Mem: | awk '{print $2}'` 3 | USED=`free | grep Mem: | awk '{print $3}'` 4 | PERCENTAGE=$(((USED*100)/TOTAL)); 5 | if [ $PERCENTAGE -gt 90 ]; then 6 |        /usr/bin/curl -X POST -d serverid=vz123456\&memorysize=2048 -k --basic -u clXXXXX:API-KEY https://api.glesys.com/server/edit/ 7 | fi; 8 | -------------------------------------------------------------------------------- /BASH/LocalMemoryUpgradeDowngrade/README.md: -------------------------------------------------------------------------------- 1 | #Upgrade/downgrade the memory of a virtual server using GleSYS API 2 | 3 | Author: [Jasper Metselaar](/formmailer) 4 | 5 | This BASH-script upgrades (or downgrades) the memory of a local server based on the current amount and current usage. 6 | It reads the memory usage information from the "free" command. The script doesn't just look at the free memory numbers, 7 | but takes buffers and cache in account. 8 | 9 | When the server gets low on memory (90%) it will upgrade one step (256MB, 512MB, 1024MB or 2048MB, depending on the 10 | amount of RAM that is currently assigned). Upgrade is done using GleSYS API. 11 | If the server doesn't use the allocated memory anymore, the script will remove RAM using the API 12 | 13 | You will be notified by mail when memory has been added or removed. 14 | 15 | This script should be run as a cron-job (typically every minute) to upgrade and downgrade a server depending on 16 | the current needs. 17 | -------------------------------------------------------------------------------- /BASH/LocalMemoryUpgradeDowngrade/memmonitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | free -m > /tmp/FREE.txt 3 | TOTAL=$(grep Mem: /tmp/FREE.txt | awk '{print $2}') 4 | USED=$(grep buffers/cache /tmp/FREE.txt | awk '{print $3}') 5 | FREE=$(grep buffers/cache /tmp/FREE.txt | awk '{print $4}') 6 | PERCENTAGE=$(((USED*100)/TOTAL)) 7 | if [ $PERCENTAGE -gt 90 ]; then 8 | if [ $TOTAL -ge 16384 ]; then 9 | ADDMEM=0 10 | elif [ $TOTAL -ge 12288 ]; then 11 | ADDMEM=2048 12 | elif [ $TOTAL -ge 4096 ]; then 13 | ADDMEM=1024 14 | elif [ $TOTAL -ge 1024 ]; then 15 | ADDMEM=512 16 | else 17 | ADDMEM=256 18 | fi 19 | NEWMEM=$((TOTAL+ADDMEM)); 20 | /usr/bin/curl -X POST -d serverid=vz1234567\&memorysize=$NEWMEM -k --basic -u cl12345:[api-key] https://api.glesys.com/server/edit/ 21 | 22 | if [ $ADDMEM -eq 0 ]; then 23 | echo -e "No more memory could be added.\n" 24 | else 25 | ( echo -e "Increasing memory to $NEWMEM MB.\n" 26 | free -m) | mail -s "Server $HOSTNAME is low on memory: $PERCENTAGE% used - RAM report" user@mail.com 27 | fi 28 | 29 | fi 30 | 31 | if [ $TOTAL -ge 14336 ]; then 32 | REMMEM=2048 33 | elif [ $TOTAL -ge 5120 ]; then 34 | REMMEM=1024 35 | elif [ $TOTAL -ge 1536 ]; then 36 | REMMEM=512 37 | elif [ $TOTAL -gt 256 ]; then 38 | REMMEM=256 39 | else 40 | REMMEM=0 41 | fi 42 | 43 | if [ $FREE -gt $((REMMEM+50)) ]; then 44 | NEWMEM=$((TOTAL-REMMEM)); 45 | /usr/bin/curl -X POST -d serverid=vz1234567\&memorysize=$NEWMEM -k --basic -u cl12345:[api-key] https://api.glesys.com/server/edit/ 46 | if [ $REMMEM -eq 0 ]; then 47 | echo -e "No more memory could be removed.\n" 48 | else 49 | ( echo -e "Decreasing memory to $NEWMEM MB.\n" 50 | free -m 51 | ) | mail -s "Server $HOSTNAME has too much memory: $PERCENTAGE% used - RAM report" user@mail.com 52 | fi 53 | fi -------------------------------------------------------------------------------- /BASH/RemoteMemUpgrade/README.md: -------------------------------------------------------------------------------- 1 | #Upgrade the memory of a remote virtual server using GleSYS API 2 | 3 | Author: [Emil Andersson](/emil-nasso) 4 | 5 | This short and basic BASH-script upgrades (or downgrades) the memory of a server based on the current amount and current usage. It gets the memory usage information from the GleSYS API. It also upgrades using GleSYS API. 6 | 7 | This script could easily be run as a cron-job to upgrade and downgrade a server depending on the current needs. 8 | -------------------------------------------------------------------------------- /BASH/RemoteMemUpgrade/memupgrade.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | USER=clXXXXX 3 | APIKEY=XX 4 | SERVERID=vzXXXXXX 5 | SERVERSTATUS=`/usr/bin/curl --silent -X POST -d serverid=$SERVERID\&statustype=memory -k --basic -u $USER:$APIKEY https://api.glesys.com/server/status/` 6 | USED=`echo "$SERVERSTATUS" | grep 'usage' | sed 's/[^0-9]//g'` 7 | TOTAL=`echo "$SERVERSTATUS" |grep 'max' | sed 's/[^0-9]//g'` 8 | #echo "$USED : $TOTAL" 9 | if [ $TOTAL -eq 256 ] && [ $USED -gt 200 ]; then 10 | echo "Upgrading" 11 | /usr/bin/curl --silent -X POST -d serverid=$SERVERID\&memorysize=1024 -k --basic -u $USER:$APIKEY https://api.glesys.com/server/edit/ > /dev/null 12 | fi; 13 | 14 | if [ $TOTAL -eq 1024 ] && [ $USED -lt 150 ]; then 15 | echo "Downgrading" 16 | /usr/bin/curl --silent -X POST -d serverid=$SERVERID\&memorysize=256 -k --basic -u $USER:$APIKEY https://api.glesys.com/server/edit/ > /dev/null 17 | fi; 18 | 19 | -------------------------------------------------------------------------------- /BASH/RoundRobinLoadBalancer/README.md: -------------------------------------------------------------------------------- 1 | #Basic Round Robin load blancing with GleSYS API 2 | 3 | Author: [Emil Andersson](/emil-nasso) 4 | 5 | One of the easiest ways to loadbalance a webservice is by using [DNS Round Robin](http://en.wikipedia.org/wiki/Round-robin_DNS). In its simplest form its just two servers with their own ip addresses. The domain in use has two A-records with identical hosts but these to different ip addresses. The traffic will then be distributed between these two servers. 6 | 7 | One of the problem with this simple method is that if one of the web servers goes down, half of the users wont be able to use the service. 8 | 9 | This basic BASH-script tries to solve this problem. This script should be seen as an example for what can be done using GleSYS API. It is not intended to be used in an production environment. 10 | 11 | The script is run on both the webservers. To check if the other server is still working a page is requested and if a predetermined string is found it is regarded as up. If the string is not found on the page, the server is regarded as down. 12 | 13 | * If the other server is up, nothing happends. 14 | * If the other server is down, this server updates the DNS-records and removes the server that is not working from the records. It the continues polling the downed server. 15 | * If the server is still down, nothing happens. 16 | * If the comes up again the records is reset to it original state (one record per server). 17 | 18 | For this to work the script has to be run on both servers and the `THIS` and `THAT` variables has to be set so that the servers are referencing each other. 19 | 20 | Feel free to add to this example but think both two and three times before using it in production. :) 21 | 22 | -------------------------------------------------------------------------------- /BASH/RoundRobinLoadBalancer/balancer.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #This script uses hardcoded recordIDs for the domain records (the RECORD1 and RECORD2 variables). Look these values up using this curl command:: 3 | #/usr/bin/curl -X POST -d domain=example.com -k --basic -u clXXXXX:API-KEY https://api.glesys.com/domain/list_records 4 | THIS="10.0.0.1" 5 | THAT="10.0.0.2" 6 | URL="http://$THAT/blog/testblog" 7 | SEARCH="Some text on the site" 8 | RECORD1="XXXXX" 9 | RECORD2="YYYYY" 10 | ACCOUNT="CL12345" 11 | APIKEY="SECRET" 12 | 13 | getStatus() { /usr/bin/wget -O - $URL 2> /dev/null | grep "$SEARCH" &>/dev/null; echo "$?"; } 14 | setRecords(){ 15 |        echo "sätter records till $1 och $2"; 16 |        /usr/bin/curl -X POST -d record_id=$RECORD1\&data=$1 -k --basic -u $ACCOUNT:$APIKEY https://api.glesys.com/domain/update_record 17 |        /usr/bin/curl -X POST -d record_id=$RECORD2\&data=$2 -k --basic -u $ACCOUNT:$APIKEY https://api.glesys.com/domain/update_record 18 | } 19 | 20 | while : 21 | do 22 |        STATUS=$(getStatus) 23 |        if [ $STATUS -eq 1 ]; then 24 |                echo "The page is down!"; 25 |                setRecords "$THIS" "$THIS" 26 |                while [ $STATUS -eq 1 ]; do 27 |                        sleep 20 28 |                        STATUS=$(getStatus) 29 |                        echo "still down" 30 |                done 31 |                setRecords "$THIS" "$THAT" 32 |        fi 33 |        echo "The page is up!"; 34 |        sleep 60 35 | done 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 GleSYS Internet Services AB and contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /PHP/DNSZone/README.md: -------------------------------------------------------------------------------- 1 | ## Synopsis 2 | 3 | This project is for importing DNS zone files to your account at GleSYS using a CLI. 4 | 5 | ## Usage 6 | 7 | php php_glesys_zone_import.php 8 | 9 | ## Author 10 | 11 | The script was created by Tobias Rahm 2015-11-28 12 | -------------------------------------------------------------------------------- /PHP/DNSZone/example.com.txt: -------------------------------------------------------------------------------- 1 | $TTL 86400 ; 24 hours could have been written as 24h or 1d 2 | ; $TTL used for all RRs without explicit TTL value 3 | $ORIGIN example.com. 4 | @ 1D IN SOA ns1.example.com. hostmaster.example.com. ( 5 | 2002022401 ; serial 6 | 3H ; refresh 7 | 300 ; retry 8 | 1w ; expire 9 | 3h ; minimum 10 | ) 11 | IN NS ns1.example.com. ; in the domain 12 | IN NS ns2.smokeyjoe.com. ; external to domain 13 | IN MX 10 mail.another.com. ; external mail provider 14 | ; server host definitions 15 | ns1 IN A 192.168.0.1 ;name server definition 16 | www IN A 192.168.0.2 ;web server definition 17 | ftp IN CNAME www.example.com. ;ftp server definition 18 | ; non server domain hosts 19 | bill IN A 192.168.0.3 20 | fred IN A 192.168.0.4 -------------------------------------------------------------------------------- /PHP/InvoiceRSS/README.md: -------------------------------------------------------------------------------- 1 | #InvoiceRSS 2 | 3 | Author: Emil Andersson (emil@glesys.se) 4 | 5 | This scripts creates an valid RSS-feed that lists all invoices on your GleSYS Account by getting the list of invoices from GleSYS API. 6 | -------------------------------------------------------------------------------- /PHP/InvoiceRSS/rss.php: -------------------------------------------------------------------------------- 1 | '; 7 | ?> 8 | 9 | 10 |        GleSYS fakturor 11 |        En list över alla fakturor för konto 12 |        http://www.glesys.se/ 13 |         17 |        Mon, 19 Dec 2011 08:45:00 +0000 18 |        1800 19 | 20 | 21 |         22 |         23 |                Faktura <?=$invoice['invoicenumber']?> 24 |                 25 |                Förfaller: 26 |                Belopp: 27 |                 28 |                 29 |                 30 |                 34 |         35 |         36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /PHP/MiniControlpanel/APIClient.php: -------------------------------------------------------------------------------- 1 | setUserCredentials($username, $apikey); 22 | } 23 | 24 | public function setUserCredentials($username, $apikey) 25 | { 26 | $this->_username = $username; 27 | $this->_apikey = $apikey; 28 | } 29 | 30 | public function get($function, $argumentsarray=array()) 31 | { 32 | return $this->_make_request($function, $argumentsarray, 'get'); 33 | } 34 | 35 | public function post($function, $argumentsarray=array()) 36 | { 37 | return $this->_make_request($function, $argumentsarray, 'post'); 38 | } 39 | 40 | private function _make_request($function, $argumentsarray,$requesttype){ 41 | if($this->_username == null || $this->_apikey == null){ 42 | return false; 43 | } 44 | $ch = curl_init(); 45 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 46 | curl_setopt($ch, CURLOPT_USERPWD, $this->_username . ":" . $this->_apikey); 47 | curl_setopt($ch, CURLOPT_TIMEOUT, 20); 48 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->_verify_ssl_validity); 49 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->_verify_ssl_validity ? 2 : 0); 50 | 51 | $url=''; 52 | if($requesttype=='get'){ 53 | $query_string = ''; 54 | if(count($argumentsarray) > 0) 55 | { 56 | foreach ($argumentsarray as $key => $value) 57 | { 58 | $query_string .= "$key/" . urlencode($value) . "/"; 59 | } 60 | } 61 | $query_string.="format/" . $this->_responseformat; 62 | 63 | $url = $this->_baseurl . $function . "/" . $query_string; 64 | $this->_full_call = "GET: " . $url; 65 | } 66 | else if($requesttype=='post'){ 67 | 68 | $post = array("format=" . $this->_responseformat); 69 | foreach ($argumentsarray as $key => $value) 70 | { 71 | $post[] = urlencode($key) . "=" . urlencode($value); 72 | } 73 | $post = implode("&", $post); 74 | curl_setopt($ch, CURLOPT_POST, 1); 75 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post); 76 | 77 | $url = $this->_baseurl . $function . "/"; 78 | $this->_full_call = "POST: " . $this->_baseurl . "/" . $function . "/
DATA: $post"; 79 | } 80 | 81 | curl_setopt($ch, CURLOPT_URL, $url); 82 | $response = curl_exec($ch); 83 | if($response === FALSE) 84 | { 85 | throw new Exception(curl_error($ch)); 86 | } 87 | 88 | if($this->_responseformat == 'json') 89 | { 90 | $info = curl_getinfo($ch); 91 | $json = json_decode($response, true); 92 | if(!is_array($json)) 93 | throw new Exception($response); 94 | $response = $json; 95 | $response = $response['response']; 96 | $this->_last_response = $response; 97 | if($info['http_code'] == 401) 98 | { 99 | throw new Exception($response['status']['text'], $info['http_code']); 100 | } 101 | if($response['status']['code'] != 200) 102 | { 103 | throw new Exception($response['status']['text'], $response['status']['code']); 104 | } 105 | } 106 | curl_close($ch); 107 | return $response; 108 | } 109 | 110 | public function getLastCall(){ 111 | return $this->_full_call; 112 | } 113 | 114 | public function getLastResponse(){ 115 | return $this->_last_response; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /PHP/MiniControlpanel/README.md: -------------------------------------------------------------------------------- 1 | #Mini-controlpanel 2 | This example code contains three files: 3 | 4 | ##APIClient.php 5 | 6 | Authors: [Magnus Johansson](/dragontoe), [Emil Andersson](/emil-nasso) 7 | 8 | Contains functions for calling functions in the API using HTTP get or post. This relies heavily on the PHP module cURL so make sure that module is installed on your server. 9 | 10 | ##full_example.php 11 | 12 | Author: Andreas Jönsson 13 | 14 | An example script that allows you to make changes on a predetermined server. This makes it easy to reboot or upgrade a server for example, from a mobile web browser or from an external script. All you need is to do visit the URL of the script and fill out the password (which is defined in the script) and click on the action that you want to perform. You can also supply the action and password in the URL by appending get-variables. The implemented functions are: 15 | 16 | * **serverlow** - Change amount of memory/cpu allocated to the server to handle low traffic. 17 | * **serverpeak** - Change amount of memory/cpu allocated to the server to handle high (peak) traffic. 18 | * **reboot** - Restart the server 19 | * **details** - Get details about the server such as current hardware configuration, ip addresses and more. 20 | * **status** - Get status information about the server such as state (running, stopped etc), cpu usage, memory usage and more. 21 | * **memchange** - Check how much memory is used on the server and downgrade/upgrade the server as needed, automatically. 22 | * **console** - Get all the information you need to connect to the server using VNC. 23 | 24 | ## mini_example.php 25 | 26 | Author: Andreas Jönsson 27 | 28 | A smaller version of full_example.php containing only the reboot-function. 29 | -------------------------------------------------------------------------------- /PHP/MiniControlpanel/full_example.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Small server control panel 6 | 7 | 8 | "CL12345", // Your username used to log on to http://customer.glesys.com 11 | "local password" => "LOSENORD", // A local password, used only for this script. 12 | "serverid" => "vzXXXXXX", // The ID of the server to be controlled. starts with vz or xm. Can be found when you 13 | // edit an server at http://customer.glesys.com 14 | "API-key" => "abc123abc123", // Your API-key. Can be generated at http://customer.glesys.com 15 | "peak" => array( 16 | "memory" => 4096, // Amount of memory assigned with the peak()-function. 17 | "cores" => 4 // Amount of CPU cores assigned with the peak()-function. 18 | ), 19 | "low" => array( 20 | "memory" => 1024, // Amount of memory assigned with the low()-function. 21 | "cores" => 1 // Amount of CPU cores assigned with the low()-function. 22 | ), 23 | "changevals" => array( // Configs for the memchange()-function 24 | "lower" => 33, // If less than this percentage of the memory is used, the memory will be downgraded 25 | "higher" => 67 // If the server uses more than "higher"% of the memory, the memory will be upgraded. 26 | ) 27 | ); 28 | include 'APIClient.php'; 29 | try{ 30 | $client = new APIClient($config["username"], $config["API-key"]); 31 | } catch(Exception $e){ 32 | echo "Connection error: ".$e->getMessage(); 33 | return; 34 | } 35 | if(isset($_GET["pass"]) and isset($_GET["cmd"])) 36 | { 37 | if($_GET["pass"] == $config["local password"]) 38 | { 39 | if($_GET["cmd"] == "low" or $_GET["cmd"] == "serverlow") 40 | serverlow(); 41 | elseif($_GET["cmd"] == "peak" or $_GET["cmd"] == "serverpeak") 42 | serverpeak(); 43 | elseif($_GET["cmd"] == "reboot") 44 | reboot(); 45 | elseif($_GET["cmd"] == "details" or $_GET["cmd"] == "detail") 46 | details(); 47 | elseif($_GET["cmd"] == "status") 48 | status(); 49 | elseif($_GET["cmd"] == "memchange"or $_GET["cmd"] == "changemem") 50 | memchange(); 51 | elseif($_GET["cmd"] == "console") 52 | console(); 53 | else 54 | echo"Unknown command."; 55 | } 56 | else 57 | echo "Wrong password"; 58 | } 59 | else 60 | { 61 | ?> 62 |
63 | Password
64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 |
72 | post("server/edit", array("serverid" => $config["serverid"], "memorysize" => $config["low"]["memory"], "cpucores" => $config["low"]["cores"])); 83 | } catch(Exception $e){ 84 | echo "Serverlow error: ".$e->getMessage(); 85 | return; 86 | } 87 | echo "Memory set to ".$config["low"]["memory"]."GB.
\nCPU-cores are now ".$config["low"]["cores"] ."."; 88 | } 89 | // Upgrades the memory and increases the amount of CPU cores. 90 | // Used when high traffic towards the server is expected. 91 | // Amount of memory and CPU cores are edited in the $config. 92 | function serverpeak() 93 | { 94 | global $client; 95 | global $config; 96 | try{ 97 | $client->post("server/edit", array("serverid" => $config["serverid"], "memorysize" => $config["peak"]["memory"], "cpucores" => $config["peak"]["cores"])); 98 | } catch(Exception $e){ 99 | echo "Serverpeak error: ".$e->getMessage(); 100 | return; 101 | } 102 | echo "Memory set to ".$config["peak"]["memory"]."GB.
\nCPU-cores are now ".$config["peak"]["cores"] ."."; 103 | } 104 | // Reboots the server. Uses "stop" with the "type"="reboot" 105 | function reboot() 106 | { 107 | global $client; 108 | global $config; 109 | try{ 110 | $client->post("server/stop", array("serverid" => $config["serverid"], "type" => "reboot")); 111 | } catch(Exception $e){ 112 | echo "Connection error: ".$e->getMessage(); 113 | return; 114 | } 115 | echo"The server was restarted succesfully."; 116 | } 117 | //Get information about the server. This lists information such as configuration (amount of cpu,memory and disk), ip adresses and more. 118 | function details() 119 | { 120 | global $client; 121 | global $config; 122 | try{ 123 | $details = $client->post("server/details", array("serverid" => $config["serverid"])); 124 | } catch(Exception $e){ 125 | echo "Details error: ".$e->getMessage(); 126 | return; 127 | } 128 | echo ""; 129 | foreach($details["server"] as $key => $values) 130 | { 131 | if($key == "disksize" or $key == "transfer") 132 | $values .= " GB"; 133 | if($key == "memorysize") 134 | $values .= " MB"; 135 | if($key == "cost") 136 | echo ""; 137 | elseif($key == "iplist") 138 | { 139 | echo ""; 143 | } 144 | else 145 | echo ""; 146 | } 147 | echo "
cost".$values["amount"]." ".$values["currency"]."/".$values["timeperiod"]."
iplist"; 140 | foreach($values as $newVal) 141 | echo"(IPv".$newVal["version"].") ".$newVal["ipaddress"]."
"; 142 | echo "
".$key."".$values."
"; 148 | } 149 | //Get status-information about the server. This information includes status (if the server is running or not),cpu usage, memory usage, uptime and more. 150 | function status() 151 | { 152 | global $client; 153 | global $config; 154 | try{ 155 | $status = $client->post("server/status", array("serverid" => $config["serverid"])); 156 | } catch(Exception $e){ 157 | echo "Status error: ".$e->getMessage(); 158 | return; 159 | } 160 | echo ""; 161 | foreach($status["server"] as $key => $values) 162 | { 163 | if($key == "cpu") 164 | echo ""; 165 | elseif($key == "memory") 166 | echo ""; 167 | elseif($key == "disk") 168 | echo ""; 169 | elseif($key == "transfer") 170 | echo ""; 171 | elseif($key == "uptime") 172 | { 173 | echo ""; 176 | } 177 | } 178 | } 179 | //Automaticall upgrade or downgrade the memory of the server based on how much memory the server is currently using. 180 | //Memory usage is only available via the api for OpenVZ-servers. To upgrade/downgrade XEN-servers you have to 181 | //supply the amount of used memory in the usedmem get-variable. 182 | function memchange() 183 | { 184 | global $client; 185 | global $config; 186 | try{ 187 | $freemem = $client->post("server/status", array("serverid" => $config["serverid"])); 188 | } catch(Exception $e){ 189 | echo "Memchange error: ".$e->getMessage(); 190 | return; 191 | } 192 | $allowed_options = array(128, 256, 512, 768, 1024, 1536, 2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288); 193 | $size = $freemem["server"]["memory"]["max"]; 194 | if(isset($_GET["usedmem"])) 195 | if(is_numeric($_GET["usedmem"])) 196 | $freemem = $size - $_GET["usedmem"]; 197 | else 198 | { 199 | echo"\"usedmem\" is an invalid value. Must be a number."; 200 | die; 201 | } 202 | else 203 | if(is_numeric($freemem["server"]["memory"]["usage"])) 204 | $freemem = $size-$freemem["server"]["memory"]["usage"]; 205 | else 206 | { 207 | echo"Needs the \"usedmem\" argument."; 208 | die; 209 | } 210 | $i = 0; 211 | while($allowed_options[$i] != $size) 212 | { 213 | $i++; 214 | } 215 | 216 | if($freemem > $size*(1-($config["changevals"]["lower"]/100)) and $i > 0) 217 | { 218 | $client->post("server/edit", array("serverid" => $config["serverid"], "memorysize" => $allowed_options[$i-1])); 219 | echo"Memory degraded to ".$allowed_options[$i-1]." MB since less than ".$config["changevals"]["lower"]." percent of the memory was used."; 220 | } 221 | elseif($freemem < $size*(1-($config["changevals"]["higher"]/100)) and $i < 18) 222 | { 223 | $client->post("server/edit", array("serverid" => $config["serverid"], "memorysize" => $allowed_options[$i+1])); 224 | echo"Memory upgraded to ".$allowed_options[$i+1]." MB since more than ".$config["changevals"]["higher"]." percent of the memory was used."; 225 | } 226 | else 227 | echo "Memory seems to \"fit\""; 228 | } 229 | //Get information about how to connect to this server using VNC. 230 | function console() 231 | { 232 | global $client; 233 | global $config; 234 | try{ 235 | $console = $client->post("server/console", array("serverid" => $config["serverid"])); 236 | } catch(Exception $e){ 237 | echo "Console error: ".$e->getMessage(); 238 | return; 239 | } 240 | echo"Remote access information:
IP: ".$console["remote"]["host"]."
Port: ".$console["remote"]["port"]."
Password: ".$console["remote"]["password"]; 241 | } 242 | ?> 243 | 244 | 245 | 246 | -------------------------------------------------------------------------------- /PHP/MiniControlpanel/mini_example.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mini control panel 6 | 7 | 8 | "CL12345", // Your username used to log on to http://customer.glesys.com 11 | "local password" => "LOSENORD", // A local password, used only for this script. 12 | "serverid" => "vzXXXXXX", // The ID of the server to be controlled. starts with vz or xm. 13 | // Can be found when you edit an server at http://customer.glesys.com 14 | "API-key" => "abc123abc123" // Your API-key. Can be generated at http://customer.glesys.com 15 | ); 16 | include 'APIClient.php'; 17 | try{ 18 | $client = new APIClient($config["username"], $config["API-key"]); 19 | } catch(Exception $e){ 20 | echo "Connection error: ".$e->getMessage(); 21 | return; 22 | } 23 | if(isset($_GET["pass"]) and isset($_GET["cmd"])) 24 | { 25 | if($_GET["pass"] == $config["local password"]) 26 | { 27 | if($_GET["cmd"] == "reboot") 28 | reboot(); 29 | else 30 | echo"Unknown command."; 31 | } 32 | else 33 | echo "Wrong password"; 34 | } 35 | else 36 | { 37 | ?> 38 | 39 | Password
40 | 41 | 42 | post("server/stop", array("serverid" => $config["serverid"], "type" => "reboot")); 51 | } catch(Exception $e){ 52 | echo "Connection error: ".$e->getMessage(); 53 | return; 54 | } 55 | echo"The server was restarted succesfully."; 56 | } 57 | ?> 58 | 59 | -------------------------------------------------------------------------------- /PHP/api_classes/README.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright (c) 2013 Jari (tumba25) Kanerva http://www.tumba25.com 3 | * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License v3 4 | */ 5 | 6 | glesys_api.php is the main class that does the actual request. All other files includes glesys_api.php 7 | and tries to find it in the same directory where the including class file is. If they aren't in the same 8 | directory you need to change the path in the class files you use. 9 | 10 | glesys_api.php also includes idna_convert.php to punycode internationalized domain names. 11 | 12 | All functions return boolean true on success and false otherwise. 13 | By calling $glesys_api->fetch_response() after the request you'll get a array with request status, 14 | eventual requested info and debug info containing the POST data sent with the request if any. 15 | This is what $glesys_api->fetch_response() returns on failure. 16 | array( 17 | 'code' => (int) response code 18 | 'text' => (string) response/error text 19 | 'debug' => array( 20 | 'input' => array( 21 | The POST data sent to the API 22 | ) 23 | ) 24 | ); 25 | 26 | What it returns on successful depends on the called function and the parameters given. There is a .txt file 27 | in the docs folder for each class where you can see the parameters for each function. 28 | 29 | You can also use $glesys_api->encode() and $glesys_api->decode() to convert domain names to and from punycode. 30 | The methods in these classes calls $glesys_api->encode() so you don't need to do that before calling them. 31 | -------------------------------------------------------------------------------- /PHP/api_classes/docs/glesys_domain.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright (c) 2013 Jari (tumba25) Kanerva http://www.tumba25.com 3 | * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License v3 4 | */ 5 | 6 | All functions return true on success and false on failure, 7 | On failure $glesys_api->fetch_response() returns 8 | array( 9 | 'code' => (int) response code 10 | 'text' => (string) response text 11 | 'debug' => array( 12 | 'input' => array( 13 | The POST data sent to the API 14 | ) 15 | ) 16 | ); 17 | 18 | On success you need to call $glesys_api->fetch_response() to get a array with the returned data. 19 | 20 | Function $glesys_api->domain_list() 21 | Description: Get a list of all domains on this account. The glesysnameserver-item in the returned data shows if this domain actually uses glesys nameservers or not. It looks in the domains NS-records for .namesystem.se 22 | Param: none 23 | 24 | Function $glesys_api->domain_add() 25 | Description: Add a domain to our dns-system. Some default records will be created on the domain. If the optional argument create_records is set to 0, only NS and SOA records will be created by default. 26 | param required string $domainname. 27 | param optional, array( 28 | 'primarynameserver' => (string) optional 29 | 'responsibleperson' => (string) optional 30 | 'ttl' => (int) optional 31 | 'refresh => (int) optional 32 | 'retry' => (int) optional 33 | 'expire' => (int) optional 34 | 'minimum' => (int) optional 35 | 'createrecords' => (int) optional 36 | ) 37 | 38 | Function $glesys_api->domain_register() 39 | Description: Register a domain. The domain has to be added to the account first by calling domain/add. The optional argument numyears decides how many years the domain in registered for. It defaults to the lowest number of years allowed for the tld. 40 | The domain name will be punycoded if it has international characters in it. 41 | Param array( 42 | 'domainname' => (string) required 43 | 'email' => (string) required 44 | 'firstname' => (string) required 45 | 'lastname' => (string) required 46 | 'organization' => (string) required 47 | 'organizationnumber' => (string) required 48 | 'address' => (string) required 49 | 'city' => (string) required 50 | 'zipcode' => (string) required 51 | 'country' => (string) required 52 | 'phonenumber' => (string) required 53 | 54 | 'fax' => (string) optional 55 | 'numyears' => (string) optional 56 | ) 57 | 58 | Function $glesys_api->domain_transfer() 59 | Description: Transfer a domain to glesys. The domain has to be added to the account first by calling domain/add. The optional argument numyears decides how many years the domain in registered for. It defaults to the lowest number of years allowed for the tld. 60 | The domain name will be punycoded if it has international characters in it. 61 | Param array( 62 | 'domainname' => (string) required 63 | 'authcode' => (string) required 64 | 'email' => (string) required 65 | 'firstname' => (string) required 66 | 'lastname' => (string) required 67 | 'organization' => (string) required 68 | 'organizationnumber' => (string) required 69 | 'address' => (string) required 70 | 'city' => (string) required 71 | 'zipcode' => (string) required 72 | 'country' => (string) required 73 | 'phonenumber' => (string) required 74 | 75 | 'fax' => (string) optional 76 | 'numyears' => (string) optional 77 | ) 78 | 79 | Function $glesys_api->domain_renew() 80 | Description: Renew a domain. The domain has to be added to the account first by calling domain/add. 81 | The domain name will be punycoded if it has international characters in it. 82 | Param string domainname required 83 | Param int numyears required 84 | 85 | Function $glesys_api->domain_autorenew() 86 | Description: Activate/deactivate autorenewal for a domain. 87 | The domain name will be punycoded if it has international characters in it. 88 | Param string domainname required 89 | Param int autorenew required (0 or 1) 90 | 91 | Function $glesys_api->domain_details() 92 | Description: Gets detailed information about this domain. This is basically the information available in the domains SOA-record. 93 | The domain name will be punycoded if it has international characters in it. 94 | Param string domainname required 95 | 96 | Function $glesys_api->domain_available() 97 | Description: Checks if the domain is available for registration. You can either set search to the domain you are interested in or leave out the tld and search for all tlds that we offer for registration. Example: example.com or example. 98 | The domain name will be punycoded if it has international characters in it. 99 | Param string domainname required 100 | 101 | Function $glesys_api->domain_pricelist() 102 | Description: Gets a full domain pricelist with all available TLDs 103 | Param: none 104 | 105 | Function $glesys_api->domain_edit() 106 | Description: edit soa for a domain in our dns-system 107 | Param: required string domainname 108 | Param: optional array( 109 | 'primarynameserver' => (string) optional 110 | 'responsibleperson' => (string) optional 111 | 'ttl' => (int) optional 112 | 'refresh' => (int) optional 113 | 'retry' => (int) optional 114 | 'expire' => (int) optional 115 | 'minimum' => (int) optional 116 | ) 117 | 118 | Function $glesys_api->domain_delete() 119 | Description: Delete a domain from the dns system. 120 | Param: required string domainname 121 | 122 | Function $glesys_api->domain_listrecords() 123 | Description: List records for a given domain. This information includes the recordid. 124 | Param: required string domainname 125 | 126 | Function $glesys_api->domain_updaterecord() 127 | Param: required int recordid (you can fetch this with $glesys_api->domain_listrecords()) 128 | Param: optional array( 129 | 'host' => (string) optional 130 | 'type' => (string) optional 131 | 'data' => (string) optional 132 | 'ttl' => (int) optional 133 | ) 134 | 135 | Function $glesys_api->domain_addrecord() 136 | Description: Adds a dns record to a domain 137 | Param array( 138 | 'domainname' => (string) required 139 | 'host' => (string) required 140 | 'type' => (string) required 141 | 'data' => (string) required 142 | 143 | 'ttl' => (int) optional 144 | ) 145 | 146 | Function $glesys_api->domain_deleterecord() 147 | Description: Removes a dns record from a domain. 148 | Param: required int recordid (you can fetch this with $glesys_api->domain_listrecords()) 149 | 150 | Function $glesys_api->domain_allowedarguments() 151 | Description: Lists the allowed arguments for some of the functions in this module such as register. Some tlds require that the registering part has connections to the country. 152 | Param: none 153 | 154 | Function $glesys_api->domain_changenameservers() 155 | Description: Change nameservers for a domain. Check the registrarinfo field in $glesys_api->domain_details() to know if this can be done for a domain. 156 | Param array( 157 | 'domainname' => (string) required 158 | 'ns1' => (string) required 159 | 'ns2' => (string) required 160 | 161 | 'ns3' => (string) optional 162 | 'ns4' => (string) optional 163 | ) 164 | -------------------------------------------------------------------------------- /PHP/api_classes/docs/glesys_email.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright (c) 2013 Jari (tumba25) Kanerva http://www.tumba25.com 3 | * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License v3 4 | */ 5 | 6 | All functions return true on success and false on failure, 7 | On failure $glesys_api->fetch_response() returns 8 | array( 9 | 'code' => (int) response code 10 | 'text' => (string) response text 11 | 'debug' => array( 12 | 'input' => array( 13 | The POST data sent to the API 14 | ) 15 | ) 16 | ); 17 | 18 | On success you need to call $glesys_api->fetch_response() to get a array with the returned data. 19 | 20 | Function $glesys_api->email_overview() 21 | Description: Returns a overview of all domains and count of emailaccounts and alias. 22 | Param: none 23 | 24 | Function $glesys_api->email_globalquota(global quota) 25 | Description: Enables the user to set and get the global quota. The global quota is the total amount of space that is allowed to be allocated to email accounts. The globalquota argument should be in MB. 26 | Param: optional int new global quota to set in MB. Min is 10240 and it must be divisible by 1024. 27 | 28 | Function $glesys_api->email_list($domainname, $filter = '') 29 | Description: Gets a list of all accounts and aliases of a domain with full details. It is also possible to filter the results by setting the optional filter parameter to an existing alias or account. 30 | Param: required domain name 31 | Param: optional filter Example: user@example.com. Must be a valid email address. 32 | 33 | Function $glesys_api->email_editaccount($emailaccount, $data = array()) 34 | Description: Edit an email account and change things like quota, password, autoresponse and antispam level. Allowed values for antispam is 0-5. Quota is in MB. 35 | Param string $emailaccount required. 36 | Param array $args, all array parts are optional array( 37 | 'antispamlevel' => 0 - 5 38 | 'antivirus' => 0|1 39 | 'password' => new password 40 | 'autorespond' => 0|1 41 | 'autorespondsaveemail' => 0|1 42 | 'autorespondmessage' => string with message 43 | 'quota' => new quota in MB 44 | ) 45 | 46 | Function $glesys_api->email_delete($email) 47 | Description: Delete an email-account or alias. 48 | Param string $email required. 49 | 50 | Function $glesys_api->email_createaccount($emailaccount, $password, $data = array()) 51 | Description: Create an email account. Allowed values for antispam is 0-5. 52 | Param string $emailaccount required. 53 | Param string $password required. 54 | Param array $args, all array parts are optional array( 55 | 'antispamlevel' => 0 - 5 56 | 'antivirus' => 0|1 57 | 'autorespond' => 0|1 58 | 'autorespondsaveemail' => 0|1 59 | 'autorespondmessage' => string with message 60 | 'quota' => new quota in MB 61 | ) 62 | 63 | Function $glesys_api->email_quota($emailaccount) 64 | Description: Gets quota information about an account. How much is being used and how much is available. 65 | Param string $emailaccount required. 66 | 67 | Function $glesys_api->email_createalias($emailalias, $goto) 68 | Description: Create an email alias. 69 | Param string $emailaccount required. 70 | Param string $goto required. 71 | 72 | Function $glesys_api->email_editalias($emailalias, $goto) 73 | Description: Edit an email alias. 74 | Param string $emailaccount required. 75 | Param string $goto required. 76 | 77 | Function $glesys_api->email_costs() 78 | Description: Get email related costs and pricelists. 79 | Param: none 80 | -------------------------------------------------------------------------------- /PHP/api_classes/glesys_api.php: -------------------------------------------------------------------------------- 1 | http://www.tumba25.com 4 | * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License v3 5 | */ 6 | 7 | 8 | class glesys_api 9 | { 10 | private $api_user = ''; 11 | private $api_key = ''; 12 | private $api_url = 'https://api.glesys.com/'; 13 | 14 | protected $response = false; 15 | protected $punycode = false; 16 | 17 | public function __construct($api_user, $api_key, $api_url = false) 18 | { 19 | if ($api_user) 20 | { 21 | $this->api_user = $api_user; 22 | } 23 | 24 | if ($api_key) 25 | { 26 | $this->api_key = $api_key; 27 | } 28 | 29 | if ($api_url) 30 | { 31 | $this->api_url = $api_url; 32 | } 33 | 34 | // Make sure the API URL ends with a slash. 35 | if (substr($this->api_url, -1) != '/') 36 | { 37 | $this->api_url .= '/'; 38 | } 39 | } 40 | 41 | /** 42 | * Makes the actual request. 43 | * 44 | * @param string, $request ex: 'email/overview'. 45 | * @param array $args or bool false if no arguments are to be passed. 46 | * @param bool $use_post: true to use POST or false to use GET. 47 | * @return true on success or false on error. 48 | */ 49 | protected function api_request($request, $args = array()) 50 | { 51 | $url = $this->api_url . $request . '/format/json'; 52 | 53 | $ch = curl_init(); 54 | curl_setopt_array($ch, array( 55 | CURLOPT_POST => true, 56 | CURLOPT_POSTFIELDS => http_build_query($args), 57 | CURLOPT_RETURNTRANSFER => true, 58 | CURLOPT_SSL_VERIFYPEER => false, 59 | CURLOPT_SSL_VERIFYHOST => 0, 60 | CURLOPT_TIMEOUT => 30, 61 | CURLOPT_URL => $url, 62 | CURLOPT_USERPWD => $this->api_user . ':' . $this->api_key, 63 | 64 | CURLOPT_CUSTOMREQUEST => 'POST', 65 | CURLOPT_SSH_AUTH_TYPES => CURLSSH_AUTH_ANY, 66 | )); 67 | 68 | $response = curl_exec($ch); 69 | 70 | if (empty($response)) 71 | { 72 | return(false); 73 | } 74 | 75 | $this->response = json_decode($response, true); 76 | $this->response = $this->response['response']; 77 | 78 | // Just make sure the return code is 200. 79 | if ($this->response['status']['code'] != 200) 80 | { 81 | $this->response = array( 82 | 'code' => $this->response['status']['code'], 83 | 'text' => $this->response['status']['text'], 84 | 'debug' => $this->response['debug'] 85 | ); 86 | 87 | return(false); 88 | } 89 | 90 | // If we get here everything should be fine. 91 | return(true); 92 | } 93 | 94 | public function fetch_response() 95 | { 96 | return($this->response); 97 | } 98 | 99 | /** 100 | * punycode domain names 101 | */ 102 | public function punycode_endoce($string) 103 | { 104 | if (empty($this->punycode)) 105 | { 106 | $phpEx = substr(strrchr(__FILE__, '.'), 1); 107 | $path = dirname(__FILE__); 108 | require("$path/idna_convert.$phpEx"); 109 | $this->punycode = new idna_convert(); 110 | } 111 | 112 | return($this->punycode->encode($string)); 113 | } 114 | 115 | /** 116 | * punydecode domain names 117 | */ 118 | public function punycode_dedoce($string) 119 | { 120 | if (empty($this->punycode)) 121 | { 122 | $phpEx = substr(strrchr(__FILE__, '.'), 1); 123 | $path = dirname(__FILE__); 124 | require("$path/idna_convert.$phpEx"); 125 | $this->punycode = new idna_convert(); 126 | } 127 | 128 | return($this->punycode->decode($string)); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /PHP/api_classes/glesys_domain.php: -------------------------------------------------------------------------------- 1 | http://www.tumba25.com 4 | * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License v3 5 | */ 6 | 7 | if (!class_exists('glesys_api')) 8 | { 9 | $phpEx = substr(strrchr(__FILE__, '.'), 1); 10 | $path = dirname(__FILE__); 11 | require("$path/glesys_api.$phpEx"); 12 | } 13 | 14 | class glesys_domain extends glesys_api 15 | { 16 | /** 17 | * Get a list of all domains on this account. 18 | * The glesysnameserver-item in the returned data shows if this domain actually uses glesys nameservers or not. 19 | * It looks in the domains NS-records for .namesystem.se 20 | * 21 | * @param void 22 | * @return true on success or false on failure. 23 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 24 | */ 25 | public function domain_list() 26 | { 27 | $success = $this->api_request('domain/list'); 28 | return($success); 29 | } 30 | 31 | /** 32 | * Add a domain to our dns-system. 33 | * Some default records will be created on the domain. 34 | * If the optional argument create_records is set to 0, only NS and SOA records will be created by default. 35 | * 36 | * @param required string $domainname. 37 | * @param optional array $args, all array parts are also optional array( 38 | * 'primarynameserver' => (string) default = 'ns1.namesystem.se.' 39 | * 'responsibleperson' => (string) default = 'registry.glesys.se.' 40 | * 'ttl' => (int) seconds, default = 3600 41 | * 'refresh' => (int) seconds, default = 10800 42 | * 'retry' => (int) seconds, default = 2700 43 | * 'expire' => (int) seconds. default = 1814400 44 | * 'minimum' => (int) seconds, default = 10800 45 | * 'createrecords' => (int) 0|1, default = 1 46 | * ) 47 | * @return true on success or false on failure. 48 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 49 | */ 50 | public function domain_add($domainname, $data = array()) 51 | { 52 | $args = array( 53 | 'domainname' => $this->punycode_endoce($domainname), 54 | ); 55 | 56 | if (!empty($data)) 57 | { 58 | $args = array_merge($args, $data); 59 | } 60 | 61 | $success = $this->api_request('domain/add', $args); 62 | return($success); 63 | } 64 | 65 | /** 66 | * Register a domain. 67 | * The domain has to be added to the account first by calling domain/add. 68 | * The optional argument numyears decides how many years the domain in registered for. 69 | * It defaults to the lowest number of years allowed for the tld. 70 | * 71 | * @param array $domain_data, array( 72 | * 'domainname' => (string) required 73 | * 'email' => (string) required 74 | * 'firstname' => (string) required 75 | * 'lastname' => (string) required 76 | * 'organization' => (string) required 77 | * 'organizationnumber' => (string) required 78 | * 'address' => (string) required 79 | * 'city' => (string) required 80 | * 'zipcode' => (string) required 81 | * 'country' => (string) required 82 | * 'phonenumber' => (string) required 83 | * 84 | * 'fax' => (string) optional 85 | * 'numyears' => (string) optional 86 | * ) 87 | * @return true on success or false on failure. 88 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 89 | */ 90 | public function domain_register($domain_data) 91 | { 92 | $domain_data['domainname'] = $this->punycode_endoce($domain_data['domainname']); 93 | 94 | $success = $this->api_request('domain/register', $domain_data); 95 | return($success); 96 | } 97 | 98 | /** 99 | * Transfer a domain to GleSYS 100 | * 101 | * @param array $domain_data, array( 102 | * 'domainname' => (string) required 103 | * 'email' => (string) required 104 | * 'firstname' => (string) required 105 | * 'lastname' => (string) required 106 | * 'organization' => (string) required 107 | * 'organizationnumber' => (string) required 108 | * 'address' => (string) required 109 | * 'city' => (string) required 110 | * 'zipcode' => (string) required 111 | * 'country' => (string) required 112 | * 'phonenumber' => (string) required 113 | * 114 | * 'fax' => (string) optional 115 | * 'numyears' => (string) optional 116 | * ) 117 | * @return true on success or false on failure. 118 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 119 | */ 120 | public function domain_transfer($domain_data) 121 | { 122 | $domain_data['domainname'] = $this->punycode_endoce($domain_data['domainname']); 123 | 124 | $success = $this->api_request('domain/transfer', $domain_data); 125 | return($success); 126 | } 127 | 128 | /** 129 | * Renew a domain 130 | * 131 | * @param string $domainname required 132 | * @param int $numyears required 133 | * @return true on success or false on failure. 134 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 135 | */ 136 | public function domain_renew($domainname, $numyears) 137 | { 138 | $args = array( 139 | 'domainname' => $this->punycode_endoce($domainname), 140 | 'numyears' => $numyears, 141 | ); 142 | 143 | $success = $this->api_request('domain/renew', $args); 144 | return($success); 145 | } 146 | 147 | /** 148 | * Activate/deactivate autorenewal for a domain. 149 | * 150 | * @param string $domainname required 151 | * @param int $autorenew required (0 or 1) 152 | * @return true on success or false on failure. 153 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 154 | */ 155 | public function domain_autorenew($domainname, $autorenew) 156 | { 157 | $args = array( 158 | 'domainname' => $this->punycode_endoce($domainname), 159 | 'autorenew' => $autorenew, 160 | ); 161 | 162 | $success = $this->api_request('domain/autorenew', $args); 163 | return($success); 164 | } 165 | 166 | /** 167 | * Gets detailed information about this domain. This is basically the information available in the domains SOA-record. 168 | * 169 | * @param string $domainname required 170 | * @return true on success or false on failure. 171 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 172 | */ 173 | public function domain_details($domainname) 174 | { 175 | $args = array( 176 | 'domainname' => $this->punycode_endoce($domainname), 177 | ); 178 | 179 | $success = $this->api_request('domain/details', $args); 180 | return($success); 181 | } 182 | 183 | /** 184 | * Checks if the domain is available for registration. 185 | * 186 | * @param string $domainname required 187 | * @return true on success or false on failure. 188 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 189 | */ 190 | public function domain_available($domainname) 191 | { 192 | $args = array( 193 | 'search' => $this->punycode_endoce($domainname), 194 | ); 195 | 196 | $success = $this->api_request('domain/available', $args); 197 | return($success); 198 | } 199 | 200 | /** 201 | * Gets a full domain pricelist with all available TLDs 202 | * 203 | * @param void 204 | * @return true on success or false on failure. 205 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 206 | */ 207 | public function domain_pricelist() 208 | { 209 | $success = $this->api_request('domain/pricelist'); 210 | return($success); 211 | } 212 | 213 | /** 214 | * Add a domain to our dns-system. 215 | * Some default records will be created on the domain. 216 | * If the optional argument create_records is set to 0, only NS and SOA records will be created by default. 217 | * 218 | * @param required string $domainname. 219 | * @param optional array $args, all array parts are also optional array( 220 | * 'primarynameserver' => (string) default = 'ns1.namesystem.se.' 221 | * 'responsibleperson' => (string) default = 'registry.glesys.se.' 222 | * 'ttl' => (int) seconds, default = 3600 223 | * 'refresh' => (int) seconds, default = 10800 224 | * 'retry' => (int) seconds, default = 2700 225 | * 'expire' => (int) seconds. default = 1814400 226 | * 'minimum' => (int) seconds, default = 10800 227 | * ) 228 | * @return true on success or false on failure. 229 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 230 | */ 231 | public function domain_edit($domainname, $data = array()) 232 | { 233 | $args = array( 234 | 'domainname' => $this->punycode_endoce($domainname), 235 | ); 236 | 237 | if (!empty($data)) 238 | { 239 | $args = array_merge($args, $data); 240 | } 241 | 242 | $success = $this->api_request('domain/edit', $args); 243 | return($success); 244 | } 245 | 246 | /** 247 | * Delete a domain from the dns system. 248 | * 249 | * @param string $domainname required 250 | * @return true on success or false on failure. 251 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 252 | */ 253 | public function domain_delete($domainname) 254 | { 255 | $args = array( 256 | 'domainname' => $this->punycode_endoce($domainname), 257 | ); 258 | 259 | $success = $this->api_request('domain/delete', $args); 260 | return($success); 261 | } 262 | 263 | /** 264 | * List records for a given domain. 265 | * This information includes the recordid. 266 | * 267 | * @param string $domainname required 268 | * @return true on success or false on failure. 269 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 270 | */ 271 | public function domain_listrecords($domainname) 272 | { 273 | $args = array( 274 | 'domainname' => $this->punycode_endoce($domainname), 275 | ); 276 | 277 | $success = $this->api_request('domain/listrecords', $args); 278 | return($success); 279 | } 280 | 281 | /** 282 | * Update a records dns information. 283 | * You can get the record id using domain_listrecords(). 284 | * 285 | * @param required string $recordid. 286 | * @param optional array( 287 | * 'ttl' => (int) optional 288 | * 'host' => (string) optional 289 | * 'type' => (string) optional 290 | * 'data' => (string) optional 291 | * ) 292 | * @return true on success or false on failure. 293 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 294 | */ 295 | public function domain_updaterecord($recordid, $data = array()) 296 | { 297 | $args = array( 298 | 'recordid' => $recordid, 299 | ); 300 | 301 | if (!empty($data)) 302 | { 303 | $args = array_merge($args, $data); 304 | } 305 | 306 | $success = $this->api_request('domain/updaterecord', $args); 307 | return($success); 308 | } 309 | 310 | /** 311 | * Adds a dns record to a domain. 312 | * 313 | * @param array( 314 | * 'domainname' => (string) required 315 | * 'host' => (string) required 316 | * 'type' => (string) required 317 | * 'data' => (string) required 318 | * 319 | * 'ttl' => (int) optional 320 | * ) 321 | * @return true on success or false on failure. 322 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 323 | */ 324 | public function domain_addrecord($data) 325 | { 326 | $data['domainname'] = $this->punycode_endoce($data['domainname']); 327 | 328 | $success = $this->api_request('domain/addrecord', $data); 329 | return($success); 330 | } 331 | 332 | /** 333 | * Removes a dns record from a domain. 334 | * You can get the record id using domain_listrecords(). 335 | * 336 | * @param int $recordid required 337 | * @return true on success or false on failure. 338 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 339 | */ 340 | public function domain_deleterecord($recordid) 341 | { 342 | $args = array( 343 | 'recordid' => $recordid, 344 | ); 345 | 346 | $success = $this->api_request('domain/deleterecord', $args); 347 | return($success); 348 | } 349 | 350 | /** 351 | * Lists the allowed arguments for some of the functions in this module such as register. 352 | * Some tlds require that the registering part has connections to the country. 353 | * 354 | * @param void 355 | * @return true on success or false on failure. 356 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 357 | */ 358 | public function domain_allowedarguments() 359 | { 360 | $success = $this->api_request('domain/allowedarguments'); 361 | return($success); 362 | } 363 | 364 | /** 365 | * Change nameservers for a domain. 366 | * Check the registrarinfo field in domain_details() to know if this can be done for a domain. 367 | * 368 | * @param array( 369 | * 'domainname' => (string) required 370 | * 'ns1' => (string) required 371 | * 'ns2' => (string) required 372 | * 373 | * 'ns3' => (string) optional 374 | * 'ns4' => (string) optional 375 | * ) 376 | * @return true on success or false on failure. 377 | * In both cases the response can be fetched using $glesys_domain->fetch_response(). 378 | */ 379 | public function domain_changenameservers($data) 380 | { 381 | $data['domainname'] = $this->punycode_endoce($data['domainname']); 382 | 383 | $success = $this->api_request('domain/changenameservers', $data); 384 | return($success); 385 | } 386 | } 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | // 417 | -------------------------------------------------------------------------------- /PHP/api_classes/glesys_email.php: -------------------------------------------------------------------------------- 1 | http://www.tumba25.com 4 | * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License v3 5 | */ 6 | 7 | if (!class_exists('glesys_api')) 8 | { 9 | $phpEx = substr(strrchr(__FILE__, '.'), 1); 10 | $path = dirname(__FILE__); 11 | require("$path/glesys_api.$phpEx"); 12 | } 13 | 14 | class glesys_email extends glesys_api 15 | { 16 | /** 17 | * Get a overview of all domains and count of email accounts and alias. 18 | * 19 | * @param void 20 | * @return true on success or false on failure. 21 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 22 | */ 23 | public function email_overview() 24 | { 25 | $success = $this->api_request('email/overview'); 26 | 27 | if ($success) 28 | { 29 | // Shorten the arrya a bit. 30 | $response = array(); 31 | $response['status'] = $this->response['status']; 32 | $response['summary'] = $this->response['overview']['summary']; 33 | $response['domains'] = $this->response['overview']['domains']; 34 | $response['debug'] = $this->response['debug']; 35 | $this->response = $response; 36 | } 37 | 38 | return($success); 39 | } 40 | 41 | /** 42 | * Get or set the global quota. 43 | * The global quota is the total amount of space that is allowed to be allocated to email accounts. 44 | * The globalquota argument should be in MB. 45 | * 46 | * @param int optional $quota. The new quota to set. 47 | * @return true on success or false on failure. 48 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 49 | */ 50 | public function email_globalquota($quota = '') 51 | { 52 | $quota = (int) $quota; 53 | 54 | if (!empty($quota)) 55 | { 56 | $args = array( 57 | 'globalquota' => $quota, 58 | ); 59 | } 60 | else 61 | { 62 | $args = array(); 63 | } 64 | 65 | $success = $this->api_request('email/globalquota', $args); 66 | return($success); 67 | } 68 | 69 | /** 70 | * Gets a list of all accounts and aliases of a domain with full details. 71 | * It is also possible to filter the results by setting the optional filter parameter to an existing alias or account. 72 | * Filter must be a valid email address. 73 | * Example: user@example.com. 74 | * 75 | * @param string $domainname required. 76 | * @param string $filter optional. 77 | * @return true on success or false on failure. 78 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 79 | */ 80 | public function email_list($domainname, $filter = '') 81 | { 82 | $args = array( 83 | 'domainname' => $this->punycode_endoce($domainname), 84 | ); 85 | 86 | if (!empty($filter)) 87 | { 88 | $args['filter'] = $filter; 89 | } 90 | 91 | $success = $this->api_request('email/list', $args); 92 | 93 | if ($success) 94 | { 95 | // Shorten the arrya a bit. 96 | $response = array(); 97 | $response['status'] = $this->response['status']; 98 | $response['emailaccounts'] = $this->response['list']['emailaccounts']; 99 | $response['emailaliases'] = $this->response['list']['emailaliases']; 100 | $response['debug'] = $this->response['debug']; 101 | $this->response = $response; 102 | } 103 | 104 | return($success); 105 | } 106 | 107 | /** 108 | * Edit an email account and change things like quota, password, autoresponse and antispam level. 109 | * Allowed values for antispam is 0-5. Quota is in MB. 110 | * 111 | * @param string $emailaccount required. 112 | * @param array $args, all array parts are optional array( 113 | * 'antispamlevel' => 0 - 5 114 | * 'antivirus' => 0|1 115 | * 'password' => new password 116 | * 'autorespond' => 0|1 117 | * 'autorespondsaveemail' => 0|1 118 | * 'autorespondmessage' => string with message 119 | * 'quota' => new quota in MB 120 | * ) 121 | * @return true on success or false on failure. 122 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 123 | */ 124 | public function email_editaccount($emailaccount, $data = array()) 125 | { 126 | $args = array( 127 | 'emailaccount' => $emailaccount, 128 | ); 129 | 130 | if (!empty($data)) 131 | { 132 | $args = array_merge($args, $data); 133 | } 134 | 135 | $success = $this->api_request('email/editaccount', $args); 136 | return($success); 137 | } 138 | 139 | /** 140 | * Delete an email-account or alias. 141 | * 142 | * @param string $email required. 143 | * @return true on success or false on failure. 144 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 145 | */ 146 | public function email_delete($email) 147 | { 148 | $args = array( 149 | 'email' => $email, 150 | ); 151 | 152 | $success = $this->api_request('email/delete', $args); 153 | return($success); 154 | } 155 | 156 | /** 157 | * Create an email account. 158 | * Allowed values for antispam is 0-5. Quota is in MB. 159 | * 160 | * @param string $emailaccount required. 161 | * @param string $password required. 162 | * @param array $args, all array parts are optional array( 163 | * 'antispamlevel' => 0 - 5 164 | * 'antivirus' => 0|1 165 | * 'autorespond' => 0|1 166 | * 'autorespondsaveemail' => 0|1 167 | * 'autorespondmessage' => string with message 168 | * 'quota' => new quota in MB 169 | * ) 170 | * @return true on success or false on failure. 171 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 172 | */ 173 | public function email_createaccount($emailaccount, $password, $data = array()) 174 | { 175 | $args = array( 176 | 'emailaccount' => $emailaccount, 177 | 'password' => $password, 178 | ); 179 | 180 | if (!empty($data)) 181 | { 182 | $args = array_merge($args, $data); 183 | } 184 | 185 | $success = $this->api_request('email/createaccount', $args); 186 | return($success); 187 | } 188 | 189 | /** 190 | * Gets quota information about an account. 191 | * How much is being used and how much is available. 192 | * 193 | * @param string $emailaccount required. 194 | * @return true on success or false on failure. 195 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 196 | */ 197 | public function email_quota($emailaccount) 198 | { 199 | $args = array( 200 | 'emailaccount' => $emailaccount, 201 | ); 202 | 203 | $success = $this->api_request('email/quota', $args); 204 | return($success); 205 | } 206 | 207 | /** 208 | * Create an email alias. 209 | * 210 | * @param string $emailaccount required. 211 | * @param string $goto required. 212 | * @return true on success or false on failure. 213 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 214 | */ 215 | public function email_createalias($emailalias, $goto) 216 | { 217 | $args = array( 218 | 'emailalias' => $emailalias, 219 | 'goto' => $goto, 220 | ); 221 | 222 | $success = $this->api_request('email/createalias', $args); 223 | return($success); 224 | } 225 | 226 | /** 227 | * Edit an email alias. 228 | * 229 | * @param string $emailaccount required. 230 | * @param string $goto required. 231 | * @return true on success or false on failure. 232 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 233 | */ 234 | public function email_editalias($emailalias, $goto) 235 | { 236 | $args = array( 237 | 'emailalias' => $emailalias, 238 | 'goto' => $goto, 239 | ); 240 | 241 | $success = $this->api_request('email/editalias', $args); 242 | return($success); 243 | } 244 | 245 | /** 246 | * Get email related costs and pricelists. 247 | * 248 | * @param void 249 | * @return true on success or false on failure. 250 | * In both cases the response can be fetched using $glesys_email->fetch_response(). 251 | */ 252 | public function email_costs() 253 | { 254 | $success = $this->api_request('email/costs'); 255 | return($success); 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /PHP/api_classes/idna_convert.php: -------------------------------------------------------------------------------- 1 | 50 | * @copyright 2004-2011 phlyLabs Berlin, http://phlylabs.de 51 | * @version 0.8.1 2011-12-19 52 | * 53 | * Downloaded from http://phlymail.com/en/downloads/idna-convert.html 54 | */ 55 | class idna_convert 56 | { 57 | // NP See below 58 | 59 | // Internal settings, do not mess with them 60 | protected $_punycode_prefix = 'xn--'; 61 | protected $_invalid_ucs = 0x80000000; 62 | protected $_max_ucs = 0x10FFFF; 63 | protected $_base = 36; 64 | protected $_tmin = 1; 65 | protected $_tmax = 26; 66 | protected $_skew = 38; 67 | protected $_damp = 700; 68 | protected $_initial_bias = 72; 69 | protected $_initial_n = 0x80; 70 | protected $_sbase = 0xAC00; 71 | protected $_lbase = 0x1100; 72 | protected $_vbase = 0x1161; 73 | protected $_tbase = 0x11A7; 74 | protected $_lcount = 19; 75 | protected $_vcount = 21; 76 | protected $_tcount = 28; 77 | protected $_ncount = 588; // _vcount * _tcount 78 | protected $_scount = 11172; // _lcount * _tcount * _vcount 79 | protected $_error = false; 80 | 81 | protected static $_mb_string_overload = null; 82 | 83 | // See {@link set_paramter()} for details of how to change the following 84 | // settings from within your script / application 85 | protected $_api_encoding = 'utf8'; // Default input charset is UTF-8 86 | protected $_allow_overlong = false; // Overlong UTF-8 encodings are forbidden 87 | protected $_strict_mode = false; // Behave strict or not 88 | protected $_idn_version = 2003; // Can be either 2003 (old, default) or 2008 89 | 90 | /** 91 | * the constructor 92 | * 93 | * @param array $options 94 | * @return boolean 95 | * @since 0.5.2 96 | */ 97 | public function __construct($options = false) 98 | { 99 | $this->slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount; 100 | // If parameters are given, pass these to the respective method 101 | if (is_array($options)) { 102 | $this->set_parameter($options); 103 | } 104 | 105 | // populate mbstring overloading cache if not set 106 | if (self::$_mb_string_overload === null) { 107 | self::$_mb_string_overload = (extension_loaded('mbstring') 108 | && (ini_get('mbstring.func_overload') & 0x02) === 0x02); 109 | } 110 | } 111 | 112 | /** 113 | * Sets a new option value. Available options and values: 114 | * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8, 115 | * 'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8] 116 | * [overlong - Unicode does not allow unnecessarily long encodings of chars, 117 | * to allow this, set this parameter to true, else to false; 118 | * default is false.] 119 | * [strict - true: strict mode, good for registration purposes - Causes errors 120 | * on failures; false: loose mode, ideal for "wildlife" applications 121 | * by silently ignoring errors and returning the original input instead 122 | * 123 | * @param mixed Parameter to set (string: single parameter; array of Parameter => Value pairs) 124 | * @param string Value to use (if parameter 1 is a string) 125 | * @return boolean true on success, false otherwise 126 | */ 127 | public function set_parameter($option, $value = false) 128 | { 129 | if (!is_array($option)) { 130 | $option = array($option => $value); 131 | } 132 | foreach ($option as $k => $v) { 133 | switch ($k) { 134 | case 'encoding': 135 | switch ($v) { 136 | case 'utf8': 137 | case 'ucs4_string': 138 | case 'ucs4_array': 139 | $this->_api_encoding = $v; 140 | break; 141 | default: 142 | $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k); 143 | return false; 144 | } 145 | break; 146 | case 'overlong': 147 | $this->_allow_overlong = ($v) ? true : false; 148 | break; 149 | case 'strict': 150 | $this->_strict_mode = ($v) ? true : false; 151 | break; 152 | case 'idn_version': 153 | if (in_array($v, array('2003', '2008'))) { 154 | $this->_idn_version = $v; 155 | } else { 156 | $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k); 157 | } 158 | break; 159 | case 'encode_german_sz': // Deprecated 160 | if (!$v) { 161 | self::$NP['replacemaps'][0xDF] = array(0x73, 0x73); 162 | } else { 163 | unset(self::$NP['replacemaps'][0xDF]); 164 | } 165 | break; 166 | default: 167 | $this->_error('Set Parameter: Unknown option '.$k); 168 | return false; 169 | } 170 | } 171 | return true; 172 | } 173 | 174 | /** 175 | * Decode a given ACE domain name 176 | * @param string Domain name (ACE string) 177 | * [@param string Desired output encoding, see {@link set_parameter}] 178 | * @return string Decoded Domain name (UTF-8 or UCS-4) 179 | */ 180 | public function decode($input, $one_time_encoding = false) 181 | { 182 | // Optionally set 183 | if ($one_time_encoding) { 184 | switch ($one_time_encoding) { 185 | case 'utf8': 186 | case 'ucs4_string': 187 | case 'ucs4_array': 188 | break; 189 | default: 190 | $this->_error('Unknown encoding '.$one_time_encoding); 191 | return false; 192 | } 193 | } 194 | // Make sure to drop any newline characters around 195 | $input = trim($input); 196 | 197 | // Negotiate input and try to determine, whether it is a plain string, 198 | // an email address or something like a complete URL 199 | if (strpos($input, '@')) { // Maybe it is an email address 200 | // No no in strict mode 201 | if ($this->_strict_mode) { 202 | $this->_error('Only simple domain name parts can be handled in strict mode'); 203 | return false; 204 | } 205 | list ($email_pref, $input) = explode('@', $input, 2); 206 | $arr = explode('.', $input); 207 | foreach ($arr as $k => $v) { 208 | if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) { 209 | $conv = $this->_decode($v); 210 | if ($conv) $arr[$k] = $conv; 211 | } 212 | } 213 | $input = join('.', $arr); 214 | $arr = explode('.', $email_pref); 215 | foreach ($arr as $k => $v) { 216 | if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) { 217 | $conv = $this->_decode($v); 218 | if ($conv) $arr[$k] = $conv; 219 | } 220 | } 221 | $email_pref = join('.', $arr); 222 | $return = $email_pref . '@' . $input; 223 | } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters) 224 | // No no in strict mode 225 | if ($this->_strict_mode) { 226 | $this->_error('Only simple domain name parts can be handled in strict mode'); 227 | return false; 228 | } 229 | $parsed = parse_url($input); 230 | if (isset($parsed['host'])) { 231 | $arr = explode('.', $parsed['host']); 232 | foreach ($arr as $k => $v) { 233 | $conv = $this->_decode($v); 234 | if ($conv) $arr[$k] = $conv; 235 | } 236 | $parsed['host'] = join('.', $arr); 237 | $return = 238 | (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://')) 239 | .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@') 240 | .$parsed['host'] 241 | .(empty($parsed['port']) ? '' : ':'.$parsed['port']) 242 | .(empty($parsed['path']) ? '' : $parsed['path']) 243 | .(empty($parsed['query']) ? '' : '?'.$parsed['query']) 244 | .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']); 245 | } else { // parse_url seems to have failed, try without it 246 | $arr = explode('.', $input); 247 | foreach ($arr as $k => $v) { 248 | $conv = $this->_decode($v); 249 | $arr[$k] = ($conv) ? $conv : $v; 250 | } 251 | $return = join('.', $arr); 252 | } 253 | } else { // Otherwise we consider it being a pure domain name string 254 | $return = $this->_decode($input); 255 | if (!$return) $return = $input; 256 | } 257 | // The output is UTF-8 by default, other output formats need conversion here 258 | // If one time encoding is given, use this, else the objects property 259 | switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) { 260 | case 'utf8': 261 | return $return; 262 | break; 263 | case 'ucs4_string': 264 | return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return)); 265 | break; 266 | case 'ucs4_array': 267 | return $this->_utf8_to_ucs4($return); 268 | break; 269 | default: 270 | $this->_error('Unsupported output format'); 271 | return false; 272 | } 273 | } 274 | 275 | /** 276 | * Encode a given UTF-8 domain name 277 | * @param string Domain name (UTF-8 or UCS-4) 278 | * [@param string Desired input encoding, see {@link set_parameter}] 279 | * @return string Encoded Domain name (ACE string) 280 | */ 281 | public function encode($decoded, $one_time_encoding = false) 282 | { 283 | // Forcing conversion of input to UCS4 array 284 | // If one time encoding is given, use this, else the objects property 285 | switch ($one_time_encoding ? $one_time_encoding : $this->_api_encoding) { 286 | case 'utf8': 287 | $decoded = $this->_utf8_to_ucs4($decoded); 288 | break; 289 | case 'ucs4_string': 290 | $decoded = $this->_ucs4_string_to_ucs4($decoded); 291 | case 'ucs4_array': 292 | break; 293 | default: 294 | $this->_error('Unsupported input format: '.($one_time_encoding ? $one_time_encoding : $this->_api_encoding)); 295 | return false; 296 | } 297 | 298 | // No input, no output, what else did you expect? 299 | if (empty($decoded)) return ''; 300 | 301 | // Anchors for iteration 302 | $last_begin = 0; 303 | // Output string 304 | $output = ''; 305 | foreach ($decoded as $k => $v) { 306 | // Make sure to use just the plain dot 307 | switch($v) { 308 | case 0x3002: 309 | case 0xFF0E: 310 | case 0xFF61: 311 | $decoded[$k] = 0x2E; 312 | // Right, no break here, the above are converted to dots anyway 313 | // Stumbling across an anchoring character 314 | case 0x2E: 315 | case 0x2F: 316 | case 0x3A: 317 | case 0x3F: 318 | case 0x40: 319 | // Neither email addresses nor URLs allowed in strict mode 320 | if ($this->_strict_mode) { 321 | $this->_error('Neither email addresses nor URLs are allowed in strict mode.'); 322 | return false; 323 | } else { 324 | // Skip first char 325 | if ($k) { 326 | $encoded = ''; 327 | $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin))); 328 | if ($encoded) { 329 | $output .= $encoded; 330 | } else { 331 | $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin))); 332 | } 333 | $output .= chr($decoded[$k]); 334 | } 335 | $last_begin = $k + 1; 336 | } 337 | } 338 | } 339 | // Catch the rest of the string 340 | if ($last_begin) { 341 | $inp_len = sizeof($decoded); 342 | $encoded = ''; 343 | $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin))); 344 | if ($encoded) { 345 | $output .= $encoded; 346 | } else { 347 | $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin))); 348 | } 349 | return $output; 350 | } else { 351 | if ($output = $this->_encode($decoded)) { 352 | return $output; 353 | } else { 354 | return $this->_ucs4_to_utf8($decoded); 355 | } 356 | } 357 | } 358 | 359 | /** 360 | * Removes a weakness of encode(), which cannot properly handle URIs but instead encodes their 361 | * path or query components, too. 362 | * @param string $uri Expects the URI as a UTF-8 (or ASCII) string 363 | * @return string The URI encoded to Punycode, everything but the host component is left alone 364 | * @since 0.6.4 365 | */ 366 | public function encode_uri($uri) 367 | { 368 | $parsed = parse_url($uri); 369 | if (!isset($parsed['host'])) { 370 | $this->_error('The given string does not look like a URI'); 371 | return false; 372 | } 373 | $arr = explode('.', $parsed['host']); 374 | foreach ($arr as $k => $v) { 375 | $conv = $this->encode($v, 'utf8'); 376 | if ($conv) $arr[$k] = $conv; 377 | } 378 | $parsed['host'] = join('.', $arr); 379 | $return = 380 | (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://')) 381 | .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@') 382 | .$parsed['host'] 383 | .(empty($parsed['port']) ? '' : ':'.$parsed['port']) 384 | .(empty($parsed['path']) ? '' : $parsed['path']) 385 | .(empty($parsed['query']) ? '' : '?'.$parsed['query']) 386 | .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']); 387 | return $return; 388 | } 389 | 390 | /** 391 | * Use this method to get the last error ocurred 392 | * @param void 393 | * @return string The last error, that occured 394 | */ 395 | public function get_last_error() 396 | { 397 | return $this->_error; 398 | } 399 | 400 | /** 401 | * The actual decoding algorithm 402 | * @param string 403 | * @return mixed 404 | */ 405 | protected function _decode($encoded) 406 | { 407 | $decoded = array(); 408 | // find the Punycode prefix 409 | if (!preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $encoded)) { 410 | $this->_error('This is not a punycode string'); 411 | return false; 412 | } 413 | $encode_test = preg_replace('!^'.preg_quote($this->_punycode_prefix, '!').'!', '', $encoded); 414 | // If nothing left after removing the prefix, it is hopeless 415 | if (!$encode_test) { 416 | $this->_error('The given encoded string was empty'); 417 | return false; 418 | } 419 | // Find last occurence of the delimiter 420 | $delim_pos = strrpos($encoded, '-'); 421 | if ($delim_pos > self::byteLength($this->_punycode_prefix)) { 422 | for ($k = self::byteLength($this->_punycode_prefix); $k < $delim_pos; ++$k) { 423 | $decoded[] = ord($encoded{$k}); 424 | } 425 | } 426 | $deco_len = count($decoded); 427 | $enco_len = self::byteLength($encoded); 428 | 429 | // Wandering through the strings; init 430 | $is_first = true; 431 | $bias = $this->_initial_bias; 432 | $idx = 0; 433 | $char = $this->_initial_n; 434 | 435 | for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) { 436 | for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) { 437 | $digit = $this->_decode_digit($encoded{$enco_idx++}); 438 | $idx += $digit * $w; 439 | $t = ($k <= $bias) ? $this->_tmin : 440 | (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias)); 441 | if ($digit < $t) break; 442 | $w = (int) ($w * ($this->_base - $t)); 443 | } 444 | $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first); 445 | $is_first = false; 446 | $char += (int) ($idx / ($deco_len + 1)); 447 | $idx %= ($deco_len + 1); 448 | if ($deco_len > 0) { 449 | // Make room for the decoded char 450 | for ($i = $deco_len; $i > $idx; $i--) $decoded[$i] = $decoded[($i - 1)]; 451 | } 452 | $decoded[$idx++] = $char; 453 | } 454 | return $this->_ucs4_to_utf8($decoded); 455 | } 456 | 457 | /** 458 | * The actual encoding algorithm 459 | * @param string 460 | * @return mixed 461 | */ 462 | protected function _encode($decoded) 463 | { 464 | // We cannot encode a domain name containing the Punycode prefix 465 | $extract = self::byteLength($this->_punycode_prefix); 466 | $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix); 467 | $check_deco = array_slice($decoded, 0, $extract); 468 | 469 | if ($check_pref == $check_deco) { 470 | $this->_error('This is already a punycode string'); 471 | return false; 472 | } 473 | // We will not try to encode strings consisting of basic code points only 474 | $encodable = false; 475 | foreach ($decoded as $k => $v) { 476 | if ($v > 0x7a) { 477 | $encodable = true; 478 | break; 479 | } 480 | } 481 | if (!$encodable) { 482 | $this->_error('The given string does not contain encodable chars'); 483 | return false; 484 | } 485 | // Do NAMEPREP 486 | $decoded = $this->_nameprep($decoded); 487 | if (!$decoded || !is_array($decoded)) return false; // NAMEPREP failed 488 | $deco_len = count($decoded); 489 | if (!$deco_len) return false; // Empty array 490 | $codecount = 0; // How many chars have been consumed 491 | $encoded = ''; 492 | // Copy all basic code points to output 493 | for ($i = 0; $i < $deco_len; ++$i) { 494 | $test = $decoded[$i]; 495 | // Will match [-0-9a-zA-Z] 496 | if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B) 497 | || (0x60 < $test && $test <= 0x7B) || (0x2D == $test)) { 498 | $encoded .= chr($decoded[$i]); 499 | $codecount++; 500 | } 501 | } 502 | if ($codecount == $deco_len) return $encoded; // All codepoints were basic ones 503 | 504 | // Start with the prefix; copy it to output 505 | $encoded = $this->_punycode_prefix.$encoded; 506 | // If we have basic code points in output, add an hyphen to the end 507 | if ($codecount) $encoded .= '-'; 508 | // Now find and encode all non-basic code points 509 | $is_first = true; 510 | $cur_code = $this->_initial_n; 511 | $bias = $this->_initial_bias; 512 | $delta = 0; 513 | while ($codecount < $deco_len) { 514 | // Find the smallest code point >= the current code point and 515 | // remember the last ouccrence of it in the input 516 | for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) { 517 | if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) { 518 | $next_code = $decoded[$i]; 519 | } 520 | } 521 | $delta += ($next_code - $cur_code) * ($codecount + 1); 522 | $cur_code = $next_code; 523 | 524 | // Scan input again and encode all characters whose code point is $cur_code 525 | for ($i = 0; $i < $deco_len; $i++) { 526 | if ($decoded[$i] < $cur_code) { 527 | $delta++; 528 | } elseif ($decoded[$i] == $cur_code) { 529 | for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) { 530 | $t = ($k <= $bias) ? $this->_tmin : 531 | (($k >= $bias + $this->_tmax) ? $this->_tmax : $k - $bias); 532 | if ($q < $t) break; 533 | $encoded .= $this->_encode_digit(intval($t + (($q - $t) % ($this->_base - $t)))); //v0.4.5 Changed from ceil() to intval() 534 | $q = (int) (($q - $t) / ($this->_base - $t)); 535 | } 536 | $encoded .= $this->_encode_digit($q); 537 | $bias = $this->_adapt($delta, $codecount+1, $is_first); 538 | $codecount++; 539 | $delta = 0; 540 | $is_first = false; 541 | } 542 | } 543 | $delta++; 544 | $cur_code++; 545 | } 546 | return $encoded; 547 | } 548 | 549 | /** 550 | * Adapt the bias according to the current code point and position 551 | * @param int $delta 552 | * @param int $npoints 553 | * @param int $is_first 554 | * @return int 555 | */ 556 | protected function _adapt($delta, $npoints, $is_first) 557 | { 558 | $delta = intval($is_first ? ($delta / $this->_damp) : ($delta / 2)); 559 | $delta += intval($delta / $npoints); 560 | for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) { 561 | $delta = intval($delta / ($this->_base - $this->_tmin)); 562 | } 563 | return intval($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew)); 564 | } 565 | 566 | /** 567 | * Encoding a certain digit 568 | * @param int $d 569 | * @return string 570 | */ 571 | protected function _encode_digit($d) 572 | { 573 | return chr($d + 22 + 75 * ($d < 26)); 574 | } 575 | 576 | /** 577 | * Decode a certain digit 578 | * @param int $cp 579 | * @return int 580 | */ 581 | protected function _decode_digit($cp) 582 | { 583 | $cp = ord($cp); 584 | return ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $this->_base)); 585 | } 586 | 587 | /** 588 | * Internal error handling method 589 | * @param string $error 590 | */ 591 | protected function _error($error = '') 592 | { 593 | $this->_error = $error; 594 | } 595 | 596 | /** 597 | * Do Nameprep according to RFC3491 and RFC3454 598 | * @param array Unicode Characters 599 | * @return string Unicode Characters, Nameprep'd 600 | */ 601 | protected function _nameprep($input) 602 | { 603 | $output = array(); 604 | $error = false; 605 | // 606 | // Mapping 607 | // Walking through the input array, performing the required steps on each of 608 | // the input chars and putting the result into the output array 609 | // While mapping required chars we apply the cannonical ordering 610 | foreach ($input as $v) { 611 | // Map to nothing == skip that code point 612 | if (in_array($v, self::$NP['map_nothing'])) continue; 613 | // Try to find prohibited input 614 | if (in_array($v, self::$NP['prohibit']) || in_array($v, self::$NP['general_prohibited'])) { 615 | $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v)); 616 | return false; 617 | } 618 | foreach (self::$NP['prohibit_ranges'] as $range) { 619 | if ($range[0] <= $v && $v <= $range[1]) { 620 | $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v)); 621 | return false; 622 | } 623 | } 624 | 625 | if (0xAC00 <= $v && $v <= 0xD7AF) { 626 | // Hangul syllable decomposition 627 | foreach ($this->_hangul_decompose($v) as $out) { 628 | $output[] = (int) $out; 629 | } 630 | } elseif (($this->_idn_version == '2003') && isset(self::$NP['replacemaps'][$v])) { 631 | // There's a decomposition mapping for that code point 632 | // Decompositions only in version 2003 (original) of IDNA 633 | foreach ($this->_apply_cannonical_ordering(self::$NP['replacemaps'][$v]) as $out) { 634 | $output[] = (int) $out; 635 | } 636 | } else { 637 | $output[] = (int) $v; 638 | } 639 | } 640 | // Before applying any Combining, try to rearrange any Hangul syllables 641 | $output = $this->_hangul_compose($output); 642 | // 643 | // Combine code points 644 | // 645 | $last_class = 0; 646 | $last_starter = 0; 647 | $out_len = count($output); 648 | for ($i = 0; $i < $out_len; ++$i) { 649 | $class = $this->_get_combining_class($output[$i]); 650 | if ((!$last_class || $last_class > $class) && $class) { 651 | // Try to match 652 | $seq_len = $i - $last_starter; 653 | $out = $this->_combine(array_slice($output, $last_starter, $seq_len)); 654 | // On match: Replace the last starter with the composed character and remove 655 | // the now redundant non-starter(s) 656 | if ($out) { 657 | $output[$last_starter] = $out; 658 | if (count($out) != $seq_len) { 659 | for ($j = $i+1; $j < $out_len; ++$j) $output[$j-1] = $output[$j]; 660 | unset($output[$out_len]); 661 | } 662 | // Rewind the for loop by one, since there can be more possible compositions 663 | $i--; 664 | $out_len--; 665 | $last_class = ($i == $last_starter) ? 0 : $this->_get_combining_class($output[$i-1]); 666 | continue; 667 | } 668 | } 669 | // The current class is 0 670 | if (!$class) $last_starter = $i; 671 | $last_class = $class; 672 | } 673 | return $output; 674 | } 675 | 676 | /** 677 | * Decomposes a Hangul syllable 678 | * (see http://www.unicode.org/unicode/reports/tr15/#Hangul 679 | * @param integer 32bit UCS4 code point 680 | * @return array Either Hangul Syllable decomposed or original 32bit value as one value array 681 | */ 682 | protected function _hangul_decompose($char) 683 | { 684 | $sindex = (int) $char - $this->_sbase; 685 | if ($sindex < 0 || $sindex >= $this->_scount) return array($char); 686 | $result = array(); 687 | $result[] = (int) $this->_lbase + $sindex / $this->_ncount; 688 | $result[] = (int) $this->_vbase + ($sindex % $this->_ncount) / $this->_tcount; 689 | $T = intval($this->_tbase + $sindex % $this->_tcount); 690 | if ($T != $this->_tbase) $result[] = $T; 691 | return $result; 692 | } 693 | /** 694 | * Ccomposes a Hangul syllable 695 | * (see http://www.unicode.org/unicode/reports/tr15/#Hangul 696 | * @param array Decomposed UCS4 sequence 697 | * @return array UCS4 sequence with syllables composed 698 | */ 699 | protected function _hangul_compose($input) 700 | { 701 | $inp_len = count($input); 702 | if (!$inp_len) return array(); 703 | $result = array(); 704 | $last = (int) $input[0]; 705 | $result[] = $last; // copy first char from input to output 706 | 707 | for ($i = 1; $i < $inp_len; ++$i) { 708 | $char = (int) $input[$i]; 709 | $sindex = $last - $this->_sbase; 710 | $lindex = $last - $this->_lbase; 711 | $vindex = $char - $this->_vbase; 712 | $tindex = $char - $this->_tbase; 713 | // Find out, whether two current characters are LV and T 714 | if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount == 0) 715 | && 0 <= $tindex && $tindex <= $this->_tcount) { 716 | // create syllable of form LVT 717 | $last += $tindex; 718 | $result[(count($result) - 1)] = $last; // reset last 719 | continue; // discard char 720 | } 721 | // Find out, whether two current characters form L and V 722 | if (0 <= $lindex && $lindex < $this->_lcount && 0 <= $vindex && $vindex < $this->_vcount) { 723 | // create syllable of form LV 724 | $last = (int) $this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount; 725 | $result[(count($result) - 1)] = $last; // reset last 726 | continue; // discard char 727 | } 728 | // if neither case was true, just add the character 729 | $last = $char; 730 | $result[] = $char; 731 | } 732 | return $result; 733 | } 734 | 735 | /** 736 | * Returns the combining class of a certain wide char 737 | * @param integer Wide char to check (32bit integer) 738 | * @return integer Combining class if found, else 0 739 | */ 740 | protected function _get_combining_class($char) 741 | { 742 | return isset(self::$NP['norm_combcls'][$char]) ? self::$NP['norm_combcls'][$char] : 0; 743 | } 744 | 745 | /** 746 | * Applies the cannonical ordering of a decomposed UCS4 sequence 747 | * @param array Decomposed UCS4 sequence 748 | * @return array Ordered USC4 sequence 749 | */ 750 | protected function _apply_cannonical_ordering($input) 751 | { 752 | $swap = true; 753 | $size = count($input); 754 | while ($swap) { 755 | $swap = false; 756 | $last = $this->_get_combining_class(intval($input[0])); 757 | for ($i = 0; $i < $size-1; ++$i) { 758 | $next = $this->_get_combining_class(intval($input[$i+1])); 759 | if ($next != 0 && $last > $next) { 760 | // Move item leftward until it fits 761 | for ($j = $i + 1; $j > 0; --$j) { 762 | if ($this->_get_combining_class(intval($input[$j-1])) <= $next) break; 763 | $t = intval($input[$j]); 764 | $input[$j] = intval($input[$j-1]); 765 | $input[$j-1] = $t; 766 | $swap = true; 767 | } 768 | // Reentering the loop looking at the old character again 769 | $next = $last; 770 | } 771 | $last = $next; 772 | } 773 | } 774 | return $input; 775 | } 776 | 777 | /** 778 | * Do composition of a sequence of starter and non-starter 779 | * @param array UCS4 Decomposed sequence 780 | * @return array Ordered USC4 sequence 781 | */ 782 | protected function _combine($input) 783 | { 784 | $inp_len = count($input); 785 | if (0 == $inp_len) { 786 | return false; 787 | } 788 | foreach (self::$NP['replacemaps'] as $np_src => $np_target) { 789 | if ($np_target[0] != $input[0]) continue; 790 | if (count($np_target) != $inp_len) continue; 791 | $hit = false; 792 | foreach ($input as $k2 => $v2) { 793 | if ($v2 == $np_target[$k2]) { 794 | $hit = true; 795 | } else { 796 | $hit = false; 797 | break; 798 | } 799 | } 800 | if ($hit) return $np_src; 801 | } 802 | return false; 803 | } 804 | 805 | /** 806 | * This converts an UTF-8 encoded string to its UCS-4 representation 807 | * By talking about UCS-4 "strings" we mean arrays of 32bit integers representing 808 | * each of the "chars". This is due to PHP not being able to handle strings with 809 | * bit depth different from 8. This apllies to the reverse method _ucs4_to_utf8(), too. 810 | * The following UTF-8 encodings are supported: 811 | * bytes bits representation 812 | * 1 7 0xxxxxxx 813 | * 2 11 110xxxxx 10xxxxxx 814 | * 3 16 1110xxxx 10xxxxxx 10xxxxxx 815 | * 4 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 816 | * 5 26 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 817 | * 6 31 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 818 | * Each x represents a bit that can be used to store character data. 819 | * The five and six byte sequences are part of Annex D of ISO/IEC 10646-1:2000 820 | * @param string $input 821 | * @return string 822 | */ 823 | protected function _utf8_to_ucs4($input) 824 | { 825 | $output = array(); 826 | $out_len = 0; 827 | $inp_len = self::byteLength($input); 828 | $mode = 'next'; 829 | $test = 'none'; 830 | for ($k = 0; $k < $inp_len; ++$k) { 831 | $v = ord($input{$k}); // Extract byte from input string 832 | if ($v < 128) { // We found an ASCII char - put into stirng as is 833 | $output[$out_len] = $v; 834 | ++$out_len; 835 | if ('add' == $mode) { 836 | $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k); 837 | return false; 838 | } 839 | continue; 840 | } 841 | if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char 842 | $start_byte = $v; 843 | $mode = 'add'; 844 | $test = 'range'; 845 | if ($v >> 5 == 6) { // &110xxxxx 10xxxxx 846 | $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left 847 | $v = ($v - 192) << 6; 848 | } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx 849 | $next_byte = 1; 850 | $v = ($v - 224) << 12; 851 | } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 852 | $next_byte = 2; 853 | $v = ($v - 240) << 18; 854 | } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 855 | $next_byte = 3; 856 | $v = ($v - 248) << 24; 857 | } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 858 | $next_byte = 4; 859 | $v = ($v - 252) << 30; 860 | } else { 861 | $this->_error('This might be UTF-8, but I don\'t understand it at byte '.$k); 862 | return false; 863 | } 864 | if ('add' == $mode) { 865 | $output[$out_len] = (int) $v; 866 | ++$out_len; 867 | continue; 868 | } 869 | } 870 | if ('add' == $mode) { 871 | if (!$this->_allow_overlong && $test == 'range') { 872 | $test = 'none'; 873 | if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) { 874 | $this->_error('Bogus UTF-8 character detected (out of legal range) at byte '.$k); 875 | return false; 876 | } 877 | } 878 | if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx 879 | $v = ($v - 128) << ($next_byte * 6); 880 | $output[($out_len - 1)] += $v; 881 | --$next_byte; 882 | } else { 883 | $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k); 884 | return false; 885 | } 886 | if ($next_byte < 0) { 887 | $mode = 'next'; 888 | } 889 | } 890 | } // for 891 | return $output; 892 | } 893 | 894 | /** 895 | * Convert UCS-4 string into UTF-8 string 896 | * See _utf8_to_ucs4() for details 897 | * @param string $input 898 | * @return string 899 | */ 900 | protected function _ucs4_to_utf8($input) 901 | { 902 | $output = ''; 903 | foreach ($input as $k => $v) { 904 | if ($v < 128) { // 7bit are transferred literally 905 | $output .= chr($v); 906 | } elseif ($v < (1 << 11)) { // 2 bytes 907 | $output .= chr(192+($v >> 6)).chr(128+($v & 63)); 908 | } elseif ($v < (1 << 16)) { // 3 bytes 909 | $output .= chr(224+($v >> 12)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63)); 910 | } elseif ($v < (1 << 21)) { // 4 bytes 911 | $output .= chr(240+($v >> 18)).chr(128+(($v >> 12) & 63)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63)); 912 | } else { 913 | $this->_error('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k); 914 | return false; 915 | } 916 | } 917 | return $output; 918 | } 919 | 920 | /** 921 | * Convert UCS-4 array into UCS-4 string 922 | * 923 | * @param array $input 924 | * @return string 925 | */ 926 | protected function _ucs4_to_ucs4_string($input) 927 | { 928 | $output = ''; 929 | // Take array values and split output to 4 bytes per value 930 | // The bit mask is 255, which reads &11111111 931 | foreach ($input as $v) { 932 | $output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255); 933 | } 934 | return $output; 935 | } 936 | 937 | /** 938 | * Convert UCS-4 strin into UCS-4 garray 939 | * 940 | * @param string $input 941 | * @return array 942 | */ 943 | protected function _ucs4_string_to_ucs4($input) 944 | { 945 | $output = array(); 946 | $inp_len = self::byteLength($input); 947 | // Input length must be dividable by 4 948 | if ($inp_len % 4) { 949 | $this->_error('Input UCS4 string is broken'); 950 | return false; 951 | } 952 | // Empty input - return empty output 953 | if (!$inp_len) return $output; 954 | for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) { 955 | // Increment output position every 4 input bytes 956 | if (!($i % 4)) { 957 | $out_len++; 958 | $output[$out_len] = 0; 959 | } 960 | $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) ); 961 | } 962 | return $output; 963 | } 964 | 965 | /** 966 | * Gets the length of a string in bytes even if mbstring function 967 | * overloading is turned on 968 | * 969 | * @param string $string the string for which to get the length. 970 | * @return integer the length of the string in bytes. 971 | */ 972 | protected static function byteLength($string) 973 | { 974 | if (self::$_mb_string_overload) { 975 | return mb_strlen($string, '8bit'); 976 | } 977 | return strlen((binary) $string); 978 | } 979 | 980 | /** 981 | * Attempts to return a concrete IDNA instance. 982 | * 983 | * @param array $params Set of paramaters 984 | * @return idna_convert 985 | * @access public 986 | */ 987 | public function getInstance($params = array()) 988 | { 989 | return new idna_convert($params); 990 | } 991 | 992 | /** 993 | * Attempts to return a concrete IDNA instance for either php4 or php5, 994 | * only creating a new instance if no IDNA instance with the same 995 | * parameters currently exists. 996 | * 997 | * @param array $params Set of paramaters 998 | * 999 | * @return object idna_convert 1000 | * @access public 1001 | */ 1002 | public function singleton($params = array()) 1003 | { 1004 | static $instances; 1005 | if (!isset($instances)) { 1006 | $instances = array(); 1007 | } 1008 | $signature = serialize($params); 1009 | if (!isset($instances[$signature])) { 1010 | $instances[$signature] = idna_convert::getInstance($params); 1011 | } 1012 | return $instances[$signature]; 1013 | } 1014 | 1015 | /** 1016 | * Holds all relevant mapping tables 1017 | * See RFC3454 for details 1018 | * 1019 | * @private array 1020 | * @since 0.5.2 1021 | */ 1022 | protected static $NP = array 1023 | ('map_nothing' => array(0xAD, 0x34F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C 1024 | ,0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07 1025 | ,0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF 1026 | ) 1027 | ,'general_prohibited' => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 1028 | ,20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ,33, 34, 35, 36, 37, 38, 39, 40, 41, 42 1029 | ,43, 44, 47, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126, 127, 0x3002 1030 | ) 1031 | ,'prohibit' => array(0xA0, 0x340, 0x341, 0x6DD, 0x70F, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003 1032 | ,0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x200E, 0x200F 1033 | ,0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, 0x202F, 0x205F, 0x206A, 0x206B, 0x206C 1034 | ,0x206D, 0x206E, 0x206F, 0x3000, 0xFEFF, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF 1035 | ,0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE 1036 | ,0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF 1037 | ,0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xE0001, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF 1038 | ) 1039 | ,'prohibit_ranges' => array(array(0x80, 0x9F), array(0x2060, 0x206F), array(0x1D173, 0x1D17A) 1040 | ,array(0xE000, 0xF8FF) ,array(0xF0000, 0xFFFFD), array(0x100000, 0x10FFFD) 1041 | ,array(0xFDD0, 0xFDEF), array(0xD800, 0xDFFF), array(0x2FF0, 0x2FFB), array(0xE0020, 0xE007F) 1042 | ) 1043 | ,'replacemaps' => array(0x41 => array(0x61), 0x42 => array(0x62), 0x43 => array(0x63) 1044 | ,0x44 => array(0x64), 0x45 => array(0x65), 0x46 => array(0x66), 0x47 => array(0x67) 1045 | ,0x48 => array(0x68), 0x49 => array(0x69), 0x4A => array(0x6A), 0x4B => array(0x6B) 1046 | ,0x4C => array(0x6C), 0x4D => array(0x6D), 0x4E => array(0x6E), 0x4F => array(0x6F) 1047 | ,0x50 => array(0x70), 0x51 => array(0x71), 0x52 => array(0x72), 0x53 => array(0x73) 1048 | ,0x54 => array(0x74), 0x55 => array(0x75), 0x56 => array(0x76), 0x57 => array(0x77) 1049 | ,0x58 => array(0x78), 0x59 => array(0x79), 0x5A => array(0x7A), 0xB5 => array(0x3BC) 1050 | ,0xC0 => array(0xE0), 0xC1 => array(0xE1), 0xC2 => array(0xE2), 0xC3 => array(0xE3) 1051 | ,0xC4 => array(0xE4), 0xC5 => array(0xE5), 0xC6 => array(0xE6), 0xC7 => array(0xE7) 1052 | ,0xC8 => array(0xE8), 0xC9 => array(0xE9), 0xCA => array(0xEA), 0xCB => array(0xEB) 1053 | ,0xCC => array(0xEC), 0xCD => array(0xED), 0xCE => array(0xEE), 0xCF => array(0xEF) 1054 | ,0xD0 => array(0xF0), 0xD1 => array(0xF1), 0xD2 => array(0xF2), 0xD3 => array(0xF3) 1055 | ,0xD4 => array(0xF4), 0xD5 => array(0xF5), 0xD6 => array(0xF6), 0xD8 => array(0xF8) 1056 | ,0xD9 => array(0xF9), 0xDA => array(0xFA), 0xDB => array(0xFB), 0xDC => array(0xFC) 1057 | ,0xDD => array(0xFD), 0xDE => array(0xFE), 0xDF => array(0x73, 0x73) 1058 | ,0x100 => array(0x101), 0x102 => array(0x103), 0x104 => array(0x105) 1059 | ,0x106 => array(0x107), 0x108 => array(0x109), 0x10A => array(0x10B) 1060 | ,0x10C => array(0x10D), 0x10E => array(0x10F), 0x110 => array(0x111) 1061 | ,0x112 => array(0x113), 0x114 => array(0x115), 0x116 => array(0x117) 1062 | ,0x118 => array(0x119), 0x11A => array(0x11B), 0x11C => array(0x11D) 1063 | ,0x11E => array(0x11F), 0x120 => array(0x121), 0x122 => array(0x123) 1064 | ,0x124 => array(0x125), 0x126 => array(0x127), 0x128 => array(0x129) 1065 | ,0x12A => array(0x12B), 0x12C => array(0x12D), 0x12E => array(0x12F) 1066 | ,0x130 => array(0x69, 0x307), 0x132 => array(0x133), 0x134 => array(0x135) 1067 | ,0x136 => array(0x137), 0x139 => array(0x13A), 0x13B => array(0x13C) 1068 | ,0x13D => array(0x13E), 0x13F => array(0x140), 0x141 => array(0x142) 1069 | ,0x143 => array(0x144), 0x145 => array(0x146), 0x147 => array(0x148) 1070 | ,0x149 => array(0x2BC, 0x6E), 0x14A => array(0x14B), 0x14C => array(0x14D) 1071 | ,0x14E => array(0x14F), 0x150 => array(0x151), 0x152 => array(0x153) 1072 | ,0x154 => array(0x155), 0x156 => array(0x157), 0x158 => array(0x159) 1073 | ,0x15A => array(0x15B), 0x15C => array(0x15D), 0x15E => array(0x15F) 1074 | ,0x160 => array(0x161), 0x162 => array(0x163), 0x164 => array(0x165) 1075 | ,0x166 => array(0x167), 0x168 => array(0x169), 0x16A => array(0x16B) 1076 | ,0x16C => array(0x16D), 0x16E => array(0x16F), 0x170 => array(0x171) 1077 | ,0x172 => array(0x173), 0x174 => array(0x175), 0x176 => array(0x177) 1078 | ,0x178 => array(0xFF), 0x179 => array(0x17A), 0x17B => array(0x17C) 1079 | ,0x17D => array(0x17E), 0x17F => array(0x73), 0x181 => array(0x253) 1080 | ,0x182 => array(0x183), 0x184 => array(0x185), 0x186 => array(0x254) 1081 | ,0x187 => array(0x188), 0x189 => array(0x256), 0x18A => array(0x257) 1082 | ,0x18B => array(0x18C), 0x18E => array(0x1DD), 0x18F => array(0x259) 1083 | ,0x190 => array(0x25B), 0x191 => array(0x192), 0x193 => array(0x260) 1084 | ,0x194 => array(0x263), 0x196 => array(0x269), 0x197 => array(0x268) 1085 | ,0x198 => array(0x199), 0x19C => array(0x26F), 0x19D => array(0x272) 1086 | ,0x19F => array(0x275), 0x1A0 => array(0x1A1), 0x1A2 => array(0x1A3) 1087 | ,0x1A4 => array(0x1A5), 0x1A6 => array(0x280), 0x1A7 => array(0x1A8) 1088 | ,0x1A9 => array(0x283), 0x1AC => array(0x1AD), 0x1AE => array(0x288) 1089 | ,0x1AF => array(0x1B0), 0x1B1 => array(0x28A), 0x1B2 => array(0x28B) 1090 | ,0x1B3 => array(0x1B4), 0x1B5 => array(0x1B6), 0x1B7 => array(0x292) 1091 | ,0x1B8 => array(0x1B9), 0x1BC => array(0x1BD), 0x1C4 => array(0x1C6) 1092 | ,0x1C5 => array(0x1C6), 0x1C7 => array(0x1C9), 0x1C8 => array(0x1C9) 1093 | ,0x1CA => array(0x1CC), 0x1CB => array(0x1CC), 0x1CD => array(0x1CE) 1094 | ,0x1CF => array(0x1D0), 0x1D1 => array(0x1D2), 0x1D3 => array(0x1D4) 1095 | ,0x1D5 => array(0x1D6), 0x1D7 => array(0x1D8), 0x1D9 => array(0x1DA) 1096 | ,0x1DB => array(0x1DC), 0x1DE => array(0x1DF), 0x1E0 => array(0x1E1) 1097 | ,0x1E2 => array(0x1E3), 0x1E4 => array(0x1E5), 0x1E6 => array(0x1E7) 1098 | ,0x1E8 => array(0x1E9), 0x1EA => array(0x1EB), 0x1EC => array(0x1ED) 1099 | ,0x1EE => array(0x1EF), 0x1F0 => array(0x6A, 0x30C), 0x1F1 => array(0x1F3) 1100 | ,0x1F2 => array(0x1F3), 0x1F4 => array(0x1F5), 0x1F6 => array(0x195) 1101 | ,0x1F7 => array(0x1BF), 0x1F8 => array(0x1F9), 0x1FA => array(0x1FB) 1102 | ,0x1FC => array(0x1FD), 0x1FE => array(0x1FF), 0x200 => array(0x201) 1103 | ,0x202 => array(0x203), 0x204 => array(0x205), 0x206 => array(0x207) 1104 | ,0x208 => array(0x209), 0x20A => array(0x20B), 0x20C => array(0x20D) 1105 | ,0x20E => array(0x20F), 0x210 => array(0x211), 0x212 => array(0x213) 1106 | ,0x214 => array(0x215), 0x216 => array(0x217), 0x218 => array(0x219) 1107 | ,0x21A => array(0x21B), 0x21C => array(0x21D), 0x21E => array(0x21F) 1108 | ,0x220 => array(0x19E), 0x222 => array(0x223), 0x224 => array(0x225) 1109 | ,0x226 => array(0x227), 0x228 => array(0x229), 0x22A => array(0x22B) 1110 | ,0x22C => array(0x22D), 0x22E => array(0x22F), 0x230 => array(0x231) 1111 | ,0x232 => array(0x233), 0x345 => array(0x3B9), 0x37A => array(0x20, 0x3B9) 1112 | ,0x386 => array(0x3AC), 0x388 => array(0x3AD), 0x389 => array(0x3AE) 1113 | ,0x38A => array(0x3AF), 0x38C => array(0x3CC), 0x38E => array(0x3CD) 1114 | ,0x38F => array(0x3CE), 0x390 => array(0x3B9, 0x308, 0x301) 1115 | ,0x391 => array(0x3B1), 0x392 => array(0x3B2), 0x393 => array(0x3B3) 1116 | ,0x394 => array(0x3B4), 0x395 => array(0x3B5), 0x396 => array(0x3B6) 1117 | ,0x397 => array(0x3B7), 0x398 => array(0x3B8), 0x399 => array(0x3B9) 1118 | ,0x39A => array(0x3BA), 0x39B => array(0x3BB), 0x39C => array(0x3BC) 1119 | ,0x39D => array(0x3BD), 0x39E => array(0x3BE), 0x39F => array(0x3BF) 1120 | ,0x3A0 => array(0x3C0), 0x3A1 => array(0x3C1), 0x3A3 => array(0x3C3) 1121 | ,0x3A4 => array(0x3C4), 0x3A5 => array(0x3C5), 0x3A6 => array(0x3C6) 1122 | ,0x3A7 => array(0x3C7), 0x3A8 => array(0x3C8), 0x3A9 => array(0x3C9) 1123 | ,0x3AA => array(0x3CA), 0x3AB => array(0x3CB), 0x3B0 => array(0x3C5, 0x308, 0x301) 1124 | ,0x3C2 => array(0x3C3), 0x3D0 => array(0x3B2), 0x3D1 => array(0x3B8) 1125 | ,0x3D2 => array(0x3C5), 0x3D3 => array(0x3CD), 0x3D4 => array(0x3CB) 1126 | ,0x3D5 => array(0x3C6), 0x3D6 => array(0x3C0), 0x3D8 => array(0x3D9) 1127 | ,0x3DA => array(0x3DB), 0x3DC => array(0x3DD), 0x3DE => array(0x3DF) 1128 | ,0x3E0 => array(0x3E1), 0x3E2 => array(0x3E3), 0x3E4 => array(0x3E5) 1129 | ,0x3E6 => array(0x3E7), 0x3E8 => array(0x3E9), 0x3EA => array(0x3EB) 1130 | ,0x3EC => array(0x3ED), 0x3EE => array(0x3EF), 0x3F0 => array(0x3BA) 1131 | ,0x3F1 => array(0x3C1), 0x3F2 => array(0x3C3), 0x3F4 => array(0x3B8) 1132 | ,0x3F5 => array(0x3B5), 0x400 => array(0x450), 0x401 => array(0x451) 1133 | ,0x402 => array(0x452), 0x403 => array(0x453), 0x404 => array(0x454) 1134 | ,0x405 => array(0x455), 0x406 => array(0x456), 0x407 => array(0x457) 1135 | ,0x408 => array(0x458), 0x409 => array(0x459), 0x40A => array(0x45A) 1136 | ,0x40B => array(0x45B), 0x40C => array(0x45C), 0x40D => array(0x45D) 1137 | ,0x40E => array(0x45E), 0x40F => array(0x45F), 0x410 => array(0x430) 1138 | ,0x411 => array(0x431), 0x412 => array(0x432), 0x413 => array(0x433) 1139 | ,0x414 => array(0x434), 0x415 => array(0x435), 0x416 => array(0x436) 1140 | ,0x417 => array(0x437), 0x418 => array(0x438), 0x419 => array(0x439) 1141 | ,0x41A => array(0x43A), 0x41B => array(0x43B), 0x41C => array(0x43C) 1142 | ,0x41D => array(0x43D), 0x41E => array(0x43E), 0x41F => array(0x43F) 1143 | ,0x420 => array(0x440), 0x421 => array(0x441), 0x422 => array(0x442) 1144 | ,0x423 => array(0x443), 0x424 => array(0x444), 0x425 => array(0x445) 1145 | ,0x426 => array(0x446), 0x427 => array(0x447), 0x428 => array(0x448) 1146 | ,0x429 => array(0x449), 0x42A => array(0x44A), 0x42B => array(0x44B) 1147 | ,0x42C => array(0x44C), 0x42D => array(0x44D), 0x42E => array(0x44E) 1148 | ,0x42F => array(0x44F), 0x460 => array(0x461), 0x462 => array(0x463) 1149 | ,0x464 => array(0x465), 0x466 => array(0x467), 0x468 => array(0x469) 1150 | ,0x46A => array(0x46B), 0x46C => array(0x46D), 0x46E => array(0x46F) 1151 | ,0x470 => array(0x471), 0x472 => array(0x473), 0x474 => array(0x475) 1152 | ,0x476 => array(0x477), 0x478 => array(0x479), 0x47A => array(0x47B) 1153 | ,0x47C => array(0x47D), 0x47E => array(0x47F), 0x480 => array(0x481) 1154 | ,0x48A => array(0x48B), 0x48C => array(0x48D), 0x48E => array(0x48F) 1155 | ,0x490 => array(0x491), 0x492 => array(0x493), 0x494 => array(0x495) 1156 | ,0x496 => array(0x497), 0x498 => array(0x499), 0x49A => array(0x49B) 1157 | ,0x49C => array(0x49D), 0x49E => array(0x49F), 0x4A0 => array(0x4A1) 1158 | ,0x4A2 => array(0x4A3), 0x4A4 => array(0x4A5), 0x4A6 => array(0x4A7) 1159 | ,0x4A8 => array(0x4A9), 0x4AA => array(0x4AB), 0x4AC => array(0x4AD) 1160 | ,0x4AE => array(0x4AF), 0x4B0 => array(0x4B1), 0x4B2 => array(0x4B3) 1161 | ,0x4B4 => array(0x4B5), 0x4B6 => array(0x4B7), 0x4B8 => array(0x4B9) 1162 | ,0x4BA => array(0x4BB), 0x4BC => array(0x4BD), 0x4BE => array(0x4BF) 1163 | ,0x4C1 => array(0x4C2), 0x4C3 => array(0x4C4), 0x4C5 => array(0x4C6) 1164 | ,0x4C7 => array(0x4C8), 0x4C9 => array(0x4CA), 0x4CB => array(0x4CC) 1165 | ,0x4CD => array(0x4CE), 0x4D0 => array(0x4D1), 0x4D2 => array(0x4D3) 1166 | ,0x4D4 => array(0x4D5), 0x4D6 => array(0x4D7), 0x4D8 => array(0x4D9) 1167 | ,0x4DA => array(0x4DB), 0x4DC => array(0x4DD), 0x4DE => array(0x4DF) 1168 | ,0x4E0 => array(0x4E1), 0x4E2 => array(0x4E3), 0x4E4 => array(0x4E5) 1169 | ,0x4E6 => array(0x4E7), 0x4E8 => array(0x4E9), 0x4EA => array(0x4EB) 1170 | ,0x4EC => array(0x4ED), 0x4EE => array(0x4EF), 0x4F0 => array(0x4F1) 1171 | ,0x4F2 => array(0x4F3), 0x4F4 => array(0x4F5), 0x4F8 => array(0x4F9) 1172 | ,0x500 => array(0x501), 0x502 => array(0x503), 0x504 => array(0x505) 1173 | ,0x506 => array(0x507), 0x508 => array(0x509), 0x50A => array(0x50B) 1174 | ,0x50C => array(0x50D), 0x50E => array(0x50F), 0x531 => array(0x561) 1175 | ,0x532 => array(0x562), 0x533 => array(0x563), 0x534 => array(0x564) 1176 | ,0x535 => array(0x565), 0x536 => array(0x566), 0x537 => array(0x567) 1177 | ,0x538 => array(0x568), 0x539 => array(0x569), 0x53A => array(0x56A) 1178 | ,0x53B => array(0x56B), 0x53C => array(0x56C), 0x53D => array(0x56D) 1179 | ,0x53E => array(0x56E), 0x53F => array(0x56F), 0x540 => array(0x570) 1180 | ,0x541 => array(0x571), 0x542 => array(0x572), 0x543 => array(0x573) 1181 | ,0x544 => array(0x574), 0x545 => array(0x575), 0x546 => array(0x576) 1182 | ,0x547 => array(0x577), 0x548 => array(0x578), 0x549 => array(0x579) 1183 | ,0x54A => array(0x57A), 0x54B => array(0x57B), 0x54C => array(0x57C) 1184 | ,0x54D => array(0x57D), 0x54E => array(0x57E), 0x54F => array(0x57F) 1185 | ,0x550 => array(0x580), 0x551 => array(0x581), 0x552 => array(0x582) 1186 | ,0x553 => array(0x583), 0x554 => array(0x584), 0x555 => array(0x585) 1187 | ,0x556 => array(0x586), 0x587 => array(0x565, 0x582), 0xE33 => array(0xE4D, 0xE32) 1188 | ,0x1E00 => array(0x1E01), 0x1E02 => array(0x1E03), 0x1E04 => array(0x1E05) 1189 | ,0x1E06 => array(0x1E07), 0x1E08 => array(0x1E09), 0x1E0A => array(0x1E0B) 1190 | ,0x1E0C => array(0x1E0D), 0x1E0E => array(0x1E0F), 0x1E10 => array(0x1E11) 1191 | ,0x1E12 => array(0x1E13), 0x1E14 => array(0x1E15), 0x1E16 => array(0x1E17) 1192 | ,0x1E18 => array(0x1E19), 0x1E1A => array(0x1E1B), 0x1E1C => array(0x1E1D) 1193 | ,0x1E1E => array(0x1E1F), 0x1E20 => array(0x1E21), 0x1E22 => array(0x1E23) 1194 | ,0x1E24 => array(0x1E25), 0x1E26 => array(0x1E27), 0x1E28 => array(0x1E29) 1195 | ,0x1E2A => array(0x1E2B), 0x1E2C => array(0x1E2D), 0x1E2E => array(0x1E2F) 1196 | ,0x1E30 => array(0x1E31), 0x1E32 => array(0x1E33), 0x1E34 => array(0x1E35) 1197 | ,0x1E36 => array(0x1E37), 0x1E38 => array(0x1E39), 0x1E3A => array(0x1E3B) 1198 | ,0x1E3C => array(0x1E3D), 0x1E3E => array(0x1E3F), 0x1E40 => array(0x1E41) 1199 | ,0x1E42 => array(0x1E43), 0x1E44 => array(0x1E45), 0x1E46 => array(0x1E47) 1200 | ,0x1E48 => array(0x1E49), 0x1E4A => array(0x1E4B), 0x1E4C => array(0x1E4D) 1201 | ,0x1E4E => array(0x1E4F), 0x1E50 => array(0x1E51), 0x1E52 => array(0x1E53) 1202 | ,0x1E54 => array(0x1E55), 0x1E56 => array(0x1E57), 0x1E58 => array(0x1E59) 1203 | ,0x1E5A => array(0x1E5B), 0x1E5C => array(0x1E5D), 0x1E5E => array(0x1E5F) 1204 | ,0x1E60 => array(0x1E61), 0x1E62 => array(0x1E63), 0x1E64 => array(0x1E65) 1205 | ,0x1E66 => array(0x1E67), 0x1E68 => array(0x1E69), 0x1E6A => array(0x1E6B) 1206 | ,0x1E6C => array(0x1E6D), 0x1E6E => array(0x1E6F), 0x1E70 => array(0x1E71) 1207 | ,0x1E72 => array(0x1E73), 0x1E74 => array(0x1E75), 0x1E76 => array(0x1E77) 1208 | ,0x1E78 => array(0x1E79), 0x1E7A => array(0x1E7B), 0x1E7C => array(0x1E7D) 1209 | ,0x1E7E => array(0x1E7F), 0x1E80 => array(0x1E81), 0x1E82 => array(0x1E83) 1210 | ,0x1E84 => array(0x1E85), 0x1E86 => array(0x1E87), 0x1E88 => array(0x1E89) 1211 | ,0x1E8A => array(0x1E8B), 0x1E8C => array(0x1E8D), 0x1E8E => array(0x1E8F) 1212 | ,0x1E90 => array(0x1E91), 0x1E92 => array(0x1E93), 0x1E94 => array(0x1E95) 1213 | ,0x1E96 => array(0x68, 0x331), 0x1E97 => array(0x74, 0x308), 0x1E98 => array(0x77, 0x30A) 1214 | ,0x1E99 => array(0x79, 0x30A), 0x1E9A => array(0x61, 0x2BE), 0x1E9B => array(0x1E61) 1215 | ,0x1EA0 => array(0x1EA1), 0x1EA2 => array(0x1EA3), 0x1EA4 => array(0x1EA5) 1216 | ,0x1EA6 => array(0x1EA7), 0x1EA8 => array(0x1EA9), 0x1EAA => array(0x1EAB) 1217 | ,0x1EAC => array(0x1EAD), 0x1EAE => array(0x1EAF), 0x1EB0 => array(0x1EB1) 1218 | ,0x1EB2 => array(0x1EB3), 0x1EB4 => array(0x1EB5), 0x1EB6 => array(0x1EB7) 1219 | ,0x1EB8 => array(0x1EB9), 0x1EBA => array(0x1EBB), 0x1EBC => array(0x1EBD) 1220 | ,0x1EBE => array(0x1EBF), 0x1EC0 => array(0x1EC1), 0x1EC2 => array(0x1EC3) 1221 | ,0x1EC4 => array(0x1EC5), 0x1EC6 => array(0x1EC7), 0x1EC8 => array(0x1EC9) 1222 | ,0x1ECA => array(0x1ECB), 0x1ECC => array(0x1ECD), 0x1ECE => array(0x1ECF) 1223 | ,0x1ED0 => array(0x1ED1), 0x1ED2 => array(0x1ED3), 0x1ED4 => array(0x1ED5) 1224 | ,0x1ED6 => array(0x1ED7), 0x1ED8 => array(0x1ED9), 0x1EDA => array(0x1EDB) 1225 | ,0x1EDC => array(0x1EDD), 0x1EDE => array(0x1EDF), 0x1EE0 => array(0x1EE1) 1226 | ,0x1EE2 => array(0x1EE3), 0x1EE4 => array(0x1EE5), 0x1EE6 => array(0x1EE7) 1227 | ,0x1EE8 => array(0x1EE9), 0x1EEA => array(0x1EEB), 0x1EEC => array(0x1EED) 1228 | ,0x1EEE => array(0x1EEF), 0x1EF0 => array(0x1EF1), 0x1EF2 => array(0x1EF3) 1229 | ,0x1EF4 => array(0x1EF5), 0x1EF6 => array(0x1EF7), 0x1EF8 => array(0x1EF9) 1230 | ,0x1F08 => array(0x1F00), 0x1F09 => array(0x1F01), 0x1F0A => array(0x1F02) 1231 | ,0x1F0B => array(0x1F03), 0x1F0C => array(0x1F04), 0x1F0D => array(0x1F05) 1232 | ,0x1F0E => array(0x1F06), 0x1F0F => array(0x1F07), 0x1F18 => array(0x1F10) 1233 | ,0x1F19 => array(0x1F11), 0x1F1A => array(0x1F12), 0x1F1B => array(0x1F13) 1234 | ,0x1F1C => array(0x1F14), 0x1F1D => array(0x1F15), 0x1F28 => array(0x1F20) 1235 | ,0x1F29 => array(0x1F21), 0x1F2A => array(0x1F22), 0x1F2B => array(0x1F23) 1236 | ,0x1F2C => array(0x1F24), 0x1F2D => array(0x1F25), 0x1F2E => array(0x1F26) 1237 | ,0x1F2F => array(0x1F27), 0x1F38 => array(0x1F30), 0x1F39 => array(0x1F31) 1238 | ,0x1F3A => array(0x1F32), 0x1F3B => array(0x1F33), 0x1F3C => array(0x1F34) 1239 | ,0x1F3D => array(0x1F35), 0x1F3E => array(0x1F36), 0x1F3F => array(0x1F37) 1240 | ,0x1F48 => array(0x1F40), 0x1F49 => array(0x1F41), 0x1F4A => array(0x1F42) 1241 | ,0x1F4B => array(0x1F43), 0x1F4C => array(0x1F44), 0x1F4D => array(0x1F45) 1242 | ,0x1F50 => array(0x3C5, 0x313), 0x1F52 => array(0x3C5, 0x313, 0x300) 1243 | ,0x1F54 => array(0x3C5, 0x313, 0x301), 0x1F56 => array(0x3C5, 0x313, 0x342) 1244 | ,0x1F59 => array(0x1F51), 0x1F5B => array(0x1F53), 0x1F5D => array(0x1F55) 1245 | ,0x1F5F => array(0x1F57), 0x1F68 => array(0x1F60), 0x1F69 => array(0x1F61) 1246 | ,0x1F6A => array(0x1F62), 0x1F6B => array(0x1F63), 0x1F6C => array(0x1F64) 1247 | ,0x1F6D => array(0x1F65), 0x1F6E => array(0x1F66), 0x1F6F => array(0x1F67) 1248 | ,0x1F80 => array(0x1F00, 0x3B9), 0x1F81 => array(0x1F01, 0x3B9) 1249 | ,0x1F82 => array(0x1F02, 0x3B9), 0x1F83 => array(0x1F03, 0x3B9) 1250 | ,0x1F84 => array(0x1F04, 0x3B9), 0x1F85 => array(0x1F05, 0x3B9) 1251 | ,0x1F86 => array(0x1F06, 0x3B9), 0x1F87 => array(0x1F07, 0x3B9) 1252 | ,0x1F88 => array(0x1F00, 0x3B9), 0x1F89 => array(0x1F01, 0x3B9) 1253 | ,0x1F8A => array(0x1F02, 0x3B9), 0x1F8B => array(0x1F03, 0x3B9) 1254 | ,0x1F8C => array(0x1F04, 0x3B9), 0x1F8D => array(0x1F05, 0x3B9) 1255 | ,0x1F8E => array(0x1F06, 0x3B9), 0x1F8F => array(0x1F07, 0x3B9) 1256 | ,0x1F90 => array(0x1F20, 0x3B9), 0x1F91 => array(0x1F21, 0x3B9) 1257 | ,0x1F92 => array(0x1F22, 0x3B9), 0x1F93 => array(0x1F23, 0x3B9) 1258 | ,0x1F94 => array(0x1F24, 0x3B9), 0x1F95 => array(0x1F25, 0x3B9) 1259 | ,0x1F96 => array(0x1F26, 0x3B9), 0x1F97 => array(0x1F27, 0x3B9) 1260 | ,0x1F98 => array(0x1F20, 0x3B9), 0x1F99 => array(0x1F21, 0x3B9) 1261 | ,0x1F9A => array(0x1F22, 0x3B9), 0x1F9B => array(0x1F23, 0x3B9) 1262 | ,0x1F9C => array(0x1F24, 0x3B9), 0x1F9D => array(0x1F25, 0x3B9) 1263 | ,0x1F9E => array(0x1F26, 0x3B9), 0x1F9F => array(0x1F27, 0x3B9) 1264 | ,0x1FA0 => array(0x1F60, 0x3B9), 0x1FA1 => array(0x1F61, 0x3B9) 1265 | ,0x1FA2 => array(0x1F62, 0x3B9), 0x1FA3 => array(0x1F63, 0x3B9) 1266 | ,0x1FA4 => array(0x1F64, 0x3B9), 0x1FA5 => array(0x1F65, 0x3B9) 1267 | ,0x1FA6 => array(0x1F66, 0x3B9), 0x1FA7 => array(0x1F67, 0x3B9) 1268 | ,0x1FA8 => array(0x1F60, 0x3B9), 0x1FA9 => array(0x1F61, 0x3B9) 1269 | ,0x1FAA => array(0x1F62, 0x3B9), 0x1FAB => array(0x1F63, 0x3B9) 1270 | ,0x1FAC => array(0x1F64, 0x3B9), 0x1FAD => array(0x1F65, 0x3B9) 1271 | ,0x1FAE => array(0x1F66, 0x3B9), 0x1FAF => array(0x1F67, 0x3B9) 1272 | ,0x1FB2 => array(0x1F70, 0x3B9), 0x1FB3 => array(0x3B1, 0x3B9) 1273 | ,0x1FB4 => array(0x3AC, 0x3B9), 0x1FB6 => array(0x3B1, 0x342) 1274 | ,0x1FB7 => array(0x3B1, 0x342, 0x3B9), 0x1FB8 => array(0x1FB0) 1275 | ,0x1FB9 => array(0x1FB1), 0x1FBA => array(0x1F70), 0x1FBB => array(0x1F71) 1276 | ,0x1FBC => array(0x3B1, 0x3B9), 0x1FBE => array(0x3B9) 1277 | ,0x1FC2 => array(0x1F74, 0x3B9), 0x1FC3 => array(0x3B7, 0x3B9) 1278 | ,0x1FC4 => array(0x3AE, 0x3B9), 0x1FC6 => array(0x3B7, 0x342) 1279 | ,0x1FC7 => array(0x3B7, 0x342, 0x3B9), 0x1FC8 => array(0x1F72) 1280 | ,0x1FC9 => array(0x1F73), 0x1FCA => array(0x1F74), 0x1FCB => array(0x1F75) 1281 | ,0x1FCC => array(0x3B7, 0x3B9), 0x1FD2 => array(0x3B9, 0x308, 0x300) 1282 | ,0x1FD3 => array(0x3B9, 0x308, 0x301), 0x1FD6 => array(0x3B9, 0x342) 1283 | ,0x1FD7 => array(0x3B9, 0x308, 0x342), 0x1FD8 => array(0x1FD0) 1284 | ,0x1FD9 => array(0x1FD1), 0x1FDA => array(0x1F76) 1285 | ,0x1FDB => array(0x1F77), 0x1FE2 => array(0x3C5, 0x308, 0x300) 1286 | ,0x1FE3 => array(0x3C5, 0x308, 0x301), 0x1FE4 => array(0x3C1, 0x313) 1287 | ,0x1FE6 => array(0x3C5, 0x342), 0x1FE7 => array(0x3C5, 0x308, 0x342) 1288 | ,0x1FE8 => array(0x1FE0), 0x1FE9 => array(0x1FE1) 1289 | ,0x1FEA => array(0x1F7A), 0x1FEB => array(0x1F7B) 1290 | ,0x1FEC => array(0x1FE5), 0x1FF2 => array(0x1F7C, 0x3B9) 1291 | ,0x1FF3 => array(0x3C9, 0x3B9), 0x1FF4 => array(0x3CE, 0x3B9) 1292 | ,0x1FF6 => array(0x3C9, 0x342), 0x1FF7 => array(0x3C9, 0x342, 0x3B9) 1293 | ,0x1FF8 => array(0x1F78), 0x1FF9 => array(0x1F79), 0x1FFA => array(0x1F7C) 1294 | ,0x1FFB => array(0x1F7D), 0x1FFC => array(0x3C9, 0x3B9) 1295 | ,0x20A8 => array(0x72, 0x73), 0x2102 => array(0x63), 0x2103 => array(0xB0, 0x63) 1296 | ,0x2107 => array(0x25B), 0x2109 => array(0xB0, 0x66), 0x210B => array(0x68) 1297 | ,0x210C => array(0x68), 0x210D => array(0x68), 0x2110 => array(0x69) 1298 | ,0x2111 => array(0x69), 0x2112 => array(0x6C), 0x2115 => array(0x6E) 1299 | ,0x2116 => array(0x6E, 0x6F), 0x2119 => array(0x70), 0x211A => array(0x71) 1300 | ,0x211B => array(0x72), 0x211C => array(0x72), 0x211D => array(0x72) 1301 | ,0x2120 => array(0x73, 0x6D), 0x2121 => array(0x74, 0x65, 0x6C) 1302 | ,0x2122 => array(0x74, 0x6D), 0x2124 => array(0x7A), 0x2126 => array(0x3C9) 1303 | ,0x2128 => array(0x7A), 0x212A => array(0x6B), 0x212B => array(0xE5) 1304 | ,0x212C => array(0x62), 0x212D => array(0x63), 0x2130 => array(0x65) 1305 | ,0x2131 => array(0x66), 0x2133 => array(0x6D), 0x213E => array(0x3B3) 1306 | ,0x213F => array(0x3C0), 0x2145 => array(0x64) ,0x2160 => array(0x2170) 1307 | ,0x2161 => array(0x2171), 0x2162 => array(0x2172), 0x2163 => array(0x2173) 1308 | ,0x2164 => array(0x2174), 0x2165 => array(0x2175), 0x2166 => array(0x2176) 1309 | ,0x2167 => array(0x2177), 0x2168 => array(0x2178), 0x2169 => array(0x2179) 1310 | ,0x216A => array(0x217A), 0x216B => array(0x217B), 0x216C => array(0x217C) 1311 | ,0x216D => array(0x217D), 0x216E => array(0x217E), 0x216F => array(0x217F) 1312 | ,0x24B6 => array(0x24D0), 0x24B7 => array(0x24D1), 0x24B8 => array(0x24D2) 1313 | ,0x24B9 => array(0x24D3), 0x24BA => array(0x24D4), 0x24BB => array(0x24D5) 1314 | ,0x24BC => array(0x24D6), 0x24BD => array(0x24D7), 0x24BE => array(0x24D8) 1315 | ,0x24BF => array(0x24D9), 0x24C0 => array(0x24DA), 0x24C1 => array(0x24DB) 1316 | ,0x24C2 => array(0x24DC), 0x24C3 => array(0x24DD), 0x24C4 => array(0x24DE) 1317 | ,0x24C5 => array(0x24DF), 0x24C6 => array(0x24E0), 0x24C7 => array(0x24E1) 1318 | ,0x24C8 => array(0x24E2), 0x24C9 => array(0x24E3), 0x24CA => array(0x24E4) 1319 | ,0x24CB => array(0x24E5), 0x24CC => array(0x24E6), 0x24CD => array(0x24E7) 1320 | ,0x24CE => array(0x24E8), 0x24CF => array(0x24E9), 0x3371 => array(0x68, 0x70, 0x61) 1321 | ,0x3373 => array(0x61, 0x75), 0x3375 => array(0x6F, 0x76) 1322 | ,0x3380 => array(0x70, 0x61), 0x3381 => array(0x6E, 0x61) 1323 | ,0x3382 => array(0x3BC, 0x61), 0x3383 => array(0x6D, 0x61) 1324 | ,0x3384 => array(0x6B, 0x61), 0x3385 => array(0x6B, 0x62) 1325 | ,0x3386 => array(0x6D, 0x62), 0x3387 => array(0x67, 0x62) 1326 | ,0x338A => array(0x70, 0x66), 0x338B => array(0x6E, 0x66) 1327 | ,0x338C => array(0x3BC, 0x66), 0x3390 => array(0x68, 0x7A) 1328 | ,0x3391 => array(0x6B, 0x68, 0x7A), 0x3392 => array(0x6D, 0x68, 0x7A) 1329 | ,0x3393 => array(0x67, 0x68, 0x7A), 0x3394 => array(0x74, 0x68, 0x7A) 1330 | ,0x33A9 => array(0x70, 0x61), 0x33AA => array(0x6B, 0x70, 0x61) 1331 | ,0x33AB => array(0x6D, 0x70, 0x61), 0x33AC => array(0x67, 0x70, 0x61) 1332 | ,0x33B4 => array(0x70, 0x76), 0x33B5 => array(0x6E, 0x76) 1333 | ,0x33B6 => array(0x3BC, 0x76), 0x33B7 => array(0x6D, 0x76) 1334 | ,0x33B8 => array(0x6B, 0x76), 0x33B9 => array(0x6D, 0x76) 1335 | ,0x33BA => array(0x70, 0x77), 0x33BB => array(0x6E, 0x77) 1336 | ,0x33BC => array(0x3BC, 0x77), 0x33BD => array(0x6D, 0x77) 1337 | ,0x33BE => array(0x6B, 0x77), 0x33BF => array(0x6D, 0x77) 1338 | ,0x33C0 => array(0x6B, 0x3C9), 0x33C1 => array(0x6D, 0x3C9) /* 1339 | ,0x33C2 => array(0x61, 0x2E, 0x6D, 0x2E) */ 1340 | ,0x33C3 => array(0x62, 0x71), 0x33C6 => array(0x63, 0x2215, 0x6B, 0x67) 1341 | ,0x33C7 => array(0x63, 0x6F, 0x2E), 0x33C8 => array(0x64, 0x62) 1342 | ,0x33C9 => array(0x67, 0x79), 0x33CB => array(0x68, 0x70) 1343 | ,0x33CD => array(0x6B, 0x6B), 0x33CE => array(0x6B, 0x6D) 1344 | ,0x33D7 => array(0x70, 0x68), 0x33D9 => array(0x70, 0x70, 0x6D) 1345 | ,0x33DA => array(0x70, 0x72), 0x33DC => array(0x73, 0x76) 1346 | ,0x33DD => array(0x77, 0x62), 0xFB00 => array(0x66, 0x66) 1347 | ,0xFB01 => array(0x66, 0x69), 0xFB02 => array(0x66, 0x6C) 1348 | ,0xFB03 => array(0x66, 0x66, 0x69), 0xFB04 => array(0x66, 0x66, 0x6C) 1349 | ,0xFB05 => array(0x73, 0x74), 0xFB06 => array(0x73, 0x74) 1350 | ,0xFB13 => array(0x574, 0x576), 0xFB14 => array(0x574, 0x565) 1351 | ,0xFB15 => array(0x574, 0x56B), 0xFB16 => array(0x57E, 0x576) 1352 | ,0xFB17 => array(0x574, 0x56D), 0xFF21 => array(0xFF41) 1353 | ,0xFF22 => array(0xFF42), 0xFF23 => array(0xFF43), 0xFF24 => array(0xFF44) 1354 | ,0xFF25 => array(0xFF45), 0xFF26 => array(0xFF46), 0xFF27 => array(0xFF47) 1355 | ,0xFF28 => array(0xFF48), 0xFF29 => array(0xFF49), 0xFF2A => array(0xFF4A) 1356 | ,0xFF2B => array(0xFF4B), 0xFF2C => array(0xFF4C), 0xFF2D => array(0xFF4D) 1357 | ,0xFF2E => array(0xFF4E), 0xFF2F => array(0xFF4F), 0xFF30 => array(0xFF50) 1358 | ,0xFF31 => array(0xFF51), 0xFF32 => array(0xFF52), 0xFF33 => array(0xFF53) 1359 | ,0xFF34 => array(0xFF54), 0xFF35 => array(0xFF55), 0xFF36 => array(0xFF56) 1360 | ,0xFF37 => array(0xFF57), 0xFF38 => array(0xFF58), 0xFF39 => array(0xFF59) 1361 | ,0xFF3A => array(0xFF5A), 0x10400 => array(0x10428), 0x10401 => array(0x10429) 1362 | ,0x10402 => array(0x1042A), 0x10403 => array(0x1042B), 0x10404 => array(0x1042C) 1363 | ,0x10405 => array(0x1042D), 0x10406 => array(0x1042E), 0x10407 => array(0x1042F) 1364 | ,0x10408 => array(0x10430), 0x10409 => array(0x10431), 0x1040A => array(0x10432) 1365 | ,0x1040B => array(0x10433), 0x1040C => array(0x10434), 0x1040D => array(0x10435) 1366 | ,0x1040E => array(0x10436), 0x1040F => array(0x10437), 0x10410 => array(0x10438) 1367 | ,0x10411 => array(0x10439), 0x10412 => array(0x1043A), 0x10413 => array(0x1043B) 1368 | ,0x10414 => array(0x1043C), 0x10415 => array(0x1043D), 0x10416 => array(0x1043E) 1369 | ,0x10417 => array(0x1043F), 0x10418 => array(0x10440), 0x10419 => array(0x10441) 1370 | ,0x1041A => array(0x10442), 0x1041B => array(0x10443), 0x1041C => array(0x10444) 1371 | ,0x1041D => array(0x10445), 0x1041E => array(0x10446), 0x1041F => array(0x10447) 1372 | ,0x10420 => array(0x10448), 0x10421 => array(0x10449), 0x10422 => array(0x1044A) 1373 | ,0x10423 => array(0x1044B), 0x10424 => array(0x1044C), 0x10425 => array(0x1044D) 1374 | ,0x1D400 => array(0x61), 0x1D401 => array(0x62), 0x1D402 => array(0x63) 1375 | ,0x1D403 => array(0x64), 0x1D404 => array(0x65), 0x1D405 => array(0x66) 1376 | ,0x1D406 => array(0x67), 0x1D407 => array(0x68), 0x1D408 => array(0x69) 1377 | ,0x1D409 => array(0x6A), 0x1D40A => array(0x6B), 0x1D40B => array(0x6C) 1378 | ,0x1D40C => array(0x6D), 0x1D40D => array(0x6E), 0x1D40E => array(0x6F) 1379 | ,0x1D40F => array(0x70), 0x1D410 => array(0x71), 0x1D411 => array(0x72) 1380 | ,0x1D412 => array(0x73), 0x1D413 => array(0x74), 0x1D414 => array(0x75) 1381 | ,0x1D415 => array(0x76), 0x1D416 => array(0x77), 0x1D417 => array(0x78) 1382 | ,0x1D418 => array(0x79), 0x1D419 => array(0x7A), 0x1D434 => array(0x61) 1383 | ,0x1D435 => array(0x62), 0x1D436 => array(0x63), 0x1D437 => array(0x64) 1384 | ,0x1D438 => array(0x65), 0x1D439 => array(0x66), 0x1D43A => array(0x67) 1385 | ,0x1D43B => array(0x68), 0x1D43C => array(0x69), 0x1D43D => array(0x6A) 1386 | ,0x1D43E => array(0x6B), 0x1D43F => array(0x6C), 0x1D440 => array(0x6D) 1387 | ,0x1D441 => array(0x6E), 0x1D442 => array(0x6F), 0x1D443 => array(0x70) 1388 | ,0x1D444 => array(0x71), 0x1D445 => array(0x72), 0x1D446 => array(0x73) 1389 | ,0x1D447 => array(0x74), 0x1D448 => array(0x75), 0x1D449 => array(0x76) 1390 | ,0x1D44A => array(0x77), 0x1D44B => array(0x78), 0x1D44C => array(0x79) 1391 | ,0x1D44D => array(0x7A), 0x1D468 => array(0x61), 0x1D469 => array(0x62) 1392 | ,0x1D46A => array(0x63), 0x1D46B => array(0x64), 0x1D46C => array(0x65) 1393 | ,0x1D46D => array(0x66), 0x1D46E => array(0x67), 0x1D46F => array(0x68) 1394 | ,0x1D470 => array(0x69), 0x1D471 => array(0x6A), 0x1D472 => array(0x6B) 1395 | ,0x1D473 => array(0x6C), 0x1D474 => array(0x6D), 0x1D475 => array(0x6E) 1396 | ,0x1D476 => array(0x6F), 0x1D477 => array(0x70), 0x1D478 => array(0x71) 1397 | ,0x1D479 => array(0x72), 0x1D47A => array(0x73), 0x1D47B => array(0x74) 1398 | ,0x1D47C => array(0x75), 0x1D47D => array(0x76), 0x1D47E => array(0x77) 1399 | ,0x1D47F => array(0x78), 0x1D480 => array(0x79), 0x1D481 => array(0x7A) 1400 | ,0x1D49C => array(0x61), 0x1D49E => array(0x63), 0x1D49F => array(0x64) 1401 | ,0x1D4A2 => array(0x67), 0x1D4A5 => array(0x6A), 0x1D4A6 => array(0x6B) 1402 | ,0x1D4A9 => array(0x6E), 0x1D4AA => array(0x6F), 0x1D4AB => array(0x70) 1403 | ,0x1D4AC => array(0x71), 0x1D4AE => array(0x73), 0x1D4AF => array(0x74) 1404 | ,0x1D4B0 => array(0x75), 0x1D4B1 => array(0x76), 0x1D4B2 => array(0x77) 1405 | ,0x1D4B3 => array(0x78), 0x1D4B4 => array(0x79), 0x1D4B5 => array(0x7A) 1406 | ,0x1D4D0 => array(0x61), 0x1D4D1 => array(0x62), 0x1D4D2 => array(0x63) 1407 | ,0x1D4D3 => array(0x64), 0x1D4D4 => array(0x65), 0x1D4D5 => array(0x66) 1408 | ,0x1D4D6 => array(0x67), 0x1D4D7 => array(0x68), 0x1D4D8 => array(0x69) 1409 | ,0x1D4D9 => array(0x6A), 0x1D4DA => array(0x6B), 0x1D4DB => array(0x6C) 1410 | ,0x1D4DC => array(0x6D), 0x1D4DD => array(0x6E), 0x1D4DE => array(0x6F) 1411 | ,0x1D4DF => array(0x70), 0x1D4E0 => array(0x71), 0x1D4E1 => array(0x72) 1412 | ,0x1D4E2 => array(0x73), 0x1D4E3 => array(0x74), 0x1D4E4 => array(0x75) 1413 | ,0x1D4E5 => array(0x76), 0x1D4E6 => array(0x77), 0x1D4E7 => array(0x78) 1414 | ,0x1D4E8 => array(0x79), 0x1D4E9 => array(0x7A), 0x1D504 => array(0x61) 1415 | ,0x1D505 => array(0x62), 0x1D507 => array(0x64), 0x1D508 => array(0x65) 1416 | ,0x1D509 => array(0x66), 0x1D50A => array(0x67), 0x1D50D => array(0x6A) 1417 | ,0x1D50E => array(0x6B), 0x1D50F => array(0x6C), 0x1D510 => array(0x6D) 1418 | ,0x1D511 => array(0x6E), 0x1D512 => array(0x6F), 0x1D513 => array(0x70) 1419 | ,0x1D514 => array(0x71), 0x1D516 => array(0x73), 0x1D517 => array(0x74) 1420 | ,0x1D518 => array(0x75), 0x1D519 => array(0x76), 0x1D51A => array(0x77) 1421 | ,0x1D51B => array(0x78), 0x1D51C => array(0x79), 0x1D538 => array(0x61) 1422 | ,0x1D539 => array(0x62), 0x1D53B => array(0x64), 0x1D53C => array(0x65) 1423 | ,0x1D53D => array(0x66), 0x1D53E => array(0x67), 0x1D540 => array(0x69) 1424 | ,0x1D541 => array(0x6A), 0x1D542 => array(0x6B), 0x1D543 => array(0x6C) 1425 | ,0x1D544 => array(0x6D), 0x1D546 => array(0x6F), 0x1D54A => array(0x73) 1426 | ,0x1D54B => array(0x74), 0x1D54C => array(0x75), 0x1D54D => array(0x76) 1427 | ,0x1D54E => array(0x77), 0x1D54F => array(0x78), 0x1D550 => array(0x79) 1428 | ,0x1D56C => array(0x61), 0x1D56D => array(0x62), 0x1D56E => array(0x63) 1429 | ,0x1D56F => array(0x64), 0x1D570 => array(0x65), 0x1D571 => array(0x66) 1430 | ,0x1D572 => array(0x67), 0x1D573 => array(0x68), 0x1D574 => array(0x69) 1431 | ,0x1D575 => array(0x6A), 0x1D576 => array(0x6B), 0x1D577 => array(0x6C) 1432 | ,0x1D578 => array(0x6D), 0x1D579 => array(0x6E), 0x1D57A => array(0x6F) 1433 | ,0x1D57B => array(0x70), 0x1D57C => array(0x71), 0x1D57D => array(0x72) 1434 | ,0x1D57E => array(0x73), 0x1D57F => array(0x74), 0x1D580 => array(0x75) 1435 | ,0x1D581 => array(0x76), 0x1D582 => array(0x77), 0x1D583 => array(0x78) 1436 | ,0x1D584 => array(0x79), 0x1D585 => array(0x7A), 0x1D5A0 => array(0x61) 1437 | ,0x1D5A1 => array(0x62), 0x1D5A2 => array(0x63), 0x1D5A3 => array(0x64) 1438 | ,0x1D5A4 => array(0x65), 0x1D5A5 => array(0x66), 0x1D5A6 => array(0x67) 1439 | ,0x1D5A7 => array(0x68), 0x1D5A8 => array(0x69), 0x1D5A9 => array(0x6A) 1440 | ,0x1D5AA => array(0x6B), 0x1D5AB => array(0x6C), 0x1D5AC => array(0x6D) 1441 | ,0x1D5AD => array(0x6E), 0x1D5AE => array(0x6F), 0x1D5AF => array(0x70) 1442 | ,0x1D5B0 => array(0x71), 0x1D5B1 => array(0x72), 0x1D5B2 => array(0x73) 1443 | ,0x1D5B3 => array(0x74), 0x1D5B4 => array(0x75), 0x1D5B5 => array(0x76) 1444 | ,0x1D5B6 => array(0x77), 0x1D5B7 => array(0x78), 0x1D5B8 => array(0x79) 1445 | ,0x1D5B9 => array(0x7A), 0x1D5D4 => array(0x61), 0x1D5D5 => array(0x62) 1446 | ,0x1D5D6 => array(0x63), 0x1D5D7 => array(0x64), 0x1D5D8 => array(0x65) 1447 | ,0x1D5D9 => array(0x66), 0x1D5DA => array(0x67), 0x1D5DB => array(0x68) 1448 | ,0x1D5DC => array(0x69), 0x1D5DD => array(0x6A), 0x1D5DE => array(0x6B) 1449 | ,0x1D5DF => array(0x6C), 0x1D5E0 => array(0x6D), 0x1D5E1 => array(0x6E) 1450 | ,0x1D5E2 => array(0x6F), 0x1D5E3 => array(0x70), 0x1D5E4 => array(0x71) 1451 | ,0x1D5E5 => array(0x72), 0x1D5E6 => array(0x73), 0x1D5E7 => array(0x74) 1452 | ,0x1D5E8 => array(0x75), 0x1D5E9 => array(0x76), 0x1D5EA => array(0x77) 1453 | ,0x1D5EB => array(0x78), 0x1D5EC => array(0x79), 0x1D5ED => array(0x7A) 1454 | ,0x1D608 => array(0x61), 0x1D609 => array(0x62) ,0x1D60A => array(0x63) 1455 | ,0x1D60B => array(0x64), 0x1D60C => array(0x65), 0x1D60D => array(0x66) 1456 | ,0x1D60E => array(0x67), 0x1D60F => array(0x68), 0x1D610 => array(0x69) 1457 | ,0x1D611 => array(0x6A), 0x1D612 => array(0x6B), 0x1D613 => array(0x6C) 1458 | ,0x1D614 => array(0x6D), 0x1D615 => array(0x6E), 0x1D616 => array(0x6F) 1459 | ,0x1D617 => array(0x70), 0x1D618 => array(0x71), 0x1D619 => array(0x72) 1460 | ,0x1D61A => array(0x73), 0x1D61B => array(0x74), 0x1D61C => array(0x75) 1461 | ,0x1D61D => array(0x76), 0x1D61E => array(0x77), 0x1D61F => array(0x78) 1462 | ,0x1D620 => array(0x79), 0x1D621 => array(0x7A), 0x1D63C => array(0x61) 1463 | ,0x1D63D => array(0x62), 0x1D63E => array(0x63), 0x1D63F => array(0x64) 1464 | ,0x1D640 => array(0x65), 0x1D641 => array(0x66), 0x1D642 => array(0x67) 1465 | ,0x1D643 => array(0x68), 0x1D644 => array(0x69), 0x1D645 => array(0x6A) 1466 | ,0x1D646 => array(0x6B), 0x1D647 => array(0x6C), 0x1D648 => array(0x6D) 1467 | ,0x1D649 => array(0x6E), 0x1D64A => array(0x6F), 0x1D64B => array(0x70) 1468 | ,0x1D64C => array(0x71), 0x1D64D => array(0x72), 0x1D64E => array(0x73) 1469 | ,0x1D64F => array(0x74), 0x1D650 => array(0x75), 0x1D651 => array(0x76) 1470 | ,0x1D652 => array(0x77), 0x1D653 => array(0x78), 0x1D654 => array(0x79) 1471 | ,0x1D655 => array(0x7A), 0x1D670 => array(0x61), 0x1D671 => array(0x62) 1472 | ,0x1D672 => array(0x63), 0x1D673 => array(0x64), 0x1D674 => array(0x65) 1473 | ,0x1D675 => array(0x66), 0x1D676 => array(0x67), 0x1D677 => array(0x68) 1474 | ,0x1D678 => array(0x69), 0x1D679 => array(0x6A), 0x1D67A => array(0x6B) 1475 | ,0x1D67B => array(0x6C), 0x1D67C => array(0x6D), 0x1D67D => array(0x6E) 1476 | ,0x1D67E => array(0x6F), 0x1D67F => array(0x70), 0x1D680 => array(0x71) 1477 | ,0x1D681 => array(0x72), 0x1D682 => array(0x73), 0x1D683 => array(0x74) 1478 | ,0x1D684 => array(0x75), 0x1D685 => array(0x76), 0x1D686 => array(0x77) 1479 | ,0x1D687 => array(0x78), 0x1D688 => array(0x79), 0x1D689 => array(0x7A) 1480 | ,0x1D6A8 => array(0x3B1), 0x1D6A9 => array(0x3B2), 0x1D6AA => array(0x3B3) 1481 | ,0x1D6AB => array(0x3B4), 0x1D6AC => array(0x3B5), 0x1D6AD => array(0x3B6) 1482 | ,0x1D6AE => array(0x3B7), 0x1D6AF => array(0x3B8), 0x1D6B0 => array(0x3B9) 1483 | ,0x1D6B1 => array(0x3BA), 0x1D6B2 => array(0x3BB), 0x1D6B3 => array(0x3BC) 1484 | ,0x1D6B4 => array(0x3BD), 0x1D6B5 => array(0x3BE), 0x1D6B6 => array(0x3BF) 1485 | ,0x1D6B7 => array(0x3C0), 0x1D6B8 => array(0x3C1), 0x1D6B9 => array(0x3B8) 1486 | ,0x1D6BA => array(0x3C3), 0x1D6BB => array(0x3C4), 0x1D6BC => array(0x3C5) 1487 | ,0x1D6BD => array(0x3C6), 0x1D6BE => array(0x3C7), 0x1D6BF => array(0x3C8) 1488 | ,0x1D6C0 => array(0x3C9), 0x1D6D3 => array(0x3C3), 0x1D6E2 => array(0x3B1) 1489 | ,0x1D6E3 => array(0x3B2), 0x1D6E4 => array(0x3B3), 0x1D6E5 => array(0x3B4) 1490 | ,0x1D6E6 => array(0x3B5), 0x1D6E7 => array(0x3B6), 0x1D6E8 => array(0x3B7) 1491 | ,0x1D6E9 => array(0x3B8), 0x1D6EA => array(0x3B9), 0x1D6EB => array(0x3BA) 1492 | ,0x1D6EC => array(0x3BB), 0x1D6ED => array(0x3BC), 0x1D6EE => array(0x3BD) 1493 | ,0x1D6EF => array(0x3BE), 0x1D6F0 => array(0x3BF), 0x1D6F1 => array(0x3C0) 1494 | ,0x1D6F2 => array(0x3C1), 0x1D6F3 => array(0x3B8) ,0x1D6F4 => array(0x3C3) 1495 | ,0x1D6F5 => array(0x3C4), 0x1D6F6 => array(0x3C5), 0x1D6F7 => array(0x3C6) 1496 | ,0x1D6F8 => array(0x3C7), 0x1D6F9 => array(0x3C8) ,0x1D6FA => array(0x3C9) 1497 | ,0x1D70D => array(0x3C3), 0x1D71C => array(0x3B1), 0x1D71D => array(0x3B2) 1498 | ,0x1D71E => array(0x3B3), 0x1D71F => array(0x3B4), 0x1D720 => array(0x3B5) 1499 | ,0x1D721 => array(0x3B6), 0x1D722 => array(0x3B7), 0x1D723 => array(0x3B8) 1500 | ,0x1D724 => array(0x3B9), 0x1D725 => array(0x3BA), 0x1D726 => array(0x3BB) 1501 | ,0x1D727 => array(0x3BC), 0x1D728 => array(0x3BD), 0x1D729 => array(0x3BE) 1502 | ,0x1D72A => array(0x3BF), 0x1D72B => array(0x3C0), 0x1D72C => array(0x3C1) 1503 | ,0x1D72D => array(0x3B8), 0x1D72E => array(0x3C3), 0x1D72F => array(0x3C4) 1504 | ,0x1D730 => array(0x3C5), 0x1D731 => array(0x3C6), 0x1D732 => array(0x3C7) 1505 | ,0x1D733 => array(0x3C8), 0x1D734 => array(0x3C9), 0x1D747 => array(0x3C3) 1506 | ,0x1D756 => array(0x3B1), 0x1D757 => array(0x3B2), 0x1D758 => array(0x3B3) 1507 | ,0x1D759 => array(0x3B4), 0x1D75A => array(0x3B5), 0x1D75B => array(0x3B6) 1508 | ,0x1D75C => array(0x3B7), 0x1D75D => array(0x3B8), 0x1D75E => array(0x3B9) 1509 | ,0x1D75F => array(0x3BA), 0x1D760 => array(0x3BB), 0x1D761 => array(0x3BC) 1510 | ,0x1D762 => array(0x3BD), 0x1D763 => array(0x3BE), 0x1D764 => array(0x3BF) 1511 | ,0x1D765 => array(0x3C0), 0x1D766 => array(0x3C1), 0x1D767 => array(0x3B8) 1512 | ,0x1D768 => array(0x3C3), 0x1D769 => array(0x3C4), 0x1D76A => array(0x3C5) 1513 | ,0x1D76B => array(0x3C6), 0x1D76C => array(0x3C7), 0x1D76D => array(0x3C8) 1514 | ,0x1D76E => array(0x3C9), 0x1D781 => array(0x3C3), 0x1D790 => array(0x3B1) 1515 | ,0x1D791 => array(0x3B2), 0x1D792 => array(0x3B3), 0x1D793 => array(0x3B4) 1516 | ,0x1D794 => array(0x3B5), 0x1D795 => array(0x3B6), 0x1D796 => array(0x3B7) 1517 | ,0x1D797 => array(0x3B8), 0x1D798 => array(0x3B9), 0x1D799 => array(0x3BA) 1518 | ,0x1D79A => array(0x3BB), 0x1D79B => array(0x3BC), 0x1D79C => array(0x3BD) 1519 | ,0x1D79D => array(0x3BE), 0x1D79E => array(0x3BF), 0x1D79F => array(0x3C0) 1520 | ,0x1D7A0 => array(0x3C1), 0x1D7A1 => array(0x3B8), 0x1D7A2 => array(0x3C3) 1521 | ,0x1D7A3 => array(0x3C4), 0x1D7A4 => array(0x3C5), 0x1D7A5 => array(0x3C6) 1522 | ,0x1D7A6 => array(0x3C7), 0x1D7A7 => array(0x3C8), 0x1D7A8 => array(0x3C9) 1523 | ,0x1D7BB => array(0x3C3), 0x3F9 => array(0x3C3), 0x1D2C => array(0x61) 1524 | ,0x1D2D => array(0xE6), 0x1D2E => array(0x62), 0x1D30 => array(0x64) 1525 | ,0x1D31 => array(0x65), 0x1D32 => array(0x1DD), 0x1D33 => array(0x67) 1526 | ,0x1D34 => array(0x68), 0x1D35 => array(0x69), 0x1D36 => array(0x6A) 1527 | ,0x1D37 => array(0x6B), 0x1D38 => array(0x6C), 0x1D39 => array(0x6D) 1528 | ,0x1D3A => array(0x6E), 0x1D3C => array(0x6F), 0x1D3D => array(0x223) 1529 | ,0x1D3E => array(0x70), 0x1D3F => array(0x72), 0x1D40 => array(0x74) 1530 | ,0x1D41 => array(0x75), 0x1D42 => array(0x77), 0x213B => array(0x66, 0x61, 0x78) 1531 | ,0x3250 => array(0x70, 0x74, 0x65), 0x32CC => array(0x68, 0x67) 1532 | ,0x32CE => array(0x65, 0x76), 0x32CF => array(0x6C, 0x74, 0x64) 1533 | ,0x337A => array(0x69, 0x75), 0x33DE => array(0x76, 0x2215, 0x6D) 1534 | ,0x33DF => array(0x61, 0x2215, 0x6D) 1535 | ) 1536 | ,'norm_combcls' => array(0x334 => 1, 0x335 => 1, 0x336 => 1, 0x337 => 1 1537 | ,0x338 => 1, 0x93C => 7, 0x9BC => 7, 0xA3C => 7, 0xABC => 7 1538 | ,0xB3C => 7, 0xCBC => 7, 0x1037 => 7, 0x3099 => 8, 0x309A => 8 1539 | ,0x94D => 9, 0x9CD => 9, 0xA4D => 9, 0xACD => 9, 0xB4D => 9 1540 | ,0xBCD => 9, 0xC4D => 9, 0xCCD => 9, 0xD4D => 9, 0xDCA => 9 1541 | ,0xE3A => 9, 0xF84 => 9, 0x1039 => 9, 0x1714 => 9, 0x1734 => 9 1542 | ,0x17D2 => 9, 0x5B0 => 10, 0x5B1 => 11, 0x5B2 => 12, 0x5B3 => 13 1543 | ,0x5B4 => 14, 0x5B5 => 15, 0x5B6 => 16, 0x5B7 => 17, 0x5B8 => 18 1544 | ,0x5B9 => 19, 0x5BB => 20, 0x5Bc => 21, 0x5BD => 22, 0x5BF => 23 1545 | ,0x5C1 => 24, 0x5C2 => 25, 0xFB1E => 26, 0x64B => 27, 0x64C => 28 1546 | ,0x64D => 29, 0x64E => 30, 0x64F => 31, 0x650 => 32, 0x651 => 33 1547 | ,0x652 => 34, 0x670 => 35, 0x711 => 36, 0xC55 => 84, 0xC56 => 91 1548 | ,0xE38 => 103, 0xE39 => 103, 0xE48 => 107, 0xE49 => 107, 0xE4A => 107 1549 | ,0xE4B => 107, 0xEB8 => 118, 0xEB9 => 118, 0xEC8 => 122, 0xEC9 => 122 1550 | ,0xECA => 122, 0xECB => 122, 0xF71 => 129, 0xF72 => 130, 0xF7A => 130 1551 | ,0xF7B => 130, 0xF7C => 130, 0xF7D => 130, 0xF80 => 130, 0xF74 => 132 1552 | ,0x321 => 202, 0x322 => 202, 0x327 => 202, 0x328 => 202, 0x31B => 216 1553 | ,0xF39 => 216, 0x1D165 => 216, 0x1D166 => 216, 0x1D16E => 216, 0x1D16F => 216 1554 | ,0x1D170 => 216, 0x1D171 => 216, 0x1D172 => 216, 0x302A => 218, 0x316 => 220 1555 | ,0x317 => 220, 0x318 => 220, 0x319 => 220, 0x31C => 220, 0x31D => 220 1556 | ,0x31E => 220, 0x31F => 220, 0x320 => 220, 0x323 => 220, 0x324 => 220 1557 | ,0x325 => 220, 0x326 => 220, 0x329 => 220, 0x32A => 220, 0x32B => 220 1558 | ,0x32C => 220, 0x32D => 220, 0x32E => 220, 0x32F => 220, 0x330 => 220 1559 | ,0x331 => 220, 0x332 => 220, 0x333 => 220, 0x339 => 220, 0x33A => 220 1560 | ,0x33B => 220, 0x33C => 220, 0x347 => 220, 0x348 => 220, 0x349 => 220 1561 | ,0x34D => 220, 0x34E => 220, 0x353 => 220, 0x354 => 220, 0x355 => 220 1562 | ,0x356 => 220, 0x591 => 220, 0x596 => 220, 0x59B => 220, 0x5A3 => 220 1563 | ,0x5A4 => 220, 0x5A5 => 220, 0x5A6 => 220, 0x5A7 => 220, 0x5AA => 220 1564 | ,0x655 => 220, 0x656 => 220, 0x6E3 => 220, 0x6EA => 220, 0x6ED => 220 1565 | ,0x731 => 220, 0x734 => 220, 0x737 => 220, 0x738 => 220, 0x739 => 220 1566 | ,0x73B => 220, 0x73C => 220, 0x73E => 220, 0x742 => 220, 0x744 => 220 1567 | ,0x746 => 220, 0x748 => 220, 0x952 => 220, 0xF18 => 220, 0xF19 => 220 1568 | ,0xF35 => 220, 0xF37 => 220, 0xFC6 => 220, 0x193B => 220, 0x20E8 => 220 1569 | ,0x1D17B => 220, 0x1D17C => 220, 0x1D17D => 220, 0x1D17E => 220, 0x1D17F => 220 1570 | ,0x1D180 => 220, 0x1D181 => 220, 0x1D182 => 220, 0x1D18A => 220, 0x1D18B => 220 1571 | ,0x59A => 222, 0x5AD => 222, 0x1929 => 222, 0x302D => 222, 0x302E => 224 1572 | ,0x302F => 224, 0x1D16D => 226, 0x5AE => 228, 0x18A9 => 228, 0x302B => 228 1573 | ,0x300 => 230, 0x301 => 230, 0x302 => 230, 0x303 => 230, 0x304 => 230 1574 | ,0x305 => 230, 0x306 => 230, 0x307 => 230, 0x308 => 230, 0x309 => 230 1575 | ,0x30A => 230, 0x30B => 230, 0x30C => 230, 0x30D => 230, 0x30E => 230 1576 | ,0x30F => 230, 0x310 => 230, 0x311 => 230, 0x312 => 230, 0x313 => 230 1577 | ,0x314 => 230, 0x33D => 230, 0x33E => 230, 0x33F => 230, 0x340 => 230 1578 | ,0x341 => 230, 0x342 => 230, 0x343 => 230, 0x344 => 230, 0x346 => 230 1579 | ,0x34A => 230, 0x34B => 230, 0x34C => 230, 0x350 => 230, 0x351 => 230 1580 | ,0x352 => 230, 0x357 => 230, 0x363 => 230, 0x364 => 230, 0x365 => 230 1581 | ,0x366 => 230, 0x367 => 230, 0x368 => 230, 0x369 => 230, 0x36A => 230 1582 | ,0x36B => 230, 0x36C => 230, 0x36D => 230, 0x36E => 230, 0x36F => 230 1583 | ,0x483 => 230, 0x484 => 230, 0x485 => 230, 0x486 => 230, 0x592 => 230 1584 | ,0x593 => 230, 0x594 => 230, 0x595 => 230, 0x597 => 230, 0x598 => 230 1585 | ,0x599 => 230, 0x59C => 230, 0x59D => 230, 0x59E => 230, 0x59F => 230 1586 | ,0x5A0 => 230, 0x5A1 => 230, 0x5A8 => 230, 0x5A9 => 230, 0x5AB => 230 1587 | ,0x5AC => 230, 0x5AF => 230, 0x5C4 => 230, 0x610 => 230, 0x611 => 230 1588 | ,0x612 => 230, 0x613 => 230, 0x614 => 230, 0x615 => 230, 0x653 => 230 1589 | ,0x654 => 230, 0x657 => 230, 0x658 => 230, 0x6D6 => 230, 0x6D7 => 230 1590 | ,0x6D8 => 230, 0x6D9 => 230, 0x6DA => 230, 0x6DB => 230, 0x6DC => 230 1591 | ,0x6DF => 230, 0x6E0 => 230, 0x6E1 => 230, 0x6E2 => 230, 0x6E4 => 230 1592 | ,0x6E7 => 230, 0x6E8 => 230, 0x6EB => 230, 0x6EC => 230, 0x730 => 230 1593 | ,0x732 => 230, 0x733 => 230, 0x735 => 230, 0x736 => 230, 0x73A => 230 1594 | ,0x73D => 230, 0x73F => 230, 0x740 => 230, 0x741 => 230, 0x743 => 230 1595 | ,0x745 => 230, 0x747 => 230, 0x749 => 230, 0x74A => 230, 0x951 => 230 1596 | ,0x953 => 230, 0x954 => 230, 0xF82 => 230, 0xF83 => 230, 0xF86 => 230 1597 | ,0xF87 => 230, 0x170D => 230, 0x193A => 230, 0x20D0 => 230, 0x20D1 => 230 1598 | ,0x20D4 => 230, 0x20D5 => 230, 0x20D6 => 230, 0x20D7 => 230, 0x20DB => 230 1599 | ,0x20DC => 230, 0x20E1 => 230, 0x20E7 => 230, 0x20E9 => 230, 0xFE20 => 230 1600 | ,0xFE21 => 230, 0xFE22 => 230, 0xFE23 => 230, 0x1D185 => 230, 0x1D186 => 230 1601 | ,0x1D187 => 230, 0x1D189 => 230, 0x1D188 => 230, 0x1D1AA => 230, 0x1D1AB => 230 1602 | ,0x1D1AC => 230, 0x1D1AD => 230, 0x315 => 232, 0x31A => 232, 0x302C => 232 1603 | ,0x35F => 233, 0x362 => 233, 0x35D => 234, 0x35E => 234, 0x360 => 234 1604 | ,0x361 => 234, 0x345 => 240 1605 | ) 1606 | ); 1607 | } 1608 | ?> 1609 | -------------------------------------------------------------------------------- /Python/ConkyServerStatus/README.md: -------------------------------------------------------------------------------- 1 | #ConkyServerStatus 2 | Basic commandline script to be used with conky (http://conky.sourceforge.net/) to show a specific glesys 3 | servers status directly on your desktop. The below image shows what it currently looks like on my desktop. 4 | 5 | ![Screenshot](conky.png) 6 | 7 | 8 | ##Configuration 9 | The configuration file should be placed in the same directory you intend to run the program from. 10 | It must be named glesys.conf. 11 | 12 | [ConkyServerStatus] 13 | apikey = xxxxx 14 | apiuser = clXXXXX 15 | apiserver = vzXXXXX 16 | apiurl = https://api.glesys.com/server/status 17 | 18 | ###Bash script 19 | I use the following bash script placed inside my local bin/ to run the script. 20 | 21 | #!/bin/bash 22 | cd ~/code/python/GlesysAPI/Python/ConkyServerStatus/ 23 | python conkyserverstatus.py 24 | 25 | 26 | ###Conky Usage: 27 | Place the following snippet in your .conkyrc or equivalent file. It will update every 5 minutes. 28 | 29 | V P S 30 | ${hr} 31 | ${execpi 300 glesys_status} 32 | 33 | -------------------------------------------------------------------------------- /Python/ConkyServerStatus/conky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glesys/api-docs/68f5e44e2b83260779ac470b28176a127bfed9c5/Python/ConkyServerStatus/conky.png -------------------------------------------------------------------------------- /Python/ConkyServerStatus/conkyserverstatus.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # coding: UTF-8 4 | 5 | import json, codecs, os, sys, datetime 6 | import xml.etree.ElementTree as ET 7 | import httplib2 8 | import ConfigParser 9 | 10 | 11 | config = ConfigParser.ConfigParser() 12 | config.readfp(open('glesys.conf')) 13 | 14 | __APIKEY__ = config.get('ConkyServerStatus', 'apikey') 15 | __APIUSER__ = config.get('ConkyServerStatus', 'apiuser') 16 | __APISERVER__ = config.get('ConkyServerStatus', 'apiserver') 17 | __APIURL__ = config.get('ConkyServerStatus', 'apiurl') 18 | 19 | #print __APIKEY__, __APISERVER__, __APIUSER__ 20 | #print __APIURL__ 21 | 22 | # For some reason ssl_certification is failing at the moment.. 23 | try: 24 | h = httplib2.Http(disable_ssl_certificate_validation=True) 25 | h.add_credentials(__APIUSER__, __APIKEY__) 26 | resp, content = h.request(__APIURL__+"/serverid/"+__APISERVER__) 27 | except: 28 | print "No connection" 29 | exit 30 | 31 | # Bugfix for conky exec, python does not know which encoding to use and 32 | # will wrongly default to ascii 33 | sys.stdout = codecs.getwriter('utf-8')(sys.stdout) 34 | 35 | 36 | def printMetric(metricNode, metricName): 37 | usage = float(metricNode.find("usage").text) 38 | max = float(metricNode.find("max").text) 39 | print metricName+": $alignr", usage, " / ", max, metricNode.find("unit").text[0:2] 40 | print "${execbar echo \""+ str(usage * 100 / max) + "\"}" 41 | 42 | tree = ET.fromstring(content) 43 | for server in tree.findall("server"): 44 | print "Server name: $alignr", __APISERVER__ 45 | print "State: $alignr", server.find("state").text 46 | uptime = int(server.find("uptime").find("current").text) 47 | d = datetime.timedelta(seconds=uptime) 48 | print "Uptime: $alignr", d 49 | print 50 | 51 | cpu = server.find("cpu") 52 | print "CPUs: $alignr", cpu.find("usage").text + " / " + cpu.find("max").text, cpu.find("unit").text 53 | memory = server.find("memory") 54 | printMetric(memory, "Memory") 55 | transfer = server.find("transfer") 56 | printMetric(transfer, "Transfer") 57 | 58 | -------------------------------------------------------------------------------- /Python/ConkyServerStatus/glesys.conf: -------------------------------------------------------------------------------- 1 | [ConkyServerStatus] 2 | apikey = key 3 | apiuser = user 4 | apiserver = server 5 | apiurl = https://api.glesys.com/server/status 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is this? 2 | This is the place to go for [documentation](https://github.com/glesys/api-docs/wiki), [examples](https://github.com/glesys/api-docs/) and [support/feedback](https://github.com/glesys/api-docs/issues) for [GleSYS](http://www.glesys.se) API. 3 | 4 | You should start out by reading the [introduction](https://github.com/glesys/api-docs/wiki/Api-Introduction). 5 | 6 | # Where can I find documentation? 7 | The [documentation](https://github.com/glesys/api-docs/wiki) can be found right here on github in our [wiki](https://github.com/glesys/api-docs/wiki). It comes in the form of an [introduction](https://github.com/glesys/api-docs/wiki/Api-Introduction) and a full [documentation of all functions available in GleSYS API](https://github.com/glesys/api-docs/wiki/API-Documentation). This documentation has been automatically generated from the API. 8 | 9 | # Where can I find examples? 10 | The examples are available right here on our [github repo](https://github.com/glesys/api-docs/). They are broken up by scripting/programming language and if you browse around in the repository you will find that each example has its own description. 11 | 12 | Please feel free to contribute with more examples. You could either do a pull-request or send us an email to [support@glesys.se](mailto:support@glesys.se) 13 | 14 | Remember that all these examples are just examples. If you want to use any of these scripts in an production environment, its on your own responsibility. 15 | 16 | ## Current examples 17 | ### BASH 18 | [All bash examples](https://github.com/glesys/api-docs/tree/master/BASH) 19 | * [LocalMemUpgrade](https://github.com/glesys/api-docs/tree/master/BASH/LocalMemUpgrade) - Upgrade memory on a local server based on memoryusage. 20 | * [RemoteMemUpgrade](https://github.com/glesys/api-docs/tree/master/BASH/RemoteMemUpgrade) - Upgrade memory on a remote server based on memoryusage. 21 | * [RoundRobinLoadBalancer](https://github.com/glesys/api-docs/tree/master/BASH/RoundRobinLoadBalancer) - Basic round robin load balancer with availability monitoring. 22 | 23 | ### PHP 24 | [All PHP examples](https://github.com/glesys/api-docs/tree/master/PHP) 25 | * [InvoiceRSS](https://github.com/glesys/api-docs/tree/master/PHP/InvoiceRSS) - List invoices in a RSS-feed. 26 | * [MiniControlpanel](https://github.com/glesys/api-docs/tree/master/PHP/MiniControlpanel) - A miniature control panel. 27 | * [api_classes](https://github.com/glesys/api-docs/tree/master/PHP/api_classes) - PHP-classes for managing domains and email accounts. 28 | 29 | ### Ruby 30 | [All Ruby examples](https://github.com/glesys/api-docs/tree/master/Ruby) 31 | * [CreateDestroyList](https://github.com/glesys/api-docs/tree/master/Ruby/CreateDestroyList) - Create, Destroy and List servers. 32 | 33 | ## Python 34 | [All Python examples](https://github.com/glesys/api-docs/tree/master/Python) 35 | * [ConkyServerStatus](https://github.com/glesys/api-docs/tree/master/Python/ConkyServerStatus) - Commandline script to be used with [conky](http://conky.sourceforge.net/) to show a specific glesys servers status directly on your desktop 36 | 37 | # Are there any frameworks/toolboxes available? 38 | If you are looking for a framework to manage your GleSYS virtual servers take a look at the following projects: 39 | 40 | * [glesys-go](https://github.com/glesys/glesys-go) - An official client library written in go. 41 | * [docker-machine-driver-glesys](https://github.com/glesys/docker-machine-driver-glesys) - An official glesys api driver for docker machine 42 | * [fog](http://fog.io) - The Ruby cloud services library. 43 | * [jclouds](http://www.jclouds.org/) - API abstractions as java and clojure libraries. 44 | * [knife-glesys](https://github.com/smgt/knife-glesys) - A Knife addon for managing you GleSYS vps. Uses fog. 45 | * [glesys-bash-client](https://github.com/MrDaar/glesys-bash-client) - A bash client for interacting with the GleSYS API. 46 | * [glesys-dnshook](https://github.com/blastur/glesys-dnshook) - A hook for the Let's Encrypt ACME client dehydrated that allows you to use GleSYS DNS records to respond to dns-01 challenges. 47 | * [lexicon](https://github.com/AnalogJ/lexicon) - Manipulate DNS records on various DNS providers (including GleSYS) in a standardized/agnostic way. 48 | * [multipass](https://github.com/joelek/multipass) - Fully-automated certificate manager for NodeJS 16 with support for various DNS providers (including GleSYS). 49 | * [glesys-api-node](https://github.com/jwilsson/glesys-api-node) - A Node.js wrapper for the GleSYS API. 50 | 51 | If you know about any other frameworks that support the GleSYS API, please let us know! 52 | 53 | # Where can I get support? 54 | You can either [open a new issue here on github](https://github.com/glesys/api-docs/issues) or send us an email at [support@glesys.se](mailto:support@glesys.se) 55 | 56 | # License 57 | 58 | If not stated otherwise, the contents of this repository are distributed under the MIT license. 59 | -------------------------------------------------------------------------------- /Ruby/CreateDestroyList/GlesysAPI.rb: -------------------------------------------------------------------------------- 1 | # GleSYS API 2 | # 3 | # Author: Anton Lindström 4 | # http://github.com/antonlindstrom 5 | # 6 | # Example for the Glesys API 7 | class Glesys 8 | 9 | API_BASE = "https://api.glesys.com" 10 | 11 | # Give me the key and set format 12 | # 13 | # Returns nothing 14 | def initialize(id, key) 15 | require 'rubygems' 16 | require 'net/http' 17 | require 'net/https' 18 | require 'json' 19 | 20 | @keyid = id 21 | @apikey = key 22 | @format = "json" 23 | end 24 | 25 | # Accessor 26 | attr_reader :settings 27 | 28 | # Sending request to server, set data 29 | # 30 | # Returns the json response 31 | def request(path, post={}) 32 | url = URI.parse("#{API_BASE}/#{path}") 33 | post[:format] = @format 34 | 35 | http = Net::HTTP.new(url.host, url.port) 36 | http.use_ssl = true 37 | 38 | req = Net::HTTP::Post.new(url.path) 39 | req.basic_auth @keyid, @apikey 40 | 41 | req.set_form_data(post, '&') 42 | http.request(req).body 43 | 44 | rescue StandardError => err 45 | err 46 | end 47 | 48 | # Default settings 49 | # 50 | # Returns settings hash 51 | def settings 52 | @settings = { 53 | :datacenter => "Falkenberg", 54 | :platform => "OpenVZ", 55 | :hostname => "example#{rand(999)}.com", 56 | :templatename => "Debian 7.0 64-bit", 57 | :disksize => "10", 58 | :memorysize => "512", 59 | :cpucores => "1", 60 | :rootpassword => "p4ssw0rd", 61 | :transfer => "500" 62 | } 63 | end 64 | 65 | # Create a server 66 | def create(options = {:hostname => 'example.com'}) 67 | settings.merge!(options) 68 | 69 | resp_json = request("/server/create", settings) 70 | resp_hash = JSON.parse(resp_json) 71 | unless status_code(resp_hash) == 200 72 | raise resp_hash['response']['status']['text'] 73 | end 74 | server_id = resp_hash['response']['server']['serverid'] 75 | ip_list = resp_hash['response']['server']['iplist'].map{ |ip| ip["ipaddress"] } 76 | return { 77 | :server_id => server_id, 78 | :ip_list => ip_list 79 | } 80 | end 81 | 82 | # Destroy a server 83 | # 84 | # Returns serverid 85 | def destroy(id, keep_ip=false) 86 | params = { 87 | :serverid => id, 88 | :keepip => keep_ip ? 1 : 0 89 | } 90 | resp_json = request("/server/destroy", params) 91 | resp_hash = JSON.parse(resp_json) 92 | unless status_code(resp_hash) == 200 93 | raise resp_hash['response']['status']['text'] 94 | end 95 | return true 96 | end 97 | 98 | # Get IP from serverid 99 | # 100 | # Returns the first IP 101 | def get_ip(id) 102 | resp_json = request("/ip/listown", :serverid => id) 103 | resp_hash = JSON.parse(resp_json) 104 | unless status_code(resp_hash) == 200 105 | raise resp_hash['response']['status']['text'] 106 | end 107 | iplist = resp_hash['response']['iplist'] 108 | 109 | unless iplist.first.nil? 110 | iplist.first['ipaddress'] 111 | else 112 | nil 113 | end 114 | end 115 | 116 | # Lists all own servers 117 | # 118 | # Returns server response 119 | def list_servers 120 | resp_json = request("/server/list") 121 | resp_hash = JSON.parse(resp_json) 122 | unless status_code(resp_hash) == 200 123 | raise resp_hash['response']['status']['text'] 124 | end 125 | resp_hash['response']['servers'] 126 | end 127 | 128 | def status_code(resp) 129 | resp['response']['status']['code'].to_i 130 | end 131 | 132 | end 133 | 134 | require "pp" 135 | 136 | ## Define your credentials 137 | glesys_api_key = "my_super_secret_api_key" 138 | api = Glesys.new("clNNNNN", glesys_api_key) 139 | 140 | ## Create a server with default settings 141 | server = api.create(:hostname => "glesys.example.com") 142 | #pp server 143 | 144 | ## List all servers on your account 145 | api.list_servers.each do |server| 146 | puts "#{server['serverid']}\t#{api.get_ip(server['serverid'])}\t#{server['hostname']}\n" 147 | end 148 | 149 | ## Destroy server 150 | if api.destroy(server[:server_id]) 151 | puts "#{server[:server_id]} has been destroyed." 152 | end 153 | 154 | -------------------------------------------------------------------------------- /Ruby/CreateDestroyList/README.md: -------------------------------------------------------------------------------- 1 | #CreateDestroyList - GleSYS API Ruby example 2 | 3 | Author: [Anton Lindström](https://github.com/antonlindstrom) 4 | 5 | This example contains methods to create, destroy and list servers in the Glesys Cloud. 6 | 7 | The class is initialized and requires the neccesary files and is setting globals for the user id, api key, and response format. 8 | 9 | Requests to the API are performed in the request method. It is using the base path of api.glesys.se and takes the url as an argument. An example is `/server/create`. All other arguments (if any) are sent in a hash (post). The key in the hash is the name of the argument and the value is the value to be sent. The settings method is an example of some of the arguments that can be supplied. 10 | 11 | To create a server we use the `create` method where the hash called custom is supplied. The default value of hostname is `example.com`. The custom hash is then merged with the default settings so we will not have to supply all of the arguments. A request is sent and the response is parsed with JSON. The response is defined and the hash with values of serverid and ip are then returned. 12 | 13 | `destroy` deletes a server from the account. The method takes the arguments id and keep_ip. The return value of this method is (if successful) the serverid of the server that was destroyed. 14 | 15 | The method `get_ip` requests the IP of a server with the serverid of id. If an IP is assigned it will return that IP, otherwise it returns "NOT ASSIGNED". 16 | 17 | To list all the servers on your account use the method `list` which will return an array of servers. 18 | 19 | When using this script we first need to initialize the class with `api = Glesys.new(account_name, api_key)` and then use the methods within by calling `api.[method]` where method is `create`, `destroy`, `get_ip` or `list`. 20 | 21 | To call the api for a list of all servers with their serverid, ip and hostname it is possible with this script to iterate through the servers in the api.list( `a.list.each do |s|` in the example) and assign the response to output which we afterwards writes out. 22 | -------------------------------------------------------------------------------- /Ruby/README.md: -------------------------------------------------------------------------------- 1 | # Ruby examples for Glesys API 2 | 3 | This directory contains example for how to consume Glesys API. To simplify access include glesys.rb in your class for easy methods to make requests and parse the response. Look at domain/domain.rb for example of how to use. 4 | 5 | ## Fog ## 6 | 7 | Fog [https://github.com/fog/fog](https://github.com/fog/fog) is a Ruby library for managing virtual servers with a bunch of different providers and is compatible with the GleSYS API. If you are planning larger use of the GleSYS API via Ruby we gladly recommend that you use Fog. -------------------------------------------------------------------------------- /Ruby/domain/README.md: -------------------------------------------------------------------------------- 1 | #Domain management - GleSYS API Ruby example 2 | 3 | Author: [Marcel Asio](https://github.com/asio) 4 | 5 | This example provides methods for listing domains and domain records as well as updating records, it utilizes glesys.rb to simplify request and response handling. 6 | 7 | To use glesys.rb just include it in your class and set value of constant MODULE to one of the valid from the [API](https://github.com/GleSYS/API/wiki/Full-API-Documentation). This constant is used to build the request url by Glesys.request method. -------------------------------------------------------------------------------- /Ruby/domain/domain.rb: -------------------------------------------------------------------------------- 1 | # GleSYS API 2 | # 3 | # Author: Marcel Asio 4 | # http://github.com/asio 5 | # 6 | # Example for the Glesys API 7 | 8 | # This file contains request method to simplify process of doing request and parsing them 9 | require_relative "../glesys" 10 | 11 | #Implemented some of the methods for the domain module 12 | class GleSYS::DNS 13 | include GleSYS 14 | 15 | # request method uses this to build the url for correct module 16 | MODULE = "domain" 17 | 18 | # Returns an array of domains on the account 19 | def list_domains 20 | request_and_parse("list") 21 | end 22 | 23 | # Returns an array of records in specified domain 24 | def list_records(domainname) 25 | request_and_parse("listrecords", "domainname" => domainname) 26 | end 27 | 28 | # Update record using hostname and domain for matching 29 | def update_record(current_host, domain, data = nil, host = nil, type = nil, ttl = nil) 30 | records = list_records(domain) 31 | record = records.select { |r| r['host'] == current_host }.first 32 | 33 | request_and_parse("updaterecord", 34 | "recordid" => record["recordid"], 35 | "data" => data, 36 | "host" => host, 37 | "type" => type, 38 | "ttl" => ttl 39 | ) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /Ruby/glesys.rb: -------------------------------------------------------------------------------- 1 | # GleSYS API 2 | # 3 | # Author: Marcel Asio 4 | # http://github.com/asio 5 | # 6 | # Example for the Glesys API 7 | 8 | require "net/http" 9 | require "net/https" 10 | require "json" 11 | 12 | # module used for implementing convenience methods for requests 13 | module GleSYS 14 | extend self 15 | 16 | # Replace these values with your own 17 | API_ID = "USERNAME" 18 | API_KEY = "API_KEY" 19 | 20 | BASE_URL = "https://api.glesys.com" 21 | FORMAT = "json" 22 | 23 | # wrapper for request and the parse_response 24 | def request_and_parse(action, data = {}) 25 | parse_response(request(action, data)) 26 | end 27 | 28 | private 29 | 30 | # make a request and returns body 31 | def request(action, data = {}) 32 | url = URI.parse("#{BASE_URL}/#{self.class::MODULE}/#{action}") 33 | data[:format] = FORMAT 34 | 35 | http = Net::HTTP.new(url.host, url.port) 36 | http.use_ssl = true 37 | 38 | req = Net::HTTP::Post.new(url.path) 39 | req.basic_auth(API_ID, API_KEY) 40 | req.set_form_data(data, "&") 41 | 42 | http.request(req).body 43 | end 44 | 45 | # parses the response body from request and returns a ruby object, on fail it prints to stdout 46 | def parse_response(body) 47 | res = JSON.parse(body) 48 | if res["response"]["status"]["code"] == 200 49 | res["response"].select { |k| !["status", "debug"].include?(k) }.values.first 50 | else 51 | puts "-------------FAILED------------------" 52 | puts res["response"]["status"]["text"] 53 | puts res["response"]["debug"] 54 | puts "-------------------------------------" 55 | end 56 | end 57 | end 58 | --------------------------------------------------------------------------------
cpu usage". $values["usage"] . " ". $values["unit"] ."
memory-usage: ".$values["usage"]." MB
size: ".$values["max"]." MB
harddrivefree: ".($values["max"]-$values["usage"])." ".$values["unit"]."
transferlast month/max: ".$values["usage"]."/".$values["max"]." ".$values["unit"]."
uptime:"; 174 | echo $values["current"]. " " . $values["unit"]; 175 | echo "