Friday, November 21, 2008

Video format basics you wish you knew about

Once upon time, video codecs and formats were really only the concern of AV nerds, anime freaks and hardcore not-so-legal movie downloaders....

More here.

Thursday, November 13, 2008

Why simply CAPTCHAs are not enough

I was looking at different CAPTCHAs today and reading about the failures their various failures. The problem as it exists is not that we can not find a problem that requires a human to solve. That is only the first peice, because CAPTCHAs as a rule defeat automation and then only part of the time. That leaves computers working in isolation (after a program of hack tool has been created) to succeed only some of the time. This does not preclude hack programs from doing all the busy work and showing a human a CAPTCHA to solve in order to continue.

Imagine the very best case scenario of this - a single person who has developed program to expedite spamming 100 times doesn't need to enter in all 100 complete entries, but instead solve 100 CAPTCHA alone. Now try to imagine the worst case scenario - programmer has developed a program to solve CAPTCHAs automatically by farming them off as CAPTCHAs to his porn site for willing patrons to fill out and verify (similar in a sense to the work of the reCAPTCHA project).

This leads us back to square one, because either we are now battling a potentially less intelligible human or the one who developed the measure to break the CAPTCHA in the first place.

Several solutions as I see it exist to this problem:

1) Variety- Add fresh dose of variety to the CAPTCHA creation. In order to prevent CAPTCHAs from being broken as easily they need to do things that even people are not expecting...at least not all the time. CAPCHTAs can have differing instructions included for how to solve them. "Enter all but the third letter" or "Enter only the vowels from above". They can have pieces that play into solving them that are not in the same place in the page or in the same place on each page. They can be moving (flash based) CAPCHTAs or items that are dynamic in nature.

2) Statistical trustworthiness - People are most trusted when they act like we expect normal people to act. They post up to a certain limit per day. They take a certain amount of time to get things done. They do certain things, and avoid others. By flagging the actions and inactions of trustworthy perople, machines and their related information, we know enough about them to know whether thay should be allowed to create another account, or post that message. We do not have to mine data everywhere to accuire this kind of information, but we do have to assume that anyone that starts with a blank slate could be as wretched as the worst spammer.

3) Private/Public Keys - Implement something like PGP (Pretty Good Privacy) which has a Private/Public Key system to sign documents, require a registration, and use the system to authenticate as a real person. This eliminates privacy just as Statistical Trustworthiness begins to do.

Looking at the kinds of solutions that are possible, the somber conclusion is that Application Service Providers are either going to have to work much harder, or the internet is going to have to become more regulated to keep spam and misuse from becoming a larger threat.

Wednesday, November 12, 2008

Adobe AIR and real Ajax advantage

When originally confronted with Adobe AIR, it seemed silly to be developing anything like that for a desktop when the browser is two clicks away. However, take a look at Google's Gmail application and I think you see many of the same ideas are leveraged into the user experience.

Connectivity - When the connection dies on a page, it literally kills the user experience. Google and Adobe both know and combat this with the appropriate ajax.

Load Time - How many times should your interface graphics and interaction logic have to be reloaded? With intelligent design, not more than once a day. This frees more bandwidth for unique data that is important to the user and minimizes wait time. Everyone hates the fact that windows takes anywhere from a half minute to several minutes to load, yet no one complains about a couple seconds of load time. All of that time accumilates however and people spend upwards of 10 to 20 minutes daily waiting for page loads.

Ease of Design - Have you ever tried to make a windows app look good? I can guarantee you...not fun, and not usually very easy. The dev time on true windows applications tends to be longer than web applications. However, once you've developed the web application, an ajax or Adobe Air application is the next logical step.

Memory Footprint - Air applications should have a smaller overall footprint than IE and Firefox if for no other reason than because Flash Applications have always been produced to load only what is needed. That means you for all proctical purposes should be truncating features you don't need from your browser. With IE and Firefox, you are pretty much stuck with whatever they give you.

Spry - A better Ajax?

When I had first heard of Spry - Dreamweaver's solution to the ajax craze, I couldn't see the advantage to it. I suppose being married into Dreamweaver theoretically makes it advantageous, but for all the simplicity and intuitiveness that jquery brings to the table, I find that it is hard to beat.


Spry does feature some good demos, but it has little in the way of real community so far as I can tell. Their demos seem fast and well done...certainly nothing to complain about from a front end perspective. The documentation also seems rather available.

Stupid jquery tricks

•You have a form that needs an intermediate confirmation page.

This is easiest done by making the form a self-submit form. Use jquery styles to hide the plaintext version of what is input, so it only shows during confirmation, Make a class called confirmation and hide it during the first run. On the second run, show the plaintext and hide the input boxes (or change them to type hidden).

<script language="JavaScript" type="text/javascript" src="./jquery.js">

<script language="javascript">

$(document).ready(function() {

$('.confirmation').hide();

$('.inputfields').show();

});


</script>
•Modify a style for an html element without access to the header section of the document.

<script language="JavaScript" type="text/javascript" src="./jquery.js">

<script language="javascript">

$(document).ready(function() {

$('label').css("font-weight","bold");

});

</script>

•Make an item by id show or hide by clicking on anchors.

By applying a unique id to anchors with class 'edit', we can distinguish which items they are supposed to show and hide by appending to that id and making a new unique id based off of the original.


<script language="JavaScript" type="text/javascript" src="./jquery.js">

<script language="javascript">

$(document).ready(function() {

$('a.edit').click(function() {

$('#' + this.id + '_hide').toggle(400);

});

});


</script>

Sometimes you want a GET and a POST - Javascript Howto

There may be a time you prefer something to submit via POST, but want to make the variables bookmarkable for easy reference. (One reason to do this is if uploading a file. Obviously you can't hold the file in a get variable but all of the options concerning the upload can be held in this fashion.) This is a cheap easy way to do that:

Remember to put the code block under the form declaration, or the last time won't work.


<script type="text/javascript">
function concatenateFields() {
concatenateFields = '';
for(i=0;i<document.forms[0].length;i++) {
concatenateFields += document.forms[0].elements[i].name + '=' + document.forms[0].elements[i].value + "&" ;
}
return concatenateFields;
}
function changeAction(){
actionfile = 'try.php?';
document.forms[0].action = actionfile + concatenateFields();
alert(document.forms[0].action);
return false;
}

document.forms[0].onsubmit = changeAction
</script>

Insert and count tags automatically using MySQL 5.0/5.1 Triggers

Sometimes, for applications, you don't want or desire the trouble of having to insert pieces of a title for say a blog, or a quoted phrase, into some database that contains/tracks your tags. Such a table probably contains fields about an auto inserted tag, such as the identifier itself, how many times the identifier is found, and whether it is worth utilizing in a popular tag list.


Now, with the power of MySQL triggers you no longer have to rely on the power of outside languages to harness these solutions. There are still some limitations to remember with MySQL triggers.For one, we can not call other stored procedures through a trigger. However, that is really more an inconvenience in organization than in functionality.


Below I will highlight some of the code to update a tag table from an insert to a table I call phrases.



DELIMITER //

CREATE TRIGGER `db_name`.`ins_phrases_update` AFTER INSERT ON `db_name`.`phrases`
FOR EACH ROW BEGIN

declare breakfound numeric default 0;
declare phraselength , l_loop, temp int default 1;

set phraselength = length(new.phrase);

while l_loop < phraselength do

SELECT LOCATE(' ', new.phrase, l_loop) INTO breakfound ;

IF breakfound > l_loop THEN
INSERT INTO tags (name) VALUES (LOWER(SUBSTRING(new.phrase, l_loop,breakfound-l_loop))) ON DUPLICATE KEY UPDATE total=total+1;

set temp := l_loop;
set l_loop := breakfound + 1;

ELSE
INSERT INTO tags (name) VALUES (LOWER(SUBSTRING(new.phrase, l_loop,phraselength-l_loop))) ON DUPLICATE KEY UPDATE total=total+1;

set temp := l_loop;
set l_loop := phraselength;

END IF;


end while;

END
//





A few notes of warning to MySQL developers.

  • Only one trigger per table operation. While that may sound limiting, I think that again an originizational inconvenience more than anything.
  • SET can not be used to increment the variable it is acting on. It seems rather Cobal-esque, but you have to declare a temp variable to hold information on any kind of increment or reassign.
  • Command line for whatever reason seems easier at the moment to create triggers than phpMyAdmin. Possibly my own setup, but if it's an issue, drop to commandline and try the same thing.
  • Remember DELIMITER before a trigger write, otherwise your MySQL will think you're ending the trigger at the end of your first SQL statement.
  • This should make sense, but you can not change a "new.value" on and AFTER INSERT operation. With some languages, like php, you can change almost anything temporarily at least, even if it is a special variable.


I have only highlighted the INSERT trigger here. Clearly to make this functional, you need also the DELETE, and maybe the UPDATE triggers. The others you will find are trvial, as with DELETE all you need to do is change every "new.phrase" to "old.phrase" and you are pretty much done. UPDATE will need to combine the DELETE and the INSERT operations.

Tuesday, November 11, 2008

Dreamweaver CS3 aka the "Special Version"

I'm not sure what has ever really been the issue with CS3 but it has in my estimation been the most "crash happy" version of Dreamweaver out there to date. What is really irksome is that they never released any kind of update for this issue, but instead have cranked out another version which is supposed to be an improvement of sorts.

Why does it even crash? The error notices are purposely vague as to this, but I think it has to do with validation checkers breaking the normal function of the program. If there was ever a version of Adobe that could be classified "specials needs", I think this would be it.

Thursday, November 06, 2008

Using triggers to auto-update aggregates with MYSQL

DROP TRIGGER IF EXISTS `db_name`.`ins_ratings_update`//
CREATE TRIGGER `db_name`.`ins_ratings_update` AFTER INSERT ON `db_name`.`ratings`
FOR EACH ROW BEGIN
UPDATE aggregate_storing_table ast SET rating = (SELECT AVG(score) FROM individual_rating_record_table WHERE ast_id=NEW.ast_id);
END
//

MySQL vs PostgreSQL

After some degree of thought and searching it has occured to me, even though I like the Postgres GUI much more than the MySQL one, that the common features...that is the features that a casual developer are going to want to use on a day to day basis are already available and implemented on MySQL. As many people know, Postgres has often been touted as the more flexible solution in that it is generally more feature rich, making it much more capable than MySQL. However, a study of MySQL 5.1 will show that most of what you would want in a DB are already very present and in many cases because of the thorough nature of the documentation, that more easily accessible for the "lay programmer". There are several sites that will tout Postgres as the clear winner if you need that one extra feature X. What MySQL brings to the table it seems is a larger support base and better speed which is available at the cost of less (it would seem) configuration.

Furthermore, it used to be said that MySQL performs best only on single core platforms. Now with recent patches from Google, this is no longer the case.

http://mysqlha.blogspot.com/2008/09/more-patches-than-we-know-what-to-do.html

In the end, it seems that Postgres will win the "feature war" for at least the next several years, but the feature gap is steadily closing. MySQL is stronger on almost every other front.