Skip to content

Commit

Permalink
Added base64 support
Browse files Browse the repository at this point in the history
  • Loading branch information
s22-tech committed May 26, 2024
1 parent 0eec33a commit ceb8508
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 73 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
# OpenBookmark-II
OBM II is a rewrite of Brendan LaMarche's fantastic OpenBookmark script, to bring it back to life and run on modern versions of PHP. It retains the same 3-column layout, but has some major changes under the hood. One of them is that favicons are now named with the domain name so that only a single favicon per domain is saved to your drive. This will help keep your inode count low if you save a lot of links. Besides, why save multiple icons when one will do?

## Features
<ul>
<li>Handles a wide array of favicon types, including base64!</li>
<li>Saves a single favicon per domain/sub-domain to keep file counts at a minimum.</li>
</ul>

## To Do
<ul>
<li>Update CSS</li>
<li>Add mobile view</li>
</ul>
The look of this script hasn't changed from the original, since CSS is not my strong suit. If someone would like to help update the look and feel of this script, please send a pull request.

## Requirements
Expand All @@ -17,5 +27,3 @@ The look of this script hasn't changed from the original, since CSS is not my st
## Installation
To install, simply copy the files to your server and adjust the values in `/config/config.php` to match your database and server.

### Disclaimer
This script was uploaded to share it with others who miss the functionality of the original OpenBookmarks. Sadly, I don't have the time to make it into a one-size-fits-all solution. If you have ideas of new features to add, feel free to let me know. However, if I don't feel they'd be a good fit, I probably won't add it myself. But pull requests are always welcome. The more people helping with this script, the better.
151 changes: 80 additions & 71 deletions favicon.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<?php

error_reporting(E_ALL);
ini_set('display_errors', true);

if (basename ($_SERVER['SCRIPT_NAME']) == basename (__FILE__)) {
die ('No direct access allowed!');
}

require_once(__DIR__ . '/header.php');
include_once(DOC_ROOT . '/vendor/simplehtmldom/HtmlWeb.php');
require_once(realpath(__DIR__ . '/header.php'));
include_once(realpath(DOC_ROOT . '/vendor/simplehtmldom/HtmlWeb.php'));
use simplehtmldom\HtmlWeb;

class Favicon
Expand All @@ -35,26 +32,26 @@ function __construct($url) {
$this->icon_name = $this->rename_favicon($url . '/'. $this->temp_icon_name);
$favicon_url_path = DOC_ROOT . '/icons/'. $this->icon_name;

debug_logger(name:'this->temp_icon_name', variable:$this->temp_icon_name, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'this->favicon_url', variable:$this->favicon_url, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'this->icon_name', variable:$this->icon_name, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'favicon_url_path', variable:$favicon_url_path, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'this->temp_icon_name', variable: $this->temp_icon_name, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'this->favicon_url', variable: $this->favicon_url, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'this->icon_name', variable: $this->icon_name, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'favicon_url_path', variable: $favicon_url_path, file: __FILE__, function:__FUNCTION__);

$tmp_file = DOC_ROOT . '/tmp/'. $this->temp_icon_name;
[$fav_ext, $ident] = $this->identify_fav($tmp_file);
debug_logger(name:'tmp_file', variable:$tmp_file, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'fav_ext', variable:$fav_ext, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'ident-status', variable:$ident, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'tmp_file', variable: $tmp_file, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'fav_ext', variable: $fav_ext, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'ident-status', variable: $ident, file: __FILE__, function:__FUNCTION__);

if ($cfg['convert_favicons']) {
$this->favicon = $this->convert_favicon($tmp_file, $fav_ext, $ident);
debug_logger(name:'converted favicon', variable:$this->favicon, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'converted favicon', variable: $this->favicon, file: __FILE__, function:__FUNCTION__);
}
else {
// Move the file from the tmp dir.
rename($tmp_file, $favicon_url_path);
$this->favicon = $favicon_url_path;
debug_logger(name:'no conversion favicon', variable:$this->favicon, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'no conversion favicon', variable: $this->favicon, file: __FILE__, function:__FUNCTION__);
}
}
else {
Expand All @@ -76,43 +73,48 @@ function __construct($url) {
###
function convert_favicon($tmp_file, $fav_ext, $ident) : string {
global $cfg;
$tmp_ext = '.'.pathinfo($tmp_file, PATHINFO_EXTENSION);
$new_ext = '.png';
$tmp_ext = pathinfo($tmp_file, PATHINFO_EXTENSION);
$new_ext = ''; //.png

if (file_exists($tmp_file)) {
debug_logger(name:'file_exists - YES', variable:$tmp_file, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'file_exists - YES', variable: $tmp_file, newline: false, file: __FILE__, function:__FUNCTION__);
}

debug_logger(name:'ident-status', variable:$ident, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'tmp_file', variable:$tmp_file, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'fav_ext', variable:$fav_ext, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'ident-status', variable: $ident, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'tmp_file', variable: $tmp_file, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'tmp_ext', variable: $tmp_ext, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'fav_ext', variable: $fav_ext, file: __FILE__, function:__FUNCTION__);

$new_name = $this->rename_favicon($this->url);
debug_logger(name: 'new_name1', variable: $new_name, newline: false, file: __FILE__, function:__FUNCTION__);
$new_name = str_replace($tmp_ext, '', $new_name);
debug_logger(name:'new_name', variable:$new_name, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'new_name2', variable: $new_name, newline: false, file: __FILE__, function:__FUNCTION__);

$save_path_name = DOC_ROOT . '/icons/'. $new_name;
debug_logger(name:'save_path_name', variable:$save_path_name, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'save_path_name', variable: $save_path_name, newline: false, file: __FILE__, function:__FUNCTION__);

if ($ident && $fav_ext !== 'svg') {
$convert = "{$cfg['convert']} $tmp_file -resize {$cfg['icon_size']}\> -unsharp 0x1 {$save_path_name}{$new_ext}";
debug_logger(name:'convert-cmd', variable:$convert, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'convert-cmd', variable: $convert, newline: false, file: __FILE__, function:__FUNCTION__);

// Convert image to .png, and resize to $cfg['icon_size'] if original is different.
## https://legacy.imagemagick.org/Usage/resize/
system("$convert", $status);
debug_logger(name:'SUCCESS--conversion status', variable:$status, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'SUCCESS--conversion status', variable: $status, file: __FILE__, function:__FUNCTION__);
if (file_exists($tmp_file)) {
debug_logger(name:'tmp_file_exists - YES', variable:'', newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'tmp_file_exists - YES', variable:'', newline: false, file: __FILE__, function:__FUNCTION__);
unlink($tmp_file);
}
}
else {
$rename = rename($tmp_file, $save_path_name . $tmp_ext); // Move & rename the file.
debug_logger(name:'MOVED--no conversion', variable:$this->icon_name, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'tmp_file', variable:$tmp_file, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'save_path_name', variable:$save_path_name . $new_ext, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'rename-move', variable:$rename, file:__FILE__, function:__FUNCTION__);
if (strlen($tmp_ext) < 3) {
$tmp_file .= '.png';
}
$rename = rename($tmp_file, $save_path_name); // Move & rename the file.
debug_logger(name: 'MOVED--no conversion', variable: $this->icon_name, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'tmp_file', variable: $tmp_file, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'save_path_name', variable: $save_path_name, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'rename-move', variable: $rename, file: __FILE__, function:__FUNCTION__);
}
return basename($save_path_name) . $new_ext;
}
Expand All @@ -125,33 +127,40 @@ function convert_favicon($tmp_file, $fav_ext, $ident) : string {
function download_favicon_image() {
global $cfg;
$save_path_name = DOC_ROOT . '/tmp/'. $this->temp_icon_name;
debug_logger(name: 'temp_icon_name', variable: $save_path_name, newline:false, file: __FILE__, function: __FUNCTION__);

$open_file_in_binary = fopen($save_path_name, 'wb');
$options = [
CURLOPT_URL => $this->favicon_url,
CURLOPT_USERAGENT => $cfg['user_agent'],
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 2,
CURLOPT_TIMEOUT => 10,
CURLOPT_FILE => $open_file_in_binary,
CURLOPT_HEADER => 0,
/* Lets you use this script when there is redirect on the server. */
CURLOPT_FOLLOWLOCATION => true,
/* Auto detect encoding for the response | identity deflation and gzip */
CURLOPT_ENCODING => '',
];
$ch = curl_init();
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);
debug_logger(name: 'temp_icon_name', variable: $save_path_name, newline: false, file: __FILE__, function: __FUNCTION__);

// Close the file pointer.
fclose($open_file_in_binary);
if (str_contains($this->favicon_url, 'base64')) {
$data = preg_replace("#$this->url#", '', $this->favicon_url);
file_put_contents($save_path_name.'.png', file_get_contents($data));
debug_logger(name: 'data', variable: $data, newline: false, file: __FILE__, function: __FUNCTION__);
}
else {
$open_file_in_binary = fopen($save_path_name, 'wb');
$options = [
CURLOPT_URL => $this->favicon_url,
CURLOPT_USERAGENT => $cfg['user_agent'],
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 2,
CURLOPT_TIMEOUT => 10,
CURLOPT_FILE => $open_file_in_binary,
CURLOPT_HEADER => 0,
/* Lets you use this script when there is redirect on the server. */
CURLOPT_FOLLOWLOCATION => true,
/* Auto detect encoding for the response | identity deflation and gzip */
CURLOPT_ENCODING => '',
];
$ch = curl_init();
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);

// Close the file pointer.
fclose($open_file_in_binary);
debug_logger(name: 'response', variable: $response, newline: false, file: __FILE__, function: __FUNCTION__);
}

if (admin_only()) {
// $bytes = file_put_contents($save_path_name, $response);
debug_logger(name: 'response', variable: $response, newline:false, file: __FILE__, function: __FUNCTION__);
// debug_logger(name: 'bytes saved', variable: $bytes, file: __FILE__, function: __FUNCTION__);
}

Expand All @@ -163,15 +172,15 @@ function download_favicon_image() {
function get_favicon_url() {
$host_url = $this->parsed_url['scheme'] . '://' . $this->parsed_url['host'];
$host_url = rtrim($host_url, '/');
debug_logger(name:'host_url', variable:$host_url, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'host_url', variable: $host_url, newline: false, file: __FILE__, function:__FUNCTION__);

## https://github.com/simplehtmldom/simplehtmldom
## https://sourceforge.net/p/simplehtmldom/bugs/
## https://simplehtmldom.sourceforge.io/docs/1.9/
$dom = new HtmlWeb();
$html = $dom->load($host_url);

debug_logger(name:'html', variable:$html, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'html', variable: $html, file: __FILE__, function:__FUNCTION__);

if (empty($html)) {
echo '<span style="color:red">&bull; favicon.php &mdash; $html is blank.<br></span>';
Expand All @@ -182,18 +191,18 @@ function get_favicon_url() {
foreach ($html->find('link') as $e) {
if (!empty($e->rel)) {
if (strtolower(trim($e->rel)) === 'shortcut icon' || strtolower(trim($e->rel)) === 'icon') {
debug_logger(name:'••• e->rel', variable:$e->rel, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: '••• e->rel', variable: $e->rel, newline: false, file: __FILE__, function:__FUNCTION__);
$favicon_url = $e->href;
break;
}
elseif (strtolower(trim($e->rel)) === 'apple-touch-icon') {
debug_logger(name:'••• e->rel', variable:$e->rel, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: '••• e->rel', variable: $e->rel, newline: false, file: __FILE__, function:__FUNCTION__);
$favicon_url = $e->href;
break;
}
}
}
debug_logger(name:'get-favicon--ORIG', variable:$favicon_url, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'get-favicon--ORIG', variable: $favicon_url, newline: false, file: __FILE__, function:__FUNCTION__);

if (empty($favicon_url)) return; // So as not to populate the /tmp/ directory.

Expand All @@ -205,21 +214,21 @@ function get_favicon_url() {
// If link doesn't start with http...
if (str_starts_with($favicon_url, '//')) {
$favicon_url = 'https:'. $favicon_url;
debug_logger(name:'get-favicon--2', variable:$favicon_url, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'get-favicon--2', variable: $favicon_url, newline: false, file: __FILE__, function: __FUNCTION__);
}
elseif (str_starts_with($favicon_url, '/')) {
$favicon_url = $host_url . $favicon_url;
debug_logger(name:'get-favicon--3', variable:$favicon_url, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'get-favicon--3', variable: $favicon_url, newline: false, file: __FILE__, function: __FUNCTION__);
}
elseif (!str_starts_with($favicon_url, 'http')) {
$favicon_url = $host_url .'/'. $favicon_url;
debug_logger(name:'get-favicon--4', variable:$favicon_url, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'get-favicon--4', variable: $favicon_url, newline: false, file: __FILE__, function: __FUNCTION__);
}

$html->clear();
unset($html);

debug_logger(name:'get-favicon--FINAL', variable:$favicon_url, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'get-favicon--FINAL', variable: $favicon_url, file: __FILE__, function: __FUNCTION__);

$this->temp_icon_name = basename(parse_url($favicon_url, PHP_URL_PATH));

Expand All @@ -236,7 +245,7 @@ function return_parse_url($url) {
$parsed['scheme'] = 'https';
}
if (empty($parsed['host']) || $parsed['host'] == '') {
debug_logger(name:'parsed[host]', variable:$parsed['host'], file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'parsed[host]', variable: $parsed['host'], file: __FILE__, function: __FUNCTION__);
return false;
}
if (empty($parsed['port']) || $parsed['port'] == '') {
Expand All @@ -258,15 +267,15 @@ function rename_favicon($domain) {
$host_name = $parsed['host'];
$host_name = str_replace('.', '-', $host_name);
$parts = explode('-', $host_name);
debug_logger(name:'•••parts', variable:print_r($parts, true), file:__FILE__, function:__FUNCTION__);
debug_logger(name: '•••parts', variable:print_r($parts, true), file: __FILE__, function:__FUNCTION__);
$last = array_pop($parts);
$parts = [implode('-', $parts), $last]; // Get domain w/o the domain extension.
$host_name = $parts[0];
debug_logger(name:'•••host_name', variable:$host_name, file:__FILE__, function:__FUNCTION__);
debug_logger(name: '•••host_name', variable: $host_name, file: __FILE__, function:__FUNCTION__);
$host_name = str_replace('www-', '', $host_name);
$ext = pathinfo($this->favicon_url, PATHINFO_EXTENSION);
$ext = strlen($ext) < 3 ? 'png' : $ext;
debug_logger(name:'•••favicon_name', variable:$host_name . '.' . $ext, file:__FILE__, function:__FUNCTION__);
debug_logger(name: '•••favicon_name', variable: $host_name . '.' . $ext, file: __FILE__, function:__FUNCTION__);
return $host_name . '.' . $ext;
}

Expand All @@ -275,8 +284,8 @@ function identify_fav($tmp_file) {
global $cfg;
$tmp_ext = pathinfo($tmp_file, PATHINFO_EXTENSION);
exec($cfg['identify'] .' '. $tmp_file, $output);
debug_logger(name:'identify output', variable:$output, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name:'identify tmp_file', variable:$tmp_file, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'identify output', variable: $output, newline: false, file: __FILE__, function:__FUNCTION__);
debug_logger(name: 'identify tmp_file', variable: $tmp_file, file: __FILE__, function:__FUNCTION__);
if ($output) {
$idents = explode(' ', $output[0]);
$file_ext = strtolower($idents[1]);
Expand All @@ -291,12 +300,12 @@ function identify_fav($tmp_file) {

if ($file_ext !== $tmp_ext) {
$info = pathinfo($file_to_convert);
debug_logger(name:'identify info', variable:$info, newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'identify info', variable: $info, newline: false, file: __FILE__, function:__FUNCTION__);
}
return [$file_ext, true];
}
else {
debug_logger(name:'identify return', variable:'', newline:false, file:__FILE__, function:__FUNCTION__);
debug_logger(name: 'identify return', variable:'', newline: false, file: __FILE__, function:__FUNCTION__);
return ['png', false];
}
}
Expand All @@ -318,7 +327,7 @@ function get_current_url($url) {

__halt_compiler();

debug_logger(name:$name, variable:$variable, $type, $file, $function)
debug_logger(name:$name, variable: $variable, $type, $file, $function)
prints out:
error_log(''. basename($file) .':'.$function.'()->$'. $name .': '. $variable . PHP_EOL, 3, $cfg['error_log']);
e.g.:
Expand Down

0 comments on commit ceb8508

Please sign in to comment.