]> 91.132.146.200 Git - insipid.git/commitdiff
submitting a new URL and finding the info via curl.
authorBanana <banana@optimus.de>
Sun, 25 Dec 2016 11:45:31 +0000 (12:45 +0100)
committerBanana <banana@optimus.de>
Sun, 25 Dec 2016 11:45:31 +0000 (12:45 +0100)
webroot/asset/css/app.css
webroot/index.php
webroot/lib/management.class.php [new file with mode: 0644]
webroot/lib/summoner.class.php
webroot/lib/tag.class.php [new file with mode: 0644]
webroot/view/home.inc.php
webroot/view/home.php

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3e8e7f64a1a63705ef392ca4cf07976bbab0d6e8 100644 (file)
@@ -0,0 +1,3 @@
+.linkthumbnail {
+       max-height: 200px;
+}
\ No newline at end of file
index c8bd963910a9fff12f6b058a5e8d073254630f07..af5a94d8e684f6151fd0ac200c018ca01974cfc2 100644 (file)
@@ -55,6 +55,7 @@ else {
 
 require('config.php');
 require('lib/summoner.class.php');
+require('lib/management.class.php');
 
 ## main vars
 $Summoner = new Summoner();
@@ -74,6 +75,9 @@ if ($DB->connect_errno) exit('Can not connect to MySQL Server');
 $DB->set_charset("utf8mb4");
 $DB->query("SET collation_connection = 'utf8mb4_bin'");
 
+# management needs the DB object
+$Management = new Management($DB);
+
 /*
 if(isset($_GET['p']) && !empty($_GET['p'])) {
     $_requestMode = trim($_GET['p']);
diff --git a/webroot/lib/management.class.php b/webroot/lib/management.class.php
new file mode 100644 (file)
index 0000000..dbdcb71
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Insipid
+ * Personal web-bookmark-system
+ *
+ * Copyright 2016-2017 Johannes Keßler
+ *
+ * Development starting from 2011: Johannes Keßler
+ * https://www.bananas-playground.net/projekt/insipid/
+ *
+ * creator:
+ * Luke Reeves <luke@neuro-tech.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/gpl-3.0.
+ *
+ */
+
+class Management {
+    /**
+     * the database object
+     * @var object
+     */
+    private $DB;
+
+    public function __construct($databaseConnectionObject) {
+        $this->DB = $databaseConnectionObject;
+    }
+
+    /**
+     * get all the available categories from the DB.
+     * optinal limit
+     * @param int $limit
+     */
+    public function categories($limit=false) {
+        $ret = array();
+
+        $queryStr = "SELECT * FROM `".DB_PREFIX."_category` ORDER BY `name`";
+        if(!empty($limit)) {
+            $queryStr .= " LIMIT $limit";
+        }
+        $query = $this->DB->query($queryStr);
+        if(!empty($query)) {
+            $ret = $query->fetch_all(MYSQLI_ASSOC);
+        }
+
+        return $ret;
+    }
+
+    /**
+     * get all the available tags from the DB.
+     * optional limit
+     * @param int $limit
+     */
+    public function tags($limit=false) {
+        $ret = array();
+
+        $queryStr = "SELECT * FROM `".DB_PREFIX."_tag` ORDER BY `name`";
+        if(!empty($limit)) {
+            $queryStr .= " LIMIT $limit";
+        }
+        $query = $this->DB->query($queryStr);
+        if(!empty($query)) {
+            $ret = $query->fetch_all(MYSQLI_ASSOC);
+        }
+
+        return $ret;
+    }
+}
+
+?>
\ No newline at end of file
index ce66c6da8d04273d8c64bd41727df1255d7ef52d..dac6c0f81746618a47e37792fc97cc60e124950e 100644 (file)
@@ -156,7 +156,7 @@ class Summoner {
         * execute a curl call to the fiven $url
         * @param string $curl The request url
         */
-       static function curlCall($url,$port=80) {
+       static function curlCall($url,$port=false) {
                $ret = false;
 
                $ch = curl_init();
@@ -165,14 +165,18 @@ class Summoner {
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
-               curl_setopt($ch, CURLOPT_PORT, $port);
+               if(!empty($port)) {
+                 curl_setopt($ch, CURLOPT_PORT, $port);
+               }
 
                $do = curl_exec($ch);
+
                if(is_string($do) === true) {
                        $ret = $do;
                }
                else {
                        $ret = false;
+                       error_log(var_export(curl_error($ch),true));
                }
 
                curl_close($ch);
@@ -220,6 +224,113 @@ class Summoner {
        static function ifset($array,$key) {
            return isset($array[$key]) ? $array[$key] : false;
        }
+
+       /**
+        * try to gather meta information from given URL
+        * @param string $url
+        */
+       static function gatherInfoFromURL($url) {
+           $ret = false;
+
+           if(self::validate($url,'url')) {
+               $data = self::curlCall($url);
+               if(!empty($data)) {
+                   $ret = self::socialMetaInfos($data);
+               }
+           }
+
+           return $ret;
+       }
+
+       /**
+        * get as much as possible solcial meta infos from given string
+        * the string is usually a HTML source
+        * @param string $string
+        */
+       static function socialMetaInfos($string) {
+           #http://www.w3bees.com/2013/11/fetch-facebook-og-meta-tags-with-php.html
+           #http://www.9lessons.info/2014/01/social-meta-tags-for-google-twitter-and.html
+           #http://ogp.me/
+           #https://moz.com/blog/meta-data-templates-123
+
+           $dom = new DomDocument;
+           # surpress invalid html warnings
+           @$dom->loadHTML($string);
+
+           $xpath = new DOMXPath($dom);
+           $metas = $xpath->query('//*/meta');
+
+           $mediaInfos = array();
+
+           # meta tags
+           foreach($metas as $meta) {
+               if($meta->getAttribute('property')) {
+                   $prop = $meta->getAttribute('property');
+                   $prop = mb_strtolower($prop);
+
+                   # minimum required information
+                   # http://ogp.me/#metadata
+                   if($prop == "og:title") {
+
+                       $mediaInfos['title'] = $meta->getAttribute('content');
+                   }
+                   elseif($prop == "og:image") {
+                       $mediaInfos['image'] = $meta->getAttribute('content');
+                   }
+                   elseif($prop == "og:url") {
+                       $mediaInfos['link'] = $meta->getAttribute('content');
+                   }
+                   elseif($prop == "og:description") {
+                       $mediaInfos['description'] = $meta->getAttribute('content');
+                   }
+               }
+               elseif($meta->getAttribute('name')) {
+                   $name = $meta->getAttribute('name');
+                   $name = mb_strtolower($name);
+
+                   # twitter
+                   # https://dev.twitter.com/cards/overview
+
+                   if($name == "twitter:title") {
+                       $mediaInfos['title'] = $meta->getAttribute('content');
+                   }
+                   elseif($name == "twitter:description") {
+                       $mediaInfos['description'] = $meta->getAttribute('content');
+                   }
+                   elseif($name == "twitter:image") {
+                       $mediaInfos['image'] = $meta->getAttribute('content');
+                   }
+                   elseif($name == "description") {
+                       $mediaInfos['description'] = $meta->getAttribute('content');
+                   }
+
+               }
+               elseif($meta->getAttribute('itemprop')) {
+                   $itemprop = $meta->getAttribute('itemprop');
+                   $itemprop = mb_strtolower($itemprop);
+
+                   # google plus
+                   if($itemprop == "name") {
+                       $mediaInfos['title'] = $meta->getAttribute('content');
+                   }
+                   elseif($itemprop == "description") {
+                       $mediaInfos['description'] = $meta->getAttribute('content');
+                   }
+                   elseif($itemprop == "image") {
+                       $mediaInfos['image'] = $meta->getAttribute('content');
+                   }
+
+               }
+           }
+
+
+           if(!isset($mediaInfos['title'])) {
+               $titleDom = $xpath->query('//html/head/title');
+               $mediaInfos['title'] = $titleDom->item(0)->nodeValue;
+           }
+
+           return $mediaInfos;
+       }
 }
 
 ?>
diff --git a/webroot/lib/tag.class.php b/webroot/lib/tag.class.php
new file mode 100644 (file)
index 0000000..6f33597
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Insipid
+ * Personal web-bookmark-system
+ *
+ * Copyright 2016-2017 Johannes Keßler
+ *
+ * Development starting from 2011: Johannes Keßler
+ * https://www.bananas-playground.net/projekt/insipid/
+ *
+ * creator:
+ * Luke Reeves <luke@neuro-tech.net>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/gpl-3.0.
+ *
+ */
+ ?>
\ No newline at end of file
index 3f6392903ccbeb83ccafd2e87a3933c0afe3ccea..af4b75673b8fb24b0d333d4085bc6f3cb630b76d 100644 (file)
@@ -33,8 +33,14 @@ $queryStr = false;
 $searchResult = false;
 $showAddForm = false;
 $formData = false;
+$honeypotCheck = false;
 
-if(isset($_POST['data']) && !empty($_POST['data']) && isset($_POST['submitsearch'])) {
+if((isset($_POST['password']) && !empty($_POST['password'])) || (isset($_POST['username']) && !empty($_POST['username']))) {
+    # those are hidden fields. A robot my input these. A valid user does not.
+    $honeypotCheck = true;
+}
+
+if(isset($_POST['data']) && !empty($_POST['data']) && isset($_POST['submitsearch']) && $honeypotCheck === false) {
     $searchValue = trim($_POST['data']['searchfield']);
     $isUrl = Summoner::validate($searchValue,'url');
     if($isUrl === true) {
@@ -55,8 +61,18 @@ if(isset($_POST['data']) && !empty($_POST['data']) && isset($_POST['submitsearch
 
     # new one?
     if(empty($searchResult) && $isUrl === true) {
+        # try to gather some information automatically
+        $linkInfo = Summoner::gatherInfoFromURL($searchValue);
+        if(!empty($linkInfo)) {
+            $formData['description'] = $linkInfo['description'];
+            $formData['title'] = $linkInfo['title'];
+            $formData['image'] = $linkInfo['image'];
+        }
         # show the add form
         $showAddForm = true;
         $formData['url'] = $searchValue;
     }
-}
\ No newline at end of file
+}
+
+$existingCategories = $Management->categories();
+$existingTags = $Management->tags();
\ No newline at end of file
index be4fbd16d05eddf0e2ec6555b466e3b32a06eb66..60ff1374d10fadaf5c6bdbc07fddd7c1b7ac1d24 100644 (file)
@@ -35,6 +35,8 @@
 <div class="row">
        <div class="large-12 columns">
                <form method="post">
+                       <input type="hidden" name="password" />
+                       <input type="hidden" name="username" />
                <div class="input-group">
                        <span class="input-group-label"><i class="fi-link"></i></span>
                        <input class="input-group-field" type="url" name="data[searchfield]">
@@ -66,6 +68,8 @@
 
 <?php if($showAddForm) { ?>
 <form method="post">
+       <input type="hidden" name="password" />
+       <input type="hidden" name="username" />
        <div class="row">
        <div class="large-12 columns">
                <h3>This URL was not found. Want to add it?</h3>
     <div class="row">
        <div class="large-6 columns">
                <label>
-                       Username
-                       <input type="text" name="data[username]" />
+                       Description
+                       <input type="text" name="data[description]" value="<?php echo Summoner::ifset($formData, 'description'); ?>" />
                </label>
        </div>
+       <div class="large-6 columns">
+                       <label>
+                               Title
+                               <input type="text" name="data[title]" value="<?php echo Summoner::ifset($formData, 'title'); ?>" />
+                       </label>
+       </div>
+    </div>
+    <div class="row">
        <div class="large-6 columns">
                <label>
-                       Password
-                       <input type="password" name="data[password]" />
+                       Image Link
+                       <input type="url" name="data[image]" value="<?php echo Summoner::ifset($formData, 'image'); ?>" />
                </label>
        </div>
+       <div class="large-6 columns">
+                       <img class="linkthumbnail" src="<?php echo Summoner::ifset($formData, 'image'); ?>" alt="Image from provided link" />
+       </div>
     </div>
-
     <div class="row">
        <div class="large-6 columns">
                <label>
                        Category
-                       <select name="data[category]"></select>
+                       <input type="text" name="data[category]" list="categorylist" />
+                       <datalist id="categorylist">
+                               <?php foreach($existingCategories as $c) { ?>
+                                       <option value="<?php echo $c; ?>">
+                               <?php } ?>
+                </datalist>
                </label>
        </div>
        <div class="large-6 columns">
                <label>
                        Tag
-                       <select name="data[tag]"></select>
+                       <input type="text" name="data[tag]" list="taglist" />
+                       <datalist id="taglist">
+                       <?php foreach($existingTags as $t) { ?>
+                                       <option value="<?php echo $t; ?>">
+                               <?php } ?>
+                </datalist>
                </label>
        </div>
     </div>
 
     <div class="row">
-       <div class="large-12 columns">
+       <div class="large-6 columns">
+               <label>
+                       Username
+                       <input type="text" name="data[username]" />
+               </label>
+       </div>
+       <div class="large-6 columns">
+               <label>
+                       Password
+                       <input type="password" name="data[password]" />
+               </label>
+       </div>
+    </div>
+
+    <div class="row">
+       <div class="large-8 columns">
+               <input type="checkbox" name="data[private]" value="1" /><label>Private</label>
+       </div>
+       <div class="large-4 columns text-right" >
                <input type="submit" class="button" value="Add new Link">
        </div>
     </div>