Skip to content

Commit

Permalink
Merge pull request #1510 from Shudrum/dataUri
Browse files Browse the repository at this point in the history
Data uri validation
  • Loading branch information
Marsup committed Jun 29, 2018
2 parents 2391f72 + 52fd99b commit 8b39221
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 0 deletions.
11 changes: 11 additions & 0 deletions API.md
Expand Up @@ -131,6 +131,7 @@
- [`string.guid()` - aliases: `uuid`](#stringguid---aliases-uuid)
- [`string.hex([options])`](#stringhexoptions)
- [`string.base64([options])`](#stringbase64options)
- [`string.dataUri()`](#stringdatauri)
- [`string.hostname()`](#stringhostname)
- [`string.normalize([form])`](#stringnormalizeform)
- [`string.lowercase()`](#stringlowercase)
Expand Down Expand Up @@ -2100,6 +2101,16 @@ paddingOptionalSchema.validate('VE9PTUFOWVNFQ1JFVFM'); // No Error
paddingOptionalSchema.validate('VE9PTUFOWVNFQ1JFVFM='); // No Error
```

#### `string.dataUri()`

Requires the string value to be a valid data URI string.

```js
const schema = Joi.string().dataUri();
schema.validate('VE9PTUFOWVNFQ1JFVFM='); // ValidationError: "value" must be a valid dataUri string
schema.validate('data:image/png;base64,VE9PTUFOWVNFQ1JFVFM='); // No Error
```

#### `string.hostname()`

Requires the string value to be a valid hostname as per [RFC1123](http://tools.ietf.org/html/rfc1123).
Expand Down
1 change: 1 addition & 0 deletions lib/language.js
Expand Up @@ -147,6 +147,7 @@ exports.errors = {
hex: 'must only contain hexadecimal characters',
hexAlign: 'hex decoded representation must be byte aligned',
base64: 'must be a valid base64 string',
dataUri: 'must be a valid dataUri string',
hostname: 'must be a valid hostname',
normalize: 'must be unicode normalized in the {{form}} form',
lowercase: 'must only contain lowercase characters',
Expand Down
30 changes: 30 additions & 0 deletions lib/types/string/index.js
Expand Up @@ -468,6 +468,36 @@ internals.String = class extends Any {
});
}

dataUri(dataUriOptions = {}) {

const regex = /^data:[\w\/\+]+;((charset=[\w-]+|base64),)?(.*)$/;

// Determine if padding is required.
const paddingRequired = dataUriOptions.paddingRequired === false ?
dataUriOptions.paddingRequired
: dataUriOptions.paddingRequired || true;

const base64regex = paddingRequired ?
/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/
: /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}(==)?|[A-Za-z0-9+\/]{3}=?)?$/;

return this._test('dataUri', regex, function (value, state, options) {

const matches = value.match(regex);

if (matches &&
matches[2] === 'base64' &&
base64regex.test(matches[3])) {
return value;
}
else if (matches && (!matches[2] || matches[2] !== 'base64')) {
return value;
}

return this.createError('string.dataUri', { value }, state, options);
});
}

hostname() {

const regex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
Expand Down
191 changes: 191 additions & 0 deletions test/types/string.js
Expand Up @@ -10104,6 +10104,197 @@ describe('string', () => {
]);
});

it('validates a dataUri string', () => {

const rule = Joi.string().dataUri();
Helper.validate(rule, [
['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', true],
['ata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'ata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', true],
['base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'data:base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;base64,=YW55IGNhcm5hbCBwbGVhc3VyZS4', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'data:image/png;base64,=YW55IGNhcm5hbCBwbGVhc3VyZS4',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;base64,YW55IGNhcm5hbCBwbGVhc3VyZS4=', true],
['data:image/png;charset=utf-8,=YW55IGNhcm5hbCBwbGVhc3VyZS', true]
]);
});

it('validates a dataUri string with padding explicitly required', () => {

const rule = Joi.string().dataUri({ paddingRequired: true });
Helper.validate(rule, [
['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', true],
['ata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'ata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', true],
['base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'data:base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;base64,=YW55IGNhcm5hbCBwbGVhc3VyZS4', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'data:image/png;base64,=YW55IGNhcm5hbCBwbGVhc3VyZS4',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;base64,YW55IGNhcm5hbCBwbGVhc3VyZS4=', true],
['data:image/png;charset=utf-8,=YW55IGNhcm5hbCBwbGVhc3VyZS', true]
]);

});

it('validates a dataUri string with padding not required', () => {

const rule = Joi.string().dataUri({ paddingRequired: false });
Helper.validate(rule, [
['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', true],
['ata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'ata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', true],
['base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'data:base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAABJRU5ErkJggg==',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;base64,=YW55IGNhcm5hbCBwbGVhc3VyZS4', false, null, {
message: '"value" must be a valid dataUri string',
details: [{
message: '"value" must be a valid dataUri string',
path: [],
type: 'string.dataUri',
context: {
value: 'data:image/png;base64,=YW55IGNhcm5hbCBwbGVhc3VyZS4',
label: 'value',
key: undefined
}
}]
}],
['data:image/png;base64,YW55IGNhcm5hbCBwbGVhc3VyZS4=', true],
['data:image/png;charset=utf-8,=YW55IGNhcm5hbCBwbGVhc3VyZS', true]
]);

});

it('validates combination of uppercase, min, max, alphanum and valid', () => {

const rule = Joi.string().uppercase().min(2).max(3).alphanum().valid('AB', 'BC');
Expand Down

0 comments on commit 8b39221

Please sign in to comment.