diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-10-16 11:20:50 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-10-16 16:41:53 +0200 |
commit | 96d7b49621a21e4e9b3eb3c03255f64e1d99fd4d (patch) | |
tree | b037c228d582c1d5a4a4175cd542bd61451177f0 /server/sonar-web/src/main | |
parent | a17989933c05819d61998257e0d5c60805547d80 (diff) | |
download | sonarqube-96d7b49621a21e4e9b3eb3c03255f64e1d99fd4d.tar.gz sonarqube-96d7b49621a21e4e9b3eb3c03255f64e1d99fd4d.zip |
SONAR-11265 use valid-url library to validate urls
Diffstat (limited to 'server/sonar-web/src/main')
4 files changed, 6 insertions, 67 deletions
diff --git a/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx b/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx index 6bacc6727e6..cf5026f87ae 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx +++ b/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { isWebUri } from 'valid-url'; import OrganizationDetailsInput from './OrganizationDetailsInput'; import Step from '../../tutorials/components/Step'; import ValidationForm, { ChildrenProps } from '../../../components/controls/ValidationForm'; @@ -25,7 +26,6 @@ import { translate } from '../../../helpers/l10n'; import { ResetButtonLink, SubmitButton } from '../../../components/ui/buttons'; import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessIcon'; import DropdownIcon from '../../../components/icons-components/DropdownIcon'; -import { isUrl } from '../../../helpers/urls'; import { OrganizationBase } from '../../../app/types'; import { getOrganization } from '../../../api/organizations'; @@ -80,7 +80,7 @@ export default class OrganizationDetailsStep extends React.PureComponent<Props, handleValidate = ({ avatar, name, key, url }: Values) => { const errors: { [P in keyof Values]?: string } = {}; - if (avatar.length > 0 && !isUrl(avatar)) { + if (avatar.length > 0 && !isWebUri(avatar)) { errors.avatar = translate('onboarding.create_organization.avatar.error'); } @@ -92,7 +92,7 @@ export default class OrganizationDetailsStep extends React.PureComponent<Props, errors.key = translate('onboarding.create_organization.organization_name.error'); } - if (url.length > 0 && !isUrl(url)) { + if (url.length > 0 && !isWebUri(url)) { errors.url = translate('onboarding.create_organization.url.error'); } diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/CreateWebhookForm.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/CreateWebhookForm.tsx index 6a76095990f..462df320caa 100644 --- a/server/sonar-web/src/main/js/apps/webhooks/components/CreateWebhookForm.tsx +++ b/server/sonar-web/src/main/js/apps/webhooks/components/CreateWebhookForm.tsx @@ -19,10 +19,10 @@ */ import * as React from 'react'; import { FormikProps } from 'formik'; +import { isWebUri } from 'valid-url'; import ValidationModal from '../../../components/controls/ValidationModal'; import InputValidationField from '../../../components/controls/InputValidationField'; import { Webhook } from '../../../app/types'; -import { isUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; interface Props { @@ -53,7 +53,7 @@ export default class CreateWebhookForm extends React.PureComponent<Props> { errors.url = translate('webhooks.url.required'); } else if (!url.startsWith('http://') && !url.startsWith('https://')) { errors.url = translate('webhooks.url.bad_protocol'); - } else if (!isUrl(url)) { + } else if (!isWebUri(url)) { errors.url = translate('webhooks.url.bad_format'); } return errors; diff --git a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts index 0dc5a089379..f5c9ef90db2 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts @@ -23,8 +23,7 @@ import { getPathUrlAsString, getProjectUrl, getQualityGatesUrl, - getQualityGateUrl, - isUrl + getQualityGateUrl } from '../urls'; const SIMPLE_COMPONENT_KEY = 'sonarqube'; @@ -118,51 +117,3 @@ describe('#getQualityGate(s)Url', () => { }); }); }); - -describe('#isUrl', () => { - it('should be valid', () => { - expect(isUrl('https://localhost')).toBeTruthy(); - expect(isUrl('https://localhost/')).toBeTruthy(); - expect(isUrl('https://localhost:9000')).toBeTruthy(); - expect(isUrl('https://localhost:9000/')).toBeTruthy(); - expect(isUrl('https://foo:bar@localhost:9000')).toBeTruthy(); - expect(isUrl('https://foo@localhost')).toBeTruthy(); - expect(isUrl('http://foo.com/blah_blah')).toBeTruthy(); - expect(isUrl('http://foo.com/blah_blah/')).toBeTruthy(); - expect(isUrl('http://www.example.com/wpstyle/?p=364')).toBeTruthy(); - expect(isUrl('https://www.example.com/foo/?bar=baz&inga=42&quux')).toBeTruthy(); - expect(isUrl('http://userid@example.com')).toBeTruthy(); - expect(isUrl('http://userid@example.com/')).toBeTruthy(); - expect(isUrl('http://userid:password@example.com:8080')).toBeTruthy(); - expect(isUrl('http://userid:password@example.com:8080/')).toBeTruthy(); - expect(isUrl('http://userid@example.com:8080')).toBeTruthy(); - expect(isUrl('http://userid@example.com:8080/')).toBeTruthy(); - expect(isUrl('http://userid:password@example.com')).toBeTruthy(); - expect(isUrl('http://userid:password@example.com/')).toBeTruthy(); - expect(isUrl('http://142.42.1.1/')).toBeTruthy(); - expect(isUrl('http://142.42.1.1:8080/')).toBeTruthy(); - expect(isUrl('http://foo.com/blah_(wikipedia)#cite-1')).toBeTruthy(); - expect(isUrl('http://foo.com/blah_(wikipedia)_blah#cite-1')).toBeTruthy(); - expect(isUrl('http://foo.com/(something)?after=parens')).toBeTruthy(); - expect(isUrl('http://code.google.com/events/#&product=browser')).toBeTruthy(); - expect(isUrl('http://j.mp')).toBeTruthy(); - expect(isUrl('http://foo.bar/?q=Test%20URL-encoded%20stuff')).toBeTruthy(); - expect(isUrl('http://1337.net')).toBeTruthy(); - expect(isUrl('http://a.b-c.de')).toBeTruthy(); - expect(isUrl('http://223.255.255.254')).toBeTruthy(); - expect(isUrl('https://foo_bar.example.com/')).toBeTruthy(); - }); - - it('should not be valid', () => { - expect(isUrl('http://')).toBeFalsy(); - expect(isUrl('http://?')).toBeFalsy(); - expect(isUrl('http://??')).toBeFalsy(); - expect(isUrl('http://??/')).toBeFalsy(); - expect(isUrl('http://#')).toBeFalsy(); - expect(isUrl('http://##')).toBeFalsy(); - expect(isUrl('http://##/')).toBeFalsy(); - expect(isUrl('//')).toBeFalsy(); - expect(isUrl('///')).toBeFalsy(); - expect(isUrl('http:// shouldfail.com')).toBeFalsy(); - }); -}); diff --git a/server/sonar-web/src/main/js/helpers/urls.ts b/server/sonar-web/src/main/js/helpers/urls.ts index de21ce40a5e..ecb965a112a 100644 --- a/server/sonar-web/src/main/js/helpers/urls.ts +++ b/server/sonar-web/src/main/js/helpers/urls.ts @@ -252,15 +252,3 @@ export function getHomePageUrl(homepage: HomePage) { // should never happen, but just in case... return '/projects'; } - -export function isUrl(url: string) { - try { - const elem = document.createElement('a'); - elem.href = url; - return !!(elem.host && elem.hostname && elem.protocol); - } catch (error) { - // both IE11 & Edge throw an exception when a url contains credentials - // is this case let's just pretend the url is fine and pass it to the server for the validation - return true; - } -} |