Friday, July 17, 2020

SQL Server Reporting Services - Summing a Field Calculated in a Custom Code Assembly

I have a report that has a complex calculation being done in a custom code assembly that is attached to the report as a reference. The problem I ran into is trying to get a SUM on that calculation. I've written some custom code that you can input into the Code section on Report Properties.

Public Shared Value as Decimal=0.00
Public Shared ReturnValue as Decimal = 0.00
Public Shared Function GetValue(Item as Integer) as Integer
     value= value + Item
     return Item
End Function
Public Shared Function GetTotal()
     returnvalue = value
     value = 0
     return returnvalue
End Function


Then you just enclose the original expression inside:

=Code.GetValue(put expression here)

And then use this expression where you want the total:

=Code.GetTotal()

This code will also zero-out the 'Value' variable so that you can reuse it in a repeating group.

Friday, June 12, 2020

MacOS Google File Stream Error: drive file stream has encountered a problem and has stopped

I've spent too much of the last few days trying to figure out why I couldn't get Google File Stream running on a new account on a mac. I tried all of the recommended solutions with no luck so finally I decided to try to figure it out myself and I did get it working.

The problem I was seeing is that I was just getting an error every single time I tried to run the application. All I'd get was "drive file stream has encountered a problem and has stopped" and I couldn't change any preferences at all or do anything besides quit the app.

What fixed this issue for me (after trying everything else recommended online) was to uninstall Google File Stream, and then in finder show hidden files on the HD (cmd + shift + .) and go to Volumes and delete the Google Drive volume. Then I reinstalled Google File Stream, and once that was done it started working just fine the next time I fired the program up.

My guess is that the volume is created under the context of the user who installs the program, and if another account gets created it doesn't have permissions to access that volume. Purely a guess though. Anyway I hope that helps anyone who is running into this same issue.

Friday, January 31, 2020

.NET Core 3.1 Identity Database Script to Build Necessary DB Objects Without Using Migrate

Not everyone has the database access they need to use the whiz-bang database-migration tools when writing Razor apps with .NET Core 3.1. If this is you, and you either can't get the DBAs to give you that access, or you don't want to be running migrations on a database with other important data in it, then you can use this script directly in SQL Server to build the DB objects you'll need for the default .NET Core 3.1 Identity implementation.


      CREATE TABLE [AspNetRoles] (
          [Id] nvarchar(450) NOT NULL,
          [Name] nvarchar(256) NULL,
          [NormalizedName] nvarchar(256) NULL,
          [ConcurrencyStamp] nvarchar(max) NULL,
          CONSTRAINT [PK_AspNetRoles] PRIMARY KEY ([Id])
      );

      CREATE TABLE [AspNetUsers] (
          [Id] nvarchar(450) NOT NULL,
          [UserName] nvarchar(256) NULL,
          [NormalizedUserName] nvarchar(256) NULL,
          [Email] nvarchar(256) NULL,
          [NormalizedEmail] nvarchar(256) NULL,
          [EmailConfirmed] bit NOT NULL,
          [PasswordHash] nvarchar(max) NULL,
          [SecurityStamp] nvarchar(max) NULL,
          [ConcurrencyStamp] nvarchar(max) NULL,
          [PhoneNumber] nvarchar(max) NULL,
          [PhoneNumberConfirmed] bit NOT NULL,
          [TwoFactorEnabled] bit NOT NULL,
          [LockoutEnd] datetimeoffset NULL,
          [LockoutEnabled] bit NOT NULL,
          [AccessFailedCount] int NOT NULL,
          CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id])
      );

      CREATE TABLE [AspNetRoleClaims] (
          [Id] int NOT NULL IDENTITY,
          [RoleId] nvarchar(450) NOT NULL,
          [ClaimType] nvarchar(max) NULL,
          [ClaimValue] nvarchar(max) NULL,
          CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY ([Id]),
          CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE
      );

      CREATE TABLE [AspNetUserClaims] (
          [Id] int NOT NULL IDENTITY,
          [UserId] nvarchar(450) NOT NULL,
          [ClaimType] nvarchar(max) NULL,
          [ClaimValue] nvarchar(max) NULL,
          CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY ([Id]),
          CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
      );

      CREATE TABLE [AspNetUserLogins] (
          [LoginProvider] nvarchar(128) NOT NULL,
          [ProviderKey] nvarchar(128) NOT NULL,
          [ProviderDisplayName] nvarchar(max) NULL,
          [UserId] nvarchar(450) NOT NULL,
          CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY ([LoginProvider], [ProviderKey]),
          CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
      );

      CREATE TABLE [AspNetUserRoles] (
          [UserId] nvarchar(450) NOT NULL,
          [RoleId] nvarchar(450) NOT NULL,
          CONSTRAINT [PK_AspNetUserRoles] PRIMARY KEY ([UserId], [RoleId]),
          CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE,
          CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
      );

      CREATE TABLE [AspNetUserTokens] (
          [UserId] nvarchar(450) NOT NULL,
          [LoginProvider] nvarchar(128) NOT NULL,
          [Name] nvarchar(128) NOT NULL,
          [Value] nvarchar(max) NULL,
          CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY ([UserId], [LoginProvider], [Name]),
          CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE
      );

      CREATE INDEX [IX_AspNetRoleClaims_RoleId] ON [AspNetRoleClaims] ([RoleId]);

      CREATE UNIQUE INDEX [RoleNameIndex] ON [AspNetRoles] ([NormalizedName]) WHERE [NormalizedName] IS NOT NULL;

      CREATE INDEX [IX_AspNetUserClaims_UserId] ON [AspNetUserClaims] ([UserId]);

      CREATE INDEX [IX_AspNetUserLogins_UserId] ON [AspNetUserLogins] ([UserId]);

      CREATE INDEX [IX_AspNetUserRoles_RoleId] ON [AspNetUserRoles] ([RoleId]);

      CREATE INDEX [EmailIndex] ON [AspNetUsers] ([NormalizedEmail]);

      CREATE UNIQUE INDEX [UserNameIndex] ON [AspNetUsers] ([NormalizedUserName]) WHERE [NormalizedUserName] IS NOT NULL;

Monday, December 9, 2019

Ikea Lack arcade table based on Retropie

Ikea Lack arcade table based on Retropie. With donated 17 inch monitor the project came in at $179. The most expensive piece was the plexiglass I had cut to size and delivered. Anyway, hope that these images are helpful to anyone who's wanting to try the same project. I'll add explanation later if anyone is interested in this post and wants more info.


























Wednesday, February 8, 2012

Linux Backup Shell Script for Files and MySQL

I assembled this script to backup my web server onto a USB thumbdrive. It mounts the thumbdrive (/dev/sdc1), backs up a couple of directories, does a MySQL dump, and then unmounts the drive. It appends the day of the week to the file name so you can run it daily as a cron job and you’ll get 7-days’ worth of backups on a rotating basis.

#!/bin/sh
####################################
#
# Backup to usb thumbdrive
#
####################################

# What to backup.
backup_files="/home/shared /etc"

# Where to backup to.
dest="/home/administrator/backup/usb"

# Create archive filename.
day=$(date +%A)
hostname=$(hostname -s)
archive_file="$hostname-$day.tgz"
sql_file="$hostname-$day.sql"

# Mount the usb thumbdrive
mount -t vfat /dev/sdc1 /home/administrator/backup/usb -o uid=1000,gid=1000,utf8,dmask=027,fmask=137
echo "Thumbdrive mounted"

# Backup MySQL
echo "Backing up MySQL to $dest/$sql_file"
date
mysqldump --all-databases --password='XXXXXXX' > $dest/$sql_file

# Print start status message.
echo "Backing up $backup_files to $dest/$archive_file"
date

# Backup the files using tar.
tar czf $dest/$archive_file $backup_files

# Print end status message.
echo "Backup finished"
date

# Long listing of files in $dest to check file sizes.
ls -lh $dest

# Unmount the usb thumbdrive
umount /home/administrator/backup/usb
echo "Thumbdrive unmounted"

Thursday, January 5, 2012

Running Node.js Alongside Apache

I decided to set up Node.js on my Linux server running Apache.  Getting a Node.js server running was trivially simple, but I had a bit of trouble getting the mod_rewrite stuff correct to make it pretty (i.e. no port in the URL).  Basically I wanted to create a sub-directory on my site and route all the requests going there to my Node.js server, leaving everything else as-is.  So, http://kevnls.com/ and http://kevnls.com/etc/ would still be handled by Apache, but http://kevnls.com/node/ would be handed-off to Node.js.

Before I began, I already had Node.js serving up content at http://kevnls.com:8000.  I'm not going to address that part, because there are plenty of resources that can help you get to that point.

The first thing I needed to do was create a symlink to the directory where my Node.js server was running (/home/shared/node/).  In my case my CMS has a public/ folder where I can put stuff like 'whatever.txt' and it will resolve to http://kevnls.com/whatever.txt.  So, this is where I created a symlink.  At this point http://kevnls.com/node/ pointed to /home/shared/node/ in the filesystem.

Then in the /home/shared/node/ folder I created my .htaccess file with this mod_rewrite rule:

-----------------------------------------------------------------

Options +FollowSymLinks -Indexes -MultiViews

RewriteEngine on

RewriteRule ^(.*)$ http://kevnls.com:8000/$1 [P]

-----------------------------------------------------------------


Then I needed to get the proper modules running in Apache to handle what I wanted to do.  You can issue the following shell command and just type in the modules you want to enable:


a2enmod

In my case I needed 'proxy', 'proxy_http' and 'rewrite'.



After a quick Apache restart everything was working the way I wanted it.  Now on to the coding.

Sunday, September 25, 2011

Receiving and Processing a SAML 2.0 Response With an HttpServlet Using OpenSAML

Due to the popularity of my prior posts on processing SAML using OpenSAML I put together this code that shows a more real-world-example of how you would setup an HttpServlet to sit and listen for SAML Responses that are posted to it.  Then it just shows what you might do with the Response to get what you need out of it.  Again, I'm just verifying the Signature on the Response, Decrypting the Assertion and then looping through the Attribute nodes to look at the name/value pairs.  There are other things that you might want to do such as receiving the signing-key from the Response itself (if it's being sent), or verifying a Signature on the Assertion if that's what's being signed.  The trouble I've found with SAML implementations is that the spec is consistent, but how people use it isn't, so you'll undoubtedly need to tweak something depending on what your requirements are, but this code should get you started.

import java.io.PrintWriter;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import java.util.List;

import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.X509EncodedKeySpec;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
import org.opensaml.ws.message.MessageContext;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.encryption.DecryptionException;
import org.opensaml.xml.encryption.InlineEncryptedKeyResolver;
import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver;
import org.opensaml.xml.security.x509.BasicX509Credential;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureValidator;
import org.opensaml.xml.validation.ValidationException;

/**
 * @author kevnls
 * If you use this code as a base for your implementation please leave this comment intact.
 * You should add your own name in addition.
 */

public class ProcessSAML extends HttpServlet {
  
    /**
     * Processes requests for both HTTP GET and POST methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        File signatureVerificationPublicKeyFile = new File("C:\\Documents and Settings\\kevnls\\My Documents\\NetBeansProjects\\SAMLReceiver\\files\\IdPSigningCert.cer");
        File decryptionPrivateKeyFile = new File("C:\\Documents and Settings\\kevnls\\My Documents\\NetBeansProjects\\SAMLReceiver\\files\\SPEncryptionCert.jks");
        String decryptionPrivateKeyName = "pvktmp:bd5ba0e0-9718-48ea-b6e6-32cd9c852d76";
        String decryptionPrivateKeyPassword = "!c3c0ld";

        try
        {
            //bootstrap the opensaml stuff
            org.opensaml.DefaultBootstrap.bootstrap();

            // get the message context
            MessageContext messageContext = new BasicSAMLMessageContext();
            messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
            HTTPPostDecoder samlMessageDecoder = new HTTPPostDecoder();
            samlMessageDecoder.decode(messageContext);

            // get the SAML Response
            Response samlResponse = (Response)messageContext.getInboundMessage();

            //get the certificate from the file
            InputStream inputStream2 = new FileInputStream(signatureVerificationPublicKeyFile);
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate certificate = (X509Certificate)certificateFactory.generateCertificate(inputStream2);
            inputStream2.close();

            //pull out the public key part of the certificate into a KeySpec
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());

            //get KeyFactory object that creates key objects, specifying RSA
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");

            //generate public key to validate signatures
            PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

            //create credentials
            BasicX509Credential publicCredential = new BasicX509Credential();

            //add public key value
            publicCredential.setPublicKey(publicKey);

            //create SignatureValidator
            SignatureValidator signatureValidator = new SignatureValidator(publicCredential);

            //get the signature to validate from the response object
            Signature signature = samlResponse.getSignature();

            //try to validate
            try
            {
                signatureValidator.validate(signature);
            }
            catch (ValidationException ve)
            {
                out.println("Signature is not valid.");
                out.println(ve.getMessage());
                return;
            }

            //no validation exception was thrown
            out.println("Signature is valid.");

            //start decryption of assertion

            //load up a KeyStore
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream(decryptionPrivateKeyFile), decryptionPrivateKeyPassword.toCharArray());

            RSAPrivateKey privateKey = (RSAPrivateKey) keyStore.getKey(decryptionPrivateKeyName, decryptionPrivateKeyPassword.toCharArray());

            //create the credential
            BasicX509Credential decryptionCredential = new BasicX509Credential();
            decryptionCredential.setPrivateKey(privateKey);

            StaticKeyInfoCredentialResolver skicr = new StaticKeyInfoCredentialResolver(decryptionCredential);

            //create a decrypter
            Decrypter decrypter = new Decrypter(null, skicr, new InlineEncryptedKeyResolver());

            //decrypt the first (and only) assertion
            Assertion decryptedAssertion;

            try
            {
                decryptedAssertion = decrypter.decrypt(samlResponse.getEncryptedAssertions().get(0));
            }
            catch (DecryptionException de)
            {
                out.println("Assertion decryption failed.");
                out.println(de.getMessage());
                return;
            }

            out.println("Assertion decryption succeeded.");

            //loop through the nodes to get the Attributes
            //this is where you would do something with these elements
            //to tie this user with your environment
            List attributeStatements = decryptedAssertion.getAttributeStatements();
            for (int i = 0; i < attributeStatements.size(); i++)
            {
                List attributes = attributeStatements.get(i).getAttributes();
                for (int x = 0; x < attributes.size(); x++)
                {
                    String strAttributeName = attributes.get(x).getDOM().getAttribute("Name");

                    List attributeValues = attributes.get(x).getAttributeValues();
                    for (int y = 0; y < attributeValues.size(); y++)
                    {
                        String strAttributeValue = attributeValues.get(y).getDOM().getTextContent();
                        out.println(strAttributeName + ": " + strAttributeValue + " ");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

    }

    //
    /**
     * Handles the HTTP GET method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP POST method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "This servlet processes a SAML 2.0 Response.  It verifies the signature, " +
                "decrypts an assertion, and parses out the data in the attribute statements.  " +
                "If you use this code as a base for your implementation please leave the @author comment intact.  " +
                "You should add your own name in addition.";
    }//


}



Anyway, hope this is useful to someone.

Saturday, September 24, 2011

Dark Arduino IDE Theme

I'm totally having fun playing around with my Arduino UNO, but the Arduino IDE is a little too bright for my tastes, so I created a dark theme and posted it here.

Here's a screenshot:



All you need to do is find your 'theme' folder (it may be nested a bit but it should be in the application folder somewhere under /lib/) and replace it with this folder.  I created this on a mac and it's theming version 1.0 of the IDE, but I'm guessing the theme folder is the same for all platforms.  Make a backup of yours before you drop this one in just in case though. 

You'll need to restart the Arduino IDE for the changes to take effect, but then you can sit back and let your eyes thank you!

Hope you like it.

Wednesday, June 8, 2011

Using Javascript to Manipulate DOM Elements in Hype

I’ve been having a lot of fun playing with Tumult’s recently-released tool called Hype for the Mac. It’s a time-line based tool for creating rich animated HTML5 content that runs natively in most modern browsers. We’ve been hearing for quite some time that Flash is no longer needed with all of HTML5 and CSS3’s capabilities, but no one had come up with a design-centric tool for creating that content. That’s where Hype has stepped in. For anyone familiar with working in Adobe’s Flash design tools, Hype should be fairly straightforward to work with. I had an interactive mobile site targeted at the iPhone finished in a few hours, with stuff animating into view, and custom buttons triggering animations between scenes. The problem I ran into though came when I wanted to start thinking about getting dynamic content from the outside world into the site instead of coding everything inside the Hype-generated container (most of the stuff lives in an ugly javascript file so don’t plan on working with content you’ve put into Hype after you’ve ‘compiled’ it down). That’s the one place I think it falls a little short. Although it’s nice that, unlike Flash, it exports to pure javascript/css, it’s still kind of an enclosed blob for all intents and purposes once you’ve moved out of the Hype application.

So, here’s the design I was trying to achieve. I had a home page that I wanted to populate with some dynamic content from my FriendFeed account via RSS. I decided to use Google’s javascript API for the RSS communication, and that’s pretty straightforward and well-documented on Google’s site. The problem I ran into was getting that code integrated with Hype. This is how I got it working.

Basically Hype has some event-hooks where you can trigger a javascript function. For what I was trying to achieve it made the most sense to tap into the hook that occurs after the animation for the home page has completed. I added a function called loadRSSContent and did the event-wiring in the GUI, which is trivially simple. Then I added a couple of lines of javascript to that function that would call another function that lives on the .html page that houses the Hype container. It’s not very well documented on the Hype site, but you can use any javascript functions/libraries within Hype that will eventually be available on the enclosing page at runtime. There is currently no support for importing these assets at design-time though (although that seems like an easy feature to add) so you’re flying-blind until you run the export and embed the container on a page. This is why I would suggest getting everything running on a test page and then only moving the pieces into Hype that are necessary to manipulate the DOM elements on the timeline. You’ll understand what I mean when you see the code.

So, on my home scene I added a Hype text box, and within it I created a div with id=“rssDiv”.

On the ‘On Animation Complete” event for the scene, the javascript in Hype looks like this:

function loadRSSContent(hypeDocument, element)
  //get the content for the rssDiv from a function outside of Hype
  var rssDiv = document.getElementById("rssDiv");
  rssDiv.innerHTML = getRSSContent();
}

The javascript that does the work lives on the .html page (outside of the Hype container). I should also point out what I’m doing here. I’m using the initialize() function to put the RSS html into a hidden element on the page, and then the getRSSContent() function takes that content and hands it back inside the Hype container when it requests it. The reason I’m doing it this way is because the DOM gets built dynamically with Hype, so you don’t want to try to manipulate it directly from outside of the Hype container. Also, the initialize() function can run as soon as the Google API is loaded and get the content ready while Hype is doing its animation stuff.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv=“Content-Type” content=“text/html; charset=utf-8”>
<meta http-equiv=“X-UA-Compatible” content=“chrome=1”>
<meta name=“viewport” content=“user-scalable=yes, width=320px” />
<script type=“text/javascript” src=“https://www.google.com/jsapi?key=yourkey”></script>
<script src=“https://www.google.com/uds/?file=feeds&v=1” type=“text/javascript”></script>
<script type=“text/javascript”>

function initialize() {
  var feed = new google.feeds.Feed(“http://friendfeed.com/kevnls?format=atom&num=4”);
  feed.setNumEntries(4);
  feed.load(function(result) {
    if (!result.error) {
      var html = ‘’;
      for (var i = 0; i < result.feed.entries.length; i++) {
        var entry = result.feed.entries[i];
        html += ‘<a href=“’ + entry.link + ‘” target=“_blank”>’ + entry.title + ‘</a><br/><br/>’;
      }
      document.getElementById(“hiddenElement”).value = html;
    }
  });
}

google.setOnLoadCallback(initialize);

function getRSSContent() {
  var hiddenElement = document.getElementById(“hiddenElement”);
  var rssResult = hiddenElement.value;
  return rssResult;
}
  
</script>
<title>kevnls</title>
        <style>
                body {
                        background-color: #FFFFFF;
                        margin: 0px;
                }
        </style>
</head>
<body>
        <input type=“hidden” id=“hiddenElement” value=“” />
        <div style =“margin:auto;width:320px”>  
        <!-- copy these lines to your document: -->
        <div id=“kevnls_hype_container” style=“position:relative;overflow:hidden;width:320px;height:396px;”>
                <script type=“text/javascript” src=“mobile_Resources/kevnls_hype_generated_script.js?43552”></script>
        </div>
        <!-- end copy -->
        </div>
</body>
</html>

The result of all of this can be seen here: http://kevnls.com/mobile

Hopefully this design will prove useful to someone (besides me).

Until next time.

Tuesday, April 19, 2011

Using jQuery to Disable a Link on a Specific Day of the Week

My company has a regular scheduled downtime of our messaging-bus each Sunday.  This brings down some functionality on our site, so I needed to disable the links for those resources automatically, but instead of hiding them or pointing them somewhere else, I decided it would be nice to give the user some information about what's going on right there on the page when they click on one of the disabled links.  I came up with the following piece of code which will do that for any link with class="TibcoRequired":

<!--script to disable links to Tibco-reliant tests on Sundays-->
     
<link href="/Resources/Scripts/jQuery/css/redmond/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css"/>
<script src="/Resources/Scripts/jQuery/js/jquery-1.4.2.min.js"></script>
<script src="/Resources/Scripts/jQuery/js/jquery-ui-1.8.1.custom.min.js"></script>

<div id="dialog" title="Dialog Title" style="display:none;"><p>This test cannot be taken on Sundays due to a regular
  scheduled downtime of the result-tracking system.</p></div>

<script type="text/javascript">
      $('.TibcoRequired').click(function () {
        var d = new Date();
        var today = d.getDay();
        if (today == 0) {
          $('#dialog').dialog({ title: 'Message' });
          return false;
        }
      });
</script>

<!--script-->

Thursday, January 13, 2011

Creating a custom Model and passing a Linq to SQL query to a View in .net MVC

Another one of my 'I was trying to do this and having no luck finding solutions' posts, so I'll post my solution and hopefully it will help someone else in the same predicament.

This time I was working on a .NET MVC project, and trying to do some reporting.  Basically it's a simple app that records users' steps-per-day.  The users are assigned to teams and I wanted to create a page that showed the ranking of the different teams each month based on their total number of steps.  As you can imagine, I had three tables.  tblTeams, tblUsers, and tblSteps.  So, my problem was, I have a model built using Linq to SQL, and it works fine if you're working with one of the objects that relates to its table.  But, in this case I just wanted to do a simple join query, with some grouping, and return that to the view to create an html table of the different teams and their totals.  So, here's how I made it work:

First off, I created a new very simple model containing the class to hold the results of the query:

namespace StepsChallenge.Models
{
    public class TeamTotalsModel
    {
        public string TeamName { get; set; }
        public string Sum { get; set; }
    }
}

Then, in my view I added a reference to this model:

Inherits="System.Web.Mvc.ViewPage<IEnumerable<StepsChallenge.Models.TeamTotalsModel>>"

OK, now we're wired-up.  On to the data.

I wrote a Linq to SQL query that looked like this in my controller and passed it into an instance of the model class:

public class HomeController : Controller
{
        public ActionResult Index()
        {
            //get monthly steps for the teams
            var allTeamsMonthlySteps = from stepRecord in homeModel.Steps
                                       join userRecord in homeModel.Users
                                       on stepRecord.EmpID equals userRecord.EmpID
                                       join teamRecord in homeModel.Teams
                                       on userRecord.TeamID equals teamRecord.TeamID
                                       where stepRecord.Date.Month == DateTime.Now.Month
                                       group stepRecord by teamRecord.TeamName into result
                                       orderby result.Key ascending
                                       select new TeamTotalsModel
                                       {  
                                          TeamName = result.Key.ToString(),
                                          Sum = result.Sum(r => r.Steps).ToString()
                                       };

            return View(allTeamsMonthlySteps);
         }
}

Then finally, back at the view I wrote something like this:

    <table>
        <tr>
            <th>
                TeamName
            </th>
            <th>
                Sum
            </th>
        </tr>

    <% foreach (var item in Model) { %>
  
        <tr>
            <td>
                <%= Html.Encode(item.TeamName) %>
            </td>
            <td>
                <%= Html.Encode(item.Sum) %>
            </td>
        </tr>
  
    <% } %>

    </table>

So, this isn't all that complicated, but the problem I was having is that every search I did on almost every piece of this pointed me back to all the Visual Studio drag-and-drop BS for working with Linq to SQL models where there's a one-to-one relationship between objects and tables.  And, I couldn't find much help at all on writing a Linq to SQL query with multiple joins, grouping, and 'where' clauses, all together, and passing it to the view.

Anyway, maybe some poor slob like me will stumble across this and find what he needs.  Until next time.

Friday, December 3, 2010

Apache configuration for SimpleSAMLphp on OS X Snow Leopard

I needed to do some testing with the SimpleSAMLphp (http://simplesamlphp.org/) application today. I’m not a php developer so my mac wasn’t setup to run php in Apache. That part was trivially simple to setup, but I ran into problems trying to get the SimpleSAMLphp application running in a configuration that made sense to me. What I wanted to do was install the application into my /Sites/ directory, and create another directory under /Sites/ that would act as the php site that uses it. It may seem odd to install the app in the sites directory, but I just wanted to keep the two together. So, the directory structure looked like this:

~/Sites/simplesamlphp/
~/Sites/phpsite/

Then, I wanted to change my Apache configuration so that http://localhost/ would remain the same (pointing at /Library/WebServer/Documents/), http://phpsite/ would point to ~/Sites/phpsite/, and http://phpsite/simplesaml would point to ~/Sites/simplesamlphp/www.

It took some trial and error, but I ended up with these configurations:

First I uncommented the following line in the /etc/apache2/httpd.conf file:

Include /private/etc/apache2/extra/httpd-vhosts.conf

Then I went to that file and changed the following line from this:

NameVirtualHost *:80

to this:

NameVirtualHost 127.0.0.1:80

and, added this:

<VirtualHost phpsite>
DocumentRoot "/Users/sysadmin/Sites/phpsite"
ServerName phpsite
<Directory "/Users/sysadmin/Sites/phpsite">
Options FollowSymLinks MultiViews Includes
AllowOverride All
Order allow,deny
Allow from all
</Directory>
Alias /simplesaml /Users/sysadmin/Sites/simplesamlphp/www
</VirtualHost>

Then I went to my /etc/hosts file and added this line:

127.0.0.1      phpsite

Then, a quick Apache restart and everything was running smoothly.

http://localhost - still points to /Library/WebServer/Documents
http://localhost/~sysadmin/ - still points to ~/Sites/
http://phpsite - points to ~/Sites/phpsite
http://phpsite/simplesaml - points to ~/Sites/simplesamlphp/www

Obviously you wouldn’t want to configure it this way if this was a production server, but when I’m doing development work like this I’d prefer to keep everything under my own home folder.

Thursday, February 18, 2010

DRY up your content using ASP.NET user controls


I was doing a little code-cleanup on an app I support this week.  I was trying to find some places where I could implement the DRY (don't repeat yourself) methodology.  It was fairly easy picking, because this app is leaning a little more toward the RYE (repeat yourself everywhere) methodology.  Anyway, I came up with a way to use ASP.NET User Controls in a project to move some of that repetitive content out of the individual pages, and into a centralized place.

This may not be anything new to anyone, but I had never thought of using a user control for content.  I created two controls, one for some contact information that was used on every page (pointing to different departments in the company), and one to encapsulate some page framework that needed to be slightly different depending on where the application was deployed (I was able to put this logic into the user control and read the location from the web.config).

The contact control renders asp labels to display content on the page, and the framework control renders standard divs.  The code had to be slightly different in the code-behind to search for the controls, but once you set up the controls this way, you wouldn't need to ever change the c# code if you wanted to add a new label or div to the .ascx file.

Anyway, like I said I just came up with this idea earlier this week, but I'm anxious to add it to the toolkit.  I'm already thinking of some more uses for this.  You could perhaps have a 'snippets.ascx' file that had all the reusable content, and enclose each piece in a div.  Then all you'd have to do is call the user control in your app with the name of the div you wanted to render.

i.e. <userControl:Snippets ID="SnippetControl" DivID="WhateverDivIwantToShow" runat="server" />

I'll add the relevant code.  Should be easy to see what I'm talking about.

------------------------------------------------------------------


front-end for user control to deterministically expose asp label controls:

<asp:Label ID="Payroll" Visible="false" runat="server">
<p>
    For questions regarding the content of your documents contact the Payroll Department at 555-5555.
</p>
</asp:Label>

<asp:Label ID="HelpDesk" Visible="false" runat="server">
<p>
    For technical questions or support please contact the Help Desk at 555-5555.
</p>
</asp:Label>


   
c# code-behind for user control:

public partial class Contact : System.Web.UI.UserControl
{
    string strLabelID = string.Empty;

    public string LabelID
    {
        get
        {
            return strLabelID;
        }
        set
        {
            strLabelID = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in Controls)
        {
            if (ctrl is Label)
            {
                if (ctrl.ID == strLabelID)
                {
                    ctrl.Visible = true;
                }
            }
        }
    }
}



usage of control:

<ucContact:Contact ID="PayrollContact" LabelID="Payroll" runat="server" />

<ucContact:Contact ID="HelpDeskContact" LabelID="HelpDesk" runat="server" />

------------------------------------------------------------------------------

Another Example:

front-end for user control to deterministically expose generic div elements:

<div id="Header" visible="false" runat="server">
    put stuff in here for the header
</div>

<div id="Footer" visible="false" runat="server">
    put stuff in here for the footer
</div>



c# code-behind for user control:

public partial class PortalFramework : System.Web.UI.UserControl
{
    private string strDivID = string.Empty;

    public string DivID
    {
        get
        {
            return strDivID;
        }
        set
        {
            strDivID = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in Controls)
        {
            if (ctrl is HtmlGenericControl)
            {
                if (ctrl.ID == strDivID)
                {
                    ctrl.Visible = true;
                }
            }
        }
    }
}



usage of control:

<ucFramework:PortalFramework ID="PortalFrameworkHeader" runat="server" DivID="Header" />

<ucFramework:PortalFramework ID="PortalFrameworkFooter" runat="server" DivID="Footer" />

Friday, December 18, 2009

Forray into xsl

This summary is not available. Please click here to view the post.

Tuesday, September 22, 2009

TestDisk to the rescue!

Last night I had a serious problem with my netbook. I'm running Ubuntu on a Dell mini with most of the data on an SD card. Anyway, I think the SD card got messed up when the machine went into hibernation, and when I opened the lid I was getting cryptic messages about the drive not being able to mount. I tried the usual tools, fsck, dumpe2fs, gpart, etc. Nothing doing. Everything that was working for other people wasn't working for me... Kept researching the messages I was getting from the various tools:

Block bitmap for group 1 not in group

Bad Magic Number in Superblock

Disk doesn't contain a valid partition table

etc. etc.

The last one ended up being the clue. Found a utility called TestDisk and it had me fixed up in less than 15 minutes.

http://www.cgsecurity.org/wiki/TestDisk_Step_By_Step

It was able to figure out the partitions based on the good data still on the disk. Then it was just a matter of using the tool to rewrite the partition table and I was back in business!

Wednesday, July 22, 2009

Receiving a SAML Response with a Java servlet

As an addendum to my previous post, if you need to receive a SAML Response in a Java servlet using OpenSAML you can use this code. This is, obviously, more likely than needing to create a Response object from an XML file. The 'request' variable is just an input to the processRequest method on the servlet.

import org.opensaml.ws.message.MessageContext;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
import org.opensaml.saml2.core.Response;

//get the message context
MessageContext messageContext = new BasicSAMLMessageContext();
messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
HTTPPostDecoder samlMessageDecoder = new HTTPPostDecoder();
samlMessageDecoder.decode(messageContext);

//get the SAML Response
Response samlResponse = (Response)messageContext.getInboundMessage();

Monday, July 6, 2009

Processing SAML in Java using OpenSAML

I'm currently doing all of my SAML 2.0 work in a .NET environment, but I wanted to verify my SAML in Java too so I created this tester utilizing OpenSAML. It certainly isn't pretty at this point, and I'm certainly not saying it represents any best-practices, but I'm going to post it in its current state because I think it illustrates some useful things. It's basically just unmarshalling xml to an OpenSAML response object, verifying the signature on the response, and decrypting an assertion. Nothing terribly mind-blowing, but it might prove useful to someone.

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.validation.Schema;

import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.X509EncodedKeySpec;

import org.opensaml.DefaultBootstrap;
import org.opensaml.common.xml.SAMLSchemaBuilder;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.encryption.DecryptionException;
import org.opensaml.xml.encryption.InlineEncryptedKeyResolver;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.parse.BasicParserPool;
import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver;
import org.opensaml.xml.security.x509.BasicX509Credential;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureValidator;
import org.opensaml.xml.validation.ValidationException;


public class Tester
{
public static void main(String[] args)
{
try
{
//initialize the opensaml library
DefaultBootstrap.bootstrap();

Schema schema = SAMLSchemaBuilder.getSAML11Schema();

//get parser pool manager
BasicParserPool parserPoolManager = new BasicParserPool();
parserPoolManager.setNamespaceAware(true);
parserPoolManager.setIgnoreElementContentWhitespace(true);
parserPoolManager.setSchema(schema);

//grab the xml file
File xmlFile = new File("C:\\Documents and Settings\\kgellis\\My Documents\\Eclipse\\Workspace\\MyOpenSamlTester\\Files\\Raw_AssertionEncrypted.xml");

//parse xml file
FileInputStream fileInputStream = new FileInputStream(xmlFile);
InputStream inputStream = fileInputStream;
Document document = parserPoolManager.parse(inputStream);
Element metadataRoot = document.getDocumentElement();

QName qName= new QName(metadataRoot.getNamespaceURI(), metadataRoot.getLocalName(), metadataRoot.getPrefix());

//get an unmarshaller
Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(qName);

//unmarshall using the document root element
Response response = (Response)unmarshaller.unmarshall(metadataRoot);

//we have the xml unmarshalled to a response object
System.out.println("Response object created");
System.out.println("Issue Instant: " + response.getIssueInstant().toString());
System.out.println("Signature Reference ID: " + response.getSignatureReferenceID().toString());

//grab the certificate file
File certificateFile = new File("C:\\Documents and Settings\\kgellis\\My Documents\\Eclipse\\Workspace\\MyOpenSamlTester\\Files\\Con-wayPublicKey.cer");

//get the certificate from the file
InputStream inputStream2 = new FileInputStream(certificateFile);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate certificate = (X509Certificate)certificateFactory.generateCertificate(inputStream2);
inputStream2.close();

//pull out the public key part of the certificate into a KeySpec
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(certificate.getPublicKey().getEncoded());

//get KeyFactory object that creates key objects, specifying RSA
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
System.out.println("Security Provider: " + keyFactory.getProvider().toString());

//generate public key to validate signatures
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

//we have the public key
System.out.println("Public Key created");

//create credentials
BasicX509Credential publicCredential = new BasicX509Credential();

//add public key value
publicCredential.setPublicKey(publicKey);

//create SignatureValidator
SignatureValidator signatureValidator = new SignatureValidator(publicCredential);

//get the signature to validate from the response object
Signature signature = response.getSignature();

//try to validate
try
{
signatureValidator.validate(signature);
}
catch (ValidationException ve)
{
System.out.println("Signature is NOT valid.");
System.out.println(ve.getMessage());
return;
}

//no validation exception was thrown
System.out.println("Signature is valid.");

//start decryption of assertion

//grab the KeyStore file
File keyStoreFile = new File("C:\\Documents and Settings\\kgellis\\My Documents\\Eclipse\\Workspace\\MyOpenSamlTester\\Files\\WWCPrivateKey.jks");

KeyStore keyStore = KeyStore.getInstance("JKS");

//load up a KeyStore
keyStore.load(new FileInputStream(keyStoreFile), "!c3c0ld".toCharArray());

RSAPrivateKey privateKey = (RSAPrivateKey) keyStore.getKey("pvktmp:bd5ba0e0-9718-48ea-b6e6-32cd9c852d76", "!c3c0ld".toCharArray());

//we have the private key
System.out.println("Private Key created");
System.out.println("Private Key Algorithm: " + privateKey.getAlgorithm());

//create the credential
BasicX509Credential decryptionCredential = new BasicX509Credential();
decryptionCredential.setPrivateKey(privateKey);

StaticKeyInfoCredentialResolver skicr = new StaticKeyInfoCredentialResolver(decryptionCredential);

//create a decrypter
Decrypter decrypter = new Decrypter(null, skicr, new InlineEncryptedKeyResolver());

//decrypt the first (and only) assertion
Assertion decryptedAssertion;

try
{
decryptedAssertion = decrypter.decrypt(response.getEncryptedAssertions().get(0));
}
catch (DecryptionException de)
{
System.out.println("Assertion decryption failed.");
System.out.println(de.getMessage());
return;
}

System.out.println("Assertion decryption succeeded.");
System.out.println("Assertion ID: " + decryptedAssertion.getID());

//loop through the nodes to get what we want
List<AttributeStatement> attributeStatements = decryptedAssertion.getAttributeStatements();
for (int i = 0; i < attributeStatements.size(); i++)
{
List<Attribute> attributes = attributeStatements.get(i).getAttributes();
for (int x = 0; x < attributes.size(); x++)
{
String strAttributeName = attributes.get(x).getDOM().getAttribute("Name");

List<XMLObject> attributeValues = attributes.get(x).getAttributeValues();
for (int y = 0; y < attributeValues.size(); y++)
{
String strAttributeValue = attributeValues.get(y).getDOM().getTextContent();
System.out.println(strAttributeName + ": " + strAttributeValue);
}
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}

Friday, May 22, 2009

Passing a variable to Openquery in SQL Server 2005

You'd think that passing a variable to Openquery in SQL Server 2005 would be easy. It isn't. The parser won't parse a string like you think it would. Instead you need to do something like this (and those are all single-quotes):

DECLARE @TSQL varchar(8000), @VAR char(50)
SELECT @VAR = 'XXXXX'
SELECT @TSQL = 'SELECT * FROM OPENQUERY(ConnectionName,''SELECT SomeField FROM SomeTable WHERE AnotherField = ''''' + @VAR + ''''''')'
EXEC (@TSQL)

Ugly, but it works.

Thursday, May 14, 2009

Creating a free public/private key pair in Windows

I recently had to test something with public and private keys. You don't want to have to pay for certificates for testing. Free is better. These commands came in very handy so I'm documenting them here so I don't forget...

Go to this directory (or the equivalent depending on your VS install):
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\

makecert -r -pe -n "cn=kevnls" -b 01/01/2008 -e 01/01/2020 -sky exchange -sv kevnls.pvk kevnls.cer

pvk2pfx -pvk kevnls.pvk -spc kevnls.cer -pfx kevnls.pfx -po somepassword

Edit: If you need a java keystore (.jks) instead of a .pvk file you can do this using the keytool in the jre (usually in C:\Program Files\Java\jre6\bin\).


./keytool -genkey -keyalg RSA -alias somealias -keystore kevnls.jks -storepass somepassword -validity 7300 -keysize 2048

./keytool -export -keystore keystore.jks -alias somealias -file kevnls.cer

Monday, March 30, 2009

Combining PDFs with Ruby in OS X

I recently had to write a fairly complex script using Ruby to match-up and combine PDF documents. I thought I'd share the command I used to do the PDF work as I matched up the files. It uses an automator action that comes default in OS X Leopard.

Here's the relevant code snippet:

filepath1 = folder1 + "/" + filename1
filepath2 = folder2 + "/" + filename2
outfilepath = folder3 + "/" + filename3

command = "python '/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py' -o '" + outfilepath + "' '" + filepath2 + "' '" + filepath1 + "'"

`#{ command }`

I think you can see how it works with that much code. It currently is complaining about a deprecated call somewhere in the automator action, but it doesn't affect the outcome, and it will hopefully go away in a future release.