Tuesday, August 28, 2012

APEX Shortcuts

One page that always eludes me when I need it is the Application Build Status page. When I need to quickly set an application to unavailable so I can update the backend for instance, I spend 10 minutes trying to find it only to give up and edit the table in the apex schema. Well not so any more.

On the Administration page there is a yellow announcement bar you can edit and add links to. Since the #SESSION# substitution doesn't work you have to use a javascript link, but it's not too hard to figure out. Here's the HTML for my Application Build Status shortcut.

<a href="javascript:document.location.href='f?p=4350:41:'+$('#pInstance').val()">
  <b>Application Build Status</b>
</a>


The internal workspace also has an instance wide announcement bar that works the same way.

Sunday, July 8, 2012

Button Confirmation Message

This is a quick way to add a javascript confirmation message to a button.

Firstly make sure that your button template uses #BUTTON_ATTRIBUTES# substitution string (note  #BUTTON_ID# doesn't seem to work as expected here). Add a button id to the Attributes field, or otherwise ensure you can identify it with a jQuery selector.


Then in Post Element Text place some jQuery to extend the click event...


I figure this method should be pretty robust. Here's the code for copy/pastability:

<script>
var btnClick = $('#PX_MYBUTTON').attr('onclick');
$('#PX_MYBUTTON')
 .removeAttr('onclick')
 .unbind('click')
 .click(function(e){
  if (confirm('Confirm message.')) btnClick(e);
 });
</script>

Tuesday, May 8, 2012

Interactive Report Column Custom Formatting

The question was posed, how to achieve custom formatting of a column if the available Format Models don't suffice? In standard SQL reports, it's not such a problem as you can simply use the "HTML Expression" field.

Well here's one way to do it, use some jQuery in a dynamic action. While this may seem really counter-intuitive, it's actually both beautifully simple and reliable after you finish considering all the other available options. Plus, that's what this blog is all about remember (when it's not being abandoned for years).

Create the dynamic action called something like "Format Report" triggered "After Refresh" on the report region. Also ensure "Fire On Page Load" is checked. The action is to execute Javascript like the following (this example will give you a trailing "%"):

$('td[headers="MY_COLUMN"]').append('%');

UPDATE: Or better yet...

$('td[headers^="MY_COLUMN"]').text(function(index,text){return text+'%'});

After teething problems with the first use case, we figured out you must have a Region Template with id="#REGION_STATIC_ID#". Also we adapted the jQuery to better support several other IR features (as seen in the second option above). Leave comments if you can build on this any further.

The advantage here is you don't have to modify the query and you can put all sorts of additional formatting in the one place without interfering with the existing functionality of the interactive report.

Here's another possible solution. The iFormat™ deluxe model. While both effective and platform independent, mounting and unmounting required to apply the formatting may prove somewhat arduous for the users after a while.

Tuesday, April 13, 2010

XSS and Apex

XSS = X(cross) Site Scripting. This is where user entered data contains some javascript that will be later inadvertently rendered and executed by another users browser. The javascript then sends session information back to the attackers external server. This information could contain cookies that can be used to steal the user's session.

Atlassian and the Apache team (who use Atlassian services) recently got hacked big time thanks in part to XSS vulnerabilities in their site. Details can be found here... https://blogs.apache.org/infra/entry/apache_org_04_09_2010 (it's a great read).

There is no simple solution to protect against XSS, but here's an article which demonstrates a generic method that web applications can use to avoid XSS from the client side. It's known as HTTPOnly cookies. This is very good news, it mentions that Firefox has a bug that doesn't implement HttpOnly correctly, but this has since been fixed... http://www.codinghorror.com/blog/2008/08/protecting-your-cookies-httponly.html

HTTPOnly is sufficiently supported by 99% of mainstream browsers (and most importantly, those in our SOE). Opera and Safari support is unconfirmed, but I'd assume they would have addressed this by now. I'd expect to see more support for HTTPOnly tighten as it's such a valuable tool to protect cookies.

I've been aware of XSS dangers for years, but only since this Atlassian incident was I curious to test the extent of the risk on Apex applications. Apex does not currently use HTTPOnly cookies, I'll investigate adding it. Apex does use the most standard method of setting cookies, which is promising as it's best supported by the browsers. We just need to figure out how to flip the HTTPOnly flag on the server somehow to provide another layer of protection for our users/applications. Apex is also wide open to session stealing based on cookie information, so please keep this in mind. Don't allow unsanitised user data to be rendered in the browser. This is absolutely critical for any application which is going to be made available to both the public and privileged users.

Monday, August 17, 2009

Subversion Autodeploy post-commit Hook

Since the apache user is non-interactive, it's difficult to get a post-commit hook to trigger an svn update elsewhere on the system. You can either temporarily make the apache user interactive, or perform the checkout in the hook one time. For the latter option, empty the deployment directory and update the post-commit hook with this command...
svn checkout file:///path/to/svn/project/ /path/to/project/dev/deployment --non-interactive
Now make a trivial change and perform a commit. Check that the project has been deployed. Change the post-commit hook to this...
svn update /path/to/project/dev/deployment --non-interactive

Sunday, July 26, 2009

It's All Text!

Every APEX developer needs to know about a handy firefox extension called It's All Text!. Install this and it will allow you to seamlessly edit any textarea in an external editor. The default file extension applied to such files can changed to ".sql". So if your editor handles syntax highlighting based on file type, you're in business. I use SciTE and it all works very well.

It's almost like having a real IDE. In fact, with some tweaking this extension could do a whole lot more for APEX developers. I'm thinking meaningful file naming/directory structure based on the structure of the application and SVN integration at least. APEX page save error messages sent back to the text editor for finding line numbers (SciTE can handle this very easily, if the APEX page save error message was dumped into a file, then SciTE can be configured to pick that text up when a hotkey is pressed and errors with line numbers will be linked to the source code). This might have to be a little side project.

To change the default file type right click the "edit" button, select "Edit with new extension...", type ".sql" and check "Save for future use".

I don't have to explain how simple and effective this little tool is. Just install it and wonder how you ever lived without it!

On a side note, there is a similar extension good for editing HTML regions called Write Area.

Friday, June 19, 2009

Haunted by Headers

Had an interesting problem today tracing the origin of some HTTP headers. An application which uses mod_plsql (non-APEX) was constantly returning some troublesome header information which we needed to remove, particularly when a certain procedure was called. I searched every where in the OAS interface, but none of the settings seemed to be applicable. Eventually I found the culprit was an apache declaration in dads.conf. Why it was there I can only speculate, not having built the application.

On the up side, I can now clarify some more of the behaviour of the undocumented htp.init procedure. During the process of tracing the problem, I attempted to use htp.init to suppress the headers from showing up when calling a particular procedure. Apparently this isn't how it works. The application server still amends header information to the response before it is sent.