commit 064c61dc557d1293b6213df9530c15c4dccb44ea Author: Dominic Szablewski Date: Sat Jul 14 23:13:47 2012 +0200 Initial commit diff --git a/image-grid-examples.html b/image-grid-examples.html new file mode 100644 index 0000000..211052c --- /dev/null +++ b/image-grid-examples.html @@ -0,0 +1,219 @@ + + + + Picturelicious 2.0 - Image Grid Example Configurations + + + +

Picturelicious - Image Grid Example Configurations

+ + +

Quadratic Thumbs in 3 Different Sizes (Default Configuration)

+

lib/config.php

+
+public static $gridView = array(
+	'gridSize' => 64,
+	'gridWidth' => 12,
+	'borderWidth' => 2,
+	'classes' => array(
+		'b2' => array( 'width'=>1, 'height'=>1, 'percentage'=>0.60, 'dir'=>'64x64' ),
+		'b1' => array( 'width'=>2, 'height'=>2, 'percentage'=>0.35, 'dir'=>'128x128' ),
+		'b0' => array( 'width'=>3, 'height'=>3, 'percentage'=>0.05, 'dir'=>'192x192' )
+	),
+);
+
+ +

media/picturelicious.js

+
+var gridSize = 64;
+var gridMinWidth = 6;
+var gridWidth = 0;
+var grid = null;
+var boxDef = {
+	'b0': {'width': 3, 'height': 3},
+	'b1': {'width': 2, 'height': 2},
+	'b2': {'width': 1, 'height': 1}
+};
+
+ +

media/styles.css

+
+.b0 {
+	width: 192px;
+	height: 192px;
+}
+.b1 {
+	width: 128px;
+	height: 128px;
+}
+.b2 {
+	width: 64x;
+	height: 64px;
+}
+
+ + + + + +

Large Spacing between Thumbnails

+

lib/config.php

+
+public static $gridView = array(
+	'gridSize' => 88,
+	'gridWidth' => 12,
+	'borderWidth' => 2,
+	'classes' => array(
+		'b2' => array( 'width'=>1, 'height'=>1,	'percentage'=>0.6,	'dir'=>'64x64' ),
+		'b1' => array( 'width'=>2, 'height'=>2,	'percentage'=>0.35,	'dir'=>'128x128' ),
+		'b0' => array( 'width'=>3, 'height'=>3,	'percentage'=>0.05,	'dir'=>'192x192' )
+	),
+);
+
+ +

media/picturelicious.js

+
+var gridSize = 88;
+var gridMinWidth = 6;
+var gridWidth = 0;
+var grid = null;
+var boxDef = {
+	'b0': {'width': 3, 'height': 3},
+	'b1': {'width': 2, 'height': 2},
+	'b2': {'width': 1, 'height': 1}
+};
+
+ +

media/styles.css

+
+.b0 {
+	padding-left: 32px;
+	padding-top: 32px;
+	width: 192px;
+	height: 192px;
+}
+.b1 {
+	padding-left: 24px;
+	padding-top: 24px;
+	width: 128px;
+	height: 128px;
+}
+.b2 {
+	padding-left: 12px;
+	padding-top: 12px;
+	width: 64x;
+	height: 64px;
+}
+
+ + + + +

4 Thumbnail sizes in 4:3 and 2:3 aspect ratios

+

lib/config.php

+
+public static $gridView = array(
+	'gridSize' => 32,
+	'gridWidth' => 24,
+	'borderWidth' => 2,
+	'classes' => array(
+		'b3' => array( 'width'=>2, 'height'=>3,	'percentage'=>0.58,	'dir'=>'64x96' ),
+		'b2' => array( 'width'=>4, 'height'=>3,	'percentage'=>0.3,	'dir'=>'128x96' ),
+		'b1' => array( 'width'=>4, 'height'=>6,	'percentage'=>0.10,	'dir'=>'128x192' ),
+		'b0' => array( 'width'=>6, 'height'=>9,	'percentage'=>0.02,	'dir'=>'192x288' )
+	),
+);
+
+ +

media/picturelicious.js

+
+var gridSize = 32;
+var gridMinWidth = 6;
+var gridWidth = 0;
+var grid = null;
+var boxDef = {
+	'b0': {'width': 6, 'height': 9},
+	'b1': {'width': 4, 'height': 6},
+	'b2': {'width': 4, 'height': 3}
+	'b3': {'width': 2, 'height': 3}
+};
+
+ +

media/styles.css

+
+.b0 {
+	width: 192px;
+	height: 288px;
+}
+.b1 {
+	width: 128px;
+	height: 192px;
+}
+.b2 {
+	width: 128px;
+	height: 96px;
+}
+.b3 {
+	width: 64px;
+	height: 96px;
+}
+
+ + + + + + + + \ No newline at end of file diff --git a/installation-readme.html b/installation-readme.html new file mode 100644 index 0000000..a6a42bc --- /dev/null +++ b/installation-readme.html @@ -0,0 +1,372 @@ + + + + Picturelicious 2.0 - Readme + + + +

Picturelicious v2.0

+ +

Installation

+
    +
  1. +

    + Edit the lib/config.php. Things you absolutely need to change + are the $frontendPath and $db (Database) settings. +

    +
  2. +
  3. +

    + Upload everything from the picturelicious/ directory, so that the + index.php is at the root of your installation. Make sure you also + upload the .htacces file (it is initially hidden on MacOS). +

    +
  4. +
  5. +

    + Make sure PHP has writing permissions on the following directories: +

    +
      +
    • cache
    • +
    • data/avatars
    • +
    • data/images
    • +
    • data/thumbs
    • +
    • import
    • +
    +

    + You can change permissions (chmod) with your FTP client. Many server configurations + require you to set permissions to 0777 (all permissions set). +

    +
  6. +
  7. +

    + Import the picturelicious.sql with PHPMyAdmin into your database. +

    +
  8. +
  9. +

    + Register a new user on your site. You can give this user Admin rights, by changing + the admin value for this user to 1 in the pl_users + table. Again, use PHPMyAdmin to do so. +

    + +

    + Important: If you want to use the vbb-Forum integration, you have to install + the forum and activate it in your config before(!) any users are registered. +

    +
  10. +
+ +

Mass importing images

+

+ You can import many images at once. Just upload all images you want to appear on your site into the + import/ directory of your installation, log in as an admin user and choose Import + from the menu. You can then click on Import Images at the bottom of the page. Please note that + this may take a while. +

+ + +

Customizing the Image Grid

+

+ The Image Grid or "Image Cloud" is highly customizable but requires some understanding. + When a page is loaded, all images are assigned to one of the available thumbnail sizes and the Image Grid + is then generated in a fixed width. This is important for users who have Javascript disabled. When Javascript is + enabled, the Image Grid will adept to the available width of the browser window. The width and height of each + thumbnail in this grid is also specified in the style.css. Therefore, if you want to change + the layout, you have to edit three different files: +

+ +

+ The Image Grid is ultimately defined by the different thumbnail sizes that are available. In the default configuration, + thumbnails are generated in 3 different, qudratic sizes 64x64, 128x128 and 192x192. Since the gridSize is set to 64, + the size of the thumbnails is only specified by 1, 2 or 3 - a multiple of the gridSize. +

+

+ The percentage setting in the lib/config.php specifies how many of the images are assigned to each of the + box definitions. All of these percentage settings should add up to 1. The order of these box definitions is also important: + the first definition is the "least important", while the last one is the "most important", meaning that images with a bad rating + will be assigned to the first one, while images with a good rating, will be assigned to the last one. +

+

+ Take a look at the image-grid-examples.html for some example configurations. +

+

+ Please note that whenever you change the size of one of these thumbnail definitions, the thumbnails have to be regenerated. There is + no tool included for doing so on the fly. The simplest solution is, to move all images into the import/ + directory, clear the database and import these images again. +

+ +

Using the Random Thumbnail Widget

+

+ To promote your Picturelicious site on other websites, you can easily embed some thumbnails from + Picturelicious by using the following code snippet: +

+

+ <script type="text/javascript" src="http://example.com/random/4/64x64/"> +

+

+ This will insert 4 thumbnails in 64x64 wherever you put this snippet to. Also take a look at the + configuration (Random Thumbnail Widget). +

+ + + +

Configuration

+

+ All configuration settings can be found in lib/config.php. Following is a list of + these settings and their meaning. Many of this settings are only needed for fine tuning. +

+ +

Names and URLs for your installation

+
+
$absolutePath
+
+ The absolute path to your Picturelicious installation from your domain root. If Picturelicious + is installed on http://example.com/picturelicious/, your $absolutePath must be set to + /picturelicious/. If Picturelicious is not in a sub-directory, the default setting (/) + is the right one. +
+
$frontendPath
+
+ The complete URL to you Picturelicious installation. +
+ +
$siteName
+
+ The name of your site. This value is extensivly used in numerous templates and the registration mail +
+ +
$siteTitle
+
+ The title of your site to appear in the browser window's title bar +
+
+ +

Cookies

+
+
$sessionCookie
+
+ The name of the session cookie - a normal user will never see this +
+ +
$rememberCookie
+
+ The name of the remember cookie - a normal user will never see this +
+
+ +

Spam protection

+
+
$ipLockTime
+
+ The time in seconds to lock an IP-adress from voting for the same image again +
+ +
$uploadLockTime
+
+ The time in seconds to which the $maxNumUploads setting corresponds +
+ +
$maxNumUploads
+
+ The maximum number of image uploads allowed in $uploadLockTime seconds +
+
+ +

User scores

+
+
$votingScore
+
+ The score a user gains for voting for an image +
+ +
$postScore
+
+ The score a user gainr for posting an image +
+ +
$tagScorePerChar
+
+ The score a user gains for each character he writes in a tag +
+ +
$tagScoreMax
+
+ The maximum score when tagging an image +
+
+ +

Misc settings

+
+
$usersPerPage
+
+ The number of users to show on one page in the user list +
+ +
$defaultChmod
+
+ The permissions to use when creating a new directory. Chances are, you have to + keep this setting at 0777 +
+ +
$templates
+
+ The directory in which all templates are stored +
+ +
$keywordWordSeperator
+
+ The seperator between words when a keyword for an image is generated. Feel free to change this to + '_' or an empty value for no word seperation +
+
+ +
+
$colorSearchDev
+
+ The maximum deviation for each color channel (R, G, B) when searching for colors +
+
+

Random Thumbnail Widget

+
+
$maxRandomThumbs
+
+ Maximum number of thumbnails to show on the random thumb widget +
+ +
$minRandomScore
+
+ Minimum score of an image to be shown on the random thumb widget +
+
+ +

vbb Forum integration

+
+
$vbbIntegration
+
+
+
enabled
+
Whether to enable the vbb integration (true|false)
+
path
+
relative path to the installation directory of vbb-Forum
+
+
+
+ +

Cache settings

+
+
$cache
+
+
+
enabled
+
Whether to enable the cache
+
path
+
relative path to the cache directory
+
clearEvery
+
The cache is cleared at every image upload or at least every n'th vote
+
+
+
+ +

Database settings

+
+
$db
+
+
+
host
+
The hostname of your database server (in most cases this should be localhost)
+
database
+
The name of the database where all the Picturelicious tables reside
+
user
+
username for the database login
+
password
+
password for the database login
+
prefix
+
prefix for all tables (note that you manually have to rename your tables if you want to change this setting)
+
+
+
+ +

Image processing and thumbnail creation

+
+
$images
+
+
+
thumbsPerPage
+
Number of images to show in the browse mode (i.e. the image cloud)
+
imagePath
+
File path to the images
+
thumbPath
+
File path to the thumbnails
+
avatarsPath
+
File path to the avatar images
+
maxDownload
+
Maximum file size when copying images from a remote URL
+
jpegQuality
+
Quality level for the created thumbnails (0-100)
+
sharpen
+
Whether to sharpen thumbnails after resizing. Note: This only works with PHP 5.1 and newer and is + automatically disabled on older versions.
+
+
+
+ +

Grid Solver settings

+
+
$gridView
+
Refer to the Grid View section in this readme
+
+ + + \ No newline at end of file diff --git a/picturelicious.sql b/picturelicious.sql new file mode 100644 index 0000000..391eb3d --- /dev/null +++ b/picturelicious.sql @@ -0,0 +1,85 @@ +CREATE TABLE `pl_comments` ( + `id` int(11) NOT NULL auto_increment, + `imageId` int(11) NOT NULL, + `userId` int(11) NOT NULL, + `created` datetime NOT NULL, + `content` text collate utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`), + KEY `imageId` (`imageId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +CREATE TABLE `pl_imagecolors` ( + `id` int(11) NOT NULL auto_increment, + `imageId` int(11) NOT NULL, + `r` tinyint(3) unsigned NOT NULL default '0', + `g` tinyint(3) unsigned NOT NULL default '0', + `b` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +CREATE TABLE `pl_images` ( + `id` int(11) NOT NULL auto_increment, + `logged` datetime NOT NULL, + `user` int(11) NOT NULL, + `score` float NOT NULL default '0', + `votes` int(11) NOT NULL default '0', + `keyword` varchar(255) collate utf8_unicode_ci NOT NULL, + `tags` text collate utf8_unicode_ci NOT NULL, + `image` varchar(255) collate utf8_unicode_ci NOT NULL, + `thumb` varchar(255) collate utf8_unicode_ci NOT NULL, + `hash` char(32) collate utf8_unicode_ci NOT NULL, + `source` varchar(255) collate utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`), + KEY `keyword` (`keyword`), + FULLTEXT KEY `tags` (`tags`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +CREATE TABLE `pl_iplock` ( + `ip` int(11) NOT NULL, + `imageId` int(11) NOT NULL, + `ts` int(11) NOT NULL, + PRIMARY KEY (`ip`,`imageId`), + KEY `ts` (`ts`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +CREATE TABLE `pl_taglog` ( + `id` int(11) NOT NULL auto_increment, + `tagged` datetime NOT NULL, + `userId` int(11) NOT NULL, + `imageId` int(11) NOT NULL, + `locked` tinyint(4) NOT NULL, + PRIMARY KEY (`id`), + KEY `tagged` (`tagged`), + KEY `userId` (`userId`), + KEY `imageId` (`imageId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +CREATE TABLE `pl_uploadlock` ( + `id` int(11) NOT NULL auto_increment, + `ip` int(11) NOT NULL, + `ts` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `ip` (`ip`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + + +CREATE TABLE `pl_users` ( + `id` int(11) NOT NULL auto_increment, + `registered` datetime NOT NULL, + `name` varchar(255) collate utf8_unicode_ci NOT NULL, + `pass` char(32) collate utf8_unicode_ci NOT NULL, + `valid` tinyint(4) NOT NULL, + `remember` char(32) collate utf8_unicode_ci NOT NULL, + `admin` tinyint(4) NOT NULL default '0', + `score` int(11) NOT NULL, + `images` int(11) NOT NULL default '0', + `avatar` varchar(255) collate utf8_unicode_ci NOT NULL, + `website` varchar(255) collate utf8_unicode_ci NOT NULL, + `email` varchar(255) collate utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; diff --git a/picturelicious/.htaccess b/picturelicious/.htaccess new file mode 100644 index 0000000..6f266dd --- /dev/null +++ b/picturelicious/.htaccess @@ -0,0 +1,7 @@ +RewriteEngine on + +#not a real file or directory +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^([^\.]*|search/.*)$ index.php?s=$1 + diff --git a/picturelicious/comments.php b/picturelicious/comments.php new file mode 100644 index 0000000..d715f3e --- /dev/null +++ b/picturelicious/comments.php @@ -0,0 +1,52 @@ +login(); + +if( !$user->admin ) { + echo "You need to be logged in as an admin user!"; + exit(); +} + + +$newComments = DB::query( + 'SELECT + c.id, c.content, u.name, u.avatar, + UNIX_TIMESTAMP(c.created) AS created, + i.keyword FROM '.TABLE_COMMENTS.' c + LEFT JOIN '.TABLE_USERS.' u + ON u.id = c.userId + LEFT JOIN '.TABLE_IMAGES.' i + ON i.id = c.imageId + ORDER BY c.created DESC LIMIT 100' +); +include( 'templates/header.tpl.php' ); +?> +

Newest Comments:

+
+ +
+
+ + + at + [bild:] + admin) { ?> +
+ [x] +
+ +
+ +
+ +
+ + + \ No newline at end of file diff --git a/picturelicious/data/avatars/default.png b/picturelicious/data/avatars/default.png new file mode 100644 index 0000000..9927667 Binary files /dev/null and b/picturelicious/data/avatars/default.png differ diff --git a/picturelicious/imageimport.php b/picturelicious/imageimport.php new file mode 100644 index 0000000..77741a6 --- /dev/null +++ b/picturelicious/imageimport.php @@ -0,0 +1,57 @@ +login(); + +if( !$user->admin ) { + echo "You need to be logged in as an admin user!"; + exit(); +} +set_time_limit(0); +$files = glob( 'import/*.*' ); + + +include( 'templates/header.tpl.php' ); + + +if( isset($_POST['import']) ) { + echo "

Imported Images:

"; + require_once( 'lib/cache.php' ); + $cache = new Cache( Config::$cache['path'], 'index' ); + $cache->clear(); +} else { + echo "

Images ready to import:

"; + if( !empty($files) ) { + echo "
'; + } else { + echo "

No images found in the import/ directory!

"; + } + +} + + +?> + + + \ No newline at end of file diff --git a/picturelicious/index.php b/picturelicious/index.php new file mode 100644 index 0000000..1e231ee --- /dev/null +++ b/picturelicious/index.php @@ -0,0 +1,283 @@ +disable(); +} + +// no session or remember cookie -> get the page from cache +if( + empty($_COOKIE[Config::$sessionCookie]) && + empty($_COOKIE[Config::$rememberCookie]) +) { + $cache->lookup(); +} + + +require_once( 'lib/users.php' ); +require_once( 'lib/db.php' ); + +// If the User logged in with POST or a remember cookie, we need forumops.php +// to log him in the forum, too. +if( + isset($_POST['login']) || + ( + empty($_COOKIE[Config::$sessionCookie]) && + !empty($_COOKIE[Config::$rememberCookie]) + ) +) { + if( Config::$vbbIntegration['enabled'] ) { require_once( 'lib/class.forumops.php' ); } +} +$user = new User(); +$user->login(); + +if( $user->id ) { + // Don't cache pages for logged-in users + $cache->disable(); +} + +$messages = array(); +$query = !empty($_GET['s']) ? $_GET['s'] : ''; +$r = explode( '/', $query ); + + +if( $r[0] == 'login' ) { //---------------------------------------- login + if( Config::$vbbIntegration['enabled'] ) { require_once( 'lib/class.forumops.php' ); } + if( !empty( $r[1] ) ) { + if( $user->validate($r[1]) ) { + header( 'location: '.Config::$absolutePath ); + } else { + header( 'location: '.Config::$absolutePath.'login' ); + } + exit(0); + } + if( $user->id ) { + header( 'location: '.Config::$absolutePath ); + exit(); + } + + if( isset($_POST['login']) ) { + $messages['wrongLogin'] = true; + } + include( Config::$templates.'login.tpl.php' ); +} + +else if( $r[0] == 'static' ) { + preg_match('/(\w+)/', $r[1], $m ); + if( !empty($m[1]) && file_exists('static/'.$m[1].'.html.php') ) { + include( Config::$templates.'header.tpl.php' ); + include( 'static/'.$m[1].'.html.php' ); + include( Config::$templates.'footer.tpl.php' ); + } else { + header( 'HTTP/1.0 404 Not Found' ); + include( Config::$templates.'404.tpl.php' ); + } +} + +else if( $r[0] == 'logout' ) { //---------------------------------- logout + if( Config::$vbbIntegration['enabled'] ) { require_once( 'lib/class.forumops.php' ); } + $user->logout(); + header( 'location: '.Config::$absolutePath ); + exit(); +} + +else if( $r[0] == 'register' ) { //-------------------------------- new user + if( Config::$vbbIntegration['enabled'] ) { require_once( 'lib/class.forumops.php' ); } + if( $user->id ) { + header( 'location: '.Config::$absolutePath ); + exit(); + } + + if( isset($_POST['register']) && $user->register( $messages ) ) { + include( Config::$templates.'registered.tpl.php' ); + } else { + include( Config::$templates.'register.tpl.php' ); + } +} + +else if( //----------------------------------------------------- view + ($r[0] == 'all' && $r[1] == 'view') || + ( in_array($r[0], array('user', 'search')) && $r[2] == 'view') +) { + require_once( 'lib/imageviewer.php' ); + $iv = new ImageViewer(); + + if( $r[0] == 'all' ) { // /all/view/2007/09/hans + $iv->setCurrent( $r[2].'/'.$r[3].'/'.$r[4] ); + } + else if( $r[0] == 'user' ) { // /user/name/view/2007/09/hans + $iv->setCurrent( $r[3].'/'.$r[4].'/'.$r[5] ); + $iv->setUser( $r[1] ); + } + else if( $r[0] == 'search' ) { // /search/term/view/2007/09/hans + list( $term, $keyword ) = explode( '/view/', str_ireplace('search/', '', $query) ); + $iv->setCurrent( $keyword ); + $iv->setSearch( $term ); + } + $iv->load(); + + // Add comment if we have one + if( $_POST['addComment'] && $iv->addComment($user->id, $_POST['content']) ) { + $cache->clear( $iv->image['keyword'] ); + header( 'Location: '.Config::$absolutePath.$iv->basePath.'view/'.$iv->image['keyword'] ); + exit(); + } + + if( !empty($iv->image['id']) ) { + $iv->loadComments(); + + $cache->capture(); + include( Config::$templates.'view.tpl.php' ); + } else { + header( 'HTTP/1.0 404 Not Found' ); + include( Config::$templates.'404.tpl.php' ); + } +} + +else if( //----------------------------------------------------- browse + empty($r[0]) || + in_array( $r[0], array('all', 'user', 'search') ) +) { + require_once( 'lib/imagebrowser.php' ); + $ib = new ImageBrowser( Config::$images['thumbsPerPage'] ); + + if( empty($r[0]) || $r[0] == 'all' ) { // /all/page/2 + $ib->setPage( $r[2] ); + } + else if( $r[0] == 'user' ) { // /user/name/page/2 + $ib->setPage( $r[3] ); + $ib->setUser( $r[1] ); + } + else if( $r[0] == 'search' ) { // /search/term/page/2 + list( $term, $page ) = explode( '/page/', str_ireplace('search/', '', $query) ); + $ib->setPage( $page ); + $ib->setSearch( $term ); + } + + $ib->load(); + if( !empty($ib->thumbs) ) { + require_once( 'lib/gridview.php' ); + $gv = new GridView( Config::$gridView['gridWidth'] ); + $gv->solve( $ib->thumbs ); + + $cache->capture(); + include( Config::$templates.'browse.tpl.php' ); + } else { + header( 'HTTP/1.0 404 Not Found' ); + include( Config::$templates.'404.tpl.php' ); + } +} + +else if( $r[0] == 'random' ) { + $count = max( 1, min( Config::$maxRandomThumbs, intval($r[1]) ) ); + $size = ''; + foreach( Config::$gridView['classes'] as $c ) { + if( $r[2] == $c['dir'] ) { + $size = $r[2]; + break; + } + if( empty($size) ) { + $size = $c['dir']; + } + } + + require_once( 'lib/imagebrowser.php' ); + $ib = new ImageBrowser( $count ); + $ib->loadRandom( Config::$minRandomScore, $size ); + + $cache->forceEnable(); + $cache->capture(); + include( Config::$templates.'random.js.php' ); +} + +else if( $r[0] == 'upload' ) { + if( $user->id ) { + $uploadErrors = array(); + if( $user->isSpamLocked() ) { + $uploadErrors[] = 'No more than 10 images in 2 hours!'; + } + else if( !empty( $_POST ) ) { + require_once( 'lib/imageuploader.php' ); + if( + ( + !empty($_POST['url']) && + ImageUploader::copyFromUrl( $_POST['url'], $_POST['tags'], false, $uploadErrors) + ) || + ( + !empty($_FILES['image']['name']) && + ImageUploader::process($_FILES['image']['name'], $_FILES['image']['tmp_name'], $_POST['tags'], true, $uploadErrors) + ) + ) { + $cache->clear(); + $user->logUpload(); + header( "Location: ".Config::$absolutePath ); + exit(0); + } + } + include( Config::$templates.'upload.tpl.php' ); + } else { + header( 'location: '.Config::$absolutePath.'login' ); + } +} + +else if( $r[0] == 'profile' ) { + if( $user->id ) { + if( Config::$vbbIntegration['enabled'] ) { require_once( 'lib/class.forumops.php' ); } + $messages = array(); + if( !empty( $_POST ) ) { + $user->profile( $_FILES['avatar']['tmp_name'], $messages ); + + if( empty( $messages ) ) { + header( 'location: '.Config::$absolutePath ); + } + } + $user->loadEmail(); + include( Config::$templates.'profile.tpl.php' ); + } else { + header( 'location: '.Config::$absolutePath.'login' ); + } +} + +else if( $r[0] == 'users' ) { + require_once( 'lib/userlist.php' ); + $ul = new UserList( Config::$usersPerPage ); + $ul->setPage( $r[2] ); + $ul->load(); + + $cache->capture(); + include( Config::$templates.'userlist.tpl.php' ); +} + +else if( $r[0] == 'quicktags' ) { //------------------------------------------- quicktagger + if( $user->id ) { + include( Config::$templates.'quicktags.tpl.php' ); + } else { + header( 'location: '.Config::$absolutePath.'login' ); + } +} + +else { //------------------------------------------------------- 404 + header( 'HTTP/1.0 404 Not Found' ); + include( Config::$templates.'404.tpl.php' ); + $cache->disable(); +} + +$cache->write(); + + +?> \ No newline at end of file diff --git a/picturelicious/json.php b/picturelicious/json.php new file mode 100644 index 0000000..ab1e601 --- /dev/null +++ b/picturelicious/json.php @@ -0,0 +1,189 @@ +login(); + +require_once( 'lib/cache.php' ); +$cache = new Cache( Config::$cache['path'], '' ); + +if( isset($_GET['addTags']) && $user->id && strlen(trim($_POST['tags'])) >= 3 ) { + $i = DB::getRow( 'SELECT id, tags, keyword FROM '.TABLE_IMAGES.' WHERE id = :1', $_POST['id'] ); + if( !empty( $i ) ) { + if($user->admin) { + $tags = trim($_POST['tags']); + } else { + $tags = trim(trim($i['tags'])." ".trim($_POST['tags'])); + } + DB::updateRow( TABLE_IMAGES, + array('id' => $i['id']), + array( 'tags' => $tags ) + ); + + $score = strlen(trim($_POST['tags'])) * Config::$tagScorePerChar; + $user->increaseScore( min($score, Config::$tagScoreMax) ); + $cache->clear( $i['keyword'] ); + + echo '{"id":"'.$i['id'].'","tags":"'.addslashes(htmlspecialchars($tags)).'"}'; + exit(0); + } +} + +if( isset($_GET['quickTag']) && $user->id ) { + if( !empty($_POST['id']) ) { + + // remove lock + DB::updateRow( TABLE_TAGLOG, + array( 'id' => $_POST['logId'], 'userId' => $user->id ), + array( 'locked' => 0 ) + ); + + if( strlen(trim($_POST['tags'])) >= 3 ) { + $i = DB::getRow( 'SELECT id, tags, keyword FROM '.TABLE_IMAGES.' WHERE id = :1', $_POST['id'] ); + if( !empty( $i ) ) { + $tags = trim(trim($i['tags'])." ".trim($_POST['tags'])); + DB::updateRow( TABLE_IMAGES, + array('id' => $i['id']), + array( 'tags' => $tags ) + ); + } + $score = strlen(trim($_POST['tags'])) * Config::$tagScorePerChar; + $user->increaseScore( min($score, Config::$tagScoreMax) ); + $cache->clear( $i['keyword'] ); + } + } + + $i = DB::getRow( + 'SELECT i.id, i.keyword, i.tags, i.image, UNIX_TIMESTAMP(i.logged) AS loggedTS + FROM '.TABLE_IMAGES.' i + LEFT JOIN '.TABLE_TAGLOG.' t + ON t.imageId = i.id AND ( + ( + t.userId = :1 AND + t.tagged > NOW() - INTERVAL 24 HOUR + ) OR ( + t.locked = 1 AND + t.tagged > NOW() - INTERVAL 5 MINUTE + ) + ) + WHERE t.id IS NULL + ORDER BY LENGTH(i.tags), i.logged DESC + LIMIT 1', + $user->id + ); + if( !empty( $i ) ) { + DB::insertRow( TABLE_TAGLOG, + array( + 'tagged' => date( 'Y.m.d H:i:s' ), + 'userId' => $user->id, + 'imageId' => $i['id'], + 'locked' => 1 + ) + ); + $logId = DB::insertId(); + $link = Config::$absolutePath.'all/view/'.$i['keyword']; + $image = + Config::$absolutePath + .Config::$images['imagePath'] + .date('Y/m/', $i['loggedTS']) + .$i['image']; + + echo '{"id":"'.$i['id'].'","tags":"'.addslashes(htmlspecialchars($i['tags'])).'"' + .',"link":"'.$link.'","image":"'.$image.'","logId":"'.$logId.'"}'; + exit(0); + } +} + +else if( isset($_GET['delete']) && $user->id && $user->admin ) { + $i = DB::getRow( 'SELECT id, logged, image, thumb, user FROM '.TABLE_IMAGES.' WHERE id = :1', $_POST['id'] ); + if( !empty($i) ) { + DB::query( 'DELETE FROM '.TABLE_IMAGES.' WHERE id = :1', $_POST['id'] ); + DB::query( 'DELETE FROM '.TABLE_IMAGECOLORS.' WHERE imageId = :1', $_POST['id'] ); + DB::query( 'DELETE FROM '.TABLE_COMMENTS.' WHERE imageId = :1', $_POST['id'] ); + foreach( Config::$gridView['classes'] as $c ) { + unlink( + Config::$images['thumbPath'] . + str_replace( '-', '/', substr( $i['logged'], 0, 7 ) ).'/'. + $c['dir'].'/'. + $i['thumb'] + ); + } + + unlink( + Config::$images['imagePath'] . + str_replace( '-', '/', substr( $i['logged'], 0, 7 ) ).'/'. + $i['image'] + ); + + DB::query( + 'UPDATE '.TABLE_USERS.' SET images = images -1, score = score - :2 + WHERE id = :1', + $i['user'], Config::$postScore + ); + $cache->clear(); + } + echo "{}"; +} + +else if( isset($_GET['deleteComment']) && $user->id && $user->admin ) { + DB::query( 'DELETE FROM '.TABLE_COMMENTS.' WHERE id = :1', $_POST['id'] ); + $cache->clear(); + echo "{}"; +} + +else if( isset($_GET['rate']) ) { + // score is in valid range / not float? + if( in_array( $_POST['score'], array(1,2,3,4,5) ) ) { + + // check if this ip has allready rated this quote + list(, $ip) = unpack('l',pack('l',ip2long($_SERVER['REMOTE_ADDR']))); + $r = DB::getRow( 'SELECT ip FROM '.TABLE_IPLOCK.' + WHERE ip = :1 AND imageId = :2', + $ip, $_POST['id'] + ); + + // not rated? + if( empty( $r ) ) { + // insert ip + DB::insertRow( TABLE_IPLOCK, + array( + 'ip' => $ip, + 'imageId' => $_POST['id'], + 'ts' => time() + ) + ); + + // update score + DB::query( 'UPDATE '.TABLE_IMAGES.' SET + score = ( score * votes + :1 ) / ( votes + 1 ), + votes = votes + 1 + WHERE id = :2', + $_POST['score'], $_POST['id'] + ); + + $user->increaseScore( Config::$votingScore ); + + if( rand(1, Config::$cache['clearEvery']) == 1 ) { + $cache->clear(); + } + else { + $i = DB::getRow( 'SELECT keyword FROM '.TABLE_IMAGES.' WHERE id = :1', $_POST['id'] ); + $cache->clear( $i['keyword'] ); + } + } + } + + // delete all ips older than IP_LOCK_TIME + DB::query( 'DELETE FROM '.TABLE_IPLOCK.' WHERE ts < :1', time() - Config::$ipLockTime ); + + // return JSON Data + header( 'Content-Type', 'text/plain' ); + $r = DB::getRow( 'SELECT id, score, votes FROM '.TABLE_IMAGES.' WHERE id = :1', $_POST['id'] ); + echo '{"id":"'.$r['id'].'","score":"'.number_format($r['score'],1).'","votes":"'.($r['votes']).'"}'; + exit(0); +} + +echo "{}"; +?> \ No newline at end of file diff --git a/picturelicious/lib/cache.php b/picturelicious/lib/cache.php new file mode 100644 index 0000000..6a18c08 --- /dev/null +++ b/picturelicious/lib/cache.php @@ -0,0 +1,72 @@ +path = $path; + $this->fileName = $this->path . strtr( $pageName, '?&', '--' ) . '.html'; + + if( $_SERVER['REQUEST_METHOD'] != 'GET' ) { + $this->enabled = false; + } + } + + public function disable() { + $this->enabled = false; + } + + public function forceEnable() { + $this->enabled = true; + } + + public function lookup() { + if( $this->enabled && file_exists($this->fileName) ) { + $fp = fopen($this->fileName, 'rb'); + fpassthru($fp); + fclose($fp); + exit(); + } + } + + public function capture() { + if( $this->enabled ) { + ob_start(); + $this->captured = true; + } + } + + public function clear( $pattern = '' ) { + require_once( 'lib/filesystem.php' ); + if( empty($pattern) && !empty($this->path) ) { + Filesystem::rmdirr( $this->path, true ); + } else { + $files = glob( $this->path . 'all/view/' . strtr( $pattern, '?&', '--' ) . '.html' ); + foreach( $files as $f ) { + unlink( $f ); + } + $files = glob( $this->path . 'user/*/view/' . strtr( $pattern, '?&', '--' ) . '.html' ); + foreach( $files as $f ) { + unlink( $f ); + } + } + } + + public function write() { + if( $this->captured ) { + require_once( 'lib/filesystem.php' ); + Filesystem::mkdirr( dirname($this->fileName) ); + file_put_contents( $this->fileName, ob_get_contents() ); + } + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/class.forumops.php b/picturelicious/lib/class.forumops.php new file mode 100644 index 0000000..501e1bc --- /dev/null +++ b/picturelicious/lib/class.forumops.php @@ -0,0 +1,323 @@ + $userdata['name'] ); + if (isset($userdata['email'])) + $vbuser['email'] = $userdata['email']; + if (isset($userdata['pass'])) + $vbuser['password'] = $userdata['pass']; + + return $vbuser; +} + + +define('REGISTERED_USERGROUP', 2); // typical default for registered users +define('PERMANENT_COOKIE', false); // false=session cookies (recommended) + +define('THIS_SCRIPT', __FILE__); +$cwd = getcwd(); +chdir(FORUMPATH); +require_once('./includes/init.php'); // includes class_core.php +require_once('./includes/class_dm.php'); // for class_dm_user.php +require_once('./includes/class_dm_user.php'); // for user functions +require_once('./includes/functions.php'); // vbsetcookie etc. +require_once('./includes/functions_login.php'); // process login/logout + + +//--------------------------------------------------------------------- +// This function duplicates the functionality of fetch_userinfo(), +// using the user name instead of numeric ID as the argument. +// See comments in includes/functions.php for documentation. +//--------------------------------------------------------------------- +function fetch_userinfo_from_username(&$username, $option=0, $languageid=0) +{ + global $vbulletin; + $useridq = $vbulletin->db->query_first_slave("SELECT userid FROM " + . TABLE_PREFIX . "user WHERE username='{$username}'"); + if (!$useridq) return $useridq; + $userid = $useridq['userid']; + return fetch_userinfo($userid, $option, $languageid); +} + + +//--------------------------------------------------------------------- +// CLASS ForumOps +//--------------------------------------------------------------------- +class ForumOps extends vB_DataManager_User { + var $userdm; + +// ********************************************************************************************************* + + function __construct( &$vbulletin ) // constructor + { + $this->vbulletin =& $vbulletin; + $this->userdm =& datamanager_init('user', $vbulletin, ERRTYPE_ARRAY); + } + + function ForumOps() // constructor + { + global $vbulletin; + $this->userdm =& datamanager_init('User', $vbulletin, ERRTYPE_ARRAY); + } + + // ********************************************************************************************************* + + //======== USER REGISTRATION / UPDATE / DELETE ======== + + function register_newuser(&$userdata, $login = true) + { + global $vbulletin; + $vbuser = userdata_convert($userdata); + foreach($vbuser as $key => $value) + $this->userdm->set($key, $value); + $this->userdm->set('usergroupid', REGISTERED_USERGROUP); + $this->userdm->set('timezoneoffset', 1); + + // Bitfields; set to desired defaults. + // Comment out those you have set as defaults + // in the vBuleltin admin control panel + $this->userdm->set_bitfield('options', 'adminemail', 1); + $this->userdm->set_bitfield('options', 'showsignatures', 1); + $this->userdm->set_bitfield('options', 'showavatars', 0); + $this->userdm->set_bitfield('options', 'showimages', 1); + $this->userdm->set_bitfield('options', 'showemail', 0); + + if ($login) $this->login($vbuser); + + //$this->userdm->errors contains error messages + if (empty($this->userdm->errors)) + $vbulletin->userinfo['userid'] = $this->userdm->save(); + else + return implode('
', $this->userdm->errors); + return NULL; + } + +// ********************************************************************************************************* + + function update_user(&$userdata) + { + global $vbulletin; + $vbuser = userdata_convert($userdata); + + if (!($existing_user = fetch_userinfo_from_username($vbuser['username']))) + return 'fetch_userinfo_from_username() failed.'; + + $this->userdm->set_existing($existing_user); + foreach($vbuser as $key => $value) + $this->userdm->set($key, $value); + + // reset password cookie in case password changed + if (isset($vbuser['password'])) + vbsetcookie('password', + md5($vbulletin->userinfo['password'].COOKIE_SALT), + PERMANENT_COOKIE, true, true); + + if (count($this->userdm->errors)) + return implode('
', $this->userdm->errors); + $vbulletin->userinfo['userid'] = $this->userdm->save(); + return NULL; + } + + +// ********************************************************************************************************* + + function update_avatar(&$userdata) { + global $vbulletin; + $vbuser = userdata_convert($userdata); + + if (!($existing_user = fetch_userinfo_from_username($vbuser['username']))) + return 'fetch_userinfo_from_username() failed.'; + + $this->userdm->set_existing($existing_user); + + // update avatar in case it should be + if (!empty($vbuser['avatarurl'])) { + //~ echo"
";
+				//~ print_r ($existing_user);
+			//~ echo "
"; + + // begin custom avatar code + require_once(DIR . '/includes/class_upload.php'); + require_once(DIR . '/includes/class_image.php'); + + $upload = new vB_Upload_Userpic($vbulletin); + + $upload->data =& datamanager_init('Userpic_Avatar', $vbulletin, ERRTYPE_STANDARD, 'userpic'); + $upload->image =& vB_Image::fetch_library($vbulletin); + $upload->userinfo =& $existing_user; + cache_permissions($existing_user, false); + $upload->maxwidth = $vbulletin->userinfo['permissions']['avatarmaxwidth']; + $upload->maxheight = $vbulletin->userinfo['permissions']['avatarmaxheight']; + if (!$upload->process_upload($vbuser['avatarurl'])) { + echo $upload->fetch_error(); + } + } + else { // no avatar used! + $userpic =& datamanager_init('Userpic_Avatar', $vbulletin, ERRTYPE_CP, 'userpic'); + $userpic->condition = "userid = " . $existing_user['userid']; + $userpic->delete(); + } + $this->userdm->set_existing($vbulletin->userinfo); + + ($hook = vBulletinHook::fetch_hook('profile_updateavatar_complete')) ? eval($hook) : false; + return NULL; + } + +// ********************************************************************************************************* + + function delete_user(&$username) + { + // The vBulletin documentation suggests using userdm->delete() + // to delete a user, but upon examining the code, this doesn't + // delete everything associated with the user. The following + // is adapted from admincp/user.php instead. + // NOTE: THIS MAY REQUIRE MAINTENANCE WITH NEW VBULLETIN UPDATES. + + global $vbulletin; + $db = &$vbulletin->db; + $userdata = $db->query_first_slave("SELECT userid FROM " + . TABLE_PREFIX . "user WHERE username='{$username}'"); + $userid = $userdata['userid']; + if ($userid) { + + // from admincp/user.php 'do prune users (step 1)' + + // delete subscribed forums + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "subscribeforum WHERE userid={$userid}"); + // delete subscribed threads + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "subscribethread WHERE userid={$userid}"); + // delete events + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "event WHERE userid={$userid}"); + // delete event reminders + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "subscribeevent WHERE userid={$userid}"); + // delete custom avatars + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "customavatar WHERE userid={$userid}"); + $customavatars = $db->query_read("SELECT userid, avatarrevision FROM " + . TABLE_PREFIX . "user WHERE userid={$userid}"); + while ($customavatar = $db->fetch_array($customavatars)) { + @unlink($vbulletin->options['avatarpath'] . "/avatar{$customavatar['userid']}_{$customavatar['avatarrevision']}.gif"); + } + // delete custom profile pics + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "customprofilepic WHERE userid={$userid}"); + $customprofilepics = $db->query_read( + "SELECT userid, profilepicrevision FROM " + . TABLE_PREFIX . "user WHERE userid={$userid}"); + while ($customprofilepic = $db->fetch_array($customprofilepics)) { + @unlink($vbulletin->options['profilepicpath'] . "/profilepic$customprofilepic[userid]_$customprofilepic[profilepicrevision].gif"); + } + // delete user forum access + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "access WHERE userid={$userid}"); + // delete moderator + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "moderator WHERE userid={$userid}"); + // delete private messages + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "pm WHERE userid={$userid}"); + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "pmreceipt WHERE userid={$userid}"); + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "session WHERE userid={$userid}"); + // delete user group join requests + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "usergrouprequest WHERE userid={$userid}"); + // delete bans + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "userban WHERE userid={$userid}"); + // delete user notes + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "usernote WHERE userid={$userid}"); + + // from admincp/users.php 'do prune users (step 2)' + + // update deleted user's posts with userid=0 + $db->query_write("UPDATE " . TABLE_PREFIX + . "thread SET postuserid = 0, postusername = '" + . $db->escape_string($username) + . "' WHERE postuserid = $userid"); + $db->query_write("UPDATE " . TABLE_PREFIX + . "post SET userid = 0, username = '" + . $db->escape_string($username) + . "' WHERE userid = $userid"); + + // finally, delete the user + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "usertextfield WHERE userid={$userid}"); + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "userfield WHERE userid={$userid}"); + $db->query_write("DELETE FROM " . TABLE_PREFIX + . "user WHERE userid={$userid}"); + } + /* + the following is suggested in the documentation but doesn't work: + + $existing_user = fetch_userinfo_from_username($username); + $this->userdm->set_existing($existing_user); + return $this->userdm->delete(); + */ + } + + function set_email( $username, $email ) { + global $vbulletin; + $db = &$vbulletin->db; + $db->query_write("UPDATE " . TABLE_PREFIX . "user SET email = '" + .mysql_real_escape_string($email)."' WHERE username = '" + .mysql_real_escape_string($username)."'" + ); + } + + function set_pass( $username, $pass ) { + global $vbulletin; + $db = &$vbulletin->db; + $pass = md5($pass); + $salt = $this->fetch_user_salt(); + $db->query_write("UPDATE " . TABLE_PREFIX . "user SET password = '" + .mysql_real_escape_string(md5($pass.$salt))."', + salt = '".mysql_real_escape_string($salt)."' WHERE username = '" + .mysql_real_escape_string($username)."'" + ); + } + + function fetch_user_salt($length = SALT_LENGTH) { + $salt = ''; + + for ($i = 0; $i < $length; $i++) + { + $salt .= chr(rand(33, 126)); + } + + return $salt; + } + + // ======== USER LOGIN / LOGOUT ======== + + function login($vbuser) + { + global $vbulletin; + $vbulletin->userinfo = fetch_userinfo_from_username($vbuser['username']); + // set cookies + vbsetcookie('userid', $vbulletin->userinfo['userid'], + PERMANENT_COOKIE, true, true); + vbsetcookie('password', + md5($vbulletin->userinfo['password'].COOKIE_SALT), + PERMANENT_COOKIE, true, true); + // create session stuff + process_new_login('', 1, ''); + } + + + function logout() + { + process_logout(); // unsets all cookies and session data + } + +} // end class ForumOps +chdir($cwd); +?> \ No newline at end of file diff --git a/picturelicious/lib/config.php b/picturelicious/lib/config.php new file mode 100644 index 0000000..72fa2bc --- /dev/null +++ b/picturelicious/lib/config.php @@ -0,0 +1,112 @@ + false, + 'path' => '/../forum' + ); + + // Cache settings + public static $cache = array( + 'enabled' => true, + 'path' => 'cache/', + 'clearEvery' => 10 + ); + + // Database settings + public static $db = array( + 'host' => 'localhost', + 'database' => 'picturelicious', + 'user' => 'root', + 'password' => '', + 'prefix' => 'pl_' + ); + + // Image processing and thumbnail creation + public static $images = array( + 'thumbsPerPage' => 90, + 'imagePath' => 'data/images/', + 'thumbPath' => 'data/thumbs/', + 'avatarsPath' => 'data/avatars/', + 'maxDownload' => 2097152, + 'jpegQuality' => 80, + 'sharpen' => true + ); + + // Grid Solver settings + public static $gridView = array( + 'gridSize' => 64, + 'gridWidth' => 12, + 'borderWidth' => 2, + + // Definition of all Thumbnail classes --------------------------- + // KEY: CSS-className + // width/ height: Size of the thumb in grid units + // percentage: Percentage of thumbnails in this size + // dir: Name of the subdir with thumbs in this size + 'classes' => array( + 'b2' => array( 'width'=>1, 'height'=>1, 'percentage'=>0.6, 'dir'=>'64x64' ), + 'b1' => array( 'width'=>2, 'height'=>2, 'percentage'=>0.35, 'dir'=>'128x128' ), + 'b0' => array( 'width'=>3, 'height'=>3, 'percentage'=>0.05, 'dir'=>'192x192' ) + ), + ); +} + + +// Edit below this line only if you know what you're doing! +// ----------------------------------------------------------------------- + +// MySQL Table names +define( 'TABLE_IMAGES', Config::$db['prefix'].'images' ); +define( 'TABLE_IMAGECOLORS',Config::$db['prefix'].'imagecolors' ); +define( 'TABLE_USERS', Config::$db['prefix'].'users' ); +define( 'TABLE_IPLOCK', Config::$db['prefix'].'iplock' ); +define( 'TABLE_UPLOADLOCK', Config::$db['prefix'].'uploadlock' ); +define( 'TABLE_TAGLOG', Config::$db['prefix'].'taglog' ); +define( 'TABLE_COMMENTS', Config::$db['prefix'].'comments' ); + +// MagicQuotes undo +if( function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ) { + $_GET = array_map( 'stripslashes', $_GET ); + $_POST = array_map( 'stripslashes', $_POST ); +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/db.php b/picturelicious/lib/db.php new file mode 100644 index 0000000..28cdaa6 --- /dev/null +++ b/picturelicious/lib/db.php @@ -0,0 +1,130 @@ + &$value ) { + $r[] = ( $useKeys ? "`$key`=":'' ) . self::quote( $value ); + } + return $r; + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/filesystem.php b/picturelicious/lib/filesystem.php new file mode 100644 index 0000000..c976b2b --- /dev/null +++ b/picturelicious/lib/filesystem.php @@ -0,0 +1,90 @@ +array( + 'method'=>"GET", + 'header'=>"Referer: $referer\r\n" + ) + ); + $context = stream_context_create($opts); + $fp = fopen( $url, 'r', false, $context ); + } else { + $fp = @fopen( $url, 'r' ); + } + if( !$fp ) { + return false; + } + + while ( !feof( $fp ) ) { + $chunk = fread( $fp, 8192 ); + $bytesRead += strlen( $chunk ); + if( $bytesRead > $maxSize) { + return false; + } + $contents .= $chunk; + } + fclose( $fp ); + + file_put_contents( $target, $contents ); + return true; + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/gridview.php b/picturelicious/lib/gridview.php new file mode 100644 index 0000000..8a8d456 --- /dev/null +++ b/picturelicious/lib/gridview.php @@ -0,0 +1,172 @@ +gridWidth = $gridWidth; + $this->grid = array_fill( 0, $this->gridWidth, 0 ); + } + + // solve expects an array with thumbnails with the keys name and score + public function solve( &$thumbs ) { + if( !is_array( $thumbs ) ) { + return false; + } + + // Order thumbs by importance (score), but leave the keys as they are + uasort( $thumbs, array( $this, 'compareScore' ) ); + + // How many thumbs get which CSS-Class? The first n thumbnails + // get the biggest box etc. + $total = count( $thumbs ); + $classCounts = array(); + $currentCount = 0; + foreach( Config::$gridView['classes'] as $className => $gc ) { + $currentCount += $gc['percentage'] * $total; + $classCounts[$className] = ceil( $currentCount ); + } + + // Assign a CSS-Class to each thumb + $currentMax = -1; + $currentClass = ''; + $j = 0; + foreach( array_keys( $thumbs ) as $i ) { + if( $j >= $currentMax ) { + list( $currentClass, $currentMax ) = each( $classCounts ); + } + $j++; + $thumbs[$i]['class'] = $currentClass; + $thumbs[$i]['thumb'] = Config::$absolutePath . Config::$images['thumbPath'] . + str_replace( '-', '/', substr( $thumbs[$i]['logged'], 0, 7 ) ) + .'/'. Config::$gridView['classes'][$currentClass]['dir'] + .'/'. $thumbs[$i]['thumb']; + } + + // Sort the thumbs back in the order we got them + ksort( $thumbs ); + + // Now that every thumb has a CSS-Class, we can sort them into our grid + for( $i = 0; $i < $total; $i++ ) { + list( $x, $y ) = $this->insert( + Config::$gridView['classes'][$thumbs[$i]['class']]['width'], + Config::$gridView['classes'][$thumbs[$i]['class']]['height'] + ); + $thumbs[$i]['left'] = $x * Config::$gridView['gridSize']; + $thumbs[$i]['top'] = $y * Config::$gridView['gridSize']; + } + + // Calculate the final grid height + for( $i = 0; $i < $this->gridWidth; $i++ ) { + if( $this->grid[$i] > $this->height ) { + $this->height = $this->grid[$i]; + } + } + + return true; + } + + // Callback for uasort() + protected function compareScore( $a, $b ) { + return $a['score'] > $b['score'] ? + 1 : + ( $a['score'] == $b['score'] && $a['votes'] > $b['votes'] ? + 1 : + -1 + ); + } + + protected function insert( $boxWidth, $boxHeight ) { + + // Height of the grid + $maxHeight = 0; + + // Height of the grid at the last position + $currentHeight = $this->grid[0]; + + // Find free spots within the grid and collect them in an arry + // A spot is a area in the grid with equal height + $spotWidth = 0; // Width of the spot in grid units + $spotLeft = 0; // Position in the grid (relative to left border) + $freeSpots = array(); + + for( $i = 0; $i < $this->gridWidth; $i++ ) { + + // Height is the same as at the last position? + // -> increase the size of this spot + if( $currentHeight == $this->grid[$i] ) { + $spotWidth++; + } + + // The height is different from the last position, and our current spot + // is wider than 0 + if( ( $currentHeight != $this->grid[$i] || $i+1 == $this->gridWidth) && $spotWidth > 0 ) { + $freeSpots[] = array( 'width' =>$spotWidth, 'left' => $spotLeft, 'height' => $currentHeight ); + $spotWidth = 1; + $spotLeft = $i; + + // Make sure we don't miss the last one + if( $currentHeight != $this->grid[$i] && $i+1 == $this->gridWidth ) { + $freeSpots[] = array( 'width' =>$spotWidth, 'left' => $spotLeft, 'height' => $this->grid[$i] ); + } + } + + $currentHeight = $this->grid[$i]; + $maxHeight = max( $maxHeight, $this->grid[$i] ); + } + + // Loop through all found spots and rate them, based on their size and height + // This way the smallest possible spot in the lowest possible height is filled + $targetHeight = 0; + $targetLeft = 0; + + // Default spot (left border) if we don't find a better one + for( $i = 0; $i < $boxWidth; $i++ ) { + if( $this->grid[$i] > $targetHeight ) { + $targetHeight = $this->grid[$i]; + } + } + + $bestScore = -1; + foreach( array_keys( $freeSpots ) as $i ) { + + // Difference of the height of this spot to the total height of the grid + $heightScore = ( $maxHeight - $freeSpots[$i]['height'] ); + + // Relation of the required and the available space + $widthScore = $boxWidth / $freeSpots[$i]['width']; + + // The score for this spot is calculated by these both criteria + $score = $heightScore * $heightScore + $widthScore * 2; + + // Is the score for this spot higher than for the last one we found? + if( $freeSpots[$i]['width'] >= $boxWidth && $score > $bestScore ) { + $targetHeight = $freeSpots[$i]['height']; + $targetLeft = $freeSpots[$i]['left']; + $bestScore = $score; + } + } + + $newHeight = $targetHeight + $boxHeight; + + // Adjust grid height + for( $j = 0; $j < $boxWidth; $j++ ) { + $this->grid[$targetLeft + $j] = $newHeight; + } + + return array( $targetLeft, $targetHeight ); + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/imagebrowser.php b/picturelicious/lib/imagebrowser.php new file mode 100644 index 0000000..17b71e2 --- /dev/null +++ b/picturelicious/lib/imagebrowser.php @@ -0,0 +1,145 @@ +thumbsPerPage = abs(intval($thumbsPerPage)); + } + + public function setPage( $page ) { + $page = intval($page); + $this->page = $page > 0 ? $page - 1 : 0; + } + + public function load() { + + if( !empty( $this->searchColor ) ) { // ----------------------------------- color search + $this->thumbs = DB::query( + 'SELECT SQL_CALC_FOUND_ROWS + i.logged, UNIX_TIMESTAMP(i.logged) AS loggedTS, + i.keyword, i.thumb, i.score, i.votes, + u.name AS userName, + MIN( ABS(ic.r - :3) + ABS(ic.g - :4) + ABS(ic.b - :5) ) AS deviation + FROM '.TABLE_IMAGES.' i + LEFT JOIN '.TABLE_USERS.' u + ON u.id = i.user + LEFT JOIN '.TABLE_IMAGECOLORS.' ic + ON ic.imageId = i.id + WHERE + ic.r BETWEEN :3 - :6 AND :3 + :6 + AND + ic.g BETWEEN :4 - :6 AND :4 + :6 + AND + ic.b BETWEEN :5 - :6 AND :5 + :6 + GROUP BY i.id + ORDER BY deviation, i.id DESC + LIMIT :1, :2', + $this->page * $this->thumbsPerPage, + $this->thumbsPerPage, + + $this->searchColor['r'], + $this->searchColor['g'], + $this->searchColor['b'], + Config::$colorSearchDev + ); + } + else if( $this->searchTerm ) { // ------------------------ fulltext search + $ftq = preg_replace( '/\s+/',' +', $this->searchTerm ); + $this->thumbs = DB::query( + 'SELECT SQL_CALC_FOUND_ROWS + i.logged, UNIX_TIMESTAMP(i.logged) AS loggedTS, + i.keyword, i.thumb, i.score, i.votes, + u.name AS userName + FROM '.TABLE_IMAGES.' i + LEFT JOIN '.TABLE_USERS.' u + ON u.id = i.user + WHERE + i.image LIKE :3 + OR MATCH( i.tags ) AGAINST ( :4 IN BOOLEAN MODE ) + ORDER BY i.id DESC + LIMIT :1, :2', + $this->page * $this->thumbsPerPage, + $this->thumbsPerPage, + + '%'.$this->searchTerm.'%', + $ftq + ); + } + else { // -------------------------------------------------------- user/all + $conditions = ''; + if( !empty($this->user) ) { + $conditions .= ' AND i.user = :3'; + } + + $this->thumbs = DB::query( + 'SELECT SQL_CALC_FOUND_ROWS + i.logged, UNIX_TIMESTAMP(i.logged) AS loggedTS, + i.keyword, i.thumb, i.score, i.votes, + u.name AS userName + FROM '.TABLE_IMAGES.' i + LEFT JOIN '.TABLE_USERS.' u + ON u.id = i.user + WHERE 1 '.$conditions.' + ORDER BY i.id DESC + LIMIT :1, :2', + + $this->page * $this->thumbsPerPage, + $this->thumbsPerPage, + $this->user['id'] + ); + } + + $this->totalResults = DB::foundRows(); + + + // compute previoues, current and next page + if( $this->totalResults > 0 ) { + $this->pages['current'] = $this->page+1; + $this->pages['total'] = ceil($this->totalResults / $this->thumbsPerPage); + if( $this->page > 0 ) { + $this->pages['prev'] = $this->page; + } + if( $this->totalResults > $this->thumbsPerPage * $this->page + $this->thumbsPerPage ) { + $this->pages['next'] = $this->page + 2; + } + } + } + + public function loadRandom( $minScore, $thumbSize ) { + $this->thumbs = DB::query( + 'SELECT SQL_CALC_FOUND_ROWS + i.logged, UNIX_TIMESTAMP(i.logged) AS loggedTS, + i.keyword, i.thumb, i.score, i.votes, + u.name AS userName + FROM '.TABLE_IMAGES.' i + LEFT JOIN '.TABLE_USERS.' u + ON u.id = i.user + WHERE i.score >= :2 + ORDER BY RAND() + LIMIT :1', + + $this->thumbsPerPage, + $minScore + ); + + foreach( array_keys( $this->thumbs ) as $i ) { + $this->thumbs[$i]['thumb'] = Config::$images['thumbPath'] . + str_replace( '-', '/', substr( $this->thumbs[$i]['logged'], 0, 7 ) ) + .'/'. $thumbSize + .'/'. $this->thumbs[$i]['thumb']; + } + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/imagecatalog.php b/picturelicious/lib/imagecatalog.php new file mode 100644 index 0000000..3d90ce4 --- /dev/null +++ b/picturelicious/lib/imagecatalog.php @@ -0,0 +1,61 @@ +user = DB::getRow( + 'SELECT id, name, score, images, avatar, website + FROM '.TABLE_USERS.' + WHERE + valid = 1 AND + name = :1', + $name + ); + if( !empty($this->user) ) { + $this->basePath = 'user/'.$this->user['name'].'/'; + } + } + + public function setSearch( $term ) { + + $this->basePath = 'search/'.htmlspecialchars($term).'/'; + + if( preg_match( '/^\s*0x([0-9a-f]{6})\s*$/i', $term, $m ) ) { + $c = str_split( $m[1], 2 ); + $this->searchColor = array( + 'r' => hexdec($c[0]), + 'g' => hexdec($c[1]), + 'b' => hexdec($c[2]), + ); + } + else if( !empty($term) ) { + $this->searchTerm = $term; + $ftq = preg_replace( '/\s+/',' +', $this->searchTerm ); + $this->seachCondition .= " AND ( + i.image LIKE ".DB::quote('%'.$this->searchTerm.'%')." + OR MATCH( i.tags ) AGAINST ( ".DB::quote($ftq)." IN BOOLEAN MODE ) + )"; + } + } + + + + public function load() { + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/images.php b/picturelicious/lib/images.php new file mode 100644 index 0000000..dc2425b --- /dev/null +++ b/picturelicious/lib/images.php @@ -0,0 +1,98 @@ + 4096 + || $srcHeight < 1 || $srcHeight > 4096 + ) { + return false; + } + + if( $type == IMAGETYPE_JPEG ) { + $imgcreate = 'ImageCreateFromJPEG'; + } else if( $type == IMAGETYPE_GIF ) { + $imgcreate = 'ImageCreateFromGIF'; + } else if( $type == IMAGETYPE_PNG ) { + $imgcreate = 'ImageCreateFromPNG'; + } else { + return false; + } + + $thumbDirName = dirname( $thumbPath ); + + if( ( $srcWidth/$srcHeight ) > ( $thumbWidth/$thumbHeight ) ) { + $zoom = ($srcWidth/$srcHeight) / ($thumbWidth/$thumbHeight); + $srcX = ($srcWidth - $srcWidth / $zoom) / 2; + $srcWidth = $srcWidth / $zoom; + } + else { + $zoom = ($thumbWidth/$thumbHeight) / ($srcWidth/$srcHeight); + $srcY = ($srcHeight - $srcHeight / $zoom) / 2; + $srcHeight = $srcHeight / $zoom; + } + + $thumb = Imagecreatetruecolor( $thumbWidth, $thumbHeight ); + $orig = $imgcreate( $imgPath ); + Imagecopyresampled($thumb, $orig, 0, 0, $srcX, $srcY, $thumbWidth, $thumbHeight, $srcWidth, $srcHeight); + + if( Config::$images['sharpen'] && function_exists('imageconvolution') ) { + $sharpenMatrix = array( array(-1,-1,-1), array(-1,16,-1), array(-1,-1,-1) ); + imageconvolution($thumb, $sharpenMatrix, 8, 0); + } + imagejpeg( $thumb, $thumbPath, Config::$images['jpegQuality'] ); + + // clean up + Imagedestroy( $thumb ); + Imagedestroy( $orig ); + + return true; + } + + public static function getColors( $imgPath, $size ) { + list( $srcWidth, $srcHeight, $type ) = getimagesize( $imgPath ); + + if( $type == IMAGETYPE_JPEG ) { + $imgcreate = 'ImageCreateFromJPEG'; + } else if( $type == IMAGETYPE_GIF ) { + $imgcreate = 'ImageCreateFromGIF'; + } else if( $type == IMAGETYPE_PNG ) { + $imgcreate = 'ImageCreateFromPNG'; + } else { + return array(); + } + + $orig = $imgcreate( $imgPath ); + + $thumb = Imagecreatetruecolor( $size, $size ); + Imagecopyresampled($thumb, $orig, 0, 0, 0, 0, $size, $size, $srcWidth, $srcHeight); + + $colors = array(); + for( $x = 0; $x < $size; $x++ ) { + for( $y = 0; $y < $size; $y++ ) { + $rgb = ImageColorAt($thumb, $x, $y); + $r = ($rgb >> 16) & 0xFF; + $g = ($rgb >> 8) & 0xFF; + $b = $rgb & 0xFF; + $colors[] = array( + 'r' => $r, + 'g' => $g, + 'b' => $b + ); + } + } + return $colors; + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/imageuploader.php b/picturelicious/lib/imageuploader.php new file mode 100644 index 0000000..54e9221 --- /dev/null +++ b/picturelicious/lib/imageuploader.php @@ -0,0 +1,170 @@ +login(); + + if( !$user->id ) { + $errors['notLoggedIn'] = 'You are not logged in!'; + return false; + } + + // no non-images + if( + !preg_match( '/([^\/]*?)\.(gif|jpg|jpeg|png)$/i', $name, $fileMatch ) + ) { + $errors['wrongExtension'] = 'Your file has not the right extension (gif, jpg or png)!'; + return false; + } + + $time = time(); + $keyword = Keyword::get( $fileMatch[1] ); + + // Iterate over all keywords, if this one is allready taken + $taken = array(); + $r = DB::query( 'SELECT keyword FROM '.TABLE_IMAGES.' WHERE keyword LIKE :1', date('Y/m/',$time).$keyword.'%' ); + foreach( $r as $v ) { + $taken[] = substr($v['keyword'],8); // Keyword without date! + } + $keyword = Keyword::iterate( $keyword, $taken ); + + list( $srcWidth, $srcHeight, $type ) = getimagesize( $localPath ); + if( $type == IMAGETYPE_JPEG ) { + $extension = 'jpg'; + } else if( $type == IMAGETYPE_GIF ) { + $extension = 'gif'; + } else if( $type == IMAGETYPE_PNG ) { + $extension = 'png'; + } else { + return false; + } + + $thumbName = $keyword.".jpg"; // all thumbs are jpegs! + $name = $keyword.".".$extension; + $imageDir = Config::$images['imagePath'] . date('Y/m', $time); + $thumbDir = Config::$images['thumbPath'] . date('Y/m', $time); + $imagePath = $imageDir.'/'.$name; + + if( !Filesystem::mkdirr($imageDir) || !Filesystem::mkdirr($thumbDir) ) { + return false; + } + + if( $uploaded ) { + if( !@move_uploaded_file( $localPath, $imagePath ) ) { + return false; + } + } else { + if( !@rename( $localPath, $imagePath ) ) { + return false; + } + } + + $hash = md5_file( $imagePath ); + $c = DB::query('SELECT id FROM '.TABLE_IMAGES.' WHERE hash = :1', $hash); + if( !empty( $c ) ) { + unlink( $imagePath ); + $errors['duplicate'] = 'This image is already in our database!'; + return false; + } + + // make thumbs + foreach( Config::$gridView['classes'] as $gc ) { + $thumbPath = $thumbDir.'/'.$gc['dir'].'/'.$thumbName; + Filesystem::mkdirr($thumbDir.'/'.$gc['dir']); + if( !Image::createThumb( $imagePath, $thumbPath, + $gc['width'] * Config::$gridView['gridSize'] - Config::$gridView['borderWidth'], + $gc['height'] * Config::$gridView['gridSize'] - Config::$gridView['borderWidth'] + )) { + unlink( $imagePath ); + $errors['internalError'] = 'Internal error processing the image!'; + return false; + } + } + + + $user->increaseScore( Config::$postScore ); + + DB::query( 'UPDATE '.TABLE_USERS.' SET images = images + 1 WHERE id = :1', $user->id ); + + DB::insertRow( TABLE_IMAGES, + array( + 'logged' => date('Y-m-d H:i:s', $time), + 'user' => $user->id, + 'score' => 3, + 'votes' => 0, + 'keyword' => date('Y/m/', $time).$keyword, + 'tags' => $tags, + 'image' => $name, + 'thumb' => $thumbName, + 'hash' => $hash, + 'source' => $source + ) + ); + $imageId = DB::insertId(); + + $colors = Image::getColors( $imagePath, 4 ); + foreach( $colors as $c ) { + DB::insertRow( TABLE_IMAGECOLORS, + array( + 'imageId' => $imageId, + 'r' => $c['r'], + 'g' => $c['g'], + 'b' => $c['b'] + ) + ); + } + return true; + } +} +?> \ No newline at end of file diff --git a/picturelicious/lib/imageviewer.php b/picturelicious/lib/imageviewer.php new file mode 100644 index 0000000..93c8510 --- /dev/null +++ b/picturelicious/lib/imageviewer.php @@ -0,0 +1,122 @@ +keyword = $keyword; + } + + public function addComment( $userId, $comment ) { + if( $this->image['id'] && $userId && !empty($comment) ) { + DB::insertRow( TABLE_COMMENTS, array( + 'imageId' => $this->image['id'], + 'userId' => $userId, + 'created' => date( 'Y.m.d H:i:s' ), + 'content' => $comment + )); + return true; + } else { + return false; + } + } + + public function load() { + $conditions = ''; + if( !empty($this->user) ) { + $conditions .= ' AND i.user = :2'; + $this->userInfo = $this->user; + } + + + $this->image = DB::getRow( + 'SELECT + i.id, i.logged, UNIX_TIMESTAMP(i.logged) AS loggedTS, + i.keyword, i.image, i.score, i.votes, + tags, u.name AS userName, i.user + FROM '.TABLE_IMAGES.' i + LEFT JOIN '.TABLE_USERS.' u + ON u.id = i.user + WHERE i.keyword = :1 '.$conditions, + $this->keyword, + $this->user['id'] + ); + $this->image['path'] = date('Y/m/', $this->image['loggedTS']).$this->image['image']; + + if( empty( $this->user) ) { + $this->userInfo = DB::getRow( + 'SELECT id, name, score, images, avatar, website + FROM '.TABLE_USERS.' + WHERE + id = :1', + $this->image['user'] + ); + } + + // compute previoues and next page + $next = DB::getRow( + 'SELECT i.keyword + FROM '.TABLE_IMAGES.' i + WHERE i.id < :1 '.$conditions.' + ORDER BY id DESC + LIMIT 1', + $this->image['id'], + $this->user['id'] + ); + + $prev = DB::getRow( + 'SELECT i.keyword + FROM '.TABLE_IMAGES.' i + WHERE i.id > :1 '.$conditions.' + ORDER BY id ASC + LIMIT 1', + $this->image['id'], + $this->user['id'] + ); + + + + if( !empty($next) ) { + $this->stream['next'] = $next['keyword']; + } + if( !empty($prev) ) { + $this->stream['prev'] = $prev['keyword']; + } + } + + public function loadComments() { + $this->comments = DB::query( + 'SELECT + c.id, c.content, u.name, u.avatar, + UNIX_TIMESTAMP(c.created) AS created + FROM '.TABLE_COMMENTS.' c + LEFT JOIN '.TABLE_USERS.' u + ON u.id = c.userId + WHERE c.imageId = :1 + ORDER BY created', + $this->image['id'] + ); + $this->commentCount = count( $this->comments ); + + foreach( array_keys($this->comments) as $i ) { + $this->comments[$i]['content'] = preg_replace( + '#(?]+)#i', + "$3$4", + nl2br( htmlspecialchars($this->comments[$i]['content']) ) + ); + } + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/keyword.php b/picturelicious/lib/keyword.php new file mode 100644 index 0000000..5c77b87 --- /dev/null +++ b/picturelicious/lib/keyword.php @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/picturelicious/lib/userlist.php b/picturelicious/lib/userlist.php new file mode 100644 index 0000000..f9fc9d9 --- /dev/null +++ b/picturelicious/lib/userlist.php @@ -0,0 +1,57 @@ +usersPerPage = abs(intval($usersPerPage)); + } + + public function setPage( $page ) { + $page = intval($page); + $this->page = $page > 0 ? $page - 1 : 0; + } + + public function load() { + $this->users = DB::query( + 'SELECT SQL_CALC_FOUND_ROWS + UNIX_TIMESTAMP( u.registered ) as registered, + u.name, u.score, u.images, u.avatar, u.website + FROM '.TABLE_USERS.' u + WHERE valid = 1 + GROUP BY u.id + ORDER BY u.score DESC + LIMIT :1, :2', + $this->page * $this->usersPerPage, + $this->usersPerPage + ); + $this->totalResults = DB::foundRows(); + + // compute previoues, current and next page + if( $this->totalResults > 0 ) { + $this->pages['current'] = $this->page+1; + $this->pages['total'] = ceil($this->totalResults / $this->usersPerPage); + if( $this->page > 0 ) { + $this->pages['prev'] = $this->page; + } + if( $this->totalResults > $this->usersPerPage * $this->page + $this->usersPerPage ) { + $this->pages['next'] = $this->page + 2; + } + } + } +} + +?> \ No newline at end of file diff --git a/picturelicious/lib/users.php b/picturelicious/lib/users.php new file mode 100644 index 0000000..5d4e3e7 --- /dev/null +++ b/picturelicious/lib/users.php @@ -0,0 +1,295 @@ + $u['id']), array( 'valid' => 1) ); + + session_name( Config::$sessionCookie ); + session_start(); + $_SESSION['id'] = $this->id = $u['id']; + $_SESSION['name'] = $this->name = $u['name']; + $_SESSION['admin'] = $this->admin = $u['admin']; + $_SESSION['website'] = $this->website = $u['website']; + + setcookie( Config::$rememberCookie, $id, time() + 3600 * 24 * 365, Config::$absolutePath ); + + if( Config::$vbbIntegration['enabled'] ) { + global $vbulletin; + $forum = new ForumOps($vbulletin); + $forum->login(array('username' => $u['name'])); + } + return true; + } + + public function isSpamLocked() { + // delete all ips older than IP_LOCK_TIME + DB::query( 'DELETE FROM '.TABLE_UPLOADLOCK.' WHERE ts < :1', time() - Config::$uploadLockTime ); + + list(, $ip) = unpack('l',pack('l',ip2long($_SERVER['REMOTE_ADDR']))); + $r = DB::getRow( 'SELECT COUNT(*) AS c FROM '.TABLE_UPLOADLOCK.' + WHERE ip = :1', + $ip + ); + + if( $r['c'] > Config::$maxNumUploads ) { + return true; + } else { + return false; + } + } + + public function logUpload() { + list(, $ip) = unpack('l',pack('l',ip2long($_SERVER['REMOTE_ADDR']))); + DB::insertRow( TABLE_UPLOADLOCK, array('ip' => $ip, 'ts' => time()) ); + } + + public function login() { + + // attempt to login via post, session or remeber cookie + session_name( Config::$sessionCookie ); + + if( isset($_POST['login']) ) { // post login + $u = DB::getRow( + 'SELECT id, name, admin, website FROM '.TABLE_USERS.' WHERE name = :1 AND pass = :2 and valid = 1', + $_POST['name'], md5($_POST['pass']) + ); + if( !empty($u) ) { + session_start(); + $_SESSION['id'] = $this->id = $u['id']; + $_SESSION['name'] = $this->name = $u['name']; + $_SESSION['admin'] = $this->admin = $u['admin']; + $_SESSION['website'] = $this->website = $u['website']; + + if( !empty($_POST['remember']) ) { + $r = md5(uniqid(rand())); + DB::updateRow( TABLE_USERS, array('id' => $this->id), array('remember' => $r ) ); + setcookie( Config::$rememberCookie, $r, time() + 3600 * 24 * 365, Config::$absolutePath ); + } + + if( Config::$vbbIntegration['enabled'] ) { + global $vbulletin; + $forum = new ForumOps($vbulletin); + $forum->login(array('username' => $u['name'])); + } + } + } + + else if( !empty($_COOKIE[Config::$sessionCookie]) ) { // session running + session_start(); + if( empty($_SESSION['id']) ) { + setcookie(Config::$sessionCookie, false, time() - 3600, Config::$absolutePath ); + } else { + $this->id = $_SESSION['id']; + $this->name = $_SESSION['name']; + $this->admin = $_SESSION['admin']; + $this->website = $_SESSION['website']; + } + } + + else if( !empty($_COOKIE[Config::$rememberCookie]) ) { // remember cookie found + $u = DB::getRow( + 'SELECT id, name, admin, website FROM '.TABLE_USERS.' WHERE remember = :1', + $_COOKIE[Config::$rememberCookie] + ); + if( !empty($u) ) { + + session_start(); + $_SESSION['id'] = $this->id = $u['id']; + $_SESSION['name'] = $this->name = $u['name']; + $_SESSION['admin'] = $this->admin = $u['admin']; + $_SESSION['website'] = $this->website = $u['website']; + + // refresh for another year + setcookie( Config::$rememberCookie, $_COOKIE[Config::$rememberCookie], time() + 3600 * 24 * 365, Config::$absolutePath ); + + if( Config::$vbbIntegration['enabled'] ) { + global $vbulletin; + $forum = new ForumOps($vbulletin); + $forum->login(array('username' => $u['name'])); + } + } + } + } + + public function profile( $localFile, &$messages ) { + $upd = array( 'website' => $_POST['website'] ); + + $_SESSION['website'] = $_POST['website']; + + if( Config::$vbbIntegration['enabled'] ) { + global $vbulletin; + $forum = new ForumOps($vbulletin); + } + + $p = trim($_POST['cpass']); + if( !empty( $p ) ) { + if( strlen($_POST['cpass']) < 6 ) { + $messages['passToShort'] = true; + } + else if( $_POST['cpass'] != $_POST['cpass2'] ) { + $messages['passNotEqual'] = true; + } + else { + $upd['pass'] = md5($_POST['cpass2']); + if( Config::$vbbIntegration['enabled'] ) { + $forum->set_pass( $_SESSION['name'], $_POST['cpass2']); + } + } + } + + if( !empty( $localFile ) ) { + require_once( 'lib/images.php' ); + $name = Config::$images['avatarsPath'].uniqid().'.jpg'; + if( Image::createThumb( $localFile, $name, 40,40 ) ) { + $upd['avatar'] = $name; + } else { + $messages['avatarFailed'] = true; + } + } + + if( empty($this->email) && + preg_match('/^[\.\w\-]{1,}@[\.\w\-]{2,}\.[\w]{2,}$/', $_POST['email']) + ) { + if( Config::$vbbIntegration['enabled'] ) { + $forum->set_email( $_SESSION['name'], $_POST['email']); + } + $upd['email'] = $_POST['email']; + } + + DB::updateRow( TABLE_USERS, array( 'id' => $this->id ), $upd ); + } + + public function loadEmail() { + $tmp = DB::getRow( + 'SELECT email FROM '.TABLE_USERS.' WHERE id = :1', + $this->id + ); + $this->email = $tmp['email']; + } + + public function logout() { + session_unset(); + session_destroy(); + $_SESSION = array(); + setcookie( Config::$rememberCookie, false, time() - 3600, Config::$absolutePath ); + setcookie( Config::$sessionCookie, false, time() - 3600, Config::$absolutePath ); + + if( Config::$vbbIntegration['enabled'] ) { + global $vbulletin; + $forum = new ForumOps($vbulletin); + $forum->logout(); + } + } + + public function increaseScore( $amount ) { + DB::query( + 'UPDATE '.TABLE_USERS.' SET score = score + :1 WHERE id = :2', + intval( $amount ), + $this->id + ); + } + + public function register( &$messages ) { + + DB::query( 'DELETE FROM '.TABLE_USERS.' WHERE valid = 0 AND registered < NOW() - INTERVAL 30 MINUTE' ); + + if( !preg_match('/^\w{2,20}$/', $_POST['name']) ) { + $messages['nameInvalid'] = true; + } else { + $u = DB::getRow( 'SELECT * FROM '.TABLE_USERS.' WHERE name = :1', $_POST['name'] ); + if( !empty($u) ) { + $messages['nameInUse'] = true; + } + } + + if( strlen($_POST['pass']) < 6 ) { + $messages['passToShort'] = true; + } + else if( $_POST['pass'] != $_POST['pass2'] ) { + $messages['passNotEqual'] = true; + } + + if( !preg_match( '/^[\.\w\-]{1,}@[\.\w\-]{2,}\.[\w]{2,}$/', $_POST['email'] ) ) { + $messages['wrongEmail'] = true; + } else { + $u = DB::getRow( 'SELECT * FROM '.TABLE_USERS.' WHERE email = :1', $_POST['email'] ); + if( !empty($u) ) { + $messages['emailInUse'] = true; + } + } + + + if( !empty($messages) ) { + return false; + } + + + $this->validationString = md5(uniqid(rand())); + + DB::insertRow( TABLE_USERS, array( + 'registered' => date('Y-m-d H:i:s'), + 'name' => $_POST['name'], + 'pass' => md5($_POST['pass']), + 'valid' => 0, + 'score' => 0, + 'images' => 0, + 'website' => '', + 'avatar' => Config::$images['avatarsPath'].'default.png', + 'remember' => $this->validationString, + 'admin' => 0, + 'email' => $_POST['email'] + )); + + if( Config::$vbbIntegration['enabled'] ) { + global $vbulletin; + $forum = new ForumOps($vbulletin); + $user['name'] = $_POST['name']; + $user['pass'] = $_POST['pass']; + $user['email'] = $_POST['email']; + echo $forum->register_newuser($user, false); + } + + $mail = file_get_contents( Config::$templates.'registrationmail.txt' ); + preg_match( '/From: (?.*?)\r?\nSubject: (?.*?)\r?\n\r?\n(?.*)/sim', $mail, $mail ); + $mail['text'] = str_replace( '%validationString%', $this->validationString, $mail['text'] ); + $mail['text'] = str_replace( '%siteName%', Config::$siteName, $mail['text'] ); + $mail['text'] = str_replace( '%frontendPath%', Config::$frontendPath, $mail['text'] ); + $mail['text'] = str_replace( '%userName%', $_POST['name'], $mail['text'] ); + + $mail['subject'] = str_replace( '%siteName%', Config::$siteName, $mail['subject'] ); + $mail['subject'] = str_replace( '%userName%', $_POST['name'], $mail['subject'] ); + + mail( $_POST['email'], $mail['subject'], $mail['text'], 'FROM: '.$mail['from'] ); + return true; + } +} + +?> \ No newline at end of file diff --git a/picturelicious/media/color.png b/picturelicious/media/color.png new file mode 100644 index 0000000..662ae6f Binary files /dev/null and b/picturelicious/media/color.png differ diff --git a/picturelicious/media/colorpicker-h.png b/picturelicious/media/colorpicker-h.png new file mode 100644 index 0000000..fc8ddc4 Binary files /dev/null and b/picturelicious/media/colorpicker-h.png differ diff --git a/picturelicious/media/colorpicker-select-h.png b/picturelicious/media/colorpicker-select-h.png new file mode 100644 index 0000000..b765793 Binary files /dev/null and b/picturelicious/media/colorpicker-select-h.png differ diff --git a/picturelicious/media/colorpicker-select-sv.png b/picturelicious/media/colorpicker-select-sv.png new file mode 100644 index 0000000..7f2a36d Binary files /dev/null and b/picturelicious/media/colorpicker-select-sv.png differ diff --git a/picturelicious/media/colorpicker-sv.png b/picturelicious/media/colorpicker-sv.png new file mode 100644 index 0000000..59fc626 Binary files /dev/null and b/picturelicious/media/colorpicker-sv.png differ diff --git a/picturelicious/media/favicon.ico b/picturelicious/media/favicon.ico new file mode 100644 index 0000000..f59bc1d Binary files /dev/null and b/picturelicious/media/favicon.ico differ diff --git a/picturelicious/media/loading.gif b/picturelicious/media/loading.gif new file mode 100644 index 0000000..0b1ba83 Binary files /dev/null and b/picturelicious/media/loading.gif differ diff --git a/picturelicious/media/logo.png b/picturelicious/media/logo.png new file mode 100644 index 0000000..86fc71d Binary files /dev/null and b/picturelicious/media/logo.png differ diff --git a/picturelicious/media/next.png b/picturelicious/media/next.png new file mode 100644 index 0000000..f5ca5c2 Binary files /dev/null and b/picturelicious/media/next.png differ diff --git a/picturelicious/media/picturelicious.js b/picturelicious/media/picturelicious.js new file mode 100644 index 0000000..92a9c18 --- /dev/null +++ b/picturelicious/media/picturelicious.js @@ -0,0 +1,400 @@ +function $(id){return document.getElementById(id)} +function gridView(id){ gridSolve(id); gridSolve(id); window.setInterval("gridSolve('"+id+"')",250); } +function swap(e, c1, c2) { e.className = e.className == c1 ? c2 : c1; }; + +// GridSolver ------------------------------------------------------------ +var gridSize = 64; +var gridMinWidth = 6; +var gridWidth = 0; +var grid = null; +var boxDef = { + 'b0': {'width': 3, 'height': 3}, + 'b1': {'width': 2, 'height': 2}, + 'b2': {'width': 1, 'height': 1} +}; + +function gridSolve( cid ) { + var container = $(cid); + var newWidth = parseInt( container.offsetWidth ); + var newGridWidth = parseInt( newWidth / gridSize ); + newGridWidth = newGridWidth < gridMinWidth ? gridMinWidth : newGridWidth; + + if( gridWidth == newGridWidth ) + return; + else + gridWidth = newGridWidth; + + boxes = new Array(); + while( container.hasChildNodes() ) { + e = container.removeChild( container.firstChild ); + if( e.tagName == 'DIV' ) { + boxes.push( e ); + } + } + + grid = new Array( gridWidth ); + for( var i = 0; i < grid.length; i++ ) { + grid[i] = 0; + } + + for(var i = 0; i < boxes.length; i++) { + insertThumb( boxes[i], cid ) + } + + var maxHeight = 0; + for( var i = 0; i < grid.length; i++) { + maxHeight = Math.max( maxHeight,grid[i] ); + } + container.style.height = (maxHeight * gridSize) + 'px'; + $('images').style.height = (maxHeight * gridSize) + 'px'; +} + +function insertThumb( box, cid ) { + var boxWidth = boxDef[box.className]['width']; + var boxHeight = boxDef[box.className]['height']; + var maxHeight = 0; + var currentHeight = -1; + var spotWidth = 0; + var spotLeft = 0; + var freeSpots = new Array(); + for( var i = 0; i < grid.length; i++) { + if( currentHeight == grid[i] ) { + spotWidth++; + } + + if( (currentHeight != grid[i] || i+1 == grid.length) && spotWidth > 0) { + freeSpots.push({'width': spotWidth, 'left': spotLeft, 'height': currentHeight}); + + spotWidth = 1; + spotLeft = i; + if(currentHeight != grid[i] && i+1 == grid.length) { + freeSpots.push({'width': spotWidth, 'left': spotLeft, 'height': grid[i]}); + } + } + + else if( spotWidth == 0 ) { + spotWidth = 1; + } + + currentHeight = grid[i]; + if( grid[i] > maxHeight ) { + maxHeight = grid[i]; + } + } + + var targetHeight = 0; + var targetLeft = 0; + var bestScore = -1; + for( var j = 0; j < boxWidth; j++ ) { + if( grid[j] > targetHeight ) { + targetHeight = grid[j]; + } + } + var newHeight = targetHeight + boxHeight; + + for( var i = 0; i < freeSpots.length; i++ ) { + var heightScore = ( maxHeight - freeSpots[i]['height'] ); + var widthScore = boxWidth / freeSpots[i]['width']; + var score = heightScore * heightScore + widthScore * 2; + + if( freeSpots[i]['width'] >= boxWidth && score > bestScore ) { + targetHeight = freeSpots[i]['height']; + targetLeft = freeSpots[i]['left']; + newHeight = freeSpots[i]['height'] + boxHeight; + bestScore = score; + } + } + + for( var j = 0; j < boxWidth; j++ ) { + grid[targetLeft + j] = newHeight; + } + + var container = $( cid ); + container.appendChild( box ); + box.style.left = (targetLeft * gridSize) + 'px'; + box.style.top = (targetHeight * gridSize) + 'px'; + return true; +} + +// Colorpicker ----------------------------------------------------------- +function colorpicker( id, size, onchange, onshow ) { + var that = this; + this.size = size; + this.onchange = onchange; + this.onshow = onshow; + + this.mode = 'none'; + + this.sv = $(id+'SV'); + this.svselect = $(id+'SVSelect'); + this.h = $(id+'H'); + this.hselect = $(id+'HSelect'); + this.value = $(id+'Value'); + this.current = $(id+'Current'); + + this.cap = function( v, min, max ) { + return Math.min(Math.max(min,v),max); + } + + this.getMousPos = function( event ) { + if(event.pageX || event.pageY){ + return { + 'x': event.pageX, + 'y': event.pageY + }; + } + return { + 'x': event.clientX + document.body.scrollLeft - document.body.clientLeft, + 'y': event.clientY + document.body.scrollTop - document.body.clientTop + }; + } + + this.getObjPos = function( obj ) { + var curleft = curtop = 0; + if (obj.offsetParent) { + curleft = obj.offsetLeft; + curtop = obj.offsetTop; + while (obj = obj.offsetParent) { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } + } + return { + 'x':curleft, + 'y':curtop + }; + } + + + this.release = function() { + document.onmousemove = ''; + this.mode = 'none'; + } + + this.move = function( event ) { + if (!event) var event = window.event; + if(event.pageX || event.pageY) { + var mx = event.pageX; + var my = event.pageY; + } else { + var mx = event.clientX + document.body.scrollLeft - document.body.clientLeft; + var my = event.clientY + document.body.scrollTop - document.body.clientTop; + } + if( this.mode == 'sv' ) { + var obj = this.getObjPos( this.sv ); + var x = this.cap(mx - obj.x - 3, -4, this.size - 4); + var y = this.cap(my - obj.y - 3, -4, this.size - 4); + this.svselect.style.left = x + "px"; + this.svselect.style.top = y + "px"; + } + else if ( this.mode == 'h' ) { + var obj = this.getObjPos( this.sv ); + var y = this.cap(my - obj.y - 2, -2, this.size - 3); + this.hselect.style.top = y + "px"; + this.sv.style.backgroundColor = '#' + this.rgb2hex(this.hsv2rgb( {'h':1-((y+3)/this.size), 's':1, 'v':1} )); + } + else return false; + + var hex = this.getHex(); + this.current.style.backgroundColor = '#' + hex; + this.value.innerHTML = '#' + hex; + this.onchange( this ); + return false; + } + + this.sv.onmousedown = function() { + that.mode = 'sv'; + document.onmousemove = function( event ) { that.move( event ) }; + document.onmouseup = that.release; + return false; + } + + this.h.onmousedown = function() { + that.mode = 'h'; + document.onmousemove = function( event ) { that.move( event ) }; + document.onmouseup = that.release; + return false; + } + + + this.getHSV = function() { + var svpos = this.getObjPos( this.sv ); + var svselectpos = this.getObjPos( this.svselect ); + + var hpos = this.getObjPos( this.h ); + var hselectpos = this.getObjPos( this.hselect ); + + return { + 'h': 1 - (this.cap(hselectpos.y - hpos.y + 3, 0, this.size) / this.size), + 's': this.cap(svselectpos.x - svpos.x + 2, 0, this.size) / this.size, + 'v': 1 - (this.cap(svselectpos.y - svpos.y + 4, 0, this.size) / this.size) + } + } + + this.getRGB = function() { + return this.hsv2rgb( this.getHSV() ); + } + + this.getHex = function() { + return this.rgb2hex( this.getRGB() ); + } + + this.toHex = function(v) { v=Math.round(Math.min(Math.max(0,v),255)); return("0123456789ABCDEF".charAt((v-v%16)/16)+"0123456789ABCDEF".charAt(v%16)); } + this.rgb2hex = function(c) { return this.toHex(c.r)+this.toHex(c.g)+this.toHex(c.b); } + + this.hsv2rgb = function( c ) { + var R, B, G, H = c.h, S = c.s, V = c.v; + if( S>0 ) { + if(H>=1) H=0; + + H=6*H; F=H-Math.floor(H); + A=Math.round(255*V*(1.0-S)); + B=Math.round(255*V*(1.0-(S*F))); + C=Math.round(255*V*(1.0-(S*(1.0-F)))); + V=Math.round(255*V); + + switch(Math.floor(H)) { + case 0: R=V; G=C; B=A; break; + case 1: R=B; G=V; B=A; break; + case 2: R=A; G=V; B=C; break; + case 3: R=A; G=B; B=V; break; + case 4: R=C; G=A; B=V; break; + case 5: R=V; G=A; B=B; break; + } + return {'r': (R?R:0), 'g': (G?G:0), 'b': (B?B:0)}; + } + else { + return {'r': (Math.round(V*255)), 'g': (Math.round(V*255)), 'b': (Math.round(V*255))}; + } + } +} + + +// Adjust height of prev/next bars in IE --------------------------------- +var ieAdjustCount = 0; +function ieAdjustHeight( oldHeight ) { + var pe = ($('viewer') ? $('viewer') : $('images')); + if( + !document.all || // IE + !( pe ) || + ( + pe.scrollHeight < oldHeight + 50 && + ieAdjustCount > 10 + ) + ) { + return; + } + ieAdjustCount++; + var newHeight = pe.scrollHeight; + $('prevBar').style.height = pe.scrollHeight + 'px'; + $('nextBar').style.height = pe.scrollHeight + 'px'; + setTimeout( 'ieAdjustHeight(' + newHeight + ')', 100 ); +} + + +// JSON functions for tagging, rating, deleting... ----------------------- +function post( url, params, callback ) { + if (window.ActiveXObject) { // ie + try { + req = new ActiveXObject( 'Msxml2.XMLHTTP' ); + } + catch (e) { + try { + req = new ActiveXObject( 'Microsoft.XMLHTTP' ); + } + catch (e) {} + } + } + else if (window.XMLHttpRequest) { // moz + req = new XMLHttpRequest(); + req.overrideMimeType( 'text/plain' ); + } + req.onreadystatechange = function(){ + if (req.readyState == 4 && req.status == 200) { + callback(); + } + }; + + if( !req ) return false; + req.open( 'POST', url, true ); + req.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded; charset=UTF-8' ); + req.setRequestHeader( 'Content-length', params.length ); + req.setRequestHeader( 'Connection', 'close' ); + req.send( params ); +} + +function addTags( imageId, inputField, admin ) { + $( 'loadTags' ).style.display = 'block'; + var tags = encodeURIComponent(inputField.value); + if( !admin ) { + inputField.value = ''; + } + post( + $('home').href + 'json.php?addTags', + 'id='+imageId+'&tags='+tags, + function(){ + q = ( eval('('+req.responseText+')') ); + if( q.tags ) { + $('tags').innerHTML = q.tags; + } + $('addTag').className='hidden'; + $( 'loadTags' ).style.display = 'none'; + } + ); + return false; +} + +function del( imageId ) { + if( !confirm( 'Delete this image?' ) ) return false; + $( 'loadDelete' ).style.display = 'block'; + post( + $('home').href + 'json.php?delete', + 'id='+imageId, + function(){ + $( 'loadDelete' ).style.display = 'none'; + $( 'del' ).style.display = 'none'; + } + ); + return false; +} + +function delComment( commentId, e ) { + if( !confirm( 'Delete this comment?' ) ) return false; + var cdiv = e.parentNode.parentNode.parentNode; + post( + $('home').href + 'json.php?deleteComment', + 'id='+commentId, + function(){ + cdiv.style.display = 'none'; + } + ); + return false; +} + +// mouseover for rating stars +function sr( id, scale ) { + $( id ).style.backgroundPosition = ( (20 * scale) - 100 ) + 'px 0'; +} + +function rate( imageId, score ) { + $( 'loadRating' ).style.display = 'block'; + post( + $('home').href + 'json.php?rate', + 'id='+imageId+'&score='+score, + function() { + q = ( eval('('+req.responseText+')') ); + $( 'loadRating' ).style.display = 'none'; + $( 'currentRating' ).style.width = 20 * parseFloat(q.score) + 'px'; + $( 'ratingDescription' ).innerHTML = q.score + ' after ' + q.votes + ' Vote' + ( q.votes > 1 ? 's' : '' ); + } + ); + return false; +} + +function s() { + var q = $( 'q' ); + if( q && q.value ) { + window.location = $('home').href + 'search/' + encodeURI( q.value ); + } + return false; +} \ No newline at end of file diff --git a/picturelicious/media/post.js.php b/picturelicious/media/post.js.php new file mode 100644 index 0000000..ed65b7c --- /dev/null +++ b/picturelicious/media/post.js.php @@ -0,0 +1,146 @@ + +function RP_RemotePost( postURL, stylesheet ) { + this.postURL = postURL; + this.stylesheet = stylesheet; + + this.visible = false; + this.menu = null; + this.dialog = null; + this.iframe = null; + this.checkSuccessInterval = 0; + this.minImageSize = 32; + + + this.create = function(){ + var that = this; + var css = document.createElement('link'); + css.type = 'text/css'; + css.rel = 'stylesheet'; + css.href = this.stylesheet; + if( document.getElementsByTagName("head").item(0) ) { + document.getElementsByTagName("head").item(0).appendChild( css ); + } else { + document.getElementsByTagName("body").item(0).appendChild( css ); + } + + var closeButton = document.createElement('a'); + closeButton.appendChild( document.createTextNode("x") ); + closeButton.className = 'close'; + closeButton.onclick = function() { return that.toggle(); } + closeButton.href = '#'; + + + this.dialog = document.createElement('div'); + this.dialog.id = 'RP_Dialog'; + this.iframe = document.createElement('iframe'); + this.iframe.src = 'about:blank'; + this.dialog.appendChild( this.iframe ); + this.dialog.appendChild( closeButton ); + document.body.appendChild( this.dialog ); + + this.loadIFrame( {} ); + } + + + this.loadIFrame = function( params ) { + var reqUrl = this.postURL + '?nocache=' + parseInt(Math.random()*10000); + for( p in params ) { + reqUrl += '&' + p + '=' + encodeURIComponent( params[p] ); + } + this.iframe.src = reqUrl; + } + + + this.selectImage = function( image ) { + var title = image.title ? image.title : ( image.alt ? image.alt : document.title ); + var imageSrc = image.src; + if( + image.parentNode.tagName.match(/^a$/i) && + image.parentNode.href && + image.parentNode.href.match(/\.(jpe?g|gif|png)$/i) + ) { + imageSrc = image.parentNode.href; + } + this.loadIFrame( { + 'url': imageSrc, + 'xhrLocation': document.location.href.replace(/#.*$/,'') + }); + return false; + } + + + this.checkSuccess = function() { + if( document.location.href.match(/#RP_Success/) ) { + var that = this; + document.location.href = document.location.href.replace(/#.*$/, '#'); + setTimeout( function() { that.hide() }, 500 ); + } + } + + + this.show = function() { + this.visible = true; + var that = this; + + this.checkSuccessInterval = setInterval( function() { that.checkSuccess(); }, 500 ); + this.dialog.style.display = 'block'; + + var images = document.getElementsByTagName('img'); + for( var i=0; i this.minImageSize && img.height > this.minImageSize) { + img.onclick = function( ev ) { + if( ev && ev.stopPropagation ) { + ev.stopPropagation(); + } + return that.selectImage(this); + }; + img.className = img.className ? img.className + ' RP_PostImage' : 'RP_PostImage'; + } + } + } + + + this.hide = function() { + this.visible = false; + + clearInterval( this.checkSuccessInterval ); + this.dialog.style.display = 'none'; + + var images = document.getElementsByTagName('img'); + for( var i=0; i this.minImageSize && img.height > this.minImageSize) { + img.onclick = null; + img.className = img.className.replace(/\s*RP_PostImage/, ''); + } + } + } + + + this.toggle = function() { + if( !this.visible ) { + this.show(); + } else { + this.hide(); + } + return false; + } + + + this.create(); +} + +if( typeof(RP_Instance) == 'undefined' ) { + var RP_Instance = new RP_RemotePost( + 'remotepost.php', + 'media/remotepost.css' + ); +} +RP_Instance.toggle(); diff --git a/picturelicious/media/prev.png b/picturelicious/media/prev.png new file mode 100644 index 0000000..1c146b0 Binary files /dev/null and b/picturelicious/media/prev.png differ diff --git a/picturelicious/media/quicktags.js b/picturelicious/media/quicktags.js new file mode 100644 index 0000000..c89eb55 --- /dev/null +++ b/picturelicious/media/quicktags.js @@ -0,0 +1,44 @@ +var nextImage = {}; +var preload = null; +function quickTag( logId, imageId, inputField ) { + var tags = encodeURIComponent(inputField.value); + + // swap nextImage + $('imageLocation').href = nextImage['link']; + $('imageLocation').innerHTML = nextImage['link']; + $('imageId').value = nextImage['id']; + $('logId').value = nextImage['logId']; + $('image').src = nextImage['image']; + $('tags').innerHTML = nextImage['tags']; + $('tagText').value = ''; + $('tagText').focus(); + + if( !nextImage['link'] ) { + $('imageInfo').innerHTML = 'No more Images found'; + } + + post( + $('home').href + 'json.php?quickTag', + 'logId='+logId+'&id='+imageId+'&tags='+tags, + function(){ + nextImage = ( eval('('+req.responseText+')') ); + preload = new Image(1,1) + preload.src=nextImage['image']; + } + ); + return false; +} + +function quickTagInit() { + swap($('quickTagIntro'), 'article', 'hidden'); + swap($('viewer'), 'hidden', 'visible'); + post( + $('home').href + 'json.php?quickTag', + '', + function(){ + nextImage = ( eval('('+req.responseText+')') ); + quickTag( 0, 0, $('tagText') ); + } + ); + return false; +} \ No newline at end of file diff --git a/picturelicious/media/remotepost.css b/picturelicious/media/remotepost.css new file mode 100644 index 0000000..4be4250 --- /dev/null +++ b/picturelicious/media/remotepost.css @@ -0,0 +1,58 @@ +img.RP_PostImage { + border: 2px dashed #00adef !important; + cursor: pointer !important; +} + + img.RP_PostImage:hover, img.RP_PostImageActive { + border: 2px solid #00adef !important; + } + +#RP_Dialog { + position: fixed; + top: 0; + left: 50%; + width: 450px; + margin-left: -243px; + padding: 0 18px 0 0; + z-index: 99999; + + background-color: #222 !important; + color: #ccc !important; + + font-size: 12pt; + font-family: Arial, Helvetica, sans-serif; + font-weight: normal; + font-style: normal; + text-align: left; + border-left: 1px solid #fff; + border-right: 1px solid #ccc; + border-bottom: 1px solid #aaa; +} + +#RP_Dialog iframe { + width: 450px; + height: 100px; + border: 0; +} + +#RP_Dialog a { + color: #fff !important; + background: transparent none !important; + text-decoration: none !important; + border: 0 !important; +} + +#RP_Dialog a:hover { + color: #000 !important; + background: #fff none !important; + text-decoration: none !important; + border: 0 !important; +} + +#RP_Dialog a.close { + position: absolute !important; + top: 0 !important; + right: 0 !important; + padding: 3px 10px; + font-weight: bold; +} diff --git a/picturelicious/media/search.png b/picturelicious/media/search.png new file mode 100644 index 0000000..de3dba2 Binary files /dev/null and b/picturelicious/media/search.png differ diff --git a/picturelicious/media/star-base.png b/picturelicious/media/star-base.png new file mode 100644 index 0000000..22eb816 Binary files /dev/null and b/picturelicious/media/star-base.png differ diff --git a/picturelicious/media/star-current.png b/picturelicious/media/star-current.png new file mode 100644 index 0000000..a7c33a1 Binary files /dev/null and b/picturelicious/media/star-current.png differ diff --git a/picturelicious/media/star-rate.png b/picturelicious/media/star-rate.png new file mode 100644 index 0000000..532f57e Binary files /dev/null and b/picturelicious/media/star-rate.png differ diff --git a/picturelicious/media/styles.css b/picturelicious/media/styles.css new file mode 100644 index 0000000..55d56da --- /dev/null +++ b/picturelicious/media/styles.css @@ -0,0 +1,587 @@ + +/* ----------------------------------------------- +layout & typo */ + +body { + background-color: #222; + color: #ccc; + font-family: Arial, Verdana, Trebuchet MS; + font-size: 10pt; + margin: 0; + padding: 0 0 1em 0; +} + +div#menu { + height: 67px; + background-color: #000; + border-bottom: 1px solid #333; +} + +div.userMenu { + float: right; + font-size: 90%; + margin: 30px 30px 0 0; +} + +div.search { + position: relative; + float: left; + font-size: 70%; + margin: 30px 30px 0 30px; +} + +div.menuItems { + position: relative; + float: left; + font-size: 90%; +} + +div.menuItems a { + float: left; + display: block; + height: 37px; + padding: 30px 12px 0 12px; + border-left: 1px solid #222; + background-color: #111; +} + +div.menuItems a:hover { + background-color: #333; + color: #fff; +} + +div.search input { + font-size: 100%; +} + +input.search { + background-image: url(search.png); + background-repeat: no-repeat; + background-position: 2px 2px; + color: #fff; + text-align: right; + width: auto; + padding-left: 14px; +} + +input.color { + background-image: url(color.png); + background-repeat: no-repeat; + width: 18px; +} + +img#logo { + float: left; +} + +img { + border: 0; +} + +div#content { + margin: 0.3em 1em; +} + + +div#footer { + color: #444; + text-align: right; + margin: 0.3em 1em; +} + +span.love { + color: #7b0043; +} + +h1 { + color: #fff; + font-size: 90%; + font-weight: normal; + text-transform: uppercase; +} + +h1.remotePost { + font-size: 110%; + font-weight: bold; + text-transform: none; +} + +h2 { + margin-top: 3em; + color: #fff; + font-size: 110%; + font-weight: bold; +} + +a { + color: #fff; + text-decoration: none; +} + +a:hover { + color: #000; + background-color: #fff; +} + +div.article { + margin-left: 1em; + width: 40em; +} + +ul { + list-style-type: square; +} + + +/* ----------------------------------------------- +prev next bars */ + +a.next, a.prev, div.noPrev, div.noNext { + text-indent: 16px; + color: #fff; + width: 12px; + overflow: hidden; + display: block; + text-align: center; + position: absolute; +} + +/* Hide from IE < 7 */ +a.next[class], a.prev[class], div.noPrev[class], div.noNext[class] { + height: 100%; +} + +a.prev { + background-color: #4bbed5; + background-image: url(prev.png); + background-position: -12px 0; + left: 0; + top: 0; +} + a.prev:hover { + background-position: -24px 0; + } + + +a.next { + background-color: #4bbed5; + background-image: url(next.png); + background-position: -12px 0; + right: 0; + top: 0; +} + + a.next:hover { + background-position: 0 0; + } + +div.noPrev { + background-image: url(prev.png); + background-position: 0 0; + left: 0; + top: 0; +} + +div.noNext { + background-image: url(next.png); + background-position: -24px 0; + right: 0; + top: 0; +} + + + + +/* ----------------------------------------------- +grid view */ + +div#images { + position: relative; +} + + div#imageGrid { + margin: 0 13px; + left: 0; + top: 0; + position: relative; + } + + #imageGrid div { + position: absolute; + overflow: hidden; + } + .b0 { + width: 192px; + height: 192px; + } + .b1 { + width: 128px; + height: 128px; + } + .b2 { + width: 64x; + height: 64px; + } + + a.thumb { + display: block; + padding: 1px; + background-color: #fff; + } + + a.thumb:hover img { + opacity: 0.8; + filter: alpha( opacity = 80 ); + } + + +/* ----------------------------------------------- +single image view */ + +div#viewer { + position: relative; +} + + div#imageContainer { + margin: 0 14px; + overflow: auto; + } + + img#image { + display:block; + border: 2px solid #fff; + margin: 1em auto; + } + + img#image[src] { + cursor: pointer; + } + + img.scaled { + max-width: 90%; + max-height: 500px; + } + + img.full { + max-width: none; + max-height: none; + } + +div#imageInfo { + width: 500px; + margin: 1em auto; + overflow: hidden; + background-color: #1a1a1a; + padding: 1em; + position: relative; +} + +div.date { + position: absolute; + right: 1em; + top: 1em; + font-style: italic; +} + +div.teaser { + margin: 1em 0; +} + +.hidden { + display: none; +} +.visible { + display: block; +} + + +/* Comments +---------------------------------------------------------*/ +div.comments h3 { + font-size: 10pt; + color: #fff; +} + +form.addComment { + margin-top: 10px; +} + +textarea { + font-family: Arial, Verdana, Trebuchet MS; + font-size: 10pt; + border: 1px solid #333; + background-color: #000; + color: #fff; + margin-bottom: 3px; + width: 100%; +} + +textarea:focus { + border: 1px solid #fff; +} + +div.comment { + background-color: #000; + padding: 2px 5px; + border-left: 2px solid #444; + margin: 10px 0; +} + +div.commentHead { + color: #888; + font-style: italic; + margin-bottom: 2px; +} +img.avatarSmall { + height:16px; + width:16px; + vertical-align:bottom; +} + + + +/* image rating +---------------------------------------------------------*/ +div.rating { + font-weight: bold; + margin-bottom: 0.5em; + position: relative; +} + + div.rating span { + display: block; + padding-top: 2px; + } + + div.ratingBase { + position: relative; + float: left; + margin-right: 0.5em; + width: 102px; + height: 20px; + background-image: url( star-base.png ); + } + + div.ratingCurrent { + position: absolute; + top: 0; + left: 0; + height: 20px; + background-image: url( star-current.png ); + } + + div.ratingRate { + position: absolute; + top: 0; + left: 0; + width: 102px; + height: 20px; + background-image: url( star-rate.png ); + background-repeat: no-repeat; + background-position: -100px 0; + } + + div.ratingRate a { + display: block; + height: 20px; + width: 20px; + float: left; + } + + div.ratingRate a:hover { + background: transparent; + } + + div.load { + background-image: url( loading.gif ); + background-repeat: no-repeat; + float: left; + margin-top: 3px; + width: 14px; + height: 14px; + display: none; + } + + +/* UserInfo +---------------------------------------------------------*/ + +div.userInfo { + margin: 1em 0; + border: 1px solid #555; + background-color: #333; + color: #fff; + position: relative; +} + +img.avatar { + float: left; + margin-right: 1em; + position: relative; +} + +div.name { + margin-top: 0.1em; + font-size: 130%; +} + +a.textPrev, div.textNoPrev { + display: block; + float: left; +} + +a.textNext, div.textNoNext { + display: block; + float: right; +} + + +/* Forms +---------------------------------------------------------*/ + +div.warn { + background-color: #7a0d00; + padding: 0.1em 0.4em; + border: 1px solid #fd5c6a; + color: #fff; + margin: 2em; +} + +input { + background-color: #000; + border: 1px solid #666; + color: #fff; + width: 12em; +} + +input.button { + background-color: #111; + border-left: 1px solid #ccc; + border-top: 1px solid #ccc; + width: auto; +} + +input.check { + width: auto; +} + +input.login, input.register { + margin-top: 1em; + padding: 0 1em; +} + +input:focus, input.button:focus { + border: 1px solid #fff; +} + +dl.form dd { + margin: 0.4em 0; +} + +dl.form dt { + margin-right: 0.5em; + padding: 0.4em 0 0 1em; + width: 8em; + height: 1em; + text-align: right; + display: block; + float: left; + font-style: italic; + color: #fff; +} + +fieldset { + width: 48em; + margin-top: 0.5em; + border: 1px solid #444; +} + + legend { + color: #fff; + font-size: 90%; + font-weight: normal; + text-transform: uppercase; + } + + +pre { + font-family: Bitstream Vera Sans Mono, Courier New, Lucida Console, monospace; + font-size: 9pt; + border-top: 1px solid #444; + border-bottom: 1px solid #333; + padding: 0.4em; + color: #fff; +} + + + + +/* colorpicker +---------------------------------------------------------*/ + +div#colorpicker { + position: absolute; + top: 16px; + left: 0; + width: 80px; + height: 76px; + background-color: #333; + border: 1px solid #777; + z-index: 10; +} +div#colorpickerSV { + background-color: #f00; + position: absolute; + bottom: 0; + left: 0; + width: 64px; + height: 64px; + background-image: url(colorpicker-sv.png); +} + +div#colorpickerH { + position: absolute; + bottom: 0; + right: 0; + width: 14px; + height: 64px; + background-image: url(colorpicker-h.png); + background-repeat: no-repeat; +} + +div#colorpickerSVSelect { + position: absolute; + top: -4px; + left: -4px; + width: 9px; + height: 9px; + background-image: url(colorpicker-select-sv.png); +} + +div#colorpickerHSelect { + position: absolute; + top: -2px; + right: 1px; + width: 3px; + height: 5px; + background-image: url(colorpicker-select-h.png); +} + +div#colorpickerCurrent { + background-color: #fff; + position: absolute; + top: 2px; + left: 1px; + width: 8px; + height: 8px; +} +div#colorpickerValue { + font-size: 9px; + font-family: arial; + color: #fff; + position: absolute; + top: 0; + left: 12px; + height: 8px; +} + diff --git a/picturelicious/remotepost.php b/picturelicious/remotepost.php new file mode 100644 index 0000000..6b8120c --- /dev/null +++ b/picturelicious/remotepost.php @@ -0,0 +1,27 @@ +login(); + +$status = 'ready'; +if( $user->id && !$user->isSpamLocked() && !empty($_GET['url'])) { + $uploadErrors = array(); + require_once( 'lib/imageuploader.php' ); + if( + ImageUploader::copyFromUrl( $_GET['url'], '', $_SERVER['HTTP_REFERER'], $uploadErrors) + ) { + $status = 'posted'; + $user->logUpload(); + } else { + $status = 'failed'; + } +} + +include( Config::$templates.'remotepost.tpl.php' ); + +?> \ No newline at end of file diff --git a/picturelicious/static/bookmarklet.html.php b/picturelicious/static/bookmarklet.html.php new file mode 100644 index 0000000..7459001 --- /dev/null +++ b/picturelicious/static/bookmarklet.html.php @@ -0,0 +1,21 @@ +

» Bookmarklet

+
+

Remote Post Bookmarklet

+ +

+ With the Remote Post Bookmarklet you can easily post images to with one simple click. + Please note that you need a decent Browser, like Firefox or + Opera, or at least Microsofts IE7 for this to work. +

+

+ To use the bookmarklet just drag the following link somewhere to your bookmarks (or in Opera right click it + and choose Bookmark link): + » Post to « +

+ +

+ Now, if you're on a website where you see an image you want to post, just click on your newly created bookmark + and then on the image you want to post. Thats all. Really! +

+ +
\ No newline at end of file diff --git a/picturelicious/templates/404.tpl.php b/picturelicious/templates/404.tpl.php new file mode 100644 index 0000000..9c62e7b --- /dev/null +++ b/picturelicious/templates/404.tpl.php @@ -0,0 +1,8 @@ + + + +
No Images found
+ + + + \ No newline at end of file diff --git a/picturelicious/templates/browse.tpl.php b/picturelicious/templates/browse.tpl.php new file mode 100644 index 0000000..9d899c6 --- /dev/null +++ b/picturelicious/templates/browse.tpl.php @@ -0,0 +1,77 @@ + + +

+ » Browsing + user) ) { ?> + User: user['name']; ?> + channel) ) { ?> + Channel: channel['name']; ?>, + searchColor) || !empty($ib->searchTerm) ) { ?> + Results for , + + All, + + + Page: pages['current']; ?> of pages['total']; ?> +

+ +user['id'] ) {?> +
+ + +
+ Score: user['score']; ?> / + Images: user['images']; ?> + user['website'])) { ?>/ + Website: + user['website']); ?> + + +
+
+
+ + +
+ pages['prev']) ) { ?> + + +
Previous
+ + + pages['next']) ) { ?> + + +
Next
+ + +
+searchColor) || !empty($ib->searchTerm) ) { + $imgBasePath = 'all/'; + } else { + $imgBasePath = $ib->basePath; + } + foreach( $ib->thumbs as $thumb ) { + if( isset( $thumb['left'] ) ) { + echo ''."\n"; + } + } +?> +
+
+ + + + + \ No newline at end of file diff --git a/picturelicious/templates/footer.tpl.php b/picturelicious/templates/footer.tpl.php new file mode 100644 index 0000000..b9f4409 --- /dev/null +++ b/picturelicious/templates/footer.tpl.php @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/picturelicious/templates/header.tpl.php b/picturelicious/templates/header.tpl.php new file mode 100644 index 0000000..7af6875 --- /dev/null +++ b/picturelicious/templates/header.tpl.php @@ -0,0 +1,67 @@ + + + + <?php if( $iv && $iv->image && $iv->image['tags']){ echo htmlspecialchars($iv->image['tags'])?> - <?php } ?><?php echo Config::$siteTitle; ?> + + + + + + + + +
+ + + + diff --git a/picturelicious/templates/login.tpl.php b/picturelicious/templates/login.tpl.php new file mode 100644 index 0000000..2cf6742 --- /dev/null +++ b/picturelicious/templates/login.tpl.php @@ -0,0 +1,40 @@ + + +
+
+ Login + + +
+ Wrong user or password! +
+ + +
+
Name:
+
+ +
+ +
Passwort:
+
+ +
+ +
 
+
+ + +
+ +
 
+
+ +
+
+ + Don't have an account yet? Register! +
+
+ + \ No newline at end of file diff --git a/picturelicious/templates/profile.tpl.php b/picturelicious/templates/profile.tpl.php new file mode 100644 index 0000000..25f51a3 --- /dev/null +++ b/picturelicious/templates/profile.tpl.php @@ -0,0 +1,58 @@ + + +
+
+ Change Profile + + +
Your password must be at least 6 characters long!
+ + + +
Your both passwords are not equal!
+ + + +
Your avatar Image could not be processed!
+ + +
+
Passwort:
+
+ (leave empty, if you don't want to change it) +
+ +
(Repeat)
+
+ +
+ +
 
+
 
+ + email) ) { ?> +
E-Mail:
+
+ +
+ + +
Website:
+
+ +
+ +
Avatar:
+
+
+
+ +
 
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/picturelicious/templates/quicktags.tpl.php b/picturelicious/templates/quicktags.tpl.php new file mode 100644 index 0000000..2b116dd --- /dev/null +++ b/picturelicious/templates/quicktags.tpl.php @@ -0,0 +1,77 @@ + + + +

+ » Quicktagger +

+ +
+

Quick tagging?

+

+ This special site automatically searches for images which are in desperate need of getting tagged. + That is: new images without any or very few tags. +

+ +

+ This site is carefully designed to allow efficient tagging of images. You don't have to move your hands + away from the keyboard - just write and press enter for the next image. Make sure javascript is + enabled in your browser, or you wont see anything. +

+ + +

A few words about tagging

+ +

+ If you are unsure what tags to write, just imagine you are searching for this image - what word(s) would you + search for? +

+ +

+ Also, is there any written text on the image itself? Try to write only the most essential words down. For instance + if you see a motivational with the text: +

+
+ Huddle House
+ For those times when Waffle House isn't quite white trashy enough +
+

+ good tags for this image would be "motivational huddle house white trash" +

+

+ If you don't know what to write, just press enter to skip the image. +

+ +

+ Don't abuse the system in any way, or the wrath of the administrator will come done on you! +

+ + +

» I get it, let's start already!

+
+ + + + \ No newline at end of file diff --git a/picturelicious/templates/random.js.php b/picturelicious/templates/random.js.php new file mode 100644 index 0000000..0a6a0f1 --- /dev/null +++ b/picturelicious/templates/random.js.php @@ -0,0 +1,6 @@ + +thumbs as $t ) { ?> + document.write(''); + \ No newline at end of file diff --git a/picturelicious/templates/register.tpl.php b/picturelicious/templates/register.tpl.php new file mode 100644 index 0000000..271548f --- /dev/null +++ b/picturelicious/templates/register.tpl.php @@ -0,0 +1,63 @@ + + +
+
+ Create Account + + +
This Username is allready registered!
+ + + +
Your name must be at least 2 characters long an may not have any special characters!
+ + + +
Your password must be at least 6 characters long!
+ + + +
Your both passwords are not equal!
+ + + +
There is already a registered user with this E-Mail address!
+ + + +
Your E-Mail address seems to be invalid!
+ + + +
+
Name:
+
+ + Only letters and numbers; at least 2 characters long +
+ +
E-Mail:
+
+ + Must be valid! +
+ +
Password:
+
+ +
+ +
(Repeat)
+
+ +
+ +
 
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/picturelicious/templates/registered.tpl.php b/picturelicious/templates/registered.tpl.php new file mode 100644 index 0000000..bbd70c4 --- /dev/null +++ b/picturelicious/templates/registered.tpl.php @@ -0,0 +1,7 @@ + +
+

Account successfully created

+

In order to activate your account, please check your mail and click on the activation link.

+ +
+ \ No newline at end of file diff --git a/picturelicious/templates/registrationmail.txt b/picturelicious/templates/registrationmail.txt new file mode 100644 index 0000000..dde942e --- /dev/null +++ b/picturelicious/templates/registrationmail.txt @@ -0,0 +1,11 @@ +From: no-reply@picturelicious.net +Subject: Welcome to %siteName%! + +Hello %userName%, +thank you for your registration at %siteName%. + +To activate your account, please click the following link +%frontendPath%login/%validationString% + + +Your %siteName% Team \ No newline at end of file diff --git a/picturelicious/templates/remotepost.tpl.php b/picturelicious/templates/remotepost.tpl.php new file mode 100644 index 0000000..c36e462 --- /dev/null +++ b/picturelicious/templates/remotepost.tpl.php @@ -0,0 +1,41 @@ + + + + <?php echo Config::$siteTitle ?> + + + + + + +

+ +id ) { ?> +
+ Name: + + + Passwort: + + + + +
+isSpamLocked() ) { ?> +

Sorry, you are not allowed to post more than 10 Images in 2 Hours.

+ +

Please click on the Image you want to post!

+ +

Sorry, the Image could not be posted for the following reason:

+

+ +

Image posted! Thank you!

+ + + + + \ No newline at end of file diff --git a/picturelicious/templates/upload.tpl.php b/picturelicious/templates/upload.tpl.php new file mode 100644 index 0000000..37b794e --- /dev/null +++ b/picturelicious/templates/upload.tpl.php @@ -0,0 +1,56 @@ + + +
+
+ Upload / Post + +

+ Images must be no larger than 4069x4096 and must not exceed 2 MB. + If the image is already in our Database, the upload will fail. Please follow our rules: +

+ +
    +
  • Absolutely NO pictures of child (Less 18 Yrs.), preteen or animal porn.
  • +
  • NO pictures of racist propaganda. No snuff pictures!
  • +
  • NO HARDCORE (porn) contents!!
  • +
  • No crappy low quality pics!
  • +
+ +

You can either upload an Image directly from your Computer, or specify an URL to copy the image From.

+ + +
+ There was an issue uploading your image: +
    + +
  • + +
+
+ + +
+
File:
+
+ +
+ +
or URL:
+
+ +
+ +
Tags:
+
+ +
+ +
 
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/picturelicious/templates/userlist.tpl.php b/picturelicious/templates/userlist.tpl.php new file mode 100644 index 0000000..51c440d --- /dev/null +++ b/picturelicious/templates/userlist.tpl.php @@ -0,0 +1,45 @@ + +

+ » Browsing Users, + Page: pages['current']; ?> of pages['total']; ?> +

+ + +users as $i => $u ) { ?> +
+ +
+ + + +
+
+ Score: / + Images: + / + Website: + + + +
+
+
+ + +
+ pages['prev']) ) { ?> + « Previous + +
« Previous
+ + + pages['next']) ) { ?> + Next » + +
Next »
+ + +
+
+ + \ No newline at end of file diff --git a/picturelicious/templates/view.tpl.php b/picturelicious/templates/view.tpl.php new file mode 100644 index 0000000..1638800 --- /dev/null +++ b/picturelicious/templates/view.tpl.php @@ -0,0 +1,142 @@ + + +

+ » Viewing + user) ) { ?> + User: user['name']; ?> + channel) ) { ?> + Channel: channel['name']; ?> + + All + +

+ +
+ + +
+ Score: userInfo['score']; ?> / + Images: userInfo['images']; ?> + userInfo['website'])) { ?>/ + Website: + userInfo['website']); ?> + + +
+
+
+ +
+ stream['prev']) ) { ?> + + +
Previous
+ + + stream['next']) ) { ?> + + +
Next
+ + +
+ <?php echo htmlspecialchars($iv->image['tags']) ?> +
+ +
+
+
+
+
+ + + + + +
+
+
+ + image['votes'] > 0 ) { ?> + image['score'],1);?> after image['votes'];?> Voteimage['votes'] > 1 ? 's' : '' ?> + + No votes yet! + + +
+ admin) { ?> +
+
+ [x] +
+ +
+ +
+ image['loggedTS']); ?> +
+ +
+ Tags: image['tags']) ? htmlspecialchars($iv->image['tags']) : 'none'; ?> + id ) { ?> + (add) + + +
+ + Post in Forum: + + + +
+ commentCount == 1 ) { ?> +

1 Comment:

+ commentCount > 1 ) { ?> +

commentCount ?> Comments:

+ +

No comments yet!

+ + + comments as $c ) { ?> +
+
+ + + at + admin) { ?> +
+ [x] +
+ +
+ +
+ + + id ) { ?> +
+
+ + +
+
+ +
+ +
+
+ + + + + \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..1171cec --- /dev/null +++ b/readme.md @@ -0,0 +1,10 @@ +Picturelicious +========== + +A Multiuser Image Gallery written in PHP and MySQL. + +More info: http://www.picturelicious.net/ + +Demo: http://demo.picturelicious.net/ + +MIT License. \ No newline at end of file