#
# control tool for maintaining Kamailio
#
#===================================================================

##### ----------------------------------------------- #####
### path to useful tools
locate_tool() {
	TOOLPATH=""
	while [ -n "$1" ]
	do
		if [ -x /usr/bin/which ] ; then
			TOOLPATH=`which $1`
			if [ -n "$TOOLPATH" ]; then
				return
			fi
		fi
		# look in common locations
		if [ -x "/usr/bin/$1" ] ; then
			TOOLPATH="/usr/bin/$1"
			return
		fi
		if [ -x "/bin/$1" ] ; then
			TOOLPATH="/bin/$1"
			return
		fi
		if [ -x "/usr/local/bin/$1" ] ; then
			TOOLPATH="/usr/local/bin/$1"
			return
		fi
		shift
	done
	return
}

if [ -z "$EGREP" ] ; then
	locate_tool egrep
	if [ -z "$TOOLPATH" ] ; then
		# now error, but we can look for alternative names if it is the case
		echo "error: 'egrep' tool not found: set EGREP variable to correct tool path"
		exit
	fi
	EGREP="$TOOLPATH"
fi
if [ -z "$AWK" ] ; then
	locate_tool awk
	if [ -z "$TOOLPATH" ] ; then
		# now error, but we can look for alternative names if it is the case
		echo "error: 'awk' tool not found: set AWK variable to correct tool path"
		exit
	fi
	AWK="$TOOLPATH"
fi
if [ -z "$GDB" ] ; then
	locate_tool gdb
	if [ -z "$TOOLPATH" ] ; then
		# now error, but we can look for alternative names if it is the case
		GDB=""
		# echo "error: 'gdb' tool not found: set GDB variable to correct tool path"
		# exit
	else
		GDB="$TOOLPATH"
	fi
fi
if [ -z "$MD5" ]; then
	locate_tool md5sum md5
	if [ -z "$TOOLPATH" ] ; then
		# now error, but we can look for alternative names if it is the case
		echo "error: 'md5sum' or 'md5' tool not found: set MD5 variable to correct tool path"
		exit
	fi
	MD5="$TOOLPATH"
fi
if [ -z "$LAST_LINE" ] ; then
	locate_tool tail
	if [ -z "$TOOLPATH" ] ; then
		# now error, but we can look for alternative names if it is the case
		echo "error: 'tail' tool not found: set LAST_LINE variable to correct tool path"
		exit
	fi
	LAST_LINE="$TOOLPATH -n 1"
fi
if [ -z "$EXPR" ] ; then
	locate_tool expr
	if [ -z "$TOOLPATH" ] ; then
		# now error, but we can look for alternative names if it is the case
		echo "error: 'expr' tool not found: set EXPR variable to correct tool path"
		exit
	fi
	EXPR="$TOOLPATH"
fi
if [ -z "$EXPAND" ] ; then
	locate_tool expand
	if [ -z "$TOOLPATH" ] ; then
		EXPAND="cat"
	else
		EXPAND="$TOOLPATH -t 2"
	fi
fi

##### ------------------------------------------------ #####
### configuration for starting/stopping kamailio
if [ -z "$PID_FILE" ] ; then
	PID_FILE=/run/kamailio/kamailio.pid
fi
if [ -z "$SYSLOG" ] ; then
	SYSLOG=1 # 0=output to console, 1=output to syslog
fi
if [ -z "$STARTOPTIONS" ] ; then
	STARTOPTIONS= # for example -dddd
fi
if [ -z "$DIR" ] ; then
	DIR=`dirname $0`
fi
if [ -z "$KAMBIN" ] ; then
	KAMBIN=$DIR/kamailio
fi

##### ------------------------------------------------ #####
### aliases configuration
#
ENABLE_ALIASES=0
if [ "$ALIASES_TYPE" = "UL" ] ; then
	ENABLE_ALIASES=1
else
	if [ "$ALIASES_TYPE" = "DB" ] ; then
		ENABLE_ALIASES=2
	fi
fi

##### ------------------------------------------------ #####
### ACL name verification
if [ -z "$VERIFY_ACL" ] ; then
	VERIFY_ACL=1
fi
if [ -z "$ACL_GROUPS" ] ; then
	ACL_GROUPS="local ld int voicemail free-pstn"
fi
if [ -z "$VERIFY_USER" ] ; then
	VERIFY_USER=1
fi

##### ----------------------------------------------- #####
#### Defined values
ALL_METHODS=4294967295
USERNAME_RE="[-a-zA-Z0-9&=\+\$,;\?/_\.\!~\*'\(\)]+"

##### ----------------------------------------------- #####
#### database tables for SQL databases and DBTEXT

SRDB_LOAD_SER=$((1 << 0))       # The row should be loaded by SER
SRDB_DISABLED=$((1 << 1))       # The row is disabled
SRDB_CANON=$((1 << 2))          # Canonical entry (domain or uri)
SRDB_IS_TO=$((1 << 3))          # The URI can be used in To
SRDB_IS_FROM=$((1 << 4))        # The URI can be used in From
SRDB_FOR_SERWEB=$((1 << 5))     # Credentials instance can be used by serweb
SRDB_PENDING=$((1 << 6))
SRDB_DELETED=$((1 << 7))
SRDB_CALLER_DELETED=$((1 << 8)) # Accounting table
SRDB_CALLEE_DELETED=$((1 << 9)) # Accounting table
SRDB_MULTIVALUE=$((1 << 10))    # Attr_types table
SRDB_FILL_ON_REG=$((1 << 11))   # Attr_types table
SRDB_REQUIRED=$((1 << 12))      # Attr_types table
SRDB_DIR=$((1 << 13))           # Domain_settings table

# UsrLoc Table
if [ -z "$UL_TABLE" ] ; then
	UL_TABLE=location
fi
USER_COLUMN=username
DOMAIN_COLUMN=domain
CALLID_COLUMN=callid

# subscriber table
if [ -z "$SUB_TABLE" ] ; then
	SUB_TABLE=subscriber
fi
REALM_COLUMN=domain
HA1_COLUMN=ha1
HA1B_COLUMN=ha1b
PASSWORD_COLUMN=password
RPID_COLUMN=rpid
SUBSCRIBER_COLUMN='username'
PHP_LIB_COLUMN=phplib_id

if [ -z "$STORE_PLAINTEXT_PW" ] ; then
	STORE_PLAINTEXT_PW=1
fi

# acl table
if [ -z "$ACL_TABLE" ] ; then
	ACL_TABLE=grp
fi
ACL_USER_COLUMN=username
ACL_DOMAIN_COLUMN=domain
ACL_GROUP_COLUMN=grp
ACL_MODIFIED_COLUMN=last_modified

# aliases table
if [ -z "$ALS_TABLE" ] ; then
	ALS_TABLE=aliases
fi
A_USER_COLUMN=username
A_CONTACT_COLUMN=contact
A_EXPIRES_COLUMN=expires
A_Q_COLUMN=q
A_CALLID_COLUMN=callid
A_CSEQ_COLUMN=cseq
A_LAST_MODIFIED_COLUMN=last_modified

# domain table
if [ -z "$DOMAIN_TABLE" ] ; then
	DOMAIN_TABLE=domain
fi
DO_DOMAIN_COLUMN=domain
DO_LAST_MODIFIED_COLUMN=last_modified

# uid_domain table
if [ -z "$UID_DOMAIN_TABLE" ] ; then
	UID_DOMAIN_TABLE=uid_domain
fi
UID_DO_DOMAIN_COLUMN=domain
UID_DO_DID_COLUMN=did
UID_DO_FLAGS_COLUMN=flags

# lcr tables
if [ -z "$LCR_TABLE" ] ; then
	LCR_TABLE=lcr
fi
LCR_ID_COLUMN=lcr_id
LCR_PREFIX_COLUMN=prefix
LCR_GRPID_COLUMN=grp_id

# gw table
if [ -z "$GW_TABLE" ] ; then
	GW_TABLE=gw
fi

# carrier_name table
if [ -z "$CARRIER_NAME_TABLE" ] ; then
	CARRIER_NAME_TABLE=carrier_name
fi
CARRIERROUTE_CARRIER_NAME_ID_COLUMN=id
CARRIERROUTE_CARRIER_NAME_CARRIER_COLUMN=carrier

# domain_name table
if [ -z "$DOMAIN_NAME_TABLE" ] ; then
	DOMAIN_NAME_TABLE=domain_name
fi
CARRIERROUTE_DOMAIN_NAME_ID_COLUMN=id
CARRIERROUTE_DOMAIN_NAME_DOMAIN_COLUMN=domain

# carrierroute table
if [ -z "$CARRIERROUTE_TABLE" ] ; then
	CARRIERROUTE_TABLE=carrierroute
fi
CARRIERROUTE_CARRIERROUTE_PREFIX_COLUMN=id
CARRIERROUTE_CARRIERROUTE_CARRIER_COLUMN=carrier
CARRIERROUTE_CARRIERROUTE_SCAN_PREFIX_COLUMN=scan_prefix
CARRIERROUTE_CARRIERROUTE_DOMAIN_COLUMN=domain
CARRIERROUTE_CARRIERROUTE_PROB_COLUMN=prob
CARRIERROUTE_CARRIERROUTE_STRIP_COLUMN=strip
CARRIERROUTE_CARRIERROUTE_REWRITE_HOST_COLUMN=rewrite_host
CARRIERROUTE_CARRIERROUTE_REWRITE_PREFIX_COLUMN=rewrite_prefix
CARRIERROUTE_CARRIERROUTE_REWRITE_SUFFIX_COLUMN=rewrite_suffix
CARRIERROUTE_CARRIERROUTE_COMMENT_COLUMN=description
CARRIERROUTE_CARRIERROUTE_FLAGS_COLUMN=flags
CARRIERROUTE_CARRIERROUTE_MASK_COLUMN=mask

# URI table
if [ -z "$URI_TABLE" ] ; then
	URI_TABLE=uri
fi
URIUSER_COLUMN=uri_user
MODIFIED_COLUMN=last_modified

# dbaliases table
if [ -z "$DA_TABLE" ] ; then
	DA_TABLE=dbaliases
fi
DA_USER_COLUMN=username
DA_DOMAIN_COLUMN=domain
DA_ALIAS_USER_COLUMN=alias_username
DA_ALIAS_DOMAIN_COLUMN=alias_domain

# speeddial table
if [ -z "$SD_TABLE" ] ; then
	SD_TABLE=speed_dial
fi
SD_USER_COLUMN=username
SD_DOMAIN_COLUMN=domain
SD_SD_USER_COLUMN=sd_username
SD_SD_DOMAIN_COLUMN=sd_domain
SD_NEW_URI_COLUMN=new_uri
SD_DESC_COLUMN=description

# avp table
if [ -z "$AVP_TABLE" ] ; then
	AVP_TABLE=usr_preferences
fi

AVP_UUID_COLUMN=uuid
AVP_USER_COLUMN=username
AVP_DOMAIN_COLUMN=domain
AVP_ATTRIBUTE_COLUMN=attribute
AVP_VALUE_COLUMN=value
AVP_TYPE_COLUMN=type
AVP_MODIFIED_COLUMN=last_modified

# trusted table
if [ -z "$TRUSTED_TABLE" ] ; then
	TRUSTED_TABLE=trusted
fi

TRUSTED_SRC_IP_COLUMN=src_ip
TRUSTED_PROTO_COLUMN=proto
TRUSTED_FROM_PATTERN_COLUMN=from_pattern
TRUSTED_TAG_COLUMN=tag

# address table
if [ -z "$ADDRESS_TABLE" ] ; then
	ADDRESS_TABLE=address
fi

# dispatcher tables
if [ -z "$DISPATCHER_TABLE" ] ; then
	DISPATCHER_TABLE=dispatcher
fi
DISPATCHER_ID_COLUMN=id
DISPATCHER_SETID_COLUMN=setid
DISPATCHER_DESTINATION_COLUMN=destination
DISPATCHER_FLAGS_COLUMN=flags
DISPATCHER_PRIORITY_COLUMN=priority
DISPATCHER_ATTRS_COLUMN=attrs
DISPATCHER_DESCRIPTION_COLUMN=description

# dialog tables
if [ -z "$DIALOG_TABLE" ] ; then
	DIALOG_TABLE=dialog
fi

# dialplan tables
if [ -z "$DIALPLAN_TABLE" ] ; then
	DIALPLAN_TABLE=dialplan
fi
DIALPLAN_ID_COLUMN=id
DIALPLAN_DPID_COLUMN=dpid
DIALPLAN_PR_COLUMN=pr
DIALPLAN_MATCH_OP_COLUMN=match_op
DIALPLAN_MATCH_EXP_COLUMN=match_exp
DIALPLAN_MATCH_LEN_COLUMN=match_len
DIALPLAN_SUBST_EXP_COLUMN=subst_exp
DIALPLAN_REPL_EXP_COLUMN=repl_exp
DIALPLAN_ATTRS_COLUMN=attrs

# ACC table
if [ -z "$ACC_TABLE" ] ; then
	ACC_TABLE=acc
fi

#
##### ------------------------------------------------ #####
### usage functions
#

usage_base() {
	echo
	mecho " -- command 'start|stop|restart|trap'"
	echo
cat <<EOF
 trap ............................... trap with gdb Kamailio processes using RPC
 pstrap ............................. trap with gdb Kamailio processes using ps
 restart ............................ restart Kamailio
 start .............................. start Kamailio
 stop ............................... stop Kamailio
EOF
}

usage_tls() {
	echo
	mecho " -- command 'tls'"
	echo
cat <<EOF
 tls rootCA [<etcdir>] .......... creates new rootCA
 tls userCERT <user> [<etcdir>] ... creates user certificate
 default <etcdir> is $ETCDIR/tls
EOF
}

USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_base"

usage_acl() {
	echo
	mecho " -- command 'acl' - manage access control lists (acl)"
	echo
cat <<EOF
 acl show [<username>] .............. show user membership
 acl grant <username> <group> ....... grant user membership (*)
 acl revoke <username> [<group>] .... grant user membership(s) (*)
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_acl"

usage_lcr() {
	echo
	mecho " -- command 'lcr' - manage least cost routes (lcr)"
	echo
cat <<EOF
 lcr show_gws....... show database gateways
 lcr show_routes.... show database routes
 lcr dump_gws....... show in memory gateways
 lcr dump_routes.... show in memory routes
 lcr reload ........ reload lcr gateways and routes
 lcr eval_weights .. evaluates probability for given GW's weights
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_lcr"

usage_cr() {
	echo
	mecho " -- command 'cr' - manage carrierroute tables"
	echo
cat <<EOF
 cr show ....................................................... show tables
 cr reload ..................................................... reload tables
 cr dump ....................................................... show in memory tables
 cr addcn <carrier id> <carrier name> .......................... add a carrier name
 cr rmcn  <carrier id> ......................................... rm a carrier name
 cr adddn <domain id> <domain name> ............................ add a domain name
 cr rmdn  <domain id> .......................................... rm a domain name
 cr addcarrier <carrier> <scan_prefix> <domain> <rewrite_host> ................
               <prob> <strip> <rewrite_prefix> <rewrite_suffix> ...............
               <flags> <mask> <comment> .........................add a carrier
               (prob, strip, rewrite_prefix, rewrite_suffix,...................
                flags, mask and comment are optional arguments) ...............
 cr rmcarrier  <carrier> <scan_prefix> <domain> ................ rm a carrier
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_cr"

usage_rpid() {
	echo
	mecho " -- command 'rpid' - manage Remote-Party-ID (RPID)"
	echo
cat <<EOF
 rpid add <username> <rpid> ......... add rpid for a user (*)
 rpid rm <username> ................. set rpid to NULL for a user (*)
 rpid show <username> ............... show rpid of a user
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_rpid"

usage_subscriber() {
	echo
	mecho " -- command 'add|passwd|rm' - manage subscribers"
	echo
cat <<EOF
 add <username> <password> .......... add a new subscriber (*)
 show <username> .................... show subscriber attributes (*)
 passwd <username> <passwd> ......... change user's password (*)
 rm <username> ...................... delete a user (*)
 sets <username> <attr> <val> ....... set string attribute (column value)
 setn <username> <attr> <val> ....... set numeric attribute (column value)
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_subscriber"

usage_trusted() {
	echo
	mecho " -- command 'add|dump|reload|rm|show' - manage trusted"
	echo
cat <<EOF
 trusted show ...................... show db content
 trusted dump ...................... show cache content
 trusted reload .................... reload db table into cache
 trusted add <src_ip> <proto> <from_pattern> <tag>
             ....................... add a new entry
	     ....................... (from_pattern and tag are optional arguments)
 trusted rm <src_ip> ............... remove all entries for the given src_ip
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_trusted"

usage_address() {
	echo
	mecho " -- command 'add|dump|reload|rm|show' - manage address"
	echo
cat <<EOF
 address show ...................... show db content
 address dump ...................... show cache content
 address reload .................... reload db table into cache
 address add <grp> <ipaddr> <mask> <port> <tag>
             ....................... add a new entry
	     ....................... (mask, port and tag are optional arguments)
 address rm <grp> <ipaddr> ......... remove entries for given grp and ipaddr
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_address"

usage_dispatcher() {
	echo
	mecho " -- command 'dispatcher' - manage dispatcher"
	echo
cat <<EOF
   * Examples: dispatcher add 1 sip:1.2.3.1:5050 1 5 'prefix=123' 'gw one'
   *           dispatcher add 2 sip:1.2.3.4:5050 3 0
   *           dispatcher rm 4
 dispatcher show ..................... show dispatcher gateways
 dispatcher reload ................... reload dispatcher gateways
 dispatcher dump ..................... show in memory dispatcher gateways
 dispatcher add <setid> <destination> [flags] [priority] [attrs] [description]
            .......................... add gateway
 dispatcher rm <id> .................. delete gateway
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_dispatcher"

usage_dialog() {
	echo
	mecho " -- command 'dialog' - manage dialog records"
	echo
cat <<EOF
   * Examples: dialog show
   *           dialog showdb
 dialog show ..................... show in-memory dialog records
 dialog showdb ................... show database dialog records
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_dialog"

usage_dialplan() {
	echo
	mecho " -- command 'dialplan' - manage dialplans"
	echo
cat <<EOF
 dialplan show <dpid> .............. show dialplan tables
 dialplan reload ................... reload dialplan tables
 dialplan addrule <dpid> <prio> <match_op> <match_exp>
 		<match_len> <subst_exp> <repl_exp> <attrs>
		.................... add a rule
 dialplan rm ....................... removes the entire dialplan table
 dialplan rmdpid <dpid> ............ removes all the gived dpid entries
 dialplan rmrule <dpid> <prio> ..... removes all the gived dpid/prio entries
EOF
}

usage_ksr_srv() {
	echo
	mecho " -- command 'srv' - server management commands"
	echo
cat <<EOF
   * Examples: srv sockets
   *           srv rpclist
 srv sockets ................... show the list of listen sockets
 srv aliases ................... show the list of server aliases
 srv rpclist ................... show the list of server rpc commands
 srv debug [<level>] ........... control the server debug level
 srv version ................... show the server version
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_ksr_srv"

usage_mtree() {
	echo
	mecho " -- command 'add|dump|reload|rm|show' - manage mtree"
	echo
cat <<EOF
 mtree show <tname> .................. show db content
 mtree dump [<tname>] ................ show cache content
 mtree reload [<tname>] .............. reload db table into cache
 mtree add <tname> <tprefix> <tvalue>
             ......................... add a new entry
 mtree rm <tname> <tprefix> .......... remove entries for given tname and tprefix
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_mtree"

usage_acc() {
	echo
	mecho " -- command 'acc' - manage accounding records"
	echo
cat <<EOF
 acc initdb .................. init acc table by adding extra colums
 acc showdb .................. show content of acc table
 recent [<secs>] ............. show most recent records in acc (default 300s)
EOF
}
USAGE_FUNCTIONS="$USAGE_FUNCTIONS usage_acc"


##### ----------------------------------------------- #####
#### Common functions


mdbg() {
	if [ "0$VERBOSE" -ne 0 ] ; then
		if [ -t 1 -a -z "$NOHLPRINT" ] ; then
			echo -e "\033[1m$1\033[0m"
		else
			echo "$1"
		fi
	fi
}

mwarn() {
	if [ -t 1 -a -z "$NOHLPRINT" ] ; then
		echo -e '\E[37;32m'"\033[1mWARNING: $1\033[0m"
	else
		echo "** WARNING: $1"
	fi
}

minfo() {
	if [ -t 1 -a -z "$NOHLPRINT" ] ; then
		echo -e '\E[37;33m'"\033[1mINFO: $1\033[0m"
	else
		echo "** INFO: $1"
	fi
}

mecho() {
	if [ -t 1 -a -z "$NOHLPRINT" ] ; then
		echo -e "\033[1m$1\033[0m"
	else
		echo "$1"
	fi
}

merr() {
	if [ -t 1 -a -z "$NOHLPRINT" ] ; then
		echo -e '\E[37;31m'"\033[1mERROR: $1\033[0m"
	else
		echo "** ERROR: $1"
	fi
}


# determine host name, typically for use in printing UAC
# messages; we use today a simplistic but portable uname -n way --
# no domain name is displayed ; fifo_uac expands !! to host
# address only for optional header fields; uname output without
# domain is sufficient for informational header fields such as
# From
#
get_my_host() {
	if [ -z "$SIP_DOMAIN" ]; then
		uname -n
	else
		echo "$SIP_DOMAIN"
	fi
}

# calculate name and domain of current user
set_user() {

	OSERUSER=`echo $1|$AWK -F@ '{print $1}'`
	OSERDOMAIN=`echo $1|$AWK -F@ '{print $2}'`

	if [ -z "$OSERDOMAIN" ] ; then
		OSERDOMAIN="$SIP_DOMAIN"
	fi

	if [ -z "$OSERDOMAIN" ] ; then
		merr "domain unknown: use usernames with domain or set default domain \
in SIP_DOMAIN"
		exit 1
	fi
}

# check the parameter if it is a valid address of record (user@domain)
check_aor() {
	echo "$1" | $EGREP "^$USERNAME_RE@.+" >/dev/null
	if [ $? -ne 0 ] ; then
		echo "error: invalid AoR: $1" >&2
		exit 1
	fi
}

# check the parameter if it is a valid address of record (user@domain)
is_aor() {
	echo "$1" | $EGREP "^$USERNAME_RE@.+" >/dev/null
	if [ $? -ne 0 ] ; then
		false
	else
		true
	fi
}

# check the parameter if it is a valid SIP address of record (sip:user@domain)
check_sipaor() {
	echo "$1" | $EGREP "^sip(s)?:$USERNAME_RE@.+" >/dev/null
	if [ $? -ne 0 ] ; then
		echo "error: invalid SIP AoR: $1" >&2
		exit 1
	fi
}

# check the parameter if it is a valid SIP URI
# quite simplified now -- it captures just very basic
# errors
check_uri() {
	echo "$1" | $EGREP "^sip(s)?:($USERNAME_RE@)?.+"  > /dev/null
	if [ $? -ne 0 ] ; then
		echo "error: invalid SIP URI: $1" >&2
		exit 1
	fi
}

print_status() {
	echo $1 | $EGREP "^[1-6][0-9][0-9]" > /dev/null
	if [ "$?" -eq 0 ] ; then
		echo $1
	else
		echo "200 OK"
	fi
}

# process output from FIFO/Unixsock server; if everything is ok
# skip the first "ok" line and proceed to returned
# parameters
filter_fl()
{
#	tail +2

	$AWK 'BEGIN {line=0;IGNORECASE=1;}
		{line++}
		NR == 1 && /^200 OK/ { next }
		/^$/ { next }
		{ print }'
}

# process jsonrpc output
filter_json()
{
	$AWK 'function ltrim(s) { sub(/^[ \t\r\n]+/, "", s); return s }
		BEGIN { line=0; IGNORECASE=1; }
		{ line++; }
		NR == 1 && /^[{].+"id"[ \t]*:[ \t]*[0-9]+[ \t]*}$/ { print; next; }
		NR == 1 && /^200 OK/ { next; }
		/^[ \t]*"jsonrpc":[ \t]*"2.0"/ { print; next; }
		/^[ \t]*"result":[ \t]*\[.+/ {
				n=split($0, a, ",");
				for (i=1; i<=n; i++) {
					if (i==1) {
						m=split(a[i], b, "[");
						print b[1] "[";
						if (substr(b[2], length(b[2]), 1)=="[" || substr(b[2], length(b[2]), 1)=="{") {
							print "\t\t" ltrim(b[2]);
						} else {
							print "\t\t" ltrim(b[2]) ",";
						}
					} else {
						if (match(a[i], ".+]$")) {
							print "\t\t" ltrim(substr(a[i], 1, length(a[i])-1));
							print "\t],";
						} else {
							if(length(a[i])>0) print "\t\t" ltrim(a[i]) ",";
						}
					}
				}
				next;
			}
		/[ \t]*}],/ {
				print substr($0, 1, length($0)-2);
				print "\t],";
				next;
			}
		/^$/ { next; }
		{ print; }'
}

# params: user, realm, password
# output: HA1
_gen_ha1()
{
	HA1=`echo -n "$1:$2:$3" | $MD5 | $AWK '{ print $1 }'`
	if [ $? -ne 0 ] ; then
		echo "HA1 calculation failed"
		exit 1
	fi
}

# params: user, realm, password
# output: HA1B
_gen_ha1b()
{
	HA1B=`echo -n "$1@$2:$2:$3" | $MD5 | $AWK '{ print $1 }'`
	if [ $? -ne 0 ] ; then
		echo "HA1B calculation failed"
		exit 1
	fi
}

# params: user, realm, password
# output: PHPLIB_ID
_gen_phplib_id()
{
	NOW=`date`;
	PHPLIB_ID=`echo -n "$1$2:$3:$NOW" | $MD5 | $AWK '{ print $1 }'`
}

# params: user, password
# output: HA1, HA1B
credentials()
{
	set_user $1
	_gen_ha1 "$OSERUSER" "$OSERDOMAIN" "$2"
	_gen_ha1b "$OSERUSER" "$OSERDOMAIN" "$2"
}