Email validation

Email validation? Why? There are thousands of validations on the net. Why another one? The answer is simple – most of the validations on the net are wrong. They ofter rely solely on regexs, and these are often wrong. Some years ago I had the opportunity to write a validation which is as close to the truth as it can be (although it was 2009 so things may have changes since then). Keep in mind that email validation is not exact science. There are contradictions in the RFCs governing it. There is even a „commentary“ RFC attempting to clear all that confusion.

First, let me give you the tools you need to succeed. A list of valid and a list of not valid email addresses. Every line contains a comment (single line Java style). explaining what is tested. These are copy/pasted from a Java array, so there are quotes, and backslashed to accommodate the Java String syntax and commas at the end of each line.

// basic emails
"a@a.ad", // the shortest possible email with letters
"abcdefghijklmnopqrstuvwxyz@abv.bg", // all letters email
"ABCDEFGHIJKLMNOPQRSTUVWXYZ@abv.bg", // all capital letters email
"1@1.ad", // the shortest possible email with numbers
"1234567890@123.com", // all numbers
/* special symbol emails */
"!@special.com", // ! ASCII 0x21
"#@special.com", // # ASCII 0x23
"$@special.com", // $ ASCII 0x24
"%@special.com", // % ASCII 0x25
"&@special.com", // & ASCII 0x26
"'@special.com", // ' ASCII 0x27
"*@special.com", // * ASCII 0x2A
"+@special.com", // + ASCII 0x2B
"-@special.com", // - ASCII 0x2D
"/@special.com", // / ASCII 0x2F
"=@special.com", // = ASCII 0x3D
"?@special.com", // ? ASCII 0x3F
"^@special.com", // ^ ASCII 0x5E
"_@special.com", // _ ASCII 0x5F
"`@special.com", // ` ASCII 0x60
"{@special.com", // { ASCII 0x7B
"|@special.com", // | ASCII 0x7C
"}@special.com", // } ASCII 0x7D
"~@special.com", // ~ ASCII 0x7E
/* complex emails */
"abc.def@dot.com", // email with dot
"abv.123.!#$@dot.atom.com", // email with dot containing all groups of characters
"local@dot.com.", // domain in absolute form
/* maximum length */
"1234567890123456789012345678901234567890123456789012345678901234@domain.com", // label long 64 characters
"1234567890@1234567890.1234567890.1234567890.1234567890.1234567890.1234567890."
    + "1234567890.1234567890.1234567890.1234567890.1234567890.1234567890.1234567890."
    + "1234567890.1234567890.1234567890.1234567890.1234567890.1234567890.1234567890."
    + "1234567890.1234567890.com", // max email length - 256
/* quoted strings */
"\"quotedstring\"@quoted.com", // Quotes string for local-part
"\"quoted\\qstring\"@quoted.com", // with quoted pair - \q
"\"quoted@string\"@quoted.com", // with second @
"\"quoted\\\"string\"@quoted.com", // with escaped double quote - \"
"\"quoteds\\ tring\"@quoted.com", // with escaped space - \SP - ASCII 0x20
"\"quoteds\\\ttring\"@quoted.com", // with escaped tab character - \HTAB - ASCII 0x09
"\"\"@quoted.com", // empty quoted string
/* quoted pairs */
"\\\"@special.com", // " ASCII 0x22 - \"
"\\(@quoted.com", // ( ASCII 0x28 - \(
"\\)@quoted.com", // ) ASCII 0x29 - \)
"\\< @quoted.com", // < ASCII 0x3C - \<
"\\>@quoted.com", // > ASCII 0x3E - \>
"\\[@quoted.com", // [ ASCII 0x5B - \[
"\\]@quoted.com", // ] ASCII 0x5D - \]
"\\:@quoted.com", // : ASCII 0x3A - \:
"\\;@quoted.com", // ; ASCII 0x3B - \;
"\\@@quoted.com", // @ ASCII 0x40 - \@
"\\\\@quoted.com", // \ ASCII 0x5C - \\
"\\,@quoted.com", // , ASCII 0x2C - \,
"\\.@quoted.com", // . ASCII 0x2E - \.
/* RFC 3696 section 3 */
"Abc\\@def@example.com",
"Fred\\ Bloggs@example.com",
"Joe.\\\\Blow@example.com",
"\"Abc@def\"@example.com",
"\"Fred Bloggs\"@example.com",
"user+mailbox@example.com",
"customer/department=shipping@example.com",
"$A12345@example.com",
"!def!xyz%abc@example.com",
"_somename@example.com",
// missing parts
"@nouser.co", // without local part
"nodomain@", // without domain part
"noatdomain.com", // with no @ sign
/* extra dots */
".@domain.com", // only one for local part
".a@domain.com", // a dot at the begining of local part
"a.@doman.com", // a dot at the end of local part
/* invalid characters */
"\"@special.com", // " ASCII 0x22
"(@special.com", // ( ASCII 0x28
")@special.com", // ) ASCII 0x29
"< @special.com", // < ASCII 0x3C
">@special.com", // > ASCII 0x3E
"[@special.com", // [ ASCII 0x5B
"]@special.com", // ] ASCII 0x5D
":@special.com", // : ASCII 0x3A
";@special.com", // ; ASCII 0x3B
"@@special.com", // @ ASCII 0x40
"\\@special.com", // \ ASCII 0x5C
",@special.com", // , ASCII 0x2C
".@special.com", // . ASCII 0x2E
/* not ASCII characters and ASCII control characters */
"кирилица@domain.com", // some Cyrillic characters
"\uFFFF@domain.com", // Unicode code point U+FFFF (guaranteed not to be a character)
"\u007F@domain.com", // ASCII 0x7F (del) character
"\u0000@domain.com", // ASCII 0x00 (nul) character
/* invalid domain part */
"local@dot..com", // to adjacent dots
"local@dot.dot", // non existing TLD - dot
"local@.dot.com", // non existing TLD - dot
/* longer than maximum length */
"12345678901234567890123456789012345678901234567890123456789012345@domain.com", // label long 65 characters
"1234567890@1234567890.1234567890.1234567890.1234567890.1234567890.1234567890."
    + "1234567890.1234567890.1234567890.1234567890.1234567890.1234567890.1234567890."
    + "1234567890.1234567890.1234567890.1234567890.1234567890.1234567890.1234567890."
    + "1234567890.12345678901.com", // max email length - 257
/* quoted local part */
"\"quotedstring\\\"@quoted.com", // ends with escaped double quote
/* quoted pairs */
"\\\u007F@quoted.com", // invalid quoted pair - ASCII 0x7F (del) character
"\\\u0000@quoted.com", // invalid quoted pair -ASCII 0x00 (nul) character
"\\ъ@quoted.com", // invalid quoted pair - non ASCII character - ъ
/* RFC 3696 section 3 */
"Fred Bloggs@example.com",

The next tool you need is the validation regexps. First, there is more than one. Second, there are some length validations. This should be pretty self explanatory. The regexp below are constructing using a formal definition for an email. It is using JavaScript syntax as they were written to work in GWT.

MAX_LOCAL_PART_LENGTH = 64;
MAX_EMAIL_LENGTH = 256;

// Using \x00-\x1F\x7F instead of \p{Cntrl}
SPECIAL_CHARS = "\\x00-\\x1F\\x7F\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]";

// Using \x00-\x7F instead of \p{ASCII}
LEGAL_ASCII_REGEX = "^[\\x00-\\x7F]+$";

Q_PAIR = "\\\\([\\x21-\\x7E]|\\x20|\\x09)";
// Bug fix including \x20 (space) due to RFC 3696 section 3
Q_TEXT = "[\\x20\\x21\\x23-\\x5B\\x5D-\\x7E]";
Q_CONTENT = "(" + Q_TEXT + ")|(" + Q_PAIR + ")";
QUOTED_USER = "\"(" + Q_CONTENT +  ")*\"";

VALID_CHARS = "([^\\s" + SPECIAL_CHARS + "])|(" + Q_PAIR + ")";
WORD = "((" + VALID_CHARS + "|')+|(" + QUOTED_USER + "))";

EMAIL_REGEX = "^\\s*?(.+)@(.+?)\\s*$";
USER_REGEX = "^\\s*" + WORD + "(\\." + WORD + ")*$";

Finally, here is the Java code which does it all. It is missing its domain validation, but that is easy.

/**
 * Licensed under APL - http://www.apache.org/licenses/LICENSE-2.0 - the rest of header skipped for brevity.
 *
 * Performs email validations.
 *
 * Based on org.apache.commons.validator.routines.EmailValidator.
 *
 * @author Apache Software Foundation
 * @author ShaMan-H_Fel
 */
public class EmailValidator {

    private static final int MAX_LOCAL_PART_LENGTH = 64;
    private static final int MAX_EMAIL_LENGTH = 256;

    // Using \x00-\x1F\x7F instead of \p{Cntrl}
    private static final String SPECIAL_CHARS = "\\x00-\\x1F\\x7F\\(\\)<>@,;:'\\\\\\\"\\.\\[\\]";

    // Using \x00-\x7F instead of \p{ASCII}
    private static final String LEGAL_ASCII_REGEX = "^[\\x00-\\x7F]+$";

    private static final String Q_PAIR = "\\\\([\\x21-\\x7E]|\\x20|\\x09)";
    // Bug fix including \x20 (space) due to RFC 3696 section 3
    private static final String Q_TEXT = "[\\x20\\x21\\x23-\\x5B\\x5D-\\x7E]";
    private static final String Q_CONTENT = "(" + Q_TEXT + ")|(" + Q_PAIR + ")";
    private static final String QUOTED_USER = "\"(" + Q_CONTENT +  ")*\"";

    private static final String VALID_CHARS = "([^\\s" + SPECIAL_CHARS + "])|(" + Q_PAIR + ")";
    private static final String WORD = "((" + VALID_CHARS + "|')+|(" + QUOTED_USER + "))";

    private static final String EMAIL_REGEX = "^\\s*?(.+)@(.+?)\\s*$";
    private static final String USER_REGEX = "^\\s*" + WORD + "(\\." + WORD + ")*$";

    /**
     * Singleton instance of this class.
     */
    private static final EmailValidator EMAIL_VALIDATOR = new EmailValidator();

    /**
     * Returns the Singleton instance of this validator.
     *
     * @return singleton instance of this validator.
     */
    public static EmailValidator getInstance() {
        return EMAIL_VALIDATOR;
    }

    /**
     * Protected constructor for subclasses to use.
     */
    protected EmailValidator() {
        super();
    }

    /**
     * <p>
     * Checks if a field has a valid e-mail address.
     * </p>
     *
     * @param email
     *            The value validation is being performed on. A <code>null</code> value is
     *            considered invalid.
     * @return true if the email address is valid.
     */
    public boolean isValid(String email) {
        if (email == null) {
            return false;
        }

        if (email.length() > MAX_EMAIL_LENGTH) {
            return false;
        }

        boolean match = email.matches(LEGAL_ASCII_REGEX);
        if (!match) {
            return false;
        }

        // Check the whole email address structure
        match = email.matches(EMAIL_REGEX);
        if (!match) {
            return false;
        }

        /*
         * There are 2 cases in which an email can contain more than one @ sign:
         *
         * 1. If the local part is "quoted", example "test@test"@domain.com
         *
         * 2. If the @ sign is in quoted pair (escaped), example: test\@test@domain.com
         */
        String[] groups = null;
        int lastAt = email.lastIndexOf("@");

        groups = new String[2];
        groups[0] = email.substring(0, lastAt);
        groups[1] = email.substring(lastAt + 1);

        if (!isValidUser(groups[0])) {
            return false;
        }

        if (!isValidDomain(groups[1])) {
            return false;
        }

        return true;
    }

    /**
     * Returns true if the domain component of an email address is valid.
     *
     * @param domain
     *            being validated.
     * @return true if the email address's domain is valid.
     */
    protected boolean isValidDomain(String domain) {
        // Hook your domain validation here.
        return true;
    }

    /**
     * Returns true if the user component (local part) of an email address is valid.
     *
     * @param user
     *            being validated
     * @return true if the user name is valid.
     */
    protected boolean isValidUser(String user) {
        if (user.length() > MAX_LOCAL_PART_LENGTH) {
            return false;
        }

        boolean result = user.matches(USER_REGEX);
        result = result && user.matches(LEGAL_ASCII_REGEX);

        return result;
    }

}
Posted in Разни | Коментарите са изключени за Email validation

Как да пишем ѝ

Някои от вас сигурно са ме чували да се оплаквам от масовото записване на думата ѝ с буквата й. Спорът по тази тема в офиса продължи цели три дни в много отделни разговори и огромен спам в чатовете ни. Аз не съм най-грамотният човек, но наистина се дразня когато видя да се използва й вместо ѝ, особено в печатни издания (вестник Капитал Daily, към теб гледам). За това ето как стават нещата – пускате си фонетична подредба (сори ама БДС варианта е прекалено дървен и остарял, за сметка на необходими символи като ѝ имаме ы), след това просто пишете:

  • За ѝShift + x
  • За ЍCaps Lock, Shift + x – първо включвате Caps Lock, после пишете
  • За ьx т.е. както си е нормално за фонетичната
  • За ЬCaps Lock, x – първо включвате Caps Lock, после пишете

Както забелязвате писането на главни букви е малко терсене, но в нормален текст не се налага да се използват главните букви (трябва да пишете нещо подобно на тази статия за да ви се наложи). Гореописаното работи на Windows след 7 и на Ubuntu базирани Linux дистрибуции. По мое мнение това е най-смислената модификация на фонетичната клавиатура.

За любителите на мобилни устройства, ако имате късмет да сте с нормална Android клавиатура – задръжте буквата „и“ и ще се появи възможност да изберете „ѝ“. Ако, като мен, сте с модифицирана клавиатура 🙁 нямате късмет, но пък винаги можете да перифразирате.

За ползващите Mac OS и iOS – съжалявам но не знам как стават нещата. Убеден съм, че има някакъв начин (в старите Window-и имаше един Character Map, от където можеха да се вземат такива символи). Ако някой знае, нека драсне един коментар за да го добавя.

В краен случай буквата ѝ се използва на много места в тази статия, копирайте я на воля.

P.S. Благодарение на Аделина разбрах как се казва еквивалентът на Character Map в MacOS – Character Palette. Пълното обяснение можете да намерите на http://eenk.com/postavyane-na-udareniya-na-kirilitsa-s-html.

P.S.S. Отново благодарение на Аделина – ето какво ви трябва за да пишете ѝ в MacOS – https://github.com/ivang/phoneticI.

Posted in Разни | Tagged , , , , | Коментарите са изключени за Как да пишем ѝ

A quick fix for the YouTube SimpleGallery WordPress plugin

Тази статия е на английски поради необходимостта да достигне до по-широка аудитория. Тя касае решаването на много специфичен проблем, който в момента представлява интерес за определена група хора, които не говорят български.

Hi Folks,

I did some digging and found that this plugin (YouTube SimpleGallery @ https://wordpress.org/plugins/youtube-simplegallery/) is broken on two levels:

  1. The format of the YouTube oEmbed code has apparently changed
  2. The YouTube has deprecated its v2 API, which this plugin uses

So, unfortunately for the people wanting a „code clean“ solution (from the following thread https://wordpress.org/support/topic/just-broke-shows-only-first-video), there is none. Also unfortunately but for everybody (including me), this plugin is dead, the last update is almost 2 years old. However I like the simple building of galleries very much, so I had to fix the plugin. Keep in mind that the fix is quick and dirty, apply on your own risk.

I tried to do the fix the right way but I was not able to disable the automatic use of oEmbed for YouTube. Maybe, sometime in the future I will return to this code and make my first plugin the right way. But for now, here is what you need to do this:

[youtubegallery]
vAJFM9qZlrI
qnRJ5Z-HP3E
BZ3Xc7bG10U
WBq_jNgpSYE
[/youtubegallery]

instead of this:

[youtubegallery]
http : // youtu . be/vAJFM9qZlrI
http : // youtu . be/qnRJ5Z-HP3E
http : // youtu . be/BZ3Xc7bG10U
http : // youtu . be/WBq_jNgpSYE
[/youtubegallery]

I don’t really like this (as I have to edit several pages on my other blog) but parsing that mess of an HTML returned by the oEmbed was beyond my PHP/Wordpress skills. So put the video IDs only, one on a line.

Then apply the following patch (using git or any other way you prefer): http://blog.pvalley.info/wp-content/uploads/2015/05/0001-Fixed-the-youtube-gallery.patch. But before that read the notes under the patch text as they are important.

From 69cb15c3624592f810e87cdba1a5891dfd24f506 Mon Sep 17 00:00:00 2001
From: Kaloyan Dimitrov <admin@pvalley.info>
Date: Tue, 12 May 2015 21:25:48 +0300
Subject: [PATCH] Fixed the youtube gallery.

 - Using the new API
 - Broken the vimeo gallery
---
 inc/shortcode.php         | 198 +++++++++++++++-------------------------------
 youtube_simplegallery.php |  14 +---
 2 files changed, 63 insertions(+), 149 deletions(-)

diff --git a/inc/shortcode.php b/inc/shortcode.php
index dc0b83e..de1b8ea 100644
--- a/inc/shortcode.php
+++ b/inc/shortcode.php
@@ -3,26 +3,7 @@
 // SHORTCODE: YOUTUBEGALLERY / VIMEOGALLERY
 function show_youtubegallery( $atts = array(), $youtubelinks = null ) {
 
-	// CLEAN UP OEMBED
-	if (stripos($youtubelinks, "</iframe>") !== false) {
-		$embededmess = explode('<p>', $youtubelinks);
-
-		foreach($embededmess as $line):
-			if (stripos($line, "</iframe>") !== false) {
-				$removeoembed = yotube_gallery_getAttribute('src', $line);
-				$newarray[] = str_replace('http://player.vimeo.com/video', 'http://vimeo.com', $removeoembed);
-			}
-			else {
-				$newarray[] = trim($line);
-			}
-		endforeach;
-
-		$youtubelinks = array_filter($newarray, 'strlen');
-
-	}
-	else {
-		$youtubelinks = explode("\n", $youtubelinks);
-	}
+	$youtubelinks = explode("\n", $youtubelinks);
 	
 	return global_output_youtubegallery( $atts, $youtubelinks );
 }
@@ -101,143 +82,88 @@ function global_output_youtubegallery( $atts = array(), $youtubelinks = null ) {
 	$x = $youtube_gallery_count;
 	$youtube_gallery_ID++;
 
-	// GET LINKS AND CAPTIONS
-	$thisgallery = array();
-	$nol = 0; /* Counter for array */
-	foreach ( $youtubelinks as $l ):
+	$thisgallerycount = 0;
+	$showgallery = ('<div id="youtube_gallery_'.$youtube_gallery_ID.'" class="youtube_gallery"><div class="youtube_gallery_center">'."\n");
+	foreach ( $youtubelinks as $videoID ):
+		$videoID = trim(strip_tags($videoID));
+		if ($videoID != '') {
+		    $x++;
+		    $thisgallerycount++;
+		}
+		else {
+		    continue;
+		}
 
-		$captions = 0;
+		// get options
+		if($youtubeoptions['hd']=='usehd') $ytsghd = 'hd=1'; else $ytsg = 'hd=0';
+		if($youtubeoptions['start']=='autoplay') $ytsgstart = 'autoplay=1'; else $ytsgstart = 'autoplay=0';
+		if($youtubeoptions['related']=='dontshow') $ytsgrel = 'rel=0'; else $ytsgrel = 'rel=1';
 
-		// Check if has caption
-		if(strstr($l, '|')) { 
-			$thumb = explode('|', $l); 
-			$captions = 1;
+		$API_KEY = "FIXME: add your API key here";
+		$videodata_raw = wp_remote_fopen('https://www.googleapis.com/youtube/v3/videos?id=' . $videoID . '&key=' . $API_KEY . '&part=snippet');
+		$videodata = json_decode($videodata_raw, true);
+
+		$items = $videodata["items"];
+		if(count($items) == 0) {
+		    $showgallery .= '<div class="youtube_gallery_item"><div class="youtube_gallery_error"><p><strong>ERROR!</strong></p></div></div>'."\r\n\r\n";
+		    continue;
 		}
-		if($captions) {
-			$thisgallery[$nol]['caption'] = stripslashes($thumb[0]);
-			$thisgallery[$nol]['url'] = strip_tags($thumb[1]);
-			if(strstr($thumb[1], 'youtube.com')) $thisgallery[$nol]['source'] = 'youtube';
-			if(strstr($thumb[1], 'vimeo.com')) $thisgallery[$nol]['source'] = 'vimeo';
+
+		$videoembedlink = 'http://www.youtube.com/embed/'.$videoID.'?'.$ytsgstart.'&'.$ytsghd.'&'.$ytsgrel;
+		if($youtubeoptions['timthumb']=='off') {
+			$videothumb = $items[0]["snippet"]["thumbnails"]["high"]["url"];
 		}
 		else {
-			$thisgallery[$nol]['url'] = strip_tags($l);
-			if(strstr($l, 'youtube.com')) $thisgallery[$nol]['source'] = 'youtube';
-			if(strstr($l, 'vimeo.com')) $thisgallery[$nol]['source'] = 'vimeo';
+			$videothumb = get_bloginfo('url').'/wp-content/plugins/youtube-simplegallery/scripts/timthumb.php?src=' . $items[0]["snippet"]["thumbnails"]["high"]["url"];
 		}
 
-		// Clean item if item is empty
-		if(!strstr($thisgallery[$nol]['url'], 'http://')) unset($thisgallery[$nol]);	
-		// Else increase counter
-		else $nol++; 
-	endforeach;
 
-	$thisgallerycount = 0;
-	$showgallery = ('<div id="youtube_gallery_'.$youtube_gallery_ID.'" class="youtube_gallery"><div class="youtube_gallery_center">'."\n");
-	foreach ( $thisgallery as $link ):
-		$x++;
-		$thisgallerycount++;
-
-			// get options
-			if($youtubeoptions['hd']=='usehd') $ytsghd = 'hd=1'; else $ytsg = 'hd=0';
-			if($youtubeoptions['start']=='autoplay') $ytsgstart = 'autoplay=1'; else $ytsgstart = 'autoplay=0';
-			if($youtubeoptions['related']=='dontshow') $ytsgrel = 'rel=0'; else $ytsgrel = 'rel=1';
-
-			/* This link is YouTube */
-			if($link['source']=='youtube') { 
-				$videoID = yotube_gallery_getYouTubeIdFromURL($link['url']);
-				
-				if(!isset($youtubeoptions['api']))
-				$videodata = yotube_gallery_getYouTubeDataFromID($videoID);
-
-				if( isset($videodata) && $videodata != 'error' ) {
-					$autotitle = $videodata->title;
-				}
-
-				$videoembedlink = 'http://www.youtube.com/embed/'.$videoID.'?'.$ytsgstart.'&'.$ytsghd.'&'.$ytsgrel;
-				if($youtubeoptions['timthumb']=='off')
-					$videothumb = 'http://img.youtube.com/vi/'.$videoID.'/0.jpg';
-				else
-					$videothumb = get_bloginfo('url').'/wp-content/plugins/youtube-simplegallery/scripts/timthumb.php?src=http://img.youtube.com/vi/'.$videoID.'/0.jpg&w=480&h=270&zc=1';
-			}
+		$caption = $items[0]["snippet"]["title"];
 
-			/* This link is Vimeo */
-			elseif($link['source']=='vimeo') { 
-				$videoID = str_replace('http://vimeo.com/', '', $link['url']);
-				$videodata = yotube_gallery_getVimeoDataFromID($videoID);
-				if( isset($videodata) && $videodata != 'error' ) {
-					$videoembedlink = 'http://player.vimeo.com/video/'.$videoID.'?'.$ytsgstart;
-					if($youtubeoptions['timthumb']=='off')
-						$videothumb = trim($videodata['thumbnail_large']);
-					else
-						$videothumb = get_bloginfo('url').'/wp-content/plugins/youtube-simplegallery/scripts/timthumb.php?src='.trim($videodata['thumbnail_large']).'&w=480&h=270&zc=1';
-					$autotitle = $videodata['title'];
-				}
-			}
-
-			// IF ERROR; OUTPUT ERROR MESSAGE
-			if($videodata == 'error') {
-				if( !isset($youtubeoptions['error']) ) {
-					$showgallery .= '<div class="youtube_gallery_item"><div class="youtube_gallery_error"><p><strong>ERROR!</strong> <a href="'.$link['url'].'" target="_blank">'.$link['url'].'</a> does not seem to be a valid video. Please verify the URL.</p></div></div>'."\r\n\r\n";
-					if(isset($cols)) // if cols, output break
-						if($thisgallerycount%$cols==0) $showgallery .= '<br clear="all" style="clear: both;" />';
-				}
-				else {
-					$thisgallerycount--;
-					$x--;
-				}
-				continue;
-			}
+		// START OUTPUT
+		$showgallery .= '<div id="youtube_gallery_item_'.$x.'" class="youtube_gallery_item">'."\n";
 
-			// get caption if exists
-			if( isset($autotitle) && $autotitles == 'fetch' ) $caption = $autotitle;
-			if( $autotitles != 'fetch' ) $caption = null;
-			if(isset($link['caption'])) $caption = strip_tags($link['caption']);
-			
-				// START OUTPUT
-				$showgallery .= '<div id="youtube_gallery_item_'.$x.'" class="youtube_gallery_item">'."\n";
+		// if title above
+		if($youtubeoptions['title'] == 'above' && $caption ) $showgallery .= ('<div class="youtube_gallery_caption">'.strip_tags($caption).'</div>');
 
-				// if title above
-				if($youtubeoptions['title'] == 'above' && $caption ) $showgallery .= ('<div class="youtube_gallery_caption">'.strip_tags($caption).'</div>');
+		$showgallery .= '<div class="youtube_gallery_player">';
 
-				$showgallery .= '<div class="youtube_gallery_player">';
+		// if use shadowbox
+		if($youtubeoptions['thickbox'] == 'shadowbox') 
+			$showgallery .= '<a rel="shadowbox[Mixed];width='.$youtubeoptions['width'].';height='.$youtubeoptions['height'].';" href="'.$videoembedlink.'" title="'.strip_tags($caption).'">';
 
-				// if use shadowbox
-				if($youtubeoptions['thickbox'] == 'shadowbox') 
-					$showgallery .= '<a rel="shadowbox[Mixed];width='.$youtubeoptions['width'].';height='.$youtubeoptions['height'].';" href="'.$videoembedlink.'" title="'.strip_tags($caption).'">';
+		// if use fancybox
+		elseif($youtubeoptions['thickbox'] == 'fancybox') 
+			$showgallery .= '<a class="fancybox iframe" href="'.$videoembedlink.'" title="'.strip_tags($caption).'">';
 
-				// if use fancybox
-				elseif($youtubeoptions['thickbox'] == 'fancybox') 
-					$showgallery .= '<a class="fancybox iframe" href="'.$videoembedlink.'" title="'.strip_tags($caption).'">';
+		// if use thickbox
+		elseif($youtubeoptions['thickbox'] == 'thickbox') 
+			$showgallery .= '<a class="thickbox" href="'.$videoembedlink.'&KeepThis=true&TB_iframe=true&height='.$youtubeoptions['height'].'&width='.$youtubeoptions['width'].'?'.$ytsgstart.'&'.$ytsghd.'&'.$ytsgrel.'" title="'.strip_tags($caption).'">';
 
-				// if use thickbox
-				elseif($youtubeoptions['thickbox'] == 'thickbox') 
-					$showgallery .= '<a class="thickbox" href="'.$videoembedlink.'&KeepThis=true&TB_iframe=true&height='.$youtubeoptions['height'].'&width='.$youtubeoptions['width'].'?'.$ytsgstart.'&'.$ytsghd.'&'.$ytsgrel.'" title="'.strip_tags($caption).'">';
-
-				// if go to youtube.com
-				elseif($youtubeoptions['thickbox'] == 'none') {
-					$showgallery .= '<a href="http://www.youtube.com/watch?v='.str_replace('<br />', '', $videoID).'"';
-					if($youtubeoptions['openlinks']) $showgallery .= ' target="_blank"';
-					$showgallery .= '>';
-				}
+		// if go to youtube.com
+		elseif($youtubeoptions['thickbox'] == 'none') {
+			$showgallery .= '<a href="http://www.youtube.com/watch?v='.str_replace('<br />', '', $videoID).'"';
+			if($youtubeoptions['openlinks']) $showgallery .= ' target="_blank"';
+			$showgallery .= '>';
+		}
 
-				// if add play btn
-				if($youtubeoptions['pb'] == 'usepb') $showgallery .= '<img src="'.get_bloginfo('wpurl').'/wp-content/plugins/youtube-simplegallery/img/play.png" alt=" " class="ytsg_play" border="0" />';
+		// if add play btn
+		if($youtubeoptions['pb'] == 'usepb') $showgallery .= '<img src="'.get_bloginfo('wpurl').'/wp-content/plugins/youtube-simplegallery/img/play.png" alt=" " class="ytsg_play" border="0" />';
 
-				// output thumb
-				$showgallery .= '<img src="'.$videothumb.'" border="0"></a><br />';
+		// output thumb
+		$showgallery .= '<img src="'.$videothumb.'" border="0"></a><br />';
 
-				// if title below
-				if($youtubeoptions['title'] == 'below' && isset($caption) ) $showgallery .= ('<div class="youtube_gallery_caption">'.strip_tags($caption).'</div>');
+		// if title below
+		if($youtubeoptions['title'] == 'below' && isset($caption) ) $showgallery .= ('<div class="youtube_gallery_caption">'.strip_tags($caption).'</div>');
 
-				// close divs
-				$showgallery .= '</div>';
-				$showgallery .='</div>'."\r\n\r\n";
+		// close divs
+		$showgallery .= '</div>';
+		$showgallery .='</div>'."\r\n\r\n";
 
+		if(isset($cols)) // if cols, output break
+			if($thisgallerycount%$cols==0) $showgallery .= '<br clear="all" style="clear: both;" />';
 
-			if(isset($cols)) // if cols, output break
-				if($thisgallerycount%$cols==0) $showgallery .= '<br clear="all" style="clear: both;" />';
-				
-			$caption = null;
+		$caption = null;
 
 	endforeach;
 	$showgallery .= '<div class="youtube_gallery_divider"></div>'."\r\n";
diff --git a/youtube_simplegallery.php b/youtube_simplegallery.php
index 3427c96..87417f6 100644
--- a/youtube_simplegallery.php
+++ b/youtube_simplegallery.php
@@ -54,18 +54,6 @@ function yotube_gallery_getYouTubeIdFromURL($url) {
 	return isset($matches[1]) ? $matches[1] : false;
 }
 
-// GET YOUTUBE VIDEO DATA 
-function yotube_gallery_getYouTubeDataFromID($vID) {
-	$videodata = wp_remote_fopen('http://gdata.youtube.com/feeds/api/videos/'.trim($vID));
-	if($videodata=='Video not found') {
-		return 'error';
-	}
-	else {
-		$videodata = new SimpleXMLElement($videodata);
-		return $videodata;
-	}
-}
-
 // GET VIMEO VIDEO DATA 
 function yotube_gallery_getVimeoDataFromID($vID) {
 	$videodata = wp_remote_fopen('http://vimeo.com/api/v2/video/'.trim($vID).'.json');
@@ -153,6 +141,6 @@ add_action('wp_footer', 'youtube_gallery_shortcode_styles');
 // HOOK IT UP TO WORDPRESS
 register_activation_hook(__FILE__,'youtubegallery_install');	
 register_deactivation_hook(__FILE__,'youtubegallery_uninstall');
-add_filter("plugin_action_links_$plugin", 'youtubegallery_settings_link' ); 
+add_filter("plugin_action_links_$plugin", 'youtubegallery_settings_link' );
 
 ?>
-- 
1.9.1

You will need to disable Timthumb, as it is not working. I haven’t had the time to investigate the issue. Also be aware that this patch is breaking the Vimeo support and that it is only fixing the youtubegallery, to the youtubeuserfeed shortcode. Finally you will need an YouTube API key. It should be put here:

FIXME: add your API key here.

And at the end, a word of warning. Use on your own risk.

I hope this helps.

Cheers,
ShaMan-H_Fel

Posted in Разни | Tagged , | 4 коментара

Гласувайте за мен.

Здравейте,

Днес имам един апел към вас. Кандидатирам се за позицията на Chief World Explorer, т.е. главен изследовател на света. Част от процеса за кандидатстване е събирането на гласове за 60 секунден клип. Моят апел към вас е да гласувате за мен. Страницата за гласуване е http://www.bestjobaroundtheworld.com/submissions/view/11796, можете да гласувате по веднъж на ден, от всеки компютър до който имате достъп (вкъщи, на работа, в някой приятел). Аз съм далеч от първите места по гласове, но гласовете не са всичко, така че стига да съм достатъчно напред имам шанс.

Моля гласувайте за мен. Клипчето, което съм направил може да видите и в youtube:

Posted in Разни | Коментарите са изключени за Гласувайте за мен.

Изненадваща статистика

Преди няколко дни/седмици забелязах, че хостинг доставчикът ми е добавил нов инструмент за статистики. До сега разполагах само с древна версия на Webalizer (2.01 от 2008 година, за сведение последната версия е 2.23-05 от 2011). Сега разполагам и с последната стабилна версия на AWStats 7.0 (от края на 2010, единствената друга версия налична на сайта е бета версията 7.1 от края на 2011).

Разглеждайки статистиките попаднах на следната интересна таблица за посещаемостта на този сайт:

Browsers Grabber Hits Percent
MS Internet Explorer No 1,483 43.1 %
Firefox No 1,192 34.6 %
Google Chrome No 432 12.5 %
Opera No 171 4.9 %
Safari No 49 1.4 %
Unknown ? 49 1.4 %
Mozilla No 34 0.9 %
Nokia Browser (PDA/Phone browser) No 21 0.6 %
Netscape No 6 0.1 %

Доста странно, IE е на първо място. Още повече, че другият ми сайт Фентъзи Свят е с доста различен профил на посещаемост:

Browsers Grabber Hits Percent
Firefox No 3,111 52.8 %
Google Chrome No 1,191 20.2 %
MS Internet Explorer No 889 15.1 %
Opera No 305 5.1 %
Unknown ? 223 3.7 %
Mozilla No 103 1.7 %
Safari No 23 0.3 %
Android browser (PDA/Phone browser) No 18 0.3 %
Netscape No 12 0.2 %
BlackBerry (PDA/Phone browser) No 5 0 %
Others 1 0 %

За да помогна на заблудените души, които ползват IE, на видно място съм сложил бутонче към Firefox. Не е към официалният сайт, но този плъгин просто предлагаше готини бутончета :), че нали знаете луд на шаренко се радва ;).

Posted in Разни | Коментарите са изключени за Изненадваща статистика