-Поиск по дневнику

Поиск сообщений в rss_thedaily_wtf

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 06.04.2008
Записей:
Комментариев:
Написано: 0

The Daily WTF





Curious Perversions in Information Technology


Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://thedailywtf.com/.
Данный дневник сформирован из открытого RSS-источника по адресу http://syndication.thedailywtf.com/thedailywtf, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

CodeSOD: ImAlNumb?

Среда, 11 Сентября 2019 г. 09:30 + в цитатник

I think it’s fair to say that C, as a language, has never had a particularly great story for working with text. Individual characters are okay, but strings are a nightmare. The need to support unicode has only made that story a little more fraught, especially as older code now suddenly needs to support extended characters. And by “older” I mean, “wchar was added in 1995, which is practically yesterday in C time”.

Lexie inherited some older code. It was not designed to support unicode, which is certainly a problem in 2019, and it’s the problem Lexie was tasked with fixing. But it had an… interesting approach to deciding if a character was alphanumeric.

Now, if we limit ourselves to ASCII, there are a variety of ways we could do this check. We could convert it to a number and do a simple check- characters 48–57 are numeric, 65–90 and 97–122 cover the alphabetic characters. But that’s a conditional expression- six comparison operations! So maybe we should be more clever. There is a built-in library function, isalnum, which might be more optimized, and is available on Lexie’s platform. But we’re dedicated to really doing some serious premature optimization, so there has to be a better way.

bool isalnumCache[256] =
{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true, false, false, false, false, false, false,
false,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true, false, false, false, false, false,
false,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true, true, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};

This is a lookup table. Convert your character to an integer, and then use it to index the array. This is fast. It’s also error prone, and this block does incorrectly identify a non-alphanumeric as an alphanumeric. It also 100% fails if you are dealing with wchar_t, which is how Lexie ended up looking at this block in the first place.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/imalnumb


Метки:  

Death by Consumption

Вторник, 10 Сентября 2019 г. 09:30 + в цитатник

Tryton Party Module Address Database Diagram

The task was simple: change an AMQ consumer to insert data into a new Oracle database instead of an old MS-SQL database. It sounded like the perfect task for the new intern, Rodger; Rodger was fresh out of a boot camp and ready for the real world, if he could only get a little experience under his belt. The kid was bright as they came, but boot camp only does so much, after all.

But there are always complications. The existing service was installed on the old app servers that weren't setup to work with the new corporate app deployment tool. The fix? To uninstall the service on the old app servers and install it on the new ones. Okay, simple enough, if not well suited to the intern.

Rodger got permissions to set up the service on his local machine so he could test his install scripts, and a senior engineer got an uninstall script working as well, so they could seamlessly switch over to the new machines. They flipped the service; deployment day came, and everything went smoothly. The business kicked off their process, the consumer service picked up their message and inserted data correctly to the new database.

The next week, the business kicked off their process again. After the weekend, the owners of the old database realized that the data was inserted into the old database and not the new database. They promptly asked how this had happened. Rodger and his senior engineer friend checked the queue; it correctly had two consumers set up, pointing at the new database. Just to be sure, they also checked the old servers to make sure the service was correctly uninstalled and removed by tech services. All clear.

Hours later, the senior engineer refreshed the queue monitor and saw the queue now had three consumers despite the new setup having only two servers. But how? They checked all three servers—two new and one old—and found no sign of a rogue process.

By that point, Rodger was online for his shift, so the senior engineer headed over to talk to him. "Say, Rodger, any chance one of your installs duplicated itself or inserted itself twice into the consumer list?"

"No way!" Rodger replied. "Here, look, you can see my script, I'll run it again locally to show you."

Running it locally ... with dawning horror, the senior engineer realized what had happened. Roger had the install script, but not the uninstall—meaning he had a copy still running on his local developer laptop, connected to the production queue, but with the old config for some reason. Every time he turned on his computer, hey presto, the service started up.

The moral of the story: always give the intern the destructive task, not the constructive one. That can't go wrong, right?

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/death-by-consumption


Метки:  

CodeSOD: Making a Nest

Понедельник, 09 Сентября 2019 г. 09:30 + в цитатник

Tiffany started the code review with an apology. "I only did this to stay in style with the existing code, because it's either that or we rewrite the whole thing from scratch."

Jim J, who was running the code review nodded. Before Tiffany, this application had been designed from the ground up by Armando. Armando had gone to a tech conference, and learned about F#, and how all those exciting functional features were available in C#, and returned jabbering about "immutable data" and "functors" and "metaprogramming" and decided that he was now a functional programmer, who just happened to work in C#.

Some struggling object-oriented developers use dictionaries for everything. As a struggling functional programmer, Armando used tuples for everything. And these tuples would get deeply nested. Sometimes, you needed to flatten them back out.

Tiffany had contributed this method to do that:

public static Result> FlatternTupleResult( Result, T3>, T4>, T5>> tuple ) { return tuple.Map(x => new Tuple(x.Item1.Item1.Item1.Item1, x.Item1.Item1.Item1.Item2, x.Item1.Item1.Item2, x.Item1.Item2, x.Item2)); }

It's safe to say that deeply nested generics are a super clear code smell, and this line: Result, T3>, T4>, T5>> tuple downright reeks. Tuples in tuples in tuples.

Tiffany cringed at the code she had written, but this method lived in the TaskResultHelper class, and lived alongside methods with these signatures:

public static Result> FlatternTupleResult(Result, T3>, T4>> tuple) public static Result> FlatternTupleResult(Result, T3>> tuple)

"This does fit in with the way the application currently works," Jim admitted. "I'm sorry."

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

https://thedailywtf.com/articles/making-a-nest


Метки:  

Error'd: Does Your Child Say "WTF" at Home?

Пятница, 06 Сентября 2019 г. 09:30 + в цитатник

Abby wrote, "I'm tempted to tell the school that my child mostly speaks Sanskrit."

 

"First of all, I have 58,199 rewards points, so I'm a little bit past joining, second, I'm pretty sure Bing Rewards was rebranded as Microsoft Rewards a while ago, and third...SERPBubbleXL...wat?" writes Zander.

 

"I guess, for T-Mobile, time really is money," Greg writes.

 

Hans K. wrote, "I guess it's sort of fitting, but in a quiz about Generics in Java, I was left a little bit confused.

 

"Wait, so if I do, um, nothing, am I allowed to make further changes or any new appointment?" Jeff K. writes.

 

Soumya wrote, "Yeah...I'm not a big fan of Starbucks' reward program..."

 

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/does-your-child-say-wtf-at-home


Метки:  

CodeSOD: Give Your Date a Workout

Четверг, 05 Сентября 2019 г. 09:30 + в цитатник

Bob E inherited a site which helps amateur sports clubs plan their recurring workouts/practices during the season. To do this, given the start date of the season, and the number of weeks, it needs to figure out all of the days in that range.

function GenWorkoutDates()
{

   global $SeasonStartDate, $WorkoutDate, $WeeksInSeason;

   $TempDate = explode("/", $SeasonStartDate);

   for ($i = 1; $i <= $WeeksInSeason; $i++)
   {
     for ($j = 1; $j <= 7; $j++)
     {

	   $MonthName = substr("JanFebMarAprMayJunJulAugSepOctNovDec", $TempDate[0] * 3 - 3, 3);

       $WorkoutDate[$i][$j] = $MonthName . " " . $TempDate[1] . "  ";
       $TempDate[1] += 1;


       switch ( $TempDate[0] )
	   {
     case 9:
	   case 4:
	   case 6:
	   case 11:
	     $DaysInMonth = 30;
	     break;

	   case 2:
     	 $DaysInMonth = 28;

	     switch ( $TempDate[2] )
	     {
	     case 2012:
	     case 2016:
	     case 2020:
	     	$DaysInMonth = 29;
	        break;

	     default:
	       $DaysInMonth = 28;
	       break;
	     }

	     break;

	   default:
	     $DaysInMonth = 31;
	     break;
	   }

	   if ($TempDate[1] > $DaysInMonth)
	   {
	     $TempDate[1] = 1;
	     $TempDate[0] += 1;
	     if ($TempDate[0] > 12)
	     {
	       $TempDate[0] = 1;
	       $TempDate[2] += 1;
	     }
	   }
     }
   }
}

I do enjoy that PHP’s string-splitting function is called explode. That’s not a WTF. More functions should be called explode.

This method of figuring out the month name, though:

$MonthName = substr("JanFebMarAprMayJunJulAugSepOctNovDec", $TempDate[0] * 3 - 3, 3);

I want to hate it, but I’m impressed with it.

From there, we have lovely hard-coded leap years, the “Thirty days has September…” poem implemented as a switch statement, and then that lovely rollover calculation for the end of a month (and the end of the year).

“I’m not a PHP developer,” Bob writes. “But I know how to use Google.” After some googling, he replaced this block of code with a 6-line version that uses built-in date handling functions.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/give-your-date-a-workout


Метки:  

CodeSOD: UnINTentional Errors

Среда, 04 Сентября 2019 г. 09:30 + в цитатник

Data type conversions are one of those areas where we have rich, well-supported, well-documented features built into most languages. Thus, we also have endless attempts for people to re-implement them. Or worse, wrap a built-in method in a way which makes everything less clear.

Mindy encountered this.

/* For converting (KEY_MSG_INPUT) to int format. */
public static int numberToIntFormat(String value) {
  int returnValue = -1;    	
  if (!StringUtil.isNullOrEmpty(value)) {
    try {
      int temp = Integer.parseInt(value);
      if (temp > 0) {
        returnValue = temp;
      }
    } catch (NumberFormatException e) {}
  }    	
  return returnValue;
}

The isNullOrEmpty check is arguably pointless, here. Any invalid input string, including null or empty ones, would cause parseInt to throw a NumberFormatException, which we’re already catching. Of course, we’re catching and ignoring it.

That’s assuming that StringUtil.isNullOrEmpty does what we think it does, since while there are third party Java libraries that offer that functionality, it’s not a built-in class (and do we really think the culprit here was using libraries?). Who knows what it actually does.

And, another useful highlight: note how we check if (temp > 0)? Well, this is a problem. Not only does the downstream code handle negative numbers, –1 is a perfectly reasonable value, which means when this method takes -10 and returns -1, what it’s actually done is passed incorrect but valid data back up the chain. And since any errors were swallowed, no one knows if this was intentional or not.

This method wasn’t called in any context relating to KEY_MSG_INPUT, but it was called everywhere, as it’s one of those utility methods that finds new uses any time someone wants to convert a string into a number. Due to its use in pretty much every module, fixing this is considered a "high risk" change, and has been scheduled for sometime in the 2020s.

[Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!

https://thedailywtf.com/articles/unintentional-errors


Метки:  

CodeSOD: Boxing with the InTern

Вторник, 03 Сентября 2019 г. 09:30 + в цитатник

A few years ago, Naomi did an internship with Initech. Before her first day, she was very clear on what her responsibilities would be: she'd be on a team modernizing an older product called "Gem" (no relation to Ruby libraries).

By the time her first day rolled around, however, Initech had new priorities. There were a collection of fires on some hyperspecific internal enterprise tool, and everyone was running around and screaming about the apocalypse while dealing with that. Except Naomi, because nobody had any time to bring the intern up to speed on this disaster. Instead, she was given a new priority: just maintain Gem. And no, she wouldn't have a mentor. For the next six months, Naomi was the Gem support team.

"Start by looking at the code quality metrics," was the advice she was given.

It was bad advice. First, while Initech had installed an automated code review tool in their source control system, they weren't using the tool. It had started crashing instead of outputting a report six years ago. Nobody had noticed, or perhaps nobody had cared. Or maybe they just didn't like getting bad news, because once Naomi had the tool running again, the report was full of bad news.

A huge mass of the code was reimplemented copies of the standard library, "tuned for performance", which meant instead of a sensible implementation it was a pile of 4,000 line functions wrapping around massive switch statements. The linter didn't catch that they were parsing XML using regular expressions, but Naomi spotted that and wisely decided not to touch that bit.

What she did find, and fix, was this pattern:

private Boolean isSided; // dozens more properties public GemGeometryEntryPoint(GemGeometryEntryPoint gemGeometryEntryPoint) { this.isSided = gemGeometryEntryPoint.isSided == null ? null : new Boolean(gemGeometryEntryPoint.isSided); // and so on, for those dozens of properties }

Java has two boolean types. The Boolean reference type, and boolean primitive type. The boolean is not a full-fledged object, and thus is smaller in memory and faster to allocate. The Boolean is a full class implementation, with all the overhead contained within. A Java developer will generally need to use both, as if you want a list of boolean values, you need to "box" any primitives into Boolean objects.

I say generally need both, because Naomi's predecessors decided that worrying about boxing was complicated, so they only used the reference types. There wasn't a boolean or an int to be found, just Booleans and Integers. Maybe they just thought "primitive" meant "legacy"?

You can't convert a null into a boxed type, so new Boolean(null) would throw an exception. Thus, the ternary check in the code above. At no point did anyone think that "hey, we're doing a null check on pretty much every variable access" mean that there was something wrong in the code.

The bright side to this whole thing was that the unit tests were exemplary. A few hours with sed meant that Naomi was able to switch most everything to primitive types, confirm that she hadn't introduced any regressions in the process, and even demonstrated that using primitives greatly improved performance, as it cut down on heap memory allocations. The downside was replacing all those ternaries with lines like this.isSided = other.gemGeometryEntryPoint.isSided didn't look nearly as impressive.

Of course, changing that many lines of code in a single commit triggered some alarms, which precipitated a mini-crisis as no one knew what to do when the intern submitted a 15,000 line commit.

Naomi adds: "Mabye null was supposed to represent FILE_NOT_FOUND?"

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/boxing-with-the-intern


Метки:  

Classic WTF: Hyperlink 2.0

Понедельник, 02 Сентября 2019 г. 09:30 + в цитатник
It's Labor Day in the US, where we celebrate the workers of the world by having a barbecue. Speaking of work, in these days of web frameworks and miles of unnecessary JavaScript to do basic things on the web, let's look back at a simpler time, where we still used server-side code and miles of unnecessary JavaScript to do basic things on the web. Original. --Remy

For those of you who haven't upgraded to Web 2.0 yet, today's submission from Daniel is a perfect example of what you're missing out on. Since the beginning of the Web (the "1.0 days"), website owners have always wanted to know who was visiting their website, how often, and when. Back then, this was accomplished by recording each website "hit" in a log file and running a report on the log later.

But the problem with this method in Web 2.0 is that people don't use logs anymore; they use blogs, and everyone knows that blogs are a pretty stupid way of tracking web traffic. Fortunately, Daniel's colleagues developed an elegant, clever, and -- most importantly -- "AJAX" way of solving this problem. Instead of being coded in HTML pages, all hyperlinks are assigned a numeric identifier and kept in a database table. This identifier is then used on the HTML pages within an anchor tag:

View Products

When the user clicks on the hyperlink, the followLink() Javascript function is executed and the following occur:

  • a translucent layer (DIV) is placed over the entire page, causing it to appear "grayed out", and ...
  • a "please wait" layer is placed on top of that, with an animated pendulum swinging back and forth, then ...
  • the XmlHttpRequest object is used to call the "GetHyperlink" web service which, in turn ...
  • opens a connection to the database server to ...
  • log the request in the RequestedHyperlinks table and ...
  • retrieves the URL from the Hyperlinks table, then ...
  • returns it to the client script, which then ...
  • sets the window.location property to the URL retrieved, which causes ...
  • the user to be redirected to the appropriate page

Now that's two-point-ohey.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/classic-wtf-hyperlink-2-0


Метки:  

Error'd: Resistant to Change

Пятница, 30 Августа 2019 г. 09:30 + в цитатник

Tom H. writes, "They got rid of their old, outdated fax machine, but updating their website? Yeah, that might take a while."

 

"In casinos, they say the house always wins. In this case, when I wanted to cash in my winnings, I gambled and lost against Windows 7 Professional," Michelle M. wrote.

 

Martin writes, "Wow! It's great to see Apple is going the extra mile by protecting my own privacy from myself!"

 

"Yes, Amazon Photos, with my mouse clicks, I will fix you," wrote Amos B.

 

"When searches go wrong at AliExpress they want you to know these three things," Erwan R. wrote.

 

Chris A. writes, "It's like Authy is saying 'I have no idea what you just did, but, on the bright side, there weren`t any errors!'"

 

[Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!

https://thedailywtf.com/articles/resistant-to-change


Метки:  

CodeSOD: Bassackwards Compatibility

Четверг, 29 Августа 2019 г. 09:30 + в цитатник

A long time ago, you built a web service. It was long enough ago that you chose XML as your serialization format. It worked fine, but before long, customers started saying that they’d really like to use JSON, so now you need to expose a slightly different, JSON-powered version of your API. To make it easy, you release a JSON client developers can drop into their front-ends.

Conor is one of those developers, and while examining the requests the client sent, he discovered a unique way of making your XML web-service JSON-friendly.

{"fetch":""}

Simplicity itself!

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/bassackwards-compatibility


Метки:  

Teleported Release

Среда, 28 Августа 2019 г. 09:30 + в цитатник

Matt works at an accounting firm, as a data engineer. He makes reports for people who don’t read said reports. Accounting firms specialize in different areas of accountancy, and Matt’s firm is a general firm with mid-size clients.

The CEO of the firm is a legacy from the last century. The most advanced technology on his desk is a business calculator and a pencil sharpener. He still doesn’t use a cellphone. But he does have a son, who is “tech savvy”, which gives the CEO a horrible idea of how things work.

Usually, this is pretty light, in that it’s sorting Excel files or sorting the output of an existing report. Sometimes the requests are bizarre or utter nonsense. And, because the boss doesn’t know what the technical folks are doing, some of the IT staff may be a bit lazy about following best practices.

This means that most of Matt’s morning is spent doing what is essentially Tier 1 support before he gets into doing his real job. Recently, there was a worse crunch, as actual support person Lucinda was out for materinity leave, and Jackie, the one other developer, was off on vacation on a foreign island with no Internet. Matt was in the middle of eating a delicious lunch of take-out lo mein when his phone rang. He sighed when he saw the number.

“Matt!” the CEO exclaimed. “Matt! We need to do a build of the flagship app! And a deploy!”

The app was rather large, and a build could take upwards of 45 minutes, depending on the day and how the IT gods were feeling. But the process was automated, the latest changes all got built and deployed each night. Anything approved was released within 24 hours. With everyone out of the office, there hadn’t been any approved changes for a few weeks.

Matt checked the Github to see if something went wrong with the automated build. Everything was fine.

“Okay, so I’m seeing that everything built on GitHub and everything is available in production,” Matt said.

“I want you to do a manual build, like you used to.”

“If I were to compile right now, it could take quite awhile, and redeploying runs the risk of taking our clients offline, and nothing would be any different.”

“Yes, but I want a build that has the changes which Jackie was working on before she left for vacation.”

Matt checked the commit history, and sure enough, Jackie hadn’t committed any changes since two weeks before leaving on vacation. “It doesn’t looked like she pushed those changes to Github.”

“Githoob? I thought everything was automated. You told me the process was automated,” the CEO said.

“It’s kind of like…” Matt paused to think of an analogy that could explain this to a golden retriever. “Your dishwasher, you could put a timer on it to run it every night, but if you don’t load the dishwasher first, nothing gets cleaned.”

There was a long pause as the CEO failed to understand this. “I want Jackie’s front-page changes to be in the demo I’m about to do. This is for Initech, and there’s millions of dollars riding on their account.”

“Well,” Matt said, “Jackie hasn’t pushed- hasn’t loaded her metaphorical dishes into the dishwasher, so I can’t really build them.”

“I don’t understand, it’s on her computer. I thought these computers were on the cloud. Why am I spending all this money on clouds?”

“If Jackie doesn’t put it on the cloud, it’s not there. It’s uh… like a fax machine, and she hasn’t sent us the fax.”

“Can’t you get it off her laptop?”

“I think she took it home with her,” Matt said.

“So?”

“Have you ever seen Star Trek? Unless Scotty can teleport us to Jackie’s laptop, we can’t get at her files.”

The CEO locked up on that metaphor. “Can’t you just hack into it? I thought the NSA could do that.”

“No-” Matt paused. Maybe Matt could try and recreate the changes quickly? “How long before this meeting?” he asked.

“Twenty minutes.”

“Just to be clear, you want me to do a local build with files I don’t have by hacking them from a computer which may or may not be on and connected to the Internet, and then complete a build process which usually takes 45 minutes- at least- deploy to production, so you can do a demo in twenty minutes?”

“Why is that so difficult?” the CEO demanded.

“I can call Jackie, and if she answers, maybe we can figure something out.”

The CEO sighed. “Fine.”

Matt called Jackie. She didn’t answer. Matt left a voicemail and then went back to eating his now-cold lo mein.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/teleported-release


Метки:  

CodeSOD: Yesterday's Enterprise

Вторник, 27 Августа 2019 г. 09:30 + в цитатник

I bumped into a few co-workers (and a few readers- that was a treat!) at Abstractions last week. My old co-workers informed me that the mainframe system, which had been “going away any day now” since about 1999, had finally gone away, as of this year.

A big part of my work at that job had been about running systems in parallel with the mainframe in some fashion, which meant I made a bunch of “datapump” applications which fed data into or pulled data out of the mainframe. Enterprise organizations often don’t know what their business processes are: the software which encodes the process is older than most anyone working in the organization, and it must work that way, because that’s the process (even though no one knows why).

Robert used to work for a company which offers an “enterprise” product, and since they know that their customers don’t actually know what they’re doing, this product can run in parallel with their existing systems. Of course, running in parallel means that you need to synchronize with the existing system.

So, for example, there were two systems. One we’ll call CQ and one we’ll call FP. Let’s say FP has the latest data. We need a method which updates CQ based on the state of FP. This is that method.

private boolean updateCQAttrFromFPAttrValue(CQRecordAttribute cqAttr, String cqtype,
        Attribute fpAttr)
        throws Exception
    {
        AppLogService.debug("Invoking " + this.getClass().getName()
            + "->updateCSAttrFromFPAttrValue()");

        String csAttrName = cqAttr.getName();
        String csAttrtype = cqAttr.getAttrType();
        String str = avt.getFPAttributeValueAsString(fpAttr);
        if (str == null)
            return false;

        if (csAttrtype.compareTo(CQConstants.CQ_SHORT_STRING_TYPE) != 0
            || csAttrtype.compareTo(CQConstants.CQ_MULTILINE_STRING_TYPE) != 0)
        {
            String csStrValue = cqAttr.getStringValue();
            if (str == null) {
                return false;
            }
            if (csStrValue != null) {
                if (str.compareTo(csStrValue) == 0) // No need to update. Still
                // same values
                {
                    return false;
                }
            }
            cqAttr.setStringValue(str);
            AppLogService.debug("CQ Attribute Name- " + csAttrName + ", Type- "
                + csAttrtype + ", Value- " + str);
            AppLogService.debug("Exiting " + this.getClass().getName()
                + "->updateCSAttrFromFPAttrValue()");
            return true;
        }
        if (csAttrtype.compareTo(CQConstants.CQ_SHORT_STRING_TYPE) == 0) {
            AttributeChoice_type0 choicetype = fpAttr
                .getAttributeChoice_type0();
            if (choicetype.getCheckBox() != null) {
                boolean val = choicetype.getCheckBox().getValue();

                if (val) {
                    str = "1";
                }

                if (str.equals(cqAttr.getStringValue())) {
                    return false;
                }

                cqAttr.setStringValue(str);

                AppLogService.debug("CS Attribute Name- " + csAttrName
                    + ", Type- " + csAttrtype + ", Value- " + str);
                AppLogService.debug("Exiting " + this.getClass().getName()
                    + "->updateCQAttrFromFPAttrValue()");
                return true;
            }
            return false;
        }
        if (csAttrtype.compareTo(CQConstants.CQ_DATE_TYPE) == 0) {
            AttributeChoice_type0 choicetype = fpAttr
                .getAttributeChoice_type0();
            if (choicetype.getDate() != null) {
                Calendar cald = choicetype.getDate().getValue();
                if (cald == null) {
                    return false;
                } else {
                    SimpleDateFormat fmt = new SimpleDateFormat(template
                        .getAdapterdateformat());
                    cqAttr.setStringValue(fmt.format(cald.getTime()));
                }
                AppLogService.debug("CS Attribute Name- " + csAttrName
                    + ", Type- " + csAttrtype + ", Value- " + str);
                AppLogService.debug("Exiting " + this.getClass().getName()
                    + "->updateCSAttrFromFPAttrValue()");
                return true;
            }
            return false;
        }

        AppLogService.debug("Exiting " + this.getClass().getName()
            + "->updateCSAttrFromFPAttrValue()");
        return false;
    }

For starters, I have to say that the method name is a thing of beauty: updateCQAttrFromFPAttrValue. It’s meaningful if you know the organizational jargon, but utterly opaque to everyone else in the world. Of course, this is the last time the code is clear even to those folks, as the very first line is a log message which outputs the wrong method name: updateCSAttrFromFPAttrValue. After that, all of our cqAttr properties get stuffed into csAttr variables.

And the fifth line: String str = avt.getFPAttributeValueAsString(fpAttr);

avt stands for “attribute value translator”, and yes, everything is string-ly typed, because of course it is.

That gets us five lines in, and it’s all downhill from there. Judging from all the getCheckBox() calls, we’re interacting with UI components directly, pretty much every logging message outputs the wrong method name, except the rare case where it doesn’t.

And as ugly and awful as this code is, it’s strangely familiar. Oh, I’ve never seen this particular bit of code before. But I have seen the code my old job wrote to keep the mainframe in sync with the Oracle ERP and the home-grown Access databases and internally developed dashboards and… it all looked pretty much like this.

The code you see here? This is the code that runs the world. This is what gets invoices processed, credit cards billed, inventory shipped, factories staffed, and hazardous materials accounted for.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/yesterday-s-enterprise


Метки:  

CodeSOD: Checksum Yourself Before you Wrecksum Yourself

Понедельник, 26 Августа 2019 г. 09:30 + в цитатник

Mistakes happen. Errors crop up. Since we know this, we need to defend against it. When it comes to things like account numbers, we can make a rule about which numbers are valid by using a checksum. A simple checksum might be, "Add the digits together, and repeat until you get a single digit, which, after modulus with a constant, must be zero." This means that most simple data-entry errors will result in an invalid account number, but there's still a nice large pool of valid numbers to draw from.

James works for a company that deals with tax certificates, and thus needs to generate numbers which meet a similar checksum rule. Unfortunately for James, this is how his predecessor chose to implement it:

while (true) { digits = ""; for (int i = 0; i < certificateNumber.ToString().Length; i++) { int doubleDigit = Convert.ToInt32(certificateNumber.ToString().Substring(i, 1)) * 2; digits += (doubleDigit.ToString().Length > 1 ? Convert.ToInt32(doubleDigit.ToString().Substring(0, 1)) + Convert.ToInt32(doubleDigit.ToString().Substring(1, 1)) : Convert.ToInt32(doubleDigit.ToString().Substring(0, 1))); } int result = digits.ToString().Sum(c => c - '0'); if ((result % 10) == 0) break; else certificateNumber++; }

Whitespace added to make the ternary vaguely more readable.

We start by treating the number as a string, which allows us to access each digit individually, and as we loop, we'll grab a digit and double it. That, unfortunately, gives us a number, which is a big problem. There's absolutely no way to tell if a number is two digits long without turning it back into a string. Absolutely no way! So that's what we do. If the number is two digits, we'll split it back up and add those digits together.

Which again, gives us one of those pesky numbers. So once we've checked every digit, we'll convert that number back to a useful string, then Sum the characters in the string to produce a result. A result which, we hope, is divisible by 10. If not, we check the next number. Repeat and repeat until we get a valid result.

The worst part is, though, is that you can see from the while loop that this is just dropped into a larger method. This isn't a single function which generates valid certificate numbers. This is a block that gets dropped in line. Similar, but slightly different blocks are dropped in when numbers need to be validated. There's no single isValidCertificate method.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/checksum-yourself-before-you-wrecksum-yourself


Метки:  

Error'd: One Size Fits All

Пятница, 23 Августа 2019 г. 09:30 + в цитатник

"Multi-platform AND multi-gender! Who knew SSDs could be so accomodating?" Felipe C. wrote.

 

"This is a progress indicator from a certain Australian "Enterprise" ERP vendor. I suspect their sales guys use it to claim that their software updates over 1000% faster than their competitors," Erin D. writes.

 

Bruce W. writes, "I guess LinkedIn wants me to know that I'm not as popular as I think."

 

"According to Icinga's Round Trip Average calculation, one of our servers must have been teleported about a quarter of the way to the center of the Milky Way. The good news is that I have negative packet loss on that route. Guess the packets got bored on the way," Mike T. writes.

 

"From undefined to invalid, this bankruptcy site has it all...or is it nothing?" Pascal writes.

 

 

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/one-size-fits-all


Метки:  

Keeping Busy

Четверг, 22 Августа 2019 г. 09:30 + в цитатник

Djungarian Hamster Pearl White run wheel

In 1979, Argle was 18, happy to be working at a large firm specializing in aerospace equipment. There was plenty of opportunity to work with interesting technology and learn from dozens of more senior programs—well, usually. But then came the day when Argle's boss summoned him to his cube for something rather different.

"This is a listing of the code we had prior to the last review," the boss said, pointing to a stack of printed Fortran code that was at least 6 inches thick. "This is what we have now." He gestured to a second printout that was slightly thicker. "I need you to read through this code and, in the old code, mark lines with 'WAS' where there was a change and 'IS' in the new listing to indicate what it was changed to."

Argle frowned at the daunting paper mountains. "I'm sorry, but, why do you need this exactly?"

"It's for FAA compliance," the boss said, waving his hand toward his cubicle's threshold. "Thanks!"

Weighed down with piles of code, Argle returned to his cube with a similarly sinking heart. At this place and time, he'd never even heard of UNIX, and his coworkers weren't likely to know anything about it, either. Their development computer had a TMS9900 CPU, the same one in the TI-99 home computer, and it ran its own proprietary OS from Texas Instruments. There was no diff command or anything like it. The closest analog was a file comparison program, but it only reported whether two files were identical or not.

Back at his cube, Argle stared at the printouts for a while, dreading the weeks of manual, mind-numbing dullness that loomed ahead of him. There was no way he'd avoid errors, no matter how careful he was. There was no way he'd complete this to every stakeholder's satisfaction. He was staring imminent failure in the face.

Was there a better way? If there weren't already a program for this kind of thing, could he write his own?

Argle had never heard of the Hunt–McIlroy algorithm, but he thought he might be able to do line comparisons between files, then hunt ahead in one file or the other until he re-synched again. He asked one of the senior programmers for the files' source code. Within one afternoon of tinkering, he'd written his very own diff program.

The next morning, Argle handed his boss 2 newly printed stacks of code, with "WAS -->" and "IS -->" printed neatly on all the relevant lines. As the boss began flipping through the pages, Argle smiled proudly, anticipating the pleasant surprise and glowing praise to come.

Quite to Argle's surprise, his boss fixed him with a red-faced, accusing glare. "Who said you could write a program?!"

Argle was speechless at first. "I was hired to program!" he finally blurted. "Besides, that's totally error-free! I know I couldn't have gotten everything correct by hand!"

The boss sighed. "I suppose not."

It wasn't until Argle was much older that his boss' reaction made any sense to him. The boss' goal hadn't been "compliance." He simply hadn't had anything constructive for Argle to do, and had thought he'd come up with a brilliant way to keep the new young hire busy and out of his hair for a few weeks.

Writer's note: Through the ages and across time, absolutely nothing has changed. In 2001, I worked at a (paid, thankfully) corporate internship where I was asked to manually browse through a huge network share and write down what every folder contained, all the way through thousands of files and sub-folders. Fortunately, I had heard of the dir command in DOS. Within 30 minutes, I proudly handed my boss the printout of the output—to his bemusement and dismay. —Ellis

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/keeping-busy


Метки:  

Coded Smorgasbord: Unstrung Manager

Среда, 21 Августа 2019 г. 09:30 + в цитатник

Deon was on a contract-to-hire job. In the beginning, it sounded like a good job. Then he looked at the C# codebase. It didn’t take him long to decide that this wasn’t going to be a job he’d work at full time. Still, he’d be happy to continue contracting, because it was quite obvious that it would be a lot of billable hours.

How many is “a lot”? Well, let’s talk about their StringManager class. A common WTF is a “god” class that does a thousand different things. Here’s a class made up of nothing but static functions which is 1800 lines long. This wasn’t assembled by a junior developer or an intern, but their senior technical lead, who was adamant that this was the right way to program, and god damn anybody who said otherwise.

		public static DateTime ConvertCharacterDateToDateTime(string inputMM,
			string inputDD,
			string inputYYYY)
		{
			inputMM = initrode.utilities.StringManager.Fill(inputMM,
				"0",    /* Zero-fill */
				true,   /* From Left */
				2);
			inputDD = initrode.utilities.StringManager.Fill(inputDD,
				"0",    /* Zero-fill */
				true,   /* From Left */
				2);

			int _MM = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputMM);
			int _DD = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputDD);
			int _YYYY = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputYYYY);
			return new DateTime(_YYYY,
				_DD,
				_MM);
		}

This is just a little taste, a small aperitif. Convert three strings into a datetime object. For some reason, this requires padding to be added to the strings. For some reason, all the calls to StringManager methods are fully prefixed with their namespace, which is utterly unnecessary from inside that namespace.

But, I mean, dates are “easy mode”. How about FormatDecimalAsString?

        public static string FormatDecimalAsString
                            (
                                decimal inputDecimal
                                , int inputNumberOfDecimalPlaces
                            )
        {
            StringBuilder _decimalStringBldr =
                new StringBuilder();
            string _tempDecimalString = inputDecimal.ToString();
            //No decimal point
            if (_tempDecimalString.IndexOf(".") < 0)
            {
                _decimalStringBldr.AppendFormat
                (
                    "{0}.{1}"
                    , _tempDecimalString
                    , initrode.utilities.StringManager.Fill
                        (
                            ""    //string input
                            , "0"  //string fillChars
                            , true //bool boolFromLet
                            , inputNumberOfDecimalPlaces    // int maxLength
                        )
                );
            }
            //"." exists
            else
            {
                //If "." at start of string.
                if (_tempDecimalString.IndexOf(".") == 0)
                {
                    _decimalStringBldr.AppendFormat
                    (
                        "0.{0}"
                        ,   initrode.utilities.StringManager.Fill
                            (
                                _tempDecimalString.Substring(1)    //string input
                                , "0"  //string fillChars
                                , false //bool boolFromLeft
                                , inputNumberOfDecimalPlaces    // int maxLength
                            )
                    );
                }
                // "." not at start.
                else
                {
                    //  "." at very end.
                    if (_tempDecimalString.IndexOf(".") == (_tempDecimalString.Length - 1))
                    {
                        _decimalStringBldr.AppendFormat
                        (
                            "{0}.{1}"
                            , _tempDecimalString.Substring(0, (_tempDecimalString.Length - 1))
                            , initrode.utilities.StringManager.Fill
                                (
                                    _tempDecimalString.Substring(1)    //string input
                                    , "0"  //string fillChars
                                    , false //bool boolFromLeft
                                    , inputNumberOfDecimalPlaces    // int maxLength
                                )
                        );
                    }
                    // "." in middle.
                    else
                    {
                        ArrayList _parts =
                            initrode.utilities.StringManager.splitIntoArrayList
                            (
                               _tempDecimalString
                               ,"."
                            );
                        if (_parts.Count == 2)
                        {
                            _decimalStringBldr.AppendFormat
                            (
                                "{0}.{1}"
                                , initrode.utilities.StringManager.StripWhitespace
                                    (
                                        _parts[0].ToString()
                                    )
                                , initrode.utilities.StringManager.Fill
                                    (
                                        initrode.utilities.StringManager.StripWhitespace
                                        (
                                            _parts[1].ToString()
                                        )
                                        ,"0"  //string fillChars
                                        ,false //bool boolFromLeft
                                        , inputNumberOfDecimalPlaces //int maxLength
                                    )
                            );
                        }
                    }
                }
            }
            return _decimalStringBldr.ToString();
        }

Well, I’m noticing a trend, anyway, in that the developer really likes to break things across lines, so our “1800” line initial estimate is probably overblown. Of course, with the number of indented levels in here, combined with using fully qualified names on every line, you sort of have to.

I’m noticing a lot of calls to StripWhitespace. I wonder how that’s implemented…

		public static string StripWhitespace(string input)
		{
			string whitespaceCharacters = " \n\t\r";
			string tempString = input;
			StringBuilder bldr = new StringBuilder();
			for(int i=0; i < tempString.Length; i++)
			{
                if (i >= tempString.Length)
                    return bldr.ToString();
				string loopChar = tempString.Substring(i,1);
				if (whitespaceCharacters.IndexOf(loopChar) < 0)
				{
					bldr.Append(loopChar);
				}
			}
			return bldr.ToString();
		}

Sure, just iterate across every character. But hey, while I was CTRL+Fing for this, I saw StripWhitespaceFromEnds. I wonder what that does.

        public static string StripWhitespaceFromEnds(string input)  
        {
            string whitespaceCharacters = " \n\t\r";  
            string tempString = input;  
            if (initrode.utilities.StringManager.IsEmptyString(tempString) == true) return "";  
            tempString = input;
            
            for(int i=0; i < tempString.Length; i++)  
            {
                string loopChar = tempString.Substring(i,1);  
                if (whitespaceCharacters.IndexOf(loopChar) < 0)  
                {
                    tempString = tempString.Substring(i);  
                    break;  
                }
            }  
            for(int i=(tempString.Length - 1); i >= 0; i--)  
            {
                string loopChar = tempString.Substring(i,1);  
                if (whitespaceCharacters.IndexOf(loopChar) < 0)  
                {
                    tempString = tempString.Substring(0,i+1);  
                    break;  
                }
            }  
            return tempString;  
        }

Oh yeah, two for loops from either side. What else would I expect. Hey, what does IsEmptyString do? Is it just a wrapper around the built-in, IsNullOrEmpty? Of course not!

    public static bool IsEmptyString(string input)
  {
    if (input == null) return true;
    input = StripWhitespace(input);
    if (input.Length == 0) return true;
    return false;
  }

Oh, of course, we have to check if it contains whitespace before we remove the whitespace it contains. What was I thinking?

Y’know, at the very top of the class, I noticed:

  public const string CHARACTERS_IN_EMAIL_ADDRESS_PART = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";

They must use that when validating an email address.

  public static bool IsValidEMailAddress(string inputEMailAddress)
  {
    if (initrode.utilities.StringManager.IsEmptyString(inputEMailAddress) == true) return false;
    if (inputEMailAddress.IndexOf("@") < 0) return false;
    
    ArrayList _parts = initrode.utilities.StringManager.splitIntoArrayList(inputEMailAddress,"@");
    for (int _partCtr = 0; _partCtr < _parts.Count; _partCtr++)
    {
      string _part = _parts[_partCtr].ToString();
      if (initrode.utilities.StringManager.IsEmptyString(_part) == true) return false;
      if (_part.IndexOf(@".") >= 0)
      {
        ArrayList _periodDelimitedParts = initrode.utilities.StringManager.splitIntoArrayList(_part,@".");
        for (int _periodDelimitedPartCtr = 0; _periodDelimitedPartCtr < _periodDelimitedParts.Count; _periodDelimitedPartCtr++)
        {
          string _periodDelimitedPart = _periodDelimitedParts[_periodDelimitedPartCtr].ToString();
          if (initrode.utilities.StringManager.IsEmptyString(_periodDelimitedPart) == true) return false;
          if (initrode.utilities.StringManager.IsValidEMailAddressPart(_periodDelimitedPart) == false) return false;
        }
      }
      else
      {
        if (initrode.utilities.StringManager.IsValidEMailAddressPart(_part) == false) return false;
      }
    }
    return true;
  }

Oh, not here. What about in that IsValidEMailAddressPart?

  public static bool IsValidEMailAddressPart(string inputPart)
  {
    if (initrode.utilities.StringManager.IsEmptyString(inputPart) == true) return false;
    inputPart = initrode.utilities.StringManager.StripWhitespace(inputPart);
    for (int i = 0; i < inputPart.Length; i++)
    {
      string _character = inputPart.Substring(i,1);
      if (initrode.utilities.StringManager.CHARACTERS_IN_EMAIL_ADDRESS_PART.IndexOf(_character) < 0) return false;
    }
    return true;
  }

Ah, there it is. Hey, notice how it calls IsEmptyString and StripWhitespace, but also remember how IsEmptyString also calls StripWhitespace? Here’s a fun exercise for the readers: how many times do we access every character in the string?

I think nearly every method in this class could be an article in itself. And this is just a slice out of a large codebase where everything is done this way. There are NumberManager classes. DatabaseManager classes. Static methods everywhere.

If you need more proof, here is the entirety of the StringManager.cs class, all 1,800 lines of it:

using System;
using System.Collections;
using System.Text.RegularExpressions;
using System.Text;

namespace initrode.utilities
{
	/** Class:  StringManager
	 *	Contains static string handling routines. 
	 */
	public class StringManager
	{
		public const string CHARACTERS_IN_EMAIL_ADDRESS_PART = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";


		public static double ConvertCharacterPartsToDecimal(string inputWhole,
			string inputDecimal)
		{
			inputWhole = initrode.utilities.StringManager.Fill(inputWhole,
				"0",    /* Zero-fill */
				true,   /* From Left */
				8);
			inputDecimal = initrode.utilities.StringManager.Fill(inputDecimal,
				"0",    /* Zero-fill */
				false,   /* From Right */
				2);

			int _whole = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputWhole);
			double _decimal = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputDecimal);
			_decimal = _decimal/100;
			double _returnDecimal = (double) _whole + _decimal;
			return _returnDecimal;
		}
        public static void  ParseCommaDelimitedNameToLastNameAndFirstWordOfFirstName
                            (
                                string inputCommaDelimitedName
                                , bool inputAllCaps
                                , out string outputLastName
                                , out string outputFirstWordOfFirstName
                            )
        {
            inputCommaDelimitedName = inputCommaDelimitedName.Replace("'", string.Empty);

            outputLastName = "";
            outputFirstWordOfFirstName = "";

            if (inputCommaDelimitedName.IndexOf(",") < 1)
                return;
            ArrayList _nameParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputCommaDelimitedName
                    ,","
                );
            if (_nameParts.Count == 1) return;

            outputLastName =
                initrode.utilities.StringManager.StripWhitespaceFromEnds
                (
                    _nameParts[0].ToString()
                );
            string _firstAndMiddleName =
                initrode.utilities.StringManager.StripWhitespaceFromEnds
                (
                    _nameParts[1].ToString()
                );
            if (_firstAndMiddleName.IndexOf(" ") >= 0)
            {
                ArrayList _firstAndMiddleNameParts =
                    initrode.utilities.StringManager.splitIntoArrayList
                    (
                        _firstAndMiddleName
                        , " "
                    );
                outputFirstWordOfFirstName =
                    initrode.utilities.StringManager.StripWhitespaceFromEnds
                    (
                        _firstAndMiddleNameParts[0].ToString()
                    );
            }
            else
            {
                outputFirstWordOfFirstName =
                    initrode.utilities.StringManager.StripWhitespaceFromEnds
                    (
                        _firstAndMiddleName
                    );
            }
            if (inputAllCaps == true)
            {
                outputFirstWordOfFirstName = outputFirstWordOfFirstName.ToUpper();
                outputLastName = outputLastName.ToUpper();
            }
        }
		public static DateTime ConvertCharacterDateToDateTime(string inputMM,
			string inputDD,
			string inputYYYY)
		{
			inputMM = initrode.utilities.StringManager.Fill(inputMM,
				"0",    /* Zero-fill */
				true,   /* From Left */
				2);
			inputDD = initrode.utilities.StringManager.Fill(inputDD,
				"0",    /* Zero-fill */
				true,   /* From Left */
				2);

			int _MM = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputMM);
			int _DD = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputDD);
			int _YYYY = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputYYYY);
			return new DateTime(_YYYY,
				_DD,
				_MM);
		}
        public static string FormatDecimalAsString
                            (
                                decimal inputDecimal
                                , int inputNumberOfDecimalPlaces
                            )
        {
            StringBuilder _decimalStringBldr =
                new StringBuilder();
            string _tempDecimalString = inputDecimal.ToString();
            //No decimal point
            if (_tempDecimalString.IndexOf(".") < 0)
            {
                _decimalStringBldr.AppendFormat
                (
                    "{0}.{1}"
                    , _tempDecimalString
                    , initrode.utilities.StringManager.Fill
                        (
                            ""    //string input
                            , "0"  //string fillChars
                            , true //bool boolFromLet
                            , inputNumberOfDecimalPlaces    // int maxLength
                        )
                );
            }
            //"." exists
            else
            {
                //If "." at start of string.
                if (_tempDecimalString.IndexOf(".") == 0)
                {
                    _decimalStringBldr.AppendFormat
                    (
                        "0.{0}"
                        ,   initrode.utilities.StringManager.Fill
                            (
                                _tempDecimalString.Substring(1)    //string input
                                , "0"  //string fillChars
                                , false //bool boolFromLeft
                                , inputNumberOfDecimalPlaces    // int maxLength
                            )
                    );
                }
                // "." not at start.
                else
                {
                    //  "." at very end.
                    if (_tempDecimalString.IndexOf(".") == (_tempDecimalString.Length - 1))
                    {
                        _decimalStringBldr.AppendFormat
                        (
                            "{0}.{1}"
                            , _tempDecimalString.Substring(0, (_tempDecimalString.Length - 1))
                            , initrode.utilities.StringManager.Fill
                                (
                                    _tempDecimalString.Substring(1)    //string input
                                    , "0"  //string fillChars
                                    , false //bool boolFromLeft
                                    , inputNumberOfDecimalPlaces    // int maxLength
                                )
                        );
                    }
                    // "." in middle.
                    else
                    {
                        ArrayList _parts =
                            initrode.utilities.StringManager.splitIntoArrayList
                            (
                               _tempDecimalString
                               ,"."
                            );
                        if (_parts.Count == 2)
                        {
                            _decimalStringBldr.AppendFormat
                            (
                                "{0}.{1}"
                                , initrode.utilities.StringManager.StripWhitespace
                                    (
                                        _parts[0].ToString()
                                    )
                                , initrode.utilities.StringManager.Fill
                                    (
                                        initrode.utilities.StringManager.StripWhitespace
                                        (
                                            _parts[1].ToString()
                                        )
                                        ,"0"  //string fillChars
                                        ,false //bool boolFromLeft
                                        , inputNumberOfDecimalPlaces //int maxLength
                                    )
                            );
                        }
                    }
                }
            }
            return _decimalStringBldr.ToString();
        }
		public static DateTime ConvertTimestampStringToDateTime(string inputTimestampInStringFormat)
		{
			ArrayList _parts = initrode.utilities.StringManager.splitIntoArrayList(inputTimestampInStringFormat," ");
			if (_parts.Count != 2) return new DateTime(1900,1,1);
			string _date = initrode.utilities.StringManager.StripWhitespace(_parts[0].ToString());
			string _timeAndMilliseconds = initrode.utilities.StringManager.StripWhitespace(_parts[1].ToString());

            bool _boolValidDateInMM_DD_YYYY = false;
            bool _boolValidDateInYYYY_MM_DD = false;
            _boolValidDateInMM_DD_YYYY = 
                initrode.utilities.StringManager.IsValidDateInMM_DD_YYYYFormat(_date);
            _boolValidDateInYYYY_MM_DD =
                initrode.utilities.StringManager.IsValidDateInYYYYDashMMDashDDFormat(_date);

			if (
                    _boolValidDateInMM_DD_YYYY == false
                    &&
                    _boolValidDateInYYYY_MM_DD == false
                )
				return new DateTime(1900,1,1);
			string _dateYYYY = "";
			string _dateMM = "";
			string _dateDD = "";
			
			ArrayList _dateParts;
            if (_boolValidDateInMM_DD_YYYY == true)
            {
                _dateParts
                    = initrode.utilities.StringManager.splitIntoArrayList
                        (
                            _date
                            , "/"
                        );
                if (_dateParts.Count != 3) return new DateTime(1900, 1, 1);
                _dateYYYY = initrode.utilities.StringManager.StripWhitespace(_dateParts[2].ToString());
                _dateMM = initrode.utilities.StringManager.StripWhitespace(_dateParts[0].ToString());
                _dateDD = initrode.utilities.StringManager.StripWhitespace(_dateParts[1].ToString());

            }
            if (_boolValidDateInYYYY_MM_DD == true)
            {
                _dateParts
                    = initrode.utilities.StringManager.splitIntoArrayList
                        (
                            _date
                            , "-"
                        );
                if (_dateParts.Count != 3) return new DateTime(1900, 1, 1);
                _dateYYYY = initrode.utilities.StringManager.StripWhitespace(_dateParts[0].ToString());
                _dateMM = initrode.utilities.StringManager.StripWhitespace(_dateParts[1].ToString());
                _dateDD = initrode.utilities.StringManager.StripWhitespace(_dateParts[2].ToString());
            }
			ArrayList _timeAndMillisecondParts =	initrode.utilities.StringManager.splitIntoArrayList
													(
														_timeAndMilliseconds
														,"."
													);
			if (_timeAndMillisecondParts.Count != 2) return new DateTime(1900,1,1);
			string _timeMilliseconds = initrode.utilities.StringManager.StripWhitespace(_timeAndMillisecondParts[1].ToString());
			if (initrode.utilities.StringManager.IsValidNumber(_timeMilliseconds) == false) return new DateTime(1900,1,1);
			if (Convert.ToInt32(_timeMilliseconds) > 999) return new DateTime(1900,1,1);
			
			string _time = initrode.utilities.StringManager.StripWhitespace(_timeAndMillisecondParts[0].ToString());
			ArrayList _timeParts =	initrode.utilities.StringManager.splitIntoArrayList
													(
														_time
														,":"
													);
			if (_timeParts.Count != 3) return new DateTime(1900,1,1);
			string _timeHours = initrode.utilities.StringManager.StripWhitespace(_timeParts[0].ToString());
			string _timeMinutes = initrode.utilities.StringManager.StripWhitespace(_timeParts[1].ToString());
			string _timeSeconds = initrode.utilities.StringManager.StripWhitespace(_timeParts[2].ToString());
			StringBuilder _timeBldr = new StringBuilder();
			_timeBldr.Append(	initrode.utilities.StringManager.Fill
								(
									_timeHours
									,"0"
									,true        // from left
									,2
								)
							);
			_timeBldr.Append(":");
			_timeBldr.Append(	initrode.utilities.StringManager.Fill
								(
									_timeMinutes
									,"0"
									,true        // from left
									,2
								)
							);
			_timeBldr.Append(":");
			_timeBldr.Append(	initrode.utilities.StringManager.Fill
								(
									_timeSeconds
									,"0"
									,true        // from left
									,2
								)
							);
			if (initrode.utilities.StringManager.IsValidTimeInHHColonMIColonSSFormat(_timeBldr.ToString()) == false) 
				return new DateTime(1900,1,1);

			return new	DateTime	
						(
							Convert.ToInt32(_dateYYYY)
							,Convert.ToInt32(_dateMM)
							,Convert.ToInt32(_dateDD)
							,Convert.ToInt32(_timeHours)
							,Convert.ToInt32(_timeMinutes)
							,Convert.ToInt32(_timeSeconds)
							,Convert.ToInt32(_timeMilliseconds)
						);
		}
        public static bool stringHas3DecimalsWithThousandsCommasInRow
                            (
                                string inputString
                                , out decimal outputDecimal1
                                , out decimal outputDecimal2
                                , out decimal outputDecimal3
                            )
        {
            outputDecimal1 = (decimal) 0;
            outputDecimal2 = (decimal) 0;
            outputDecimal3 = (decimal) 0;
            ArrayList _oldParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputString
                    , @" "
                );
            ArrayList _parts;
            initrode.utilities.StringManager.eliminateEmptyStringsFromArrayListOfString
            (
                _oldParts
                ,out _parts
            );
            for (int _partCtr = 0;
                    _partCtr < (_parts.Count - 2);
                    _partCtr++)
            {
                if (
                        initrode.utilities.StringManager.IsValidDecimal
                        (
                            initrode.utilities.StringManager.StripWhitespace
                            (
                                _parts[_partCtr].ToString()
                            ).Replace(",", "")
                        ) == true
                        && initrode.utilities.StringManager.IsValidDecimal
                            (
                                initrode.utilities.StringManager.StripWhitespace
                                (
                                    _parts[(_partCtr + 1)].ToString()
                                ).Replace(",","")
                                    
                            ) == true
                        && initrode.utilities.StringManager.IsValidDecimal
                            (
                                initrode.utilities.StringManager.StripWhitespace
                                (
                                    _parts[(_partCtr + 2)].ToString()
                                ).Replace(",","")
                            ) == true
                   )
                {
                    outputDecimal1 = 
                        Convert.ToDecimal
                        (
                            initrode.utilities.StringManager.StripWhitespace
                            (
                                _parts[_partCtr].ToString()
                            ).Replace(",","")
                        );
                    outputDecimal2 =
                        Convert.ToDecimal
                        (
                            initrode.utilities.StringManager.StripWhitespace
                            (
                                _parts[(_partCtr + 1)].ToString()
                            ).Replace(",", "")
                        );
                    outputDecimal3 =
                        Convert.ToDecimal
                        (
                            initrode.utilities.StringManager.StripWhitespace
                            (
                                _parts[(_partCtr + 2)].ToString()
                            ).Replace(",", "")
                        );
                    return true;
                }
            }
            return false;
        }

        public static bool stringHas3CommaDelimitedNumbersInRow
                            (
                                string inputCommaDelimitedString
                                , out string outputNumericString1
                                , out string outputNumericString2
                                , out string outputNumericString3
                            )
        {
            outputNumericString1 = "";
            outputNumericString2 = "";
            outputNumericString3 = "";
            ArrayList _parts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputCommaDelimitedString
                    , ","
                );
            for (int _partCtr = 0;
                    _partCtr < (_parts.Count - 2);
                    _partCtr++)
            {
                if (
                        initrode.utilities.StringManager.IsValidNumber
                        (
                            _parts[_partCtr].ToString()
                        ) == true
                        && initrode.utilities.StringManager.IsValidNumber
                            (
                                _parts[(_partCtr + 1)].ToString()
                            ) == true
                        && initrode.utilities.StringManager.IsValidNumber
                            (
                                _parts[(_partCtr + 2)].ToString()
                            ) == true
                   )
                {
                    outputNumericString1 = _parts[_partCtr].ToString();
                    outputNumericString2 = _parts[(_partCtr + 1)].ToString();
                    outputNumericString3 = _parts[(_partCtr + 2)].ToString();
                    return true;
                }
            }
            return false;
        }
        public static string getBasePathGivenPhysicalPath
                                (
                                    string inputPhysicalPath
                                )
        {
            inputPhysicalPath = inputPhysicalPath.ToUpper();
            string _endOfPath =
                initrode.utilities.StringManager.CaptureFirstOccurrenceOfParenthesesedPattern
                (	    
                    @"^C:\\INETPUB\\WWWROOT\\(.+)$"
                    ,inputPhysicalPath
                );
            ArrayList _pathParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    _endOfPath
                    , @"\\"
                );


            if (_pathParts.Count > 0)
            {
                StringBuilder _basePathBldr = new StringBuilder();
                _basePathBldr.Append("/");
                _basePathBldr.Append(_pathParts[0].ToString());
                return _basePathBldr.ToString();
            }
            return _endOfPath;
        }
        public static bool IsValidEMailAddressPart(string inputPart)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputPart) == true) return false;
			inputPart = initrode.utilities.StringManager.StripWhitespace(inputPart);
			for (int i = 0; i < inputPart.Length; i++)
			{
				string _character = inputPart.Substring(i,1);
				if (initrode.utilities.StringManager.CHARACTERS_IN_EMAIL_ADDRESS_PART.IndexOf(_character) < 0) return false;
			}
			return true;
		}
		public static bool IsValidEMailAddressList(string inputEMailAddressList)
		{
			if (inputEMailAddressList.IndexOf(";") >= 0) 
			{
				ArrayList _emailAddresses = initrode.utilities.StringManager.splitIntoArrayList(inputEMailAddressList,";");
				for (int _emailAddressCtr = 0; _emailAddressCtr < _emailAddresses.Count; _emailAddressCtr++)
				{
					string _emailAddress = _emailAddresses[_emailAddressCtr].ToString();
					if (initrode.utilities.StringManager.IsValidEMailAddress(_emailAddress) == false) return false;
				}
			}
			else
			{
				if (inputEMailAddressList.IndexOf(",") >= 0) 
				{
					ArrayList _emailAddresses = initrode.utilities.StringManager.splitIntoArrayList(inputEMailAddressList,";");
					for (int _emailAddressCtr = 0; _emailAddressCtr < _emailAddresses.Count; _emailAddressCtr++)
					{
						string _emailAddress = _emailAddresses[_emailAddressCtr].ToString();
						if (initrode.utilities.StringManager.IsValidEMailAddress(_emailAddress) == false) return false;
					}
				}
				else
				{
					if (initrode.utilities.StringManager.IsValidEMailAddress(inputEMailAddressList) == false) return false;
				}
			}
        
			return true;
		}

		public static bool IsEmptyString(string input)
		{
			if (input == null) return true;
			input = StripWhitespace(input);
			if (input.Length == 0) return true;
			return false;
		}
		public static string convertDateTimeInSQLFormatIntoMM_DD_YYYYFormat(string inputDateInSQLFormat)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputDateInSQLFormat) == true)
				return "";
			inputDateInSQLFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputDateInSQLFormat);
			ArrayList _dateAndTimeParts = initrode.utilities.StringManager.splitIntoArrayList(inputDateInSQLFormat," ");
			if (_dateAndTimeParts.Count != 3) return "";
			string _datePart = initrode.utilities.StringManager.StripWhitespaceFromEnds(_dateAndTimeParts[0].ToString());
            ArrayList _dateParts =
                initrode.utilities.StringManager.splitIntoArrayList(_datePart, "/");
            if (_dateParts.Count != 3) return "";

            StringBuilder _dateBldr =
                new StringBuilder();
            _dateBldr.AppendFormat
            (
                "{0}/{1}/{2}"
                ,   initrode.utilities.StringManager.Fill
                    (
                        initrode.utilities.StringManager.StripWhitespaceFromEnds
                        (
                            _dateParts[0].ToString()
                        )
                        , "0"
                        , true //from left
                        , 2
                    )
                ,   initrode.utilities.StringManager.Fill
                    (
                        initrode.utilities.StringManager.StripWhitespaceFromEnds
                        (
                            _dateParts[1].ToString()
                        )
                        , "0"
                        , true //from left
                        , 2
                    )
                ,   initrode.utilities.StringManager.StripWhitespaceFromEnds
                    (
                        _dateParts[2].ToString()
                    )
            );

            return _dateBldr.ToString();
		}
        public static string   ConvertDateInBESFormatToDB2Format
                                (
                                   string inputDateInBESFormat
                                )
        {
            ArrayList _dateParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputDateInBESFormat
                    , " "
                );
            string _month_string = 
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[0].ToString()
                ).ToUpper();
            int _month_int = 0;
            switch (_month_string)
            {
                case "JAN":
                    _month_int = 1;
                    break;
                case "FEB":
                    _month_int = 2;
                    break;
                case "MAR":
                    _month_int = 3;
                    break;
                case "APR":
                    _month_int = 4;
                    break;
                case "MAY":
                    _month_int = 5;
                    break;
                case "JUN":
                    _month_int = 6;
                    break;
                case "JUL":
                    _month_int = 7;
                    break;
                case "AUG":
                    _month_int = 8;
                    break;
                case "SEP":
                    _month_int = 9;
                    break;
                case "OCT":
                    _month_int = 10;
                    break;
                case "NOV":
                    _month_int = 11;
                    break;
                case "DEC":
                    _month_int = 12;
                    break;
            }
            string _day_string =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[1].ToString()
                ).Replace(",", "");
            int _day_int =
                Convert.ToInt32
                (
                    _day_string
                );
            string _year_string =
               initrode.utilities.StringManager.StripWhitespace
               (
                   _dateParts[2].ToString()
               );
            int _year_int =
                Convert.ToInt32
                (
                    _year_string
                );

            string _time_string =
               initrode.utilities.StringManager.StripWhitespace
               (
                   _dateParts[3].ToString()
               );

            ArrayList _timeParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    _time_string
                    , ":"
                );
            string _hours_string =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _timeParts[0].ToString()
                );
            int _hours_int =
                Convert.ToInt32
                (
                    _hours_string
                );
            string _minutes_string =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _timeParts[1].ToString()
                );
            int _minutes_int =
                Convert.ToInt32
                (
                    _minutes_string
                );
            string _seconds_string =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _timeParts[2].ToString()
                );
            int _seconds_int =
                Convert.ToInt32
                (
                    _seconds_string
                );
            string _am_or_pm_string =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[4].ToString()
                );
            if (_am_or_pm_string.CompareTo("PM") == 0)
                _hours_int += 12;
            string _microSeconds_string =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[5].ToString()
                );
            int _microSeconds_int =
                Convert.ToInt32
                (
                    _microSeconds_string
                );
            StringBuilder _outputDB2DateStringBuilder =
                new StringBuilder();
            _outputDB2DateStringBuilder.AppendFormat
            (
                "{0}-{1}-{2}-{3}.{4}.{5}.{6}"
                , _year_int.ToString()
                , initrode.utilities.StringManager.Fill
                    (
                        _month_int.ToString()
                        , "0"
                        , true //fromLeft
                        , 2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        _day_int.ToString()
                        , "0"
                        , true //fromLeft
                        , 2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        _hours_int.ToString()
                        , "0"
                        , true //fromLeft
                        , 2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        _minutes_int.ToString()
                        , "0"
                        , true //fromLeft
                        , 2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        _seconds_int.ToString()
                        , "0"
                        , true //fromLeft
                        , 2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        _microSeconds_int.ToString()
                        , "0"
                        , true //fromLeft
                        , 6
                    )
            );
            return _outputDB2DateStringBuilder.ToString();
        }
		public static bool HasCharactersMatchingRegexString(string inputRegexString, 
															string input)
		{
			input = initrode.utilities.StringManager.StripWhitespaceFromEnds(input);
			Regex pattern = new Regex(inputRegexString);
            bool _patternMatches = false;
            _patternMatches = pattern.IsMatch(input);

            return _patternMatches;
		}

		public static bool IsValidAlphanumeric(string input)
		{
			if (initrode.utilities.StringManager.IsEmptyString(input) == true) return false;
			return initrode.utilities.StringManager.HasCharactersMatchingRegexString("[^a-zA-Z0-9$]", 
																			input);
		}

        public static bool IsValidAlphanumericPlusBlanks(string input)
        {
            if (initrode.utilities.StringManager.IsEmptyString(input) == true) return false;
            return initrode.utilities.StringManager.HasCharactersMatchingRegexString("^[a-zA-Z0-9 ]+$",
                                                                            input);
        }

		public static bool IsValidName(string input)
		{
			if (initrode.utilities.StringManager.IsEmptyString(input) == true) return false;
			return initrode.utilities.StringManager.HasCharactersMatchingRegexString("^[a-zA-Z ]+$", 
																					input);
		}
		public static bool IsValidDecimal(string input)
		{
            input =
                initrode.utilities.StringManager.StripWhitespace
                (
                    input
                );
			if (initrode.utilities.StringManager.IsEmptyString(input) == true) return false;
            if (input.IndexOf("-") == 0
                || input.IndexOf("-") == (input.Length - 1))
            {
                input = input.Replace("-", "");
            }
			return initrode.utilities.StringManager.HasCharactersMatchingRegexString(@"^\d*\.?\d+$", 
																				 input);
		}

		public static bool IsValidNumber(string input)
		{
			if (initrode.utilities.StringManager.IsEmptyString(input) == true) return false;
            input = initrode.utilities.StringManager.StripWhitespace
                    (
                        input
                    );
            if (input.Substring(0, 1).CompareTo("-") == 0)
            {
                input = input.Substring(1);
            }
			return initrode.utilities.StringManager.HasCharactersMatchingRegexString(@"^\d+$", 
																				 input);
		}
		public static string ConvertDateInYYYYMMDDToMMSlashDDSlashYYYY(string inputDateInYYYYMMDDFormat)
		{
			string _strDate =  initrode.utilities.StringManager.StripWhitespace(inputDateInYYYYMMDDFormat);
			if (_strDate.Length != 8) return "";

			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputDateInYYYYMMDDFormat.Substring(4,2));
			_bldr.Append("/");
			_bldr.Append(inputDateInYYYYMMDDFormat.Substring(6,2));
			_bldr.Append("/");
			_bldr.Append(inputDateInYYYYMMDDFormat.Substring(0,4));
			return _bldr.ToString();
		}
		public static string	splicePathAndFileNameInfo
								(	
									string inputPath,
									string inputFileName
								)
		{
			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputPath);
			_bldr.Append("\\");
			_bldr.Append(inputFileName);
			return _bldr.ToString();
		}
														
		public static void ConvertLastNameCommaFirstNameToLastNameAndFirstName(
								string inputName,
								out string outputLastName,
								out string outputFirstName)
		{
			outputLastName = "";
			outputFirstName = "";
			ArrayList _parts = initrode.utilities.StringManager.splitIntoArrayList(
										inputName,
										",");
			if (_parts.Count != 2) return;
			outputLastName = initrode.utilities.StringManager.StripWhitespaceFromEnds(_parts[0].ToString());
			outputFirstName = initrode.utilities.StringManager.StripWhitespaceFromEnds(_parts[1].ToString());
		}
		public static void ConvertDashedCodeAndLastNameCommaFirstNameIntoCodeLastNameAndFirstName(
								string inputCodeLastNameFirstName,
								out string outputCode,
								out string outputLastName,
								out string outputFirstName)
		{
			outputCode = "";
			outputLastName = "";
			outputFirstName = "";

			if (inputCodeLastNameFirstName.IndexOf("-") < 0 
				|| inputCodeLastNameFirstName.IndexOf(",") < 0) return;
			string _lastNameCommaFirstName = "";
			initrode.utilities.StringManager.ConvertDashedCodeAndDescriptionToCodeAndDescription(
								inputCodeLastNameFirstName,
								out outputCode,
								out _lastNameCommaFirstName);
			ConvertLastNameCommaFirstNameToLastNameAndFirstName(
								 _lastNameCommaFirstName,
								out outputLastName,
								out outputFirstName);

		}
		public static void ConvertDashedCodeAndDescriptionToCodeAndDescription(
								string inputCodeAndDescription,
								out string outputCode,
								out string outputDescription)
		{
			outputCode = "";
			outputDescription = "";

			if (inputCodeAndDescription == null 
				|| initrode.utilities.StringManager.StripWhitespaceFromEnds(inputCodeAndDescription).Length < 3) return;	
			inputCodeAndDescription = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputCodeAndDescription);

			outputCode = initrode.utilities.StringManager.StripWhitespaceFromEnds(
							initrode.utilities.StringManager.CaptureFirstOccurrenceOfParenthesesedPattern(	
									@"^(.*)-.*$",
									inputCodeAndDescription));

			outputDescription = initrode.utilities.StringManager.StripWhitespaceFromEnds(
									initrode.utilities.StringManager.CaptureFirstOccurrenceOfParenthesesedPattern(	
										@"^.*-(.*)$",
										inputCodeAndDescription));
		}

		public static void ConvertPhoneNumberInParenthesesedAreaCodeAndDashedPrefixAndSuffixIntoParts(
								string inputPhoneNumber,
								out string outputAreaCode,
								out string outputPrefix,
								out string outputSuffix)
		{
			outputAreaCode = "";
			outputPrefix = "";
			outputSuffix = "";

			if (inputPhoneNumber == null 
				|| initrode.utilities.StringManager.StripWhitespaceFromEnds(inputPhoneNumber).Length < 13) return;	

			outputAreaCode = initrode.utilities.StringManager.StripWhitespaceFromEnds(
								initrode.utilities.StringManager.CaptureFirstOccurrenceOfParenthesesedPattern(	
									@"^.*\(([0-9][0-9][0-9])\).+$",
									inputPhoneNumber));

			outputPrefix = initrode.utilities.StringManager.StripWhitespaceFromEnds(
								initrode.utilities.StringManager.CaptureFirstOccurrenceOfParenthesesedPattern(	
									@"^.*([0-9][0-9][0-9])\w*-.*$",
									inputPhoneNumber));

			outputSuffix = initrode.utilities.StringManager.StripWhitespaceFromEnds(
							initrode.utilities.StringManager.CaptureFirstOccurrenceOfParenthesesedPattern(	
									@"^.*-([0-9][0-9][0-9][0-9]).*$",
									inputPhoneNumber));

		}

		public static double ConvertStringWithNoPeriodIntoDoubleWithTwoDecimalPlaces(string inputNumber)
		{
			inputNumber =  initrode.utilities.StringManager.StripWhitespace(inputNumber);
			if (initrode.utilities.StringManager.IsValidNumber(inputNumber) == false) return 0;

			return (Convert.ToDouble(inputNumber)/100);
		}

		public static string ConvertDateInMMSlashDDSlashYYYYToYYYYMMDD(string inputDateInMMSlashDDSlashYYYYFormat)
		{
			string _strDate =  initrode.utilities.StringManager.StripWhitespace(inputDateInMMSlashDDSlashYYYYFormat);
			if (_strDate.Length != 10 
				|| _strDate.IndexOf("/") == -1) return "";

			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputDateInMMSlashDDSlashYYYYFormat.Substring(6,4));
			_bldr.Append(inputDateInMMSlashDDSlashYYYYFormat.Substring(0,2));
			_bldr.Append(inputDateInMMSlashDDSlashYYYYFormat.Substring(3,2));
			return _bldr.ToString();
		}

		public static string ConvertDateInMMSlashDDSlashYYYYToYYYYDashMMDashDD(string inputDateInMMSlashDDSlashYYYYFormat)
		{
			string _strDate =  initrode.utilities.StringManager.StripWhitespace(inputDateInMMSlashDDSlashYYYYFormat);
			if (_strDate.Length != 10 
				|| _strDate.IndexOf("/") == -1) return "";

			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputDateInMMSlashDDSlashYYYYFormat.Substring(6,4));
			_bldr.Append("-");
			_bldr.Append(inputDateInMMSlashDDSlashYYYYFormat.Substring(0,2));
			_bldr.Append("-");
			_bldr.Append(inputDateInMMSlashDDSlashYYYYFormat.Substring(3,2));
			return _bldr.ToString();
		}

		public static void GetDateTimeIfValidDateInYYYYMMDDFormat(string inputDateInYYYYMMDDFormat,
																	out bool outputValid,
																	out DateTime outputDateTime)
		{
			outputValid = false;
			outputDateTime = new DateTime();
			string _strippedInputDate = initrode.utilities.StringManager.StripWhitespace(inputDateInYYYYMMDDFormat);
			if (_strippedInputDate.Length != 8) return;

			string _mm = _strippedInputDate.Substring(4,2);
			string _dd = _strippedInputDate.Substring(6,2);
			string _yyyy = _strippedInputDate.Substring(0,4);
			if (initrode.utilities.StringManager.IsValidDate(	_mm,
															_dd,
															_yyyy) == false) return;

			// We have a valid date - convert it to DateTime
			outputValid = true;
			outputDateTime = new DateTime(	Convert.ToInt16(_yyyy),
											Convert.ToInt16(_mm),
											Convert.ToInt16(_dd));	
	
		}
		public static bool IsValidDateInYYYYMMDDFormat(string inputDateInYYYYMMDDFormat)
		{
			inputDateInYYYYMMDDFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputDateInYYYYMMDDFormat);
			if (inputDateInYYYYMMDDFormat.Length != 8) return false;
			
			string _strYYYY = inputDateInYYYYMMDDFormat.Substring(0,4);
			string _strMM = inputDateInYYYYMMDDFormat.Substring(4,2);
			string _strDD = inputDateInYYYYMMDDFormat.Substring(6,2);

			if (initrode.utilities.StringManager.IsValidDate(	_strMM,
															_strDD,
															_strYYYY) == false) return false;
			return true;
			
		}
		public static bool	IsValidTimeInHHColonMIColonSSFormat
							(
								string inputTimeInHHColonMIColonSSFormat
							)
		{
			inputTimeInHHColonMIColonSSFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputTimeInHHColonMIColonSSFormat);
			if (inputTimeInHHColonMIColonSSFormat.Length != 8) return false;

			string _strHH =	inputTimeInHHColonMIColonSSFormat.Substring(0,2); 
			string _strMI =	inputTimeInHHColonMIColonSSFormat.Substring(3,2); 
			string _strSS =	inputTimeInHHColonMIColonSSFormat.Substring(6,2); 
			if (initrode.utilities.StringManager.IsValidNumber(_strHH) == false ||
				initrode.utilities.StringManager.IsValidNumber(_strMI) == false ||
				initrode.utilities.StringManager.IsValidNumber(_strSS) == false) return false;
			
			int _intHH = Convert.ToInt32(_strHH);
			int _intMI = Convert.ToInt32(_strMI);
			int _intSS = Convert.ToInt32(_strSS);
		
			if (_intHH < 0 || _intHH > 23) return false;
			if (_intMI < 0 || _intMI > 59) return false;
			if (_intSS < 0 || _intSS > 59) return false;

			return true;
		}

		public static string getCurrentDateInMMSlashDDSlashYYYYFormat()
		{
			DateTime _currentDate = DateTime.Now;
			StringBuilder _currentDateBldr = new StringBuilder();
			_currentDateBldr.Append(initrode.utilities.StringManager.Fill(
											_currentDate.Month.ToString(),
											"0",
											true,
											2));
			_currentDateBldr.Append("/");
			_currentDateBldr.Append(initrode.utilities.StringManager.Fill(
											_currentDate.Day.ToString(),
											"0",
											true,
											2));
			_currentDateBldr.Append("/");
			_currentDateBldr.Append(_currentDate.Year.ToString());
			return _currentDateBldr.ToString();
		}

		public static string getCurrentDateInYYYYMMDDFormat()
		{
			DateTime _currentDate = DateTime.Now;
			StringBuilder _currentDateBldr = new StringBuilder();
			_currentDateBldr.Append(_currentDate.Year.ToString());
			_currentDateBldr.Append(initrode.utilities.StringManager.Fill(
											_currentDate.Month.ToString(),
											"0",
											true,
											2));
			_currentDateBldr.Append(initrode.utilities.StringManager.Fill(
											_currentDate.Day.ToString(),
											"0",
											true,
											2));
			return _currentDateBldr.ToString();
		}

		public static bool IsValidTimestamp(string inputTimestamp)
		{
			if (	initrode.utilities.StringManager.IsEmptyString(inputTimestamp) == true) return false;
			if (	initrode.utilities.DateManager.date1ComparedToDate2
					(
						initrode.utilities.StringManager.ConvertTimestampStringToDateTime(inputTimestamp)
						,new DateTime(1900,1,1)
					) == 0) return false;
			return true;
		}
		public static void ValidateAndConvertDateInMM_DD_YYYYFormatWithPossibleOneDigitMonthOrDayToMM_DD_YYYYFormat(
								string inputDateInMM_DD_YYYYFormat,
								out bool outputIsValid,
								out string outputDateInMM_DD_YYYYFormat)
		{
			outputDateInMM_DD_YYYYFormat = "01/01/1900";
			outputIsValid = false;
			if (initrode.utilities.StringManager.IsEmptyString(inputDateInMM_DD_YYYYFormat) == true) return;
			ArrayList _parts = initrode.utilities.StringManager.splitIntoArrayList(
										inputDateInMM_DD_YYYYFormat,
										"/");
			if (_parts.Count != 3) return;
			string strMM = initrode.utilities.StringManager.Fill(
							initrode.utilities.StringManager.StripWhitespaceFromEnds(_parts[0].ToString()),
							"0",
							true,
							2);
			string strDD = initrode.utilities.StringManager.Fill(
							initrode.utilities.StringManager.StripWhitespaceFromEnds(_parts[1].ToString()),
							"0",
							true,
							2);
			string strYYYY = initrode.utilities.StringManager.StripWhitespaceFromEnds(_parts[2].ToString());
			if (initrode.utilities.StringManager.IsValidDate(
											strMM,
											strDD,
											strYYYY) == false) return;

			outputIsValid = true;

			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(strMM);
			_bldr.Append("/");
			_bldr.Append(strDD);
			_bldr.Append("/");
			_bldr.Append(strYYYY);

			outputDateInMM_DD_YYYYFormat = _bldr.ToString();
		}

		public static bool IsValidEMailAddress(string inputEMailAddress)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputEMailAddress) == true) return false;
			if (inputEMailAddress.IndexOf("@") < 0) return false;
			
			ArrayList _parts = initrode.utilities.StringManager.splitIntoArrayList(inputEMailAddress,"@");
			for (int _partCtr = 0; _partCtr < _parts.Count; _partCtr++)
			{
				string _part = _parts[_partCtr].ToString();
				if (initrode.utilities.StringManager.IsEmptyString(_part) == true) return false;
				if (_part.IndexOf(@".") >= 0)
				{
					ArrayList _periodDelimitedParts = initrode.utilities.StringManager.splitIntoArrayList(_part,@".");
					for (int _periodDelimitedPartCtr = 0; _periodDelimitedPartCtr < _periodDelimitedParts.Count; _periodDelimitedPartCtr++)
					{
						string _periodDelimitedPart = _periodDelimitedParts[_periodDelimitedPartCtr].ToString();
						if (initrode.utilities.StringManager.IsEmptyString(_periodDelimitedPart) == true) return false;
						if (initrode.utilities.StringManager.IsValidEMailAddressPart(_periodDelimitedPart) == false) return false;
					}
				}
				else
				{
					if (initrode.utilities.StringManager.IsValidEMailAddressPart(_part) == false) return false;
				}
			}
			return true;
		}

		public static bool IsValidDateInMM_DD_YYYYFormat(string inputDateInMM_DD_YYYYFormat)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputDateInMM_DD_YYYYFormat) == true) return false;

			if (initrode.utilities.StringManager.StripWhitespace(inputDateInMM_DD_YYYYFormat).Length != 10) return false;
			return initrode.utilities.StringManager.IsValidDate(inputDateInMM_DD_YYYYFormat.Substring(0,2),
															inputDateInMM_DD_YYYYFormat.Substring(3,2),
															inputDateInMM_DD_YYYYFormat.Substring(6,4));
			

		}
		public static bool IsValidDateInYYYYDashMMDashDDFormat(string inputDateInYYYYDashMMDashDDFormat)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputDateInYYYYDashMMDashDDFormat) == true) return false;
			inputDateInYYYYDashMMDashDDFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputDateInYYYYDashMMDashDDFormat);
			if (inputDateInYYYYDashMMDashDDFormat.Length != 10) return false;

			string _strTestDateYYYY = inputDateInYYYYDashMMDashDDFormat.Substring(0,4);
			string _strTestDateMM = inputDateInYYYYDashMMDashDDFormat.Substring(5,2);
			string _strTestDateDD = inputDateInYYYYDashMMDashDDFormat.Substring(8,2);
			if (initrode.utilities.StringManager.IsValidDate(
						_strTestDateMM,
						_strTestDateDD,
						_strTestDateYYYY) == true) return true;
			return false;
		}
		public static DateTime convertDateInYYYYDashMMDashDDToDateTime(string inputDateInYYYYDashMMDashDDFormat)
		{
			inputDateInYYYYDashMMDashDDFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputDateInYYYYDashMMDashDDFormat);
			if (initrode.utilities.StringManager.IsValidDateInYYYYDashMMDashDDFormat(inputDateInYYYYDashMMDashDDFormat) == true)
			{
				string _strTestDateYYYY = inputDateInYYYYDashMMDashDDFormat.Substring(0,4);
				string _strTestDateMM = inputDateInYYYYDashMMDashDDFormat.Substring(5,2);
				string _strTestDateDD = inputDateInYYYYDashMMDashDDFormat.Substring(8,2);
				int _intTestDateYYYY = Convert.ToInt32(_strTestDateYYYY);
				int _intTestDateMM = Convert.ToInt32(_strTestDateMM);
				int _intTestDateDD = Convert.ToInt32(_strTestDateDD);
				return new DateTime(_intTestDateYYYY,_intTestDateMM,_intTestDateDD);
			}
			return new DateTime(DateTime.Now.Year,
								DateTime.Now.Month,
								DateTime.Now.Day);
		}
		public static bool IsValidDate(string inputMM,
			string inputDD,
			string inputYYYY)
		{
			if (initrode.utilities.StringManager.IsValidNumber(inputMM) == false ||
				initrode.utilities.StringManager.IsValidNumber(inputDD) == false ||
				initrode.utilities.StringManager.IsValidNumber(inputYYYY) == false) return false;

			int _MM = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputMM);
			int _DD = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputDD);
			int _YYYY = initrode.utilities.StringManager.ConvertCharacterStringToInt(inputYYYY);

			if (_MM < 1 || _MM > 12) return false;

			if (_MM == 1 || 
				_MM == 3 || 
				_MM == 5 || 
				_MM == 7 || 
				_MM == 8 || 
				_MM == 10 || 
				_MM == 12)
			{
				if (_DD < 1 || _DD > 31) return false;
			}
				
			if (_MM == 4 || 
				_MM == 6 || 
				_MM == 9 ||
				_MM == 11)
			{
				if (_DD < 1 || _DD > 30) return false;
			}

			if (_MM == 2)
			{
				bool doesFebruaryHave29Days = false;
				if (_YYYY % 4 == 0)
				{
					if (_YYYY % 100 == 0)
					{
						if (_YYYY % 400 == 0)
						{
							doesFebruaryHave29Days = true;
						}
					}
					else
					{
						doesFebruaryHave29Days = true;
					}
				}
				if (doesFebruaryHave29Days == true)
				{
					if (_DD < 1 || _DD > 29) return false;
				}
				else
				{
					if (_DD < 1 || _DD > 28) return false;
				}
			}
			return true;
		}
		public static ArrayList splitIntoArrayListAfterRemovingCharacterSequence(
											string inputString,
                                            string inputSplitAt,
											string inputCharacterSequenceToBeRemoved)
		{
			inputString = inputString.Replace(inputCharacterSequenceToBeRemoved,"");
			return splitIntoArrayList(inputString,
                                      inputSplitAt);
		}
		public static string	getCurrentDateStringInYYYYMMDDFormat()
		{
			StringBuilder _dateStringbldr = new StringBuilder();
			DateTime _currentDateTime = DateTime.Now;

			_dateStringbldr.Append	(_currentDateTime.Year.ToString());
			_dateStringbldr.Append	(	initrode.utilities.StringManager.Fill
										(
											_currentDateTime.Month.ToString(),
											"0",
											true,
											2
										)
									);								
			_dateStringbldr.Append	(	initrode.utilities.StringManager.Fill
										(
											_currentDateTime.Day.ToString(),
											"0",
											true,
											2
										)
									);					
			return _dateStringbldr.ToString();			
		}
		public static string buildPathAndFileNameFromPathAndFileName
							(
								string inputPath,
								string inputFileNameAndExtension
							)
		{
			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputPath);
			_bldr.Append("\\");
			_bldr.Append(inputFileNameAndExtension);
			return _bldr.ToString();
		}
		public static string extractFileNameFromFileNameAndExtension(string inputFileNameAndExtension)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputFileNameAndExtension) == true) return "";
			ArrayList _fileNameParts = initrode.utilities.StringManager.splitIntoArrayList(inputFileNameAndExtension,@".");
			StringBuilder returnFileNameBldr = new StringBuilder();
			for (int _partCtr = 0; _partCtr < (_fileNameParts.Count - 1); _partCtr++)
			{
				if (returnFileNameBldr.Length > 0) returnFileNameBldr.Append(".");
				returnFileNameBldr.Append(_fileNameParts[_partCtr].ToString());
			}
			return returnFileNameBldr.ToString();
			
		}
		public static string extractPathFromPathAndFileName(string inputPathAndFileName)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputPathAndFileName) == true) return "";
			ArrayList _fileNameAndPathParts = initrode.utilities.StringManager.splitIntoArrayList(inputPathAndFileName,@"\\");
			StringBuilder returnPathBldr = new StringBuilder();
			for (int _partCtr = 0; _partCtr < (_fileNameAndPathParts.Count - 1); _partCtr++)
			{
				if (returnPathBldr.Length > 0) returnPathBldr.Append("\\");
				returnPathBldr.Append(_fileNameAndPathParts[_partCtr].ToString());
			}
			return returnPathBldr.ToString();
		}

		public static string extractFileNameFromPathAndFileName(string inputPathAndFileName)
		{
			if (initrode.utilities.StringManager.IsEmptyString(inputPathAndFileName) == true) return "";
			ArrayList _fileNameAndPathParts = initrode.utilities.StringManager.splitIntoArrayList(inputPathAndFileName,@"\\");
			return _fileNameAndPathParts[(_fileNameAndPathParts.Count - 1)].ToString();
		}
        public static void eliminateEmptyStringsFromArrayListOfString
                            (
                                ArrayList inputArrayListOfStrings
                                , out ArrayList outputArrayListOfStrings
                            )
        {
            outputArrayListOfStrings = new ArrayList();
            for (int _entryCtr = 0;
                    _entryCtr < inputArrayListOfStrings.Count;
                    _entryCtr++)
            {
                if (
                        initrode.utilities.StringManager.IsEmptyString
                        (
                            inputArrayListOfStrings[_entryCtr].ToString()
                        ) == false
                    )
                    outputArrayListOfStrings.Add
                    (
                        initrode.utilities.StringManager.StripWhitespaceFromEnds
                        (
                            inputArrayListOfStrings[_entryCtr].ToString()
                        )
                    );
            }
        }
        public static ArrayList splitIntoArrayList(string inputString,
                                                   string inputSplitAt)
		{
			ArrayList _returnParts = new ArrayList();
			Regex _r;

			string[] _strParts;
			if (inputSplitAt.CompareTo(@".") == 0) _r = new Regex(@"(\.)");
			else
			{
				if (inputSplitAt.CompareTo(@"\\") == 0) _r = new Regex(@"(\\)");
				else
				{
				
					StringBuilder _bldrPattern = new StringBuilder();
					_bldrPattern.Append("(");
					_bldrPattern.Append(inputSplitAt);
					_bldrPattern.Append(")");
					_r = new Regex(_bldrPattern.ToString()); // Split on inputSplitAt.
				}
			}


			_strParts = _r.Split(inputString);
			for(int i = 0; i < _strParts.Length; i++)
			{
				string _loopPart = _strParts[i].ToString();
				if (_loopPart.CompareTo(inputSplitAt) == 0
					|| (inputSplitAt.CompareTo(@"\\") == 0
						&& _loopPart.CompareTo(@"\") == 0)) continue;
				_returnParts.Add(_strParts[i].ToString());
			}
			return _returnParts;
		}
        public static ArrayList splitIntoArrayListOfNonBlankStrings
                                (
                                    string inputString
                                    ,string inputSplitAt
                                )
        {
            ArrayList _returnParts = new ArrayList();
            Regex _r;

            string[] _strParts;
            if (inputSplitAt.CompareTo
	        
	        
	        

Метки:  

CodeSOD: I'm Sooooooo Random, LOL

Вторник, 20 Августа 2019 г. 09:30 + в цитатник

There are some blocks of code that require a preamble, and an explanation of the code and its flow. Often you need to provide some broader context.

Sometimes, you get some code like Wolf found, which needs no explanation:

export function generateRandomId(): string { counter++; return 'id' + counter; }

I mean, I guess that's a slightly better than this solution. Wolf found this because some code downstream was expecting random, unique IDs, and wasn't getting them.

[Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!

https://thedailywtf.com/articles/i-m-sooooooo-random-lol


Метки:  

Lowest Bidder Squared

Понедельник, 19 Августа 2019 г. 09:30 + в цитатник

Stack of coins 0214

Initech was in dire straits. The website was dog slow, and the budget had been exceeded by a factor of five already trying to fix it. Korbin, today's submitter, was brought in to help in exchange for decent pay and an office in their facility.

He showed up only to find a boxed-up computer and a brand new flat-packed desk, also still in the box. The majority of the space was a video-recording studio that saw maybe 4-6 hours of use a week. After setting up his office, Korbin spent the next day and a half finding his way around the completely undocumented C# code. The third day, there was a carpenter in the studio area. Inexplicably, said carpenter decided he needed to contact-glue carpet to a set of huge risers ... indoors. At least a gallon of contact cement was involved. In minutes, Korbin got a raging headache, and he was essentially gassed out of the building for the rest of the day. Things were not off to a good start.

Upon asking around, Korbin quickly determined that the contractors originally responsible for coding the website had underbid the project by half, then subcontracted the whole thing out to a team in India to do the work on the cheap. The India team had then done the very same thing, subcontracting it out to the most cut-rate individuals they could find. Everything had been written in triplicate for some reason, making it impossible to determine what was actually powering the website and what was dead code. Furthermore, while this was a database-oriented site, there were no stored procedures, and none of the (sub)subcontractors seemed to understand how to use a JOIN command.

In an effort to tease apart what code was actually needed, Korbin turned on profiling. Only ... it was already on in the test version of the site. With a sudden ominous hunch, he checked the live site—and sure enough, profiling was running in production as well. He shut it off, and instantly, the whole site became more responsive.

The next fix was also pretty simple. The site had a bad habit of asking for information it already had, over and over, without any JOINs. Reducing the frequency of database hits improved performance again, bringing it to within an order of magnitude of what one might expect from a website.

While all this was going on, the leaderboard page had begun timing out. Sure enough, it was an N-squared solution: open database, fetch record, close database, repeat, then compare the two records, putting them in order and beginning again. With 500 members, it was doing 250,000 passes each time someone hit the page. Korbin scrapped the whole thing in favor of the site's first stored procedure, then cached it to call only once a day.

The weeks went on, and the site began to take shape, finally getting something like back on track. Thanks to the botched rollout, however, many of the company's endorsements had vanished, and backers were pulling out. The president got on the phone with some VIP about Facebook—because as we all know, the solution to any company's problem is the solution to every company's problems.

"Facebook was written in PHP. He told me it was the best thing out there. So we're going to completely redo the website in PHP," the president confidently announced at the next all-hands meeting. "I want to hear how long everyone thinks this will take to get done."

The only developers left at that point were Korbin and a junior kid just out of college, with one contractor with some experience on the project.

"Two weeks. Maybe three," the kid replied.

They went around the table, and all the non-programmers chimed in with the 2-3 week assessment. Next to last came the experienced contractor. Korbin's jaw nearly dropped when he weighed in at 3-4 weeks.

"None of that is realistic!" Korbin proclaimed. "Even with the existing code as a road map, it's going to take 4-6 months to rewrite. And with the inevitable feature-creep and fixes for things found in testing, it is likely to take even longer."

Korbin was told the next day he could pick up his final check. Seven months later, he ran into the junior kid again, and asked how the rewrite went.

"It's still ongoing," he admitted.

[Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today!

https://thedailywtf.com/articles/lowest-bidder-squared


Метки:  

Error'd: What About the Fish?

Пятница, 16 Августа 2019 г. 09:30 + в цитатник

"On the one hand, I don't want to know what the fish has to do with Boris Johnson's love life...but on the other hand I have to know!" Mark R. writes.

 

"Not sure if that's a new GDPR rule or the Slack Mailbot's weekend was just that much better then mine," Adam G. writes.

 

Connor W. wrote, "You know what, I think I'll just stay inside."

 

"It's great to see that an attempt at personalization was made, but whatever happened to 'trust but verify'?" writes Rob H.

 

"For a while, I thought that, maybe, I didn't actually know how to use my iPhone's alarm. Instead, I found that it just wasn't working right. So, I contacted Apple Support, and while they were initially skeptical that it was an iOS issue, this morning, I actually have proof!" Markus G. wrote.

 

Tim G. writes, "I guess that's better than an angry error message."

 

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/what-about-the-fish


Метки:  

CodeSOD: A Devil With a Date

Четверг, 15 Августа 2019 г. 09:30 + в цитатник

Jim was adding a feature to the backend. This feature updated a few fields on an object, and then handed the object off as JSON to the front-end.

Adding the feature seemed pretty simple, but when Jim went to check out its behavior in the front-end, he got validation errors. Something in the data getting passed back by his web service was fighting with the front end.

On its surface, that seemed like a reasonable problem, but when looking into it, Jim discovered that it was the record_update_date field which was causing validation issues. The front-end displayed this as a read only field, so there was no reason to do any client-side validation in the first place, and that field was never sent to the backend, so there was even less than no reason to do validation.

Worse, the field had, at least to the eye, a valid date: 2019-07-29T00:00:00.000Z. Even weirder, if Jim changed the backend to just return 2019-07-29, everything worked. He dug into the validation code to see what might be wrong about it:

/**
 * Custom validation
 *
 * This is a callback function for ajv custom keywords
 *
 * @param  {object} wsFormat aiFormat property content
 * @param  {object} data Data (of element type) from document where validation is required
 * @param  {object} itemSchema Schema part from wsValidation keyword
 * @param  {string} dataPath Path to document element
 * @param  {object} parentData Data of parent object
 * @param  {string} key Property name
 * @param  {object} rootData Document data
 */
function wsFormatFunction(wsFormat, data, itemSchema, dataPath, parentData, key, rootData) {

    let valid;
    switch (aiFormat) {
        case 'date': {
            let regex = /^\d\d\d\d-[0-1]\d-[0-3](T00:00:00.000Z)?\d$/;
            valid = regex.test(data);
            break;
        }
        case 'date-time': {
            let regex = /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i;
            valid = regex.test(data);
            break;
        }
        case 'time': {
            let regex = /^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
            valid = regex.test(data);
            break;
        }
        default: throw 'Unknown wsFormat: ' + wsFormat;
    }

    if (!valid) {
        wsFormatFunction['errors'] = wsFormatFunction['errors'] || [];

        wsFormatFunction['errors'].push({
            keyword: 'wsFormat',
            dataPath: dataPath,
            message: 'should match format "' + wsFormat + '"',
            schema: itemSchema,
            data: data
        });
    }

    return valid;
}

When it starts with “Custom validation” and it involves dates, you know you’re in for a bad time. Worse, it’s custom validation, dates, and regular expressions written by someone who clearly didn’t understand regular expressions.

Let’s take a peek at the branch which was causing Jim’s error, and examine the regex:

/^\d\d\d\d-[0-1]\d-[0-3](T00:00:00.000Z)?\d$/

It should start with four digits, followed by a dash, followed by a value between 0 and 1. Then another digit, then a dash, then a number between 0 and 3, then the time (optionally), then a final digit.

It’s obvious why Jim’s perfectly reasonable date wasn’t working: it needed to be 2019-07-2T00:00:00.000Z9. Or, if Jim just didn’t include the timestamp, not only would 2019-07-29 be a valid date, but so would 2019-19-39, which just so happens to be my birthday. Mark your calendars for the 39th of Undevigintiber.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

https://thedailywtf.com/articles/a-devil-with-a-date


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 82 81 [80] 79 78 ..
.. 1 Календарь