file import got , { Got } from "got" ; import { CSVConf , HTAccessConf } from "./../../culturize.conf" ; const validUrl = require ( "valid-url" ) ; /**
 * This class contains the relevant data of a CSV file row. This is usually
 * used in arrays.
 */ export class CSVRow { public static count : number = 2 ; param { any } row returns public static createRow ( row ) { if ( this . checkColumns ( row ) ) { const columns = [ ] ; columns . push ( 1 + Reflect . ownKeys ( row ) . indexOf ( CSVConf . COL_PID ) ) ; columns . push ( 1 + Reflect . ownKeys ( row ) . indexOf ( CSVConf . COL_DOCTYPE ) ) ; columns . push ( 1 + Reflect . ownKeys ( row ) . indexOf ( CSVConf . COL_URL ) ) ; columns . push ( 1 + Reflect . ownKeys ( row ) . indexOf ( CSVConf . COL_ENABLED ) ) ; return new CSVRow ( row [ CSVConf . COL_PID ] , row [ CSVConf . COL_DOCTYPE ] , row [ CSVConf . COL_URL ] , row [ CSVConf . COL_ENABLED ] , columns ) ; } return null ; } static param { any } row returns private static checkColumns ( row ) { return CSVConf . COL_PID in row && CSVConf . COL_URL in row && ( CSVConf . COL_DOCTYPE in row || CSVConf . ALLOW_NO_DOCTYPE ) && CSVConf . COL_ENABLED in row ; } public index : number ; public columns : string [ ] ; public pid : string ; public docType : string ; public url : string ; public enabled : string ; public valid : boolean ; public error : string [ ] ; public affectedCels : string [ ] ; public urlChecked : boolean ; public urlWorking : boolean ; public duplicateOf : number = - 1 ; constructor param { string } pid param { string } docType param { string } url param { string } enabled param { number [ ] } Column private constructor ( pid , docType , url , enabled , columns ) { this . index = CSVRow . count ; CSVRow . count += 1 ; this . columns = [ ] ; for ( let index of columns ) { let column = "" ; if ( index > 26 ) { column += String . fromCharCode ( 64 + Math . floor ( index / 26 ) ) ; } if ( index % 26 === 0 ) { column += "Z" ; } index %= 26 ; if ( index > 0 ) { column += String . fromCharCode ( 64 + index ) ; } this . columns . push ( column ) ; } this . pid = pid . trim ( ) ; if ( docType != null ) { this . docType = docType . trim ( ) ; } else { this . docType = "" ; } this . url = url . trim ( ) ; this . enabled = enabled . trim ( ) ; this . error = [ ] ; this . affectedCels = [ ] ; this . valid = this . isValid ( ) ; this . urlChecked = false ; this . urlWorking = false ; } static param { any } row returns public isValidAndEnabled ( ) { return this . valid && this . enabled === "1" ; } static param { number } othIndex returns public markAsDuplicateOf ( othIndex ) { this . error . push ( "E07" ) ; this . duplicateOf = othIndex ; if ( this . affectedCels . indexOf ( "duplicate" ) === - 1 ) { this . affectedCels . push ( "duplicate" ) ; } } returns public async checkURL ( ) { if ( this . error . indexOf ( "E04" ) !== - 1 ) { return ; } try { this . urlChecked = true ; const result = await got ( this . url , { method : "HEAD" , throwHttpErrors : false , timeout : 2000 , https : { rejectUnauthorized : false } } ) ; if ( result . statusCode !== 200 ) { this . urlWorking = false ; this . error . push ( "E06" ) ; } else { this . urlWorking = true ; } } catch ( error ) { console . log ( "error in HTTP request" ) ; this . urlWorking = false ; this . error . push ( "E06" ) ; } } returns public createHTMLRow ( ) { let enabledCel ; if ( this . error . indexOf ( "E05" ) !== - 1 ) { enabledCel = `<td class="error" title="not 0 or 1">${ this . enabled }</td>` ; } else { enabledCel = `<td>${ this . enabled }</td>` ; } let doctypeCel ; if ( this . error . indexOf ( "E02" ) !== - 1 ) { doctypeCel = `<td class="error" title="Invalid characters">${ this . docType }</td>` ; } else if ( this . error . indexOf ( "E03" ) !== - 1 ) { doctypeCel = `<td class="error" title="No document type specified">${ this . docType }</td>` ; } else { doctypeCel = `<td>${ this . docType }</td>` ; } let pidCel ; if ( this . error . indexOf ( "E01" ) !== - 1 ) { pidCel = `<td class="error" title="Invalid characters">${ this . pid }</td>` ; } else { pidCel = `<td>${ this . pid }</td>` ; } let urlCel ; if ( this . error . indexOf ( "E04" ) !== - 1 ) { if ( this . url === "" ) { urlCel = `<td class="error" title="${ this . url }">no URL</td>` ; } else { urlCel = `<td class="error" title="${ this . url }">invalid URL</td>` ; } } else { urlCel = `<td title="${ this . url }">valid URL</td>` ; } let urlCheckCel ; if ( this . urlChecked ) { if ( this . urlWorking ) { urlCheckCel = `<td class="check"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none" /><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="#15B28E"/></svg></td>` ; } else { urlCheckCel = `<td class="check error" title="URL unavailable"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17 7h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1 0 1.43-.98 2.63-2.31 2.98l1.46 1.46C20.88 15.61 22 13.95 22 12c0-2.76-2.24-5-5-5zm-1 4h-2.19l2 2H16zM2 4.27l3.11 3.11C3.29 8.12 2 9.91 2 12c0 2.76 2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1 0-1.59 1.21-2.9 2.76-3.07L8.73 11H8v2h2.73L13 15.27V17h1.73l4.01 4L20 19.74 3.27 3 2 4.27z "/><path d="M0 24V0" fill="none"/></svg></td>` ; } } else { urlCheckCel = `<td class="check" title="URL not tested"><svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/></svg></td>` ; } let affectedCel ; if ( this . error . indexOf ( "E07" ) !== - 1 ) { affectedCel = `<td class="error" title="doctype, pid combination is duplicate of row ${ this . duplicateOf }">${ this . affectedCels . join ( "," ) }</td>` ; } else { affectedCel = `<td>${ this . affectedCels . join ( "," ) }</td>` ; } return `<tr class="${ this . error . length > 0 ? "invalid" : "valid" }">` + `<td>${ this . index }</td>` + enabledCel + doctypeCel + pidCel + urlCel + affectedCel + urlCheckCel + `</tr>\n` ; } returns private isValid ( ) { param { string } text returns const fn = ( text ) : boolean => { return /^([a-z]|[A-Z]|[0-9]|-|_)+$/ . test ( text ) ; } ; let retval = true ; if ( ! fn ( this . pid ) ) { this . error . push ( "E01" ) ; this . affectedCels . push ( `${ this . columns [ 0 ] }${ this . index }` ) ; retval = false ; } if ( this . docType !== "" ) { if ( ! fn ( this . docType ) ) { this . error . push ( "E02" ) ; this . affectedCels . push ( `${ this . columns [ 1 ] }${ this . index }` ) ; retval = false ; } } else if ( ! CSVConf . ALLOW_NO_DOCTYPE ) { this . error . push ( "E03" ) ; this . affectedCels . push ( `${ this . columns [ 1 ] }${ this . index }` ) ; retval = false ; } if ( ! validUrl . isWebUri ( this . url ) ) { this . error . push ( "E04" ) ; this . affectedCels . push ( `${ this . columns [ 2 ] }${ this . index }` ) ; retval = false ; } if ( this . enabled !== "1" && this . enabled !== "0" ) { this . error . push ( "E05" ) ; this . affectedCels . push ( `${ this . columns [ 3 ] }${ this . index }` ) ; retval = false ; } return retval ; } }