From b5a22f6fe25b609f61c3239eb577e9e64609a459 Mon Sep 17 00:00:00 2001 From: tom-reith Date: Sat, 19 Nov 2022 23:03:11 +0100 Subject: [PATCH] CATTY-643 Show warning for downloaded project that contains Web request bricks --- src/Catty.xcodeproj/project.pbxproj | 96 +++++++------- src/Catty/DataModel/Bricks/Brick.h | 2 + src/Catty/DataModel/Bricks/Brick.m | 5 + .../Bricks/Data/WebRequestBrick.swift | 4 + .../Defines/KeychainUserDefaultsDefines.h | 2 + .../Defines/LanguageTranslationDefines.h | 2 + .../LanguageTranslationDefinesSwift.swift | 2 + .../SceneTableViewControllerExtension.swift | 55 +++++++- .../Localization/en.lproj/Localizable.strings | 6 + .../Continue&New/SceneTableViewController.m | 1 + .../Bricks/WebRequestWarningBrickTest.swift | 123 ++++++++++++++++++ .../LanguageTranslationDefinesUI.swift | 2 + 12 files changed, 253 insertions(+), 47 deletions(-) create mode 100644 src/CattyTests/Bricks/WebRequestWarningBrickTest.swift diff --git a/src/Catty.xcodeproj/project.pbxproj b/src/Catty.xcodeproj/project.pbxproj index 2dddb92160..89e24a8aaf 100644 --- a/src/Catty.xcodeproj/project.pbxproj +++ b/src/Catty.xcodeproj/project.pbxproj @@ -118,6 +118,7 @@ 18E83F832493C4C3003295DA /* PenClearBrick+CBXMLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E83F822493C4C3003295DA /* PenClearBrick+CBXMLHandler.swift */; }; 18E83F852493C978003295DA /* PenClearBrickTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E83F842493C978003295DA /* PenClearBrickTests.swift */; }; 18E908A82624995900EF57D6 /* FormulaEditorComputeDialogTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E908A72624995900EF57D6 /* FormulaEditorComputeDialogTest.swift */; }; + 1AB763002969DFF000D01FBA /* WebRequestWarningBrickTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB762FF2969DFF000D01FBA /* WebRequestWarningBrickTest.swift */; }; 2219ED8D2519EB8100EBA379 /* NSMutableArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2219ED89251745EA00EBA379 /* NSMutableArrayExtension.swift */; }; 222A6934247E43AB004BE434 /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA2D44451B123B7E00A3B53D /* Util.swift */; }; 22412CFE26ECE5B70074915C /* PaddingLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22412CFD26ECE5B70074915C /* PaddingLabel.swift */; }; @@ -2232,6 +2233,7 @@ 18E83F842493C978003295DA /* PenClearBrickTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenClearBrickTests.swift; sourceTree = ""; }; 18E908A72624995900EF57D6 /* FormulaEditorComputeDialogTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormulaEditorComputeDialogTest.swift; sourceTree = ""; }; 18EF8F4D5C0ED599CBA2B488 /* vi */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; + 1AB762FF2969DFF000D01FBA /* WebRequestWarningBrickTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebRequestWarningBrickTest.swift; sourceTree = ""; }; 1B5E0F4EFA8B76CD707F0556 /* ur */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = ur; path = ur.lproj/Localizable.strings; sourceTree = ""; }; 1C035A070A526C061039C146 /* ha */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = ha; path = ha.lproj/Localizable.strings; sourceTree = ""; }; 1C557E56F94895CB30ED2558 /* en-CA */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/Localizable.strings"; sourceTree = ""; }; @@ -7562,96 +7564,97 @@ 4CEB222C1B95E47500B3BE2F /* Bricks */ = { isa = PBXGroup; children = ( - 0581B73127BAA58D0098BDF8 /* StopCurrentStitchBrickTests.swift */, - 0594CE65275E567D007DC3F9 /* SewUpBrickTests.swift */, 4C16042D1F0025F6004525A5 /* Abstract */, + E57E6D8E2540552F00E775DF /* AddItemToUserListBrickTests.swift */, + 4C5AEEFA22F6F92B00280F8B /* ArduinoBrickTests.swift */, + E592D1552539DD6A00B9F288 /* ArduinoSendDigitalValueBrickTests.swift */, + E592D1592539E16400B9F288 /* ArduinoSendPWMValueBrickTests.swift */, + 440B1D58250FE6B10041CC7D /* AskBrickTests.swift */, + D3AF5C18243F6A4C00B04BC6 /* BrickCategoryTest.swift */, + 590200D123FC03A900F0978B /* BrickExtensionTests.swift */, + 4CEB226B1B95E4BC00B3BE2F /* BrickInsertManager */, 4C3746E622FC7AC3007B2BE1 /* BrickManager */, 4CEB222D1B95E47500B3BE2F /* BrickMoveManager */, - 4CEB226B1B95E4BC00B3BE2F /* BrickInsertManager */, - 4C5AEEFA22F6F92B00280F8B /* ArduinoBrickTests.swift */, - 461C7DBF25BA0A0C00E50D69 /* SetBackgroundAndWaitBrickTests.swift */, + 3DA1BED824365A3400133C99 /* BrickMutableCopyTests.swift */, 4C968C3F1F00288500355C0D /* BrickTests.swift */, - 46162CB92544AE2D00DF6042 /* SetRotationStyleBrickTests.swift */, 4C38B3772371531300F33721 /* BubbleBrickTests.swift */, 9E2C2D8F23257704004B66C6 /* ChangeBrightnessByNBrickTests.swift */, 9E2D47C62328428100917D92 /* ChangeColorByNBrickTests.swift */, - 4CD487751ED2C2A3001BB80A /* ChangeVariableBrickTests.swift */, 9E2D47CA232846AD00917D92 /* ChangeSizeByNBrickTests.swift */, 9ECDCB0A2328491F00EBDA63 /* ChangeTransparencyByNBrickTests.swift */, + 4CD487751ED2C2A3001BB80A /* ChangeVariableBrickTests.swift */, + E57E6D84254040B400E775DF /* ChangeVolumeByNBrickTests.swift */, + E579F119253DCD90009107C8 /* ChangeXByNBrickTests.swift */, + E579F11B253DCE2C009107C8 /* ChangeYByNBrickTests.swift */, 4C0F9FD4204BD3C200E71B2D /* ChooseCameraBrickTests.swift */, 9ECDCB0C23284CBE00EBDA63 /* ClearGraphicEffectBrickTests.swift */, 9ECDCB0E2328528D00EBDA63 /* ComeToFrontBrickTests.swift */, 4CB23D6F21E6613D00A0FEA7 /* DeleteItemOfUserListBrickTests.swift */, 4CFD5C5823C47E2100980CD0 /* GlideToBrickTests.swift */, 9E4D2385232AE9E5009D0C3C /* GoNStepsBackBrickTests.swift */, + D3C6E3A724C8134A00A9E186 /* GoToBrickTests.swift */, 9ECDCB122328578F00EBDA63 /* HideBrickTests.swift */, 4CAB10081ECF1A9A0019A67B /* HideTextBrickTests.swift */, - 9E3AF7992326F4D100AB16F1 /* IfOnEdgeBounceBrickTests.swift */, 18A9DBA82434C7F400F4C390 /* IfLogicBeginBrickTests.swift */, + 9E3AF7992326F4D100AB16F1 /* IfOnEdgeBounceBrickTests.swift */, + E592D15B2539E1E300B9F288 /* IfThenLogicBeginBrickTests.swift */, 4CF4CB7221E64BEE009D6DD9 /* InsertItemIntoUserListBrickTests.swift */, 9EA6DCAF2329A9E1007E837A /* MoveNStepsBrickTests.swift */, 9EBCBD822329B44E0074C2D9 /* NextLookBrickTests.swift */, + 18E83F842493C978003295DA /* PenClearBrickTests.swift */, + 186AA34824830491001E38FD /* PenDownBrickTests.swift */, + 186E991C2488FBDB00627E36 /* PenUpBrickTests.swift */, + E579F104253D88B4009107C8 /* PhiroMotorMoveBackwardBrickTests.swift */, + E579F108253D9485009107C8 /* PhiroMotorMoveForwardBrickTests.swift */, + E579F10A253D98B0009107C8 /* PhiroPlayToneBrickTests.swift */, + E579F10C253D9C58009107C8 /* PhiroRGBLightBrickTests.swift */, 9EBCBD842329B73D0074C2D9 /* PlaceAtBrickTests.swift */, 187A3F1F2434BC4300EF1B02 /* PlaySoundAndWaitBrickTests.swift */, 9EBCBD862329BD700074C2D9 /* PointInDirectionBrickTests.swift */, 9EBCBD882329BF5F0074C2D9 /* PointToBrickTests.swift */, - D3C6E3A724C8134A00A9E186 /* GoToBrickTests.swift */, 9EBCBD8A2329C3BF0074C2D9 /* PreviousLookBrickTests.swift */, + 4C1D26601E84EFBD00BAA2D2 /* RepeatBrickTests.swift */, 4C0F9FD8204BD3D500E71B2D /* RepeatUntilBrickTests.swift */, 4CF4CB7621E65A9B009D6DD9 /* ReplaceItemInUserListBrickTests.swift */, + E579F10E253DAF20009107C8 /* SayBubbleBrickTests.swift */, + E579F110253DB124009107C8 /* SayForBubbleBrickTests.swift */, + 461C7DBF25BA0A0C00E50D69 /* SetBackgroundAndWaitBrickTests.swift */, 9ECDCB102328548800EBDA63 /* SetBackgroundBrickTests.swift */, - 187CECAA24314F1600C3EDCA /* SetLookBrickTests.swift */, - 4C1D26601E84EFBD00BAA2D2 /* RepeatBrickTests.swift */, + 83F8230725EBA9610093DD9A /* SetBackgroundByIndexBrickTests.swift */, 9E4D2389232AF24B009D0C3C /* SetBrightnessBrickTests.swift */, 9E4D238B232AF688009D0C3C /* SetColorBrickTests.swift */, 4C514A1025931A1F008A0B78 /* SetInstrumentBrickTests.swift */, + 187CECAA24314F1600C3EDCA /* SetLookBrickTests.swift */, + E5E1E5B32578117400D2F1BC /* SetLookByIndexBrickTests.swift */, + 18D939EA24C97A1C00A32544 /* SetPenColorBrickTests.swift */, + 18B9A1B924A75F3C009028F8 /* SetPenSizeBrickTests.swift */, + 46162CB92544AE2D00DF6042 /* SetRotationStyleBrickTests.swift */, 9EBCBD8C2329C56F0074C2D9 /* SetSizeToBrickTests.swift */, + 971C6F20260526ED00AD4857 /* SetTempoToBrickTests.swift */, 9EBCBD8E2329C7A30074C2D9 /* SetTransparencyBrickTests.swift */, 4CAB100C1ECF1AB20019A67B /* SetVariableBrickTests.swift */, + E57E6D862540414700E775DF /* SetVolumeToBrickTests.swift */, 9E3AF7972326F21300AB16F1 /* SetXBrickTests.swift */, 9E24D7082326ED6C00608203 /* SetYBrickTests.swift */, - 4CAB100E1ECF1AC60019A67B /* ShowTextBrickTests.swift */, + 0594CE65275E567D007DC3F9 /* SewUpBrickTests.swift */, 9E24D7062326EBC300608203 /* ShowBrickTests.swift */, + 4CAB100E1ECF1AC60019A67B /* ShowTextBrickTests.swift */, + E57E6D88254041BE00E775DF /* SpeakAndWaitBrickTests.swift */, + E57E6D8A2540427000E775DF /* SpeakBrickTests.swift */, + 18390A7224D0A33D00A07DFD /* StampBrickTests.swift */, + 0580514826EF734F00F719E0 /* StartRunningStitchBrickTests.swift */, + 056677FA27DF8C4C006B4477 /* StartZigzagStitchBrickTests.swift */, + 46B94F9625791507007E5ABE /* StitchBrickTests.swift */, + 0581B73127BAA58D0098BDF8 /* StopCurrentStitchBrickTests.swift */, + E579F113253DCA96009107C8 /* ThinkBubbleBrickTests.swift */, + E579F117253DCC65009107C8 /* ThinkForBubbleBrickTests.swift */, 9E24D7022326E8E600608203 /* TurnLeftBrickTests.swift */, 9E2C2D9123258F3F004B66C6 /* TurnRightBrickTests.swift */, - 590200D123FC03A900F0978B /* BrickExtensionTests.swift */, 4C1D26641E84F12700BAA2D2 /* VibrationBrickTests.swift */, AA3BD9081BBF4BFB002B34A0 /* WaitBrickTests.swift */, BA584CB9219C8803002CC082 /* WaitUntilBrickTests.swift */, - 3DA1BED824365A3400133C99 /* BrickMutableCopyTests.swift */, - D3AF5C18243F6A4C00B04BC6 /* BrickCategoryTest.swift */, - 186AA34824830491001E38FD /* PenDownBrickTests.swift */, - 186E991C2488FBDB00627E36 /* PenUpBrickTests.swift */, - 46B94F9625791507007E5ABE /* StitchBrickTests.swift */, - 18E83F842493C978003295DA /* PenClearBrickTests.swift */, - 18B9A1B924A75F3C009028F8 /* SetPenSizeBrickTests.swift */, - 18D939EA24C97A1C00A32544 /* SetPenColorBrickTests.swift */, - 18390A7224D0A33D00A07DFD /* StampBrickTests.swift */, - 440B1D58250FE6B10041CC7D /* AskBrickTests.swift */, - E57E6D84254040B400E775DF /* ChangeVolumeByNBrickTests.swift */, - E57E6D862540414700E775DF /* SetVolumeToBrickTests.swift */, - E57E6D88254041BE00E775DF /* SpeakAndWaitBrickTests.swift */, - E57E6D8A2540427000E775DF /* SpeakBrickTests.swift */, - E57E6D8E2540552F00E775DF /* AddItemToUserListBrickTests.swift */, - E592D1552539DD6A00B9F288 /* ArduinoSendDigitalValueBrickTests.swift */, - E592D1592539E16400B9F288 /* ArduinoSendPWMValueBrickTests.swift */, - E592D15B2539E1E300B9F288 /* IfThenLogicBeginBrickTests.swift */, - E579F104253D88B4009107C8 /* PhiroMotorMoveBackwardBrickTests.swift */, - E579F108253D9485009107C8 /* PhiroMotorMoveForwardBrickTests.swift */, - E579F10A253D98B0009107C8 /* PhiroPlayToneBrickTests.swift */, - E579F10C253D9C58009107C8 /* PhiroRGBLightBrickTests.swift */, - E579F10E253DAF20009107C8 /* SayBubbleBrickTests.swift */, - E579F110253DB124009107C8 /* SayForBubbleBrickTests.swift */, - E579F113253DCA96009107C8 /* ThinkBubbleBrickTests.swift */, - E579F117253DCC65009107C8 /* ThinkForBubbleBrickTests.swift */, - E579F119253DCD90009107C8 /* ChangeXByNBrickTests.swift */, - E579F11B253DCE2C009107C8 /* ChangeYByNBrickTests.swift */, - E5E1E5B32578117400D2F1BC /* SetLookByIndexBrickTests.swift */, - 971C6F20260526ED00AD4857 /* SetTempoToBrickTests.swift */, - 83F8230725EBA9610093DD9A /* SetBackgroundByIndexBrickTests.swift */, 2E8780A72542BCE200816B52 /* WebRequestBrickTests.swift */, - 0580514826EF734F00F719E0 /* StartRunningStitchBrickTests.swift */, - 056677FA27DF8C4C006B4477 /* StartZigzagStitchBrickTests.swift */, + 1AB762FF2969DFF000D01FBA /* WebRequestWarningBrickTest.swift */, ); path = Bricks; sourceTree = ""; @@ -12609,6 +12612,7 @@ 4C822673213FA7A400F3D750 /* AccelerationZSensorTest.swift in Sources */, BC35168C231D00B90090872A /* SpriteBubbleConstraintsTests.swift in Sources */, 18B8021F2469170400201847 /* BrickCellVariableDataTests.swift in Sources */, + 1AB763002969DFF000D01FBA /* WebRequestWarningBrickTest.swift in Sources */, 4C6FE15E212D2D2E0067B7D5 /* MaxFunctionTest.swift in Sources */, 83F8231325EBAA810093DD9A /* SetBackgroundByIndexBrickTests.swift in Sources */, 1833ED942446572F0053BF7C /* HelpWebViewControllerTests.swift in Sources */, diff --git a/src/Catty/DataModel/Bricks/Brick.h b/src/Catty/DataModel/Bricks/Brick.h index 92dbefeae9..3f8506dfcd 100644 --- a/src/Catty/DataModel/Bricks/Brick.h +++ b/src/Catty/DataModel/Bricks/Brick.h @@ -54,6 +54,8 @@ - (BOOL)isArduinoBrick; +- (BOOL)isWebRequestBrick; + - (NSString*)description; - (BOOL)isEqualToBrick:(Brick*)brick; diff --git a/src/Catty/DataModel/Bricks/Brick.m b/src/Catty/DataModel/Bricks/Brick.m index 5bdd47b8bd..819f1e1ab1 100644 --- a/src/Catty/DataModel/Bricks/Brick.m +++ b/src/Catty/DataModel/Bricks/Brick.m @@ -77,6 +77,11 @@ - (BOOL)isArduinoBrick return NO; } +- (BOOL)isWebRequestBrick +{ + return NO; +} + - (BOOL)isDisabledForBackground { return NO; diff --git a/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift b/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift index b7e41a756c..b4bb105057 100644 --- a/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift +++ b/src/Catty/DataModel/Bricks/Data/WebRequestBrick.swift @@ -49,6 +49,10 @@ "WebRequestBrick" } + override func isWebRequest() -> Bool { + true + } + override func getRequiredResources() -> Int { ResourceType.internet.rawValue } diff --git a/src/Catty/Defines/KeychainUserDefaultsDefines.h b/src/Catty/Defines/KeychainUserDefaultsDefines.h index 4d1a94c6b8..49a6afd7e7 100644 --- a/src/Catty/Defines/KeychainUserDefaultsDefines.h +++ b/src/Catty/Defines/KeychainUserDefaultsDefines.h @@ -42,3 +42,5 @@ #define kEmbroideryActivated 1 #define kFirebaseSendCrashReportsDefault 1 #define kWebRequestBrickActivated 0 + +#define kWebRequestWarningWasShown @"webRequestWarningHasBeenShown" diff --git a/src/Catty/Defines/LanguageTranslationDefines.h b/src/Catty/Defines/LanguageTranslationDefines.h index 54e44ce2a7..be98b166e9 100644 --- a/src/Catty/Defines/LanguageTranslationDefines.h +++ b/src/Catty/Defines/LanguageTranslationDefines.h @@ -288,6 +288,7 @@ #define kLocalizedCatrobatWebsite NSLocalizedString(@"Catrobat website", nil) #define kLocalizedViewTermsOfUse NSLocalizedString(@"View Terms of Use and Service", nil) #define kLocalizedTrustedDomains NSLocalizedString(@"Trusted domains", nil) +#define kLocalizedWarning NSLocalizedString(@"Warning", nil) //************************************************************************************************************ //********************************** SHORT DESCRIPTIONS ******************************************* @@ -348,6 +349,7 @@ #define kLocalizedNoAccesToMicrophoneCheckSettingsDescription NSLocalizedString(@"Pocket Code has no access to your microphone. To permit access, tap settings and activate microphone.", nil) #define kLocalizedUnsupportedElementsDescription NSLocalizedString(@"Following features used in this project are not compatible with this version of Pocket Code:", nil) #define kLocalizedAlwaysAllowWebRequestDescription NSLocalizedString(@"Be very careful before allowing access, since the link may expose your personal information, such as your precise geographical location or any text you have entered to malicious other persons or to the public. See our wiki for more information why this can be extremely dangerous. By always allowing access, you will not be asked again to confirm web addresses from this domain. If you want to revoke this permission later, you can remove the domain from the list of trusted domains in the settings of this app.", nil) +#define kLocalizedProjectContainsWebBricksWarning NSLocalizedString(@"The project you have downloaded uses a \"Send web request\", \"Get image from\" or \"Open in browser\" brick, which can send your data to the internet. This may be harmless, and necessary for its intended behavior. In any case, please be cautious about what data you provide, as it may be misused. In case of any doubt, please delete the downloaded project. You shall also report the project on its page on the Catrobat community platform in case you are sure that it is harmful.", nil) //************************************************************************************************************ //******************************* BRICK TITLE TRANSLATIONS **************************************** diff --git a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift index 049baf9283..28f3b88fcc 100644 --- a/src/Catty/Defines/LanguageTranslationDefinesSwift.swift +++ b/src/Catty/Defines/LanguageTranslationDefinesSwift.swift @@ -288,6 +288,7 @@ let kLocalizedAboutUs = NSLocalizedString("About Us", comment: "") let kLocalizedCatrobatWebsite = NSLocalizedString("Catrobat website", comment: "") let kLocalizedViewTermsOfUse = NSLocalizedString("View Terms of Use and Service", comment: "") let kLocalizedTrustedDomains = NSLocalizedString("Trusted domains", comment: "") +let kLocalizedWarning = NSLocalizedString("Warning", comment: "") //************************************************************************************************************ //********************************** SHORT DESCRIPTIONS ******************************************* @@ -348,6 +349,7 @@ let kLocalizedNoAccesToCameraCheckSettingsDescription = NSLocalizedString("Pocke let kLocalizedNoAccesToMicrophoneCheckSettingsDescription = NSLocalizedString("Pocket Code has no access to your microphone. To permit access, tap settings and activate microphone.", comment: "") let kLocalizedUnsupportedElementsDescription = NSLocalizedString("Following features used in this project are not compatible with this version of Pocket Code:", comment: "") let kLocalizedAlwaysAllowWebRequestDescription = NSLocalizedString("Be very careful before allowing access, since the link may expose your personal information, such as your precise geographical location or any text you have entered to malicious other persons or to the public. See our wiki for more information why this can be extremely dangerous. By always allowing access, you will not be asked again to confirm web addresses from this domain. If you want to revoke this permission later, you can remove the domain from the list of trusted domains in the settings of this app.", comment: "") +let kLocalizedProjectContainsWebBricksWarning = NSLocalizedString("The project you have downloaded uses a \"Send web request\", comment: \"Get image from\" or \"Open in browser\" brick, which can send your data to the internet. This may be harmless, and necessary for its intended behavior. In any case, please be cautious about what data you provide, as it may be misused. In case of any doubt, please delete the downloaded project. You shall also report the project on its page on the Catrobat community platform in case you are sure that it is harmful.", comment: "") //************************************************************************************************************ //******************************* BRICK TITLE TRANSLATIONS **************************************** diff --git a/src/Catty/Extension&Delegate&Protocol/Extensions/UIViewController/SceneTableViewControllerExtension.swift b/src/Catty/Extension&Delegate&Protocol/Extensions/UIViewController/SceneTableViewControllerExtension.swift index b6424fdc5d..a6f82375c8 100644 --- a/src/Catty/Extension&Delegate&Protocol/Extensions/UIViewController/SceneTableViewControllerExtension.swift +++ b/src/Catty/Extension&Delegate&Protocol/Extensions/UIViewController/SceneTableViewControllerExtension.swift @@ -1,5 +1,5 @@ /** - * Copyright (C) 2010-2022 The Catrobat Team + * Copyright (C) 2010-2023 The Catrobat Team * (http://developer.catrobat.org/credits) * * This program is free software: you can redistribute it and/or modify @@ -46,3 +46,56 @@ import Foundation }) } } + +extension SceneTableViewController { + + @objc func checkProjectContainsWebRequestBricks(_ project: Project) -> Bool { + + guard let programID = project.header.programID else { return false } + + if checkIfWarningWasShown(programID: programID) { return false } + updateUserDefaults(programId: programID) + + let spriteObjects = project.scene.objects() + for spriteObject in spriteObjects { + for script in spriteObject.scriptList { + + guard let script = script as? Script else { return false } + for brick in script.brickList { + + guard let brick = brick as? Brick else { return false } + + if brick.isWebRequest() { + print("alarm") + AlertControllerBuilder.alert(title: kLocalizedWarning, message: kLocalizedProjectContainsWebBricksWarning) + .addDefaultAction(title: kLocalizedOK) { } + .build() + .showWithController(self) + + return true + } + } + } + } + + return false + } + + private func checkIfWarningWasShown(programID: String) -> Bool { + if let defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + if defaultStorage.contains(programID) { + return true + } + } + return false + } + + private func updateUserDefaults(programId: String) { + if var defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + defaultStorage.append(programId) + UserDefaults.standard.set(defaultStorage, forKey: kWebRequestWarningWasShown) + } else { + UserDefaults.standard.set([programId], forKey: kWebRequestWarningWasShown) + } + } +} diff --git a/src/Catty/Resources/Localization/en.lproj/Localizable.strings b/src/Catty/Resources/Localization/en.lproj/Localizable.strings index 1bc22f70f7..6fcb48726b 100644 --- a/src/Catty/Resources/Localization/en.lproj/Localizable.strings +++ b/src/Catty/Resources/Localization/en.lproj/Localizable.strings @@ -2191,6 +2191,9 @@ /* No comment provided by engineer. */ "The name contains blocked characters. Please try again!" = "The name contains blocked characters. Please try again!"; +/* No comment provided by engineer. */ +"The project you have downloaded uses a \"Send web request\", \"Get image from\" or \"Open in browser\" brick, which can send your data to the internet. This may be harmless, and necessary for its intended behavior. In any case, please be cautious about what data you provide, as it may be misused. In case of any doubt, please delete the downloaded project. You shall also report the project on its page on the Catrobat community platform in case you are sure that it is harmful." = "The project you have downloaded uses a \"Send web request\", \"Get image from\" or \"Open in browser\" brick, which can send your data to the internet. This may be harmless, and necessary for its intended behavior. In any case, please be cautious about what data you provide, as it may be misused. In case of any doubt, please delete the downloaded project. You shall also report the project on its page on the Catrobat community platform in case you are sure that it is harmful."; + /* No comment provided by engineer. */ "The recent projects cannot be loaded" = "The recent projects cannot be loaded"; @@ -2410,6 +2413,9 @@ /* No comment provided by engineer. */ "Wait until" = "Wait until"; +/* No comment provided by engineer. */ +"Warning" = "Warning"; + /* No comment provided by engineer. */ "We" = "We"; diff --git a/src/Catty/ViewController/Continue&New/SceneTableViewController.m b/src/Catty/ViewController/Continue&New/SceneTableViewController.m index 157ca42b3a..258dd62ecb 100644 --- a/src/Catty/ViewController/Continue&New/SceneTableViewController.m +++ b/src/Catty/ViewController/Continue&New/SceneTableViewController.m @@ -88,6 +88,7 @@ - (void)viewDidLoad [self addObjectAction:nil]; } [self checkUnsupportedElements]; + [self checkProjectContainsWebRequestBricks:self.scene.project]; } - (void)viewWillAppear:(BOOL)animated diff --git a/src/CattyTests/Bricks/WebRequestWarningBrickTest.swift b/src/CattyTests/Bricks/WebRequestWarningBrickTest.swift new file mode 100644 index 0000000000..2bb0ee7633 --- /dev/null +++ b/src/CattyTests/Bricks/WebRequestWarningBrickTest.swift @@ -0,0 +1,123 @@ +/** + * Copyright (C) 2010-2023 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +import XCTest + +@testable import Pocket_Code + +final class WebRequestWarningBrickTest: XCTestCase { + + var fileManager: CBFileManager! + + var controller: SceneTableViewController! + + var projectWithoutWebRequest: Project! + var projectWithWebRequest: Project! + + var programId = "123" + + override func setUp() { + + UserDefaults.standard.setValue(true, forKey: kUseWebRequestBrick) + UserDefaults.standard.setValue([], forKey: kWebRequestWarningWasShown) + + controller = SceneTableViewController() + + fileManager = CBFileManager.shared() + setupCleanProjects() + + projectWithoutWebRequest.header.programID = programId + + let script = StartScript() + + let url = "http://catrob.at/joke" + let formula = Formula(string: url) + let userVariable = UserVariable(name: "var") + let brick = WebRequestBrick(request: formula!, userVariable: userVariable, script: script) + + script.brickList.addObjects(from: [brick] as [AnyObject]) + + let scene = projectWithWebRequest.scene + let object = SpriteObject() + object.scene = scene + object.name = "newObject" + object.scriptList.add(script) + + projectWithWebRequest.scene.add(object: object) + projectWithWebRequest.header.programID = "123" + } + + private func setupCleanProjects() { + for loadingInfo in Project.allProjectLoadingInfos() as! [ProjectLoadingInfo] { + fileManager.deleteDirectory(loadingInfo.basePath!) + } + fileManager.addDefaultProjectToProjectsRootDirectoryIfNoProjectsExist() + + let loadingInfos = Project.allProjectLoadingInfos() + XCTAssertEqual(1, loadingInfos.count) + + projectWithWebRequest = Project(loadingInfo: (loadingInfos.first as! ProjectLoadingInfo)) + projectWithoutWebRequest = Project(loadingInfo: (loadingInfos.first as! ProjectLoadingInfo)) + } + + func testCheckWebRequestWarningIsNotShown() { + if let defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + XCTAssertFalse(defaultStorage.contains(programId)) + } else { + XCTFail("Should Never Happen") + } + + XCTAssertFalse(controller.checkProjectContainsWebRequestBricks(projectWithoutWebRequest)) + + if let defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + XCTAssertTrue(defaultStorage.contains(programId)) + } else { + XCTFail("Should Never Happen") + } + + XCTAssertFalse(controller.checkProjectContainsWebRequestBricks(projectWithWebRequest)) + } + + func testCheckWebRequestWarningIsShownFirstTimeOnly() { + if let defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + XCTAssertFalse(defaultStorage.contains(programId)) + } else { + XCTFail("Should Never Happen") + } + + XCTAssertTrue(controller.checkProjectContainsWebRequestBricks(projectWithWebRequest)) + + if let defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + XCTAssertTrue(defaultStorage.contains(programId)) + } else { + XCTFail("Should Never Happen") + } + + XCTAssertFalse(controller.checkProjectContainsWebRequestBricks(projectWithWebRequest)) + + if let defaultStorage = UserDefaults.standard.stringArray(forKey: kWebRequestWarningWasShown) { + XCTAssertTrue(defaultStorage.contains(programId)) + } else { + XCTFail("Should Never Happen") + } + } +} diff --git a/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift b/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift index 8680305e4e..fa5907224e 100644 --- a/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift +++ b/src/CattyUITests/Defines/LanguageTranslationDefinesUI.swift @@ -288,6 +288,7 @@ let kLocalizedAboutUs = NSLocalizedString("About Us", bundle: Bundle(for: Langua let kLocalizedCatrobatWebsite = NSLocalizedString("Catrobat website", bundle: Bundle(for: LanguageTranslation.self), comment: "") let kLocalizedViewTermsOfUse = NSLocalizedString("View Terms of Use and Service", bundle: Bundle(for: LanguageTranslation.self), comment: "") let kLocalizedTrustedDomains = NSLocalizedString("Trusted domains", bundle: Bundle(for: LanguageTranslation.self), comment: "") +let kLocalizedWarning = NSLocalizedString("Warning", bundle: Bundle(for: LanguageTranslation.self), comment: "") //************************************************************************************************************ //********************************** SHORT DESCRIPTIONS ******************************************* @@ -348,6 +349,7 @@ let kLocalizedNoAccesToCameraCheckSettingsDescription = NSLocalizedString("Pocke let kLocalizedNoAccesToMicrophoneCheckSettingsDescription = NSLocalizedString("Pocket Code has no access to your microphone. To permit access, tap settings and activate microphone.", bundle: Bundle(for: LanguageTranslation.self), comment: "") let kLocalizedUnsupportedElementsDescription = NSLocalizedString("Following features used in this project are not compatible with this version of Pocket Code:", bundle: Bundle(for: LanguageTranslation.self), comment: "") let kLocalizedAlwaysAllowWebRequestDescription = NSLocalizedString("Be very careful before allowing access, since the link may expose your personal information, such as your precise geographical location or any text you have entered to malicious other persons or to the public. See our wiki for more information why this can be extremely dangerous. By always allowing access, you will not be asked again to confirm web addresses from this domain. If you want to revoke this permission later, you can remove the domain from the list of trusted domains in the settings of this app.", bundle: Bundle(for: LanguageTranslation.self), comment: "") +let kLocalizedProjectContainsWebBricksWarning = NSLocalizedString("The project you have downloaded uses a \"Send web request\", bundle: Bundle(for: LanguageTranslation.self), comment: \"Get image from\" or \"Open in browser\" brick, which can send your data to the internet. This may be harmless, and necessary for its intended behavior. In any case, please be cautious about what data you provide, as it may be misused. In case of any doubt, please delete the downloaded project. You shall also report the project on its page on the Catrobat community platform in case you are sure that it is harmful.", bundle: Bundle(for: LanguageTranslation.self), comment: "") //************************************************************************************************************ //******************************* BRICK TITLE TRANSLATIONS ****************************************