Article 52J13 CodeSOD: WTFYou, Pay Me

CodeSOD: WTFYou, Pay Me

by
Remy Porter
from The Daily WTF on (#52J13)

Julien's employer has switched their payroll operations to a hosted solution. The hosted solution has some... interesting features. The fact that it has a share" button, implying you can share your paystub infromation with other people is unusual (but good: keeping salaries confidential only helps management underpay their employees). More problematic is that this feature emails it, and instead of putting in an email address manually, you instead pick off a drop-down list- which contains the email of every user of the hosted system.

Seeing this, Julien had to take a peek at the code, just to see what other horrors might lurk in there.

Let's open with some ugly regexes:

var regExtURL =/(http(s)?|ftp:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/;///^(?:(?:https?|ftp):\/\/)?[\w.-]+(?:\S+(?::\S*)?@)?(?:(?!(?:0|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/; function isValidURL(thisObj){if (thisObj.value != '' && !regExtURL.test(thisObj.value)){ alert('Veuillez entrer une URL valide.'); return false;}};var re = /^(([a-zA-Z0-9-_"+"]+(\.[a-zA-Z]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z0-9])+(\-[a-zA-Z0-9]+)*(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,})+))$/;function isEmailKey(thisObj){//var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z0-9]+\.)+[a-zA-Z]{2,}))$/;//var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z0-9])+(\-[a-zA-Z0-9]+)*(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,})+))$/;if (thisObj.value != '' && !re.test(thisObj.value)){ alert('Please enter a valid email address.'); return false;}};

I like that they kept their old attempts at validating email addresses right there in the code. Real helpful for us. Presenting errors via the built-in alert method is also really great UX.

Do you want a super complex and probably inaccurate date validator? We've got one of those:

function validateDateValue(obj, format, errorMesage){ try { format = format.toUpperCase(); if(obj != null){ var dateValue = obj.value; if (dateValue.length == 0) return; if (dateValue.length > 10) dateValue = dateValue.substring(0, 10); if (dateValue.length < 6) { alert(errorMesage); return; } var d = null; var sep = getSeparator(format); if (sep.length > 0) d = stringToDate(dateValue, format, sep); else d = Date.parse(dateValue.substring(0,4) + '-' + dateValue.substring(4,6) + '-' + dateValue.substring(6,8)); if (d == null) { if (dateValue.length == 6 ) { if (d == null) d = stringToDate(dateValue,"ddMMyy",""); if (d == null) d = stringToDate(dateValue,"MMddyy",""); } else if (dateValue.length == 8 ) { d = Date.parse(dateValue.substring(0,4) + '-' + dateValue.substring(4,6) + '-' + dateValue.substring(6,8)); if(isNaN(d)) d = null; if (d == null) d = stringToDate(dateValue,"dd/MM/yy","/"); if (d == null) d = stringToDate(dateValue,"dd-MM-yy","-"); if (d == null) d = stringToDate(dateValue,"dd.MM.yy","."); if (d == null) d = stringToDate(dateValue,"dd MM yy"," "); if (d == null) d = stringToDate(dateValue,"MM/dd/yy","/"); if (d == null) d = stringToDate(dateValue,"MM-dd-yy","-"); if (d == null) d = stringToDate(dateValue,"MM.dd.yy","."); if (d == null) d = stringToDate(dateValue,"MM dd yy"," "); if (d == null) d = stringToDate(dateValue,"yy/MM/dd","/"); if (d == null) d = stringToDate(dateValue,"yy-MM-dd","-"); if (d == null) d = stringToDate(dateValue,"yy.MM.dd","."); if (d == null) d = stringToDate(dateValue,"yy MM dd"," "); } else { if (d == null) d = stringToDate(dateValue,"dd/MM/yyyy","/"); if (d == null) d = stringToDate(dateValue,"dd-MM-yyyy","-"); if (d == null) d = stringToDate(dateValue,"dd.MM.yyyy","."); if (d == null) d = stringToDate(dateValue,"dd MM yyyy"," "); if (d == null) d = stringToDate(dateValue,"MM/dd/yyyy","/"); if (d == null) d = stringToDate(dateValue,"MM-dd-yyyy","-"); if (d == null) d = stringToDate(dateValue,"MM.dd.yyyy","."); if (d == null) d = stringToDate(dateValue,"MM dd yyyy"," "); if (d == null) d = stringToDate(dateValue,"yyyy/MM/dd","/"); if (d == null) d = stringToDate(dateValue,"yyyy-MM-dd","-"); if (d == null) d = stringToDate(dateValue,"yyyy.MM.dd","."); if (d == null) d = stringToDate(dateValue,"yyyy MM dd"," "); } } if (d == null) { alert(errorMesage); } else { var formatedDate = moment(d).format(format); obj.value = formatedDate; } } } catch(e) { alert(errorMesage); }};

In fact, that one's so good, let's do it again!

function validateDateValue_(dateValue, format, errorMesage) {try {format = format.toUpperCase();if (dateValue.length == 0) {return errorMesage;}if (dateValue.length > 10)dateValue = dateValue.substring(0, 10);if (dateValue.length < 6) {return errorMesage;}var d = null;var sep = getSeparator(format);if (sep.length > 0)d = stringToDate(dateValue, format, sep);elsed = Date.parse(dateValue.substring(0, 4) + '-' + dateValue.substring(4, 6) + '-' + dateValue.substring(6, 8));if (d == null) {if (dateValue.length == 6 ) { if (d == null) d = stringToDate(dateValue,"ddMMyy",""); if (d == null) d = stringToDate(dateValue,"MMddyy",""); } else if (dateValue.length == 8) {d = Date.parse(dateValue.substring(0, 4) + '-' + dateValue.substring(4, 6) + '-' + dateValue.substring(6, 8));if (isNaN(d))d = null;if (d == null)d = stringToDate(dateValue, "dd/MM/yy", "/");if (d == null)d = stringToDate(dateValue, "dd-MM-yy", "-");if (d == null)d = stringToDate(dateValue, "dd.MM.yy", ".");if (d == null)d = stringToDate(dateValue, "MM/dd/yy", "/");if (d == null)d = stringToDate(dateValue, "MM-dd-yy", "-");if (d == null)d = stringToDate(dateValue, "MM.dd.yy", ".");if (d == null) d = stringToDate(dateValue,"ddMMyyyy",""); if (d == null) d = stringToDate(dateValue,"MMddyyyy","");} else {if (d == null)d = stringToDate(dateValue, "dd/MM/yyyy", "/");if (d == null)d = stringToDate(dateValue, "dd-MM-yyyy", "-");if (d == null)d = stringToDate(dateValue, "dd.MM.yyyy", ".");if (d == null)d = stringToDate(dateValue, "MM/dd/yyyy", "/");if (d == null)d = stringToDate(dateValue, "MM-dd-yyyy", "-");if (d == null)d = stringToDate(dateValue, "MM.dd.yyyy", ".");if (d == null)d = stringToDate(dateValue, "yyyy-MM-dd", "-");}}if (d == null) {return errorMesage;} else {var formatedDate = moment(d).format(format);dateValue = formatedDate;}} catch (e) {return errorMesage;}return "";};

Yes, that is basically the identical method, but some of the parameter names are different, and one of them has more sensible indentation than the other.

But that only handles dates. What about datetimes?

function validateDateTimeValue(obj, format, errorMesage){format = format.toUpperCase();format = format.substring(0, format.length-2) + "mm"; if(obj != null){ var dateTimeValue = obj.value; if (dateTimeValue.length == 0) return; if (dateTimeValue.length == 8 || dateTimeValue.length == 10 || dateTimeValue.length == 6) dateTimeValue = dateTimeValue + " 00:00"; if (dateTimeValue.length > 16) dateTimeValue = dateTimeValue.substring(0, 16); if (dateTimeValue.length < 12 || dateTimeValue.length > 16){ alert(errorMesage); return; } var time = dateTimeValue.substring(dateTimeValue.length-6, dateTimeValue.length); if (time.charAt(0) != ' '){ alert(errorMesage); return; } var h = parseInt(time.substring(1, 3)); if (isNaN(h)){ alert(errorMesage); return; } var m = parseInt(time.substring(4, 6)); if (isNaN(m)){ alert(errorMesage); return; } var d = null; var dateValue = dateTimeValue.substring(0,dateTimeValue.length-6); var sep = getSeparator(format); if (sep.length>0) d = stringToDateTime(dateValue,format.substring(0, format.length-6), sep,h,m); else d = Date.parse(dateValue.substring(0,4) + '-' + dateValue.substring(4,6) + '-' + dateValue.substring(6,8) + 'T' + h + ':' + m + ':00'); if (d == null){ if (dateTimeValue.length == 12 ){ if (d == null) d = stringToDateTime(dateValue,"ddMMyy","",h,m); if (d == null) d = stringToDateTime(dateValue,"MMddyy","",h,m); } else if (dateTimeValue.length == 14 ){ d = Date.parse(dateValue.substring(0,4) + '-' + dateValue.substring(4,6) + '-' + dateValue.substring(6,8) + 'T' + h + ':' + m + ':00'); if(isNaN(d)) d = null; if (d == null) d = stringToDateTime(dateValue,"dd/MM/yy","/",h,m); if (d == null) d = stringToDateTime(dateValue,"dd-MM-yy","-",h,m); if (d == null) d = stringToDateTime(dateValue,"dd.MM.yy",".",h,m); if (d == null) d = stringToDateTime(dateValue,"dd MM yy"," ",h,m); if (d == null) d = stringToDateTime(dateValue,"MM/dd/yy","/",h,m); if (d == null) d = stringToDateTime(dateValue,"MM-dd-yy","-",h,m); if (d == null) d = stringToDateTime(dateValue,"MM.dd.yy",".",h,m); if (d == null) d = stringToDateTime(dateValue,"MM dd yy"," ",h,m); if (d == null) d = stringToDateTime(dateValue,"yy/MM/dd","/",h,m); if (d == null) d = stringToDateTime(dateValue,"yy-MM-dd","-",h,m); if (d == null) d = stringToDateTime(dateValue,"yy.MM.dd",".",h,m); if (d == null) d = stringToDateTime(dateValue,"yy MM dd"," ",h,m); if (d == null) d = stringToDateTime(dateValue,"ddMMyyyy","",h,m); if (d == null) d = stringToDateTime(dateValue,"MMddyyyy","",h,m); } else { if (d == null) d = stringToDateTime(dateValue,"dd/MM/yyyy","/",h,m); if (d == null) d = stringToDateTime(dateValue,"dd-MM-yyyy","-",h,m); if (d == null) d = stringToDateTime(dateValue,"dd.MM.yyyy",".",h,m); if (d == null) d = stringToDateTime(dateValue,"dd MM yyyy"," ",h,m); if (d == null) d = stringToDateTime(dateValue,"MM/dd/yyyy","/",h,m); if (d == null) d = stringToDateTime(dateValue,"MM-dd-yyyy","-",h,m); if (d == null) d = stringToDateTime(dateValue,"MM.dd.yyyy",".",h,m); if (d == null) d = stringToDateTime(dateValue,"MM dd yyyy"," ",h,m); if (d == null) d = stringToDateTime(dateValue,"yyyy/MM/dd","/",h,m); if (d == null) d = stringToDateTime(dateValue,"yyyy-MM-dd","-",h,m); if (d == null) d = stringToDateTime(dateValue,"yyyy.MM.dd",".",h,m); if (d == null) d = stringToDateTime(dateValue,"yyyy MM dd"," ",h,m); } } if (d == null) { alert(errorMesage); } else{ var formatedDate = moment(d).format(format); obj.value = formatedDate; } } return true;}

And is it also duplicated? You know it is, following the same underscore naming convention: validateDateTimeValue_. (I won't share it again)

Okay, complex regexes that you can't debug is bad. Custom date handling code is a WTF. Duplicating that code for no clear reason is bizarre. But what's the stinger?

How about hardcoded credentials for connecting to the database"?

function Register(){registerCurrentUserToFDB("Doe", "name surname", "abc@abc.com", "chgitem", "0fc6c0427cea929a3e21028f68cecf42");}function Login(){loginUserToFDB("abc@abc.com", "0fc6c0427cea929a3e21028f68cecf42");}

In this the backend is Firebase (that's the FDB above), so this is client side JS phoning home to a Firebase backend.

buildmaster-icon.png [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how! TheDailyWtf?d=yIl2AUoC8zAE3mN70aJtcs
External Content
Source RSS or Atom Feed
Feed Location http://syndication.thedailywtf.com/TheDailyWtf
Feed Title The Daily WTF
Feed Link http://thedailywtf.com/
Reply 0 comments