diff --git a/package-lock.json b/package-lock.json
index 5627f66a..b4036992 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "purplea11ydesktop",
- "version": "0.9.40",
+ "version": "0.9.41",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "purplea11ydesktop",
- "version": "0.9.40",
+ "version": "0.9.41",
"dependencies": {
"axios": "^1.6.0",
"fs-extra": "^11.1.1",
diff --git a/package.json b/package.json
index 20244242..977c5e43 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "purplea11ydesktop",
"productName": "Purple A11y",
- "version": "0.9.40",
+ "version": "0.9.41",
"private": true,
"dependencies": {
"axios": "^1.6.0",
diff --git a/public/electron/scanManager.js b/public/electron/scanManager.js
index 6b5fa53f..d51d9a76 100644
--- a/public/electron/scanManager.js
+++ b/public/electron/scanManager.js
@@ -58,6 +58,7 @@ const getScanOptions = (details) => {
falsePositive,
includeScreenshots,
includeSubdomains,
+ followRobots,
metadata,
} = details;
const options = ["-c", scanType, "-u", url, "-k", `${name}:${email}`, "-i", fileTypes];
@@ -108,6 +109,10 @@ const getScanOptions = (details) => {
options.push("-f", "true");
}
+ if (followRobots) {
+ options.push("-r", "yes");
+ }
+
if (metadata) {
options.push("-q", metadata);
}
diff --git a/src/MainWindow/CustomFlow/index.jsx b/src/MainWindow/CustomFlow/index.jsx
index af6b56a3..846e837f 100644
--- a/src/MainWindow/CustomFlow/index.jsx
+++ b/src/MainWindow/CustomFlow/index.jsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router";
-import { cliErrorCodes, cliErrorTypes } from "../../common/constants";
+import { cliErrorCodes, cliErrorTypes, errorStates } from "../../common/constants";
import services from "../../services";
import './CustomFlow.scss';
import arrowLeft from "../../assets/arrow-left-purple.svg";
@@ -195,7 +195,7 @@ const CustomFlowPage = ({ completedScanId, setCompletedScanId }) => {
return;
}
- navigate("/error", {state: { isCustomScan: true }});
+ navigate("/error", {state: { errorState: errorStates.customScanError }});
return;
}
diff --git a/src/MainWindow/ErrorPage/ErrorPage.scss b/src/MainWindow/ErrorPage/ErrorPage.scss
index 467e81f6..152d6baa 100644
--- a/src/MainWindow/ErrorPage/ErrorPage.scss
+++ b/src/MainWindow/ErrorPage/ErrorPage.scss
@@ -29,8 +29,9 @@
background-color: transparent;
}
- .actions {
+ .btn-container {
display: flex;
+ align-items: center;
justify-content: center;
}
}
diff --git a/src/MainWindow/ErrorPage/index.jsx b/src/MainWindow/ErrorPage/index.jsx
index fb62c27b..bbb4d834 100644
--- a/src/MainWindow/ErrorPage/index.jsx
+++ b/src/MainWindow/ErrorPage/index.jsx
@@ -5,21 +5,15 @@ import returnIcon from "../../assets/return-purple.svg";
import { useNavigate, useLocation } from "react-router";
import { ReactComponent as ExclamationCircleIcon } from "../../assets/exclamation-circle.svg";
import { useState, useEffect } from "react";
+import { errorStates } from "../../common/constants";
const ErrorPage = () => {
const { state } = useLocation();
const navigate = useNavigate();
- const [isCustomScan, setIsCustomScan] = useState(false);
- const [isBrowserError, setIsBrowserError] = useState(false);
+ const [ errorState, setErrorState ] = useState('');
useEffect(() => {
- if (state?.isCustomScan) {
- setIsCustomScan(state.isCustomScan);
- }
-
- if (state?.isBrowserError) {
- setIsBrowserError(state.isBrowserError);
- }
+ if (state?.errorState) setErrorState(state.errorState);
}, []);
const replayCustomFlow = async () => {
@@ -28,7 +22,7 @@ const ErrorPage = () => {
};
const handleBackToHome = () => {
- if (isCustomScan) {
+ if (errorState === errorStates.customScanError) {
window.services.cleanUpCustomFlowScripts();
window.localStorage.removeItem("latestCustomFlowGeneratedScript");
window.localStorage.removeItem("latestCustomFlowScanDetails");
@@ -37,35 +31,47 @@ const ErrorPage = () => {
return;
}
+ const errorMessageToDisplay = () => {
+ switch (errorState) {
+ case errorStates.browserError:
+ return (
+ <>
+
Unable to use browser to scan
+ Please close either Google Chrome or Microsoft Edge browser.
+ >
+ )
+ case errorStates.noPagesScannedError:
+ return (<>No pages were scanned.
>)
+ default:
+ return (<>Something went wrong! Please try again.
>)
+ }
+
+ }
+
return (
}
/>
- {isBrowserError
- ? <>
-
Unable to use browser to scan
-
Please close either Google Chrome or Microsoft Edge browser.
- >
- :
Something went wrong! Please try again.
- }
-
- {isCustomScan
- ? (
- <>
-
-
- >
- )
- :
}
+ {errorMessageToDisplay()}
+
+ {errorState === errorStates.customScanError
+ ? (
+ <>
+
+
+ >
+ )
+ :
+ }
);
diff --git a/src/MainWindow/HomePage/AdvancedScanOptions.jsx b/src/MainWindow/HomePage/AdvancedScanOptions.jsx
index 581e6862..73e12c36 100644
--- a/src/MainWindow/HomePage/AdvancedScanOptions.jsx
+++ b/src/MainWindow/HomePage/AdvancedScanOptions.jsx
@@ -226,42 +226,58 @@ const AdvancedScanOptions = ({
{advancedOptions.scanType !== scanTypeOptions[3] && (
-
-
handleMaxConcurrencyOnFocus()}
- onBlur={() => setShowMaxConcurrencyTooltip(false)}
- onMouseEnter={() => handleMaxConcurrencyOnMouseEnter()}
- onMouseLeave={() => setIsMaxConcurrencyMouseEvent(false)}
- onChange={handleSetAdvancedOption(
- "maxConcurrency",
- (e) => e.target.checked
- )}
- />
-
-
-
-
-
+
+
setShowMaxConcurrencyTooltip(true)}
- onMouseLeave={() => setShowMaxConcurrencyTooltip(false)}
- alt="tooltip icon for slow scan mode"
+ checked={advancedOptions.maxConcurrency}
+ onFocus={() => handleMaxConcurrencyOnFocus()}
+ onBlur={() => setShowMaxConcurrencyTooltip(false)}
+ onMouseEnter={() => handleMaxConcurrencyOnMouseEnter()}
+ onMouseLeave={() => setIsMaxConcurrencyMouseEvent(false)}
+ onChange={handleSetAdvancedOption(
+ "maxConcurrency",
+ (e) => e.target.checked
+ )}
/>
+
+
+
+
setShowMaxConcurrencyTooltip(true)}
+ onMouseLeave={() => setShowMaxConcurrencyTooltip(false)}
+ alt="tooltip icon for slow scan mode"
+ />
+
-
+
+ e.target.checked
+ )}
+ />
+
+
+ >
)}
diff --git a/src/MainWindow/HomePage/HomePage.scss b/src/MainWindow/HomePage/HomePage.scss
index ded00aa7..621a98ef 100644
--- a/src/MainWindow/HomePage/HomePage.scss
+++ b/src/MainWindow/HomePage/HomePage.scss
@@ -164,7 +164,8 @@
#false-positive-toggle-group,
#screenshots-toggle-group,
- #subdomain-toggle-group {
+ #subdomain-toggle-group,
+ #max-concurrency-toggle-group {
margin-bottom: 1rem;
}
diff --git a/src/MainWindow/HomePage/index.jsx b/src/MainWindow/HomePage/index.jsx
index bc4860e6..fba128a1 100644
--- a/src/MainWindow/HomePage/index.jsx
+++ b/src/MainWindow/HomePage/index.jsx
@@ -8,7 +8,7 @@ import labModeOn from "../../assets/lab-icon-on.svg";
import InitScanForm from "./InitScanForm";
import "./HomePage.scss";
import services from "../../services";
-import { cliErrorCodes, cliErrorTypes, versionComparator } from "../../common/constants";
+import { cliErrorCodes, cliErrorTypes, errorStates, versionComparator } from "../../common/constants";
import Modal from "../../common/components/Modal";
import { BasicAuthForm, BasicAuthFormFooter } from "./BasicAuthForm";
import EditUserDetailsModal from "./EditUserDetailsModal";
@@ -195,7 +195,7 @@ const HomePage = ({ isProxy, appVersionInfo, setCompletedScanId }) => {
} else {
/* When no pages were scanned (e.g. out of domain upon redirects when valid URL was entered),
redirects user to error page to going to result page with empty result */
- navigate("/error");
+ navigate("/error", { state: { errorState: errorStates.noPagesScannedError }});
return;
}
}
@@ -223,7 +223,7 @@ const HomePage = ({ isProxy, appVersionInfo, setCompletedScanId }) => {
errorMessageToShow = "Invalid sitemap.";
break;
case cliErrorTypes.browserError:
- navigate('/error', { state: { isBrowserError: true }});
+ navigate('/error', { state: { errorState: errorStates.browserError }});
return;
case cliErrorTypes.systemError:
default:
@@ -250,6 +250,7 @@ const HomePage = ({ isProxy, appVersionInfo, setCompletedScanId }) => {
const scanDetails = JSON.parse(window.localStorage.getItem("scanDetails"));
const splitUrl = scanDetails.scanUrl.split("://");
scanDetails.scanUrl = `${splitUrl[0]}://${username}:${password}@${splitUrl[1]}`;
+ setScanButtonIsClicked(true);
startScan(scanDetails);
setShowBasicAuthModal(false);
return;
diff --git a/src/common/constants.js b/src/common/constants.js
index b8014998..f49b5db3 100644
--- a/src/common/constants.js
+++ b/src/common/constants.js
@@ -88,7 +88,8 @@ export const getDefaultAdvancedOptions = (isProxy) => {
maxConcurrency: false,
falsePositive: false,
includeScreenshots: true,
- includeSubdomains: true
+ includeSubdomains: true,
+ followRobots: false,
}
};
@@ -104,6 +105,12 @@ export const cliErrorTypes = {
browserError: 17,
};
+export const errorStates = {
+ browserError: 'browserError',
+ customScanError: 'customScanError',
+ noPagesScannedError: 'noPagesScannedError'
+}
+
export const userDataFormDetails = {
// production form
// formUrl: "https://form.gov.sg/6453387735eb0c00128becdc",
diff --git a/src/services.js b/src/services.js
index 6aeb8a51..f7870017 100644
--- a/src/services.js
+++ b/src/services.js
@@ -68,6 +68,7 @@ const startScan = async (scanDetails) => {
falsePositive,
includeScreenshots,
includeSubdomains,
+ followRobots,
scanMetadata,
} = scanDetails;
@@ -85,6 +86,7 @@ const startScan = async (scanDetails) => {
fileTypes: fileTypes[selectedFileTypes],
includeScreenshots,
includeSubdomains,
+ followRobots,
metadata: JSON.stringify(scanMetadata),
};