| 
60 | 60 |                         placeholder="Leave blank for default graph"  | 
61 | 61 |                       />  | 
62 | 62 |                       <div class="invalid-feedback">  | 
63 |  | -                        Invalid graph name. Please remove any spaces.  | 
 | 63 | +                        Invalid graph name. Please remove any spaces and encoded values.  | 
64 | 64 |                       </div>  | 
65 | 65 |                     </div>  | 
66 | 66 |                   </div>  | 
@@ -325,7 +325,8 @@ export default {  | 
325 | 325 |       }  | 
326 | 326 |       const params = (this.datasetGraphName && this.datasetGraphName !== '') ? `?graph=${this.datasetGraphName}` : ''  | 
327 | 327 |       const dataEndpoint = this.services['gsp-rw']['srv.endpoints'].find(endpoint => endpoint !== '') || ''  | 
328 |  | -      return this.$fusekiService.getFusekiUrl(`/${this.datasetName}/${dataEndpoint}${params}`)  | 
 | 328 | +      const fusekiUrl = this.$fusekiService.getFusekiUrl(`/${this.datasetName}/${dataEndpoint}${params}`)  | 
 | 329 | +      return fusekiUrl  | 
329 | 330 |     },  | 
330 | 331 |     uploadCount () {  | 
331 | 332 |       if (!this.upload || !this.upload.files) {  | 
@@ -416,15 +417,33 @@ export default {  | 
416 | 417 |       return this.validateGraphName() && this.validateFiles()  | 
417 | 418 |     },  | 
418 | 419 |     validateGraphName () {  | 
419 |  | -      // No spaces allowed in graph names.  | 
420 |  | -      const pattern = /^[^\s]+$/  | 
421 | 420 |       const graphName = this.$refs['dataset-graph-name'].value  | 
422 |  | -      if (graphName === '' || pattern.test(graphName)) {  | 
 | 421 | +      // An empty graph name is OK.  | 
 | 422 | +      if (graphName === '') {  | 
423 | 423 |         this.graphNameClasses = ['form-control is-valid']  | 
424 | 424 |         return true  | 
425 | 425 |       }  | 
426 |  | -      this.graphNameClasses = ['form-control is-invalid']  | 
427 |  | -      return false  | 
 | 426 | +      // No spaces allowed in graph names.  | 
 | 427 | +      const pattern = /^\S+$/  | 
 | 428 | +      if (!pattern.test(graphName)) {  | 
 | 429 | +        this.graphNameClasses = ['form-control is-invalid']  | 
 | 430 | +        return false  | 
 | 431 | +      }  | 
 | 432 | +      // Only valid URIs allowed.  | 
 | 433 | +      try {  | 
 | 434 | +        new URL(graphName)  | 
 | 435 | +      } catch {  | 
 | 436 | +        this.graphNameClasses = ['form-control is-invalid']  | 
 | 437 | +        return false  | 
 | 438 | +      }  | 
 | 439 | +      // Encoded components are not allowed.  | 
 | 440 | +      if (decodeURI(graphName) !== decodeURIComponent(graphName)) {  | 
 | 441 | +        this.graphNameClasses = ['form-control is-invalid']  | 
 | 442 | +        return false  | 
 | 443 | +      }  | 
 | 444 | +      // If it reached this part, then it's a valid graph name.  | 
 | 445 | +      this.graphNameClasses = ['form-control is-valid']  | 
 | 446 | +      return true  | 
428 | 447 |     },  | 
429 | 448 |     validateFiles () {  | 
430 | 449 |       if (this.upload.files !== null && this.upload.files.length > 0) {  | 
 | 
0 commit comments