From a918c273d413e0fbf629bc4219e8121cea0d7947 Mon Sep 17 00:00:00 2001 From: Nicolas Boisselier Date: Sun, 11 Dec 2016 01:47:09 +0000 Subject: [PATCH] dbq --- etc/dbq.php | 2 +- etc/dbq/zzz-all.php | 6 +- etc/profile | 2 + etc/profile.d/functions | 12 +- etc/profile.d/mac.sh | 14 +- etc/profile.d/puppet.sh | 4 + etc/profile.d/sys.sh | 15 +- etc/vim/source/abbreviate.vim | 2 + etc/vim/templates/bash.tt | 2 + lib/php/db.php | 21 ++- lib/php/db/config.php | 2 +- lib/php/db/field.php | 2 +- lib/php/db/table.php | 111 +++++++++---- lib/php/http.php | 107 +++++++++++++ lib/php/nb.php | 7 +- lib/php/out.php | 35 +++- share/db/update.sh | 4 +- src/Docker/php/Dockerfile | 2 +- www/dbq/dbq.php | 291 +++++++++++++++++++++++++--------- www/dbq/docker-compose.yaml | 8 +- 20 files changed, 499 insertions(+), 150 deletions(-) create mode 100644 lib/php/http.php diff --git a/etc/dbq.php b/etc/dbq.php index 181e91ac..8504ae6b 100644 --- a/etc/dbq.php +++ b/etc/dbq.php @@ -21,6 +21,6 @@ foreach ([ } } if (!empty($DIR_SQLITE)) $DIR_SQLITE .= '/var/lib/sqlite'; -if (empty($DIR_SQLITE) and file_exists('/var/lib/sqlite')) $DIR_SQLITE = '/var/lib/sqlite'; +elseif (file_exists('/var/lib/sqlite')) $DIR_SQLITE = '/var/lib/sqlite'; ?> diff --git a/etc/dbq/zzz-all.php b/etc/dbq/zzz-all.php index 2a65962e..b5ffa3d2 100644 --- a/etc/dbq/zzz-all.php +++ b/etc/dbq/zzz-all.php @@ -43,7 +43,7 @@ $DBQ['all'] = [ 'type' => 'sqlite', 'name' => 'all', 'pdo' => '', - '_import' => [], + '_import' => ['nb'], 'order' => '10', 'options' => [ PDO::ATTR_PERSISTENT => true, @@ -53,9 +53,9 @@ $DBQ['all'] = [ 'sql_pre' => [], ], 'sql_pre' => [ - #'PRAGMA synchronous=NORMAL', + #'PRAGMA synchronous = NORMAL', 'PRAGMA busy_timeout = 10000', - 'PRAGMA journal_mode=MEMORY', + 'PRAGMA journal_mode = MEMORY', ], ]; diff --git a/etc/profile b/etc/profile index 2e488a62..18f3f6f9 100755 --- a/etc/profile +++ b/etc/profile @@ -62,6 +62,8 @@ else #echo $NB_CURRENT_DIR; #return [ -e "$NB_CURRENT_DIR/profile.d/functions" ] && . "$NB_CURRENT_DIR/profile.d/functions" + [ -n "$NB_DEBUG" ] && $NB_DEBUG ". $NB_CURRENT_DIR/profile.d/functions" + export NB_ROOT=$(realpath $NB_CURRENT_DIR/.. 2>/dev/null) [ -n "$NB_DEBUG" ] && $NB_DEBUG "NB_ROOT=$NB_ROOT" diff --git a/etc/profile.d/functions b/etc/profile.d/functions index fc1a3785..89f52f5b 100644 --- a/etc/profile.d/functions +++ b/etc/profile.d/functions @@ -724,7 +724,7 @@ myip() { return 1 } -get() { +http_get() { if which curl &>/dev/null; then curl -sk $* @@ -738,9 +738,9 @@ get() { echo "Can't find web client" 1>&2 fi } -alias Get=get +alias Get=http_get -head() { +http_head() { if which curl &>/dev/null; then curl -sk --head $* @@ -754,4 +754,8 @@ head() { echo "Can't find web client" 1>&2 fi } -alias Head=head +alias Head=http_head +( +unset -f get +unset -f head +) 2> /dev/null | true diff --git a/etc/profile.d/mac.sh b/etc/profile.d/mac.sh index 278362dc..6aaa10ca 100644 --- a/etc/profile.d/mac.sh +++ b/etc/profile.d/mac.sh @@ -25,7 +25,15 @@ case "$OSTYPE" in darwin*) alias strace='dtruss' alias updatedb='sudo sh -c "cd / && exec /usr/libexec/locate.updatedb"' -alias seq='jot -' +if ! which seq 1>/dev/null; then +seq() { + if [ -n "$2" ]; then + jot - "$1" "$2" + else + jot "$1" + fi +} +fi alias mac_top_proc="echo 'TOP PROCESSES:'; ps -Aro'%cpu, ucomm, user' | grep root | grep -v ' 0.0 '" alias mac_sleep='pmset sleepnow' @@ -42,6 +50,7 @@ alias macps_top="echo 'TOP PROCESSES:'; ps -Aro'%cpu, ucomm, user' | grep $USER alias mac_mount_nfs="sudo mount -o resvport -t nfs" if ! which mysql > /dev/null && which mysql5 > /dev/null; then +eval ' function mysql() { if ! which mysql > /dev/null && which mysql5 > /dev/null; then mysql5 $* @@ -49,7 +58,8 @@ function mysql() { $(which mysql) $* fi } - alias mysql=mysql5 +' +alias mysql=mysql5 fi test "$TERM_PROGRAM" = "iTerm.app" && export PROMPT_COMMAND='printf "\033]0;%s\007" "${USER}@${HOSTNAME%%.*}"' diff --git a/etc/profile.d/puppet.sh b/etc/profile.d/puppet.sh index 43a1afef..cd85f63d 100644 --- a/etc/profile.d/puppet.sh +++ b/etc/profile.d/puppet.sh @@ -40,6 +40,10 @@ END { for (@l) { } which puppet > /dev/null || return 0 +puppet_node_clean() { + puppet node clean $* +} + puppet_upgrade_modules() { local m for m in $(puppet module list|perl -ne '/([\w-]+).*?v[\.\d]+/ and print "$1\n"'); do diff --git a/etc/profile.d/sys.sh b/etc/profile.d/sys.sh index 5d6522a1..647a51cb 100644 --- a/etc/profile.d/sys.sh +++ b/etc/profile.d/sys.sh @@ -1,7 +1,7 @@ -case "$OSTYPE" in - linux*) [ 1 ] ;; - #*) return ;; -esac +# NB 10.12.16 case "$OSTYPE" in +# NB 10.12.16 linux*) [ 1 ] ;; +# NB 10.12.16 #*) return ;; +# NB 10.12.16 esac sys_is_vm() { grep -q ^flags.*\ hypervisor /proc/cpuinfo && echo "This machine is a VM" @@ -10,7 +10,7 @@ sys_is_vm() { sys_watch() { local opt="$@" [ -z "$opt" ] && opt="-d" - #export -f sys_activity + watch --no-title $opt bash -c "sys_activity" } @@ -59,3 +59,8 @@ sys_activity() { rm -rf "$tmp"* } + +( +export -f sys_activity +export -f sys_logs +) 2> /dev/null | true diff --git a/etc/vim/source/abbreviate.vim b/etc/vim/source/abbreviate.vim index 1c31c3e3..e25029ae 100644 --- a/etc/vim/source/abbreviate.vim +++ b/etc/vim/source/abbreviate.vim @@ -9,6 +9,8 @@ iab tjrs toujours iab etre être iab meme même iab ete été +iab Unknow Unknown +iab unknow unknown " iab !D =StrTrim(system('date')) iab !D =strftime('%d.%m.%Y') diff --git a/etc/vim/templates/bash.tt b/etc/vim/templates/bash.tt index cafa59bd..f0aff950 100644 --- a/etc/vim/templates/bash.tt +++ b/etc/vim/templates/bash.tt @@ -13,6 +13,8 @@ # disable shell expansion so * is passed to each command #set -f #declare -r NAME="${0##*/}" + +#set -e declare -r NAME="$(basename "${0}")" declare -r DIR_NAME="$(cd "$(dirname "${0}")"; echo $(pwd))" declare -r FILE_NAME="${DIR_NAME}/${NAME}" diff --git a/lib/php/db.php b/lib/php/db.php index 75ef7553..f9c63997 100644 --- a/lib/php/db.php +++ b/lib/php/db.php @@ -453,7 +453,7 @@ class Db extends nb { if (empty($require[$type])) { $require[$type] = dirname(__FILE__).'/db/types/'.$type.'.php'; - if (!file_exists($require[$type])) self::bye("Unknow type `$type`"); + if (!file_exists($require[$type])) self::bye("Unknown type `$type`"); $require[$type] = dirname(__FILE__).'/db/types/'.$type.'.php'; require_once($require[$type]); } @@ -476,7 +476,7 @@ class Db extends nb { # Check key exists if (empty($db_type[$key])) { - if ($die_if_empty) self::bye("db.type(): Unknow key `$key` for type `".$this->type."`");#.' - '.print_r($db_type,true)); + if ($die_if_empty) self::bye("db.type(): Unknown key `$key` for type `".$this->type."`");#.' - '.print_r($db_type,true)); return; } @@ -695,9 +695,12 @@ class Db extends nb { # $dbs = []; + $done = []; foreach ((array)$files as $file) { - $file = self::untilde($file); + $file = self::untilde(realpath($file)); + if (isset($done[$file])) continue; + else $done[$file] = 1; if (!is_readable($file)) continue; if (preg_match('/\.(yaml|yml)$/i',$file) and ($yaml = self::yaml_parse_file($file))) { @@ -786,6 +789,8 @@ class Db extends nb { $conf = [$id => []]; $conf[$id] = $conf[$id] + self::pdo2h($id); + # NB 10.12.16: NEW + if (empty($conf['id'])) $conf['id'] = $id; return $conf; } @@ -801,14 +806,6 @@ class Db extends nb { # Load databases $conf = self::is_hash($conf) ? $conf : self::conf_load($conf); - /* - # NB 19.11.16: TODEL - replaced with conf_param_db - # Check db=pdo - if ($id and preg_match('/^(\w+):(.*)/',$id,$m)) { - if (empty($conf[$id])) $conf[$id] = []; - $conf[$id] = $conf[$id] + self::pdo2h($id); - } - */ $conf += self::conf_param_db($id); if (!$conf) return false; @@ -829,7 +826,7 @@ class Db extends nb { $db = array_merge($conf[$id],[ #'dbs' => array_keys($conf), 'conf' => $conf, - 'id' => $id, +# NB 10.12.16 'id' => $id, ]); return $db; diff --git a/lib/php/db/config.php b/lib/php/db/config.php index f7af80e7..d4354fa1 100644 --- a/lib/php/db/config.php +++ b/lib/php/db/config.php @@ -1,6 +1,6 @@ sql = $opt['sql']; unset($opt['sql']); } + // Params + if (isset($opt['params'])) { + self::$params = $opt['params']; unset($opt['params']); + } + // Db / Connection if (isset($opt['db'])) { $this->db(is_object($opt['db']) ? $opt['db'] : new Db($opt['db'])); @@ -344,7 +352,7 @@ Class Table extends nb { return $this->fields; } - public function url_keys($values=null,$params=[],$sep='&') { + public function url_keys($values=null,$params=[],$preff='?',$sep='&') { if ($values === null) $values = $this->p(); $url = is_array($params) ? $params : [$params]; @@ -352,14 +360,26 @@ Class Table extends nb { if (empty($keys)) $keys = $others; foreach ($keys as $name => $field) { - #if (isset($values[$name]) and strcmp($values[$name],'')!=0) if (isset($values[$name])) $url[] = $name . '=' .urlencode($values[$name]) ; } foreach (self::$params as $p) if ($v=self::p($p)) $url[] = $p.'='.urlencode($v); - return $url ? '?'.join($sep,$url) : ''; + return $url ? $preff.join($sep,$url) : ''; + } + + public function fields_keys_values($values) { + $keys = $this->fields_keys(); + if (empty($keys)) $keys = $this->fields(); + + $ret = []; + foreach ($keys as $name => $field) { + if (isset($values[$name])) + $ret[] = $values[$name]; + ; + } + return $ret; } public function fields_keys(&$others=[]) { @@ -389,7 +409,7 @@ Class Table extends nb { return $h; } - public function html_edit($values = null) { + public function html_edit($values = null,$form_action='?') { if ($values === null) $values = $this->p(); if (!is_array($values)) $values = [$values]; $fields = array_filter($this->fields(),function($v){return empty($v->extra);}); @@ -408,12 +428,14 @@ Class Table extends nb { $sql = "SELECT *" . $this->select_extras(); $sql .= " FROM ".$this->sql_name().$where; # NB 28.03.16 $this->sql = $sql; + if ($this->type == 'sql' and !empty($this->sql)) $sql = $this->sql.$where; +#bye($sql); $this->debug(preg_replace('/(,|FROM|WHERE|HAVING|GROUP|ORDER)/i',"\n\\1",$sql),1); $st = $this->db()->conn->prepare($sql); $st->execute(); - echo '
'.NB_EOL; + echo ''.NB_EOL; echo '
'.NB_EOL; $count = 0; if ( $add or ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT))) { @@ -442,11 +464,13 @@ Class Table extends nb { .'
'.NB_EOL ; - echo '' + if ($this->show_hidden_params and !empty(self::$params)) echo '' .'' .self::form_hidden(['action','HTTP_REFERER']) .(!empty($_SERVER['HTTP_REFERER']) ? '' : '') - .'
'.NB_EOL; + ; + + echo ''.NB_EOL; } @@ -481,7 +505,7 @@ Class Table extends nb { public function url_sort($name) { - if (!$this->buttons() or !($f=$this->fields($name)) or !empty($f->dyn) or $f->is_encrypt()) return self::prettyText($name); + if (!$this->show_url_sort or !($f=$this->fields($name)) or !empty($f->dyn) or $f->is_encrypt()) return self::prettyText($name); #debug($f); # See: http://dev.w3.org/html5/html-author/charref @@ -747,6 +771,7 @@ Class Table extends nb { } public function buttons() { + if (!$this->show_buttons or empty(self::$params)) return false; if ($this->type() != 'table') return false; return true; } @@ -775,9 +800,35 @@ Class Table extends nb { $call = $this->row_parse_post; $call($row); } + # Passed param on rows() + if ($parser and !empty($opt['row_parse_post'])) { + $call = $opt['row_parse_post']; $call($row); + } + return $call; } + + public function fields_add_missing(&$fields,$row) { + $new = []; + foreach (array_keys($row) as $name) { + + #debug($name); + $new[$name] = isset($fields[$name]) + ? $fields[$name] + : new Field([ + 'name' => $name, + 'dyn' => true, + 'table' => $this, + ]) + ; + + } + + $fields = $new; + return $fields; + } + public function rows(&$opt=[],$opt_by_val=null) { # @@ -860,13 +911,13 @@ Class Table extends nb { ; #debug($this->db()->name); - if ($opt['is_html'] and !$this->p('action') and !$this->p('inc')) { + if ($opt['is_html'] and !empty(self::$params) and !$this->p('action') and !$this->p('inc')) { echo $this->html_menu(); } if ($opt['is_html']) { echo '
'.NB_EOL; - if (!$this->p('inc')) echo $this->form_hidden(); + if ($this->show_hidden_params and !$this->p('inc')) echo $this->form_hidden(); } if ($opt['is_html']) $this->db()->out->type('html'); @@ -877,8 +928,6 @@ Class Table extends nb { # Parser on/off (default: on) if (!isset($opt['parser'])) $opt['parser'] = true; - $parser = $opt['parser']; - #bye($parser); $count = 0; while ($row = $st->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) { @@ -909,12 +958,7 @@ Class Table extends nb { if ($opt['is_html']) echo $this->html_rows_top(); if ($call) { - foreach (array_keys($row) as $name) { - if (!isset($fields[$name])) { - $fields[$name] = new Field($name); - $fields[$name]->dyn = true; - } - } + $this->fields_add_missing($fields,$row); } if ($out_conf) { @@ -1269,14 +1313,14 @@ Class Table extends nb { $html = ''.NB_EOL; - if ($this->buttons()) $html .= ''.$buttons[0].''.NB_EOL; + if ($this->buttons() and !empty($buttons[0])) $html .= ''.$buttons[0].''.NB_EOL; foreach ($row as $k => $v) { if (isset($this->extras[$k])) $k .= " extra"; $html .= ''.$v.''.NB_EOL; } - if ($this->buttons()) $html .= ''.$buttons[1].''.NB_EOL; + if ($this->buttons() and !empty($buttons[1])) $html .= ''.$buttons[1].''.NB_EOL; $html .= ''.NB_EOL; @@ -1474,6 +1518,7 @@ Class Table extends nb { $info['values'] = $hvalues; $keys = $this->fields_keys(); + // If no primary keys, we use all field if (empty($keys)) $keys = $this->fields(); @@ -1555,26 +1600,29 @@ Class Table extends nb { return $this->out($this->info()); } elseif ($action == 'table.delete') { - if (!$this->delete($this->p(),$e) and !isset($e['rowCount'])) bye($e); +# NB 10.12.16 if (!$this->delete($this->p(),$e) and !isset($e['rowCount'])) bye($e); + if (!$this->delete($_POST,$e) and !isset($e['rowCount'])) bye($e); $this->db()->print_header('Location',$this->url_referer(str_replace('&','&',$this->url_list()))); $this->out($e); return true; } elseif ($action == 'table.replace') { - if (!$this->replace($this->p(),$e) and !isset($e['rowCount'])) bye($e); +# NB 10.12.16 if (!$this->replace($this->p(),$e) and !isset($e['rowCount'])) bye($e); + if (!$this->replace($_POST,$e) and !isset($e['rowCount'])) bye($e); $this->db()->print_header('Location',$this->url_referer()); $this->out($e); return true; } elseif ($action == 'table.insert') { - if (!$this->insert($this->p(),$e)) bye(); +# NB 10.12.16 if (!$this->insert($this->p(),$e)) bye(); + if (!$this->insert($_POST,$e)) bye(); $this->db()->print_header('Location',$this->url_referer()); $this->out($e); return true; } elseif ($action == 'table.update') { - #$this->bye($this->p()); - if (!$this->update($this->p(),$e)) bye($e); +# NB 10.12.16 if (!$this->update($this->p(),$e)) bye($e); + if (!$this->update($_POST,$e)) bye($e); $this->db()->print_header('Location',$this->url_referer()); $this->out($e); return true; @@ -1604,12 +1652,13 @@ Class Table extends nb { } public function html_row_buttons(&$row) { + if (!$this->show_buttons or empty(self::$params)) return []; return [ - ''.DB_HTML_EDIT.''.NB_EOL, - ''.DB_HTML_EDIT.''.NB_EOL), + (!DB_HTML_DELETE ? '' : ''.DB_HTML_DELETE.''.NB_EOL, + .'">'.DB_HTML_DELETE.''.NB_EOL), ]; } @@ -1669,8 +1718,10 @@ Class Table extends nb { $r .= '
'; // Hiddens - $r .= self::form_hidden(['db','table','format','limit','download']); - $r .= ''; // Embed for no html format + if ($this->show_hidden_params) $r .= '' + .self::form_hidden(['db','table','format','limit','download']) + .''; // Embed for no html format + ; // Tables - see default.js if you change class $r .= ''; diff --git a/lib/php/http.php b/lib/php/http.php new file mode 100644 index 00000000..832549a6 --- /dev/null +++ b/lib/php/http.php @@ -0,0 +1,107 @@ +SHELL_REPLACE dbq t="SELECT id,name FROM http_status" format=csv sep=" => " quote="'" eol=",\n" +'id' => 'name', +'100' => 'Continue', +'101' => 'Switching Protocols', +'102' => 'Processing', +'200' => 'OK', +'201' => 'Created', +'202' => 'Accepted', +'203' => 'Non-Authoritative Information', +'204' => 'No Content', +'205' => 'Reset Content', +'206' => 'Partial Content', +'207' => 'Multi-Status', +'208' => 'Already Reported', +'226' => 'IM Used', +'300' => 'Multiple Choices', +'301' => 'Moved Permanently', +'302' => 'Found', +'303' => 'See Other', +'304' => 'Not Modified', +'305' => 'Use Proxy', +'306' => 'Switch Proxy', +'307' => 'Temporary Redirect', +'308' => 'Permanent Redirect', +'400' => 'Bad Request', +'401' => 'Unauthorized', +'402' => 'Payment Required', +'403' => 'Forbidden', +'404' => 'Not Found', +'405' => 'Method Not Allowed', +'406' => 'Not Acceptable', +'407' => 'Proxy Authentication Required', +'408' => 'Request Time-out', +'409' => 'Conflict', +'410' => 'Gone', +'411' => 'Length Required', +'412' => 'Precondition Failed', +'413' => 'Payload Too Large', +'414' => 'URI Too Long', +'415' => 'Unsupported Media Type', +'416' => 'Range Not Satisfiable', +'417' => 'Expectation Failed', +'418' => 'I\'m a teapot', +'421' => 'Misdirected Request', +'422' => 'Unprocessable Entity', +'423' => 'Locked', +'424' => 'Failed Dependency', +'426' => 'Upgrade Required', +'428' => 'Precondition Required', +'429' => 'Too Many Requests', +'431' => 'Request Header Fields Too Large', +'451' => 'Unavailable For Legal Reasons', +'500' => 'Internal Server Error', +'501' => 'Not Implemented', +'502' => 'Bad Gateway', +'503' => 'Service Unavailable', +'504' => 'Gateway Time-out', +'505' => 'HTTP Version Not Supported', +'506' => 'Variant Also Negotiates', +'507' => 'Insufficient Storage', +'508' => 'Loop Detected', +'510' => 'Not Extended', +'511' => 'Network Authentication Required', +'420' => 'Method Failure', +'450' => 'Blocked by Windows Parental Controls', +'498' => 'Invalid Token', +'509' => 'Bandwidth Limit Exceeded', +'530' => 'Site is frozen', +'599' => 'Network connect timeout error', +'440' => 'Login Time-out', +'449' => 'Retry With', +'444' => 'No Response', +'495' => 'SSL Certificate Error', +'496' => 'SSL Certificate Required', +'497' => 'HTTP Request Sent to HTTPS Port', +'499' => 'Client Closed Request', +'520' => 'Unknown Error', +'521' => 'Web Server Is Down', +'522' => 'Connection Timed Out', +'523' => 'Origin Is Unreachable', +'524' => 'A Timeout Occurred', +'525' => 'SSL Handshake Failed', +'526' => 'Invalid SSL Certificate', +'527' => 'Railgun Error', +# diff --git a/lib/php/nb.php b/lib/php/nb.php index d13c947d..c83c20bb 100644 --- a/lib/php/nb.php +++ b/lib/php/nb.php @@ -39,7 +39,7 @@ class NB { # Deep merge of vars foreach ($opt as $k => $v) { - if ( ! array_key_exists($k,$this) ) self::bye("Unknow param $k = `$v`"); + if ( ! array_key_exists($k,$this) ) self::bye("Unknown param $k = `$v`"); if ($v === null) continue; @@ -105,7 +105,8 @@ class NB { * Function: pset * Set a value for param, delete it if null */ - public static function pset($name,$value) { + public static function pset($name,$value=null) { + if (is_array($name)) return ($_REQUEST=$name); if ($value === null or $value === '') { unset ($_REQUEST[$name]); return null; @@ -553,7 +554,7 @@ class NB { $rows = array(); if (in_array($name,get_class_methods($class))) $rows = $class->$name(); elseif (in_array($name,get_class_vars($class_name))) $rows = $class->$name; - else self::bye("Unknow action: `$action`"); + else self::bye("Unknown action: `$action`"); #else $rows = $class->$name; if (is_array($rows) and !$rows) return $rows; if (!$rows) return false; diff --git a/lib/php/out.php b/lib/php/out.php index 292a0abc..45699013 100644 --- a/lib/php/out.php +++ b/lib/php/out.php @@ -56,8 +56,8 @@ Class Out extends Nb { $v = $r[$k]; if (!empty($o['quote'])) $v = $o['quote'] . - str_replace($o['quote'],$o['quote_escape'].$o['quote'],$v) . $o['quote'] - ; + str_replace($o['quote'],$o['quote_escape'].$o['quote'],$v) + . $o['quote']; if ($size) { $align = $size>0 ? STR_PAD_LEFT : STR_PAD_RIGHT; @@ -105,10 +105,10 @@ Class Out extends Nb { # NB 27.09.16 ''.NB_EOL # NB 27.09.16 ], - 'enclose' => [ + 'enclose' => (self::p('enclose') === '0' ? [] : [ ''.NB_EOL - ], + ]), 'eol' => self::p('eol',NB_EOL), 'rec' => ',', 'row' => function(&$o,&$r) { @@ -185,8 +185,10 @@ Class Out extends Nb { ), 'csv' => array( - 'sep' => self::p('sep',"\t"), - 'eol' => self::p('eol',"\n"), + 'sep' => self::punescape('sep',"\t"), + 'quote' => self::p('quote',''), + 'quote_escape' => self::punescape('quote_escape','\\'), + 'eol' => self::punescape('eol',"\n"), # NB 17.10.16 'enclose' => ["","\n"], ), @@ -390,7 +392,7 @@ Class Out extends Nb { if (empty($data)) return; if (is_scalar($data)) $data = [[$data]]; - if (!isset(self::$types[$type])) self::bye("Unknow type: `$type`"); + if (!isset(self::$types[$type])) self::bye("Unknown type: `$type`"); if ($type) self::type($type); #$conf['type'] = $type; @@ -552,6 +554,9 @@ Class Out extends Nb { $values = []; foreach (array_values($row) as $k=>$v) { + if (!empty($o['quote'])) $v = $o['quote'] . + str_replace($o['quote'],$o['quote_escape'].$o['quote'],$v) + . $o['quote']; $values[] = str_replace("\n",'\\n',out::scalar($v)); } @@ -559,6 +564,22 @@ Class Out extends Nb { echo join($o['sep'],$values); } + public static function punescape($name=null,$default=null) { + return str_replace( + [ + '\n', + '\r', + '\t', + ], + [ + "\n", + "\r", + "\t", + ], + self::p($name,$default) + ); + } + } Out::init() ; # < Class /*--------------------------------------------------------------------------*/ // Functions diff --git a/share/db/update.sh b/share/db/update.sh index e516313c..807cc977 100755 --- a/share/db/update.sh +++ b/share/db/update.sh @@ -2,7 +2,7 @@ set -e cd "$(dirname "$0")" -echo "Create shell.db" +echo "Update sys.shell_function" ( @@ -17,5 +17,5 @@ cat << EOF COMMIT; EOF -) | sqlite3 shell.db.tmp && mv shell.db.tmp shell.db +) | sqlite3 sys.db diff --git a/src/Docker/php/Dockerfile b/src/Docker/php/Dockerfile index c50d04f6..6f743cef 100644 --- a/src/Docker/php/Dockerfile +++ b/src/Docker/php/Dockerfile @@ -4,7 +4,7 @@ RUN mkdir /opt # Install Postgre PDO #RUN export DEBIAN_FRONTEND=noninteractive && apt-get -q=2 update && apt-get -q=2 -y install libpq-dev #RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql -RUN set -ex && apk --no-cache add postgresql-dev sqlite perl perl-uri libmcrypt-dev +RUN set -ex && apk --no-cache add postgresql-dev sqlite bash perl perl-uri libmcrypt-dev RUN docker-php-ext-install -j$(grep ^proc /proc/cpuinfo |wc -l) mcrypt pdo pdo_mysql pdo_sqlite pdo_sqlite pdo_pgsql pgsql mcrypt RUN mkdir -p /var/www/html && echo 'Welcom to php:7.0-fpm-alpine

Welcom to php:7.0-fpm-alpine

' > /var/www/html/index.php diff --git a/www/dbq/dbq.php b/www/dbq/dbq.php index 2dc7aeee..8ff3cdf5 100644 --- a/www/dbq/dbq.php +++ b/www/dbq/dbq.php @@ -1,34 +1,47 @@ 'human', - 'db' => 'ls', + 'db' => self::PARAM_DB_DEFAULT, 'table' => 'ls', 'action' => 'ls', + 'args' => '', ]; - - public $_colors = [ - 'body' => '#ddd', - 'body-background' => '#009B9C', - - #'button' => '#ddd', - #'button-background' => '#3C3C3B', - 'button' => '#444', - 'button-background' => '#aaa', - 'button-border' => '#888', - ]; + public $params_deep = []; + +# NB 10.12.16 public $_colors = [ +# NB 10.12.16 'body' => '#ddd', +# NB 10.12.16 'body-background' => '#009B9C', +# NB 10.12.16 +# NB 10.12.16 #'button' => '#ddd', +# NB 10.12.16 #'button-background' => '#3C3C3B', +# NB 10.12.16 'button' => '#444', +# NB 10.12.16 'button-background' => '#aaa', +# NB 10.12.16 'button-border' => '#888', +# NB 10.12.16 ]; public $colors = [ ]; public $css = '/default.css'; public $ext; - public $paths = []; + public $uri; + public $uri_params; # Object public $page; @@ -36,22 +49,26 @@ class DbQ extends nb { public $db; public function __construct($opt=[]) { - #bye($this->params); + #debug(self::READ); - if (self::p('action')) $this->params['action'] = self::p('action'); - $this->uri_params(); - $this->params['format'] = - preg_match('/^\S+\s+.Windows|iPhone|Android|Macintosh|Linux/',$_SERVER['HTTP_USER_AGENT']) + // Pre defaults values + $this->params['format'] = (!empty($_SERVER['HTTP_USER_AGENT']) and + preg_match('/^\S+\s+.Windows|iPhone|Android|Macintosh|Linux/',$_SERVER['HTTP_USER_AGENT']) + ) ? 'html' : $this->params['format'] ; + $this->uri_params(); parent::__construct($opt); - if (!$this->params['db']) $this->not_implemented(); + if (!$this->params['db']) $this->not_implemented('Db missing'); + // Post defaults values if (empty($this->ext)) $this->ext = $this->params['format']; + if ($this->params['format'] == 'html') $this->params['format'] = 'table'; + // Page require_once(NB_ROOT.'/lib/php/page.php'); list($title,$nav) = $this->title_nav(); @@ -65,8 +82,7 @@ class DbQ extends nb { if ($this->run) $this->run(); } - public function page($obj,$meth=null,$head=[],$fct=null) { - + public function page_colors() { if (!empty($this->colors)) { if (empty($this->colors['body-border'])) $this->colors['body-border'] = $this->colors['body']; if (empty($this->colors['button'])) $this->colors['button'] = $this->colors['body']; @@ -93,15 +109,19 @@ table.rows th, table.rows td { border-color: '.$this->colors['body-border'].'; } background-color: '.$this->colors['button-background'].'; } '); + } } -if (empty($this->_nopage)) { - $this->page->content_type($this->page->ext2mime($this->params['format']) ? $this->page->ext2mime($this->params['format']) : 'text/plain'); - if ($this->page->is('text') and !$this->page->is('html')) $this->page->content_type('text/plain'); + public function page($obj,$meth=null,$head=[],$fct=null) { - $this->page->headers_no_cache(); - $this->page->begin(); -} + if (empty($this->_nopage)) { + $this->page_colors(); + $this->page->content_type($this->page->ext2mime($this->params['format']) ? $this->page->ext2mime($this->params['format']) : 'text/plain'); + if ($this->page->is('text') and !$this->page->is('html')) $this->page->content_type('text/plain'); + + $this->page->headers_no_cache(); + $this->page->begin(); + } #die($obj); #if (is_scalar($obj)) { @@ -118,42 +138,125 @@ if (empty($this->_nopage)) { } } - $this->page->end(); + if (empty($this->_nopage)) $this->page->end(); exit; } public function db($connect=[]) { + // Connect if (!empty($connect)) { + if (!isset($this->db)) $this->db = $this->db(); - if (!is_array($connect) and $connect === true and isset($this->db->conf[$this->params['db']])) - $connect = $this->db->conf[$this->params['db']] - ; + if (!is_array($connect) + and $connect === true + and isset($this->db->conf[$this->params['db']]) + ) { + $connect = $this->db->conf[$this->params['db']]; + } - if (empty($connect['name'])) $this->not_implemented(); + if (empty($connect['name'])) $this->not_found('Unknown database'); $this->db->__construct($connect); + $this->id = $this->params['db']; $this->db->connect(); + $this->db->base = '/'.$this->db->id.'/'; return $this->db; } + // Re use + if (!empty($this->db)) return $this->db; + + // New global $DB_CONFS; - require_once(NB_ROOT.'/lib/php/db/config.php'); + if (!empty($_SERVER['DBQ_CONF_DIR'])) { + $DB_CONFS = Db::conf_load(array_merge( + (array)glob($_SERVER['DBQ_CONF_DIR'].'/*.yml'), + (array)glob($_SERVER['DBQ_CONF_DIR'].'/*.yaml'), + (array)glob($_SERVER['DBQ_CONF_DIR'].'/*.php'), + [])); + } else { + require_once(NB_ROOT.'/lib/php/db/config.php'); + } $this->db = new Db(['conf'=>$DB_CONFS]); $this->db->format = $this->params['format']; + $this->db->base = '/'; return $this->db; } + public function table_html_edit() { + $all = []; + $keys = $this->table->fields_keys($all); + if (!$keys) $keys = $all; + $keys = array_keys($keys); + + $values = explode(self::PARAM_ARGS_SEP,$this->params['args']); + + #if (!$keys) return; #$this->not_implemented('Table has no fields'); + #bye(array_combine($keys,$values)); + $this->table->html_edit(array_combine($keys,$values)); + } + + public function table_rows($fct=null) { + $opt = ($this->page->is('html') + #and $this->table->type() == 'table' + ) ? [ + 'row_parse_post' => function(&$r){ + $args = join(self::PARAM_ARGS_SEP,$this->table->fields_keys_values($r)); + $args = urlencode($args); + $base = $this->table->base; + + $r = ['@' => join(' ',[ + 'View' + ]) ] + $r; + + $rm = $base.'rm/'.$args; + $r['-'] = '' + #'Delete' + .'
' + .'Delete' + .'
' + ; + + }, + ] : []; + + $this->table->rows($opt); + } + + + public function table() { - if (!in_array($this->params['table'],array_keys($this->db->tables()))) $this->not_implemented(); - $this->table = $this->db->table($this->params['table'],['db'=>$this->db]); + if (!in_array($this->params['table'],array_keys($this->db->tables()))) { + #$this->bye($this->db->tables()); + $this->not_found('Unknown table'); + } + + $this->table = $this->db->table($this->params['table'],[ + 'db' => $this->db, + 'show_hidden_params' => false, + 'show_buttons' => false, + #'params' => [], + 'params' => [ + 'limit' + ], + ]); + + $this->table->base = $this->db->base.$this->table->name.'/'; + } public function title_nav() { $params = $this->params; $ext = $this->ext; - $title = array_filter(array_unique(array_slice(array_values($params),1)),function($v){ return($v=='ls' ? '' : $v); }); + + $title = array_filter(array_unique(array_slice(array_values($params),1)), + function($v){ + return($v==self::PARAM_DB_DEFAULT ? '' : $v); + } + ); + if (!empty($this->title)) array_unshift($title,$this->title); $path = '/'; @@ -183,7 +286,10 @@ if (empty($this->_nopage)) { if (empty($_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'] = join('/',count($GLOBALS['argv'])>0 ? array_slice($GLOBALS['argv'],1) : []); - $path = preg_replace('/\?.*$/','',$_SERVER['REQUEST_URI']); + list ($path,$args) = explode('?',$_SERVER['REQUEST_URI']); + $this->uri = $path; + $this->uri_params = $args; + #$path = preg_replace('/\?.*$/','',$_SERVER['REQUEST_URI']); if (preg_match('/\.(\w+)$/',$path,$m)) { $values[] = $m[1]; @@ -199,30 +305,63 @@ if (empty($this->_nopage)) { $count = count($values); #var_export($values); foreach ($this->params as $p => $default) { - if ($i>=$count) break; - if ($values[$i]!=='') { - if (!preg_match('/^[\w\._-]{2,100}$/',$values[$i])) $this->not_implemented(); - $this->params[$p] = $values[$i]; + #if ($i>=$count) break; + if ($i<$count) { + + # Can be overwrite by get request + if (isset($_GET[$p])) $values[$i] = $_GET[$p]; + + # Sanitize + if ($values[$i]!=='') { + $values[$i] = urldecode($values[$i]); + if ( + $this->perm < self::ADMIN + and + !preg_match('/^'.self::PARAM_EXP.'$/',$values[$i]) + ) $this->error('Wrong value'); + $this->params[$p] = $values[$i]; + } + } $i++; + $this->params_deep[$p] = $i; } return $this->params; } - public function not_implemented() { - #return http_response_code(501); + public function not_found($admin_msg='') { + header('Content-type: text/plain'); + $msg = '404 Not Found'; if (empty($_SERVER['SERVER_PROTOCOL'])) $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'; + header($_SERVER['SERVER_PROTOCOL'].' '.$msg); + echo "$msg\n"; + if (!empty($admin_msg) and $this->perm >= self::ADMIN) echo "$admin_msg\n"; + exit; + } + + public function error($admin_msg='') { + header('Content-type: text/plain'); + $msg = '500 Internal Server Error'; + if (empty($_SERVER['SERVER_PROTOCOL'])) $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'; + header($_SERVER['SERVER_PROTOCOL'].' '.$msg); + echo "$msg\n"; + if (!empty($admin_msg) and $this->perm >= self::ADMIN) echo "$admin_msg\n"; + exit; + } + + public function not_implemented($admin_msg='') { + header('Content-type: text/plain'); $msg = '501 Not Implemented'; + if (empty($_SERVER['SERVER_PROTOCOL'])) $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'; header($_SERVER['SERVER_PROTOCOL'].' '.$msg); echo "$msg\n"; + if (!empty($admin_msg) and $this->perm >= self::ADMIN) echo "$admin_msg\n"; exit; } public function run() { - #$DBQ = new DbQ(); - # # Db Init # @@ -239,18 +378,19 @@ if (empty($this->_nopage)) { [ 'databases', 'List others databases' ], [ 'cryptkey', 'Generate a new encryption key' ], ],['command','description'],function(&$r) { - $r['command'] = $this->page->tag('a',$r['command'],'href="'.$r['command'].'.'.$this->ext.'"'); + $r['command'] = $this->page->tag('a',$r['command'],'href="'.$this->db->base.$r['command'].'.'.$this->ext.'"'); }); } elseif ($action == 'ls') { $this->page($this->db,'ls',[],function(&$r){ - $r['id'] = $this->page->tag('a',$r['id'],'href="'.$r['id'].'.'.$this->ext.'"'); + $r['id'] = $this->page->tag('a',$r['id'],'href="'.$this->db->base.$r['id'].'.'.$this->ext.'"'); + #$r['id'] = $this->page->tag('a',$r['id'],'href="'.$r['id'].'.'.$this->ext.'"'); }); } elseif ($action == 'cryptkey') { $this->page($this->db,'cryptkey',['key']); - } elseif ($action == 'phpinfo' and $this->admin) { + } elseif ($action == 'phpinfo' and $this->perm >= self::ADMIN) { $this->page($this->page->phpinfo()); } @@ -270,12 +410,12 @@ if (empty($this->_nopage)) { [ 'status', 'Database status' ], [ 'ls', 'List tables' ], ],['command','description'],function(&$r){ - $r['command'] = $this->page->tag('a',$r['command'],'href="'.$r['command'].'.'.$this->ext.'"'); + $r['command'] = $this->page->tag('a',$r['command'],'href="'.$this->db->base.$r['command'].'.'.$this->ext.'"'); }); } elseif ($action == 'ls') { $this->page('',$this->db->tables_rows(),[],function(&$r){ - $r['name'] = $this->page->tag('a',$r['name'],'href="'.$this->params['db'].'/'.$r['name'].'.'.$this->ext.'"'); + $r['name'] = $this->page->tag('a',$r['name'],'href="'.$this->db->base.$r['name'].'.'.$this->ext.'"'); }); } elseif ($action == 'status') { @@ -294,42 +434,44 @@ if (empty($this->_nopage)) { # # Table action # - if ($this->params['action'] == 'help') { - $this->page($this->db(),[ + $action = $this->params['action']; +#bye([$this->params,$action]); + if ($action == 'help') { + $this->page($this->table,[ [ 'help', 'This help' ], [ 'ls', 'List records' ], [ 'fields', 'List fields' ], ],['command','description'],function(&$r){ - $r['command'] = $this->page->tag('a',$r['command'],'href="'.$r['command'].'.'.$this->ext.'"'); + $r['command'] = $this->page->tag('a',$r['command'],'href="'.$this->db->base.$r['command'].'.'.$this->ext.'"'); }); - } elseif ($this->params['action'] == 'status') { + } elseif ($action == 'ls') { + $this->page($this,'table_rows'); + + } elseif ($action == 'status') { $this->page($this->table->status()+$this->table->status(['fields'])); - } elseif ($this->params['action'] == 'fields') { + } elseif ($action == 'fields') { $this->page($this->table,'fields_rows'); - } elseif ($this->params['action'] == 'edit') { - $this->page($this->table,'html_edit'); - - } elseif ($this->params['action'] == 'ls') { - $this->page($this->table,'rows'); - -# NB 08.12.16 } elseif ($action == 'insert') { -# NB 08.12.16 if (!$this->insert($this->p(),$e)) bye(); -# NB 08.12.16 $this->db()->print_header('Location',$this->url_referer()); -# NB 08.12.16 $this->out($e); -# NB 08.12.16 return true; -# NB 08.12.16 -# NB 08.12.16 } elseif ($action == 'update') { -# NB 08.12.16 #$this->bye($this->p()); -# NB 08.12.16 if (!$this->update($this->p(),$e)) bye($e); -# NB 08.12.16 $this->db()->print_header('Location',$this->url_referer()); -# NB 08.12.16 $this->out($e); -# NB 08.12.16 return true; + } elseif ($action == 'vi') { + $this->page($this,'table_html_edit'); + + } elseif ($action == 'insert' and $this->perm >= self::WRITE) { + if (!$this->table->insert($_POST)) $this->error('insert'); + header('Location: '.$this->page->url_referer()); + + } elseif ($action == 'update' and $this->perm >= self::WRITE) { + if (!$this->table->update($_POST)) $this->error('update'); + header('Location: '.$this->page->url_referer()); + + } elseif ($action == 'rm' and $this->perm >= self::DELETE) { + if (!$this->table->delete($_POST)) $this->error('rm'); + header('Location: '.$this->page->url_referer()); + } else { - $this->not_implemented(); + $this->not_implemented('Unknown table action'." `$action`"); } @@ -337,6 +479,5 @@ if (empty($this->_nopage)) { } } - $DBQ = new DbQ(['run'=>true]); ?> diff --git a/www/dbq/docker-compose.yaml b/www/dbq/docker-compose.yaml index d659add6..fcc24a72 100644 --- a/www/dbq/docker-compose.yaml +++ b/www/dbq/docker-compose.yaml @@ -7,11 +7,13 @@ services: - 9000 environment: NB_ROOT: /opt/nb + hostname: dbq volumes: - ./../..:$NB_ROOT - /etc/profile.d - - $HOME/.dbq:/home/www-data/.dbq - - $HOME/$DOCKER_HOME/var/lib/sqlite:/var/lib/sqlite + #- $HOME/.dbq:/home/www-data/.dbq + - $HOME/.dbq:/etc/dbq + - $HOME/ownCloud/var/lib/sqlite:/var/lib/sqlite #- $HOME/ownCloud/var/lib/sqlite:/var/lib/sqlite entrypoint: sh -c "echo . $NB_ROOT/etc/profile > /etc/profile.d/nb.sh && /usr/local/sbin/php-fpm" #entrypoint: "/usr/local/sbin/php-fpm" @@ -26,4 +28,4 @@ services: links: - php ports: - - "8080:80" + - "80:80" -- 2.47.3