Custom Validation

The most common validations for uploaded data seem to be JPG and PNG—just enough to make sure that the image really is one of the two, and won't crash horribly in the main application when being parsed. Given that kvalid_string(3) only covers common types, how do we handle custom validation? Let's consider all three types, using the common libgd library to abstract image handling.

Source Code

We could parse directly using libpng and so on, but for the sake of our example, this is a bit easier. Our mission is to make sure that a JPG or PNG file is readable. In our example, we'll create validation functions, register them with a named input field, then access the parsed data in our web application.

To do so, we override the validator as described in khttp_parse(3) (scan down to valid). It notes that the KPAIR_DOUBLE, KPAIR_STRING, and KPAIR_DOUBLE are provided for validators that set the parsed field of struct kpair. However, if our validator sets KPAIR__MAX, we don't use the parsed field at all. The return code of the function will tell whether to bucket the pair in fieldmap (success) or fieldnmap (failure). The web application will then need to know to use the val and valsz if the validated pair instead of the parsed fields.

To wit, we'll need to create the following functions, with the given header file:

#include <gd.h>
int
kvalid_png(struct kpair *kp)
{
  gdImagePtr im;
  int rc;
  im = gdImageCreateFromPngPtr(kp->valsz, kp->val);
  if ((rc = (im != NULL)))
    gdImageDestroy(im);
  kp->type = KPAIR__MAX;
  return rc;
}

int
kvalid_jpeg(struct kpair *kp)
{
  gdImagePtr im;
  int rc;
  im = gdImageCreateFromJpegPtr(kp->valsz, kp->val);
  if ((rc = (im != NULL)))
    gdImageDestroy(im);
  kp->type = KPAIR__MAX;
  return rc;
}

Now we need to hook these into validations. Let's assume that our HTML inputs are called jpeg and png, for simplicity.

enum key {
  KEY_JPEG,
  KEY_PNG,
  KEY__MAX
};

static const struct kvalid keys[KEY__MAX] = {
  { kvalid_jpeg, "jpeg" }, /* KEY_JPEG */
  { kvalid_png, "png" }, /* KEY_PNG */
};

That's it! Now, our application logic can simply check for the existence of KEY_JPEG or KEY_PNG in the fieldmap table of struct kreq, and be guaranteed that the results will be usable (at least by libgd). The valid interface can do all sorts of more complicated things—for example, we could have converted JPEGs, TIFFs, and other formats all into PNG files during validation by reading into a gdImagePtr, then writing the results of gdImagePngPtr into the val and valsz members. These would then be written into the validated data, and all of our images would then be PNG.